summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWaldemar Brodkorb <wbx@openadk.org>2014-12-03 20:16:06 -0600
committerWaldemar Brodkorb <wbx@openadk.org>2014-12-03 20:16:06 -0600
commit7868376f50a7d49432f5e40ee6f53f76e5aa8d98 (patch)
tree712b230d60e7b1730d769a46716e0b0ab78f59d0
parente816651b1653ef168af2fcae483abc79e427a70d (diff)
update 3.12.x kernel to 3.12.33
Add latest changes to raspberry-pi support patch. Add rpi-proto driver patch.
-rw-r--r--mk/kernel-ver.mk6
-rw-r--r--target/arm/raspberry-pi/patches/3.12.33/0001-add-support-for-rpi-proto-driver.patch226
-rw-r--r--target/arm/raspberry-pi/patches/3.12.33/0002-enable-MMAP-by-default-allow-overide-via-use_mmap.patch53
-rw-r--r--target/arm/raspberry-pi/patches/3.12.33/raspberry-pi.patch (renamed from target/arm/raspberry-pi/patches/3.12.27/raspberry-pi.patch)16611
-rw-r--r--target/config/Config.in.kernelversion.choice4
-rw-r--r--target/config/Config.in.kernelversion.default2
-rw-r--r--target/linux/patches/3.12.33/bsd-compatibility.patch (renamed from target/linux/patches/3.12.27/bsd-compatibility.patch)0
-rw-r--r--target/linux/patches/3.12.33/cleankernel.patch (renamed from target/linux/patches/3.12.27/cleankernel.patch)0
-rw-r--r--target/linux/patches/3.12.33/defaults.patch (renamed from target/linux/patches/3.12.27/defaults.patch)0
-rw-r--r--target/linux/patches/3.12.33/disable-netfilter.patch (renamed from target/linux/patches/3.12.27/disable-netfilter.patch)0
-rw-r--r--target/linux/patches/3.12.33/export-symbol-for-exmap.patch (renamed from target/linux/patches/3.12.27/export-symbol-for-exmap.patch)0
-rw-r--r--target/linux/patches/3.12.33/gemalto.patch (renamed from target/linux/patches/3.12.27/gemalto.patch)0
-rw-r--r--target/linux/patches/3.12.33/lemote-rfkill.patch (renamed from target/linux/patches/3.12.27/lemote-rfkill.patch)0
-rw-r--r--target/linux/patches/3.12.33/microblaze-ethernet.patch (renamed from target/linux/patches/3.12.27/microblaze-ethernet.patch)0
-rw-r--r--target/linux/patches/3.12.33/microblaze-setup.patch (renamed from target/linux/patches/3.12.27/microblaze-setup.patch)0
-rw-r--r--target/linux/patches/3.12.33/mips-lzo-fix.patch (renamed from target/linux/patches/3.12.27/mips-lzo-fix.patch)0
-rw-r--r--target/linux/patches/3.12.33/mkpiggy.patch (renamed from target/linux/patches/3.12.27/mkpiggy.patch)0
-rw-r--r--target/linux/patches/3.12.33/mtd-rootfs.patch (renamed from target/linux/patches/3.12.27/mtd-rootfs.patch)0
-rw-r--r--target/linux/patches/3.12.33/non-static.patch (renamed from target/linux/patches/3.12.27/non-static.patch)0
-rw-r--r--target/linux/patches/3.12.33/patch-yaffs2 (renamed from target/linux/patches/3.12.27/patch-yaffs2)0
-rw-r--r--target/linux/patches/3.12.33/ppc64-missing-zlib.patch (renamed from target/linux/patches/3.12.27/ppc64-missing-zlib.patch)0
-rw-r--r--target/linux/patches/3.12.33/relocs.patch (renamed from target/linux/patches/3.12.27/relocs.patch)0
-rw-r--r--target/linux/patches/3.12.33/sgidefs.patch (renamed from target/linux/patches/3.12.27/sgidefs.patch)0
-rw-r--r--target/linux/patches/3.12.33/sortext.patch (renamed from target/linux/patches/3.12.27/sortext.patch)0
-rw-r--r--target/linux/patches/3.12.33/startup.patch (renamed from target/linux/patches/3.12.27/startup.patch)0
-rw-r--r--target/linux/patches/3.12.33/tcp-fastopen.patch (renamed from target/linux/patches/3.12.27/tcp-fastopen.patch)0
-rw-r--r--target/linux/patches/3.12.33/usb-defaults-off.patch (renamed from target/linux/patches/3.12.27/usb-defaults-off.patch)0
-rw-r--r--target/linux/patches/3.12.33/vga-cons-default-off.patch (renamed from target/linux/patches/3.12.27/vga-cons-default-off.patch)0
-rw-r--r--target/linux/patches/3.12.33/wlan-cf.patch (renamed from target/linux/patches/3.12.27/wlan-cf.patch)0
-rw-r--r--target/linux/patches/3.12.33/xargs.patch (renamed from target/linux/patches/3.12.27/xargs.patch)0
-rw-r--r--target/linux/patches/3.12.33/zlib-inflate.patch (renamed from target/linux/patches/3.12.27/zlib-inflate.patch)0
-rw-r--r--target/mips/mikrotik-rb532/patches/3.12.33/rb532-cfgfs.patch (renamed from target/mips/mikrotik-rb532/patches/3.12.27/rb532-cfgfs.patch)0
-rw-r--r--target/mips/mikrotik-rb532/patches/3.12.33/rb532-pci.patch (renamed from target/mips/mikrotik-rb532/patches/3.12.27/rb532-pci.patch)0
33 files changed, 12277 insertions, 4625 deletions
diff --git a/mk/kernel-ver.mk b/mk/kernel-ver.mk
index 7af4cf028..12d008cf6 100644
--- a/mk/kernel-ver.mk
+++ b/mk/kernel-ver.mk
@@ -10,11 +10,11 @@ KERNEL_MOD_VERSION:= $(KERNEL_VERSION)
KERNEL_RELEASE:= 1
KERNEL_MD5SUM:= cb00fadd0a720cc2d1690792e72e0134
endif
-ifeq ($(ADK_KERNEL_VERSION_3_12_27),y)
-KERNEL_VERSION:= 3.12.27
+ifeq ($(ADK_KERNEL_VERSION_3_12_33),y)
+KERNEL_VERSION:= 3.12.33
KERNEL_MOD_VERSION:= $(KERNEL_VERSION)
KERNEL_RELEASE:= 1
-KERNEL_MD5SUM:= 02801cc33702ff165c2cd6d0fcf3df34
+KERNEL_MD5SUM:= 7048cce0d24f784595b96f9d1e14a6ba
endif
ifeq ($(ADK_KERNEL_VERSION_3_10_53),y)
KERNEL_VERSION:= 3.10.53
diff --git a/target/arm/raspberry-pi/patches/3.12.33/0001-add-support-for-rpi-proto-driver.patch b/target/arm/raspberry-pi/patches/3.12.33/0001-add-support-for-rpi-proto-driver.patch
new file mode 100644
index 000000000..e0e977741
--- /dev/null
+++ b/target/arm/raspberry-pi/patches/3.12.33/0001-add-support-for-rpi-proto-driver.patch
@@ -0,0 +1,226 @@
+From 70449ef0fb20c168dd341e9bd02dd1929554971c Mon Sep 17 00:00:00 2001
+From: Waldemar Brodkorb <wbrodkorb@conet.de>
+Date: Wed, 29 Oct 2014 16:30:53 +0100
+Subject: [PATCH 1/2] add support for rpi-proto driver
+
+Forward port of 3.10.x driver from https://github.com/koalo
+We are using a custom board and would like to use rpi 3.12.x
+kernel. Patch works fine for our embedded system.
+
+Signed-off-by: Waldemar Brodkorb <wbrodkorb@conet.de>
+Signed-off-by: Waldemar Brodkorb <wbx@openadk.org>
+---
+ arch/arm/mach-bcm2708/bcm2708.c | 17 +++++
+ sound/soc/bcm/Kconfig | 8 +++
+ sound/soc/bcm/Makefile | 2 +
+ sound/soc/bcm/rpi-proto.c | 130 +++++++++++++++++++++++++++++++++++++++
+ 4 files changed, 157 insertions(+)
+ create mode 100644 sound/soc/bcm/rpi-proto.c
+
+diff --git a/arch/arm/mach-bcm2708/bcm2708.c b/arch/arm/mach-bcm2708/bcm2708.c
+index c1a5943..0a0bb05 100644
+--- a/arch/arm/mach-bcm2708/bcm2708.c
++++ b/arch/arm/mach-bcm2708/bcm2708.c
+@@ -754,6 +754,19 @@ static struct i2c_board_info __initdata snd_pcm512x_i2c_devices[] = {
+ };
+ #endif
+
++#ifdef CONFIG_SND_BCM2708_SOC_RPI_CODEC_PROTO_MODULE
++static struct platform_device snd_rpi_proto_device = {
++ .name = "snd-rpi-proto",
++ .id = 0,
++ .num_resources = 0,
++};
++static struct i2c_board_info __initdata snd_rpi_proto_i2c_devices[] = {
++ {
++ I2C_BOARD_INFO("wm8731", 0x1a)
++ },
++};
++#endif
++
+ int __init bcm_register_device(struct platform_device *pdev)
+ {
+ int ret;
+@@ -923,6 +936,10 @@ void __init bcm2708_init(void)
+ bcm_register_device(&snd_rpi_iqaudio_dac_device);
+ i2c_register_board_info(1, snd_pcm512x_i2c_devices, ARRAY_SIZE(snd_pcm512x_i2c_devices));
+ #endif
++#if defined(CONFIG_SND_BCM2708_SOC_RPI_CODEC_PROTO_MODULE)
++ bcm_register_device(&snd_rpi_proto_device);
++ i2c_register_board_info(1, snd_rpi_proto_i2c_devices, ARRAY_SIZE(snd_rpi_proto_i2c_devices));
++#endif
+
+
+ for (i = 0; i < ARRAY_SIZE(amba_devs); i++) {
+diff --git a/sound/soc/bcm/Kconfig b/sound/soc/bcm/Kconfig
+index 301f758..bfe382a 100644
+--- a/sound/soc/bcm/Kconfig
++++ b/sound/soc/bcm/Kconfig
+@@ -50,3 +50,11 @@ config SND_BCM2708_SOC_IQAUDIO_DAC
+ select SND_SOC_PCM512x
+ help
+ Say Y or M if you want to add support for IQaudIO-DAC.
++
++config SND_BCM2708_SOC_RPI_CODEC_PROTO
++ tristate "Support for Audio Codec Board - PROTO (WM8731)"
++ depends on SND_BCM2708_SOC_I2S
++ select SND_SOC_WM8731
++ help
++ Say Y if you want to add support for Audio Codec Board -
++ PROTO (WM8731)
+diff --git a/sound/soc/bcm/Makefile b/sound/soc/bcm/Makefile
+index 8b5e8bb..d1bf274 100644
+--- a/sound/soc/bcm/Makefile
++++ b/sound/soc/bcm/Makefile
+@@ -10,6 +10,7 @@ snd-soc-hifiberry-digi-objs := hifiberry_digi.o
+ snd-soc-hifiberry-amp-objs := hifiberry_amp.o
+ snd-soc-rpi-dac-objs := rpi-dac.o
+ snd-soc-iqaudio-dac-objs := iqaudio-dac.o
++snd-soc-rpi-proto-objs := rpi-proto.o
+
+ obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DAC) += snd-soc-hifiberry-dac.o
+ obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DACPLUS) += snd-soc-hifiberry-dacplus.o
+@@ -17,3 +18,4 @@ obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DIGI) += snd-soc-hifiberry-digi.o
+ obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_AMP) += snd-soc-hifiberry-amp.o
+ obj-$(CONFIG_SND_BCM2708_SOC_RPI_DAC) += snd-soc-rpi-dac.o
+ obj-$(CONFIG_SND_BCM2708_SOC_IQAUDIO_DAC) += snd-soc-iqaudio-dac.o
++obj-$(CONFIG_SND_BCM2708_SOC_RPI_CODEC_PROTO) += snd-soc-rpi-proto.o
+diff --git a/sound/soc/bcm/rpi-proto.c b/sound/soc/bcm/rpi-proto.c
+new file mode 100644
+index 0000000..70b0166
+--- /dev/null
++++ b/sound/soc/bcm/rpi-proto.c
+@@ -0,0 +1,130 @@
++/*
++ * ASoC driver for PROTO AudioCODEC (with a WM8731)
++ * connected to a Raspberry Pi
++ *
++ * Author: Florian Meier, <koalo@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.
++ */
++
++#include <linux/module.h>
++#include <linux/platform_device.h>
++
++#include <sound/core.h>
++#include <sound/pcm.h>
++#include <sound/soc.h>
++#include <sound/jack.h>
++
++#include "../codecs/wm8731.h"
++
++static const unsigned int wm8731_rates_12288000[] = {
++ 8000, 32000, 48000, 96000,
++};
++
++static struct snd_pcm_hw_constraint_list wm8731_constraints_12288000 = {
++ .list = wm8731_rates_12288000,
++ .count = ARRAY_SIZE(wm8731_rates_12288000),
++};
++
++static int snd_rpi_proto_startup(struct snd_pcm_substream *substream)
++{
++ /* Setup constraints, because there is a 12.288 MHz XTAL on the board */
++ snd_pcm_hw_constraint_list(substream->runtime, 0,
++ SNDRV_PCM_HW_PARAM_RATE,
++ &wm8731_constraints_12288000);
++ return 0;
++}
++
++static int snd_rpi_proto_hw_params(struct snd_pcm_substream *substream,
++ struct snd_pcm_hw_params *params)
++{
++ struct snd_soc_pcm_runtime *rtd = substream->private_data;
++ struct snd_soc_dai *codec_dai = rtd->codec_dai;
++ struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
++ int sysclk = 12288000; /* This is fixed on this board */
++
++ /* Set proto bclk */
++ int ret = snd_soc_dai_set_bclk_ratio(cpu_dai,32*2);
++ if (ret < 0){
++ dev_err(substream->pcm->dev,
++ "Failed to set BCLK ratio %d\n", ret);
++ return ret;
++ }
++
++ /* Set proto sysclk */
++ ret = snd_soc_dai_set_sysclk(codec_dai, WM8731_SYSCLK_XTAL,
++ sysclk, SND_SOC_CLOCK_IN);
++ if (ret < 0) {
++ dev_err(substream->pcm->dev,
++ "Failed to set WM8731 SYSCLK: %d\n", ret);
++ return ret;
++ }
++
++ return 0;
++}
++
++/* machine stream operations */
++static struct snd_soc_ops snd_rpi_proto_ops = {
++ .startup = snd_rpi_proto_startup,
++ .hw_params = snd_rpi_proto_hw_params,
++};
++
++static struct snd_soc_dai_link snd_rpi_proto_dai[] = {
++{
++ .name = "WM8731",
++ .stream_name = "WM8731 HiFi",
++ .cpu_dai_name = "bcm2708-i2s.0",
++ .codec_dai_name = "wm8731-hifi",
++ .platform_name = "bcm2708-i2s.0",
++ .codec_name = "wm8731.1-001a",
++ .dai_fmt = SND_SOC_DAIFMT_I2S
++ | SND_SOC_DAIFMT_NB_NF
++ | SND_SOC_DAIFMT_CBM_CFM,
++ .ops = &snd_rpi_proto_ops,
++},
++};
++
++/* audio machine driver */
++static struct snd_soc_card snd_rpi_proto = {
++ .name = "snd_rpi_proto",
++ .dai_link = snd_rpi_proto_dai,
++ .num_links = ARRAY_SIZE(snd_rpi_proto_dai),
++};
++
++static int snd_rpi_proto_probe(struct platform_device *pdev)
++{
++ int ret = 0;
++
++ snd_rpi_proto.dev = &pdev->dev;
++ ret = snd_soc_register_card(&snd_rpi_proto);
++ if (ret) {
++ dev_err(&pdev->dev,
++ "snd_soc_register_card() failed: %d\n", ret);
++ }
++
++ return ret;
++}
++
++
++static int snd_rpi_proto_remove(struct platform_device *pdev)
++{
++ return snd_soc_unregister_card(&snd_rpi_proto);
++}
++
++static struct platform_driver snd_rpi_proto_driver = {
++ .driver = {
++ .name = "snd-rpi-proto",
++ .owner = THIS_MODULE,
++ },
++ .probe = snd_rpi_proto_probe,
++ .remove = snd_rpi_proto_remove,
++};
++
++module_platform_driver(snd_rpi_proto_driver);
++
++MODULE_AUTHOR("Florian Meier");
++MODULE_DESCRIPTION("ASoC Driver for Raspberry Pi connected to PROTO board (WM8731)");
++MODULE_LICENSE("GPL");
+--
+1.7.10.4
+
diff --git a/target/arm/raspberry-pi/patches/3.12.33/0002-enable-MMAP-by-default-allow-overide-via-use_mmap.patch b/target/arm/raspberry-pi/patches/3.12.33/0002-enable-MMAP-by-default-allow-overide-via-use_mmap.patch
new file mode 100644
index 000000000..a8af27d9f
--- /dev/null
+++ b/target/arm/raspberry-pi/patches/3.12.33/0002-enable-MMAP-by-default-allow-overide-via-use_mmap.patch
@@ -0,0 +1,53 @@
+From f1290350dc2cc8defb2d613a32f1a7bd4400de65 Mon Sep 17 00:00:00 2001
+From: Waldemar Brodkorb <wbrodkorb@conet.de>
+Date: Fri, 28 Nov 2014 16:18:36 +0100
+Subject: [PATCH 2/2] enable MMAP by default, allow overide via use_mmap
+
+Add a bool module parameter to control availability of MMAP
+in the driver.
+
+Signed-off-by: Waldemar Brodkorb <wbx@openadk.org>
+---
+ sound/soc/bcm/bcm2708-i2s.c | 12 +++++++++++-
+ 1 file changed, 11 insertions(+), 1 deletion(-)
+
+diff --git a/sound/soc/bcm/bcm2708-i2s.c b/sound/soc/bcm/bcm2708-i2s.c
+index 3fcb740..ddf9796 100644
+--- a/sound/soc/bcm/bcm2708-i2s.c
++++ b/sound/soc/bcm/bcm2708-i2s.c
+@@ -171,6 +171,11 @@ static const unsigned int bcm2708_clk_freq[BCM2708_CLK_SRC_HDMI+1] = {
+ /* I2S pin configuration */
+ static int bcm2708_i2s_gpio=BCM2708_I2S_GPIO_AUTO;
+
++static bool use_mmap = 1;
++module_param(use_mmap, bool, S_IRUGO);
++MODULE_PARM_DESC(use_mmap, "Use MMAP");
++
++
+ /* General device struct */
+ struct bcm2708_i2s_dev {
+ struct device *dev;
+@@ -870,7 +875,7 @@ static const struct snd_soc_component_driver bcm2708_i2s_component = {
+ .name = "bcm2708-i2s-comp",
+ };
+
+-static const struct snd_pcm_hardware bcm2708_pcm_hardware = {
++static struct snd_pcm_hardware bcm2708_pcm_hardware = {
+ .info = SNDRV_PCM_INFO_INTERLEAVED |
+ SNDRV_PCM_INFO_JOINT_DUPLEX,
+ .formats = SNDRV_PCM_FMTBIT_S16_LE |
+@@ -962,6 +967,11 @@ static int bcm2708_i2s_probe(struct platform_device *pdev)
+ return ret;
+ }
+
++ if (use_mmap) {
++ bcm2708_pcm_hardware.info |= SNDRV_PCM_INFO_MMAP;
++ bcm2708_pcm_hardware.info |= SNDRV_PCM_INFO_MMAP_VALID;
++ }
++
+ ret = snd_dmaengine_pcm_register(&pdev->dev,
+ &bcm2708_dmaengine_pcm_config,
+ SND_DMAENGINE_PCM_FLAG_COMPAT);
+--
+1.7.10.4
+
diff --git a/target/arm/raspberry-pi/patches/3.12.27/raspberry-pi.patch b/target/arm/raspberry-pi/patches/3.12.33/raspberry-pi.patch
index 4cfea3f5d..af972bb3e 100644
--- a/target/arm/raspberry-pi/patches/3.12.27/raspberry-pi.patch
+++ b/target/arm/raspberry-pi/patches/3.12.33/raspberry-pi.patch
@@ -1,62 +1,12 @@
-diff -Nur linux-3.12.26.orig/arch/arc/boot/dts/nsimosci.dts linux-3.12.26/arch/arc/boot/dts/nsimosci.dts
---- linux-3.12.26.orig/arch/arc/boot/dts/nsimosci.dts 2014-07-30 18:02:44.000000000 +0200
-+++ linux-3.12.26/arch/arc/boot/dts/nsimosci.dts 2014-08-06 16:50:13.737956371 +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.26.orig/arch/arc/configs/nsimosci_defconfig linux-3.12.26/arch/arc/configs/nsimosci_defconfig
---- linux-3.12.26.orig/arch/arc/configs/nsimosci_defconfig 2014-07-30 18:02:44.000000000 +0200
-+++ linux-3.12.26/arch/arc/configs/nsimosci_defconfig 2014-08-06 16:50:13.737956371 +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.26.orig/arch/arm/configs/bcmrpi_cutdown_defconfig linux-3.12.26/arch/arm/configs/bcmrpi_cutdown_defconfig
---- linux-3.12.26.orig/arch/arm/configs/bcmrpi_cutdown_defconfig 1970-01-01 01:00:00.000000000 +0100
-+++ linux-3.12.26/arch/arm/configs/bcmrpi_cutdown_defconfig 2014-08-06 16:50:13.737956371 +0200
-@@ -0,0 +1,503 @@
-+CONFIG_EXPERIMENTAL=y
+diff -Nur linux-3.12.33/arch/arm/configs/bcmrpi_cutdown_defconfig linux-3.12.33-rpi/arch/arm/configs/bcmrpi_cutdown_defconfig
+--- linux-3.12.33/arch/arm/configs/bcmrpi_cutdown_defconfig 1969-12-31 18:00:00.000000000 -0600
++++ linux-3.12.33-rpi/arch/arm/configs/bcmrpi_cutdown_defconfig 2014-12-03 19:13:32.260418001 -0600
+@@ -0,0 +1,463 @@
+# CONFIG_LOCALVERSION_AUTO is not set
+CONFIG_SYSVIPC=y
+CONFIG_POSIX_MQUEUE=y
++CONFIG_NO_HZ=y
++CONFIG_HIGH_RES_TIMERS=y
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+# CONFIG_UID16 is not set
@@ -70,9 +20,9 @@ diff -Nur linux-3.12.26.orig/arch/arm/configs/bcmrpi_cutdown_defconfig linux-3.1
+CONFIG_MODVERSIONS=y
+CONFIG_MODULE_SRCVERSION_ALL=y
+# CONFIG_BLK_DEV_BSG is not set
++CONFIG_PARTITION_ADVANCED=y
++CONFIG_MAC_PARTITION=y
+CONFIG_ARCH_BCM2708=y
-+CONFIG_NO_HZ=y
-+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_AEABI=y
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
@@ -112,8 +62,6 @@ diff -Nur linux-3.12.26.orig/arch/arm/configs/bcmrpi_cutdown_defconfig linux-3.1
+CONFIG_SIGMATEL_FIR=m
+CONFIG_MCS_FIR=m
+CONFIG_BT=m
-+CONFIG_BT_L2CAP=y
-+CONFIG_BT_SCO=y
+CONFIG_BT_RFCOMM=m
+CONFIG_BT_RFCOMM_TTY=y
+CONFIG_BT_BNEP=m
@@ -142,7 +90,6 @@ diff -Nur linux-3.12.26.orig/arch/arm/configs/bcmrpi_cutdown_defconfig linux-3.1
+CONFIG_BLK_DEV_NBD=m
+CONFIG_BLK_DEV_RAM=y
+CONFIG_CDROM_PKTCDVD=m
-+CONFIG_MISC_DEVICES=y
+CONFIG_SCSI=y
+# CONFIG_SCSI_PROC_FS is not set
+CONFIG_BLK_DEV_SD=m
@@ -150,44 +97,16 @@ diff -Nur linux-3.12.26.orig/arch/arm/configs/bcmrpi_cutdown_defconfig linux-3.1
+CONFIG_SCSI_MULTI_LUN=y
+# CONFIG_SCSI_LOWLEVEL is not set
+CONFIG_NETDEVICES=y
++CONFIG_NETCONSOLE=m
+CONFIG_TUN=m
-+CONFIG_PHYLIB=m
+CONFIG_MDIO_BITBANG=m
-+CONFIG_NET_ETHERNET=y
-+# CONFIG_NETDEV_1000 is not set
-+# CONFIG_NETDEV_10000 is not set
-+CONFIG_LIBERTAS_THINFIRM=m
-+CONFIG_LIBERTAS_THINFIRM_USB=m
-+CONFIG_AT76C50X_USB=m
-+CONFIG_USB_ZD1201=m
-+CONFIG_USB_NET_RNDIS_WLAN=m
-+CONFIG_RTL8187=m
-+CONFIG_MAC80211_HWSIM=m
-+CONFIG_ATH_COMMON=m
-+CONFIG_ATH9K=m
-+CONFIG_ATH9K_HTC=m
-+CONFIG_CARL9170=m
-+CONFIG_B43=m
-+CONFIG_B43LEGACY=m
-+CONFIG_HOSTAP=m
-+CONFIG_IWM=m
-+CONFIG_LIBERTAS=m
-+CONFIG_LIBERTAS_USB=m
-+CONFIG_LIBERTAS_SDIO=m
-+CONFIG_P54_COMMON=m
-+CONFIG_P54_USB=m
-+CONFIG_RT2X00=m
-+CONFIG_RT2500USB=m
-+CONFIG_RT73USB=m
-+CONFIG_RT2800USB=m
-+CONFIG_RT2800USB_RT53XX=y
-+CONFIG_RTL8192CU=m
-+CONFIG_WL1251=m
-+CONFIG_WL12XX_MENU=m
-+CONFIG_ZD1211RW=m
-+CONFIG_MWIFIEX=m
-+CONFIG_MWIFIEX_SDIO=m
-+CONFIG_WIMAX_I2400M_USB=m
++CONFIG_PPP=m
++CONFIG_PPP_BSDCOMP=m
++CONFIG_PPP_DEFLATE=m
++CONFIG_PPP_ASYNC=m
++CONFIG_PPP_SYNC_TTY=m
++CONFIG_SLIP=m
++CONFIG_SLIP_COMPRESSED=y
+CONFIG_USB_CATC=m
+CONFIG_USB_KAWETH=m
+CONFIG_USB_PEGASUS=m
@@ -214,14 +133,31 @@ diff -Nur linux-3.12.26.orig/arch/arm/configs/bcmrpi_cutdown_defconfig linux-3.1
+CONFIG_USB_IPHETH=m
+CONFIG_USB_SIERRA_NET=m
+CONFIG_USB_VL600=m
-+CONFIG_PPP=m
-+CONFIG_PPP_ASYNC=m
-+CONFIG_PPP_SYNC_TTY=m
-+CONFIG_PPP_DEFLATE=m
-+CONFIG_PPP_BSDCOMP=m
-+CONFIG_SLIP=m
-+CONFIG_SLIP_COMPRESSED=y
-+CONFIG_NETCONSOLE=m
++CONFIG_LIBERTAS_THINFIRM=m
++CONFIG_LIBERTAS_THINFIRM_USB=m
++CONFIG_AT76C50X_USB=m
++CONFIG_USB_ZD1201=m
++CONFIG_USB_NET_RNDIS_WLAN=m
++CONFIG_RTL8187=m
++CONFIG_MAC80211_HWSIM=m
++CONFIG_B43=m
++CONFIG_B43LEGACY=m
++CONFIG_HOSTAP=m
++CONFIG_LIBERTAS=m
++CONFIG_LIBERTAS_USB=m
++CONFIG_LIBERTAS_SDIO=m
++CONFIG_P54_COMMON=m
++CONFIG_P54_USB=m
++CONFIG_RT2X00=m
++CONFIG_RT2500USB=m
++CONFIG_RT73USB=m
++CONFIG_RT2800USB=m
++CONFIG_RT2800USB_RT53XX=y
++CONFIG_RTL8192CU=m
++CONFIG_ZD1211RW=m
++CONFIG_MWIFIEX=m
++CONFIG_MWIFIEX_SDIO=m
++CONFIG_WIMAX_I2400M_USB=m
+CONFIG_INPUT_POLLDEV=m
+# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
+CONFIG_INPUT_JOYDEV=m
@@ -230,7 +166,6 @@ diff -Nur linux-3.12.26.orig/arch/arm/configs/bcmrpi_cutdown_defconfig linux-3.1
+# CONFIG_INPUT_MOUSE is not set
+CONFIG_INPUT_MISC=y
+CONFIG_INPUT_AD714X=m
-+CONFIG_INPUT_ATI_REMOTE=m
+CONFIG_INPUT_ATI_REMOTE2=m
+CONFIG_INPUT_KEYSPAN_REMOTE=m
+CONFIG_INPUT_POWERMATE=m
@@ -245,18 +180,21 @@ diff -Nur linux-3.12.26.orig/arch/arm/configs/bcmrpi_cutdown_defconfig linux-3.1
+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
+CONFIG_SERIAL_AMBA_PL011_CONSOLE=y
+# CONFIG_HW_RANDOM is not set
+CONFIG_RAW_DRIVER=y
++CONFIG_I2C=y
++CONFIG_I2C_CHARDEV=m
++CONFIG_I2C_BCM2708=m
++CONFIG_SPI=y
++CONFIG_SPI_BCM2708=m
+CONFIG_GPIO_SYSFS=y
+# CONFIG_HWMON is not set
+CONFIG_WATCHDOG=y
+CONFIG_BCM2708_WDT=m
-+# CONFIG_MFD_SUPPORT is not set
+CONFIG_FB=y
+CONFIG_FB_BCM2708=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
@@ -283,8 +221,6 @@ diff -Nur linux-3.12.26.orig/arch/arm/configs/bcmrpi_cutdown_defconfig linux-3.1
+CONFIG_SND_USB_CAIAQ=m
+CONFIG_SND_USB_6FIRE=m
+CONFIG_SOUND_PRIME=m
-+CONFIG_HID_PID=y
-+CONFIG_USB_HIDDEV=y
+CONFIG_HID_A4TECH=m
+CONFIG_HID_ACRUX=m
+CONFIG_HID_APPLE=m
@@ -315,20 +251,18 @@ diff -Nur linux-3.12.26.orig/arch/arm/configs/bcmrpi_cutdown_defconfig linux-3.1
+CONFIG_HID_PANTHERLORD=m
+CONFIG_HID_PETALYNX=m
+CONFIG_HID_PICOLCD=m
-+CONFIG_HID_QUANTA=m
+CONFIG_HID_ROCCAT=m
+CONFIG_HID_SAMSUNG=m
-+CONFIG_HID_SONY=m
+CONFIG_HID_SPEEDLINK=m
+CONFIG_HID_SUNPLUS=m
+CONFIG_HID_GREENASIA=m
+CONFIG_HID_SMARTJOYPLUS=m
+CONFIG_HID_TOPSEED=m
+CONFIG_HID_THRUSTMASTER=m
-+CONFIG_HID_WACOM=m
-+CONFIG_HID_WIIMOTE=m
+CONFIG_HID_ZEROPLUS=m
+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
@@ -347,8 +281,6 @@ diff -Nur linux-3.12.26.orig/arch/arm/configs/bcmrpi_cutdown_defconfig linux-3.1
+CONFIG_USB_STORAGE_KARMA=m
+CONFIG_USB_STORAGE_CYPRESS_ATACB=m
+CONFIG_USB_STORAGE_ENE_UB6250=m
-+CONFIG_USB_UAS=m
-+CONFIG_USB_LIBUSUAL=y
+CONFIG_USB_MDC800=m
+CONFIG_USB_MICROTEK=m
+CONFIG_USB_SERIAL=m
@@ -363,7 +295,6 @@ diff -Nur linux-3.12.26.orig/arch/arm/configs/bcmrpi_cutdown_defconfig linux-3.1
+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
@@ -379,16 +310,13 @@ diff -Nur linux-3.12.26.orig/arch/arm/configs/bcmrpi_cutdown_defconfig linux-3.1
+CONFIG_USB_SERIAL_MCT_U232=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
@@ -397,8 +325,6 @@ diff -Nur linux-3.12.26.orig/arch/arm/configs/bcmrpi_cutdown_defconfig linux-3.1
+CONFIG_USB_SERIAL_OPTION=m
+CONFIG_USB_SERIAL_OMNINET=m
+CONFIG_USB_SERIAL_OPTICON=m
-+CONFIG_USB_SERIAL_VIVOPAY_SERIAL=m
-+CONFIG_USB_SERIAL_ZIO=m
+CONFIG_USB_SERIAL_SSU100=m
+CONFIG_USB_SERIAL_DEBUG=m
+CONFIG_USB_EMI62=m
@@ -425,12 +351,9 @@ diff -Nur linux-3.12.26.orig/arch/arm/configs/bcmrpi_cutdown_defconfig linux-3.1
+CONFIG_MMC_SDHCI_PLTFM=y
+CONFIG_MMC_SDHCI_BCM2708=y
+CONFIG_MMC_SDHCI_BCM2708_DMA=y
-+CONFIG_LEDS_GPIO=y
-+CONFIG_LEDS_TRIGGER_TIMER=m
-+CONFIG_LEDS_TRIGGER_HEARTBEAT=m
-+CONFIG_LEDS_TRIGGER_DEFAULT_ON=m
++CONFIG_MMC_BCM2835=y
++CONFIG_MMC_BCM2835_DMA=y
+CONFIG_UIO=m
-+CONFIG_UIO_PDRV=m
+CONFIG_UIO_PDRV_GENIRQ=m
+# CONFIG_IOMMU_SUPPORT is not set
+CONFIG_EXT4_FS=y
@@ -473,7 +396,6 @@ diff -Nur linux-3.12.26.orig/arch/arm/configs/bcmrpi_cutdown_defconfig linux-3.1
+CONFIG_SQUASHFS_LZO=y
+CONFIG_SQUASHFS_XZ=y
+CONFIG_NFS_FS=y
-+CONFIG_NFS_V3=y
+CONFIG_NFS_V3_ACL=y
+CONFIG_NFS_V4=y
+CONFIG_ROOT_NFS=y
@@ -483,9 +405,6 @@ diff -Nur linux-3.12.26.orig/arch/arm/configs/bcmrpi_cutdown_defconfig linux-3.1
+CONFIG_CIFS_XATTR=y
+CONFIG_CIFS_POSIX=y
+CONFIG_9P_FS=m
-+CONFIG_PARTITION_ADVANCED=y
-+CONFIG_MAC_PARTITION=y
-+CONFIG_EFI_PARTITION=y
+CONFIG_NLS_DEFAULT="utf8"
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_CODEPAGE_737=m
@@ -536,7 +455,6 @@ diff -Nur linux-3.12.26.orig/arch/arm/configs/bcmrpi_cutdown_defconfig linux-3.1
+CONFIG_CRYPTO_XCBC=m
+CONFIG_CRYPTO_MD5=y
+CONFIG_CRYPTO_SHA1=y
-+CONFIG_CRYPTO_SHA256=m
+CONFIG_CRYPTO_SHA512=m
+CONFIG_CRYPTO_TGR192=m
+CONFIG_CRYPTO_WP512=m
@@ -547,19 +465,10 @@ diff -Nur linux-3.12.26.orig/arch/arm/configs/bcmrpi_cutdown_defconfig linux-3.1
+# CONFIG_CRYPTO_HW is not set
+CONFIG_CRC_ITU_T=y
+CONFIG_LIBCRC32C=y
-+CONFIG_I2C=y
-+CONFIG_I2C_BOARDINFO=y
-+CONFIG_I2C_COMPAT=y
-+CONFIG_I2C_CHARDEV=m
-+CONFIG_I2C_HELPER_AUTO=y
-+CONFIG_I2C_BCM2708=m
-+CONFIG_SPI=y
-+CONFIG_SPI_MASTER=y
-+CONFIG_SPI_BCM2708=m
-diff -Nur linux-3.12.26.orig/arch/arm/configs/bcmrpi_defconfig linux-3.12.26/arch/arm/configs/bcmrpi_defconfig
---- linux-3.12.26.orig/arch/arm/configs/bcmrpi_defconfig 1970-01-01 01:00:00.000000000 +0100
-+++ linux-3.12.26/arch/arm/configs/bcmrpi_defconfig 2014-08-06 16:50:13.753956496 +0200
-@@ -0,0 +1,1097 @@
+diff -Nur linux-3.12.33/arch/arm/configs/bcmrpi_defconfig linux-3.12.33-rpi/arch/arm/configs/bcmrpi_defconfig
+--- linux-3.12.33/arch/arm/configs/bcmrpi_defconfig 1969-12-31 18:00:00.000000000 -0600
++++ linux-3.12.33-rpi/arch/arm/configs/bcmrpi_defconfig 2014-12-03 19:13:32.288418001 -0600
+@@ -0,0 +1,1119 @@
+# CONFIG_ARM_PATCH_PHYS_VIRT is not set
+# CONFIG_LOCALVERSION_AUTO is not set
+CONFIG_SYSVIPC=y
@@ -654,6 +563,7 @@ diff -Nur linux-3.12.26.orig/arch/arm/configs/bcmrpi_defconfig linux-3.12.26/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
@@ -829,6 +739,7 @@ diff -Nur linux-3.12.26.orig/arch/arm/configs/bcmrpi_defconfig linux-3.12.26/arc
+CONFIG_BRIDGE_EBT_ULOG=m
+CONFIG_BRIDGE_EBT_NFLOG=m
+CONFIG_SCTP_COOKIE_HMAC_SHA1=y
++CONFIG_ATM=m
+CONFIG_L2TP=m
+CONFIG_L2TP_V3=y
+CONFIG_L2TP_IP=m
@@ -943,12 +854,15 @@ diff -Nur linux-3.12.26.orig/arch/arm/configs/bcmrpi_defconfig linux-3.12.26/arc
+CONFIG_NFC_PN533=m
+CONFIG_DEVTMPFS=y
+CONFIG_DEVTMPFS_MOUNT=y
++CONFIG_DMA_CMA=y
++CONFIG_CMA_SIZE_MBYTES=5
+CONFIG_BLK_DEV_LOOP=y
+CONFIG_BLK_DEV_CRYPTOLOOP=m
+CONFIG_BLK_DEV_DRBD=m
+CONFIG_BLK_DEV_NBD=m
+CONFIG_BLK_DEV_RAM=y
+CONFIG_CDROM_PKTCDVD=m
++CONFIG_EEPROM_AT24=m
+CONFIG_SCSI=y
+# CONFIG_SCSI_PROC_FS is not set
+CONFIG_BLK_DEV_SD=y
@@ -967,8 +881,8 @@ diff -Nur linux-3.12.26.orig/arch/arm/configs/bcmrpi_defconfig linux-3.12.26/arc
+CONFIG_DM_CRYPT=m
+CONFIG_DM_SNAPSHOT=m
+CONFIG_DM_MIRROR=m
-+CONFIG_DM_LOG_USERSPACE=m
+CONFIG_DM_RAID=m
++CONFIG_DM_LOG_USERSPACE=m
+CONFIG_DM_ZERO=m
+CONFIG_DM_DELAY=m
+CONFIG_NETDEVICES=y
@@ -986,6 +900,7 @@ diff -Nur linux-3.12.26.orig/arch/arm/configs/bcmrpi_defconfig linux-3.12.26/arc
+CONFIG_PPP_FILTER=y
+CONFIG_PPP_MPPE=m
+CONFIG_PPP_MULTILINK=y
++CONFIG_PPPOATM=m
+CONFIG_PPPOE=m
+CONFIG_PPPOL2TP=m
+CONFIG_PPP_ASYNC=m
@@ -1021,6 +936,7 @@ diff -Nur linux-3.12.26.orig/arch/arm/configs/bcmrpi_defconfig linux-3.12.26/arc
+CONFIG_USB_NET_CX82310_ETH=m
+CONFIG_USB_NET_KALMIA=m
+CONFIG_USB_NET_QMI_WWAN=m
++CONFIG_USB_HSO=m
+CONFIG_USB_NET_INT51X1=m
+CONFIG_USB_IPHETH=m
+CONFIG_USB_SIERRA_NET=m
@@ -1091,6 +1007,7 @@ diff -Nur linux-3.12.26.orig/arch/arm/configs/bcmrpi_defconfig linux-3.12.26/arc
+CONFIG_GAMEPORT=m
+CONFIG_GAMEPORT_NS558=m
+CONFIG_GAMEPORT_L4=m
++CONFIG_DEVPTS_MULTIPLE_INSTANCES=y
+# CONFIG_LEGACY_PTYS is not set
+# CONFIG_DEVKMEM is not set
+CONFIG_SERIAL_AMBA_PL011=y
@@ -1101,12 +1018,16 @@ diff -Nur linux-3.12.26.orig/arch/arm/configs/bcmrpi_defconfig linux-3.12.26/arc
+CONFIG_RAW_DRIVER=y
+CONFIG_BRCM_CHAR_DRIVERS=y
+CONFIG_BCM_VC_CMA=y
++CONFIG_BCM_VC_SM=y
+CONFIG_I2C=y
+CONFIG_I2C_CHARDEV=m
+CONFIG_I2C_BCM2708=m
+CONFIG_SPI=y
+CONFIG_SPI_BCM2708=m
+CONFIG_SPI_SPIDEV=y
++CONFIG_PPS=m
++CONFIG_PPS_CLIENT_LDISC=m
++CONFIG_PPS_CLIENT_GPIO=m
+CONFIG_GPIO_SYSFS=y
+CONFIG_W1=m
+CONFIG_W1_MASTER_DS2490=m
@@ -1188,6 +1109,7 @@ diff -Nur linux-3.12.26.orig/arch/arm/configs/bcmrpi_defconfig linux-3.12.26/arc
+CONFIG_USB_GSPCA_SQ905C=m
+CONFIG_USB_GSPCA_SQ930X=m
+CONFIG_USB_GSPCA_STK014=m
++CONFIG_USB_GSPCA_STK1135=m
+CONFIG_USB_GSPCA_STV0680=m
+CONFIG_USB_GSPCA_SUNPLUS=m
+CONFIG_USB_GSPCA_T613=m
@@ -1203,10 +1125,12 @@ diff -Nur linux-3.12.26.orig/arch/arm/configs/bcmrpi_defconfig linux-3.12.26/arc
+CONFIG_USB_STKWEBCAM=m
+CONFIG_USB_S2255=m
+CONFIG_USB_SN9C102=m
++CONFIG_VIDEO_USBTV=m
+CONFIG_VIDEO_PVRUSB2=m
+CONFIG_VIDEO_HDPVR=m
+CONFIG_VIDEO_TLG2300=m
+CONFIG_VIDEO_USBVISION=m
++CONFIG_VIDEO_STK1160_COMMON=m
+CONFIG_VIDEO_AU0828=m
+CONFIG_VIDEO_CX231XX=m
+CONFIG_VIDEO_CX231XX_ALSA=m
@@ -1304,17 +1228,14 @@ diff -Nur linux-3.12.26.orig/arch/arm/configs/bcmrpi_defconfig linux-3.12.26/arc
+CONFIG_SND_USB_CAIAQ_INPUT=y
+CONFIG_SND_USB_6FIRE=m
+CONFIG_SND_SOC=m
-+CONFIG_SND_SOC_DMAENGINE_PCM=y
-+CONFIG_SND_SOC_GENERIC_DMAENGINE_PCM=y
-+CONFIG_SND_SOC_WM8804=m
+CONFIG_SND_BCM2708_SOC_I2S=m
+CONFIG_SND_BCM2708_SOC_HIFIBERRY_DAC=m
++CONFIG_SND_BCM2708_SOC_HIFIBERRY_DACPLUS=m
+CONFIG_SND_BCM2708_SOC_HIFIBERRY_DIGI=m
++CONFIG_SND_BCM2708_SOC_HIFIBERRY_AMP=m
+CONFIG_SND_BCM2708_SOC_RPI_DAC=m
-+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_SND_SIMPLE_CARD=m
+CONFIG_SOUND_PRIME=m
+CONFIG_HIDRAW=y
+CONFIG_HID_A4TECH=m
@@ -1327,6 +1248,7 @@ diff -Nur linux-3.12.26.orig/arch/arm/configs/bcmrpi_defconfig linux-3.12.26/arc
+CONFIG_HID_DRAGONRISE=m
+CONFIG_HID_EMS_FF=m
+CONFIG_HID_ELECOM=m
++CONFIG_HID_ELO=m
+CONFIG_HID_EZKEY=m
+CONFIG_HID_HOLTEK=m
+CONFIG_HID_KEYTOUCH=m
@@ -1359,6 +1281,7 @@ diff -Nur linux-3.12.26.orig/arch/arm/configs/bcmrpi_defconfig linux-3.12.26/arc
+CONFIG_HID_THRUSTMASTER=m
+CONFIG_HID_WACOM=m
+CONFIG_HID_WIIMOTE=m
++CONFIG_HID_XINMO=m
+CONFIG_HID_ZEROPLUS=m
+CONFIG_HID_ZYDACRON=m
+CONFIG_HID_PID=y
@@ -1453,12 +1376,19 @@ diff -Nur linux-3.12.26.orig/arch/arm/configs/bcmrpi_defconfig linux-3.12.26/arc
+CONFIG_USB_TEST=m
+CONFIG_USB_ISIGHTFW=m
+CONFIG_USB_YUREX=m
++CONFIG_USB_ATM=m
++CONFIG_USB_SPEEDTOUCH=m
++CONFIG_USB_CXACRU=m
++CONFIG_USB_UEAGLEATM=m
++CONFIG_USB_XUSBATM=m
+CONFIG_MMC=y
+CONFIG_MMC_BLOCK_MINORS=32
+CONFIG_MMC_SDHCI=y
+CONFIG_MMC_SDHCI_PLTFM=y
+CONFIG_MMC_SDHCI_BCM2708=y
+CONFIG_MMC_SDHCI_BCM2708_DMA=y
++CONFIG_MMC_BCM2835=y
++CONFIG_MMC_BCM2835_DMA=y
+CONFIG_MMC_SPI=m
+CONFIG_LEDS_GPIO=m
+CONFIG_LEDS_TRIGGER_TIMER=y
@@ -1481,6 +1411,7 @@ diff -Nur linux-3.12.26.orig/arch/arm/configs/bcmrpi_defconfig linux-3.12.26/arc
+CONFIG_RTC_DRV_ISL1208=m
+CONFIG_RTC_DRV_ISL12022=m
+CONFIG_RTC_DRV_X1205=m
++CONFIG_RTC_DRV_PCF2127=m
+CONFIG_RTC_DRV_PCF8523=m
+CONFIG_RTC_DRV_PCF8563=m
+CONFIG_RTC_DRV_PCF8583=m
@@ -1503,9 +1434,7 @@ diff -Nur linux-3.12.26.orig/arch/arm/configs/bcmrpi_defconfig linux-3.12.26/arc
+CONFIG_RTC_DRV_PCF2123=m
+CONFIG_RTC_DRV_RX4581=m
+CONFIG_DMADEVICES=y
-+CONFIG_DMA_BCM2708=m
-+CONFIG_DMA_ENGINE=y
-+CONFIG_DMA_VIRTUAL_CHANNELS=m
++CONFIG_DMA_BCM2708=y
+CONFIG_UIO=m
+CONFIG_UIO_PDRV_GENIRQ=m
+CONFIG_STAGING=y
@@ -1577,6 +1506,7 @@ diff -Nur linux-3.12.26.orig/arch/arm/configs/bcmrpi_defconfig linux-3.12.26/arc
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3_ACL=y
+CONFIG_NFS_V4=y
++CONFIG_NFS_SWAP=y
+CONFIG_ROOT_NFS=y
+CONFIG_NFS_FSCACHE=y
+CONFIG_NFSD=m
@@ -1644,6 +1574,7 @@ diff -Nur linux-3.12.26.orig/arch/arm/configs/bcmrpi_defconfig linux-3.12.26/arc
+CONFIG_CRYPTO_NULL=m
+CONFIG_CRYPTO_CRYPTD=m
+CONFIG_CRYPTO_CBC=y
++CONFIG_CRYPTO_CTS=m
+CONFIG_CRYPTO_XTS=m
+CONFIG_CRYPTO_XCBC=m
+CONFIG_CRYPTO_SHA1_ARM=m
@@ -1657,22 +1588,21 @@ diff -Nur linux-3.12.26.orig/arch/arm/configs/bcmrpi_defconfig linux-3.12.26/arc
+# CONFIG_CRYPTO_HW is not set
+CONFIG_CRC_ITU_T=y
+CONFIG_LIBCRC32C=y
-diff -Nur linux-3.12.26.orig/arch/arm/configs/bcmrpi_emergency_defconfig linux-3.12.26/arch/arm/configs/bcmrpi_emergency_defconfig
---- linux-3.12.26.orig/arch/arm/configs/bcmrpi_emergency_defconfig 1970-01-01 01:00:00.000000000 +0100
-+++ linux-3.12.26/arch/arm/configs/bcmrpi_emergency_defconfig 2014-08-06 16:50:13.777956685 +0200
-@@ -0,0 +1,532 @@
-+CONFIG_EXPERIMENTAL=y
+diff -Nur linux-3.12.33/arch/arm/configs/bcmrpi_emergency_defconfig linux-3.12.33-rpi/arch/arm/configs/bcmrpi_emergency_defconfig
+--- linux-3.12.33/arch/arm/configs/bcmrpi_emergency_defconfig 1969-12-31 18:00:00.000000000 -0600
++++ linux-3.12.33-rpi/arch/arm/configs/bcmrpi_emergency_defconfig 2014-12-03 19:13:32.288418001 -0600
+@@ -0,0 +1,495 @@
+# CONFIG_LOCALVERSION_AUTO is not set
+CONFIG_SYSVIPC=y
+CONFIG_POSIX_MQUEUE=y
-+CONFIG_BSD_PROCESS_ACCT=y
-+CONFIG_BSD_PROCESS_ACCT_V3=y
+CONFIG_FHANDLE=y
+CONFIG_AUDIT=y
++CONFIG_NO_HZ=y
++CONFIG_HIGH_RES_TIMERS=y
++CONFIG_BSD_PROCESS_ACCT=y
++CONFIG_BSD_PROCESS_ACCT_V3=y
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
-+CONFIG_BLK_DEV_INITRD=y
-+CONFIG_INITRAMFS_SOURCE="../target_fs"
+CONFIG_CGROUP_FREEZER=y
+CONFIG_CGROUP_DEVICE=y
+CONFIG_CGROUP_CPUACCT=y
@@ -1680,6 +1610,8 @@ diff -Nur linux-3.12.26.orig/arch/arm/configs/bcmrpi_emergency_defconfig linux-3
+CONFIG_BLK_CGROUP=y
+CONFIG_NAMESPACES=y
+CONFIG_SCHED_AUTOGROUP=y
++CONFIG_BLK_DEV_INITRD=y
++CONFIG_INITRAMFS_SOURCE="../target_fs"
+CONFIG_EMBEDDED=y
+# CONFIG_COMPAT_BRK is not set
+CONFIG_SLAB=y
@@ -1692,10 +1624,10 @@ diff -Nur linux-3.12.26.orig/arch/arm/configs/bcmrpi_emergency_defconfig linux-3
+CONFIG_MODULE_SRCVERSION_ALL=y
+# CONFIG_BLK_DEV_BSG is not set
+CONFIG_BLK_DEV_THROTTLING=y
++CONFIG_PARTITION_ADVANCED=y
++CONFIG_MAC_PARTITION=y
+CONFIG_CFQ_GROUP_IOSCHED=y
+CONFIG_ARCH_BCM2708=y
-+CONFIG_NO_HZ=y
-+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_AEABI=y
+CONFIG_SECCOMP=y
+CONFIG_CC_STACKPROTECTOR=y
@@ -1738,8 +1670,6 @@ diff -Nur linux-3.12.26.orig/arch/arm/configs/bcmrpi_emergency_defconfig linux-3
+CONFIG_SIGMATEL_FIR=m
+CONFIG_MCS_FIR=m
+CONFIG_BT=m
-+CONFIG_BT_L2CAP=y
-+CONFIG_BT_SCO=y
+CONFIG_BT_RFCOMM=m
+CONFIG_BT_RFCOMM_TTY=y
+CONFIG_BT_BNEP=m
@@ -1768,7 +1698,6 @@ diff -Nur linux-3.12.26.orig/arch/arm/configs/bcmrpi_emergency_defconfig linux-3
+CONFIG_BLK_DEV_NBD=m
+CONFIG_BLK_DEV_RAM=y
+CONFIG_CDROM_PKTCDVD=m
-+CONFIG_MISC_DEVICES=y
+CONFIG_SCSI=y
+# CONFIG_SCSI_PROC_FS is not set
+CONFIG_BLK_DEV_SD=y
@@ -1777,44 +1706,16 @@ diff -Nur linux-3.12.26.orig/arch/arm/configs/bcmrpi_emergency_defconfig linux-3
+# CONFIG_SCSI_LOWLEVEL is not set
+CONFIG_MD=y
+CONFIG_NETDEVICES=y
++CONFIG_NETCONSOLE=m
+CONFIG_TUN=m
-+CONFIG_PHYLIB=m
+CONFIG_MDIO_BITBANG=m
-+CONFIG_NET_ETHERNET=y
-+# CONFIG_NETDEV_1000 is not set
-+# CONFIG_NETDEV_10000 is not set
-+CONFIG_LIBERTAS_THINFIRM=m
-+CONFIG_LIBERTAS_THINFIRM_USB=m
-+CONFIG_AT76C50X_USB=m
-+CONFIG_USB_ZD1201=m
-+CONFIG_USB_NET_RNDIS_WLAN=m
-+CONFIG_RTL8187=m
-+CONFIG_MAC80211_HWSIM=m
-+CONFIG_ATH_COMMON=m
-+CONFIG_ATH9K=m
-+CONFIG_ATH9K_HTC=m
-+CONFIG_CARL9170=m
-+CONFIG_B43=m
-+CONFIG_B43LEGACY=m
-+CONFIG_HOSTAP=m
-+CONFIG_IWM=m
-+CONFIG_LIBERTAS=m
-+CONFIG_LIBERTAS_USB=m
-+CONFIG_LIBERTAS_SDIO=m
-+CONFIG_P54_COMMON=m
-+CONFIG_P54_USB=m
-+CONFIG_RT2X00=m
-+CONFIG_RT2500USB=m
-+CONFIG_RT73USB=m
-+CONFIG_RT2800USB=m
-+CONFIG_RT2800USB_RT53XX=y
-+CONFIG_RTL8192CU=m
-+CONFIG_WL1251=m
-+CONFIG_WL12XX_MENU=m
-+CONFIG_ZD1211RW=m
-+CONFIG_MWIFIEX=m
-+CONFIG_MWIFIEX_SDIO=m
-+CONFIG_WIMAX_I2400M_USB=m
++CONFIG_PPP=m
++CONFIG_PPP_BSDCOMP=m
++CONFIG_PPP_DEFLATE=m
++CONFIG_PPP_ASYNC=m
++CONFIG_PPP_SYNC_TTY=m
++CONFIG_SLIP=m
++CONFIG_SLIP_COMPRESSED=y
+CONFIG_USB_CATC=m
+CONFIG_USB_KAWETH=m
+CONFIG_USB_PEGASUS=m
@@ -1841,14 +1742,31 @@ diff -Nur linux-3.12.26.orig/arch/arm/configs/bcmrpi_emergency_defconfig linux-3
+CONFIG_USB_IPHETH=m
+CONFIG_USB_SIERRA_NET=m
+CONFIG_USB_VL600=m
-+CONFIG_PPP=m
-+CONFIG_PPP_ASYNC=m
-+CONFIG_PPP_SYNC_TTY=m
-+CONFIG_PPP_DEFLATE=m
-+CONFIG_PPP_BSDCOMP=m
-+CONFIG_SLIP=m
-+CONFIG_SLIP_COMPRESSED=y
-+CONFIG_NETCONSOLE=m
++CONFIG_LIBERTAS_THINFIRM=m
++CONFIG_LIBERTAS_THINFIRM_USB=m
++CONFIG_AT76C50X_USB=m
++CONFIG_USB_ZD1201=m
++CONFIG_USB_NET_RNDIS_WLAN=m
++CONFIG_RTL8187=m
++CONFIG_MAC80211_HWSIM=m
++CONFIG_B43=m
++CONFIG_B43LEGACY=m
++CONFIG_HOSTAP=m
++CONFIG_LIBERTAS=m
++CONFIG_LIBERTAS_USB=m
++CONFIG_LIBERTAS_SDIO=m
++CONFIG_P54_COMMON=m
++CONFIG_P54_USB=m
++CONFIG_RT2X00=m
++CONFIG_RT2500USB=m
++CONFIG_RT73USB=m
++CONFIG_RT2800USB=m
++CONFIG_RT2800USB_RT53XX=y
++CONFIG_RTL8192CU=m
++CONFIG_ZD1211RW=m
++CONFIG_MWIFIEX=m
++CONFIG_MWIFIEX_SDIO=m
++CONFIG_WIMAX_I2400M_USB=m
+CONFIG_INPUT_POLLDEV=m
+# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
+CONFIG_INPUT_JOYDEV=m
@@ -1857,7 +1775,6 @@ diff -Nur linux-3.12.26.orig/arch/arm/configs/bcmrpi_emergency_defconfig linux-3
+# CONFIG_INPUT_MOUSE is not set
+CONFIG_INPUT_MISC=y
+CONFIG_INPUT_AD714X=m
-+CONFIG_INPUT_ATI_REMOTE=m
+CONFIG_INPUT_ATI_REMOTE2=m
+CONFIG_INPUT_KEYSPAN_REMOTE=m
+CONFIG_INPUT_POWERMATE=m
@@ -1872,7 +1789,6 @@ diff -Nur linux-3.12.26.orig/arch/arm/configs/bcmrpi_emergency_defconfig linux-3
+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
@@ -1883,7 +1799,6 @@ diff -Nur linux-3.12.26.orig/arch/arm/configs/bcmrpi_emergency_defconfig linux-3
+# CONFIG_HWMON is not set
+CONFIG_WATCHDOG=y
+CONFIG_BCM2708_WDT=m
-+# CONFIG_MFD_SUPPORT is not set
+CONFIG_FB=y
+CONFIG_FB_BCM2708=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
@@ -1910,8 +1825,6 @@ diff -Nur linux-3.12.26.orig/arch/arm/configs/bcmrpi_emergency_defconfig linux-3
+CONFIG_SND_USB_CAIAQ=m
+CONFIG_SND_USB_6FIRE=m
+CONFIG_SOUND_PRIME=m
-+CONFIG_HID_PID=y
-+CONFIG_USB_HIDDEV=y
+CONFIG_HID_A4TECH=m
+CONFIG_HID_ACRUX=m
+CONFIG_HID_APPLE=m
@@ -1942,20 +1855,18 @@ diff -Nur linux-3.12.26.orig/arch/arm/configs/bcmrpi_emergency_defconfig linux-3
+CONFIG_HID_PANTHERLORD=m
+CONFIG_HID_PETALYNX=m
+CONFIG_HID_PICOLCD=m
-+CONFIG_HID_QUANTA=m
+CONFIG_HID_ROCCAT=m
+CONFIG_HID_SAMSUNG=m
-+CONFIG_HID_SONY=m
+CONFIG_HID_SPEEDLINK=m
+CONFIG_HID_SUNPLUS=m
+CONFIG_HID_GREENASIA=m
+CONFIG_HID_SMARTJOYPLUS=m
+CONFIG_HID_TOPSEED=m
+CONFIG_HID_THRUSTMASTER=m
-+CONFIG_HID_WACOM=m
-+CONFIG_HID_WIIMOTE=m
+CONFIG_HID_ZEROPLUS=m
+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
@@ -1974,8 +1885,6 @@ diff -Nur linux-3.12.26.orig/arch/arm/configs/bcmrpi_emergency_defconfig linux-3
+CONFIG_USB_STORAGE_KARMA=m
+CONFIG_USB_STORAGE_CYPRESS_ATACB=m
+CONFIG_USB_STORAGE_ENE_UB6250=m
-+CONFIG_USB_UAS=y
-+CONFIG_USB_LIBUSUAL=y
+CONFIG_USB_MDC800=m
+CONFIG_USB_MICROTEK=m
+CONFIG_USB_SERIAL=m
@@ -1990,7 +1899,6 @@ diff -Nur linux-3.12.26.orig/arch/arm/configs/bcmrpi_emergency_defconfig linux-3
+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
@@ -2006,16 +1914,13 @@ diff -Nur linux-3.12.26.orig/arch/arm/configs/bcmrpi_emergency_defconfig linux-3
+CONFIG_USB_SERIAL_MCT_U232=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
@@ -2024,8 +1929,6 @@ diff -Nur linux-3.12.26.orig/arch/arm/configs/bcmrpi_emergency_defconfig linux-3
+CONFIG_USB_SERIAL_OPTION=m
+CONFIG_USB_SERIAL_OMNINET=m
+CONFIG_USB_SERIAL_OPTICON=m
-+CONFIG_USB_SERIAL_VIVOPAY_SERIAL=m
-+CONFIG_USB_SERIAL_ZIO=m
+CONFIG_USB_SERIAL_SSU100=m
+CONFIG_USB_SERIAL_DEBUG=m
+CONFIG_USB_EMI62=m
@@ -2052,12 +1955,9 @@ diff -Nur linux-3.12.26.orig/arch/arm/configs/bcmrpi_emergency_defconfig linux-3
+CONFIG_MMC_SDHCI_PLTFM=y
+CONFIG_MMC_SDHCI_BCM2708=y
+CONFIG_MMC_SDHCI_BCM2708_DMA=y
-+CONFIG_LEDS_GPIO=y
-+CONFIG_LEDS_TRIGGER_TIMER=m
-+CONFIG_LEDS_TRIGGER_HEARTBEAT=m
-+CONFIG_LEDS_TRIGGER_DEFAULT_ON=m
++CONFIG_MMC_BCM2835=y
++CONFIG_MMC_BCM2835_DMA=y
+CONFIG_UIO=m
-+CONFIG_UIO_PDRV=m
+CONFIG_UIO_PDRV_GENIRQ=m
+# CONFIG_IOMMU_SUPPORT is not set
+CONFIG_EXT4_FS=y
@@ -2104,7 +2004,6 @@ diff -Nur linux-3.12.26.orig/arch/arm/configs/bcmrpi_emergency_defconfig linux-3
+CONFIG_SQUASHFS_LZO=y
+CONFIG_SQUASHFS_XZ=y
+CONFIG_NFS_FS=y
-+CONFIG_NFS_V3=y
+CONFIG_NFS_V3_ACL=y
+CONFIG_NFS_V4=y
+CONFIG_ROOT_NFS=y
@@ -2115,9 +2014,6 @@ diff -Nur linux-3.12.26.orig/arch/arm/configs/bcmrpi_emergency_defconfig linux-3
+CONFIG_CIFS_POSIX=y
+CONFIG_9P_FS=m
+CONFIG_9P_FS_POSIX_ACL=y
-+CONFIG_PARTITION_ADVANCED=y
-+CONFIG_MAC_PARTITION=y
-+CONFIG_EFI_PARTITION=y
+CONFIG_NLS_DEFAULT="utf8"
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_CODEPAGE_737=m
@@ -2158,14 +2054,13 @@ diff -Nur linux-3.12.26.orig/arch/arm/configs/bcmrpi_emergency_defconfig linux-3
+CONFIG_NLS_KOI8_U=m
+CONFIG_NLS_UTF8=m
+CONFIG_PRINTK_TIME=y
-+CONFIG_DETECT_HUNG_TASK=y
-+CONFIG_TIMER_STATS=y
-+CONFIG_DEBUG_STACK_USAGE=y
++CONFIG_BOOT_PRINTK_DELAY=y
+CONFIG_DEBUG_INFO=y
++CONFIG_DEBUG_STACK_USAGE=y
+CONFIG_DEBUG_MEMORY_INIT=y
-+CONFIG_BOOT_PRINTK_DELAY=y
++CONFIG_DETECT_HUNG_TASK=y
++CONFIG_TIMER_STATS=y
+CONFIG_LATENCYTOP=y
-+CONFIG_SYSCTL_SYSCALL_CHECK=y
+CONFIG_IRQSOFF_TRACER=y
+CONFIG_SCHED_TRACER=y
+CONFIG_STACK_TRACER=y
@@ -2182,7 +2077,6 @@ diff -Nur linux-3.12.26.orig/arch/arm/configs/bcmrpi_emergency_defconfig linux-3
+CONFIG_CRYPTO_XCBC=m
+CONFIG_CRYPTO_MD5=y
+CONFIG_CRYPTO_SHA1=y
-+CONFIG_CRYPTO_SHA256=m
+CONFIG_CRYPTO_SHA512=m
+CONFIG_CRYPTO_TGR192=m
+CONFIG_CRYPTO_WP512=m
@@ -2193,10 +2087,10 @@ diff -Nur linux-3.12.26.orig/arch/arm/configs/bcmrpi_emergency_defconfig linux-3
+# CONFIG_CRYPTO_HW is not set
+CONFIG_CRC_ITU_T=y
+CONFIG_LIBCRC32C=y
-diff -Nur linux-3.12.26.orig/arch/arm/configs/bcmrpi_quick_defconfig linux-3.12.26/arch/arm/configs/bcmrpi_quick_defconfig
---- linux-3.12.26.orig/arch/arm/configs/bcmrpi_quick_defconfig 1970-01-01 01:00:00.000000000 +0100
-+++ linux-3.12.26/arch/arm/configs/bcmrpi_quick_defconfig 2014-08-06 16:50:13.777956685 +0200
-@@ -0,0 +1,197 @@
+diff -Nur linux-3.12.33/arch/arm/configs/bcmrpi_quick_defconfig linux-3.12.33-rpi/arch/arm/configs/bcmrpi_quick_defconfig
+--- linux-3.12.33/arch/arm/configs/bcmrpi_quick_defconfig 1969-12-31 18:00:00.000000000 -0600
++++ linux-3.12.33-rpi/arch/arm/configs/bcmrpi_quick_defconfig 2014-12-03 19:13:32.288418001 -0600
+@@ -0,0 +1,198 @@
+# CONFIG_ARM_PATCH_PHYS_VIRT is not set
+CONFIG_LOCALVERSION="-quick"
+# CONFIG_LOCALVERSION_AUTO is not set
@@ -2281,7 +2175,6 @@ diff -Nur linux-3.12.26.orig/arch/arm/configs/bcmrpi_quick_defconfig linux-3.12.
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_SERIO is not set
-+CONFIG_VT_HW_CONSOLE_BINDING=y
+# CONFIG_LEGACY_PTYS is not set
+# CONFIG_DEVKMEM is not set
+CONFIG_SERIAL_AMBA_PL011=y
@@ -2317,6 +2210,8 @@ diff -Nur linux-3.12.26.orig/arch/arm/configs/bcmrpi_quick_defconfig linux-3.12.
+CONFIG_MMC_SDHCI_PLTFM=y
+CONFIG_MMC_SDHCI_BCM2708=y
+CONFIG_MMC_SDHCI_BCM2708_DMA=y
++CONFIG_MMC_BCM2835=y
++CONFIG_MMC_BCM2835_DMA=y
+CONFIG_NEW_LEDS=y
+CONFIG_LEDS_CLASS=y
+CONFIG_LEDS_TRIGGERS=y
@@ -2394,9 +2289,9 @@ diff -Nur linux-3.12.26.orig/arch/arm/configs/bcmrpi_quick_defconfig linux-3.12.
+# CONFIG_CRYPTO_HW is not set
+CONFIG_CRC_ITU_T=y
+CONFIG_LIBCRC32C=y
-diff -Nur linux-3.12.26.orig/arch/arm/include/asm/irqflags.h linux-3.12.26/arch/arm/include/asm/irqflags.h
---- linux-3.12.26.orig/arch/arm/include/asm/irqflags.h 2014-07-30 18:02:44.000000000 +0200
-+++ linux-3.12.26/arch/arm/include/asm/irqflags.h 2014-08-06 16:50:13.777956685 +0200
+diff -Nur linux-3.12.33/arch/arm/include/asm/irqflags.h linux-3.12.33-rpi/arch/arm/include/asm/irqflags.h
+--- linux-3.12.33/arch/arm/include/asm/irqflags.h 2014-11-15 06:28:07.000000000 -0600
++++ linux-3.12.33-rpi/arch/arm/include/asm/irqflags.h 2014-12-03 19:13:32.320418001 -0600
@@ -145,12 +145,22 @@
}
@@ -2423,9 +2318,35 @@ diff -Nur linux-3.12.26.orig/arch/arm/include/asm/irqflags.h linux-3.12.26/arch/
:
: "r" (flags)
: "memory", "cc");
-diff -Nur linux-3.12.26.orig/arch/arm/Kconfig linux-3.12.26/arch/arm/Kconfig
---- linux-3.12.26.orig/arch/arm/Kconfig 2014-07-30 18:02:44.000000000 +0200
-+++ linux-3.12.26/arch/arm/Kconfig 2014-08-06 16:50:13.777956685 +0200
+diff -Nur linux-3.12.33/arch/arm/include/asm/string.h linux-3.12.33-rpi/arch/arm/include/asm/string.h
+--- linux-3.12.33/arch/arm/include/asm/string.h 2014-11-15 06:28:07.000000000 -0600
++++ linux-3.12.33-rpi/arch/arm/include/asm/string.h 2014-12-03 19:13:32.324418001 -0600
+@@ -24,6 +24,11 @@
+ #define __HAVE_ARCH_MEMSET
+ extern void * memset(void *, int, __kernel_size_t);
+
++#ifdef CONFIG_MACH_BCM2708
++#define __HAVE_ARCH_MEMCMP
++extern int memcmp(const void *, const void *, size_t);
++#endif
++
+ extern void __memzero(void *ptr, __kernel_size_t n);
+
+ #define memset(p,v,n) \
+diff -Nur linux-3.12.33/arch/arm/include/asm/uaccess.h linux-3.12.33-rpi/arch/arm/include/asm/uaccess.h
+--- linux-3.12.33/arch/arm/include/asm/uaccess.h 2014-11-15 06:28:07.000000000 -0600
++++ linux-3.12.33-rpi/arch/arm/include/asm/uaccess.h 2014-12-03 19:13:32.324418001 -0600
+@@ -427,6 +427,7 @@
+
+ #ifdef CONFIG_MMU
+ extern unsigned long __must_check __copy_from_user(void *to, const void __user *from, unsigned long n);
++extern unsigned long __must_check __copy_from_user_std(void *to, const void __user *from, unsigned long n);
+ extern unsigned long __must_check __copy_to_user(void __user *to, const void *from, unsigned long n);
+ extern unsigned long __must_check __copy_to_user_std(void __user *to, const void *from, unsigned long n);
+ extern unsigned long __must_check __clear_user(void __user *addr, unsigned long n);
+diff -Nur linux-3.12.33/arch/arm/Kconfig linux-3.12.33-rpi/arch/arm/Kconfig
+--- linux-3.12.33/arch/arm/Kconfig 2014-11-15 06:28:07.000000000 -0600
++++ linux-3.12.33-rpi/arch/arm/Kconfig 2014-12-03 19:13:32.212418001 -0600
@@ -369,6 +369,24 @@
This enables support for systems based on Atmel
AT91RM9200 and AT91SAM9* processors.
@@ -2459,9 +2380,9 @@ diff -Nur linux-3.12.26.orig/arch/arm/Kconfig linux-3.12.26/arch/arm/Kconfig
source "arch/arm/mach-zynq/Kconfig"
-diff -Nur linux-3.12.26.orig/arch/arm/Kconfig.debug linux-3.12.26/arch/arm/Kconfig.debug
---- linux-3.12.26.orig/arch/arm/Kconfig.debug 2014-07-30 18:02:44.000000000 +0200
-+++ linux-3.12.26/arch/arm/Kconfig.debug 2014-08-06 16:50:13.781956717 +0200
+diff -Nur linux-3.12.33/arch/arm/Kconfig.debug linux-3.12.33-rpi/arch/arm/Kconfig.debug
+--- linux-3.12.33/arch/arm/Kconfig.debug 2014-11-15 06:28:07.000000000 -0600
++++ linux-3.12.33-rpi/arch/arm/Kconfig.debug 2014-12-03 19:13:32.212418001 -0600
@@ -847,6 +847,14 @@
options; the platform specific options are deprecated
and will be soon removed.
@@ -2477,9 +2398,9 @@ diff -Nur linux-3.12.26.orig/arch/arm/Kconfig.debug linux-3.12.26/arch/arm/Kconf
endchoice
config DEBUG_EXYNOS_UART
-diff -Nur linux-3.12.26.orig/arch/arm/kernel/fiqasm.S linux-3.12.26/arch/arm/kernel/fiqasm.S
---- linux-3.12.26.orig/arch/arm/kernel/fiqasm.S 2014-07-30 18:02:44.000000000 +0200
-+++ linux-3.12.26/arch/arm/kernel/fiqasm.S 2014-08-06 16:50:13.817956999 +0200
+diff -Nur linux-3.12.33/arch/arm/kernel/fiqasm.S linux-3.12.33-rpi/arch/arm/kernel/fiqasm.S
+--- linux-3.12.33/arch/arm/kernel/fiqasm.S 2014-11-15 06:28:07.000000000 -0600
++++ linux-3.12.33-rpi/arch/arm/kernel/fiqasm.S 2014-12-03 19:13:32.328418001 -0600
@@ -47,3 +47,7 @@
mov r0, r0 @ avoid hazard prior to ARMv4
mov pc, lr
@@ -2488,9 +2409,9 @@ diff -Nur linux-3.12.26.orig/arch/arm/kernel/fiqasm.S linux-3.12.26/arch/arm/ker
+ENTRY(__FIQ_Branch)
+ mov pc, r8
+ENDPROC(__FIQ_Branch)
-diff -Nur linux-3.12.26.orig/arch/arm/kernel/process.c linux-3.12.26/arch/arm/kernel/process.c
---- linux-3.12.26.orig/arch/arm/kernel/process.c 2014-07-30 18:02:44.000000000 +0200
-+++ linux-3.12.26/arch/arm/kernel/process.c 2014-08-06 16:50:13.817956999 +0200
+diff -Nur linux-3.12.33/arch/arm/kernel/process.c linux-3.12.33-rpi/arch/arm/kernel/process.c
+--- linux-3.12.33/arch/arm/kernel/process.c 2014-11-15 06:28:07.000000000 -0600
++++ linux-3.12.33-rpi/arch/arm/kernel/process.c 2014-12-03 19:13:32.332418001 -0600
@@ -176,6 +176,16 @@
default_idle();
}
@@ -2508,9 +2429,1460 @@ diff -Nur linux-3.12.26.orig/arch/arm/kernel/process.c linux-3.12.26/arch/arm/ke
/*
* Called by kexec, immediately prior to machine_kexec().
*
-diff -Nur linux-3.12.26.orig/arch/arm/mach-bcm2708/armctrl.c linux-3.12.26/arch/arm/mach-bcm2708/armctrl.c
---- linux-3.12.26.orig/arch/arm/mach-bcm2708/armctrl.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-3.12.26/arch/arm/mach-bcm2708/armctrl.c 2014-08-06 16:50:13.821957030 +0200
+diff -Nur linux-3.12.33/arch/arm/lib/arm-mem.h linux-3.12.33-rpi/arch/arm/lib/arm-mem.h
+--- linux-3.12.33/arch/arm/lib/arm-mem.h 1969-12-31 18:00:00.000000000 -0600
++++ linux-3.12.33-rpi/arch/arm/lib/arm-mem.h 2014-12-03 19:13:32.424418001 -0600
+@@ -0,0 +1,159 @@
++/*
++Copyright (c) 2013, Raspberry Pi Foundation
++Copyright (c) 2013, RISC OS Open Ltd
++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 the copyright holder 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 THE COPYRIGHT HOLDER OR CONTRIBUTORS 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.
++*/
++
++.macro myfunc fname
++ .func fname
++ .global fname
++fname:
++.endm
++
++.macro preload_leading_step1 backwards, ptr, base
++/* If the destination is already 16-byte aligned, then we need to preload
++ * between 0 and prefetch_distance (inclusive) cache lines ahead so there
++ * are no gaps when the inner loop starts.
++ */
++ .if backwards
++ sub ptr, base, #1
++ bic ptr, ptr, #31
++ .else
++ bic ptr, base, #31
++ .endif
++ .set OFFSET, 0
++ .rept prefetch_distance+1
++ pld [ptr, #OFFSET]
++ .if backwards
++ .set OFFSET, OFFSET-32
++ .else
++ .set OFFSET, OFFSET+32
++ .endif
++ .endr
++.endm
++
++.macro preload_leading_step2 backwards, ptr, base, leading_bytes, tmp
++/* However, if the destination is not 16-byte aligned, we may need to
++ * preload one more cache line than that. The question we need to ask is:
++ * are the leading bytes more than the amount by which the source
++ * pointer will be rounded down for preloading, and if so, by how many
++ * cache lines?
++ */
++ .if backwards
++/* Here we compare against how many bytes we are into the
++ * cache line, counting down from the highest such address.
++ * Effectively, we want to calculate
++ * leading_bytes = dst&15
++ * cacheline_offset = 31-((src-leading_bytes-1)&31)
++ * extra_needed = leading_bytes - cacheline_offset
++ * and test if extra_needed is <= 0, or rearranging:
++ * leading_bytes + (src-leading_bytes-1)&31 <= 31
++ */
++ mov tmp, base, lsl #32-5
++ sbc tmp, tmp, leading_bytes, lsl #32-5
++ adds tmp, tmp, leading_bytes, lsl #32-5
++ bcc 61f
++ pld [ptr, #-32*(prefetch_distance+1)]
++ .else
++/* Effectively, we want to calculate
++ * leading_bytes = (-dst)&15
++ * cacheline_offset = (src+leading_bytes)&31
++ * extra_needed = leading_bytes - cacheline_offset
++ * and test if extra_needed is <= 0.
++ */
++ mov tmp, base, lsl #32-5
++ add tmp, tmp, leading_bytes, lsl #32-5
++ rsbs tmp, tmp, leading_bytes, lsl #32-5
++ bls 61f
++ pld [ptr, #32*(prefetch_distance+1)]
++ .endif
++61:
++.endm
++
++.macro preload_trailing backwards, base, remain, tmp
++ /* We need either 0, 1 or 2 extra preloads */
++ .if backwards
++ rsb tmp, base, #0
++ mov tmp, tmp, lsl #32-5
++ .else
++ mov tmp, base, lsl #32-5
++ .endif
++ adds tmp, tmp, remain, lsl #32-5
++ adceqs tmp, tmp, #0
++ /* The instruction above has two effects: ensures Z is only
++ * set if C was clear (so Z indicates that both shifted quantities
++ * were 0), and clears C if Z was set (so C indicates that the sum
++ * of the shifted quantities was greater and not equal to 32) */
++ beq 82f
++ .if backwards
++ sub tmp, base, #1
++ bic tmp, tmp, #31
++ .else
++ bic tmp, base, #31
++ .endif
++ bcc 81f
++ .if backwards
++ pld [tmp, #-32*(prefetch_distance+1)]
++81:
++ pld [tmp, #-32*prefetch_distance]
++ .else
++ pld [tmp, #32*(prefetch_distance+2)]
++81:
++ pld [tmp, #32*(prefetch_distance+1)]
++ .endif
++82:
++.endm
++
++.macro preload_all backwards, narrow_case, shift, base, remain, tmp0, tmp1
++ .if backwards
++ sub tmp0, base, #1
++ bic tmp0, tmp0, #31
++ pld [tmp0]
++ sub tmp1, base, remain, lsl #shift
++ .else
++ bic tmp0, base, #31
++ pld [tmp0]
++ add tmp1, base, remain, lsl #shift
++ sub tmp1, tmp1, #1
++ .endif
++ bic tmp1, tmp1, #31
++ cmp tmp1, tmp0
++ beq 92f
++ .if narrow_case
++ /* In this case, all the data fits in either 1 or 2 cache lines */
++ pld [tmp1]
++ .else
++91:
++ .if backwards
++ sub tmp0, tmp0, #32
++ .else
++ add tmp0, tmp0, #32
++ .endif
++ cmp tmp0, tmp1
++ pld [tmp0]
++ bne 91b
++ .endif
++92:
++.endm
+diff -Nur linux-3.12.33/arch/arm/lib/copy_from_user.S linux-3.12.33-rpi/arch/arm/lib/copy_from_user.S
+--- linux-3.12.33/arch/arm/lib/copy_from_user.S 2014-11-15 06:28:07.000000000 -0600
++++ linux-3.12.33-rpi/arch/arm/lib/copy_from_user.S 2014-12-03 19:13:32.424418001 -0600
+@@ -84,11 +84,13 @@
+
+ .text
+
+-ENTRY(__copy_from_user)
++ENTRY(__copy_from_user_std)
++WEAK(__copy_from_user)
+
+ #include "copy_template.S"
+
+ ENDPROC(__copy_from_user)
++ENDPROC(__copy_from_user_std)
+
+ .pushsection .fixup,"ax"
+ .align 0
+diff -Nur linux-3.12.33/arch/arm/lib/exports_rpi.c linux-3.12.33-rpi/arch/arm/lib/exports_rpi.c
+--- linux-3.12.33/arch/arm/lib/exports_rpi.c 1969-12-31 18:00:00.000000000 -0600
++++ linux-3.12.33-rpi/arch/arm/lib/exports_rpi.c 2014-12-03 19:13:32.428418001 -0600
+@@ -0,0 +1,37 @@
++/**
++ * Copyright (c) 2014, Raspberry Pi (Trading) Ltd.
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions
++ * are met:
++ * 1. Redistributions of source code must retain the above copyright
++ * notice, this list of conditions, and the following disclaimer,
++ * without modification.
++ * 2. 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.
++ * 3. The names of the above-listed copyright holders may not be used
++ * to endorse or promote products derived from this software without
++ * specific prior written permission.
++ *
++ * ALTERNATIVELY, this software may be distributed under the terms of the
++ * GNU General Public License ("GPL") version 2, as published by the Free
++ * Software Foundation.
++ *
++ * 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 THE COPYRIGHT OWNER OR
++ * CONTRIBUTORS 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 <linux/kernel.h>
++#include <linux/module.h>
++
++EXPORT_SYMBOL(memcmp);
+diff -Nur linux-3.12.33/arch/arm/lib/Makefile linux-3.12.33-rpi/arch/arm/lib/Makefile
+--- linux-3.12.33/arch/arm/lib/Makefile 2014-11-15 06:28:07.000000000 -0600
++++ linux-3.12.33-rpi/arch/arm/lib/Makefile 2014-12-03 19:13:32.424418001 -0600
+@@ -6,15 +6,24 @@
+
+ lib-y := backtrace.o changebit.o csumipv6.o csumpartial.o \
+ csumpartialcopy.o csumpartialcopyuser.o clearbit.o \
+- delay.o delay-loop.o findbit.o memchr.o memcpy.o \
+- memmove.o memset.o memzero.o setbit.o \
+- strchr.o strrchr.o \
++ delay.o delay-loop.o findbit.o memchr.o memzero.o \
++ setbit.o strchr.o strrchr.o \
+ testchangebit.o testclearbit.o testsetbit.o \
+ ashldi3.o ashrdi3.o lshrdi3.o muldi3.o \
+ ucmpdi2.o lib1funcs.o div64.o \
+ io-readsb.o io-writesb.o io-readsl.o io-writesl.o \
+ call_with_stack.o
+
++# Choose optimised implementations for Raspberry Pi
++ifeq ($(CONFIG_MACH_BCM2708),y)
++ CFLAGS_uaccess_with_memcpy.o += -DCOPY_FROM_USER_THRESHOLD=1600
++ CFLAGS_uaccess_with_memcpy.o += -DCOPY_TO_USER_THRESHOLD=672
++ obj-$(CONFIG_MODULES) += exports_rpi.o
++ lib-y += memcpy_rpi.o memmove_rpi.o memset_rpi.o memcmp_rpi.o
++else
++ lib-y += memcpy.o memmove.o memset.o
++endif
++
+ mmu-y := clear_user.o copy_page.o getuser.o putuser.o
+
+ # the code in uaccess.S is not preemption safe and
+diff -Nur linux-3.12.33/arch/arm/lib/memcmp_rpi.S linux-3.12.33-rpi/arch/arm/lib/memcmp_rpi.S
+--- linux-3.12.33/arch/arm/lib/memcmp_rpi.S 1969-12-31 18:00:00.000000000 -0600
++++ linux-3.12.33-rpi/arch/arm/lib/memcmp_rpi.S 2014-12-03 19:13:32.432418001 -0600
+@@ -0,0 +1,285 @@
++/*
++Copyright (c) 2013, Raspberry Pi Foundation
++Copyright (c) 2013, RISC OS Open Ltd
++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 the copyright holder 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 THE COPYRIGHT HOLDER OR CONTRIBUTORS 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 <linux/linkage.h>
++#include "arm-mem.h"
++
++/* Prevent the stack from becoming executable */
++#if defined(__linux__) && defined(__ELF__)
++.section .note.GNU-stack,"",%progbits
++#endif
++
++ .text
++ .arch armv6
++ .object_arch armv4
++ .arm
++ .altmacro
++ .p2align 2
++
++.macro memcmp_process_head unaligned
++ .if unaligned
++ ldr DAT0, [S_1], #4
++ ldr DAT1, [S_1], #4
++ ldr DAT2, [S_1], #4
++ ldr DAT3, [S_1], #4
++ .else
++ ldmia S_1!, {DAT0, DAT1, DAT2, DAT3}
++ .endif
++ ldmia S_2!, {DAT4, DAT5, DAT6, DAT7}
++.endm
++
++.macro memcmp_process_tail
++ cmp DAT0, DAT4
++ cmpeq DAT1, DAT5
++ cmpeq DAT2, DAT6
++ cmpeq DAT3, DAT7
++ bne 200f
++.endm
++
++.macro memcmp_leading_31bytes
++ movs DAT0, OFF, lsl #31
++ ldrmib DAT0, [S_1], #1
++ ldrcsh DAT1, [S_1], #2
++ ldrmib DAT4, [S_2], #1
++ ldrcsh DAT5, [S_2], #2
++ movpl DAT0, #0
++ movcc DAT1, #0
++ movpl DAT4, #0
++ movcc DAT5, #0
++ submi N, N, #1
++ subcs N, N, #2
++ cmp DAT0, DAT4
++ cmpeq DAT1, DAT5
++ bne 200f
++ movs DAT0, OFF, lsl #29
++ ldrmi DAT0, [S_1], #4
++ ldrcs DAT1, [S_1], #4
++ ldrcs DAT2, [S_1], #4
++ ldrmi DAT4, [S_2], #4
++ ldmcsia S_2!, {DAT5, DAT6}
++ movpl DAT0, #0
++ movcc DAT1, #0
++ movcc DAT2, #0
++ movpl DAT4, #0
++ movcc DAT5, #0
++ movcc DAT6, #0
++ submi N, N, #4
++ subcs N, N, #8
++ cmp DAT0, DAT4
++ cmpeq DAT1, DAT5
++ cmpeq DAT2, DAT6
++ bne 200f
++ tst OFF, #16
++ beq 105f
++ memcmp_process_head 1
++ sub N, N, #16
++ memcmp_process_tail
++105:
++.endm
++
++.macro memcmp_trailing_15bytes unaligned
++ movs N, N, lsl #29
++ .if unaligned
++ ldrcs DAT0, [S_1], #4
++ ldrcs DAT1, [S_1], #4
++ .else
++ ldmcsia S_1!, {DAT0, DAT1}
++ .endif
++ ldrmi DAT2, [S_1], #4
++ ldmcsia S_2!, {DAT4, DAT5}
++ ldrmi DAT6, [S_2], #4
++ movcc DAT0, #0
++ movcc DAT1, #0
++ movpl DAT2, #0
++ movcc DAT4, #0
++ movcc DAT5, #0
++ movpl DAT6, #0
++ cmp DAT0, DAT4
++ cmpeq DAT1, DAT5
++ cmpeq DAT2, DAT6
++ bne 200f
++ movs N, N, lsl #2
++ ldrcsh DAT0, [S_1], #2
++ ldrmib DAT1, [S_1]
++ ldrcsh DAT4, [S_2], #2
++ ldrmib DAT5, [S_2]
++ movcc DAT0, #0
++ movpl DAT1, #0
++ movcc DAT4, #0
++ movpl DAT5, #0
++ cmp DAT0, DAT4
++ cmpeq DAT1, DAT5
++ bne 200f
++.endm
++
++.macro memcmp_long_inner_loop unaligned
++110:
++ memcmp_process_head unaligned
++ pld [S_2, #prefetch_distance*32 + 16]
++ memcmp_process_tail
++ memcmp_process_head unaligned
++ pld [S_1, OFF]
++ memcmp_process_tail
++ subs N, N, #32
++ bhs 110b
++ /* Just before the final (prefetch_distance+1) 32-byte blocks,
++ * deal with final preloads */
++ preload_trailing 0, S_1, N, DAT0
++ preload_trailing 0, S_2, N, DAT0
++ add N, N, #(prefetch_distance+2)*32 - 16
++120:
++ memcmp_process_head unaligned
++ memcmp_process_tail
++ subs N, N, #16
++ bhs 120b
++ /* Trailing words and bytes */
++ tst N, #15
++ beq 199f
++ memcmp_trailing_15bytes unaligned
++199: /* Reached end without detecting a difference */
++ mov a1, #0
++ setend le
++ pop {DAT1-DAT6, pc}
++.endm
++
++.macro memcmp_short_inner_loop unaligned
++ subs N, N, #16 /* simplifies inner loop termination */
++ blo 122f
++120:
++ memcmp_process_head unaligned
++ memcmp_process_tail
++ subs N, N, #16
++ bhs 120b
++122: /* Trailing words and bytes */
++ tst N, #15
++ beq 199f
++ memcmp_trailing_15bytes unaligned
++199: /* Reached end without detecting a difference */
++ mov a1, #0
++ setend le
++ pop {DAT1-DAT6, pc}
++.endm
++
++/*
++ * int memcmp(const void *s1, const void *s2, size_t n);
++ * On entry:
++ * a1 = pointer to buffer 1
++ * a2 = pointer to buffer 2
++ * a3 = number of bytes to compare (as unsigned chars)
++ * On exit:
++ * a1 = >0/=0/<0 if s1 >/=/< s2
++ */
++
++.set prefetch_distance, 2
++
++ENTRY(memcmp)
++ S_1 .req a1
++ S_2 .req a2
++ N .req a3
++ DAT0 .req a4
++ DAT1 .req v1
++ DAT2 .req v2
++ DAT3 .req v3
++ DAT4 .req v4
++ DAT5 .req v5
++ DAT6 .req v6
++ DAT7 .req ip
++ OFF .req lr
++
++ push {DAT1-DAT6, lr}
++ setend be /* lowest-addressed bytes are most significant */
++
++ /* To preload ahead as we go, we need at least (prefetch_distance+2) 32-byte blocks */
++ cmp N, #(prefetch_distance+3)*32 - 1
++ blo 170f
++
++ /* Long case */
++ /* Adjust N so that the decrement instruction can also test for
++ * inner loop termination. We want it to stop when there are
++ * (prefetch_distance+1) complete blocks to go. */
++ sub N, N, #(prefetch_distance+2)*32
++ preload_leading_step1 0, DAT0, S_1
++ preload_leading_step1 0, DAT1, S_2
++ tst S_2, #31
++ beq 154f
++ rsb OFF, S_2, #0 /* no need to AND with 15 here */
++ preload_leading_step2 0, DAT0, S_1, OFF, DAT2
++ preload_leading_step2 0, DAT1, S_2, OFF, DAT2
++ memcmp_leading_31bytes
++154: /* Second source now cacheline (32-byte) aligned; we have at
++ * least one prefetch to go. */
++ /* Prefetch offset is best selected such that it lies in the
++ * first 8 of each 32 bytes - but it's just as easy to aim for
++ * the first one */
++ and OFF, S_1, #31
++ rsb OFF, OFF, #32*prefetch_distance
++ tst S_1, #3
++ bne 140f
++ memcmp_long_inner_loop 0
++140: memcmp_long_inner_loop 1
++
++170: /* Short case */
++ teq N, #0
++ beq 199f
++ preload_all 0, 0, 0, S_1, N, DAT0, DAT1
++ preload_all 0, 0, 0, S_2, N, DAT0, DAT1
++ tst S_2, #3
++ beq 174f
++172: subs N, N, #1
++ blo 199f
++ ldrb DAT0, [S_1], #1
++ ldrb DAT4, [S_2], #1
++ cmp DAT0, DAT4
++ bne 200f
++ tst S_2, #3
++ bne 172b
++174: /* Second source now 4-byte aligned; we have 0 or more bytes to go */
++ tst S_1, #3
++ bne 140f
++ memcmp_short_inner_loop 0
++140: memcmp_short_inner_loop 1
++
++200: /* Difference found: determine sign. */
++ movhi a1, #1
++ movlo a1, #-1
++ setend le
++ pop {DAT1-DAT6, pc}
++
++ .unreq S_1
++ .unreq S_2
++ .unreq N
++ .unreq DAT0
++ .unreq DAT1
++ .unreq DAT2
++ .unreq DAT3
++ .unreq DAT4
++ .unreq DAT5
++ .unreq DAT6
++ .unreq DAT7
++ .unreq OFF
++ENDPROC(memcmp)
+diff -Nur linux-3.12.33/arch/arm/lib/memcpymove.h linux-3.12.33-rpi/arch/arm/lib/memcpymove.h
+--- linux-3.12.33/arch/arm/lib/memcpymove.h 1969-12-31 18:00:00.000000000 -0600
++++ linux-3.12.33-rpi/arch/arm/lib/memcpymove.h 2014-12-03 19:13:32.432418001 -0600
+@@ -0,0 +1,506 @@
++/*
++Copyright (c) 2013, Raspberry Pi Foundation
++Copyright (c) 2013, RISC OS Open Ltd
++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 the copyright holder 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 THE COPYRIGHT HOLDER OR CONTRIBUTORS 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.
++*/
++
++.macro unaligned_words backwards, align, use_pld, words, r0, r1, r2, r3, r4, r5, r6, r7, r8
++ .if words == 1
++ .if backwards
++ mov r1, r0, lsl #32-align*8
++ ldr r0, [S, #-4]!
++ orr r1, r1, r0, lsr #align*8
++ str r1, [D, #-4]!
++ .else
++ mov r0, r1, lsr #align*8
++ ldr r1, [S, #4]!
++ orr r0, r0, r1, lsl #32-align*8
++ str r0, [D], #4
++ .endif
++ .elseif words == 2
++ .if backwards
++ ldr r1, [S, #-4]!
++ mov r2, r0, lsl #32-align*8
++ ldr r0, [S, #-4]!
++ orr r2, r2, r1, lsr #align*8
++ mov r1, r1, lsl #32-align*8
++ orr r1, r1, r0, lsr #align*8
++ stmdb D!, {r1, r2}
++ .else
++ ldr r1, [S, #4]!
++ mov r0, r2, lsr #align*8
++ ldr r2, [S, #4]!
++ orr r0, r0, r1, lsl #32-align*8
++ mov r1, r1, lsr #align*8
++ orr r1, r1, r2, lsl #32-align*8
++ stmia D!, {r0, r1}
++ .endif
++ .elseif words == 4
++ .if backwards
++ ldmdb S!, {r2, r3}
++ mov r4, r0, lsl #32-align*8
++ ldmdb S!, {r0, r1}
++ orr r4, r4, r3, lsr #align*8
++ mov r3, r3, lsl #32-align*8
++ orr r3, r3, r2, lsr #align*8
++ mov r2, r2, lsl #32-align*8
++ orr r2, r2, r1, lsr #align*8
++ mov r1, r1, lsl #32-align*8
++ orr r1, r1, r0, lsr #align*8
++ stmdb D!, {r1, r2, r3, r4}
++ .else
++ ldmib S!, {r1, r2}
++ mov r0, r4, lsr #align*8
++ ldmib S!, {r3, r4}
++ orr r0, r0, r1, lsl #32-align*8
++ mov r1, r1, lsr #align*8
++ orr r1, r1, r2, lsl #32-align*8
++ mov r2, r2, lsr #align*8
++ orr r2, r2, r3, lsl #32-align*8
++ mov r3, r3, lsr #align*8
++ orr r3, r3, r4, lsl #32-align*8
++ stmia D!, {r0, r1, r2, r3}
++ .endif
++ .elseif words == 8
++ .if backwards
++ ldmdb S!, {r4, r5, r6, r7}
++ mov r8, r0, lsl #32-align*8
++ ldmdb S!, {r0, r1, r2, r3}
++ .if use_pld
++ pld [S, OFF]
++ .endif
++ orr r8, r8, r7, lsr #align*8
++ mov r7, r7, lsl #32-align*8
++ orr r7, r7, r6, lsr #align*8
++ mov r6, r6, lsl #32-align*8
++ orr r6, r6, r5, lsr #align*8
++ mov r5, r5, lsl #32-align*8
++ orr r5, r5, r4, lsr #align*8
++ mov r4, r4, lsl #32-align*8
++ orr r4, r4, r3, lsr #align*8
++ mov r3, r3, lsl #32-align*8
++ orr r3, r3, r2, lsr #align*8
++ mov r2, r2, lsl #32-align*8
++ orr r2, r2, r1, lsr #align*8
++ mov r1, r1, lsl #32-align*8
++ orr r1, r1, r0, lsr #align*8
++ stmdb D!, {r5, r6, r7, r8}
++ stmdb D!, {r1, r2, r3, r4}
++ .else
++ ldmib S!, {r1, r2, r3, r4}
++ mov r0, r8, lsr #align*8
++ ldmib S!, {r5, r6, r7, r8}
++ .if use_pld
++ pld [S, OFF]
++ .endif
++ orr r0, r0, r1, lsl #32-align*8
++ mov r1, r1, lsr #align*8
++ orr r1, r1, r2, lsl #32-align*8
++ mov r2, r2, lsr #align*8
++ orr r2, r2, r3, lsl #32-align*8
++ mov r3, r3, lsr #align*8
++ orr r3, r3, r4, lsl #32-align*8
++ mov r4, r4, lsr #align*8
++ orr r4, r4, r5, lsl #32-align*8
++ mov r5, r5, lsr #align*8
++ orr r5, r5, r6, lsl #32-align*8
++ mov r6, r6, lsr #align*8
++ orr r6, r6, r7, lsl #32-align*8
++ mov r7, r7, lsr #align*8
++ orr r7, r7, r8, lsl #32-align*8
++ stmia D!, {r0, r1, r2, r3}
++ stmia D!, {r4, r5, r6, r7}
++ .endif
++ .endif
++.endm
++
++.macro memcpy_leading_15bytes backwards, align
++ movs DAT1, DAT2, lsl #31
++ sub N, N, DAT2
++ .if backwards
++ ldrmib DAT0, [S, #-1]!
++ ldrcsh DAT1, [S, #-2]!
++ strmib DAT0, [D, #-1]!
++ strcsh DAT1, [D, #-2]!
++ .else
++ ldrmib DAT0, [S], #1
++ ldrcsh DAT1, [S], #2
++ strmib DAT0, [D], #1
++ strcsh DAT1, [D], #2
++ .endif
++ movs DAT1, DAT2, lsl #29
++ .if backwards
++ ldrmi DAT0, [S, #-4]!
++ .if align == 0
++ ldmcsdb S!, {DAT1, DAT2}
++ .else
++ ldrcs DAT2, [S, #-4]!
++ ldrcs DAT1, [S, #-4]!
++ .endif
++ strmi DAT0, [D, #-4]!
++ stmcsdb D!, {DAT1, DAT2}
++ .else
++ ldrmi DAT0, [S], #4
++ .if align == 0
++ ldmcsia S!, {DAT1, DAT2}
++ .else
++ ldrcs DAT1, [S], #4
++ ldrcs DAT2, [S], #4
++ .endif
++ strmi DAT0, [D], #4
++ stmcsia D!, {DAT1, DAT2}
++ .endif
++.endm
++
++.macro memcpy_trailing_15bytes backwards, align
++ movs N, N, lsl #29
++ .if backwards
++ .if align == 0
++ ldmcsdb S!, {DAT0, DAT1}
++ .else
++ ldrcs DAT1, [S, #-4]!
++ ldrcs DAT0, [S, #-4]!
++ .endif
++ ldrmi DAT2, [S, #-4]!
++ stmcsdb D!, {DAT0, DAT1}
++ strmi DAT2, [D, #-4]!
++ .else
++ .if align == 0
++ ldmcsia S!, {DAT0, DAT1}
++ .else
++ ldrcs DAT0, [S], #4
++ ldrcs DAT1, [S], #4
++ .endif
++ ldrmi DAT2, [S], #4
++ stmcsia D!, {DAT0, DAT1}
++ strmi DAT2, [D], #4
++ .endif
++ movs N, N, lsl #2
++ .if backwards
++ ldrcsh DAT0, [S, #-2]!
++ ldrmib DAT1, [S, #-1]
++ strcsh DAT0, [D, #-2]!
++ strmib DAT1, [D, #-1]
++ .else
++ ldrcsh DAT0, [S], #2
++ ldrmib DAT1, [S]
++ strcsh DAT0, [D], #2
++ strmib DAT1, [D]
++ .endif
++.endm
++
++.macro memcpy_long_inner_loop backwards, align
++ .if align != 0
++ .if backwards
++ ldr DAT0, [S, #-align]!
++ .else
++ ldr LAST, [S, #-align]!
++ .endif
++ .endif
++110:
++ .if align == 0
++ .if backwards
++ ldmdb S!, {DAT0, DAT1, DAT2, DAT3, DAT4, DAT5, DAT6, LAST}
++ pld [S, OFF]
++ stmdb D!, {DAT4, DAT5, DAT6, LAST}
++ stmdb D!, {DAT0, DAT1, DAT2, DAT3}
++ .else
++ ldmia S!, {DAT0, DAT1, DAT2, DAT3, DAT4, DAT5, DAT6, LAST}
++ pld [S, OFF]
++ stmia D!, {DAT0, DAT1, DAT2, DAT3}
++ stmia D!, {DAT4, DAT5, DAT6, LAST}
++ .endif
++ .else
++ unaligned_words backwards, align, 1, 8, DAT0, DAT1, DAT2, DAT3, DAT4, DAT5, DAT6, DAT7, LAST
++ .endif
++ subs N, N, #32
++ bhs 110b
++ /* Just before the final (prefetch_distance+1) 32-byte blocks, deal with final preloads */
++ preload_trailing backwards, S, N, OFF
++ add N, N, #(prefetch_distance+2)*32 - 32
++120:
++ .if align == 0
++ .if backwards
++ ldmdb S!, {DAT0, DAT1, DAT2, DAT3, DAT4, DAT5, DAT6, LAST}
++ stmdb D!, {DAT4, DAT5, DAT6, LAST}
++ stmdb D!, {DAT0, DAT1, DAT2, DAT3}
++ .else
++ ldmia S!, {DAT0, DAT1, DAT2, DAT3, DAT4, DAT5, DAT6, LAST}
++ stmia D!, {DAT0, DAT1, DAT2, DAT3}
++ stmia D!, {DAT4, DAT5, DAT6, LAST}
++ .endif
++ .else
++ unaligned_words backwards, align, 0, 8, DAT0, DAT1, DAT2, DAT3, DAT4, DAT5, DAT6, DAT7, LAST
++ .endif
++ subs N, N, #32
++ bhs 120b
++ tst N, #16
++ .if align == 0
++ .if backwards
++ ldmnedb S!, {DAT0, DAT1, DAT2, LAST}
++ stmnedb D!, {DAT0, DAT1, DAT2, LAST}
++ .else
++ ldmneia S!, {DAT0, DAT1, DAT2, LAST}
++ stmneia D!, {DAT0, DAT1, DAT2, LAST}
++ .endif
++ .else
++ beq 130f
++ unaligned_words backwards, align, 0, 4, DAT0, DAT1, DAT2, DAT3, LAST
++130:
++ .endif
++ /* Trailing words and bytes */
++ tst N, #15
++ beq 199f
++ .if align != 0
++ add S, S, #align
++ .endif
++ memcpy_trailing_15bytes backwards, align
++199:
++ pop {DAT3, DAT4, DAT5, DAT6, DAT7}
++ pop {D, DAT1, DAT2, pc}
++.endm
++
++.macro memcpy_medium_inner_loop backwards, align
++120:
++ .if backwards
++ .if align == 0
++ ldmdb S!, {DAT0, DAT1, DAT2, LAST}
++ .else
++ ldr LAST, [S, #-4]!
++ ldr DAT2, [S, #-4]!
++ ldr DAT1, [S, #-4]!
++ ldr DAT0, [S, #-4]!
++ .endif
++ stmdb D!, {DAT0, DAT1, DAT2, LAST}
++ .else
++ .if align == 0
++ ldmia S!, {DAT0, DAT1, DAT2, LAST}
++ .else
++ ldr DAT0, [S], #4
++ ldr DAT1, [S], #4
++ ldr DAT2, [S], #4
++ ldr LAST, [S], #4
++ .endif
++ stmia D!, {DAT0, DAT1, DAT2, LAST}
++ .endif
++ subs N, N, #16
++ bhs 120b
++ /* Trailing words and bytes */
++ tst N, #15
++ beq 199f
++ memcpy_trailing_15bytes backwards, align
++199:
++ pop {D, DAT1, DAT2, pc}
++.endm
++
++.macro memcpy_short_inner_loop backwards, align
++ tst N, #16
++ .if backwards
++ .if align == 0
++ ldmnedb S!, {DAT0, DAT1, DAT2, LAST}
++ .else
++ ldrne LAST, [S, #-4]!
++ ldrne DAT2, [S, #-4]!
++ ldrne DAT1, [S, #-4]!
++ ldrne DAT0, [S, #-4]!
++ .endif
++ stmnedb D!, {DAT0, DAT1, DAT2, LAST}
++ .else
++ .if align == 0
++ ldmneia S!, {DAT0, DAT1, DAT2, LAST}
++ .else
++ ldrne DAT0, [S], #4
++ ldrne DAT1, [S], #4
++ ldrne DAT2, [S], #4
++ ldrne LAST, [S], #4
++ .endif
++ stmneia D!, {DAT0, DAT1, DAT2, LAST}
++ .endif
++ memcpy_trailing_15bytes backwards, align
++199:
++ pop {D, DAT1, DAT2, pc}
++.endm
++
++.macro memcpy backwards
++ D .req a1
++ S .req a2
++ N .req a3
++ DAT0 .req a4
++ DAT1 .req v1
++ DAT2 .req v2
++ DAT3 .req v3
++ DAT4 .req v4
++ DAT5 .req v5
++ DAT6 .req v6
++ DAT7 .req sl
++ LAST .req ip
++ OFF .req lr
++
++ .cfi_startproc
++
++ push {D, DAT1, DAT2, lr}
++
++ .cfi_def_cfa_offset 16
++ .cfi_rel_offset D, 0
++ .cfi_undefined S
++ .cfi_undefined N
++ .cfi_undefined DAT0
++ .cfi_rel_offset DAT1, 4
++ .cfi_rel_offset DAT2, 8
++ .cfi_undefined LAST
++ .cfi_rel_offset lr, 12
++
++ .if backwards
++ add D, D, N
++ add S, S, N
++ .endif
++
++ /* See if we're guaranteed to have at least one 16-byte aligned 16-byte write */
++ cmp N, #31
++ blo 170f
++ /* To preload ahead as we go, we need at least (prefetch_distance+2) 32-byte blocks */
++ cmp N, #(prefetch_distance+3)*32 - 1
++ blo 160f
++
++ /* Long case */
++ push {DAT3, DAT4, DAT5, DAT6, DAT7}
++
++ .cfi_def_cfa_offset 36
++ .cfi_rel_offset D, 20
++ .cfi_rel_offset DAT1, 24
++ .cfi_rel_offset DAT2, 28
++ .cfi_rel_offset DAT3, 0
++ .cfi_rel_offset DAT4, 4
++ .cfi_rel_offset DAT5, 8
++ .cfi_rel_offset DAT6, 12
++ .cfi_rel_offset DAT7, 16
++ .cfi_rel_offset lr, 32
++
++ /* Adjust N so that the decrement instruction can also test for
++ * inner loop termination. We want it to stop when there are
++ * (prefetch_distance+1) complete blocks to go. */
++ sub N, N, #(prefetch_distance+2)*32
++ preload_leading_step1 backwards, DAT0, S
++ .if backwards
++ /* Bug in GAS: it accepts, but mis-assembles the instruction
++ * ands DAT2, D, #60, 2
++ * which sets DAT2 to the number of leading bytes until destination is aligned and also clears C (sets borrow)
++ */
++ .word 0xE210513C
++ beq 154f
++ .else
++ ands DAT2, D, #15
++ beq 154f
++ rsb DAT2, DAT2, #16 /* number of leading bytes until destination aligned */
++ .endif
++ preload_leading_step2 backwards, DAT0, S, DAT2, OFF
++ memcpy_leading_15bytes backwards, 1
++154: /* Destination now 16-byte aligned; we have at least one prefetch as well as at least one 16-byte output block */
++ /* Prefetch offset is best selected such that it lies in the first 8 of each 32 bytes - but it's just as easy to aim for the first one */
++ .if backwards
++ rsb OFF, S, #3
++ and OFF, OFF, #28
++ sub OFF, OFF, #32*(prefetch_distance+1)
++ .else
++ and OFF, S, #28
++ rsb OFF, OFF, #32*prefetch_distance
++ .endif
++ movs DAT0, S, lsl #31
++ bhi 157f
++ bcs 156f
++ bmi 155f
++ memcpy_long_inner_loop backwards, 0
++155: memcpy_long_inner_loop backwards, 1
++156: memcpy_long_inner_loop backwards, 2
++157: memcpy_long_inner_loop backwards, 3
++
++ .cfi_def_cfa_offset 16
++ .cfi_rel_offset D, 0
++ .cfi_rel_offset DAT1, 4
++ .cfi_rel_offset DAT2, 8
++ .cfi_same_value DAT3
++ .cfi_same_value DAT4
++ .cfi_same_value DAT5
++ .cfi_same_value DAT6
++ .cfi_same_value DAT7
++ .cfi_rel_offset lr, 12
++
++160: /* Medium case */
++ preload_all backwards, 0, 0, S, N, DAT2, OFF
++ sub N, N, #16 /* simplifies inner loop termination */
++ .if backwards
++ ands DAT2, D, #15
++ beq 164f
++ .else
++ ands DAT2, D, #15
++ beq 164f
++ rsb DAT2, DAT2, #16
++ .endif
++ memcpy_leading_15bytes backwards, align
++164: /* Destination now 16-byte aligned; we have at least one 16-byte output block */
++ tst S, #3
++ bne 140f
++ memcpy_medium_inner_loop backwards, 0
++140: memcpy_medium_inner_loop backwards, 1
++
++170: /* Short case, less than 31 bytes, so no guarantee of at least one 16-byte block */
++ teq N, #0
++ beq 199f
++ preload_all backwards, 1, 0, S, N, DAT2, LAST
++ tst D, #3
++ beq 174f
++172: subs N, N, #1
++ blo 199f
++ .if backwards
++ ldrb DAT0, [S, #-1]!
++ strb DAT0, [D, #-1]!
++ .else
++ ldrb DAT0, [S], #1
++ strb DAT0, [D], #1
++ .endif
++ tst D, #3
++ bne 172b
++174: /* Destination now 4-byte aligned; we have 0 or more output bytes to go */
++ tst S, #3
++ bne 140f
++ memcpy_short_inner_loop backwards, 0
++140: memcpy_short_inner_loop backwards, 1
++
++ .cfi_endproc
++
++ .unreq D
++ .unreq S
++ .unreq N
++ .unreq DAT0
++ .unreq DAT1
++ .unreq DAT2
++ .unreq DAT3
++ .unreq DAT4
++ .unreq DAT5
++ .unreq DAT6
++ .unreq DAT7
++ .unreq LAST
++ .unreq OFF
++.endm
+diff -Nur linux-3.12.33/arch/arm/lib/memcpy_rpi.S linux-3.12.33-rpi/arch/arm/lib/memcpy_rpi.S
+--- linux-3.12.33/arch/arm/lib/memcpy_rpi.S 1969-12-31 18:00:00.000000000 -0600
++++ linux-3.12.33-rpi/arch/arm/lib/memcpy_rpi.S 2014-12-03 19:13:32.432418001 -0600
+@@ -0,0 +1,59 @@
++/*
++Copyright (c) 2013, Raspberry Pi Foundation
++Copyright (c) 2013, RISC OS Open Ltd
++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 the copyright holder 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 THE COPYRIGHT HOLDER OR CONTRIBUTORS 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 <linux/linkage.h>
++#include "arm-mem.h"
++#include "memcpymove.h"
++
++/* Prevent the stack from becoming executable */
++#if defined(__linux__) && defined(__ELF__)
++.section .note.GNU-stack,"",%progbits
++#endif
++
++ .text
++ .arch armv6
++ .object_arch armv4
++ .arm
++ .altmacro
++ .p2align 2
++
++/*
++ * void *memcpy(void * restrict s1, const void * restrict s2, size_t n);
++ * On entry:
++ * a1 = pointer to destination
++ * a2 = pointer to source
++ * a3 = number of bytes to copy
++ * On exit:
++ * a1 preserved
++ */
++
++.set prefetch_distance, 3
++
++ENTRY(memcpy)
++ memcpy 0
++ENDPROC(memcpy)
+diff -Nur linux-3.12.33/arch/arm/lib/memmove_rpi.S linux-3.12.33-rpi/arch/arm/lib/memmove_rpi.S
+--- linux-3.12.33/arch/arm/lib/memmove_rpi.S 1969-12-31 18:00:00.000000000 -0600
++++ linux-3.12.33-rpi/arch/arm/lib/memmove_rpi.S 2014-12-03 19:13:32.432418001 -0600
+@@ -0,0 +1,61 @@
++/*
++Copyright (c) 2013, Raspberry Pi Foundation
++Copyright (c) 2013, RISC OS Open Ltd
++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 the copyright holder 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 THE COPYRIGHT HOLDER OR CONTRIBUTORS 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 <linux/linkage.h>
++#include "arm-mem.h"
++#include "memcpymove.h"
++
++/* Prevent the stack from becoming executable */
++#if defined(__linux__) && defined(__ELF__)
++.section .note.GNU-stack,"",%progbits
++#endif
++
++ .text
++ .arch armv6
++ .object_arch armv4
++ .arm
++ .altmacro
++ .p2align 2
++
++/*
++ * void *memmove(void *s1, const void *s2, size_t n);
++ * On entry:
++ * a1 = pointer to destination
++ * a2 = pointer to source
++ * a3 = number of bytes to copy
++ * On exit:
++ * a1 preserved
++ */
++
++.set prefetch_distance, 3
++
++ENTRY(memmove)
++ cmp a2, a1
++ bpl memcpy /* pl works even over -1 - 0 and 0x7fffffff - 0x80000000 boundaries */
++ memcpy 1
++ENDPROC(memmove)
+diff -Nur linux-3.12.33/arch/arm/lib/memset_rpi.S linux-3.12.33-rpi/arch/arm/lib/memset_rpi.S
+--- linux-3.12.33/arch/arm/lib/memset_rpi.S 1969-12-31 18:00:00.000000000 -0600
++++ linux-3.12.33-rpi/arch/arm/lib/memset_rpi.S 2014-12-03 19:13:32.432418001 -0600
+@@ -0,0 +1,121 @@
++/*
++Copyright (c) 2013, Raspberry Pi Foundation
++Copyright (c) 2013, RISC OS Open Ltd
++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 the copyright holder 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 THE COPYRIGHT HOLDER OR CONTRIBUTORS 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 <linux/linkage.h>
++#include "arm-mem.h"
++
++/* Prevent the stack from becoming executable */
++#if defined(__linux__) && defined(__ELF__)
++.section .note.GNU-stack,"",%progbits
++#endif
++
++ .text
++ .arch armv6
++ .object_arch armv4
++ .arm
++ .altmacro
++ .p2align 2
++
++/*
++ * void *memset(void *s, int c, size_t n);
++ * On entry:
++ * a1 = pointer to buffer to fill
++ * a2 = byte pattern to fill with (caller-narrowed)
++ * a3 = number of bytes to fill
++ * On exit:
++ * a1 preserved
++ */
++ENTRY(memset)
++ S .req a1
++ DAT0 .req a2
++ N .req a3
++ DAT1 .req a4
++ DAT2 .req ip
++ DAT3 .req lr
++
++ orr DAT0, DAT0, lsl #8
++ push {S, lr}
++ orr DAT0, DAT0, lsl #16
++ mov DAT1, DAT0
++
++ /* See if we're guaranteed to have at least one 16-byte aligned 16-byte write */
++ cmp N, #31
++ blo 170f
++
++161: sub N, N, #16 /* simplifies inner loop termination */
++ /* Leading words and bytes */
++ tst S, #15
++ beq 164f
++ rsb DAT3, S, #0 /* bits 0-3 = number of leading bytes until aligned */
++ movs DAT2, DAT3, lsl #31
++ submi N, N, #1
++ strmib DAT0, [S], #1
++ subcs N, N, #2
++ strcsh DAT0, [S], #2
++ movs DAT2, DAT3, lsl #29
++ submi N, N, #4
++ strmi DAT0, [S], #4
++ subcs N, N, #8
++ stmcsia S!, {DAT0, DAT1}
++164: /* Delayed set up of DAT2 and DAT3 so we could use them as scratch registers above */
++ mov DAT2, DAT0
++ mov DAT3, DAT0
++ /* Now the inner loop of 16-byte stores */
++165: stmia S!, {DAT0, DAT1, DAT2, DAT3}
++ subs N, N, #16
++ bhs 165b
++166: /* Trailing words and bytes */
++ movs N, N, lsl #29
++ stmcsia S!, {DAT0, DAT1}
++ strmi DAT0, [S], #4
++ movs N, N, lsl #2
++ strcsh DAT0, [S], #2
++ strmib DAT0, [S]
++199: pop {S, pc}
++
++170: /* Short case */
++ mov DAT2, DAT0
++ mov DAT3, DAT0
++ tst S, #3
++ beq 174f
++172: subs N, N, #1
++ blo 199b
++ strb DAT0, [S], #1
++ tst S, #3
++ bne 172b
++174: tst N, #16
++ stmneia S!, {DAT0, DAT1, DAT2, DAT3}
++ b 166b
++
++ .unreq S
++ .unreq DAT0
++ .unreq N
++ .unreq DAT1
++ .unreq DAT2
++ .unreq DAT3
++ENDPROC(memset)
+diff -Nur linux-3.12.33/arch/arm/lib/uaccess_with_memcpy.c linux-3.12.33-rpi/arch/arm/lib/uaccess_with_memcpy.c
+--- linux-3.12.33/arch/arm/lib/uaccess_with_memcpy.c 2014-11-15 06:28:07.000000000 -0600
++++ linux-3.12.33-rpi/arch/arm/lib/uaccess_with_memcpy.c 2014-12-03 19:13:32.432418001 -0600
+@@ -21,6 +21,14 @@
+ #include <asm/current.h>
+ #include <asm/page.h>
+
++#ifndef COPY_FROM_USER_THRESHOLD
++#define COPY_FROM_USER_THRESHOLD 64
++#endif
++
++#ifndef COPY_TO_USER_THRESHOLD
++#define COPY_TO_USER_THRESHOLD 64
++#endif
++
+ static int
+ pin_page_for_write(const void __user *_addr, pte_t **ptep, spinlock_t **ptlp)
+ {
+@@ -56,7 +64,44 @@
+ return 1;
+ }
+
+-static unsigned long noinline
++static int
++pin_page_for_read(const void __user *_addr, pte_t **ptep, spinlock_t **ptlp)
++{
++ unsigned long addr = (unsigned long)_addr;
++ pgd_t *pgd;
++ pmd_t *pmd;
++ pte_t *pte;
++ pud_t *pud;
++ spinlock_t *ptl;
++
++ pgd = pgd_offset(current->mm, addr);
++ if (unlikely(pgd_none(*pgd) || pgd_bad(*pgd)))
++ {
++ return 0;
++ }
++ pud = pud_offset(pgd, addr);
++ if (unlikely(pud_none(*pud) || pud_bad(*pud)))
++ {
++ return 0;
++ }
++
++ pmd = pmd_offset(pud, addr);
++ if (unlikely(pmd_none(*pmd) || pmd_bad(*pmd)))
++ return 0;
++
++ pte = pte_offset_map_lock(current->mm, pmd, addr, &ptl);
++ if (unlikely(!pte_present(*pte) || !pte_young(*pte))) {
++ pte_unmap_unlock(pte, ptl);
++ return 0;
++ }
++
++ *ptep = pte;
++ *ptlp = ptl;
++
++ return 1;
++}
++
++unsigned long noinline
+ __copy_to_user_memcpy(void __user *to, const void *from, unsigned long n)
+ {
+ int atomic;
+@@ -103,6 +148,54 @@
+ return n;
+ }
+
++unsigned long noinline
++__copy_from_user_memcpy(void *to, const void __user *from, unsigned long n)
++{
++ int atomic;
++
++ if (unlikely(segment_eq(get_fs(), KERNEL_DS))) {
++ memcpy(to, (const void *)from, n);
++ return 0;
++ }
++
++ /* the mmap semaphore is taken only if not in an atomic context */
++ atomic = in_atomic();
++
++ if (!atomic)
++ down_read(&current->mm->mmap_sem);
++ while (n) {
++ pte_t *pte;
++ spinlock_t *ptl;
++ int tocopy;
++
++ while (!pin_page_for_read(from, &pte, &ptl)) {
++ char temp;
++ if (!atomic)
++ up_read(&current->mm->mmap_sem);
++ if (__get_user(temp, (char __user *)from))
++ goto out;
++ if (!atomic)
++ down_read(&current->mm->mmap_sem);
++ }
++
++ tocopy = (~(unsigned long)from & ~PAGE_MASK) + 1;
++ if (tocopy > n)
++ tocopy = n;
++
++ memcpy(to, (const void *)from, tocopy);
++ to += tocopy;
++ from += tocopy;
++ n -= tocopy;
++
++ pte_unmap_unlock(pte, ptl);
++ }
++ if (!atomic)
++ up_read(&current->mm->mmap_sem);
++
++out:
++ return n;
++}
++
+ unsigned long
+ __copy_to_user(void __user *to, const void *from, unsigned long n)
+ {
+@@ -113,10 +206,25 @@
+ * With frame pointer disabled, tail call optimization kicks in
+ * as well making this test almost invisible.
+ */
+- if (n < 64)
++ if (n < COPY_TO_USER_THRESHOLD)
+ return __copy_to_user_std(to, from, n);
+ return __copy_to_user_memcpy(to, from, n);
+ }
++
++unsigned long
++__copy_from_user(void *to, const void __user *from, unsigned long n)
++{
++ /*
++ * This test is stubbed out of the main function above to keep
++ * the overhead for small copies low by avoiding a large
++ * register dump on the stack just to reload them right away.
++ * With frame pointer disabled, tail call optimization kicks in
++ * as well making this test almost invisible.
++ */
++ if (n < COPY_FROM_USER_THRESHOLD)
++ return __copy_from_user_std(to, from, n);
++ return __copy_from_user_memcpy(to, from, n);
++}
+
+ static unsigned long noinline
+ __clear_user_memset(void __user *addr, unsigned long n)
+diff -Nur linux-3.12.33/arch/arm/mach-bcm2708/armctrl.c linux-3.12.33-rpi/arch/arm/mach-bcm2708/armctrl.c
+--- linux-3.12.33/arch/arm/mach-bcm2708/armctrl.c 1969-12-31 18:00:00.000000000 -0600
++++ linux-3.12.33-rpi/arch/arm/mach-bcm2708/armctrl.c 2014-12-03 19:13:32.448418001 -0600
@@ -0,0 +1,219 @@
+/*
+ * linux/arch/arm/mach-bcm2708/armctrl.c
@@ -2698,7 +4070,7 @@ diff -Nur linux-3.12.26.orig/arch/arm/mach-bcm2708/armctrl.c linux-3.12.26/arch/
+
+static struct irq_chip armctrl_chip = {
+ .name = "ARMCTRL",
-+ .irq_ack = armctrl_mask_irq,
++ .irq_ack = NULL,
+ .irq_mask = armctrl_mask_irq,
+ .irq_unmask = armctrl_unmask_irq,
+ .irq_set_wake = armctrl_set_wake,
@@ -2731,9 +4103,9 @@ diff -Nur linux-3.12.26.orig/arch/arm/mach-bcm2708/armctrl.c linux-3.12.26/arch/
+ init_FIQ(FIQ_START);
+ return 0;
+}
-diff -Nur linux-3.12.26.orig/arch/arm/mach-bcm2708/armctrl.h linux-3.12.26/arch/arm/mach-bcm2708/armctrl.h
---- linux-3.12.26.orig/arch/arm/mach-bcm2708/armctrl.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-3.12.26/arch/arm/mach-bcm2708/armctrl.h 2014-08-06 16:50:13.821957030 +0200
+diff -Nur linux-3.12.33/arch/arm/mach-bcm2708/armctrl.h linux-3.12.33-rpi/arch/arm/mach-bcm2708/armctrl.h
+--- linux-3.12.33/arch/arm/mach-bcm2708/armctrl.h 1969-12-31 18:00:00.000000000 -0600
++++ linux-3.12.33-rpi/arch/arm/mach-bcm2708/armctrl.h 2014-12-03 19:13:32.448418001 -0600
@@ -0,0 +1,27 @@
+/*
+ * linux/arch/arm/mach-bcm2708/armctrl.h
@@ -2762,10 +4134,10 @@ diff -Nur linux-3.12.26.orig/arch/arm/mach-bcm2708/armctrl.h linux-3.12.26/arch/
+ u32 armctrl_sources, u32 resume_sources);
+
+#endif
-diff -Nur linux-3.12.26.orig/arch/arm/mach-bcm2708/bcm2708.c linux-3.12.26/arch/arm/mach-bcm2708/bcm2708.c
---- linux-3.12.26.orig/arch/arm/mach-bcm2708/bcm2708.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-3.12.26/arch/arm/mach-bcm2708/bcm2708.c 2014-08-06 16:50:13.821957030 +0200
-@@ -0,0 +1,1017 @@
+diff -Nur linux-3.12.33/arch/arm/mach-bcm2708/bcm2708.c linux-3.12.33-rpi/arch/arm/mach-bcm2708/bcm2708.c
+--- linux-3.12.33/arch/arm/mach-bcm2708/bcm2708.c 1969-12-31 18:00:00.000000000 -0600
++++ linux-3.12.33-rpi/arch/arm/mach-bcm2708/bcm2708.c 2014-12-03 19:13:32.448418001 -0600
+@@ -0,0 +1,1139 @@
+/*
+ * linux/arch/arm/mach-bcm2708/bcm2708.c
+ *
@@ -2801,6 +4173,7 @@ diff -Nur linux-3.12.26.orig/arch/arm/mach-bcm2708/bcm2708.c linux-3.12.26/arch/
+#include <linux/module.h>
+#include <linux/spi/spi.h>
+#include <linux/w1-gpio.h>
++#include <linux/pps-gpio.h>
+
+#include <linux/version.h>
+#include <linux/clkdev.h>
@@ -2847,6 +4220,8 @@ diff -Nur linux-3.12.26.orig/arch/arm/mach-bcm2708/bcm2708.c linux-3.12.26/arch/
+
+// use GPIO 4 for the one-wire GPIO pin, if enabled
+#define W1_GPIO 4
++// ensure one-wire GPIO pullup is disabled by default
++#define W1_PULLUP -1
+
+/* command line parameters */
+static unsigned boardrev, serial;
@@ -2855,6 +4230,10 @@ diff -Nur linux-3.12.26.orig/arch/arm/mach-bcm2708/bcm2708.c linux-3.12.26/arch/
+static unsigned disk_led_active_low = 1;
+static unsigned reboot_part = 0;
+static unsigned w1_gpio_pin = W1_GPIO;
++static unsigned w1_gpio_pullup = W1_PULLUP;
++static int pps_gpio_pin = -1;
++static unsigned bcm2835_mmc = 1;
++static bool vc_i2c_override = false;
+
+static void __init bcm2708_init_led(void);
+
@@ -3034,6 +4413,7 @@ diff -Nur linux-3.12.26.orig/arch/arm/mach-bcm2708/bcm2708.c linux-3.12.26/arch/
+#if defined(CONFIG_W1_MASTER_GPIO) || defined(CONFIG_W1_MASTER_GPIO_MODULE)
+static struct w1_gpio_platform_data w1_gpio_pdata = {
+ .pin = W1_GPIO,
++ .ext_pullup_enable_pin = W1_PULLUP,
+ .is_open_drain = 0,
+};
+
@@ -3044,6 +4424,19 @@ diff -Nur linux-3.12.26.orig/arch/arm/mach-bcm2708/bcm2708.c linux-3.12.26/arch/
+};
+#endif
+
++static struct pps_gpio_platform_data pps_gpio_info = {
++ .assert_falling_edge = false,
++ .capture_clear = false,
++ .gpio_pin = -1,
++ .gpio_label = "PPS",
++};
++
++static struct platform_device pps_gpio_device = {
++ .name = "pps-gpio",
++ .id = PLATFORM_DEVID_NONE,
++ .dev.platform_data = &pps_gpio_info,
++};
++
+static u64 fb_dmamask = DMA_BIT_MASK(DMA_MASK_BITS_COMMON);
+
+static struct platform_device bcm2708_fb_device = {
@@ -3094,6 +4487,11 @@ diff -Nur linux-3.12.26.orig/arch/arm/mach-bcm2708/bcm2708.c linux-3.12.26/arch/
+ .end = IRQ_HOSTPORT,
+ .flags = IORESOURCE_IRQ,
+ },
++ [3] = {
++ .start = IRQ_USB,
++ .end = IRQ_USB,
++ .flags = IORESOURCE_IRQ,
++ },
+};
+
+
@@ -3211,6 +4609,34 @@ diff -Nur linux-3.12.26.orig/arch/arm/mach-bcm2708/bcm2708.c linux-3.12.26/arch/
+};
+#endif /* CONFIG_MMC_SDHCI_BCM2708 */
+
++#ifdef CONFIG_MMC_BCM2835 /* Arasan emmc SD (new) */
++static struct resource bcm2835_emmc_resources[] = {
++ [0] = {
++ .start = EMMC_BASE,
++ .end = EMMC_BASE + SZ_256 - 1, /* we only need this area */
++ /* the memory map actually makes SZ_4K available */
++ .flags = IORESOURCE_MEM,
++ },
++ [1] = {
++ .start = IRQ_ARASANSDIO,
++ .end = IRQ_ARASANSDIO,
++ .flags = IORESOURCE_IRQ,
++ },
++};
++
++static u64 bcm2835_emmc_dmamask = 0xffffffffUL;
++
++struct platform_device bcm2835_emmc_device = {
++ .name = "mmc-bcm2835",
++ .id = 0,
++ .num_resources = ARRAY_SIZE(bcm2835_emmc_resources),
++ .resource = bcm2835_emmc_resources,
++ .dev = {
++ .dma_mask = &bcm2835_emmc_dmamask,
++ .coherent_dma_mask = 0xffffffffUL},
++};
++#endif /* CONFIG_MMC_BCM2835 */
++
+static struct resource bcm2708_powerman_resources[] = {
+ [0] = {
+ .start = PM_BASE,
@@ -3410,6 +4836,20 @@ diff -Nur linux-3.12.26.orig/arch/arm/mach-bcm2708/bcm2708.c linux-3.12.26/arch/
+};
+#endif
+
++#if defined(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DACPLUS) || defined(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DACPLUS_MODULE)
++static struct platform_device snd_rpi_hifiberry_dacplus_device = {
++ .name = "snd-rpi-hifiberry-dacplus",
++ .id = 0,
++ .num_resources = 0,
++};
++
++static struct i2c_board_info __initdata snd_pcm512x_hbdacplus_i2c_devices[] = {
++ {
++ I2C_BOARD_INFO("pcm5122", 0x4d)
++ },
++};
++#endif
++
+#if defined(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DIGI) || defined(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DIGI_MODULE)
+static struct platform_device snd_hifiberry_digi_device = {
+ .name = "snd-hifiberry-digi",
@@ -3425,6 +4865,20 @@ diff -Nur linux-3.12.26.orig/arch/arm/mach-bcm2708/bcm2708.c linux-3.12.26/arch/
+
+#endif
+
++#if defined(CONFIG_SND_BCM2708_SOC_HIFIBERRY_AMP) || defined(CONFIG_SND_BCM2708_SOC_HIFIBERRY_AMP_MODULE)
++static struct platform_device snd_hifiberry_amp_device = {
++ .name = "snd-hifiberry-amp",
++ .id = 0,
++ .num_resources = 0,
++};
++
++static struct i2c_board_info __initdata snd_tas5713_i2c_devices[] = {
++ {
++ I2C_BOARD_INFO("tas5713", 0x1b)
++ },
++};
++#endif
++
+#if defined(CONFIG_SND_BCM2708_SOC_RPI_DAC) || defined(CONFIG_SND_BCM2708_SOC_RPI_DAC_MODULE)
+static struct platform_device snd_rpi_dac_device = {
+ .name = "snd-rpi-dac",
@@ -3552,9 +5006,16 @@ diff -Nur linux-3.12.26.orig/arch/arm/mach-bcm2708/bcm2708.c linux-3.12.26/arch/
+ bcm_register_device(&bcm2708_vcio_device);
+#ifdef CONFIG_BCM2708_GPIO
+ bcm_register_device(&bcm2708_gpio_device);
++ if (pps_gpio_pin >= 0) {
++ pr_info("bcm2708: GPIO %d setup as pps-gpio device\n", pps_gpio_pin);
++ pps_gpio_info.gpio_pin = pps_gpio_pin;
++ pps_gpio_device.id = pps_gpio_pin;
++ bcm_register_device(&pps_gpio_device);
++ }
+#endif
+#if defined(CONFIG_W1_MASTER_GPIO) || defined(CONFIG_W1_MASTER_GPIO_MODULE)
+ w1_gpio_pdata.pin = w1_gpio_pin;
++ w1_gpio_pdata.ext_pullup_enable_pin = w1_gpio_pullup;
+ platform_device_register(&w1_device);
+#endif
+ bcm_register_device(&bcm2708_systemtimer_device);
@@ -3564,15 +5025,27 @@ diff -Nur linux-3.12.26.orig/arch/arm/mach-bcm2708/bcm2708.c linux-3.12.26/arch/
+ bcm_register_device(&bcm2708_powerman_device);
+
+#ifdef CONFIG_MMC_SDHCI_BCM2708
-+ bcm_register_device(&bcm2708_emmc_device);
++ if (!bcm2835_mmc)
++ bcm_register_device(&bcm2708_emmc_device);
++#endif
++#ifdef CONFIG_MMC_BCM2835
++ if (bcm2835_mmc)
++ bcm_register_device(&bcm2835_emmc_device);
+#endif
+ bcm2708_init_led();
+ for (i = 0; i < ARRAY_SIZE(bcm2708_alsa_devices); i++)
+ bcm_register_device(&bcm2708_alsa_devices[i]);
+
+ bcm_register_device(&bcm2708_spi_device);
-+ bcm_register_device(&bcm2708_bsc0_device);
-+ bcm_register_device(&bcm2708_bsc1_device);
++
++ if (vc_i2c_override) {
++ bcm_register_device(&bcm2708_bsc0_device);
++ bcm_register_device(&bcm2708_bsc1_device);
++ } else if ((boardrev & 0xffffff) == 0x2 || (boardrev & 0xffffff) == 0x3) {
++ bcm_register_device(&bcm2708_bsc0_device);
++ } else {
++ bcm_register_device(&bcm2708_bsc1_device);
++ }
+
+ bcm_register_device(&bcm2835_hwmon_device);
+ bcm_register_device(&bcm2835_thermal_device);
@@ -3586,11 +5059,22 @@ diff -Nur linux-3.12.26.orig/arch/arm/mach-bcm2708/bcm2708.c linux-3.12.26/arch/
+ bcm_register_device(&snd_pcm5102a_codec_device);
+#endif
+
++#if defined(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DACPLUS) || defined(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DACPLUS_MODULE)
++ bcm_register_device(&snd_rpi_hifiberry_dacplus_device);
++ i2c_register_board_info(1, snd_pcm512x_hbdacplus_i2c_devices, ARRAY_SIZE(snd_pcm512x_hbdacplus_i2c_devices));
++#endif
++
+#if defined(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DIGI) || defined(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DIGI_MODULE)
+ bcm_register_device(&snd_hifiberry_digi_device);
+ i2c_register_board_info(1, snd_wm8804_i2c_devices, ARRAY_SIZE(snd_wm8804_i2c_devices));
+#endif
+
++#if defined(CONFIG_SND_BCM2708_SOC_HIFIBERRY_AMP) || defined(CONFIG_SND_BCM2708_SOC_HIFIBERRY_AMP_MODULE)
++ bcm_register_device(&snd_hifiberry_amp_device);
++ i2c_register_board_info(1, snd_tas5713_i2c_devices, ARRAY_SIZE(snd_tas5713_i2c_devices));
++#endif
++
++
+#if defined(CONFIG_SND_BCM2708_SOC_RPI_DAC) || defined(CONFIG_SND_BCM2708_SOC_RPI_DAC_MODULE)
+ bcm_register_device(&snd_rpi_dac_device);
+ bcm_register_device(&snd_pcm1794a_codec_device);
@@ -3639,9 +5123,13 @@ diff -Nur linux-3.12.26.orig/arch/arm/mach-bcm2708/bcm2708.c linux-3.12.26/arch/
+ struct clock_event_device *unused)
+{
+ unsigned long stc;
-+
-+ stc = readl(__io_address(ST_BASE + 0x04));
-+ writel(stc + cycles, __io_address(ST_BASE + 0x18)); /* stc3 */
++ do {
++ stc = readl(__io_address(ST_BASE + 0x04));
++ /* We could take a FIQ here, which may push ST above STC3 */
++ writel(stc + cycles, __io_address(ST_BASE + 0x18));
++ } while ((signed long) cycles >= 0 &&
++ (signed long) (readl(__io_address(ST_BASE + 0x04)) - stc)
++ >= (signed long) cycles);
+ return 0;
+}
+
@@ -3783,10 +5271,16 @@ diff -Nur linux-3.12.26.orig/arch/arm/mach-bcm2708/bcm2708.c linux-3.12.26/arch/
+module_param(disk_led_active_low, uint, 0644);
+module_param(reboot_part, uint, 0644);
+module_param(w1_gpio_pin, uint, 0644);
-diff -Nur linux-3.12.26.orig/arch/arm/mach-bcm2708/bcm2708_gpio.c linux-3.12.26/arch/arm/mach-bcm2708/bcm2708_gpio.c
---- linux-3.12.26.orig/arch/arm/mach-bcm2708/bcm2708_gpio.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-3.12.26/arch/arm/mach-bcm2708/bcm2708_gpio.c 2014-08-06 16:50:13.821957030 +0200
-@@ -0,0 +1,361 @@
++module_param(w1_gpio_pullup, uint, 0644);
++module_param(pps_gpio_pin, int, 0644);
++MODULE_PARM_DESC(pps_gpio_pin, "Set GPIO pin to reserve for PPS");
++module_param(bcm2835_mmc, uint, 0644);
++module_param(vc_i2c_override, bool, 0644);
++MODULE_PARM_DESC(vc_i2c_override, "Allow the use of VC's I2C peripheral.");
+diff -Nur linux-3.12.33/arch/arm/mach-bcm2708/bcm2708_gpio.c linux-3.12.33-rpi/arch/arm/mach-bcm2708/bcm2708_gpio.c
+--- linux-3.12.33/arch/arm/mach-bcm2708/bcm2708_gpio.c 1969-12-31 18:00:00.000000000 -0600
++++ linux-3.12.33-rpi/arch/arm/mach-bcm2708/bcm2708_gpio.c 2014-12-03 19:13:32.448418001 -0600
+@@ -0,0 +1,401 @@
+/*
+ * linux/arch/arm/mach-bcm2708/bcm2708_gpio.c
+ *
@@ -3800,6 +5294,7 @@ diff -Nur linux-3.12.26.orig/arch/arm/mach-bcm2708/bcm2708_gpio.c linux-3.12.26/
+
+#include <linux/spinlock.h>
+#include <linux/module.h>
++#include <linux/delay.h>
+#include <linux/list.h>
+#include <linux/io.h>
+#include <linux/irq.h>
@@ -3810,6 +5305,8 @@ diff -Nur linux-3.12.26.orig/arch/arm/mach-bcm2708/bcm2708_gpio.c linux-3.12.26/
+#include <linux/platform_device.h>
+#include <mach/platform.h>
+
++#include <linux/platform_data/bcm2708.h>
++
+#define BCM_GPIO_DRIVER_NAME "bcm2708_gpio"
+#define DRIVER_NAME BCM_GPIO_DRIVER_NAME
+#define BCM_GPIO_USE_IRQ 1
@@ -3845,10 +5342,10 @@ diff -Nur linux-3.12.26.orig/arch/arm/mach-bcm2708/bcm2708_gpio.c linux-3.12.26/
+ struct list_head list;
+ void __iomem *base;
+ struct gpio_chip gc;
-+ unsigned long rising;
-+ unsigned long falling;
-+ unsigned long high;
-+ unsigned long low;
++ unsigned long rising[(BCM2708_NR_GPIOS + 31) / 32];
++ unsigned long falling[(BCM2708_NR_GPIOS + 31) / 32];
++ unsigned long high[(BCM2708_NR_GPIOS + 31) / 32];
++ unsigned long low[(BCM2708_NR_GPIOS + 31) / 32];
+};
+
+static int bcm2708_set_function(struct gpio_chip *gc, unsigned offset,
@@ -3920,6 +5417,41 @@ diff -Nur linux-3.12.26.orig/arch/arm/mach-bcm2708/bcm2708_gpio.c linux-3.12.26/
+ writel(1 << gpio_field_offset, gpio->base + GPIOCLR(gpio_bank));
+}
+
++/**********************
++ * extension to configure pullups
++ */
++int bcm2708_gpio_setpull(struct gpio_chip *gc, unsigned offset,
++ bcm2708_gpio_pull_t value)
++{
++ struct bcm2708_gpio *gpio = container_of(gc, struct bcm2708_gpio, gc);
++ unsigned gpio_bank = offset / 32;
++ unsigned gpio_field_offset = (offset - 32 * gpio_bank);
++
++ if (offset >= BCM2708_NR_GPIOS)
++ return -EINVAL;
++
++ switch (value) {
++ case BCM2708_PULL_UP:
++ writel(2, gpio->base + GPIOUD(0));
++ break;
++ case BCM2708_PULL_DOWN:
++ writel(1, gpio->base + GPIOUD(0));
++ break;
++ case BCM2708_PULL_OFF:
++ writel(0, gpio->base + GPIOUD(0));
++ break;
++ }
++
++ udelay(5);
++ writel(1 << gpio_field_offset, gpio->base + GPIOUDCLK(gpio_bank));
++ udelay(5);
++ writel(0, gpio->base + GPIOUD(0));
++ writel(0 << gpio_field_offset, gpio->base + GPIOUDCLK(gpio_bank));
++
++ return 0;
++}
++EXPORT_SYMBOL(bcm2708_gpio_setpull);
++
+/*************************************************************************************************************************
+ * bcm2708 GPIO IRQ
+ */
@@ -3935,23 +5467,26 @@ diff -Nur linux-3.12.26.orig/arch/arm/mach-bcm2708/bcm2708_gpio.c linux-3.12.26/
+{
+ unsigned irq = d->irq;
+ struct bcm2708_gpio *gpio = irq_get_chip_data(irq);
++ unsigned gn = irq_to_gpio(irq);
++ unsigned gb = gn / 32;
++ unsigned go = gn % 32;
+
-+ 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));
++ gpio->rising[gb] &= ~(1 << go);
++ gpio->falling[gb] &= ~(1 << go);
++ gpio->high[gb] &= ~(1 << go);
++ gpio->low[gb] &= ~(1 << go);
+
+ 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)
-+ gpio->rising |= (1 << irq_to_gpio(irq));
++ gpio->rising[gb] |= (1 << go);
+ if (type & IRQ_TYPE_EDGE_FALLING)
-+ gpio->falling |= (1 << irq_to_gpio(irq));
++ gpio->falling[gb] |= (1 << go);
+ if (type & IRQ_TYPE_LEVEL_HIGH)
-+ gpio->high |= (1 << irq_to_gpio(irq));
++ gpio->high[gb] |= (1 << go);
+ if (type & IRQ_TYPE_LEVEL_LOW)
-+ gpio->low |= (1 << irq_to_gpio(irq));
++ gpio->low[gb] |= (1 << go);
+ return 0;
+}
+
@@ -3980,37 +5515,36 @@ diff -Nur linux-3.12.26.orig/arch/arm/mach-bcm2708/bcm2708_gpio.c linux-3.12.26/
+ struct bcm2708_gpio *gpio = irq_get_chip_data(irq);
+ unsigned gn = irq_to_gpio(irq);
+ unsigned gb = gn / 32;
++ unsigned go = gn % 32;
+ 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));
++ writel(1 << go, gpio->base + GPIOEDS(gb));
+
-+ if (gpio->rising & (1 << gn)) {
-+ writel(rising | (1 << gn), gpio->base + GPIOREN(gb));
++ if (gpio->rising[gb] & (1 << go)) {
++ writel(rising | (1 << go), gpio->base + GPIOREN(gb));
+ } else {
-+ writel(rising & ~(1 << gn), gpio->base + GPIOREN(gb));
++ writel(rising & ~(1 << go), gpio->base + GPIOREN(gb));
+ }
+
-+ if (gpio->falling & (1 << gn)) {
-+ writel(falling | (1 << gn), gpio->base + GPIOFEN(gb));
++ if (gpio->falling[gb] & (1 << go)) {
++ writel(falling | (1 << go), gpio->base + GPIOFEN(gb));
+ } else {
-+ writel(falling & ~(1 << gn), gpio->base + GPIOFEN(gb));
++ writel(falling & ~(1 << go), gpio->base + GPIOFEN(gb));
+ }
+
-+ if (gpio->high & (1 << gn)) {
-+ writel(high | (1 << gn), gpio->base + GPIOHEN(gb));
++ if (gpio->high[gb] & (1 << go)) {
++ writel(high | (1 << go), gpio->base + GPIOHEN(gb));
+ } else {
-+ writel(high & ~(1 << gn), gpio->base + GPIOHEN(gb));
++ writel(high & ~(1 << go), gpio->base + GPIOHEN(gb));
+ }
+
-+ if (gpio->low & (1 << gn)) {
-+ writel(low | (1 << gn), gpio->base + GPIOLEN(gb));
++ if (gpio->low[gb] & (1 << go)) {
++ writel(low | (1 << go), gpio->base + GPIOLEN(gb));
+ } else {
-+ writel(low & ~(1 << gn), gpio->base + GPIOLEN(gb));
++ writel(low & ~(1 << go), gpio->base + GPIOLEN(gb));
+ }
+}
+
@@ -4148,9 +5682,9 @@ diff -Nur linux-3.12.26.orig/arch/arm/mach-bcm2708/bcm2708_gpio.c linux-3.12.26/
+
+MODULE_DESCRIPTION("Broadcom BCM2708 GPIO driver");
+MODULE_LICENSE("GPL");
-diff -Nur linux-3.12.26.orig/arch/arm/mach-bcm2708/bcm2708.h linux-3.12.26/arch/arm/mach-bcm2708/bcm2708.h
---- linux-3.12.26.orig/arch/arm/mach-bcm2708/bcm2708.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-3.12.26/arch/arm/mach-bcm2708/bcm2708.h 2014-08-06 16:50:13.821957030 +0200
+diff -Nur linux-3.12.33/arch/arm/mach-bcm2708/bcm2708.h linux-3.12.33-rpi/arch/arm/mach-bcm2708/bcm2708.h
+--- linux-3.12.33/arch/arm/mach-bcm2708/bcm2708.h 1969-12-31 18:00:00.000000000 -0600
++++ linux-3.12.33-rpi/arch/arm/mach-bcm2708/bcm2708.h 2014-12-03 19:13:32.448418001 -0600
@@ -0,0 +1,49 @@
+/*
+ * linux/arch/arm/mach-bcm2708/bcm2708.h
@@ -4201,9 +5735,9 @@ diff -Nur linux-3.12.26.orig/arch/arm/mach-bcm2708/bcm2708.h linux-3.12.26/arch/
+}
+
+#endif
-diff -Nur linux-3.12.26.orig/arch/arm/mach-bcm2708/clock.c linux-3.12.26/arch/arm/mach-bcm2708/clock.c
---- linux-3.12.26.orig/arch/arm/mach-bcm2708/clock.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-3.12.26/arch/arm/mach-bcm2708/clock.c 2014-08-06 16:50:13.821957030 +0200
+diff -Nur linux-3.12.33/arch/arm/mach-bcm2708/clock.c linux-3.12.33-rpi/arch/arm/mach-bcm2708/clock.c
+--- linux-3.12.33/arch/arm/mach-bcm2708/clock.c 1969-12-31 18:00:00.000000000 -0600
++++ linux-3.12.33-rpi/arch/arm/mach-bcm2708/clock.c 2014-12-03 19:13:32.448418001 -0600
@@ -0,0 +1,61 @@
+/*
+ * linux/arch/arm/mach-bcm2708/clock.c
@@ -4266,9 +5800,9 @@ diff -Nur linux-3.12.26.orig/arch/arm/mach-bcm2708/clock.c linux-3.12.26/arch/ar
+ return -EIO;
+}
+EXPORT_SYMBOL(clk_set_rate);
-diff -Nur linux-3.12.26.orig/arch/arm/mach-bcm2708/clock.h linux-3.12.26/arch/arm/mach-bcm2708/clock.h
---- linux-3.12.26.orig/arch/arm/mach-bcm2708/clock.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-3.12.26/arch/arm/mach-bcm2708/clock.h 2014-08-06 16:50:13.821957030 +0200
+diff -Nur linux-3.12.33/arch/arm/mach-bcm2708/clock.h linux-3.12.33-rpi/arch/arm/mach-bcm2708/clock.h
+--- linux-3.12.33/arch/arm/mach-bcm2708/clock.h 1969-12-31 18:00:00.000000000 -0600
++++ linux-3.12.33-rpi/arch/arm/mach-bcm2708/clock.h 2014-12-03 19:13:32.448418001 -0600
@@ -0,0 +1,24 @@
+/*
+ * linux/arch/arm/mach-bcm2708/clock.h
@@ -4294,10 +5828,10 @@ diff -Nur linux-3.12.26.orig/arch/arm/mach-bcm2708/clock.h linux-3.12.26/arch/ar
+struct clk {
+ unsigned long rate;
+};
-diff -Nur linux-3.12.26.orig/arch/arm/mach-bcm2708/dma.c linux-3.12.26/arch/arm/mach-bcm2708/dma.c
---- linux-3.12.26.orig/arch/arm/mach-bcm2708/dma.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-3.12.26/arch/arm/mach-bcm2708/dma.c 2014-08-06 16:50:13.821957030 +0200
-@@ -0,0 +1,407 @@
+diff -Nur linux-3.12.33/arch/arm/mach-bcm2708/dma.c linux-3.12.33-rpi/arch/arm/mach-bcm2708/dma.c
+--- linux-3.12.33/arch/arm/mach-bcm2708/dma.c 1969-12-31 18:00:00.000000000 -0600
++++ linux-3.12.33-rpi/arch/arm/mach-bcm2708/dma.c 2014-12-03 19:13:32.448418001 -0600
+@@ -0,0 +1,409 @@
+/*
+ * linux/arch/arm/mach-bcm2708/dma.c
+ *
@@ -4456,6 +5990,8 @@ diff -Nur linux-3.12.26.orig/arch/arm/mach-bcm2708/dma.c linux-3.12.26/arch/arm/
+ dmaman->chan_available = chans_available;
+ dmaman->has_feature[BCM_DMA_FEATURE_FAST_ORD] = 0x0c; /* chans 2 & 3 */
+ dmaman->has_feature[BCM_DMA_FEATURE_BULK_ORD] = 0x01; /* chan 0 */
++ dmaman->has_feature[BCM_DMA_FEATURE_NORMAL_ORD] = 0xfe; /* chans 1 to 7 */
++ dmaman->has_feature[BCM_DMA_FEATURE_LITE_ORD] = 0x7f00; /* chans 8 to 14 */
+}
+
+static int vc_dmaman_chan_alloc(struct vc_dmaman *dmaman,
@@ -4705,9 +6241,9 @@ diff -Nur linux-3.12.26.orig/arch/arm/mach-bcm2708/dma.c linux-3.12.26/arch/arm/
+MODULE_LICENSE("GPL");
+
+MODULE_PARM_DESC(dmachans, "Bitmap of DMA channels available to the ARM");
-diff -Nur linux-3.12.26.orig/arch/arm/mach-bcm2708/include/mach/arm_control.h linux-3.12.26/arch/arm/mach-bcm2708/include/mach/arm_control.h
---- linux-3.12.26.orig/arch/arm/mach-bcm2708/include/mach/arm_control.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-3.12.26/arch/arm/mach-bcm2708/include/mach/arm_control.h 2014-08-06 16:50:13.825957062 +0200
+diff -Nur linux-3.12.33/arch/arm/mach-bcm2708/include/mach/arm_control.h linux-3.12.33-rpi/arch/arm/mach-bcm2708/include/mach/arm_control.h
+--- linux-3.12.33/arch/arm/mach-bcm2708/include/mach/arm_control.h 1969-12-31 18:00:00.000000000 -0600
++++ linux-3.12.33-rpi/arch/arm/mach-bcm2708/include/mach/arm_control.h 2014-12-03 19:13:32.448418001 -0600
@@ -0,0 +1,419 @@
+/*
+ * linux/arch/arm/mach-bcm2708/arm_control.h
@@ -5128,10 +6664,10 @@ diff -Nur linux-3.12.26.orig/arch/arm/mach-bcm2708/include/mach/arm_control.h li
+#define AJBTDO HW_REGISTER_RW(AJB_BASE+0x0c)
+
+#endif
-diff -Nur linux-3.12.26.orig/arch/arm/mach-bcm2708/include/mach/arm_power.h linux-3.12.26/arch/arm/mach-bcm2708/include/mach/arm_power.h
---- linux-3.12.26.orig/arch/arm/mach-bcm2708/include/mach/arm_power.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-3.12.26/arch/arm/mach-bcm2708/include/mach/arm_power.h 2014-08-06 16:50:13.825957062 +0200
-@@ -0,0 +1,60 @@
+diff -Nur linux-3.12.33/arch/arm/mach-bcm2708/include/mach/arm_power.h linux-3.12.33-rpi/arch/arm/mach-bcm2708/include/mach/arm_power.h
+--- linux-3.12.33/arch/arm/mach-bcm2708/include/mach/arm_power.h 1969-12-31 18:00:00.000000000 -0600
++++ linux-3.12.33-rpi/arch/arm/mach-bcm2708/include/mach/arm_power.h 2014-12-03 19:13:32.448418001 -0600
+@@ -0,0 +1,62 @@
+/*
+ * linux/arch/arm/mach-bcm2708/include/mach/arm_power.h
+ *
@@ -5172,6 +6708,7 @@ diff -Nur linux-3.12.26.orig/arch/arm/mach-bcm2708/include/mach/arm_power.h linu
+ PREFIX(POWER_I2C2_BIT),
+ PREFIX(POWER_SPI_BIT),
+ PREFIX(POWER_CCP2TX_BIT),
++ PREFIX(POWER_DSI_BIT),
+
+ PREFIX(POWER_MAX)
+};
@@ -5186,15 +6723,16 @@ diff -Nur linux-3.12.26.orig/arch/arm/mach-bcm2708/include/mach/arm_power.h linu
+ PREFIX(POWER_I2C2_MASK) = (1 << PREFIX(POWER_I2C2_BIT)),
+ PREFIX(POWER_SPI_MASK) = (1 << PREFIX(POWER_SPI_BIT)),
+ PREFIX(POWER_CCP2TX_MASK) = (1 << PREFIX(POWER_CCP2TX_BIT)),
++ PREFIX(POWER_DSI) = (1 << PREFIX(POWER_DSI_BIT)),
+
+ PREFIX(POWER_MASK) = (1 << PREFIX(POWER_MAX)) - 1,
+ PREFIX(POWER_NONE) = 0
+};
+
+#endif
-diff -Nur linux-3.12.26.orig/arch/arm/mach-bcm2708/include/mach/clkdev.h linux-3.12.26/arch/arm/mach-bcm2708/include/mach/clkdev.h
---- linux-3.12.26.orig/arch/arm/mach-bcm2708/include/mach/clkdev.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-3.12.26/arch/arm/mach-bcm2708/include/mach/clkdev.h 2014-08-06 16:50:13.825957062 +0200
+diff -Nur linux-3.12.33/arch/arm/mach-bcm2708/include/mach/clkdev.h linux-3.12.33-rpi/arch/arm/mach-bcm2708/include/mach/clkdev.h
+--- linux-3.12.33/arch/arm/mach-bcm2708/include/mach/clkdev.h 1969-12-31 18:00:00.000000000 -0600
++++ linux-3.12.33-rpi/arch/arm/mach-bcm2708/include/mach/clkdev.h 2014-12-03 19:13:32.448418001 -0600
@@ -0,0 +1,7 @@
+#ifndef __ASM_MACH_CLKDEV_H
+#define __ASM_MACH_CLKDEV_H
@@ -5203,9 +6741,9 @@ diff -Nur linux-3.12.26.orig/arch/arm/mach-bcm2708/include/mach/clkdev.h linux-3
+#define __clk_put(clk) do { } while (0)
+
+#endif
-diff -Nur linux-3.12.26.orig/arch/arm/mach-bcm2708/include/mach/debug-macro.S linux-3.12.26/arch/arm/mach-bcm2708/include/mach/debug-macro.S
---- linux-3.12.26.orig/arch/arm/mach-bcm2708/include/mach/debug-macro.S 1970-01-01 01:00:00.000000000 +0100
-+++ linux-3.12.26/arch/arm/mach-bcm2708/include/mach/debug-macro.S 2014-08-06 16:50:13.825957062 +0200
+diff -Nur linux-3.12.33/arch/arm/mach-bcm2708/include/mach/debug-macro.S linux-3.12.33-rpi/arch/arm/mach-bcm2708/include/mach/debug-macro.S
+--- linux-3.12.33/arch/arm/mach-bcm2708/include/mach/debug-macro.S 1969-12-31 18:00:00.000000000 -0600
++++ linux-3.12.33-rpi/arch/arm/mach-bcm2708/include/mach/debug-macro.S 2014-12-03 19:13:32.448418001 -0600
@@ -0,0 +1,22 @@
+/* arch/arm/mach-bcm2708/include/mach/debug-macro.S
+ *
@@ -5229,10 +6767,10 @@ diff -Nur linux-3.12.26.orig/arch/arm/mach-bcm2708/include/mach/debug-macro.S li
+ .endm
+
+#include <debug/pl01x.S>
-diff -Nur linux-3.12.26.orig/arch/arm/mach-bcm2708/include/mach/dma.h linux-3.12.26/arch/arm/mach-bcm2708/include/mach/dma.h
---- linux-3.12.26.orig/arch/arm/mach-bcm2708/include/mach/dma.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-3.12.26/arch/arm/mach-bcm2708/include/mach/dma.h 2014-08-06 16:50:13.825957062 +0200
-@@ -0,0 +1,90 @@
+diff -Nur linux-3.12.33/arch/arm/mach-bcm2708/include/mach/dma.h linux-3.12.33-rpi/arch/arm/mach-bcm2708/include/mach/dma.h
+--- linux-3.12.33/arch/arm/mach-bcm2708/include/mach/dma.h 1969-12-31 18:00:00.000000000 -0600
++++ linux-3.12.33-rpi/arch/arm/mach-bcm2708/include/mach/dma.h 2014-12-03 19:13:32.448418001 -0600
+@@ -0,0 +1,94 @@
+/*
+ * linux/arch/arm/mach-bcm2708/include/mach/dma.h
+ *
@@ -5312,9 +6850,13 @@ diff -Nur linux-3.12.26.orig/arch/arm/mach-bcm2708/include/mach/dma.h linux-3.12
+ those with higher priority smaller ordinal numbers */
+#define BCM_DMA_FEATURE_FAST_ORD 0
+#define BCM_DMA_FEATURE_BULK_ORD 1
++#define BCM_DMA_FEATURE_NORMAL_ORD 2
++#define BCM_DMA_FEATURE_LITE_ORD 3
+#define BCM_DMA_FEATURE_FAST (1<<BCM_DMA_FEATURE_FAST_ORD)
+#define BCM_DMA_FEATURE_BULK (1<<BCM_DMA_FEATURE_BULK_ORD)
-+#define BCM_DMA_FEATURE_COUNT 2
++#define BCM_DMA_FEATURE_NORMAL (1<<BCM_DMA_FEATURE_NORMAL_ORD)
++#define BCM_DMA_FEATURE_LITE (1<<BCM_DMA_FEATURE_LITE_ORD)
++#define BCM_DMA_FEATURE_COUNT 4
+
+/* return channel no or -ve error */
+extern int bcm_dma_chan_alloc(unsigned preferred_feature_set,
@@ -5323,9 +6865,9 @@ diff -Nur linux-3.12.26.orig/arch/arm/mach-bcm2708/include/mach/dma.h linux-3.12
+
+
+#endif /* _MACH_BCM2708_DMA_H */
-diff -Nur linux-3.12.26.orig/arch/arm/mach-bcm2708/include/mach/entry-macro.S linux-3.12.26/arch/arm/mach-bcm2708/include/mach/entry-macro.S
---- linux-3.12.26.orig/arch/arm/mach-bcm2708/include/mach/entry-macro.S 1970-01-01 01:00:00.000000000 +0100
-+++ linux-3.12.26/arch/arm/mach-bcm2708/include/mach/entry-macro.S 2014-08-06 16:50:13.829957093 +0200
+diff -Nur linux-3.12.33/arch/arm/mach-bcm2708/include/mach/entry-macro.S linux-3.12.33-rpi/arch/arm/mach-bcm2708/include/mach/entry-macro.S
+--- linux-3.12.33/arch/arm/mach-bcm2708/include/mach/entry-macro.S 1969-12-31 18:00:00.000000000 -0600
++++ linux-3.12.33-rpi/arch/arm/mach-bcm2708/include/mach/entry-macro.S 2014-12-03 19:13:32.448418001 -0600
@@ -0,0 +1,69 @@
+/*
+ * arch/arm/mach-bcm2708/include/mach/entry-macro.S
@@ -5396,9 +6938,9 @@ diff -Nur linux-3.12.26.orig/arch/arm/mach-bcm2708/include/mach/entry-macro.S li
+1020: @ EQ will be set if no irqs pending
+
+ .endm
-diff -Nur linux-3.12.26.orig/arch/arm/mach-bcm2708/include/mach/frc.h linux-3.12.26/arch/arm/mach-bcm2708/include/mach/frc.h
---- linux-3.12.26.orig/arch/arm/mach-bcm2708/include/mach/frc.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-3.12.26/arch/arm/mach-bcm2708/include/mach/frc.h 2014-08-06 16:50:13.829957093 +0200
+diff -Nur linux-3.12.33/arch/arm/mach-bcm2708/include/mach/frc.h linux-3.12.33-rpi/arch/arm/mach-bcm2708/include/mach/frc.h
+--- linux-3.12.33/arch/arm/mach-bcm2708/include/mach/frc.h 1969-12-31 18:00:00.000000000 -0600
++++ linux-3.12.33-rpi/arch/arm/mach-bcm2708/include/mach/frc.h 2014-12-03 19:13:32.448418001 -0600
@@ -0,0 +1,38 @@
+/*
+ * arch/arm/mach-bcm2708/include/mach/timex.h
@@ -5438,9 +6980,9 @@ diff -Nur linux-3.12.26.orig/arch/arm/mach-bcm2708/include/mach/frc.h linux-3.12
+extern unsigned long long frc_clock_ticks63(void);
+
+#endif
-diff -Nur linux-3.12.26.orig/arch/arm/mach-bcm2708/include/mach/gpio.h linux-3.12.26/arch/arm/mach-bcm2708/include/mach/gpio.h
---- linux-3.12.26.orig/arch/arm/mach-bcm2708/include/mach/gpio.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-3.12.26/arch/arm/mach-bcm2708/include/mach/gpio.h 2014-08-06 16:50:13.829957093 +0200
+diff -Nur linux-3.12.33/arch/arm/mach-bcm2708/include/mach/gpio.h linux-3.12.33-rpi/arch/arm/mach-bcm2708/include/mach/gpio.h
+--- linux-3.12.33/arch/arm/mach-bcm2708/include/mach/gpio.h 1969-12-31 18:00:00.000000000 -0600
++++ linux-3.12.33-rpi/arch/arm/mach-bcm2708/include/mach/gpio.h 2014-12-03 19:13:32.448418001 -0600
@@ -0,0 +1,17 @@
+/*
+ * arch/arm/mach-bcm2708/include/mach/gpio.h
@@ -5459,9 +7001,9 @@ diff -Nur linux-3.12.26.orig/arch/arm/mach-bcm2708/include/mach/gpio.h linux-3.1
+#define irq_to_gpio(x) ((x) - GPIO_IRQ_START)
+
+#endif
-diff -Nur linux-3.12.26.orig/arch/arm/mach-bcm2708/include/mach/hardware.h linux-3.12.26/arch/arm/mach-bcm2708/include/mach/hardware.h
---- linux-3.12.26.orig/arch/arm/mach-bcm2708/include/mach/hardware.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-3.12.26/arch/arm/mach-bcm2708/include/mach/hardware.h 2014-08-06 16:50:13.857957313 +0200
+diff -Nur linux-3.12.33/arch/arm/mach-bcm2708/include/mach/hardware.h linux-3.12.33-rpi/arch/arm/mach-bcm2708/include/mach/hardware.h
+--- linux-3.12.33/arch/arm/mach-bcm2708/include/mach/hardware.h 1969-12-31 18:00:00.000000000 -0600
++++ linux-3.12.33-rpi/arch/arm/mach-bcm2708/include/mach/hardware.h 2014-12-03 19:13:32.448418001 -0600
@@ -0,0 +1,28 @@
+/*
+ * arch/arm/mach-bcm2708/include/mach/hardware.h
@@ -5491,9 +7033,9 @@ diff -Nur linux-3.12.26.orig/arch/arm/mach-bcm2708/include/mach/hardware.h linux
+#include <mach/platform.h>
+
+#endif
-diff -Nur linux-3.12.26.orig/arch/arm/mach-bcm2708/include/mach/io.h linux-3.12.26/arch/arm/mach-bcm2708/include/mach/io.h
---- linux-3.12.26.orig/arch/arm/mach-bcm2708/include/mach/io.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-3.12.26/arch/arm/mach-bcm2708/include/mach/io.h 2014-08-06 16:50:13.865957376 +0200
+diff -Nur linux-3.12.33/arch/arm/mach-bcm2708/include/mach/io.h linux-3.12.33-rpi/arch/arm/mach-bcm2708/include/mach/io.h
+--- linux-3.12.33/arch/arm/mach-bcm2708/include/mach/io.h 1969-12-31 18:00:00.000000000 -0600
++++ linux-3.12.33-rpi/arch/arm/mach-bcm2708/include/mach/io.h 2014-12-03 19:13:32.448418001 -0600
@@ -0,0 +1,27 @@
+/*
+ * arch/arm/mach-bcm2708/include/mach/io.h
@@ -5522,10 +7064,10 @@ diff -Nur linux-3.12.26.orig/arch/arm/mach-bcm2708/include/mach/io.h linux-3.12.
+#define __io(a) __typesafe_io(a)
+
+#endif
-diff -Nur linux-3.12.26.orig/arch/arm/mach-bcm2708/include/mach/irqs.h linux-3.12.26/arch/arm/mach-bcm2708/include/mach/irqs.h
---- linux-3.12.26.orig/arch/arm/mach-bcm2708/include/mach/irqs.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-3.12.26/arch/arm/mach-bcm2708/include/mach/irqs.h 2014-08-06 16:50:13.865957376 +0200
-@@ -0,0 +1,200 @@
+diff -Nur linux-3.12.33/arch/arm/mach-bcm2708/include/mach/irqs.h linux-3.12.33-rpi/arch/arm/mach-bcm2708/include/mach/irqs.h
+--- linux-3.12.33/arch/arm/mach-bcm2708/include/mach/irqs.h 1969-12-31 18:00:00.000000000 -0600
++++ linux-3.12.33-rpi/arch/arm/mach-bcm2708/include/mach/irqs.h 2014-12-03 19:13:32.448418001 -0600
+@@ -0,0 +1,197 @@
+/*
+ * arch/arm/mach-bcm2708/include/mach/irqs.h
+ *
@@ -5715,20 +7257,17 @@ diff -Nur linux-3.12.26.orig/arch/arm/mach-bcm2708/include/mach/irqs.h linux-3.1
+#define FIQ_PENDING1 (FIQ_START+INTERRUPT_PENDING1)
+#define FIQ_PENDING2 (FIQ_START+INTERRUPT_PENDING2)
+
-+#define GPIO_IRQ_START (HARD_IRQS + FIQ_IRQS)
-+
+#define HARD_IRQS (64 + 21)
-+#define FIQ_IRQS (64 + 21)
++#define FIQ_IRQS (64 + 21)
++#define GPIO_IRQ_START (HARD_IRQS + FIQ_IRQS)
+#define GPIO_IRQS (32*5)
-+#define SPARE_IRQS (64)
-+
-+#define NR_IRQS HARD_IRQS+FIQ_IRQS+GPIO_IRQS+SPARE_IRQS
-+
++#define SPARE_IRQS (64)
++#define NR_IRQS (HARD_IRQS+FIQ_IRQS+GPIO_IRQS+SPARE_IRQS)
+
+#endif /* _BCM2708_IRQS_H_ */
-diff -Nur linux-3.12.26.orig/arch/arm/mach-bcm2708/include/mach/memory.h linux-3.12.26/arch/arm/mach-bcm2708/include/mach/memory.h
---- linux-3.12.26.orig/arch/arm/mach-bcm2708/include/mach/memory.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-3.12.26/arch/arm/mach-bcm2708/include/mach/memory.h 2014-08-06 16:50:13.869957407 +0200
+diff -Nur linux-3.12.33/arch/arm/mach-bcm2708/include/mach/memory.h linux-3.12.33-rpi/arch/arm/mach-bcm2708/include/mach/memory.h
+--- linux-3.12.33/arch/arm/mach-bcm2708/include/mach/memory.h 1969-12-31 18:00:00.000000000 -0600
++++ linux-3.12.33-rpi/arch/arm/mach-bcm2708/include/mach/memory.h 2014-12-03 19:13:32.448418001 -0600
@@ -0,0 +1,57 @@
+/*
+ * arch/arm/mach-bcm2708/include/mach/memory.h
@@ -5787,9 +7326,9 @@ diff -Nur linux-3.12.26.orig/arch/arm/mach-bcm2708/include/mach/memory.h linux-3
+#define __bus_to_pfn(x) __phys_to_pfn((x) - (BUS_OFFSET - PLAT_PHYS_OFFSET))
+
+#endif
-diff -Nur linux-3.12.26.orig/arch/arm/mach-bcm2708/include/mach/platform.h linux-3.12.26/arch/arm/mach-bcm2708/include/mach/platform.h
---- linux-3.12.26.orig/arch/arm/mach-bcm2708/include/mach/platform.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-3.12.26/arch/arm/mach-bcm2708/include/mach/platform.h 2014-08-06 16:50:13.869957407 +0200
+diff -Nur linux-3.12.33/arch/arm/mach-bcm2708/include/mach/platform.h linux-3.12.33-rpi/arch/arm/mach-bcm2708/include/mach/platform.h
+--- linux-3.12.33/arch/arm/mach-bcm2708/include/mach/platform.h 1969-12-31 18:00:00.000000000 -0600
++++ linux-3.12.33-rpi/arch/arm/mach-bcm2708/include/mach/platform.h 2014-12-03 19:13:32.448418001 -0600
@@ -0,0 +1,228 @@
+/*
+ * arch/arm/mach-bcm2708/include/mach/platform.h
@@ -6019,9 +7558,9 @@ diff -Nur linux-3.12.26.orig/arch/arm/mach-bcm2708/include/mach/platform.h linux
+#endif
+
+/* END */
-diff -Nur linux-3.12.26.orig/arch/arm/mach-bcm2708/include/mach/power.h linux-3.12.26/arch/arm/mach-bcm2708/include/mach/power.h
---- linux-3.12.26.orig/arch/arm/mach-bcm2708/include/mach/power.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-3.12.26/arch/arm/mach-bcm2708/include/mach/power.h 2014-08-06 16:50:13.869957407 +0200
+diff -Nur linux-3.12.33/arch/arm/mach-bcm2708/include/mach/power.h linux-3.12.33-rpi/arch/arm/mach-bcm2708/include/mach/power.h
+--- linux-3.12.33/arch/arm/mach-bcm2708/include/mach/power.h 1969-12-31 18:00:00.000000000 -0600
++++ linux-3.12.33-rpi/arch/arm/mach-bcm2708/include/mach/power.h 2014-12-03 19:13:32.448418001 -0600
@@ -0,0 +1,26 @@
+/*
+ * linux/arch/arm/mach-bcm2708/power.h
@@ -6049,9 +7588,9 @@ diff -Nur linux-3.12.26.orig/arch/arm/mach-bcm2708/include/mach/power.h linux-3.
+extern int bcm_power_close(BCM_POWER_HANDLE_T handle);
+
+#endif
-diff -Nur linux-3.12.26.orig/arch/arm/mach-bcm2708/include/mach/system.h linux-3.12.26/arch/arm/mach-bcm2708/include/mach/system.h
---- linux-3.12.26.orig/arch/arm/mach-bcm2708/include/mach/system.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-3.12.26/arch/arm/mach-bcm2708/include/mach/system.h 2014-08-06 16:50:13.869957407 +0200
+diff -Nur linux-3.12.33/arch/arm/mach-bcm2708/include/mach/system.h linux-3.12.33-rpi/arch/arm/mach-bcm2708/include/mach/system.h
+--- linux-3.12.33/arch/arm/mach-bcm2708/include/mach/system.h 1969-12-31 18:00:00.000000000 -0600
++++ linux-3.12.33-rpi/arch/arm/mach-bcm2708/include/mach/system.h 2014-12-03 19:13:32.448418001 -0600
@@ -0,0 +1,38 @@
+/*
+ * arch/arm/mach-bcm2708/include/mach/system.h
@@ -6091,9 +7630,9 @@ diff -Nur linux-3.12.26.orig/arch/arm/mach-bcm2708/include/mach/system.h linux-3
+}
+
+#endif
-diff -Nur linux-3.12.26.orig/arch/arm/mach-bcm2708/include/mach/timex.h linux-3.12.26/arch/arm/mach-bcm2708/include/mach/timex.h
---- linux-3.12.26.orig/arch/arm/mach-bcm2708/include/mach/timex.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-3.12.26/arch/arm/mach-bcm2708/include/mach/timex.h 2014-08-06 16:50:13.873957439 +0200
+diff -Nur linux-3.12.33/arch/arm/mach-bcm2708/include/mach/timex.h linux-3.12.33-rpi/arch/arm/mach-bcm2708/include/mach/timex.h
+--- linux-3.12.33/arch/arm/mach-bcm2708/include/mach/timex.h 1969-12-31 18:00:00.000000000 -0600
++++ linux-3.12.33-rpi/arch/arm/mach-bcm2708/include/mach/timex.h 2014-12-03 19:13:32.448418001 -0600
@@ -0,0 +1,23 @@
+/*
+ * arch/arm/mach-bcm2708/include/mach/timex.h
@@ -6118,9 +7657,9 @@ diff -Nur linux-3.12.26.orig/arch/arm/mach-bcm2708/include/mach/timex.h linux-3.
+ */
+
+#define CLOCK_TICK_RATE (1000000)
-diff -Nur linux-3.12.26.orig/arch/arm/mach-bcm2708/include/mach/uncompress.h linux-3.12.26/arch/arm/mach-bcm2708/include/mach/uncompress.h
---- linux-3.12.26.orig/arch/arm/mach-bcm2708/include/mach/uncompress.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-3.12.26/arch/arm/mach-bcm2708/include/mach/uncompress.h 2014-08-06 16:50:13.873957439 +0200
+diff -Nur linux-3.12.33/arch/arm/mach-bcm2708/include/mach/uncompress.h linux-3.12.33-rpi/arch/arm/mach-bcm2708/include/mach/uncompress.h
+--- linux-3.12.33/arch/arm/mach-bcm2708/include/mach/uncompress.h 1969-12-31 18:00:00.000000000 -0600
++++ linux-3.12.33-rpi/arch/arm/mach-bcm2708/include/mach/uncompress.h 2014-12-03 19:13:32.448418001 -0600
@@ -0,0 +1,84 @@
+/*
+ * arch/arm/mach-bcn2708/include/mach/uncompress.h
@@ -6206,10 +7745,10 @@ diff -Nur linux-3.12.26.orig/arch/arm/mach-bcm2708/include/mach/uncompress.h lin
+ * nothing to do
+ */
+#define arch_decomp_wdog()
-diff -Nur linux-3.12.26.orig/arch/arm/mach-bcm2708/include/mach/vcio.h linux-3.12.26/arch/arm/mach-bcm2708/include/mach/vcio.h
---- linux-3.12.26.orig/arch/arm/mach-bcm2708/include/mach/vcio.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-3.12.26/arch/arm/mach-bcm2708/include/mach/vcio.h 2014-08-06 16:50:13.873957439 +0200
-@@ -0,0 +1,141 @@
+diff -Nur linux-3.12.33/arch/arm/mach-bcm2708/include/mach/vcio.h linux-3.12.33-rpi/arch/arm/mach-bcm2708/include/mach/vcio.h
+--- linux-3.12.33/arch/arm/mach-bcm2708/include/mach/vcio.h 1969-12-31 18:00:00.000000000 -0600
++++ linux-3.12.33-rpi/arch/arm/mach-bcm2708/include/mach/vcio.h 2014-12-03 19:13:32.448418001 -0600
+@@ -0,0 +1,165 @@
+/*
+ * arch/arm/mach-bcm2708/include/mach/vcio.h
+ *
@@ -6245,17 +7784,24 @@ diff -Nur linux-3.12.26.orig/arch/arm/mach-bcm2708/include/mach/vcio.h linux-3.1
+#define MBOX_CHAN_PROPERTY 8 /* for use by the property channel */
+#define MBOX_CHAN_COUNT 9
+
++enum {
++ VCMSG_PROCESS_REQUEST = 0x00000000
++};
++enum {
++ VCMSG_REQUEST_SUCCESSFUL = 0x80000000,
++ VCMSG_REQUEST_FAILED = 0x80000001
++};
+/* Mailbox property tags */
+enum {
+ VCMSG_PROPERTY_END = 0x00000000,
+ VCMSG_GET_FIRMWARE_REVISION = 0x00000001,
+ VCMSG_GET_BOARD_MODEL = 0x00010001,
-+ VCMSG_GET_BOARD_REVISION = 0x00020002,
-+ VCMSG_GET_BOARD_MAC_ADDRESS = 0x00020003,
-+ VCMSG_GET_BOARD_SERIAL = 0x00020004,
-+ VCMSG_GET_ARM_MEMORY = 0x00020005,
-+ VCMSG_GET_VC_MEMORY = 0x00020006,
-+ VCMSG_GET_CLOCKS = 0x00020007,
++ VCMSG_GET_BOARD_REVISION = 0x00010002,
++ VCMSG_GET_BOARD_MAC_ADDRESS = 0x00010003,
++ VCMSG_GET_BOARD_SERIAL = 0x00010004,
++ VCMSG_GET_ARM_MEMORY = 0x00010005,
++ VCMSG_GET_VC_MEMORY = 0x00010006,
++ VCMSG_GET_CLOCKS = 0x00010007,
+ VCMSG_GET_COMMAND_LINE = 0x00050001,
+ VCMSG_GET_DMA_CHANNELS = 0x00060001,
+ VCMSG_GET_POWER_STATE = 0x00020001,
@@ -6273,7 +7819,20 @@ diff -Nur linux-3.12.26.orig/arch/arm/mach-bcm2708/include/mach/vcio.h linux-3.1
+ VCMSG_GET_MIN_CLOCK = 0x00030007,
+ VCMSG_GET_MIN_VOLTAGE = 0x00030008,
+ VCMSG_GET_TURBO = 0x00030009,
++ VCMSG_GET_MAX_TEMPERATURE = 0x0003000a,
++ VCMSG_GET_STC = 0x0003000b,
+ VCMSG_SET_TURBO = 0x00038009,
++ VCMSG_SET_ALLOCATE_MEM = 0x0003000c,
++ VCMSG_SET_LOCK_MEM = 0x0003000d,
++ VCMSG_SET_UNLOCK_MEM = 0x0003000e,
++ VCMSG_SET_RELEASE_MEM = 0x0003000f,
++ VCMSG_SET_EXECUTE_CODE = 0x00030010,
++ VCMSG_SET_EXECUTE_QPU = 0x00030011,
++ VCMSG_SET_ENABLE_QPU = 0x00030012,
++ VCMSG_GET_RESOURCE_HANDLE = 0x00030014,
++ VCMSG_GET_EDID_BLOCK = 0x00030020,
++ VCMSG_GET_CUSTOMER_OTP = 0x00030021,
++ VCMSG_SET_CUSTOMER_OTP = 0x00038021,
+ VCMSG_SET_ALLOCATE_BUFFER = 0x00040001,
+ VCMSG_SET_RELEASE_BUFFER = 0x00048001,
+ VCMSG_SET_BLANK_SCREEN = 0x00040002,
@@ -6311,6 +7870,10 @@ diff -Nur linux-3.12.26.orig/arch/arm/mach-bcm2708/include/mach/vcio.h linux-3.1
+ VCMSG_GET_TRANSFORM = 0x0004000d,
+ VCMSG_TST_TRANSFORM = 0x0004400d,
+ VCMSG_SET_TRANSFORM = 0x0004800d,
++ VCMSG_TST_VSYNC = 0x0004400e,
++ VCMSG_SET_VSYNC = 0x0004800e,
++ VCMSG_SET_CURSOR_INFO = 0x00008010,
++ VCMSG_SET_CURSOR_STATE = 0x00008011,
+};
+
+extern int /*rc*/ bcm_mailbox_read(unsigned chan, uint32_t *data28);
@@ -6348,12 +7911,12 @@ diff -Nur linux-3.12.26.orig/arch/arm/mach-bcm2708/include/mach/vcio.h linux-3.1
+/*
+ * The name of the device file
+ */
-+#define DEVICE_FILE_NAME "char_dev"
++#define DEVICE_FILE_NAME "vcio"
+
+#endif
-diff -Nur linux-3.12.26.orig/arch/arm/mach-bcm2708/include/mach/vc_mem.h linux-3.12.26/arch/arm/mach-bcm2708/include/mach/vc_mem.h
---- linux-3.12.26.orig/arch/arm/mach-bcm2708/include/mach/vc_mem.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-3.12.26/arch/arm/mach-bcm2708/include/mach/vc_mem.h 2014-08-06 16:50:13.873957439 +0200
+diff -Nur linux-3.12.33/arch/arm/mach-bcm2708/include/mach/vc_mem.h linux-3.12.33-rpi/arch/arm/mach-bcm2708/include/mach/vc_mem.h
+--- linux-3.12.33/arch/arm/mach-bcm2708/include/mach/vc_mem.h 1969-12-31 18:00:00.000000000 -0600
++++ linux-3.12.33-rpi/arch/arm/mach-bcm2708/include/mach/vc_mem.h 2014-12-03 19:13:32.448418001 -0600
@@ -0,0 +1,35 @@
+/*****************************************************************************
+* Copyright 2010 - 2011 Broadcom Corporation. All rights reserved.
@@ -6390,9 +7953,339 @@ diff -Nur linux-3.12.26.orig/arch/arm/mach-bcm2708/include/mach/vc_mem.h linux-3
+#endif
+
+#endif /* VC_MEM_H */
-diff -Nur linux-3.12.26.orig/arch/arm/mach-bcm2708/include/mach/vmalloc.h linux-3.12.26/arch/arm/mach-bcm2708/include/mach/vmalloc.h
---- linux-3.12.26.orig/arch/arm/mach-bcm2708/include/mach/vmalloc.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-3.12.26/arch/arm/mach-bcm2708/include/mach/vmalloc.h 2014-08-06 16:50:13.893957595 +0200
+diff -Nur linux-3.12.33/arch/arm/mach-bcm2708/include/mach/vc_sm_defs.h linux-3.12.33-rpi/arch/arm/mach-bcm2708/include/mach/vc_sm_defs.h
+--- linux-3.12.33/arch/arm/mach-bcm2708/include/mach/vc_sm_defs.h 1969-12-31 18:00:00.000000000 -0600
++++ linux-3.12.33-rpi/arch/arm/mach-bcm2708/include/mach/vc_sm_defs.h 2014-12-03 19:13:32.448418001 -0600
+@@ -0,0 +1,181 @@
++/*****************************************************************************
++* Copyright 2011 Broadcom Corporation. All rights reserved.
++*
++* Unless you and Broadcom execute a separate written software license
++* agreement governing use of this software, this software is licensed to you
++* under the terms of the GNU General Public License version 2, available at
++* http://www.broadcom.com/licenses/GPLv2.php (the "GPL").
++*
++* Notwithstanding the above, under no circumstances may you combine this
++* software in any way with any other Broadcom software provided under a
++* license other than the GPL, without Broadcom's express prior written
++* consent.
++*****************************************************************************/
++
++#ifndef __VC_SM_DEFS_H__INCLUDED__
++#define __VC_SM_DEFS_H__INCLUDED__
++
++/* FourCC code used for VCHI connection */
++#define VC_SM_SERVER_NAME MAKE_FOURCC("SMEM")
++
++/* Maximum message length */
++#define VC_SM_MAX_MSG_LEN (sizeof(VC_SM_MSG_UNION_T) + \
++ sizeof(VC_SM_MSG_HDR_T))
++#define VC_SM_MAX_RSP_LEN (sizeof(VC_SM_MSG_UNION_T))
++
++/* Resource name maximum size */
++#define VC_SM_RESOURCE_NAME 32
++
++/* All message types supported for HOST->VC direction */
++typedef enum {
++ /* Allocate shared memory block */
++ VC_SM_MSG_TYPE_ALLOC,
++ /* Lock allocated shared memory block */
++ VC_SM_MSG_TYPE_LOCK,
++ /* Unlock allocated shared memory block */
++ VC_SM_MSG_TYPE_UNLOCK,
++ /* Unlock allocated shared memory block, do not answer command */
++ VC_SM_MSG_TYPE_UNLOCK_NOANS,
++ /* Free shared memory block */
++ VC_SM_MSG_TYPE_FREE,
++ /* Resize a shared memory block */
++ VC_SM_MSG_TYPE_RESIZE,
++ /* Walk the allocated shared memory block(s) */
++ VC_SM_MSG_TYPE_WALK_ALLOC,
++
++ /* A previously applied action will need to be reverted */
++ VC_SM_MSG_TYPE_ACTION_CLEAN,
++ VC_SM_MSG_TYPE_MAX
++} VC_SM_MSG_TYPE;
++
++/* Type of memory to be allocated */
++typedef enum {
++ VC_SM_ALLOC_CACHED,
++ VC_SM_ALLOC_NON_CACHED,
++
++} VC_SM_ALLOC_TYPE_T;
++
++/* Message header for all messages in HOST->VC direction */
++typedef struct {
++ int32_t type;
++ uint32_t trans_id;
++ uint8_t body[0];
++
++} VC_SM_MSG_HDR_T;
++
++/* Request to allocate memory (HOST->VC) */
++typedef struct {
++ /* type of memory to allocate */
++ VC_SM_ALLOC_TYPE_T type;
++ /* byte amount of data to allocate per unit */
++ uint32_t base_unit;
++ /* number of unit to allocate */
++ uint32_t num_unit;
++ /* alignement to be applied on allocation */
++ uint32_t alignement;
++ /* identity of who allocated this block */
++ uint32_t allocator;
++ /* resource name (for easier tracking on vc side) */
++ char name[VC_SM_RESOURCE_NAME];
++
++} VC_SM_ALLOC_T;
++
++/* Result of a requested memory allocation (VC->HOST) */
++typedef struct {
++ /* Transaction identifier */
++ uint32_t trans_id;
++
++ /* Resource handle */
++ uint32_t res_handle;
++ /* Pointer to resource buffer */
++ void *res_mem;
++ /* Resource base size (bytes) */
++ uint32_t res_base_size;
++ /* Resource number */
++ uint32_t res_num;
++
++} VC_SM_ALLOC_RESULT_T;
++
++/* Request to free a previously allocated memory (HOST->VC) */
++typedef struct {
++ /* Resource handle (returned from alloc) */
++ uint32_t res_handle;
++ /* Resource buffer (returned from alloc) */
++ void *res_mem;
++
++} VC_SM_FREE_T;
++
++/* Request to lock a previously allocated memory (HOST->VC) */
++typedef struct {
++ /* Resource handle (returned from alloc) */
++ uint32_t res_handle;
++ /* Resource buffer (returned from alloc) */
++ void *res_mem;
++
++} VC_SM_LOCK_UNLOCK_T;
++
++/* Request to resize a previously allocated memory (HOST->VC) */
++typedef struct {
++ /* Resource handle (returned from alloc) */
++ uint32_t res_handle;
++ /* Resource buffer (returned from alloc) */
++ void *res_mem;
++ /* Resource *new* size requested (bytes) */
++ uint32_t res_new_size;
++
++} VC_SM_RESIZE_T;
++
++/* Result of a requested memory lock (VC->HOST) */
++typedef struct {
++ /* Transaction identifier */
++ uint32_t trans_id;
++
++ /* Resource handle */
++ uint32_t res_handle;
++ /* Pointer to resource buffer */
++ void *res_mem;
++ /* Pointer to former resource buffer if the memory
++ * was reallocated */
++ void *res_old_mem;
++
++} VC_SM_LOCK_RESULT_T;
++
++/* Generic result for a request (VC->HOST) */
++typedef struct {
++ /* Transaction identifier */
++ uint32_t trans_id;
++
++ int32_t success;
++
++} VC_SM_RESULT_T;
++
++/* Request to revert a previously applied action (HOST->VC) */
++typedef struct {
++ /* Action of interest */
++ VC_SM_MSG_TYPE res_action;
++ /* Transaction identifier for the action of interest */
++ uint32_t action_trans_id;
++
++} VC_SM_ACTION_CLEAN_T;
++
++/* Request to remove all data associated with a given allocator (HOST->VC) */
++typedef struct {
++ /* Allocator identifier */
++ uint32_t allocator;
++
++} VC_SM_FREE_ALL_T;
++
++/* Union of ALL messages */
++typedef union {
++ VC_SM_ALLOC_T alloc;
++ VC_SM_ALLOC_RESULT_T alloc_result;
++ VC_SM_FREE_T free;
++ VC_SM_ACTION_CLEAN_T action_clean;
++ VC_SM_RESIZE_T resize;
++ VC_SM_LOCK_RESULT_T lock_result;
++ VC_SM_RESULT_T result;
++ VC_SM_FREE_ALL_T free_all;
++
++} VC_SM_MSG_UNION_T;
++
++#endif /* __VC_SM_DEFS_H__INCLUDED__ */
+diff -Nur linux-3.12.33/arch/arm/mach-bcm2708/include/mach/vc_sm_knl.h linux-3.12.33-rpi/arch/arm/mach-bcm2708/include/mach/vc_sm_knl.h
+--- linux-3.12.33/arch/arm/mach-bcm2708/include/mach/vc_sm_knl.h 1969-12-31 18:00:00.000000000 -0600
++++ linux-3.12.33-rpi/arch/arm/mach-bcm2708/include/mach/vc_sm_knl.h 2014-12-03 19:13:32.448418001 -0600
+@@ -0,0 +1,55 @@
++/*****************************************************************************
++* Copyright 2011 Broadcom Corporation. All rights reserved.
++*
++* Unless you and Broadcom execute a separate written software license
++* agreement governing use of this software, this software is licensed to you
++* under the terms of the GNU General Public License version 2, available at
++* http://www.broadcom.com/licenses/GPLv2.php (the "GPL").
++*
++* Notwithstanding the above, under no circumstances may you combine this
++* software in any way with any other Broadcom software provided under a
++* license other than the GPL, without Broadcom's express prior written
++* consent.
++*****************************************************************************/
++
++#ifndef __VC_SM_KNL_H__INCLUDED__
++#define __VC_SM_KNL_H__INCLUDED__
++
++#if !defined(__KERNEL__)
++#error "This interface is for kernel use only..."
++#endif
++
++/* Type of memory to be locked (ie mapped) */
++typedef enum {
++ VC_SM_LOCK_CACHED,
++ VC_SM_LOCK_NON_CACHED,
++
++} VC_SM_LOCK_CACHE_MODE_T;
++
++/* Allocate a shared memory handle and block.
++*/
++int vc_sm_alloc(VC_SM_ALLOC_T *alloc, int *handle);
++
++/* Free a previously allocated shared memory handle and block.
++*/
++int vc_sm_free(int handle);
++
++/* Lock a memory handle for use by kernel.
++*/
++int vc_sm_lock(int handle, VC_SM_LOCK_CACHE_MODE_T mode,
++ long unsigned int *data);
++
++/* Unlock a memory handle in use by kernel.
++*/
++int vc_sm_unlock(int handle, int flush, int no_vc_unlock);
++
++/* Get an internal resource handle mapped from the external one.
++*/
++int vc_sm_int_handle(int handle);
++
++/* Map a shared memory region for use by kernel.
++*/
++int vc_sm_map(int handle, unsigned int sm_addr, VC_SM_LOCK_CACHE_MODE_T mode,
++ long unsigned int *data);
++
++#endif /* __VC_SM_KNL_H__INCLUDED__ */
+diff -Nur linux-3.12.33/arch/arm/mach-bcm2708/include/mach/vc_vchi_sm.h linux-3.12.33-rpi/arch/arm/mach-bcm2708/include/mach/vc_vchi_sm.h
+--- linux-3.12.33/arch/arm/mach-bcm2708/include/mach/vc_vchi_sm.h 1969-12-31 18:00:00.000000000 -0600
++++ linux-3.12.33-rpi/arch/arm/mach-bcm2708/include/mach/vc_vchi_sm.h 2014-12-03 19:13:32.448418001 -0600
+@@ -0,0 +1,82 @@
++/*****************************************************************************
++* Copyright 2011 Broadcom Corporation. All rights reserved.
++*
++* Unless you and Broadcom execute a separate written software license
++* agreement governing use of this software, this software is licensed to you
++* under the terms of the GNU General Public License version 2, available at
++* http://www.broadcom.com/licenses/GPLv2.php (the "GPL").
++*
++* Notwithstanding the above, under no circumstances may you combine this
++* software in any way with any other Broadcom software provided under a
++* license other than the GPL, without Broadcom's express prior written
++* consent.
++*****************************************************************************/
++
++#ifndef __VC_VCHI_SM_H__INCLUDED__
++#define __VC_VCHI_SM_H__INCLUDED__
++
++#include "interface/vchi/vchi.h"
++
++#include "vc_sm_defs.h"
++
++/* Forward declare.
++*/
++typedef struct sm_instance *VC_VCHI_SM_HANDLE_T;
++
++/* Initialize the shared memory service, opens up vchi connection to talk to it.
++*/
++VC_VCHI_SM_HANDLE_T vc_vchi_sm_init(VCHI_INSTANCE_T vchi_instance,
++ VCHI_CONNECTION_T **vchi_connections,
++ uint32_t num_connections);
++
++/* Terminates the shared memory service.
++*/
++int vc_vchi_sm_stop(VC_VCHI_SM_HANDLE_T *handle);
++
++/* Ask the shared memory service to allocate some memory on videocre and
++** return the result of this allocation (which upon success will be a pointer
++** to some memory in videocore space).
++*/
++int vc_vchi_sm_alloc(VC_VCHI_SM_HANDLE_T handle,
++ VC_SM_ALLOC_T *alloc,
++ VC_SM_ALLOC_RESULT_T *alloc_result, uint32_t *trans_id);
++
++/* Ask the shared memory service to free up some memory that was previously
++** allocated by the vc_vchi_sm_alloc function call.
++*/
++int vc_vchi_sm_free(VC_VCHI_SM_HANDLE_T handle,
++ VC_SM_FREE_T *free, uint32_t *trans_id);
++
++/* Ask the shared memory service to lock up some memory that was previously
++** allocated by the vc_vchi_sm_alloc function call.
++*/
++int vc_vchi_sm_lock(VC_VCHI_SM_HANDLE_T handle,
++ VC_SM_LOCK_UNLOCK_T *lock_unlock,
++ VC_SM_LOCK_RESULT_T *lock_result, uint32_t *trans_id);
++
++/* Ask the shared memory service to unlock some memory that was previously
++** allocated by the vc_vchi_sm_alloc function call.
++*/
++int vc_vchi_sm_unlock(VC_VCHI_SM_HANDLE_T handle,
++ VC_SM_LOCK_UNLOCK_T *lock_unlock,
++ uint32_t *trans_id, uint8_t wait_reply);
++
++/* Ask the shared memory service to resize some memory that was previously
++** allocated by the vc_vchi_sm_alloc function call.
++*/
++int vc_vchi_sm_resize(VC_VCHI_SM_HANDLE_T handle,
++ VC_SM_RESIZE_T *resize, uint32_t *trans_id);
++
++/* Walk the allocated resources on the videocore side, the allocation will
++** show up in the log. This is purely for debug/information and takes no
++** specific actions.
++*/
++int vc_vchi_sm_walk_alloc(VC_VCHI_SM_HANDLE_T handle);
++
++/* Clean up following a previously interrupted action which left the system
++** in a bad state of some sort.
++*/
++int vc_vchi_sm_clean_up(VC_VCHI_SM_HANDLE_T handle,
++ VC_SM_ACTION_CLEAN_T *action_clean);
++
++#endif /* __VC_VCHI_SM_H__INCLUDED__ */
+diff -Nur linux-3.12.33/arch/arm/mach-bcm2708/include/mach/vmalloc.h linux-3.12.33-rpi/arch/arm/mach-bcm2708/include/mach/vmalloc.h
+--- linux-3.12.33/arch/arm/mach-bcm2708/include/mach/vmalloc.h 1969-12-31 18:00:00.000000000 -0600
++++ linux-3.12.33-rpi/arch/arm/mach-bcm2708/include/mach/vmalloc.h 2014-12-03 19:13:32.448418001 -0600
@@ -0,0 +1,20 @@
+/*
+ * arch/arm/mach-bcm2708/include/mach/vmalloc.h
@@ -6414,9 +8307,246 @@ diff -Nur linux-3.12.26.orig/arch/arm/mach-bcm2708/include/mach/vmalloc.h linux-
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+#define VMALLOC_END (0xe8000000)
-diff -Nur linux-3.12.26.orig/arch/arm/mach-bcm2708/Kconfig linux-3.12.26/arch/arm/mach-bcm2708/Kconfig
---- linux-3.12.26.orig/arch/arm/mach-bcm2708/Kconfig 1970-01-01 01:00:00.000000000 +0100
-+++ linux-3.12.26/arch/arm/mach-bcm2708/Kconfig 2014-08-06 16:50:13.893957595 +0200
+diff -Nur linux-3.12.33/arch/arm/mach-bcm2708/include/mach/vmcs_sm_ioctl.h linux-3.12.33-rpi/arch/arm/mach-bcm2708/include/mach/vmcs_sm_ioctl.h
+--- linux-3.12.33/arch/arm/mach-bcm2708/include/mach/vmcs_sm_ioctl.h 1969-12-31 18:00:00.000000000 -0600
++++ linux-3.12.33-rpi/arch/arm/mach-bcm2708/include/mach/vmcs_sm_ioctl.h 2014-12-03 19:13:32.448418001 -0600
+@@ -0,0 +1,233 @@
++/*****************************************************************************
++* Copyright 2011 Broadcom Corporation. All rights reserved.
++*
++* Unless you and Broadcom execute a separate written software license
++* agreement governing use of this software, this software is licensed to you
++* under the terms of the GNU General Public License version 2, available at
++* http://www.broadcom.com/licenses/GPLv2.php (the "GPL").
++*
++* Notwithstanding the above, under no circumstances may you combine this
++* software in any way with any other Broadcom software provided under a
++* license other than the GPL, without Broadcom's express prior written
++* consent.
++*
++*****************************************************************************/
++
++#if !defined(__VMCS_SM_IOCTL_H__INCLUDED__)
++#define __VMCS_SM_IOCTL_H__INCLUDED__
++
++/* ---- Include Files ---------------------------------------------------- */
++
++#if defined(__KERNEL__)
++#include <linux/types.h> /* Needed for standard types */
++#else
++#include <stdint.h>
++#endif
++
++#include <linux/ioctl.h>
++
++/* ---- Constants and Types ---------------------------------------------- */
++
++#define VMCS_SM_RESOURCE_NAME 32
++#define VMCS_SM_RESOURCE_NAME_DEFAULT "sm-host-resource"
++
++/* Type define used to create unique IOCTL number */
++#define VMCS_SM_MAGIC_TYPE 'I'
++
++/* IOCTL commands */
++enum vmcs_sm_cmd_e {
++ VMCS_SM_CMD_ALLOC = 0x5A, /* Start at 0x5A arbitrarily */
++ VMCS_SM_CMD_ALLOC_SHARE,
++ VMCS_SM_CMD_LOCK,
++ VMCS_SM_CMD_LOCK_CACHE,
++ VMCS_SM_CMD_UNLOCK,
++ VMCS_SM_CMD_RESIZE,
++ VMCS_SM_CMD_UNMAP,
++ VMCS_SM_CMD_FREE,
++ VMCS_SM_CMD_FLUSH,
++ VMCS_SM_CMD_INVALID,
++
++ VMCS_SM_CMD_SIZE_USR_HANDLE,
++ VMCS_SM_CMD_CHK_USR_HANDLE,
++
++ VMCS_SM_CMD_MAPPED_USR_HANDLE,
++ VMCS_SM_CMD_MAPPED_USR_ADDRESS,
++ VMCS_SM_CMD_MAPPED_VC_HDL_FROM_ADDR,
++ VMCS_SM_CMD_MAPPED_VC_HDL_FROM_HDL,
++ VMCS_SM_CMD_MAPPED_VC_ADDR_FROM_HDL,
++
++ VMCS_SM_CMD_VC_WALK_ALLOC,
++ VMCS_SM_CMD_HOST_WALK_MAP,
++ VMCS_SM_CMD_HOST_WALK_PID_ALLOC,
++ VMCS_SM_CMD_HOST_WALK_PID_MAP,
++
++ VMCS_SM_CMD_LAST /* Do no delete */
++};
++
++/* Cache type supported, conveniently matches the user space definition in
++** user-vcsm.h.
++*/
++enum vmcs_sm_cache_e {
++ VMCS_SM_CACHE_NONE,
++ VMCS_SM_CACHE_HOST,
++ VMCS_SM_CACHE_VC,
++ VMCS_SM_CACHE_BOTH,
++};
++
++/* IOCTL Data structures */
++struct vmcs_sm_ioctl_alloc {
++ /* user -> kernel */
++ unsigned int size;
++ unsigned int num;
++ enum vmcs_sm_cache_e cached;
++ char name[VMCS_SM_RESOURCE_NAME];
++
++ /* kernel -> user */
++ unsigned int handle;
++ /* unsigned int base_addr; */
++};
++
++struct vmcs_sm_ioctl_alloc_share {
++ /* user -> kernel */
++ unsigned int handle;
++ unsigned int size;
++};
++
++struct vmcs_sm_ioctl_free {
++ /* user -> kernel */
++ unsigned int handle;
++ /* unsigned int base_addr; */
++};
++
++struct vmcs_sm_ioctl_lock_unlock {
++ /* user -> kernel */
++ unsigned int handle;
++
++ /* kernel -> user */
++ unsigned int addr;
++};
++
++struct vmcs_sm_ioctl_lock_cache {
++ /* user -> kernel */
++ unsigned int handle;
++ enum vmcs_sm_cache_e cached;
++};
++
++struct vmcs_sm_ioctl_resize {
++ /* user -> kernel */
++ unsigned int handle;
++ unsigned int new_size;
++
++ /* kernel -> user */
++ unsigned int old_size;
++};
++
++struct vmcs_sm_ioctl_map {
++ /* user -> kernel */
++ /* and kernel -> user */
++ unsigned int pid;
++ unsigned int handle;
++ unsigned int addr;
++
++ /* kernel -> user */
++ unsigned int size;
++};
++
++struct vmcs_sm_ioctl_walk {
++ /* user -> kernel */
++ unsigned int pid;
++};
++
++struct vmcs_sm_ioctl_chk {
++ /* user -> kernel */
++ unsigned int handle;
++
++ /* kernel -> user */
++ unsigned int addr;
++ unsigned int size;
++ enum vmcs_sm_cache_e cache;
++};
++
++struct vmcs_sm_ioctl_size {
++ /* user -> kernel */
++ unsigned int handle;
++
++ /* kernel -> user */
++ unsigned int size;
++};
++
++struct vmcs_sm_ioctl_cache {
++ /* user -> kernel */
++ unsigned int handle;
++ unsigned int addr;
++ unsigned int size;
++};
++
++/* IOCTL numbers */
++#define VMCS_SM_IOCTL_MEM_ALLOC\
++ _IOR(VMCS_SM_MAGIC_TYPE, VMCS_SM_CMD_ALLOC,\
++ struct vmcs_sm_ioctl_alloc)
++#define VMCS_SM_IOCTL_MEM_ALLOC_SHARE\
++ _IOR(VMCS_SM_MAGIC_TYPE, VMCS_SM_CMD_ALLOC_SHARE,\
++ struct vmcs_sm_ioctl_alloc_share)
++#define VMCS_SM_IOCTL_MEM_LOCK\
++ _IOR(VMCS_SM_MAGIC_TYPE, VMCS_SM_CMD_LOCK,\
++ struct vmcs_sm_ioctl_lock_unlock)
++#define VMCS_SM_IOCTL_MEM_LOCK_CACHE\
++ _IOR(VMCS_SM_MAGIC_TYPE, VMCS_SM_CMD_LOCK_CACHE,\
++ struct vmcs_sm_ioctl_lock_cache)
++#define VMCS_SM_IOCTL_MEM_UNLOCK\
++ _IOR(VMCS_SM_MAGIC_TYPE, VMCS_SM_CMD_UNLOCK,\
++ struct vmcs_sm_ioctl_lock_unlock)
++#define VMCS_SM_IOCTL_MEM_RESIZE\
++ _IOR(VMCS_SM_MAGIC_TYPE, VMCS_SM_CMD_RESIZE,\
++ struct vmcs_sm_ioctl_resize)
++#define VMCS_SM_IOCTL_MEM_FREE\
++ _IOR(VMCS_SM_MAGIC_TYPE, VMCS_SM_CMD_FREE,\
++ struct vmcs_sm_ioctl_free)
++#define VMCS_SM_IOCTL_MEM_FLUSH\
++ _IOR(VMCS_SM_MAGIC_TYPE, VMCS_SM_CMD_FLUSH,\
++ struct vmcs_sm_ioctl_cache)
++#define VMCS_SM_IOCTL_MEM_INVALID\
++ _IOR(VMCS_SM_MAGIC_TYPE, VMCS_SM_CMD_INVALID,\
++ struct vmcs_sm_ioctl_cache)
++
++#define VMCS_SM_IOCTL_SIZE_USR_HDL\
++ _IOR(VMCS_SM_MAGIC_TYPE, VMCS_SM_CMD_SIZE_USR_HANDLE,\
++ struct vmcs_sm_ioctl_size)
++#define VMCS_SM_IOCTL_CHK_USR_HDL\
++ _IOR(VMCS_SM_MAGIC_TYPE, VMCS_SM_CMD_CHK_USR_HANDLE,\
++ struct vmcs_sm_ioctl_chk)
++
++#define VMCS_SM_IOCTL_MAP_USR_HDL\
++ _IOR(VMCS_SM_MAGIC_TYPE, VMCS_SM_CMD_MAPPED_USR_HANDLE,\
++ struct vmcs_sm_ioctl_map)
++#define VMCS_SM_IOCTL_MAP_USR_ADDRESS\
++ _IOR(VMCS_SM_MAGIC_TYPE, VMCS_SM_CMD_MAPPED_USR_ADDRESS,\
++ struct vmcs_sm_ioctl_map)
++#define VMCS_SM_IOCTL_MAP_VC_HDL_FR_ADDR\
++ _IOR(VMCS_SM_MAGIC_TYPE, VMCS_SM_CMD_MAPPED_VC_HDL_FROM_ADDR,\
++ struct vmcs_sm_ioctl_map)
++#define VMCS_SM_IOCTL_MAP_VC_HDL_FR_HDL\
++ _IOR(VMCS_SM_MAGIC_TYPE, VMCS_SM_CMD_MAPPED_VC_HDL_FROM_HDL,\
++ struct vmcs_sm_ioctl_map)
++#define VMCS_SM_IOCTL_MAP_VC_ADDR_FR_HDL\
++ _IOR(VMCS_SM_MAGIC_TYPE, VMCS_SM_CMD_MAPPED_VC_ADDR_FROM_HDL,\
++ struct vmcs_sm_ioctl_map)
++
++#define VMCS_SM_IOCTL_VC_WALK_ALLOC\
++ _IO(VMCS_SM_MAGIC_TYPE, VMCS_SM_CMD_VC_WALK_ALLOC)
++#define VMCS_SM_IOCTL_HOST_WALK_MAP\
++ _IO(VMCS_SM_MAGIC_TYPE, VMCS_SM_CMD_HOST_WALK_MAP)
++#define VMCS_SM_IOCTL_HOST_WALK_PID_ALLOC\
++ _IOR(VMCS_SM_MAGIC_TYPE, VMCS_SM_CMD_HOST_WALK_PID_ALLOC,\
++ struct vmcs_sm_ioctl_walk)
++#define VMCS_SM_IOCTL_HOST_WALK_PID_MAP\
++ _IOR(VMCS_SM_MAGIC_TYPE, VMCS_SM_CMD_HOST_WALK_PID_MAP,\
++ struct vmcs_sm_ioctl_walk)
++
++/* ---- Variable Externs ------------------------------------------------- */
++
++/* ---- Function Prototypes ---------------------------------------------- */
++
++#endif /* __VMCS_SM_IOCTL_H__INCLUDED__ */
+diff -Nur linux-3.12.33/arch/arm/mach-bcm2708/Kconfig linux-3.12.33-rpi/arch/arm/mach-bcm2708/Kconfig
+--- linux-3.12.33/arch/arm/mach-bcm2708/Kconfig 1969-12-31 18:00:00.000000000 -0600
++++ linux-3.12.33-rpi/arch/arm/mach-bcm2708/Kconfig 2014-12-03 19:13:32.448418001 -0600
@@ -0,0 +1,41 @@
+menu "Broadcom BCM2708 Implementations"
+ depends on ARCH_BCM2708
@@ -6459,9 +8589,9 @@ diff -Nur linux-3.12.26.orig/arch/arm/mach-bcm2708/Kconfig linux-3.12.26/arch/ar
+ help
+ Binds spidev driver to the SPI0 master
+endmenu
-diff -Nur linux-3.12.26.orig/arch/arm/mach-bcm2708/Makefile linux-3.12.26/arch/arm/mach-bcm2708/Makefile
---- linux-3.12.26.orig/arch/arm/mach-bcm2708/Makefile 1970-01-01 01:00:00.000000000 +0100
-+++ linux-3.12.26/arch/arm/mach-bcm2708/Makefile 2014-08-06 16:50:13.893957595 +0200
+diff -Nur linux-3.12.33/arch/arm/mach-bcm2708/Makefile linux-3.12.33-rpi/arch/arm/mach-bcm2708/Makefile
+--- linux-3.12.33/arch/arm/mach-bcm2708/Makefile 1969-12-31 18:00:00.000000000 -0600
++++ linux-3.12.33-rpi/arch/arm/mach-bcm2708/Makefile 2014-12-03 19:13:32.448418001 -0600
@@ -0,0 +1,7 @@
+#
+# Makefile for the linux kernel.
@@ -6470,16 +8600,16 @@ diff -Nur linux-3.12.26.orig/arch/arm/mach-bcm2708/Makefile linux-3.12.26/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
-diff -Nur linux-3.12.26.orig/arch/arm/mach-bcm2708/Makefile.boot linux-3.12.26/arch/arm/mach-bcm2708/Makefile.boot
---- linux-3.12.26.orig/arch/arm/mach-bcm2708/Makefile.boot 1970-01-01 01:00:00.000000000 +0100
-+++ linux-3.12.26/arch/arm/mach-bcm2708/Makefile.boot 2014-08-06 16:50:13.893957595 +0200
+diff -Nur linux-3.12.33/arch/arm/mach-bcm2708/Makefile.boot linux-3.12.33-rpi/arch/arm/mach-bcm2708/Makefile.boot
+--- linux-3.12.33/arch/arm/mach-bcm2708/Makefile.boot 1969-12-31 18:00:00.000000000 -0600
++++ linux-3.12.33-rpi/arch/arm/mach-bcm2708/Makefile.boot 2014-12-03 19:13:32.448418001 -0600
@@ -0,0 +1,3 @@
+ zreladdr-y := 0x00008000
+params_phys-y := 0x00000100
+initrd_phys-y := 0x00800000
-diff -Nur linux-3.12.26.orig/arch/arm/mach-bcm2708/power.c linux-3.12.26/arch/arm/mach-bcm2708/power.c
---- linux-3.12.26.orig/arch/arm/mach-bcm2708/power.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-3.12.26/arch/arm/mach-bcm2708/power.c 2014-08-06 16:50:13.897957627 +0200
+diff -Nur linux-3.12.33/arch/arm/mach-bcm2708/power.c linux-3.12.33-rpi/arch/arm/mach-bcm2708/power.c
+--- linux-3.12.33/arch/arm/mach-bcm2708/power.c 1969-12-31 18:00:00.000000000 -0600
++++ linux-3.12.33-rpi/arch/arm/mach-bcm2708/power.c 2014-12-03 19:13:32.468418001 -0600
@@ -0,0 +1,194 @@
+/*
+ * linux/arch/arm/mach-bcm2708/power.c
@@ -6675,9 +8805,9 @@ diff -Nur linux-3.12.26.orig/arch/arm/mach-bcm2708/power.c linux-3.12.26/arch/ar
+MODULE_AUTHOR("Phil Elwell");
+MODULE_DESCRIPTION("Interface to BCM2708 power management");
+MODULE_LICENSE("GPL");
-diff -Nur linux-3.12.26.orig/arch/arm/mach-bcm2708/vcio.c linux-3.12.26/arch/arm/mach-bcm2708/vcio.c
---- linux-3.12.26.orig/arch/arm/mach-bcm2708/vcio.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-3.12.26/arch/arm/mach-bcm2708/vcio.c 2014-08-06 16:50:13.897957627 +0200
+diff -Nur linux-3.12.33/arch/arm/mach-bcm2708/vcio.c linux-3.12.33-rpi/arch/arm/mach-bcm2708/vcio.c
+--- linux-3.12.33/arch/arm/mach-bcm2708/vcio.c 1969-12-31 18:00:00.000000000 -0600
++++ linux-3.12.33-rpi/arch/arm/mach-bcm2708/vcio.c 2014-12-03 19:13:32.472418001 -0600
@@ -0,0 +1,474 @@
+/*
+ * linux/arch/arm/mach-bcm2708/vcio.c
@@ -7153,9 +9283,9 @@ diff -Nur linux-3.12.26.orig/arch/arm/mach-bcm2708/vcio.c linux-3.12.26/arch/arm
+MODULE_DESCRIPTION("ARM I/O to VideoCore processor");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:bcm-mbox");
-diff -Nur linux-3.12.26.orig/arch/arm/mach-bcm2708/vc_mem.c linux-3.12.26/arch/arm/mach-bcm2708/vc_mem.c
---- linux-3.12.26.orig/arch/arm/mach-bcm2708/vc_mem.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-3.12.26/arch/arm/mach-bcm2708/vc_mem.c 2014-08-06 16:50:13.897957627 +0200
+diff -Nur linux-3.12.33/arch/arm/mach-bcm2708/vc_mem.c linux-3.12.33-rpi/arch/arm/mach-bcm2708/vc_mem.c
+--- linux-3.12.33/arch/arm/mach-bcm2708/vc_mem.c 1969-12-31 18:00:00.000000000 -0600
++++ linux-3.12.33-rpi/arch/arm/mach-bcm2708/vc_mem.c 2014-12-03 19:13:32.468418001 -0600
@@ -0,0 +1,432 @@
+/*****************************************************************************
+* Copyright 2010 - 2011 Broadcom Corporation. All rights reserved.
@@ -7589,9 +9719,9 @@ diff -Nur linux-3.12.26.orig/arch/arm/mach-bcm2708/vc_mem.c linux-3.12.26/arch/a
+module_param(mem_size, uint, 0644);
+module_param(mem_base, uint, 0644);
+
-diff -Nur linux-3.12.26.orig/arch/arm/Makefile linux-3.12.26/arch/arm/Makefile
---- linux-3.12.26.orig/arch/arm/Makefile 2014-07-30 18:02:44.000000000 +0200
-+++ linux-3.12.26/arch/arm/Makefile 2014-08-06 16:50:13.897957627 +0200
+diff -Nur linux-3.12.33/arch/arm/Makefile linux-3.12.33-rpi/arch/arm/Makefile
+--- linux-3.12.33/arch/arm/Makefile 2014-11-15 06:28:07.000000000 -0600
++++ linux-3.12.33-rpi/arch/arm/Makefile 2014-12-03 19:13:32.212418001 -0600
@@ -146,6 +146,7 @@
# by CONFIG_* macro name.
machine-$(CONFIG_ARCH_AT91) += at91
@@ -7600,9 +9730,9 @@ diff -Nur linux-3.12.26.orig/arch/arm/Makefile linux-3.12.26/arch/arm/Makefile
machine-$(CONFIG_ARCH_BCM2835) += bcm2835
machine-$(CONFIG_ARCH_CLPS711X) += clps711x
machine-$(CONFIG_ARCH_CNS3XXX) += cns3xxx
-diff -Nur linux-3.12.26.orig/arch/arm/mm/Kconfig linux-3.12.26/arch/arm/mm/Kconfig
---- linux-3.12.26.orig/arch/arm/mm/Kconfig 2014-07-30 18:02:44.000000000 +0200
-+++ linux-3.12.26/arch/arm/mm/Kconfig 2014-08-06 16:50:13.897957627 +0200
+diff -Nur linux-3.12.33/arch/arm/mm/Kconfig linux-3.12.33-rpi/arch/arm/mm/Kconfig
+--- linux-3.12.33/arch/arm/mm/Kconfig 2014-11-15 06:28:07.000000000 -0600
++++ linux-3.12.33-rpi/arch/arm/mm/Kconfig 2014-12-03 19:13:32.640418001 -0600
@@ -358,7 +358,7 @@
# ARMv6
@@ -7612,9 +9742,9 @@ diff -Nur linux-3.12.26.orig/arch/arm/mm/Kconfig linux-3.12.26/arch/arm/mm/Kconf
select CPU_32v6
select CPU_ABRT_EV6
select CPU_CACHE_V6
-diff -Nur linux-3.12.26.orig/arch/arm/mm/proc-v6.S linux-3.12.26/arch/arm/mm/proc-v6.S
---- linux-3.12.26.orig/arch/arm/mm/proc-v6.S 2014-07-30 18:02:44.000000000 +0200
-+++ linux-3.12.26/arch/arm/mm/proc-v6.S 2014-08-06 16:50:13.897957627 +0200
+diff -Nur linux-3.12.33/arch/arm/mm/proc-v6.S linux-3.12.33-rpi/arch/arm/mm/proc-v6.S
+--- linux-3.12.33/arch/arm/mm/proc-v6.S 2014-11-15 06:28:07.000000000 -0600
++++ linux-3.12.33-rpi/arch/arm/mm/proc-v6.S 2014-12-03 19:13:32.644418001 -0600
@@ -73,10 +73,19 @@
*
* IRQs are already disabled.
@@ -7638,9 +9768,9 @@ diff -Nur linux-3.12.26.orig/arch/arm/mm/proc-v6.S linux-3.12.26/arch/arm/mm/pro
mov pc, lr
ENTRY(cpu_v6_dcache_clean_area)
-diff -Nur linux-3.12.26.orig/arch/arm/tools/mach-types linux-3.12.26/arch/arm/tools/mach-types
---- linux-3.12.26.orig/arch/arm/tools/mach-types 2014-07-30 18:02:44.000000000 +0200
-+++ linux-3.12.26/arch/arm/tools/mach-types 2014-08-06 16:50:13.901957659 +0200
+diff -Nur linux-3.12.33/arch/arm/tools/mach-types linux-3.12.33-rpi/arch/arm/tools/mach-types
+--- linux-3.12.33/arch/arm/tools/mach-types 2014-11-15 06:28:07.000000000 -0600
++++ linux-3.12.33-rpi/arch/arm/tools/mach-types 2014-12-03 19:13:32.656418001 -0600
@@ -522,6 +522,7 @@
prima2_evb MACH_PRIMA2_EVB PRIMA2_EVB 3103
paz00 MACH_PAZ00 PAZ00 3128
@@ -7649,119 +9779,9 @@ diff -Nur linux-3.12.26.orig/arch/arm/tools/mach-types linux-3.12.26/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.26.orig/arch/m68k/Kconfig linux-3.12.26/arch/m68k/Kconfig
---- linux-3.12.26.orig/arch/m68k/Kconfig 2014-07-30 18:02:44.000000000 +0200
-+++ linux-3.12.26/arch/m68k/Kconfig 2014-08-06 16:50:13.901957659 +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.26.orig/arch/s390/Kconfig linux-3.12.26/arch/s390/Kconfig
---- linux-3.12.26.orig/arch/s390/Kconfig 2014-07-30 18:02:44.000000000 +0200
-+++ linux-3.12.26/arch/s390/Kconfig 2014-08-06 16:50:13.901957659 +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.26.orig/arch/x86/crypto/ghash-clmulni-intel_asm.S linux-3.12.26/arch/x86/crypto/ghash-clmulni-intel_asm.S
---- linux-3.12.26.orig/arch/x86/crypto/ghash-clmulni-intel_asm.S 2014-07-30 18:02:44.000000000 +0200
-+++ linux-3.12.26/arch/x86/crypto/ghash-clmulni-intel_asm.S 2014-08-06 16:50:13.905957690 +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.26.orig/arch/x86/crypto/ghash-clmulni-intel_glue.c linux-3.12.26/arch/x86/crypto/ghash-clmulni-intel_glue.c
---- linux-3.12.26.orig/arch/x86/crypto/ghash-clmulni-intel_glue.c 2014-07-30 18:02:44.000000000 +0200
-+++ linux-3.12.26/arch/x86/crypto/ghash-clmulni-intel_glue.c 2014-08-06 16:50:13.905957690 +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.26.orig/Documentation/devicetree/bindings/net/micrel-ks8851.txt linux-3.12.26/Documentation/devicetree/bindings/net/micrel-ks8851.txt
---- linux-3.12.26.orig/Documentation/devicetree/bindings/net/micrel-ks8851.txt 2014-07-30 18:02:44.000000000 +0200
-+++ linux-3.12.26/Documentation/devicetree/bindings/net/micrel-ks8851.txt 2014-08-06 16:50:13.905957690 +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.26.orig/Documentation/video4linux/bcm2835-v4l2.txt linux-3.12.26/Documentation/video4linux/bcm2835-v4l2.txt
---- linux-3.12.26.orig/Documentation/video4linux/bcm2835-v4l2.txt 1970-01-01 01:00:00.000000000 +0100
-+++ linux-3.12.26/Documentation/video4linux/bcm2835-v4l2.txt 2014-08-06 16:50:13.905957690 +0200
+diff -Nur linux-3.12.33/Documentation/video4linux/bcm2835-v4l2.txt linux-3.12.33-rpi/Documentation/video4linux/bcm2835-v4l2.txt
+--- linux-3.12.33/Documentation/video4linux/bcm2835-v4l2.txt 1969-12-31 18:00:00.000000000 -0600
++++ linux-3.12.33-rpi/Documentation/video4linux/bcm2835-v4l2.txt 2014-12-03 19:13:32.164418001 -0600
@@ -0,0 +1,60 @@
+
+BCM2835 (aka Raspberry Pi) V4L2 driver
@@ -7823,10 +9843,10 @@ diff -Nur linux-3.12.26.orig/Documentation/video4linux/bcm2835-v4l2.txt linux-3.
+List of available formats:
+
+$ v4l2-ctl --list-formats
-diff -Nur linux-3.12.26.orig/drivers/char/broadcom/Kconfig linux-3.12.26/drivers/char/broadcom/Kconfig
---- linux-3.12.26.orig/drivers/char/broadcom/Kconfig 1970-01-01 01:00:00.000000000 +0100
-+++ linux-3.12.26/drivers/char/broadcom/Kconfig 2014-08-06 16:50:13.933957910 +0200
-@@ -0,0 +1,16 @@
+diff -Nur linux-3.12.33/drivers/char/broadcom/Kconfig linux-3.12.33-rpi/drivers/char/broadcom/Kconfig
+--- linux-3.12.33/drivers/char/broadcom/Kconfig 1969-12-31 18:00:00.000000000 -0600
++++ linux-3.12.33-rpi/drivers/char/broadcom/Kconfig 2014-12-03 19:13:34.236418001 -0600
+@@ -0,0 +1,22 @@
+#
+# Broadcom char driver config
+#
@@ -7843,14 +9863,21 @@ diff -Nur linux-3.12.26.orig/drivers/char/broadcom/Kconfig linux-3.12.26/drivers
+ help
+ Helper for videocore CMA access.
+
-diff -Nur linux-3.12.26.orig/drivers/char/broadcom/Makefile linux-3.12.26/drivers/char/broadcom/Makefile
---- linux-3.12.26.orig/drivers/char/broadcom/Makefile 1970-01-01 01:00:00.000000000 +0100
-+++ linux-3.12.26/drivers/char/broadcom/Makefile 2014-08-06 16:50:13.933957910 +0200
-@@ -0,0 +1 @@
++config BCM_VC_SM
++ tristate "VMCS Shared Memory"
++ default n
++ help
++ Support for the VC shared memory on the Broadcom reference
++ design. Uses the VCHIQ stack.
+diff -Nur linux-3.12.33/drivers/char/broadcom/Makefile linux-3.12.33-rpi/drivers/char/broadcom/Makefile
+--- linux-3.12.33/drivers/char/broadcom/Makefile 1969-12-31 18:00:00.000000000 -0600
++++ linux-3.12.33-rpi/drivers/char/broadcom/Makefile 2014-12-03 19:13:34.236418001 -0600
+@@ -0,0 +1,2 @@
+obj-$(CONFIG_BCM_VC_CMA) += vc_cma/
-diff -Nur linux-3.12.26.orig/drivers/char/broadcom/vc_cma/Makefile linux-3.12.26/drivers/char/broadcom/vc_cma/Makefile
---- linux-3.12.26.orig/drivers/char/broadcom/vc_cma/Makefile 1970-01-01 01:00:00.000000000 +0100
-+++ linux-3.12.26/drivers/char/broadcom/vc_cma/Makefile 2014-08-06 16:50:13.933957910 +0200
++obj-$(CONFIG_BCM_VC_SM) += vc_sm/
+diff -Nur linux-3.12.33/drivers/char/broadcom/vc_cma/Makefile linux-3.12.33-rpi/drivers/char/broadcom/vc_cma/Makefile
+--- linux-3.12.33/drivers/char/broadcom/vc_cma/Makefile 1969-12-31 18:00:00.000000000 -0600
++++ linux-3.12.33-rpi/drivers/char/broadcom/vc_cma/Makefile 2014-12-03 19:13:34.236418001 -0600
@@ -0,0 +1,14 @@
+ccflags-y += -Wall -Wstrict-prototypes -Wno-trigraphs
+ccflags-y += -Werror
@@ -7866,9 +9893,9 @@ diff -Nur linux-3.12.26.orig/drivers/char/broadcom/vc_cma/Makefile linux-3.12.26
+obj-$(CONFIG_BCM_VC_CMA) += vc-cma.o
+
+vc-cma-objs := vc_cma.o
-diff -Nur linux-3.12.26.orig/drivers/char/broadcom/vc_cma/vc_cma.c linux-3.12.26/drivers/char/broadcom/vc_cma/vc_cma.c
---- linux-3.12.26.orig/drivers/char/broadcom/vc_cma/vc_cma.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-3.12.26/drivers/char/broadcom/vc_cma/vc_cma.c 2014-08-06 16:50:13.933957910 +0200
+diff -Nur linux-3.12.33/drivers/char/broadcom/vc_cma/vc_cma.c linux-3.12.33-rpi/drivers/char/broadcom/vc_cma/vc_cma.c
+--- linux-3.12.33/drivers/char/broadcom/vc_cma/vc_cma.c 1969-12-31 18:00:00.000000000 -0600
++++ linux-3.12.33-rpi/drivers/char/broadcom/vc_cma/vc_cma.c 2014-12-03 19:13:34.236418001 -0600
@@ -0,0 +1,1143 @@
+/**
+ * Copyright (c) 2010-2012 Broadcom. All rights reserved.
@@ -9013,9 +11040,3697 @@ diff -Nur linux-3.12.26.orig/drivers/char/broadcom/vc_cma/vc_cma.c linux-3.12.26
+module_exit(vc_cma_exit);
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Broadcom Corporation");
-diff -Nur linux-3.12.26.orig/drivers/char/hw_random/bcm2708-rng.c linux-3.12.26/drivers/char/hw_random/bcm2708-rng.c
---- linux-3.12.26.orig/drivers/char/hw_random/bcm2708-rng.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-3.12.26/drivers/char/hw_random/bcm2708-rng.c 2014-08-06 16:50:13.937957941 +0200
+diff -Nur linux-3.12.33/drivers/char/broadcom/vc_sm/Makefile linux-3.12.33-rpi/drivers/char/broadcom/vc_sm/Makefile
+--- linux-3.12.33/drivers/char/broadcom/vc_sm/Makefile 1969-12-31 18:00:00.000000000 -0600
++++ linux-3.12.33-rpi/drivers/char/broadcom/vc_sm/Makefile 2014-12-03 19:13:34.236418001 -0600
+@@ -0,0 +1,21 @@
++EXTRA_CFLAGS += -Wall -Wstrict-prototypes -Wno-trigraphs -O2
++
++EXTRA_CFLAGS += -I"./arch/arm/mach-bcm2708/include/mach"
++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"
++EXTRA_CFLAGS += -I"$(srctree)/fs/"
++
++EXTRA_CFLAGS += -DOS_ASSERT_FAILURE
++EXTRA_CFLAGS += -D__STDC_VERSION=199901L
++EXTRA_CFLAGS += -D__STDC_VERSION__=199901L
++EXTRA_CFLAGS += -D__VCCOREVER__=0
++EXTRA_CFLAGS += -D__KERNEL__
++EXTRA_CFLAGS += -D__linux__
++EXTRA_CFLAGS += -Werror
++
++obj-$(CONFIG_BCM_VC_SM) := vc-sm.o
++
++vc-sm-objs := \
++ vmcs_sm.o \
++ vc_vchi_sm.o
+diff -Nur linux-3.12.33/drivers/char/broadcom/vc_sm/vc_vchi_sm.c linux-3.12.33-rpi/drivers/char/broadcom/vc_sm/vc_vchi_sm.c
+--- linux-3.12.33/drivers/char/broadcom/vc_sm/vc_vchi_sm.c 1969-12-31 18:00:00.000000000 -0600
++++ linux-3.12.33-rpi/drivers/char/broadcom/vc_sm/vc_vchi_sm.c 2014-12-03 19:13:34.236418001 -0600
+@@ -0,0 +1,492 @@
++/*****************************************************************************
++* Copyright 2011-2012 Broadcom Corporation. All rights reserved.
++*
++* Unless you and Broadcom execute a separate written software license
++* agreement governing use of this software, this software is licensed to you
++* under the terms of the GNU General Public License version 2, available at
++* http://www.broadcom.com/licenses/GPLv2.php (the "GPL").
++*
++* Notwithstanding the above, under no circumstances may you combine this
++* software in any way with any other Broadcom software provided under a
++* license other than the GPL, without Broadcom's express prior written
++* consent.
++*****************************************************************************/
++
++/* ---- Include Files ----------------------------------------------------- */
++#include <linux/types.h>
++#include <linux/kernel.h>
++#include <linux/list.h>
++#include <linux/semaphore.h>
++#include <linux/mutex.h>
++#include <linux/slab.h>
++#include <linux/kthread.h>
++
++#include "vc_vchi_sm.h"
++
++#define VC_SM_VER 1
++#define VC_SM_MIN_VER 0
++
++/* ---- Private Constants and Types -------------------------------------- */
++
++/* Command blocks come from a pool */
++#define SM_MAX_NUM_CMD_RSP_BLKS 32
++
++struct sm_cmd_rsp_blk {
++ struct list_head head; /* To create lists */
++ struct semaphore sema; /* To be signaled when the response is there */
++
++ uint16_t id;
++ uint16_t length;
++
++ uint8_t msg[VC_SM_MAX_MSG_LEN];
++
++ uint32_t wait:1;
++ uint32_t sent:1;
++ uint32_t alloc:1;
++
++};
++
++struct sm_instance {
++ uint32_t num_connections;
++ VCHI_SERVICE_HANDLE_T vchi_handle[VCHI_MAX_NUM_CONNECTIONS];
++ struct task_struct *io_thread;
++ struct semaphore io_sema;
++
++ uint32_t trans_id;
++
++ struct mutex lock;
++ struct list_head cmd_list;
++ struct list_head rsp_list;
++ struct list_head dead_list;
++
++ struct sm_cmd_rsp_blk free_blk[SM_MAX_NUM_CMD_RSP_BLKS];
++ struct list_head free_list;
++ struct mutex free_lock;
++ struct semaphore free_sema;
++
++};
++
++/* ---- Private Variables ------------------------------------------------ */
++
++/* ---- Private Function Prototypes -------------------------------------- */
++
++/* ---- Private Functions ------------------------------------------------ */
++static struct
++sm_cmd_rsp_blk *vc_vchi_cmd_create(struct sm_instance *instance,
++ VC_SM_MSG_TYPE id, void *msg,
++ uint32_t size, int wait)
++{
++ struct sm_cmd_rsp_blk *blk;
++ VC_SM_MSG_HDR_T *hdr;
++
++ if (down_interruptible(&instance->free_sema)) {
++ blk = kmalloc(sizeof(*blk), GFP_KERNEL);
++ if (!blk)
++ return NULL;
++
++ blk->alloc = 1;
++ sema_init(&blk->sema, 0);
++ } else {
++ mutex_lock(&instance->free_lock);
++ blk =
++ list_first_entry(&instance->free_list,
++ struct sm_cmd_rsp_blk, head);
++ list_del(&blk->head);
++ mutex_unlock(&instance->free_lock);
++ }
++
++ blk->sent = 0;
++ blk->wait = wait;
++ blk->length = sizeof(*hdr) + size;
++
++ hdr = (VC_SM_MSG_HDR_T *) blk->msg;
++ hdr->type = id;
++ mutex_lock(&instance->lock);
++ hdr->trans_id = blk->id = ++instance->trans_id;
++ mutex_unlock(&instance->lock);
++
++ if (size)
++ memcpy(hdr->body, msg, size);
++
++ return blk;
++}
++
++static void
++vc_vchi_cmd_delete(struct sm_instance *instance, struct sm_cmd_rsp_blk *blk)
++{
++ if (blk->alloc) {
++ kfree(blk);
++ return;
++ }
++
++ mutex_lock(&instance->free_lock);
++ list_add(&blk->head, &instance->free_list);
++ mutex_unlock(&instance->free_lock);
++ up(&instance->free_sema);
++}
++
++static int vc_vchi_sm_videocore_io(void *arg)
++{
++ struct sm_instance *instance = arg;
++ struct sm_cmd_rsp_blk *cmd = NULL, *cmd_tmp;
++ VC_SM_RESULT_T *reply;
++ uint32_t reply_len;
++ int32_t status;
++ int svc_use = 1;
++
++ while (1) {
++ if (svc_use)
++ vchi_service_release(instance->vchi_handle[0]);
++ svc_use = 0;
++ if (!down_interruptible(&instance->io_sema)) {
++ vchi_service_use(instance->vchi_handle[0]);
++ svc_use = 1;
++
++ do {
++ unsigned int flags;
++ /*
++ * Get new command and move it to response list
++ */
++ mutex_lock(&instance->lock);
++ if (list_empty(&instance->cmd_list)) {
++ /* no more commands to process */
++ mutex_unlock(&instance->lock);
++ break;
++ }
++ cmd =
++ list_first_entry(&instance->cmd_list,
++ struct sm_cmd_rsp_blk,
++ head);
++ list_move(&cmd->head, &instance->rsp_list);
++ cmd->sent = 1;
++ mutex_unlock(&instance->lock);
++
++ /* Send the command */
++ flags = VCHI_FLAGS_BLOCK_UNTIL_QUEUED;
++ status = vchi_msg_queue(
++ instance->vchi_handle[0],
++ cmd->msg, cmd->length,
++ flags, NULL);
++ if (status) {
++ pr_err("%s: failed to queue message (%d)",
++ __func__, status);
++ }
++
++ /* If no reply is needed then we're done */
++ if (!cmd->wait) {
++ mutex_lock(&instance->lock);
++ list_del(&cmd->head);
++ mutex_unlock(&instance->lock);
++ vc_vchi_cmd_delete(instance, cmd);
++ continue;
++ }
++
++ if (status) {
++ up(&cmd->sema);
++ continue;
++ }
++
++ } while (1);
++
++ while (!vchi_msg_peek
++ (instance->vchi_handle[0], (void **)&reply,
++ &reply_len, VCHI_FLAGS_NONE)) {
++ mutex_lock(&instance->lock);
++ list_for_each_entry(cmd, &instance->rsp_list,
++ head) {
++ if (cmd->id == reply->trans_id)
++ break;
++ }
++ mutex_unlock(&instance->lock);
++
++ if (&cmd->head == &instance->rsp_list) {
++ pr_debug("%s: received response %u, throw away...",
++ __func__, reply->trans_id);
++ } else if (reply_len > sizeof(cmd->msg)) {
++ pr_err("%s: reply too big (%u) %u, throw away...",
++ __func__, reply_len,
++ reply->trans_id);
++ } else {
++ memcpy(cmd->msg, reply, reply_len);
++ up(&cmd->sema);
++ }
++
++ vchi_msg_remove(instance->vchi_handle[0]);
++ }
++
++ /* Go through the dead list and free them */
++ mutex_lock(&instance->lock);
++ list_for_each_entry_safe(cmd, cmd_tmp,
++ &instance->dead_list, head) {
++ list_del(&cmd->head);
++ vc_vchi_cmd_delete(instance, cmd);
++ }
++ mutex_unlock(&instance->lock);
++ }
++ }
++
++ return 0;
++}
++
++static void vc_sm_vchi_callback(void *param,
++ const VCHI_CALLBACK_REASON_T reason,
++ void *msg_handle)
++{
++ struct sm_instance *instance = param;
++
++ (void)msg_handle;
++
++ switch (reason) {
++ case VCHI_CALLBACK_MSG_AVAILABLE:
++ up(&instance->io_sema);
++ break;
++
++ case VCHI_CALLBACK_SERVICE_CLOSED:
++ pr_info("%s: service CLOSED!!", __func__);
++ default:
++ break;
++ }
++}
++
++VC_VCHI_SM_HANDLE_T vc_vchi_sm_init(VCHI_INSTANCE_T vchi_instance,
++ VCHI_CONNECTION_T **vchi_connections,
++ uint32_t num_connections)
++{
++ uint32_t i;
++ struct sm_instance *instance;
++ int status;
++
++ pr_debug("%s: start", __func__);
++
++ if (num_connections > VCHI_MAX_NUM_CONNECTIONS) {
++ pr_err("%s: unsupported number of connections %u (max=%u)",
++ __func__, num_connections, VCHI_MAX_NUM_CONNECTIONS);
++
++ goto err_null;
++ }
++ /* Allocate memory for this instance */
++ instance = kzalloc(sizeof(*instance), GFP_KERNEL);
++
++ /* Misc initialisations */
++ mutex_init(&instance->lock);
++ sema_init(&instance->io_sema, 0);
++ INIT_LIST_HEAD(&instance->cmd_list);
++ INIT_LIST_HEAD(&instance->rsp_list);
++ INIT_LIST_HEAD(&instance->dead_list);
++ INIT_LIST_HEAD(&instance->free_list);
++ sema_init(&instance->free_sema, SM_MAX_NUM_CMD_RSP_BLKS);
++ mutex_init(&instance->free_lock);
++ for (i = 0; i < SM_MAX_NUM_CMD_RSP_BLKS; i++) {
++ sema_init(&instance->free_blk[i].sema, 0);
++ list_add(&instance->free_blk[i].head, &instance->free_list);
++ }
++
++ /* Open the VCHI service connections */
++ instance->num_connections = num_connections;
++ for (i = 0; i < num_connections; i++) {
++ SERVICE_CREATION_T params = {
++ VCHI_VERSION_EX(VC_SM_VER, VC_SM_MIN_VER),
++ VC_SM_SERVER_NAME,
++ vchi_connections[i],
++ 0,
++ 0,
++ vc_sm_vchi_callback,
++ instance,
++ 0,
++ 0,
++ 0,
++ };
++
++ status = vchi_service_open(vchi_instance,
++ &params, &instance->vchi_handle[i]);
++ if (status) {
++ pr_err("%s: failed to open VCHI service (%d)",
++ __func__, status);
++
++ goto err_close_services;
++ }
++ }
++
++ /* Create the thread which takes care of all io to/from videoocore. */
++ instance->io_thread = kthread_create(&vc_vchi_sm_videocore_io,
++ (void *)instance, "SMIO");
++ if (instance->io_thread == NULL) {
++ pr_err("%s: failed to create SMIO thread", __func__);
++
++ goto err_close_services;
++ }
++ set_user_nice(instance->io_thread, -10);
++ wake_up_process(instance->io_thread);
++
++ pr_debug("%s: success - instance 0x%x", __func__, (unsigned)instance);
++ return instance;
++
++err_close_services:
++ for (i = 0; i < instance->num_connections; i++) {
++ if (instance->vchi_handle[i] != NULL)
++ vchi_service_close(instance->vchi_handle[i]);
++ }
++ kfree(instance);
++err_null:
++ pr_debug("%s: FAILED", __func__);
++ return NULL;
++}
++
++int vc_vchi_sm_stop(VC_VCHI_SM_HANDLE_T *handle)
++{
++ struct sm_instance *instance;
++ uint32_t i;
++
++ if (handle == NULL) {
++ pr_err("%s: invalid pointer to handle %p", __func__, handle);
++ goto lock;
++ }
++
++ if (*handle == NULL) {
++ pr_err("%s: invalid handle %p", __func__, *handle);
++ goto lock;
++ }
++
++ instance = *handle;
++
++ /* Close all VCHI service connections */
++ for (i = 0; i < instance->num_connections; i++) {
++ int32_t success;
++ vchi_service_use(instance->vchi_handle[i]);
++
++ success = vchi_service_close(instance->vchi_handle[i]);
++ }
++
++ kfree(instance);
++
++ *handle = NULL;
++ return 0;
++
++lock:
++ return -EINVAL;
++}
++
++int vc_vchi_sm_send_msg(VC_VCHI_SM_HANDLE_T handle,
++ VC_SM_MSG_TYPE msg_id,
++ void *msg, uint32_t msg_size,
++ void *result, uint32_t result_size,
++ uint32_t *cur_trans_id, uint8_t wait_reply)
++{
++ int status = 0;
++ struct sm_instance *instance = handle;
++ struct sm_cmd_rsp_blk *cmd_blk;
++
++ if (handle == NULL) {
++ pr_err("%s: invalid handle", __func__);
++ return -EINVAL;
++ }
++ if (msg == NULL) {
++ pr_err("%s: invalid msg pointer", __func__);
++ return -EINVAL;
++ }
++
++ cmd_blk =
++ vc_vchi_cmd_create(instance, msg_id, msg, msg_size, wait_reply);
++ if (cmd_blk == NULL) {
++ pr_err("[%s]: failed to allocate global tracking resource",
++ __func__);
++ return -ENOMEM;
++ }
++
++ if (cur_trans_id != NULL)
++ *cur_trans_id = cmd_blk->id;
++
++ mutex_lock(&instance->lock);
++ list_add_tail(&cmd_blk->head, &instance->cmd_list);
++ mutex_unlock(&instance->lock);
++ up(&instance->io_sema);
++
++ if (!wait_reply)
++ /* We're done */
++ return 0;
++
++ /* Wait for the response */
++ if (down_interruptible(&cmd_blk->sema)) {
++ mutex_lock(&instance->lock);
++ if (!cmd_blk->sent) {
++ list_del(&cmd_blk->head);
++ mutex_unlock(&instance->lock);
++ vc_vchi_cmd_delete(instance, cmd_blk);
++ return -ENXIO;
++ }
++ mutex_unlock(&instance->lock);
++
++ mutex_lock(&instance->lock);
++ list_move(&cmd_blk->head, &instance->dead_list);
++ mutex_unlock(&instance->lock);
++ up(&instance->io_sema);
++ return -EINTR; /* We're done */
++ }
++
++ if (result && result_size) {
++ memcpy(result, cmd_blk->msg, result_size);
++ } else {
++ VC_SM_RESULT_T *res = (VC_SM_RESULT_T *) cmd_blk->msg;
++ status = (res->success == 0) ? 0 : -ENXIO;
++ }
++
++ mutex_lock(&instance->lock);
++ list_del(&cmd_blk->head);
++ mutex_unlock(&instance->lock);
++ vc_vchi_cmd_delete(instance, cmd_blk);
++ return status;
++}
++
++int vc_vchi_sm_alloc(VC_VCHI_SM_HANDLE_T handle, VC_SM_ALLOC_T *msg,
++ VC_SM_ALLOC_RESULT_T *result, uint32_t *cur_trans_id)
++{
++ return vc_vchi_sm_send_msg(handle, VC_SM_MSG_TYPE_ALLOC,
++ msg, sizeof(*msg), result, sizeof(*result),
++ cur_trans_id, 1);
++}
++
++int vc_vchi_sm_free(VC_VCHI_SM_HANDLE_T handle,
++ VC_SM_FREE_T *msg, uint32_t *cur_trans_id)
++{
++ return vc_vchi_sm_send_msg(handle, VC_SM_MSG_TYPE_FREE,
++ msg, sizeof(*msg), 0, 0, cur_trans_id, 0);
++}
++
++int vc_vchi_sm_lock(VC_VCHI_SM_HANDLE_T handle,
++ VC_SM_LOCK_UNLOCK_T *msg,
++ VC_SM_LOCK_RESULT_T *result, uint32_t *cur_trans_id)
++{
++ return vc_vchi_sm_send_msg(handle, VC_SM_MSG_TYPE_LOCK,
++ msg, sizeof(*msg), result, sizeof(*result),
++ cur_trans_id, 1);
++}
++
++int vc_vchi_sm_unlock(VC_VCHI_SM_HANDLE_T handle,
++ VC_SM_LOCK_UNLOCK_T *msg,
++ uint32_t *cur_trans_id, uint8_t wait_reply)
++{
++ return vc_vchi_sm_send_msg(handle, wait_reply ?
++ VC_SM_MSG_TYPE_UNLOCK :
++ VC_SM_MSG_TYPE_UNLOCK_NOANS, msg,
++ sizeof(*msg), 0, 0, cur_trans_id,
++ wait_reply);
++}
++
++int vc_vchi_sm_resize(VC_VCHI_SM_HANDLE_T handle, VC_SM_RESIZE_T *msg,
++ uint32_t *cur_trans_id)
++{
++ return vc_vchi_sm_send_msg(handle, VC_SM_MSG_TYPE_RESIZE,
++ msg, sizeof(*msg), 0, 0, cur_trans_id, 1);
++}
++
++int vc_vchi_sm_walk_alloc(VC_VCHI_SM_HANDLE_T handle)
++{
++ return vc_vchi_sm_send_msg(handle, VC_SM_MSG_TYPE_WALK_ALLOC,
++ 0, 0, 0, 0, 0, 0);
++}
++
++int vc_vchi_sm_clean_up(VC_VCHI_SM_HANDLE_T handle, VC_SM_ACTION_CLEAN_T *msg)
++{
++ return vc_vchi_sm_send_msg(handle, VC_SM_MSG_TYPE_ACTION_CLEAN,
++ msg, sizeof(*msg), 0, 0, 0, 0);
++}
+diff -Nur linux-3.12.33/drivers/char/broadcom/vc_sm/vmcs_sm.c linux-3.12.33-rpi/drivers/char/broadcom/vc_sm/vmcs_sm.c
+--- linux-3.12.33/drivers/char/broadcom/vc_sm/vmcs_sm.c 1969-12-31 18:00:00.000000000 -0600
++++ linux-3.12.33-rpi/drivers/char/broadcom/vc_sm/vmcs_sm.c 2014-12-03 19:13:34.236418001 -0600
+@@ -0,0 +1,3163 @@
++/*****************************************************************************
++* Copyright 2011-2012 Broadcom Corporation. All rights reserved.
++*
++* Unless you and Broadcom execute a separate written software license
++* agreement governing use of this software, this software is licensed to you
++* under the terms of the GNU General Public License version 2, available at
++* http://www.broadcom.com/licenses/GPLv2.php (the "GPL").
++*
++* Notwithstanding the above, under no circumstances may you combine this
++* software in any way with any other Broadcom software provided under a
++* license other than the GPL, without Broadcom's express prior written
++* consent.
++*****************************************************************************/
++
++/* ---- Include Files ----------------------------------------------------- */
++
++#include <linux/cdev.h>
++#include <linux/device.h>
++#include <linux/debugfs.h>
++#include <linux/dma-mapping.h>
++#include <linux/errno.h>
++#include <linux/fs.h>
++#include <linux/hugetlb.h>
++#include <linux/ioctl.h>
++#include <linux/kernel.h>
++#include <linux/list.h>
++#include <linux/module.h>
++#include <linux/mm.h>
++#include <linux/pfn.h>
++#include <linux/proc_fs.h>
++#include <linux/pagemap.h>
++#include <linux/semaphore.h>
++#include <linux/slab.h>
++#include <linux/seq_file.h>
++#include <linux/types.h>
++#include <asm/cacheflush.h>
++
++#include <vc_mem.h>
++
++#include "vchiq_connected.h"
++#include "vc_vchi_sm.h"
++
++#include <vmcs_sm_ioctl.h>
++#include "vc_sm_knl.h"
++
++/* ---- Private Constants and Types --------------------------------------- */
++
++#define DEVICE_NAME "vcsm"
++#define DEVICE_MINOR 0
++
++#define VC_SM_DIR_ROOT_NAME "vc-smem"
++#define VC_SM_DIR_ALLOC_NAME "alloc"
++#define VC_SM_STATE "state"
++#define VC_SM_STATS "statistics"
++#define VC_SM_RESOURCES "resources"
++#define VC_SM_DEBUG "debug"
++#define VC_SM_WRITE_BUF_SIZE 128
++
++/* Statistics tracked per resource and globally.
++*/
++enum SM_STATS_T {
++ /* Attempt. */
++ ALLOC,
++ FREE,
++ LOCK,
++ UNLOCK,
++ MAP,
++ FLUSH,
++ INVALID,
++
++ END_ATTEMPT,
++
++ /* Failure. */
++ ALLOC_FAIL,
++ FREE_FAIL,
++ LOCK_FAIL,
++ UNLOCK_FAIL,
++ MAP_FAIL,
++ FLUSH_FAIL,
++ INVALID_FAIL,
++
++ END_ALL,
++
++};
++
++static const char *const sm_stats_human_read[] = {
++ "Alloc",
++ "Free",
++ "Lock",
++ "Unlock",
++ "Map",
++ "Cache Flush",
++ "Cache Invalidate",
++};
++
++typedef int (*VC_SM_SHOW) (struct seq_file *s, void *v);
++struct SM_PDE_T {
++ VC_SM_SHOW show; /* Debug fs function hookup. */
++ struct dentry *dir_entry; /* Debug fs directory entry. */
++ void *priv_data; /* Private data */
++
++};
++
++/* Single resource allocation tracked for all devices.
++*/
++struct sm_mmap {
++ struct list_head map_list; /* Linked list of maps. */
++
++ struct SM_RESOURCE_T *resource; /* Pointer to the resource. */
++
++ pid_t res_pid; /* PID owning that resource. */
++ unsigned int res_vc_hdl; /* Resource handle (videocore). */
++ unsigned int res_usr_hdl; /* Resource handle (user). */
++
++ long unsigned int res_addr; /* Mapped virtual address. */
++ struct vm_area_struct *vma; /* VM area for this mapping. */
++ unsigned int ref_count; /* Reference count to this vma. */
++
++ /* Used to link maps associated with a resource. */
++ struct list_head resource_map_list;
++};
++
++/* Single resource allocation tracked for each opened device.
++*/
++struct SM_RESOURCE_T {
++ struct list_head resource_list; /* List of resources. */
++ struct list_head global_resource_list; /* Global list of resources. */
++
++ pid_t pid; /* PID owning that resource. */
++ uint32_t res_guid; /* Unique identifier. */
++ uint32_t lock_count; /* Lock count for this resource. */
++ uint32_t ref_count; /* Ref count for this resource. */
++
++ uint32_t res_handle; /* Resource allocation handle. */
++ void *res_base_mem; /* Resource base memory address. */
++ uint32_t res_size; /* Resource size allocated. */
++ enum vmcs_sm_cache_e res_cached; /* Resource cache type. */
++ struct SM_RESOURCE_T *res_shared; /* Shared resource */
++
++ enum SM_STATS_T res_stats[END_ALL]; /* Resource statistics. */
++
++ uint8_t map_count; /* Counter of mappings for this resource. */
++ struct list_head map_list; /* Maps associated with a resource. */
++
++ struct SM_PRIV_DATA_T *private;
++};
++
++/* Private file data associated with each opened device.
++*/
++struct SM_PRIV_DATA_T {
++ struct list_head resource_list; /* List of resources. */
++
++ pid_t pid; /* PID of creator. */
++
++ struct dentry *dir_pid; /* Debug fs entries root. */
++ struct SM_PDE_T dir_stats; /* Debug fs entries statistics sub-tree. */
++ struct SM_PDE_T dir_res; /* Debug fs resource sub-tree. */
++
++ int restart_sys; /* Tracks restart on interrupt. */
++ VC_SM_MSG_TYPE int_action; /* Interrupted action. */
++ uint32_t int_trans_id; /* Interrupted transaction. */
++
++};
++
++/* Global state information.
++*/
++struct SM_STATE_T {
++ VC_VCHI_SM_HANDLE_T sm_handle; /* Handle for videocore service. */
++ struct dentry *dir_root; /* Debug fs entries root. */
++ struct dentry *dir_alloc; /* Debug fs entries allocations. */
++ struct SM_PDE_T dir_stats; /* Debug fs entries statistics sub-tree. */
++ struct SM_PDE_T dir_state; /* Debug fs entries state sub-tree. */
++ struct dentry *debug; /* Debug fs entries debug. */
++
++ struct mutex map_lock; /* Global map lock. */
++ struct list_head map_list; /* List of maps. */
++ struct list_head resource_list; /* List of resources. */
++
++ enum SM_STATS_T deceased[END_ALL]; /* Natural termination stats. */
++ enum SM_STATS_T terminated[END_ALL]; /* Forced termination stats. */
++ uint32_t res_deceased_cnt; /* Natural termination counter. */
++ uint32_t res_terminated_cnt; /* Forced termination counter. */
++
++ struct cdev sm_cdev; /* Device. */
++ dev_t sm_devid; /* Device identifier. */
++ struct class *sm_class; /* Class. */
++ struct device *sm_dev; /* Device. */
++
++ struct SM_PRIV_DATA_T *data_knl; /* Kernel internal data tracking. */
++
++ struct mutex lock; /* Global lock. */
++ uint32_t guid; /* GUID (next) tracker. */
++
++};
++
++/* ---- Private Variables ----------------------------------------------- */
++
++static struct SM_STATE_T *sm_state;
++static int sm_inited;
++
++static const char *const sm_cache_map_vector[] = {
++ "(null)",
++ "host",
++ "videocore",
++ "host+videocore",
++};
++
++/* ---- Private Function Prototypes -------------------------------------- */
++
++/* ---- Private Functions ------------------------------------------------ */
++
++static inline unsigned vcaddr_to_pfn(unsigned long vc_addr)
++{
++ unsigned long pfn = vc_addr & 0x3FFFFFFF;
++ pfn += mm_vc_mem_phys_addr;
++ pfn >>= PAGE_SHIFT;
++ return pfn;
++}
++
++/* Carries over to the state statistics the statistics once owned by a deceased
++** resource.
++*/
++static void vc_sm_resource_deceased(struct SM_RESOURCE_T *p_res, int terminated)
++{
++ if (sm_state != NULL) {
++ if (p_res != NULL) {
++ int ix;
++
++ if (terminated)
++ sm_state->res_terminated_cnt++;
++ else
++ sm_state->res_deceased_cnt++;
++
++ for (ix = 0; ix < END_ALL; ix++) {
++ if (terminated)
++ sm_state->terminated[ix] +=
++ p_res->res_stats[ix];
++ else
++ sm_state->deceased[ix] +=
++ p_res->res_stats[ix];
++ }
++ }
++ }
++}
++
++/* Fetch a videocore handle corresponding to a mapping of the pid+address
++** returns 0 (ie NULL) if no such handle exists in the global map.
++*/
++static unsigned int vmcs_sm_vc_handle_from_pid_and_address(unsigned int pid,
++ unsigned int addr)
++{
++ struct sm_mmap *map = NULL;
++ unsigned int handle = 0;
++
++ if (!sm_state || addr == 0)
++ goto out;
++
++ mutex_lock(&(sm_state->map_lock));
++
++ /* Lookup the resource.
++ */
++ if (!list_empty(&sm_state->map_list)) {
++ list_for_each_entry(map, &sm_state->map_list, map_list) {
++ if (map->res_pid != pid || map->res_addr != addr)
++ continue;
++
++ pr_debug("[%s]: global map %p (pid %u, addr %lx) -> vc-hdl %x (usr-hdl %x)\n",
++ __func__, map, map->res_pid, map->res_addr,
++ map->res_vc_hdl, map->res_usr_hdl);
++
++ handle = map->res_vc_hdl;
++ break;
++ }
++ }
++
++ mutex_unlock(&(sm_state->map_lock));
++
++out:
++ /* Use a debug log here as it may be a valid situation that we query
++ ** for something that is not mapped, we do not want a kernel log each
++ ** time around.
++ **
++ ** There are other error log that would pop up accordingly if someone
++ ** subsequently tries to use something invalid after being told not to
++ ** use it...
++ */
++ if (handle == 0) {
++ pr_debug("[%s]: not a valid map (pid %u, addr %x)\n",
++ __func__, pid, addr);
++ }
++
++ return handle;
++}
++
++/* Fetch a user handle corresponding to a mapping of the pid+address
++** returns 0 (ie NULL) if no such handle exists in the global map.
++*/
++static unsigned int vmcs_sm_usr_handle_from_pid_and_address(unsigned int pid,
++ unsigned int addr)
++{
++ struct sm_mmap *map = NULL;
++ unsigned int handle = 0;
++
++ if (!sm_state || addr == 0)
++ goto out;
++
++ mutex_lock(&(sm_state->map_lock));
++
++ /* Lookup the resource.
++ */
++ if (!list_empty(&sm_state->map_list)) {
++ list_for_each_entry(map, &sm_state->map_list, map_list) {
++ if (map->res_pid != pid || map->res_addr != addr)
++ continue;
++
++ pr_debug("[%s]: global map %p (pid %u, addr %lx) -> usr-hdl %x (vc-hdl %x)\n",
++ __func__, map, map->res_pid, map->res_addr,
++ map->res_usr_hdl, map->res_vc_hdl);
++
++ handle = map->res_usr_hdl;
++ break;
++ }
++ }
++
++ mutex_unlock(&(sm_state->map_lock));
++
++out:
++ /* Use a debug log here as it may be a valid situation that we query
++ * for something that is not mapped yet.
++ *
++ * There are other error log that would pop up accordingly if someone
++ * subsequently tries to use something invalid after being told not to
++ * use it...
++ */
++ if (handle == 0)
++ pr_debug("[%s]: not a valid map (pid %u, addr %x)\n",
++ __func__, pid, addr);
++
++ return handle;
++}
++
++#if defined(DO_NOT_USE)
++/* Fetch an address corresponding to a mapping of the pid+handle
++** returns 0 (ie NULL) if no such address exists in the global map.
++*/
++static unsigned int vmcs_sm_usr_address_from_pid_and_vc_handle(unsigned int pid,
++ unsigned int hdl)
++{
++ struct sm_mmap *map = NULL;
++ unsigned int addr = 0;
++
++ if (sm_state == NULL || hdl == 0)
++ goto out;
++
++ mutex_lock(&(sm_state->map_lock));
++
++ /* Lookup the resource.
++ */
++ if (!list_empty(&sm_state->map_list)) {
++ list_for_each_entry(map, &sm_state->map_list, map_list) {
++ if (map->res_pid != pid || map->res_vc_hdl != hdl)
++ continue;
++
++ pr_debug("[%s]: global map %p (pid %u, vc-hdl %x, usr-hdl %x) -> addr %lx\n",
++ __func__, map, map->res_pid, map->res_vc_hdl,
++ map->res_usr_hdl, map->res_addr);
++
++ addr = map->res_addr;
++ break;
++ }
++ }
++
++ mutex_unlock(&(sm_state->map_lock));
++
++out:
++ /* Use a debug log here as it may be a valid situation that we query
++ ** for something that is not mapped, we do not want a kernel log each
++ ** time around.
++ **
++ ** There are other error log that would pop up accordingly if someone
++ ** subsequently tries to use something invalid after being told not to
++ ** use it...
++ */
++ if (addr == 0)
++ pr_debug("[%s]: not a valid map (pid %u, hdl %x)\n",
++ __func__, pid, hdl);
++
++ return addr;
++}
++#endif
++
++/* Fetch an address corresponding to a mapping of the pid+handle
++** returns 0 (ie NULL) if no such address exists in the global map.
++*/
++static unsigned int vmcs_sm_usr_address_from_pid_and_usr_handle(unsigned int
++ pid,
++ unsigned int
++ hdl)
++{
++ struct sm_mmap *map = NULL;
++ unsigned int addr = 0;
++
++ if (sm_state == NULL || hdl == 0)
++ goto out;
++
++ mutex_lock(&(sm_state->map_lock));
++
++ /* Lookup the resource.
++ */
++ if (!list_empty(&sm_state->map_list)) {
++ list_for_each_entry(map, &sm_state->map_list, map_list) {
++ if (map->res_pid != pid || map->res_usr_hdl != hdl)
++ continue;
++
++ pr_debug("[%s]: global map %p (pid %u, vc-hdl %x, usr-hdl %x) -> addr %lx\n",
++ __func__, map, map->res_pid, map->res_vc_hdl,
++ map->res_usr_hdl, map->res_addr);
++
++ addr = map->res_addr;
++ break;
++ }
++ }
++
++ mutex_unlock(&(sm_state->map_lock));
++
++out:
++ /* Use a debug log here as it may be a valid situation that we query
++ * for something that is not mapped, we do not want a kernel log each
++ * time around.
++ *
++ * There are other error log that would pop up accordingly if someone
++ * subsequently tries to use something invalid after being told not to
++ * use it...
++ */
++ if (addr == 0)
++ pr_debug("[%s]: not a valid map (pid %u, hdl %x)\n", __func__,
++ pid, hdl);
++
++ return addr;
++}
++
++/* Adds a resource mapping to the global data list.
++*/
++static void vmcs_sm_add_map(struct SM_STATE_T *state,
++ struct SM_RESOURCE_T *resource, struct sm_mmap *map)
++{
++ mutex_lock(&(state->map_lock));
++
++ /* Add to the global list of mappings
++ */
++ list_add(&map->map_list, &state->map_list);
++
++ /* Add to the list of mappings for this resource
++ */
++ list_add(&map->resource_map_list, &resource->map_list);
++ resource->map_count++;
++
++ mutex_unlock(&(state->map_lock));
++
++ pr_debug("[%s]: added map %p (pid %u, vc-hdl %x, usr-hdl %x, addr %lx)\n",
++ __func__, map, map->res_pid, map->res_vc_hdl,
++ map->res_usr_hdl, map->res_addr);
++}
++
++/* Removes a resource mapping from the global data list.
++*/
++static void vmcs_sm_remove_map(struct SM_STATE_T *state,
++ struct SM_RESOURCE_T *resource,
++ struct sm_mmap *map)
++{
++ mutex_lock(&(state->map_lock));
++
++ /* Remove from the global list of mappings
++ */
++ list_del(&map->map_list);
++
++ /* Remove from the list of mapping for this resource
++ */
++ list_del(&map->resource_map_list);
++ if (resource->map_count > 0)
++ resource->map_count--;
++
++ mutex_unlock(&(state->map_lock));
++
++ pr_debug("[%s]: removed map %p (pid %d, vc-hdl %x, usr-hdl %x, addr %lx)\n",
++ __func__, map, map->res_pid, map->res_vc_hdl, map->res_usr_hdl,
++ map->res_addr);
++
++ kfree(map);
++}
++
++/* Read callback for the global state proc entry.
++*/
++static int vc_sm_global_state_show(struct seq_file *s, void *v)
++{
++ struct sm_mmap *map = NULL;
++ int map_count = 0;
++
++ if (sm_state == NULL)
++ return 0;
++
++ seq_printf(s, "\nVC-ServiceHandle 0x%x\n",
++ (unsigned int)sm_state->sm_handle);
++
++ /* Log all applicable mapping(s).
++ */
++
++ mutex_lock(&(sm_state->map_lock));
++
++ if (!list_empty(&sm_state->map_list)) {
++ list_for_each_entry(map, &sm_state->map_list, map_list) {
++ map_count++;
++
++ seq_printf(s, "\nMapping 0x%x\n",
++ (unsigned int)map);
++ seq_printf(s, " TGID %u\n",
++ map->res_pid);
++ seq_printf(s, " VC-HDL 0x%x\n",
++ map->res_vc_hdl);
++ seq_printf(s, " USR-HDL 0x%x\n",
++ map->res_usr_hdl);
++ seq_printf(s, " USR-ADDR 0x%lx\n",
++ map->res_addr);
++ }
++ }
++
++ mutex_unlock(&(sm_state->map_lock));
++ seq_printf(s, "\n\nTotal map count: %d\n\n", map_count);
++
++ return 0;
++}
++
++static int vc_sm_global_statistics_show(struct seq_file *s, void *v)
++{
++ int ix;
++
++ /* Global state tracked statistics.
++ */
++ if (sm_state != NULL) {
++ seq_puts(s, "\nDeceased Resources Statistics\n");
++
++ seq_printf(s, "\nNatural Cause (%u occurences)\n",
++ sm_state->res_deceased_cnt);
++ for (ix = 0; ix < END_ATTEMPT; ix++) {
++ if (sm_state->deceased[ix] > 0) {
++ seq_printf(s, " %u\t%s\n",
++ sm_state->deceased[ix],
++ sm_stats_human_read[ix]);
++ }
++ }
++ seq_puts(s, "\n");
++ for (ix = 0; ix < END_ATTEMPT; ix++) {
++ if (sm_state->deceased[ix + END_ATTEMPT] > 0) {
++ seq_printf(s, " %u\tFAILED %s\n",
++ sm_state->deceased[ix + END_ATTEMPT],
++ sm_stats_human_read[ix]);
++ }
++ }
++
++ seq_printf(s, "\nForcefull (%u occurences)\n",
++ sm_state->res_terminated_cnt);
++ for (ix = 0; ix < END_ATTEMPT; ix++) {
++ if (sm_state->terminated[ix] > 0) {
++ seq_printf(s, " %u\t%s\n",
++ sm_state->terminated[ix],
++ sm_stats_human_read[ix]);
++ }
++ }
++ seq_puts(s, "\n");
++ for (ix = 0; ix < END_ATTEMPT; ix++) {
++ if (sm_state->terminated[ix + END_ATTEMPT] > 0) {
++ seq_printf(s, " %u\tFAILED %s\n",
++ sm_state->terminated[ix +
++ END_ATTEMPT],
++ sm_stats_human_read[ix]);
++ }
++ }
++ }
++
++ return 0;
++}
++
++#if 0
++/* Read callback for the statistics proc entry.
++*/
++static int vc_sm_statistics_show(struct seq_file *s, void *v)
++{
++ int ix;
++ struct SM_PRIV_DATA_T *file_data;
++ struct SM_RESOURCE_T *resource;
++ int res_count = 0;
++ struct SM_PDE_T *p_pde;
++
++ p_pde = (struct SM_PDE_T *)(s->private);
++ file_data = (struct SM_PRIV_DATA_T *)(p_pde->priv_data);
++
++ if (file_data == NULL)
++ return 0;
++
++ /* Per process statistics.
++ */
++
++ seq_printf(s, "\nStatistics for TGID %d\n", file_data->pid);
++
++ mutex_lock(&(sm_state->map_lock));
++
++ if (!list_empty(&file_data->resource_list)) {
++ list_for_each_entry(resource, &file_data->resource_list,
++ resource_list) {
++ res_count++;
++
++ seq_printf(s, "\nGUID: 0x%x\n\n",
++ resource->res_guid);
++ for (ix = 0; ix < END_ATTEMPT; ix++) {
++ if (resource->res_stats[ix] > 0) {
++ seq_printf(s,
++ " %u\t%s\n",
++ resource->res_stats[ix],
++ sm_stats_human_read[ix]);
++ }
++ }
++ seq_puts(s, "\n");
++ for (ix = 0; ix < END_ATTEMPT; ix++) {
++ if (resource->res_stats[ix + END_ATTEMPT] > 0) {
++ seq_printf(s,
++ " %u\tFAILED %s\n",
++ resource->res_stats[
++ ix + END_ATTEMPT],
++ sm_stats_human_read[ix]);
++ }
++ }
++ }
++ }
++
++ mutex_unlock(&(sm_state->map_lock));
++
++ seq_printf(s, "\nResources Count %d\n", res_count);
++
++ return 0;
++}
++#endif
++
++#if 0
++/* Read callback for the allocation proc entry. */
++static int vc_sm_alloc_show(struct seq_file *s, void *v)
++{
++ struct SM_PRIV_DATA_T *file_data;
++ struct SM_RESOURCE_T *resource;
++ int alloc_count = 0;
++ struct SM_PDE_T *p_pde;
++
++ p_pde = (struct SM_PDE_T *)(s->private);
++ file_data = (struct SM_PRIV_DATA_T *)(p_pde->priv_data);
++
++ if (!file_data)
++ return 0;
++
++ /* Per process statistics. */
++ seq_printf(s, "\nAllocation for TGID %d\n", file_data->pid);
++
++ mutex_lock(&(sm_state->map_lock));
++
++ if (!list_empty(&file_data->resource_list)) {
++ list_for_each_entry(resource, &file_data->resource_list,
++ resource_list) {
++ alloc_count++;
++
++ seq_printf(s, "\nGUID: 0x%x\n",
++ resource->res_guid);
++ seq_printf(s, "Lock Count: %u\n",
++ resource->lock_count);
++ seq_printf(s, "Mapped: %s\n",
++ (resource->map_count ? "yes" : "no"));
++ seq_printf(s, "VC-handle: 0x%x\n",
++ resource->res_handle);
++ seq_printf(s, "VC-address: 0x%p\n",
++ resource->res_base_mem);
++ seq_printf(s, "VC-size (bytes): %u\n",
++ resource->res_size);
++ seq_printf(s, "Cache: %s\n",
++ sm_cache_map_vector[resource->res_cached]);
++ }
++ }
++
++ mutex_unlock(&(sm_state->map_lock));
++
++ seq_printf(s, "\n\nTotal allocation count: %d\n\n", alloc_count);
++
++ return 0;
++}
++#endif
++
++static int vc_sm_seq_file_show(struct seq_file *s, void *v)
++{
++ struct SM_PDE_T *sm_pde;
++
++ sm_pde = (struct SM_PDE_T *)(s->private);
++
++ if (sm_pde && sm_pde->show)
++ sm_pde->show(s, v);
++
++ return 0;
++}
++
++static int vc_sm_single_open(struct inode *inode, struct file *file)
++{
++ return single_open(file, vc_sm_seq_file_show, inode->i_private);
++}
++
++static const struct file_operations vc_sm_debug_fs_fops = {
++ .open = vc_sm_single_open,
++ .read = seq_read,
++ .llseek = seq_lseek,
++ .release = single_release,
++};
++
++/* Adds a resource to the private data list which tracks all the allocated
++** data.
++*/
++static void vmcs_sm_add_resource(struct SM_PRIV_DATA_T *privdata,
++ struct SM_RESOURCE_T *resource)
++{
++ mutex_lock(&(sm_state->map_lock));
++ list_add(&resource->resource_list, &privdata->resource_list);
++ list_add(&resource->global_resource_list, &sm_state->resource_list);
++ mutex_unlock(&(sm_state->map_lock));
++
++ pr_debug("[%s]: added resource %p (base addr %p, hdl %x, size %u, cache %u)\n",
++ __func__, resource, resource->res_base_mem,
++ resource->res_handle, resource->res_size, resource->res_cached);
++}
++
++/* Locates a resource and acquire a reference on it.
++** The resource won't be deleted while there is a reference on it.
++*/
++static struct SM_RESOURCE_T *vmcs_sm_acquire_resource(struct SM_PRIV_DATA_T
++ *private,
++ unsigned int res_guid)
++{
++ struct SM_RESOURCE_T *resource, *ret = NULL;
++
++ mutex_lock(&(sm_state->map_lock));
++
++ list_for_each_entry(resource, &private->resource_list, resource_list) {
++ if (resource->res_guid != res_guid)
++ continue;
++
++ pr_debug("[%s]: located resource %p (guid: %x, base addr %p, hdl %x, size %u, cache %u)\n",
++ __func__, resource, resource->res_guid,
++ resource->res_base_mem, resource->res_handle,
++ resource->res_size, resource->res_cached);
++ resource->ref_count++;
++ ret = resource;
++ break;
++ }
++
++ mutex_unlock(&(sm_state->map_lock));
++
++ return ret;
++}
++
++/* Locates a resource and acquire a reference on it.
++** The resource won't be deleted while there is a reference on it.
++*/
++static struct SM_RESOURCE_T *vmcs_sm_acquire_first_resource(
++ struct SM_PRIV_DATA_T *private)
++{
++ struct SM_RESOURCE_T *resource, *ret = NULL;
++
++ mutex_lock(&(sm_state->map_lock));
++
++ list_for_each_entry(resource, &private->resource_list, resource_list) {
++ pr_debug("[%s]: located resource %p (guid: %x, base addr %p, hdl %x, size %u, cache %u)\n",
++ __func__, resource, resource->res_guid,
++ resource->res_base_mem, resource->res_handle,
++ resource->res_size, resource->res_cached);
++ resource->ref_count++;
++ ret = resource;
++ break;
++ }
++
++ mutex_unlock(&(sm_state->map_lock));
++
++ return ret;
++}
++
++/* Locates a resource and acquire a reference on it.
++** The resource won't be deleted while there is a reference on it.
++*/
++static struct SM_RESOURCE_T *vmcs_sm_acquire_global_resource(unsigned int
++ res_guid)
++{
++ struct SM_RESOURCE_T *resource, *ret = NULL;
++
++ mutex_lock(&(sm_state->map_lock));
++
++ list_for_each_entry(resource, &sm_state->resource_list,
++ global_resource_list) {
++ if (resource->res_guid != res_guid)
++ continue;
++
++ pr_debug("[%s]: located resource %p (guid: %x, base addr %p, hdl %x, size %u, cache %u)\n",
++ __func__, resource, resource->res_guid,
++ resource->res_base_mem, resource->res_handle,
++ resource->res_size, resource->res_cached);
++ resource->ref_count++;
++ ret = resource;
++ break;
++ }
++
++ mutex_unlock(&(sm_state->map_lock));
++
++ return ret;
++}
++
++/* Release a previously acquired resource.
++** The resource will be deleted when its refcount reaches 0.
++*/
++static void vmcs_sm_release_resource(struct SM_RESOURCE_T *resource, int force)
++{
++ struct SM_PRIV_DATA_T *private = resource->private;
++ struct sm_mmap *map, *map_tmp;
++ struct SM_RESOURCE_T *res_tmp;
++ int ret;
++
++ mutex_lock(&(sm_state->map_lock));
++
++ if (--resource->ref_count) {
++ if (force)
++ pr_err("[%s]: resource %p in use\n", __func__, resource);
++
++ mutex_unlock(&(sm_state->map_lock));
++ return;
++ }
++
++ /* Time to free the resource. Start by removing it from the list */
++ list_del(&resource->resource_list);
++ list_del(&resource->global_resource_list);
++
++ /* Walk the global resource list, find out if the resource is used
++ * somewhere else. In which case we don't want to delete it.
++ */
++ list_for_each_entry(res_tmp, &sm_state->resource_list,
++ global_resource_list) {
++ if (res_tmp->res_handle == resource->res_handle) {
++ resource->res_handle = 0;
++ break;
++ }
++ }
++
++ mutex_unlock(&(sm_state->map_lock));
++
++ pr_debug("[%s]: freeing data - guid %x, hdl %x, base address %p\n",
++ __func__, resource->res_guid, resource->res_handle,
++ resource->res_base_mem);
++ resource->res_stats[FREE]++;
++
++ /* Make sure the resource we're removing is unmapped first */
++ if (resource->map_count && !list_empty(&resource->map_list)) {
++ down_write(&current->mm->mmap_sem);
++ list_for_each_entry_safe(map, map_tmp, &resource->map_list,
++ resource_map_list) {
++ ret =
++ do_munmap(current->mm, map->res_addr,
++ resource->res_size);
++ if (ret) {
++ pr_err("[%s]: could not unmap resource %p\n",
++ __func__, resource);
++ }
++ }
++ up_write(&current->mm->mmap_sem);
++ }
++
++ /* Free up the videocore allocated resource.
++ */
++ if (resource->res_handle) {
++ VC_SM_FREE_T free = {
++ resource->res_handle, resource->res_base_mem
++ };
++ int status = vc_vchi_sm_free(sm_state->sm_handle, &free,
++ &private->int_trans_id);
++ if (status != 0 && status != -EINTR) {
++ pr_err("[%s]: failed to free memory on videocore (status: %u, trans_id: %u)\n",
++ __func__, status, private->int_trans_id);
++ resource->res_stats[FREE_FAIL]++;
++ ret = -EPERM;
++ }
++ }
++
++ /* Free up the shared resource.
++ */
++ if (resource->res_shared)
++ vmcs_sm_release_resource(resource->res_shared, 0);
++
++ /* Free up the local resource tracking this allocation.
++ */
++ vc_sm_resource_deceased(resource, force);
++ kfree(resource);
++}
++
++/* Dump the map table for the driver. If process is -1, dumps the whole table,
++** if process is a valid pid (non -1) dump only the entries associated with the
++** pid of interest.
++*/
++static void vmcs_sm_host_walk_map_per_pid(int pid)
++{
++ struct sm_mmap *map = NULL;
++
++ /* Make sure the device was started properly.
++ */
++ if (sm_state == NULL) {
++ pr_err("[%s]: invalid device\n", __func__);
++ return;
++ }
++
++ mutex_lock(&(sm_state->map_lock));
++
++ /* Log all applicable mapping(s).
++ */
++ if (!list_empty(&sm_state->map_list)) {
++ list_for_each_entry(map, &sm_state->map_list, map_list) {
++ if (pid == -1 || map->res_pid == pid) {
++ pr_info("[%s]: tgid: %u - vc-hdl: %x, usr-hdl: %x, usr-addr: %lx\n",
++ __func__, map->res_pid, map->res_vc_hdl,
++ map->res_usr_hdl, map->res_addr);
++ }
++ }
++ }
++
++ mutex_unlock(&(sm_state->map_lock));
++
++ return;
++}
++
++/* Dump the allocation table from host side point of view. This only dumps the
++** data allocated for this process/device referenced by the file_data.
++*/
++static void vmcs_sm_host_walk_alloc(struct SM_PRIV_DATA_T *file_data)
++{
++ struct SM_RESOURCE_T *resource = NULL;
++
++ /* Make sure the device was started properly.
++ */
++ if ((sm_state == NULL) || (file_data == NULL)) {
++ pr_err("[%s]: invalid device\n", __func__);
++ return;
++ }
++
++ mutex_lock(&(sm_state->map_lock));
++
++ if (!list_empty(&file_data->resource_list)) {
++ list_for_each_entry(resource, &file_data->resource_list,
++ resource_list) {
++ pr_info("[%s]: guid: %x - hdl: %x, vc-mem: %p, size: %u, cache: %u\n",
++ __func__, resource->res_guid, resource->res_handle,
++ resource->res_base_mem, resource->res_size,
++ resource->res_cached);
++ }
++ }
++
++ mutex_unlock(&(sm_state->map_lock));
++
++ return;
++}
++
++/* Create support for private data tracking.
++*/
++static struct SM_PRIV_DATA_T *vc_sm_create_priv_data(pid_t id)
++{
++ char alloc_name[32];
++ struct SM_PRIV_DATA_T *file_data = NULL;
++
++ /* Allocate private structure. */
++ file_data = kzalloc(sizeof(*file_data), GFP_KERNEL);
++
++ if (!file_data) {
++ pr_err("[%s]: cannot allocate file data\n", __func__);
++ goto out;
++ }
++
++ snprintf(alloc_name, sizeof(alloc_name), "%d", id);
++
++ INIT_LIST_HEAD(&file_data->resource_list);
++ file_data->pid = id;
++ file_data->dir_pid = debugfs_create_dir(alloc_name,
++ sm_state->dir_alloc);
++#if 0
++ /* TODO: fix this to support querying statistics per pid */
++
++ if (IS_ERR_OR_NULL(file_data->dir_pid)) {
++ file_data->dir_pid = NULL;
++ } else {
++ struct dentry *dir_entry;
++
++ dir_entry = debugfs_create_file(VC_SM_RESOURCES, S_IRUGO,
++ file_data->dir_pid, file_data,
++ vc_sm_debug_fs_fops);
++
++ file_data->dir_res.dir_entry = dir_entry;
++ file_data->dir_res.priv_data = file_data;
++ file_data->dir_res.show = &vc_sm_alloc_show;
++
++ dir_entry = debugfs_create_file(VC_SM_STATS, S_IRUGO,
++ file_data->dir_pid, file_data,
++ vc_sm_debug_fs_fops);
++
++ file_data->dir_res.dir_entry = dir_entry;
++ file_data->dir_res.priv_data = file_data;
++ file_data->dir_res.show = &vc_sm_statistics_show;
++ }
++ pr_debug("[%s]: private data allocated %p\n", __func__, file_data);
++
++#endif
++out:
++ return file_data;
++}
++
++/* Open the device. Creates a private state to help track all allocation
++** associated with this device.
++*/
++static int vc_sm_open(struct inode *inode, struct file *file)
++{
++ int ret = 0;
++
++ /* Make sure the device was started properly.
++ */
++ if (!sm_state) {
++ pr_err("[%s]: invalid device\n", __func__);
++ ret = -EPERM;
++ goto out;
++ }
++
++ file->private_data = vc_sm_create_priv_data(current->tgid);
++ if (file->private_data == NULL) {
++ pr_err("[%s]: failed to create data tracker\n", __func__);
++
++ ret = -ENOMEM;
++ goto out;
++ }
++
++out:
++ return ret;
++}
++
++/* Close the device. Free up all resources still associated with this device
++** at the time.
++*/
++static int vc_sm_release(struct inode *inode, struct file *file)
++{
++ struct SM_PRIV_DATA_T *file_data =
++ (struct SM_PRIV_DATA_T *)file->private_data;
++ struct SM_RESOURCE_T *resource;
++ int ret = 0;
++
++ /* Make sure the device was started properly.
++ */
++ if (sm_state == NULL || file_data == NULL) {
++ pr_err("[%s]: invalid device\n", __func__);
++ ret = -EPERM;
++ goto out;
++ }
++
++ pr_debug("[%s]: using private data %p\n", __func__, file_data);
++
++ if (file_data->restart_sys == -EINTR) {
++ VC_SM_ACTION_CLEAN_T action_clean;
++
++ pr_debug("[%s]: releasing following EINTR on %u (trans_id: %u) (likely due to signal)...\n",
++ __func__, file_data->int_action,
++ file_data->int_trans_id);
++
++ action_clean.res_action = file_data->int_action;
++ action_clean.action_trans_id = file_data->int_trans_id;
++
++ vc_vchi_sm_clean_up(sm_state->sm_handle, &action_clean);
++ }
++
++ while ((resource = vmcs_sm_acquire_first_resource(file_data)) != NULL) {
++ vmcs_sm_release_resource(resource, 0);
++ vmcs_sm_release_resource(resource, 1);
++ }
++
++ /* Remove the corresponding proc entry. */
++ debugfs_remove_recursive(file_data->dir_pid);
++
++ /* Terminate the private data.
++ */
++ kfree(file_data);
++
++out:
++ return ret;
++}
++
++static void vcsm_vma_open(struct vm_area_struct *vma)
++{
++ struct sm_mmap *map = (struct sm_mmap *)vma->vm_private_data;
++
++ pr_debug("[%s]: virt %lx-%lx, pid %i, pfn %i\n",
++ __func__, vma->vm_start, vma->vm_end, (int)current->tgid,
++ (int)vma->vm_pgoff);
++
++ map->ref_count++;
++}
++
++static void vcsm_vma_close(struct vm_area_struct *vma)
++{
++ struct sm_mmap *map = (struct sm_mmap *)vma->vm_private_data;
++
++ pr_debug("[%s]: virt %lx-%lx, pid %i, pfn %i\n",
++ __func__, vma->vm_start, vma->vm_end, (int)current->tgid,
++ (int)vma->vm_pgoff);
++
++ map->ref_count--;
++
++ /* Remove from the map table.
++ */
++ if (map->ref_count == 0)
++ vmcs_sm_remove_map(sm_state, map->resource, map);
++}
++
++static int vcsm_vma_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
++{
++ struct sm_mmap *map = (struct sm_mmap *)vma->vm_private_data;
++ struct SM_RESOURCE_T *resource = map->resource;
++ pgoff_t page_offset;
++ unsigned long pfn;
++ int ret = 0;
++
++ /* Lock the resource if necessary.
++ */
++ if (!resource->lock_count) {
++ VC_SM_LOCK_UNLOCK_T lock_unlock;
++ VC_SM_LOCK_RESULT_T lock_result;
++ int status;
++
++ lock_unlock.res_handle = resource->res_handle;
++ lock_unlock.res_mem = resource->res_base_mem;
++
++ pr_debug("[%s]: attempt to lock data - hdl %x, base address %p\n",
++ __func__, lock_unlock.res_handle, lock_unlock.res_mem);
++
++ /* Lock the videocore allocated resource.
++ */
++ status = vc_vchi_sm_lock(sm_state->sm_handle,
++ &lock_unlock, &lock_result, 0);
++ if ((status != 0) ||
++ ((status == 0) && (lock_result.res_mem == NULL))) {
++ pr_err("[%s]: failed to lock memory on videocore (status: %u)\n",
++ __func__, status);
++ resource->res_stats[LOCK_FAIL]++;
++ return VM_FAULT_SIGBUS;
++ }
++
++ pfn = vcaddr_to_pfn((unsigned long)resource->res_base_mem);
++ outer_inv_range(__pfn_to_phys(pfn),
++ __pfn_to_phys(pfn) + resource->res_size);
++
++ resource->res_stats[LOCK]++;
++ resource->lock_count++;
++
++ /* Keep track of the new base memory.
++ */
++ if ((lock_result.res_mem != NULL) &&
++ (lock_result.res_old_mem != NULL) &&
++ (lock_result.res_mem != lock_result.res_old_mem)) {
++ resource->res_base_mem = lock_result.res_mem;
++ }
++ }
++
++ /* We don't use vmf->pgoff since that has the fake offset */
++ page_offset = ((unsigned long)vmf->virtual_address - vma->vm_start);
++ pfn = (uint32_t)resource->res_base_mem & 0x3FFFFFFF;
++ pfn += mm_vc_mem_phys_addr;
++ pfn += page_offset;
++ pfn >>= PAGE_SHIFT;
++
++ /* Finally, remap it */
++ ret = vm_insert_pfn(vma, (unsigned long)vmf->virtual_address, pfn);
++
++ switch (ret) {
++ case 0:
++ case -ERESTARTSYS:
++ return VM_FAULT_NOPAGE;
++ case -ENOMEM:
++ case -EAGAIN:
++ return VM_FAULT_OOM;
++ default:
++ return VM_FAULT_SIGBUS;
++ }
++}
++
++static struct vm_operations_struct vcsm_vm_ops = {
++ .open = vcsm_vma_open,
++ .close = vcsm_vma_close,
++ .fault = vcsm_vma_fault,
++};
++
++/* Walks a VMA and clean each valid page from the cache */
++static void vcsm_vma_cache_clean_page_range(unsigned long addr,
++ unsigned long end)
++{
++ pgd_t *pgd;
++ pud_t *pud;
++ pmd_t *pmd;
++ pte_t *pte;
++ unsigned long pgd_next, pud_next, pmd_next;
++
++ if (addr >= end)
++ return;
++
++ /* Walk PGD */
++ pgd = pgd_offset(current->mm, addr);
++ do {
++ pgd_next = pgd_addr_end(addr, end);
++
++ if (pgd_none(*pgd) || pgd_bad(*pgd))
++ continue;
++
++ /* Walk PUD */
++ pud = pud_offset(pgd, addr);
++ do {
++ pud_next = pud_addr_end(addr, pgd_next);
++ if (pud_none(*pud) || pud_bad(*pud))
++ continue;
++
++ /* Walk PMD */
++ pmd = pmd_offset(pud, addr);
++ do {
++ pmd_next = pmd_addr_end(addr, pud_next);
++ if (pmd_none(*pmd) || pmd_bad(*pmd))
++ continue;
++
++ /* Walk PTE */
++ pte = pte_offset_map(pmd, addr);
++ do {
++ if (pte_none(*pte)
++ || !pte_present(*pte))
++ continue;
++
++ /* Clean + invalidate */
++ dmac_flush_range((const void *) addr,
++ (const void *)
++ (addr + PAGE_SIZE));
++
++ } while (pte++, addr +=
++ PAGE_SIZE, addr != pmd_next);
++ pte_unmap(pte);
++
++ } while (pmd++, addr = pmd_next, addr != pud_next);
++
++ } while (pud++, addr = pud_next, addr != pgd_next);
++ } while (pgd++, addr = pgd_next, addr != end);
++}
++
++/* Map an allocated data into something that the user space.
++*/
++static int vc_sm_mmap(struct file *file, struct vm_area_struct *vma)
++{
++ int ret = 0;
++ struct SM_PRIV_DATA_T *file_data =
++ (struct SM_PRIV_DATA_T *)file->private_data;
++ struct SM_RESOURCE_T *resource = NULL;
++ struct sm_mmap *map = NULL;
++
++ /* Make sure the device was started properly.
++ */
++ if ((sm_state == NULL) || (file_data == NULL)) {
++ pr_err("[%s]: invalid device\n", __func__);
++ return -EPERM;
++ }
++
++ pr_debug("[%s]: private data %p, guid %x\n", __func__, file_data,
++ ((unsigned int)vma->vm_pgoff << PAGE_SHIFT));
++
++ /* We lookup to make sure that the data we are being asked to mmap is
++ ** something that we allocated.
++ **
++ ** We use the offset information as the key to tell us which resource
++ ** we are mapping.
++ */
++ resource = vmcs_sm_acquire_resource(file_data,
++ ((unsigned int)vma->vm_pgoff <<
++ PAGE_SHIFT));
++ if (resource == NULL) {
++ pr_err("[%s]: failed to locate resource for guid %x\n", __func__,
++ ((unsigned int)vma->vm_pgoff << PAGE_SHIFT));
++ return -ENOMEM;
++ }
++
++ pr_debug("[%s]: guid %x, tgid %u, %u, %u\n",
++ __func__, resource->res_guid, current->tgid, resource->pid,
++ file_data->pid);
++
++ /* Check permissions.
++ */
++ if (resource->pid && (resource->pid != current->tgid)) {
++ pr_err("[%s]: current tgid %u != %u owner\n",
++ __func__, current->tgid, resource->pid);
++ ret = -EPERM;
++ goto error;
++ }
++
++ /* Verify that what we are asked to mmap is proper.
++ */
++ if (resource->res_size != (unsigned int)(vma->vm_end - vma->vm_start)) {
++ pr_err("[%s]: size inconsistency (resource: %u - mmap: %u)\n",
++ __func__,
++ resource->res_size,
++ (unsigned int)(vma->vm_end - vma->vm_start));
++
++ ret = -EINVAL;
++ goto error;
++ }
++
++ /* Keep track of the tuple in the global resource list such that one
++ * can do a mapping lookup for address/memory handle.
++ */
++ map = kzalloc(sizeof(*map), GFP_KERNEL);
++ if (map == NULL) {
++ pr_err("[%s]: failed to allocate global tracking resource\n",
++ __func__);
++ ret = -ENOMEM;
++ goto error;
++ }
++
++ map->res_pid = current->tgid;
++ map->res_vc_hdl = resource->res_handle;
++ map->res_usr_hdl = resource->res_guid;
++ map->res_addr = (long unsigned int)vma->vm_start;
++ map->resource = resource;
++ map->vma = vma;
++ vmcs_sm_add_map(sm_state, resource, map);
++
++ /* We are not actually mapping the pages, we just provide a fault
++ ** handler to allow pages to be mapped when accessed
++ */
++ vma->vm_flags |=
++ VM_IO | VM_PFNMAP | VM_DONTCOPY | VM_DONTEXPAND;
++ vma->vm_ops = &vcsm_vm_ops;
++ vma->vm_private_data = map;
++
++ /* vm_pgoff is the first PFN of the mapped memory */
++ vma->vm_pgoff = (unsigned long)resource->res_base_mem & 0x3FFFFFFF;
++ vma->vm_pgoff += mm_vc_mem_phys_addr;
++ vma->vm_pgoff >>= PAGE_SHIFT;
++
++ if ((resource->res_cached == VMCS_SM_CACHE_NONE) ||
++ (resource->res_cached == VMCS_SM_CACHE_VC)) {
++ /* Allocated non host cached memory, honour it.
++ */
++ vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
++ }
++
++ pr_debug("[%s]: resource %p (guid %x) - cnt %u, base address %p, handle %x, size %u (%u), cache %u\n",
++ __func__,
++ resource, resource->res_guid, resource->lock_count,
++ resource->res_base_mem, resource->res_handle,
++ resource->res_size, (unsigned int)(vma->vm_end - vma->vm_start),
++ resource->res_cached);
++
++ pr_debug("[%s]: resource %p (base address %p, handle %x) - map-count %d, usr-addr %x\n",
++ __func__, resource, resource->res_base_mem,
++ resource->res_handle, resource->map_count,
++ (unsigned int)vma->vm_start);
++
++ vcsm_vma_open(vma);
++ resource->res_stats[MAP]++;
++ vmcs_sm_release_resource(resource, 0);
++ return 0;
++
++error:
++ vmcs_sm_release_resource(resource, 0);
++ resource->res_stats[MAP_FAIL]++;
++ return ret;
++}
++
++/* Allocate a shared memory handle and block.
++*/
++int vc_sm_ioctl_alloc(struct SM_PRIV_DATA_T *private,
++ struct vmcs_sm_ioctl_alloc *ioparam)
++{
++ int ret = 0;
++ int status;
++ struct SM_RESOURCE_T *resource;
++ VC_SM_ALLOC_T alloc = { 0 };
++ VC_SM_ALLOC_RESULT_T result = { 0 };
++
++ /* Setup our allocation parameters */
++ alloc.type = ((ioparam->cached == VMCS_SM_CACHE_VC)
++ || (ioparam->cached ==
++ VMCS_SM_CACHE_BOTH)) ? VC_SM_ALLOC_CACHED :
++ VC_SM_ALLOC_NON_CACHED;
++ alloc.base_unit = ioparam->size;
++ alloc.num_unit = ioparam->num;
++ alloc.allocator = current->tgid;
++ /* Align to kernel page size */
++ alloc.alignement = 4096;
++ /* Align the size to the kernel page size */
++ alloc.base_unit =
++ (alloc.base_unit + alloc.alignement - 1) & ~(alloc.alignement - 1);
++ if (*ioparam->name) {
++ memcpy(alloc.name, ioparam->name, sizeof(alloc.name) - 1);
++ } else {
++ memcpy(alloc.name, VMCS_SM_RESOURCE_NAME_DEFAULT,
++ sizeof(VMCS_SM_RESOURCE_NAME_DEFAULT));
++ }
++
++ pr_debug("[%s]: attempt to allocate \"%s\" data - type %u, base %u (%u), num %u, alignement %u\n",
++ __func__, alloc.name, alloc.type, ioparam->size,
++ alloc.base_unit, alloc.num_unit, alloc.alignement);
++
++ /* Allocate local resource to track this allocation.
++ */
++ resource = kzalloc(sizeof(*resource), GFP_KERNEL);
++ if (!resource) {
++ ret = -ENOMEM;
++ goto error;
++ }
++ INIT_LIST_HEAD(&resource->map_list);
++ resource->ref_count++;
++ resource->pid = current->tgid;
++
++ /* Allocate the videocore resource.
++ */
++ status = vc_vchi_sm_alloc(sm_state->sm_handle, &alloc, &result,
++ &private->int_trans_id);
++ if (status == -EINTR) {
++ pr_debug("[%s]: requesting allocate memory action restart (trans_id: %u)\n",
++ __func__, private->int_trans_id);
++ ret = -ERESTARTSYS;
++ private->restart_sys = -EINTR;
++ private->int_action = VC_SM_MSG_TYPE_ALLOC;
++ goto error;
++ } else if (status != 0 || (status == 0 && result.res_mem == NULL)) {
++ pr_err("[%s]: failed to allocate memory on videocore (status: %u, trans_id: %u)\n",
++ __func__, status, private->int_trans_id);
++ ret = -ENOMEM;
++ resource->res_stats[ALLOC_FAIL]++;
++ goto error;
++ }
++
++ /* Keep track of the resource we created.
++ */
++ resource->private = private;
++ resource->res_handle = result.res_handle;
++ resource->res_base_mem = result.res_mem;
++ resource->res_size = alloc.base_unit * alloc.num_unit;
++ resource->res_cached = ioparam->cached;
++
++ /* Kernel/user GUID. This global identifier is used for mmap'ing the
++ * allocated region from user space, it is passed as the mmap'ing
++ * offset, we use it to 'hide' the videocore handle/address.
++ */
++ mutex_lock(&sm_state->lock);
++ resource->res_guid = ++sm_state->guid;
++ mutex_unlock(&sm_state->lock);
++ resource->res_guid <<= PAGE_SHIFT;
++
++ vmcs_sm_add_resource(private, resource);
++
++ pr_debug("[%s]: allocated data - guid %x, hdl %x, base address %p, size %d, cache %d\n",
++ __func__, resource->res_guid, resource->res_handle,
++ resource->res_base_mem, resource->res_size,
++ resource->res_cached);
++
++ /* We're done */
++ resource->res_stats[ALLOC]++;
++ ioparam->handle = resource->res_guid;
++ return 0;
++
++error:
++ pr_err("[%s]: failed to allocate \"%s\" data (%i) - type %u, base %u (%u), num %u, alignment %u\n",
++ __func__, alloc.name, ret, alloc.type, ioparam->size,
++ alloc.base_unit, alloc.num_unit, alloc.alignement);
++ if (resource != NULL) {
++ vc_sm_resource_deceased(resource, 1);
++ kfree(resource);
++ }
++ return ret;
++}
++
++/* Share an allocate memory handle and block.
++*/
++int vc_sm_ioctl_alloc_share(struct SM_PRIV_DATA_T *private,
++ struct vmcs_sm_ioctl_alloc_share *ioparam)
++{
++ struct SM_RESOURCE_T *resource, *shared_resource;
++ int ret = 0;
++
++ pr_debug("[%s]: attempt to share resource %u\n", __func__,
++ ioparam->handle);
++
++ shared_resource = vmcs_sm_acquire_global_resource(ioparam->handle);
++ if (shared_resource == NULL) {
++ ret = -ENOMEM;
++ goto error;
++ }
++
++ /* Allocate local resource to track this allocation.
++ */
++ resource = kzalloc(sizeof(*resource), GFP_KERNEL);
++ if (resource == NULL) {
++ pr_err("[%s]: failed to allocate local tracking resource\n",
++ __func__);
++ ret = -ENOMEM;
++ goto error;
++ }
++ INIT_LIST_HEAD(&resource->map_list);
++ resource->ref_count++;
++ resource->pid = current->tgid;
++
++ /* Keep track of the resource we created.
++ */
++ resource->private = private;
++ resource->res_handle = shared_resource->res_handle;
++ resource->res_base_mem = shared_resource->res_base_mem;
++ resource->res_size = shared_resource->res_size;
++ resource->res_cached = shared_resource->res_cached;
++ resource->res_shared = shared_resource;
++
++ mutex_lock(&sm_state->lock);
++ resource->res_guid = ++sm_state->guid;
++ mutex_unlock(&sm_state->lock);
++ resource->res_guid <<= PAGE_SHIFT;
++
++ vmcs_sm_add_resource(private, resource);
++
++ pr_debug("[%s]: allocated data - guid %x, hdl %x, base address %p, size %d, cache %d\n",
++ __func__, resource->res_guid, resource->res_handle,
++ resource->res_base_mem, resource->res_size,
++ resource->res_cached);
++
++ /* We're done */
++ resource->res_stats[ALLOC]++;
++ ioparam->handle = resource->res_guid;
++ ioparam->size = resource->res_size;
++ return 0;
++
++error:
++ pr_err("[%s]: failed to share %u\n", __func__, ioparam->handle);
++ if (shared_resource != NULL)
++ vmcs_sm_release_resource(shared_resource, 0);
++
++ return ret;
++}
++
++/* Free a previously allocated shared memory handle and block.
++*/
++static int vc_sm_ioctl_free(struct SM_PRIV_DATA_T *private,
++ struct vmcs_sm_ioctl_free *ioparam)
++{
++ struct SM_RESOURCE_T *resource =
++ vmcs_sm_acquire_resource(private, ioparam->handle);
++
++ if (resource == NULL) {
++ pr_err("[%s]: resource for guid %u does not exist\n", __func__,
++ ioparam->handle);
++ return -EINVAL;
++ }
++
++ /* Check permissions.
++ */
++ if (resource->pid && (resource->pid != current->tgid)) {
++ pr_err("[%s]: current tgid %u != %u owner\n",
++ __func__, current->tgid, resource->pid);
++ vmcs_sm_release_resource(resource, 0);
++ return -EPERM;
++ }
++
++ vmcs_sm_release_resource(resource, 0);
++ vmcs_sm_release_resource(resource, 0);
++ return 0;
++}
++
++/* Resize a previously allocated shared memory handle and block.
++*/
++static int vc_sm_ioctl_resize(struct SM_PRIV_DATA_T *private,
++ struct vmcs_sm_ioctl_resize *ioparam)
++{
++ int ret = 0;
++ int status;
++ VC_SM_RESIZE_T resize;
++ struct SM_RESOURCE_T *resource;
++
++ /* Locate resource from GUID.
++ */
++ resource = vmcs_sm_acquire_resource(private, ioparam->handle);
++ if (!resource) {
++ pr_err("[%s]: failed resource - guid %x\n",
++ __func__, ioparam->handle);
++ ret = -EFAULT;
++ goto error;
++ }
++
++ /* If the resource is locked, its reference count will be not NULL,
++ ** in which case we will not be allowed to resize it anyways, so
++ ** reject the attempt here.
++ */
++ if (resource->lock_count != 0) {
++ pr_err("[%s]: cannot resize - guid %x, ref-cnt %d\n",
++ __func__, ioparam->handle, resource->lock_count);
++ ret = -EFAULT;
++ goto error;
++ }
++
++ /* Check permissions.
++ */
++ if (resource->pid && (resource->pid != current->tgid)) {
++ pr_err("[%s]: current tgid %u != %u owner\n", __func__,
++ current->tgid, resource->pid);
++ ret = -EPERM;
++ goto error;
++ }
++
++ if (resource->map_count != 0) {
++ pr_err("[%s]: cannot resize - guid %x, ref-cnt %d\n",
++ __func__, ioparam->handle, resource->map_count);
++ ret = -EFAULT;
++ goto error;
++ }
++
++ resize.res_handle = resource->res_handle;
++ resize.res_mem = resource->res_base_mem;
++ resize.res_new_size = ioparam->new_size;
++
++ pr_debug("[%s]: attempt to resize data - guid %x, hdl %x, base address %p\n",
++ __func__, ioparam->handle, resize.res_handle, resize.res_mem);
++
++ /* Resize the videocore allocated resource.
++ */
++ status = vc_vchi_sm_resize(sm_state->sm_handle, &resize,
++ &private->int_trans_id);
++ if (status == -EINTR) {
++ pr_debug("[%s]: requesting resize memory action restart (trans_id: %u)\n",
++ __func__, private->int_trans_id);
++ ret = -ERESTARTSYS;
++ private->restart_sys = -EINTR;
++ private->int_action = VC_SM_MSG_TYPE_RESIZE;
++ goto error;
++ } else if (status != 0) {
++ pr_err("[%s]: failed to resize memory on videocore (status: %u, trans_id: %u)\n",
++ __func__, status, private->int_trans_id);
++ ret = -EPERM;
++ goto error;
++ }
++
++ pr_debug("[%s]: success to resize data - hdl %x, size %d -> %d\n",
++ __func__, resize.res_handle, resource->res_size,
++ resize.res_new_size);
++
++ /* Successfully resized, save the information and inform the user.
++ */
++ ioparam->old_size = resource->res_size;
++ resource->res_size = resize.res_new_size;
++
++error:
++ if (resource)
++ vmcs_sm_release_resource(resource, 0);
++
++ return ret;
++}
++
++/* Lock a previously allocated shared memory handle and block.
++*/
++static int vc_sm_ioctl_lock(struct SM_PRIV_DATA_T *private,
++ struct vmcs_sm_ioctl_lock_unlock *ioparam,
++ int change_cache, enum vmcs_sm_cache_e cache_type,
++ unsigned int vc_addr)
++{
++ int status;
++ VC_SM_LOCK_UNLOCK_T lock;
++ VC_SM_LOCK_RESULT_T result;
++ struct SM_RESOURCE_T *resource;
++ int ret = 0;
++ struct sm_mmap *map, *map_tmp;
++ long unsigned int phys_addr;
++
++ map = NULL;
++
++ /* Locate resource from GUID.
++ */
++ resource = vmcs_sm_acquire_resource(private, ioparam->handle);
++ if (resource == NULL) {
++ ret = -EINVAL;
++ goto error;
++ }
++
++ /* Check permissions.
++ */
++ if (resource->pid && (resource->pid != current->tgid)) {
++ pr_err("[%s]: current tgid %u != %u owner\n", __func__,
++ current->tgid, resource->pid);
++ ret = -EPERM;
++ goto error;
++ }
++
++ lock.res_handle = resource->res_handle;
++ lock.res_mem = resource->res_base_mem;
++
++ /* Take the lock and get the address to be mapped.
++ */
++ if (vc_addr == 0) {
++ pr_debug("[%s]: attempt to lock data - guid %x, hdl %x, base address %p\n",
++ __func__, ioparam->handle, lock.res_handle,
++ lock.res_mem);
++
++ /* Lock the videocore allocated resource.
++ */
++ status = vc_vchi_sm_lock(sm_state->sm_handle, &lock, &result,
++ &private->int_trans_id);
++ if (status == -EINTR) {
++ pr_debug("[%s]: requesting lock memory action restart (trans_id: %u)\n",
++ __func__, private->int_trans_id);
++ ret = -ERESTARTSYS;
++ private->restart_sys = -EINTR;
++ private->int_action = VC_SM_MSG_TYPE_LOCK;
++ goto error;
++ } else if (status != 0 ||
++ (status == 0 && result.res_mem == NULL)) {
++ pr_err("[%s]: failed to lock memory on videocore (status: %u, trans_id: %u)\n",
++ __func__, status, private->int_trans_id);
++ ret = -EPERM;
++ resource->res_stats[LOCK_FAIL]++;
++ goto error;
++ }
++
++ pr_debug("[%s]: succeed to lock data - hdl %x, base address %p (%p), ref-cnt %d\n",
++ __func__, lock.res_handle, result.res_mem,
++ lock.res_mem, resource->lock_count);
++ }
++ /* Lock assumed taken already, address to be mapped is known.
++ */
++ else
++ resource->res_base_mem = (void *)vc_addr;
++
++ resource->res_stats[LOCK]++;
++ resource->lock_count++;
++
++ /* Keep track of the new base memory allocation if it has changed.
++ */
++ if ((vc_addr == 0) &&
++ (result.res_mem != NULL) &&
++ (result.res_old_mem != NULL) &&
++ (result.res_mem != result.res_old_mem)) {
++ resource->res_base_mem = result.res_mem;
++
++ /* Kernel allocated resources.
++ */
++ if (resource->pid == 0) {
++ if (!list_empty(&resource->map_list)) {
++ list_for_each_entry_safe(map, map_tmp,
++ &resource->map_list,
++ resource_map_list) {
++ if (map->res_addr) {
++ iounmap((void *)map->res_addr);
++ map->res_addr = 0;
++
++ vmcs_sm_remove_map(sm_state,
++ map->resource,
++ map);
++ break;
++ }
++ }
++ }
++ }
++ }
++
++ if (change_cache)
++ resource->res_cached = cache_type;
++
++ if (resource->map_count) {
++ ioparam->addr =
++ vmcs_sm_usr_address_from_pid_and_usr_handle(
++ current->tgid, ioparam->handle);
++
++ pr_debug("[%s] map_count %d private->pid %d current->tgid %d hnd %x addr %u\n",
++ __func__, resource->map_count, private->pid,
++ current->tgid, ioparam->handle, ioparam->addr);
++ } else {
++ /* Kernel allocated resources.
++ */
++ if (resource->pid == 0) {
++ pr_debug("[%s]: attempt mapping kernel resource - guid %x, hdl %x\n",
++ __func__, ioparam->handle, lock.res_handle);
++
++ ioparam->addr = 0;
++
++ map = kzalloc(sizeof(*map), GFP_KERNEL);
++ if (map == NULL) {
++ pr_err("[%s]: failed allocating tracker\n",
++ __func__);
++ ret = -ENOMEM;
++ goto error;
++ } else {
++ phys_addr = (uint32_t)resource->res_base_mem &
++ 0x3FFFFFFF;
++ phys_addr += mm_vc_mem_phys_addr;
++ if (resource->res_cached
++ == VMCS_SM_CACHE_HOST) {
++ ioparam->addr = (long unsigned int)
++ /* TODO - make cached work */
++ ioremap_nocache(phys_addr,
++ resource->res_size);
++
++ pr_debug("[%s]: mapping kernel - guid %x, hdl %x - cached mapping %u\n",
++ __func__, ioparam->handle,
++ lock.res_handle, ioparam->addr);
++ } else {
++ ioparam->addr = (long unsigned int)
++ ioremap_nocache(phys_addr,
++ resource->res_size);
++
++ pr_debug("[%s]: mapping kernel- guid %x, hdl %x - non cached mapping %u\n",
++ __func__, ioparam->handle,
++ lock.res_handle, ioparam->addr);
++ }
++
++ map->res_pid = 0;
++ map->res_vc_hdl = resource->res_handle;
++ map->res_usr_hdl = resource->res_guid;
++ map->res_addr = ioparam->addr;
++ map->resource = resource;
++ map->vma = NULL;
++
++ vmcs_sm_add_map(sm_state, resource, map);
++ }
++ } else
++ ioparam->addr = 0;
++ }
++
++error:
++ if (resource)
++ vmcs_sm_release_resource(resource, 0);
++
++ return ret;
++}
++
++/* Unlock a previously allocated shared memory handle and block.
++*/
++static int vc_sm_ioctl_unlock(struct SM_PRIV_DATA_T *private,
++ struct vmcs_sm_ioctl_lock_unlock *ioparam,
++ int flush, int wait_reply, int no_vc_unlock)
++{
++ int status;
++ VC_SM_LOCK_UNLOCK_T unlock;
++ struct sm_mmap *map, *map_tmp;
++ struct SM_RESOURCE_T *resource;
++ int ret = 0;
++
++ map = NULL;
++
++ /* Locate resource from GUID.
++ */
++ resource = vmcs_sm_acquire_resource(private, ioparam->handle);
++ if (resource == NULL) {
++ ret = -EINVAL;
++ goto error;
++ }
++
++ /* Check permissions.
++ */
++ if (resource->pid && (resource->pid != current->tgid)) {
++ pr_err("[%s]: current tgid %u != %u owner\n",
++ __func__, current->tgid, resource->pid);
++ ret = -EPERM;
++ goto error;
++ }
++
++ unlock.res_handle = resource->res_handle;
++ unlock.res_mem = resource->res_base_mem;
++
++ pr_debug("[%s]: attempt to unlock data - guid %x, hdl %x, base address %p\n",
++ __func__, ioparam->handle, unlock.res_handle, unlock.res_mem);
++
++ /* User space allocated resources.
++ */
++ if (resource->pid) {
++ /* Flush if requested */
++ if (resource->res_cached && flush) {
++ dma_addr_t phys_addr = 0;
++ resource->res_stats[FLUSH]++;
++
++ phys_addr =
++ (dma_addr_t)((uint32_t)resource->res_base_mem &
++ 0x3FFFFFFF);
++ phys_addr += (dma_addr_t)mm_vc_mem_phys_addr;
++
++ /* L1 cache flush */
++ down_read(&current->mm->mmap_sem);
++ list_for_each_entry(map, &resource->map_list,
++ resource_map_list) {
++ if (map->vma) {
++ unsigned long start;
++ unsigned long end;
++ start = map->vma->vm_start;
++ end = map->vma->vm_end;
++
++ vcsm_vma_cache_clean_page_range(
++ start, end);
++ }
++ }
++ up_read(&current->mm->mmap_sem);
++
++ /* L2 cache flush */
++ outer_clean_range(phys_addr,
++ phys_addr +
++ (size_t) resource->res_size);
++ }
++
++ /* We need to zap all the vmas associated with this resource */
++ if (resource->lock_count == 1) {
++ down_read(&current->mm->mmap_sem);
++ list_for_each_entry(map, &resource->map_list,
++ resource_map_list) {
++ if (map->vma) {
++ zap_vma_ptes(map->vma,
++ map->vma->vm_start,
++ map->vma->vm_end -
++ map->vma->vm_start);
++ }
++ }
++ up_read(&current->mm->mmap_sem);
++ }
++ }
++ /* Kernel allocated resources. */
++ else {
++ /* Global + Taken in this context */
++ if (resource->ref_count == 2) {
++ if (!list_empty(&resource->map_list)) {
++ list_for_each_entry_safe(map, map_tmp,
++ &resource->map_list,
++ resource_map_list) {
++ if (map->res_addr) {
++ if (flush &&
++ (resource->res_cached ==
++ VMCS_SM_CACHE_HOST)) {
++ long unsigned int
++ phys_addr;
++ phys_addr = (uint32_t)
++ resource->res_base_mem & 0x3FFFFFFF;
++ phys_addr +=
++ mm_vc_mem_phys_addr;
++
++ /* L1 cache flush */
++ dmac_flush_range((const
++ void
++ *)
++ map->res_addr, (const void *)
++ (map->res_addr + resource->res_size));
++
++ /* L2 cache flush */
++ outer_clean_range
++ (phys_addr,
++ phys_addr +
++ (size_t)
++ resource->res_size);
++ }
++
++ iounmap((void *)map->res_addr);
++ map->res_addr = 0;
++
++ vmcs_sm_remove_map(sm_state,
++ map->resource,
++ map);
++ break;
++ }
++ }
++ }
++ }
++ }
++
++ if (resource->lock_count) {
++ /* Bypass the videocore unlock.
++ */
++ if (no_vc_unlock)
++ status = 0;
++ /* Unlock the videocore allocated resource.
++ */
++ else {
++ status =
++ vc_vchi_sm_unlock(sm_state->sm_handle, &unlock,
++ &private->int_trans_id,
++ wait_reply);
++ if (status == -EINTR) {
++ pr_debug("[%s]: requesting unlock memory action restart (trans_id: %u)\n",
++ __func__, private->int_trans_id);
++
++ ret = -ERESTARTSYS;
++ resource->res_stats[UNLOCK]--;
++ private->restart_sys = -EINTR;
++ private->int_action = VC_SM_MSG_TYPE_UNLOCK;
++ goto error;
++ } else if (status != 0) {
++ pr_err("[%s]: failed to unlock vc mem (status: %u, trans_id: %u)\n",
++ __func__, status, private->int_trans_id);
++
++ ret = -EPERM;
++ resource->res_stats[UNLOCK_FAIL]++;
++ goto error;
++ }
++ }
++
++ resource->res_stats[UNLOCK]++;
++ resource->lock_count--;
++ }
++
++ pr_debug("[%s]: success to unlock data - hdl %x, base address %p, ref-cnt %d\n",
++ __func__, unlock.res_handle, unlock.res_mem,
++ resource->lock_count);
++
++error:
++ if (resource)
++ vmcs_sm_release_resource(resource, 0);
++
++ return ret;
++}
++
++/* Handle control from host. */
++static long vc_sm_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
++{
++ int ret = 0;
++ unsigned int cmdnr = _IOC_NR(cmd);
++ struct SM_PRIV_DATA_T *file_data =
++ (struct SM_PRIV_DATA_T *)file->private_data;
++ struct SM_RESOURCE_T *resource = NULL;
++
++ /* Validate we can work with this device. */
++ if ((sm_state == NULL) || (file_data == NULL)) {
++ pr_err("[%s]: invalid device\n", __func__);
++ ret = -EPERM;
++ goto out;
++ }
++
++ pr_debug("[%s]: cmd %x tgid %u, owner %u\n", __func__, cmdnr,
++ current->tgid, file_data->pid);
++
++ /* Action is a re-post of a previously interrupted action? */
++ if (file_data->restart_sys == -EINTR) {
++ VC_SM_ACTION_CLEAN_T action_clean;
++
++ pr_debug("[%s]: clean up of action %u (trans_id: %u) following EINTR\n",
++ __func__, file_data->int_action,
++ file_data->int_trans_id);
++
++ action_clean.res_action = file_data->int_action;
++ action_clean.action_trans_id = file_data->int_trans_id;
++
++ vc_vchi_sm_clean_up(sm_state->sm_handle, &action_clean);
++
++ file_data->restart_sys = 0;
++ }
++
++ /* Now process the command.
++ */
++ switch (cmdnr) {
++ /* New memory allocation.
++ */
++ case VMCS_SM_CMD_ALLOC:
++ {
++ struct vmcs_sm_ioctl_alloc ioparam;
++
++ /* Get the parameter data.
++ */
++ if (copy_from_user
++ (&ioparam, (void *)arg, sizeof(ioparam)) != 0) {
++ pr_err("[%s]: failed to copy-from-user for cmd %x\n",
++ __func__, cmdnr);
++ ret = -EFAULT;
++ goto out;
++ }
++
++ ret = vc_sm_ioctl_alloc(file_data, &ioparam);
++ if (!ret &&
++ (copy_to_user((void *)arg,
++ &ioparam, sizeof(ioparam)) != 0)) {
++ struct vmcs_sm_ioctl_free freeparam = {
++ ioparam.handle
++ };
++ pr_err("[%s]: failed to copy-to-user for cmd %x\n",
++ __func__, cmdnr);
++ vc_sm_ioctl_free(file_data, &freeparam);
++ ret = -EFAULT;
++ }
++
++ /* Done.
++ */
++ goto out;
++ }
++ break;
++
++ /* Share existing memory allocation.
++ */
++ case VMCS_SM_CMD_ALLOC_SHARE:
++ {
++ struct vmcs_sm_ioctl_alloc_share ioparam;
++
++ /* Get the parameter data.
++ */
++ if (copy_from_user
++ (&ioparam, (void *)arg, sizeof(ioparam)) != 0) {
++ pr_err("[%s]: failed to copy-from-user for cmd %x\n",
++ __func__, cmdnr);
++ ret = -EFAULT;
++ goto out;
++ }
++
++ ret = vc_sm_ioctl_alloc_share(file_data, &ioparam);
++
++ /* Copy result back to user.
++ */
++ if (!ret
++ && copy_to_user((void *)arg, &ioparam,
++ sizeof(ioparam)) != 0) {
++ struct vmcs_sm_ioctl_free freeparam = {
++ ioparam.handle
++ };
++ pr_err("[%s]: failed to copy-to-user for cmd %x\n",
++ __func__, cmdnr);
++ vc_sm_ioctl_free(file_data, &freeparam);
++ ret = -EFAULT;
++ }
++
++ /* Done.
++ */
++ goto out;
++ }
++ break;
++
++ /* Lock (attempt to) *and* register a cache behavior change.
++ */
++ case VMCS_SM_CMD_LOCK_CACHE:
++ {
++ struct vmcs_sm_ioctl_lock_cache ioparam;
++ struct vmcs_sm_ioctl_lock_unlock lock;
++
++ /* Get parameter data.
++ */
++ if (copy_from_user
++ (&ioparam, (void *)arg, sizeof(ioparam)) != 0) {
++ pr_err("[%s]: failed to copy-from-user for cmd %x\n",
++ __func__, cmdnr);
++ ret = -EFAULT;
++ goto out;
++ }
++
++ lock.handle = ioparam.handle;
++ ret =
++ vc_sm_ioctl_lock(file_data, &lock, 1,
++ ioparam.cached, 0);
++
++ /* Done.
++ */
++ goto out;
++ }
++ break;
++
++ /* Lock (attempt to) existing memory allocation.
++ */
++ case VMCS_SM_CMD_LOCK:
++ {
++ struct vmcs_sm_ioctl_lock_unlock ioparam;
++
++ /* Get parameter data.
++ */
++ if (copy_from_user
++ (&ioparam, (void *)arg, sizeof(ioparam)) != 0) {
++ pr_err("[%s]: failed to copy-from-user for cmd %x\n",
++ __func__, cmdnr);
++ ret = -EFAULT;
++ goto out;
++ }
++
++ ret = vc_sm_ioctl_lock(file_data, &ioparam, 0, 0, 0);
++
++ /* Copy result back to user.
++ */
++ if (copy_to_user((void *)arg, &ioparam, sizeof(ioparam))
++ != 0) {
++ pr_err("[%s]: failed to copy-to-user for cmd %x\n",
++ __func__, cmdnr);
++ ret = -EFAULT;
++ }
++
++ /* Done.
++ */
++ goto out;
++ }
++ break;
++
++ /* Unlock (attempt to) existing memory allocation.
++ */
++ case VMCS_SM_CMD_UNLOCK:
++ {
++ struct vmcs_sm_ioctl_lock_unlock ioparam;
++
++ /* Get parameter data.
++ */
++ if (copy_from_user
++ (&ioparam, (void *)arg, sizeof(ioparam)) != 0) {
++ pr_err("[%s]: failed to copy-from-user for cmd %x\n",
++ __func__, cmdnr);
++ ret = -EFAULT;
++ goto out;
++ }
++
++ ret = vc_sm_ioctl_unlock(file_data, &ioparam, 0, 1, 0);
++
++ /* Done.
++ */
++ goto out;
++ }
++ break;
++
++ /* Resize (attempt to) existing memory allocation.
++ */
++ case VMCS_SM_CMD_RESIZE:
++ {
++ struct vmcs_sm_ioctl_resize ioparam;
++
++ /* Get parameter data.
++ */
++ if (copy_from_user
++ (&ioparam, (void *)arg, sizeof(ioparam)) != 0) {
++ pr_err("[%s]: failed to copy-from-user for cmd %x\n",
++ __func__, cmdnr);
++ ret = -EFAULT;
++ goto out;
++ }
++
++ ret = vc_sm_ioctl_resize(file_data, &ioparam);
++
++ /* Copy result back to user.
++ */
++ if (copy_to_user((void *)arg, &ioparam, sizeof(ioparam))
++ != 0) {
++ pr_err("[%s]: failed to copy-to-user for cmd %x\n",
++ __func__, cmdnr);
++ ret = -EFAULT;
++ }
++
++ /* Done.
++ */
++ goto out;
++ }
++ break;
++
++ /* Terminate existing memory allocation.
++ */
++ case VMCS_SM_CMD_FREE:
++ {
++ struct vmcs_sm_ioctl_free ioparam;
++
++ /* Get parameter data.
++ */
++ if (copy_from_user
++ (&ioparam, (void *)arg, sizeof(ioparam)) != 0) {
++ pr_err("[%s]: failed to copy-from-user for cmd %x\n",
++ __func__, cmdnr);
++ ret = -EFAULT;
++ goto out;
++ }
++
++ ret = vc_sm_ioctl_free(file_data, &ioparam);
++
++ /* Done.
++ */
++ goto out;
++ }
++ break;
++
++ /* Walk allocation on videocore, information shows up in the
++ ** videocore log.
++ */
++ case VMCS_SM_CMD_VC_WALK_ALLOC:
++ {
++ pr_debug("[%s]: invoking walk alloc\n", __func__);
++
++ if (vc_vchi_sm_walk_alloc(sm_state->sm_handle) != 0)
++ pr_err("[%s]: failed to walk-alloc on videocore\n",
++ __func__);
++
++ /* Done.
++ */
++ goto out;
++ }
++ break;
++/* Walk mapping table on host, information shows up in the
++ ** kernel log.
++ */
++ case VMCS_SM_CMD_HOST_WALK_MAP:
++ {
++ /* Use pid of -1 to tell to walk the whole map. */
++ vmcs_sm_host_walk_map_per_pid(-1);
++
++ /* Done. */
++ goto out;
++ }
++ break;
++
++ /* Walk mapping table per process on host. */
++ case VMCS_SM_CMD_HOST_WALK_PID_ALLOC:
++ {
++ struct vmcs_sm_ioctl_walk ioparam;
++
++ /* Get parameter data. */
++ if (copy_from_user(&ioparam,
++ (void *)arg, sizeof(ioparam)) != 0) {
++ pr_err("[%s]: failed to copy-from-user for cmd %x\n",
++ __func__, cmdnr);
++ ret = -EFAULT;
++ goto out;
++ }
++
++ vmcs_sm_host_walk_alloc(file_data);
++
++ /* Done. */
++ goto out;
++ }
++ break;
++
++ /* Walk allocation per process on host. */
++ case VMCS_SM_CMD_HOST_WALK_PID_MAP:
++ {
++ struct vmcs_sm_ioctl_walk ioparam;
++
++ /* Get parameter data. */
++ if (copy_from_user(&ioparam,
++ (void *)arg, sizeof(ioparam)) != 0) {
++ pr_err("[%s]: failed to copy-from-user for cmd %x\n",
++ __func__, cmdnr);
++ ret = -EFAULT;
++ goto out;
++ }
++
++ vmcs_sm_host_walk_map_per_pid(ioparam.pid);
++
++ /* Done. */
++ goto out;
++ }
++ break;
++
++ /* Gets the size of the memory associated with a user handle. */
++ case VMCS_SM_CMD_SIZE_USR_HANDLE:
++ {
++ struct vmcs_sm_ioctl_size ioparam;
++
++ /* Get parameter data. */
++ if (copy_from_user(&ioparam,
++ (void *)arg, sizeof(ioparam)) != 0) {
++ pr_err("[%s]: failed to copy-from-user for cmd %x\n",
++ __func__, cmdnr);
++ ret = -EFAULT;
++ goto out;
++ }
++
++ /* Locate resource from GUID. */
++ resource =
++ vmcs_sm_acquire_resource(file_data, ioparam.handle);
++ if (resource != NULL) {
++ ioparam.size = resource->res_size;
++ vmcs_sm_release_resource(resource, 0);
++ } else {
++ ioparam.size = 0;
++ }
++
++ if (copy_to_user((void *)arg,
++ &ioparam, sizeof(ioparam)) != 0) {
++ pr_err("[%s]: failed to copy-to-user for cmd %x\n",
++ __func__, cmdnr);
++ ret = -EFAULT;
++ }
++
++ /* Done. */
++ goto out;
++ }
++ break;
++
++ /* Verify we are dealing with a valid resource. */
++ case VMCS_SM_CMD_CHK_USR_HANDLE:
++ {
++ struct vmcs_sm_ioctl_chk ioparam;
++
++ /* Get parameter data.
++ */
++ if (copy_from_user(&ioparam,
++ (void *)arg, sizeof(ioparam)) != 0) {
++ pr_err("[%s]: failed to copy-from-user for cmd %x\n",
++ __func__, cmdnr);
++
++ ret = -EFAULT;
++ goto out;
++ }
++
++ /* Locate resource from GUID. */
++ resource =
++ vmcs_sm_acquire_resource(file_data, ioparam.handle);
++ if (resource == NULL)
++ ret = -EINVAL;
++ /* If the resource is cacheable, return additional
++ * information that may be needed to flush the cache.
++ */
++ else if ((resource->res_cached == VMCS_SM_CACHE_HOST) ||
++ (resource->res_cached == VMCS_SM_CACHE_BOTH)) {
++ ioparam.addr =
++ vmcs_sm_usr_address_from_pid_and_usr_handle
++ (current->tgid, ioparam.handle);
++ ioparam.size = resource->res_size;
++ ioparam.cache = resource->res_cached;
++ } else {
++ ioparam.addr = 0;
++ ioparam.size = 0;
++ ioparam.cache = resource->res_cached;
++ }
++
++ if (resource)
++ vmcs_sm_release_resource(resource, 0);
++
++ if (copy_to_user((void *)arg,
++ &ioparam, sizeof(ioparam)) != 0) {
++ pr_err("[%s]: failed to copy-to-user for cmd %x\n",
++ __func__, cmdnr);
++ ret = -EFAULT;
++ }
++
++ /* Done.
++ */
++ goto out;
++ }
++ break;
++
++ /*
++ * Maps a user handle given the process and the virtual address.
++ */
++ case VMCS_SM_CMD_MAPPED_USR_HANDLE:
++ {
++ struct vmcs_sm_ioctl_map ioparam;
++
++ /* Get parameter data. */
++ if (copy_from_user(&ioparam,
++ (void *)arg, sizeof(ioparam)) != 0) {
++ pr_err("[%s]: failed to copy-from-user for cmd %x\n",
++ __func__, cmdnr);
++
++ ret = -EFAULT;
++ goto out;
++ }
++
++ ioparam.handle =
++ vmcs_sm_usr_handle_from_pid_and_address(
++ ioparam.pid, ioparam.addr);
++
++ resource =
++ vmcs_sm_acquire_resource(file_data, ioparam.handle);
++ if ((resource != NULL)
++ && ((resource->res_cached == VMCS_SM_CACHE_HOST)
++ || (resource->res_cached ==
++ VMCS_SM_CACHE_BOTH))) {
++ ioparam.size = resource->res_size;
++ } else {
++ ioparam.size = 0;
++ }
++
++ if (resource)
++ vmcs_sm_release_resource(resource, 0);
++
++ if (copy_to_user((void *)arg,
++ &ioparam, sizeof(ioparam)) != 0) {
++ pr_err("[%s]: failed to copy-to-user for cmd %x\n",
++ __func__, cmdnr);
++ ret = -EFAULT;
++ }
++
++ /* Done. */
++ goto out;
++ }
++ break;
++
++ /*
++ * Maps a videocore handle given process and virtual address.
++ */
++ case VMCS_SM_CMD_MAPPED_VC_HDL_FROM_ADDR:
++ {
++ struct vmcs_sm_ioctl_map ioparam;
++
++ /* Get parameter data. */
++ if (copy_from_user(&ioparam,
++ (void *)arg, sizeof(ioparam)) != 0) {
++ pr_err("[%s]: failed to copy-from-user for cmd %x\n",
++ __func__, cmdnr);
++ ret = -EFAULT;
++ goto out;
++ }
++
++ ioparam.handle = vmcs_sm_vc_handle_from_pid_and_address(
++ ioparam.pid, ioparam.addr);
++
++ if (copy_to_user((void *)arg,
++ &ioparam, sizeof(ioparam)) != 0) {
++ pr_err("[%s]: failed to copy-to-user for cmd %x\n",
++ __func__, cmdnr);
++
++ ret = -EFAULT;
++ }
++
++ /* Done.
++ */
++ goto out;
++ }
++ break;
++
++ /* Maps a videocore handle given process and user handle. */
++ case VMCS_SM_CMD_MAPPED_VC_HDL_FROM_HDL:
++ {
++ struct vmcs_sm_ioctl_map ioparam;
++
++ /* Get parameter data. */
++ if (copy_from_user(&ioparam,
++ (void *)arg, sizeof(ioparam)) != 0) {
++ pr_err("[%s]: failed to copy-from-user for cmd %x\n",
++ __func__, cmdnr);
++ ret = -EFAULT;
++ goto out;
++ }
++
++ /* Locate resource from GUID. */
++ resource =
++ vmcs_sm_acquire_resource(file_data, ioparam.handle);
++ if (resource != NULL) {
++ ioparam.handle = resource->res_handle;
++ vmcs_sm_release_resource(resource, 0);
++ } else {
++ ioparam.handle = 0;
++ }
++
++ if (copy_to_user((void *)arg,
++ &ioparam, sizeof(ioparam)) != 0) {
++ pr_err("[%s]: failed to copy-to-user for cmd %x\n",
++ __func__, cmdnr);
++
++ ret = -EFAULT;
++ }
++
++ /* Done. */
++ goto out;
++ }
++ break;
++
++ /*
++ * Maps a videocore address given process and videocore handle.
++ */
++ case VMCS_SM_CMD_MAPPED_VC_ADDR_FROM_HDL:
++ {
++ struct vmcs_sm_ioctl_map ioparam;
++
++ /* Get parameter data. */
++ if (copy_from_user(&ioparam,
++ (void *)arg, sizeof(ioparam)) != 0) {
++ pr_err("[%s]: failed to copy-from-user for cmd %x\n",
++ __func__, cmdnr);
++
++ ret = -EFAULT;
++ goto out;
++ }
++
++ /* Locate resource from GUID. */
++ resource =
++ vmcs_sm_acquire_resource(file_data, ioparam.handle);
++ if (resource != NULL) {
++ ioparam.addr =
++ (unsigned int)resource->res_base_mem;
++ vmcs_sm_release_resource(resource, 0);
++ } else {
++ ioparam.addr = 0;
++ }
++
++ if (copy_to_user((void *)arg,
++ &ioparam, sizeof(ioparam)) != 0) {
++ pr_err("[%s]: failed to copy-to-user for cmd %x\n",
++ __func__, cmdnr);
++ ret = -EFAULT;
++ }
++
++ /* Done. */
++ goto out;
++ }
++ break;
++
++ /* Maps a user address given process and vc handle.
++ */
++ case VMCS_SM_CMD_MAPPED_USR_ADDRESS:
++ {
++ struct vmcs_sm_ioctl_map ioparam;
++
++ /* Get parameter data. */
++ if (copy_from_user(&ioparam,
++ (void *)arg, sizeof(ioparam)) != 0) {
++ pr_err("[%s]: failed to copy-from-user for cmd %x\n",
++ __func__, cmdnr);
++ ret = -EFAULT;
++ goto out;
++ }
++
++ /*
++ * Return the address information from the mapping,
++ * 0 (ie NULL) if it cannot locate the actual mapping.
++ */
++ ioparam.addr =
++ vmcs_sm_usr_address_from_pid_and_usr_handle
++ (ioparam.pid, ioparam.handle);
++
++ if (copy_to_user((void *)arg,
++ &ioparam, sizeof(ioparam)) != 0) {
++ pr_err("[%s]: failed to copy-to-user for cmd %x\n",
++ __func__, cmdnr);
++ ret = -EFAULT;
++ }
++
++ /* Done. */
++ goto out;
++ }
++ break;
++
++ /* Flush the cache for a given mapping. */
++ case VMCS_SM_CMD_FLUSH:
++ {
++ struct vmcs_sm_ioctl_cache ioparam;
++
++ /* Get parameter data. */
++ if (copy_from_user(&ioparam,
++ (void *)arg, sizeof(ioparam)) != 0) {
++ pr_err("[%s]: failed to copy-from-user for cmd %x\n",
++ __func__, cmdnr);
++ ret = -EFAULT;
++ goto out;
++ }
++
++ /* Locate resource from GUID. */
++ resource =
++ vmcs_sm_acquire_resource(file_data, ioparam.handle);
++
++ if ((resource != NULL) && resource->res_cached) {
++ dma_addr_t phys_addr = 0;
++
++ resource->res_stats[FLUSH]++;
++
++ phys_addr =
++ (dma_addr_t)((uint32_t)
++ resource->res_base_mem &
++ 0x3FFFFFFF);
++ phys_addr += (dma_addr_t)mm_vc_mem_phys_addr;
++
++ /* L1 cache flush */
++ down_read(&current->mm->mmap_sem);
++ vcsm_vma_cache_clean_page_range((unsigned long)
++ ioparam.addr,
++ (unsigned long)
++ ioparam.addr +
++ ioparam.size);
++ up_read(&current->mm->mmap_sem);
++
++ /* L2 cache flush */
++ outer_clean_range(phys_addr,
++ phys_addr +
++ (size_t) ioparam.size);
++ } else if (resource == NULL) {
++ ret = -EINVAL;
++ goto out;
++ }
++
++ if (resource)
++ vmcs_sm_release_resource(resource, 0);
++
++ /* Done. */
++ goto out;
++ }
++ break;
++
++ /* Invalidate the cache for a given mapping. */
++ case VMCS_SM_CMD_INVALID:
++ {
++ struct vmcs_sm_ioctl_cache ioparam;
++
++ /* Get parameter data. */
++ if (copy_from_user(&ioparam,
++ (void *)arg, sizeof(ioparam)) != 0) {
++ pr_err("[%s]: failed to copy-from-user for cmd %x\n",
++ __func__, cmdnr);
++ ret = -EFAULT;
++ goto out;
++ }
++
++ /* Locate resource from GUID.
++ */
++ resource =
++ vmcs_sm_acquire_resource(file_data, ioparam.handle);
++
++ if ((resource != NULL) && resource->res_cached) {
++ dma_addr_t phys_addr = 0;
++
++ resource->res_stats[INVALID]++;
++
++ phys_addr =
++ (dma_addr_t)((uint32_t)
++ resource->res_base_mem &
++ 0x3FFFFFFF);
++ phys_addr += (dma_addr_t)mm_vc_mem_phys_addr;
++
++ /* L2 cache invalidate */
++ outer_inv_range(phys_addr,
++ phys_addr +
++ (size_t) ioparam.size);
++
++ /* L1 cache invalidate */
++ down_read(&current->mm->mmap_sem);
++ vcsm_vma_cache_clean_page_range((unsigned long)
++ ioparam.addr,
++ (unsigned long)
++ ioparam.addr +
++ ioparam.size);
++ up_read(&current->mm->mmap_sem);
++ } else if (resource == NULL) {
++ ret = -EINVAL;
++ goto out;
++ }
++
++ if (resource)
++ vmcs_sm_release_resource(resource, 0);
++
++ /* Done.
++ */
++ goto out;
++ }
++ break;
++
++ default:
++ {
++ ret = -EINVAL;
++ goto out;
++ }
++ break;
++ }
++
++out:
++ return ret;
++}
++
++/* Device operations that we managed in this driver.
++*/
++static const struct file_operations vmcs_sm_ops = {
++ .owner = THIS_MODULE,
++ .unlocked_ioctl = vc_sm_ioctl,
++ .open = vc_sm_open,
++ .release = vc_sm_release,
++ .mmap = vc_sm_mmap,
++};
++
++/* Creation of device.
++*/
++static int vc_sm_create_sharedmemory(void)
++{
++ int ret;
++
++ if (sm_state == NULL) {
++ ret = -ENOMEM;
++ goto out;
++ }
++
++ /* Create a device class for creating dev nodes.
++ */
++ sm_state->sm_class = class_create(THIS_MODULE, "vc-sm");
++ if (IS_ERR(sm_state->sm_class)) {
++ pr_err("[%s]: unable to create device class\n", __func__);
++ ret = PTR_ERR(sm_state->sm_class);
++ goto out;
++ }
++
++ /* Create a character driver.
++ */
++ ret = alloc_chrdev_region(&sm_state->sm_devid,
++ DEVICE_MINOR, 1, DEVICE_NAME);
++ if (ret != 0) {
++ pr_err("[%s]: unable to allocate device number\n", __func__);
++ goto out_dev_class_destroy;
++ }
++
++ cdev_init(&sm_state->sm_cdev, &vmcs_sm_ops);
++ ret = cdev_add(&sm_state->sm_cdev, sm_state->sm_devid, 1);
++ if (ret != 0) {
++ pr_err("[%s]: unable to register device\n", __func__);
++ goto out_chrdev_unreg;
++ }
++
++ /* Create a device node.
++ */
++ sm_state->sm_dev = device_create(sm_state->sm_class,
++ NULL,
++ MKDEV(MAJOR(sm_state->sm_devid),
++ DEVICE_MINOR), NULL,
++ DEVICE_NAME);
++ if (IS_ERR(sm_state->sm_dev)) {
++ pr_err("[%s]: unable to create device node\n", __func__);
++ ret = PTR_ERR(sm_state->sm_dev);
++ goto out_chrdev_del;
++ }
++
++ goto out;
++
++out_chrdev_del:
++ cdev_del(&sm_state->sm_cdev);
++out_chrdev_unreg:
++ unregister_chrdev_region(sm_state->sm_devid, 1);
++out_dev_class_destroy:
++ class_destroy(sm_state->sm_class);
++ sm_state->sm_class = NULL;
++out:
++ return ret;
++}
++
++/* Termination of the device.
++*/
++static int vc_sm_remove_sharedmemory(void)
++{
++ int ret;
++
++ if (sm_state == NULL) {
++ /* Nothing to do.
++ */
++ ret = 0;
++ goto out;
++ }
++
++ /* Remove the sharedmemory character driver.
++ */
++ cdev_del(&sm_state->sm_cdev);
++
++ /* Unregister region.
++ */
++ unregister_chrdev_region(sm_state->sm_devid, 1);
++
++ ret = 0;
++ goto out;
++
++out:
++ return ret;
++}
++
++/* Videocore connected. */
++static void vc_sm_connected_init(void)
++{
++ int ret;
++ VCHI_INSTANCE_T vchi_instance;
++ VCHI_CONNECTION_T *vchi_connection = NULL;
++
++ pr_info("[%s]: start\n", __func__);
++
++ /* Allocate memory for the state structure.
++ */
++ sm_state = kzalloc(sizeof(struct SM_STATE_T), GFP_KERNEL);
++ if (sm_state == NULL) {
++ pr_err("[%s]: failed to allocate memory\n", __func__);
++ ret = -ENOMEM;
++ goto out;
++ }
++
++ mutex_init(&sm_state->lock);
++ mutex_init(&sm_state->map_lock);
++
++ /* Initialize and create a VCHI connection for the shared memory service
++ ** running on videocore.
++ */
++ ret = vchi_initialise(&vchi_instance);
++ if (ret != 0) {
++ pr_err("[%s]: failed to initialise VCHI instance (ret=%d)\n",
++ __func__, ret);
++
++ ret = -EIO;
++ goto err_free_mem;
++ }
++
++ ret = vchi_connect(NULL, 0, vchi_instance);
++ if (ret != 0) {
++ pr_err("[%s]: failed to connect VCHI instance (ret=%d)\n",
++ __func__, ret);
++
++ ret = -EIO;
++ goto err_free_mem;
++ }
++
++ /* Initialize an instance of the shared memory service. */
++ sm_state->sm_handle =
++ vc_vchi_sm_init(vchi_instance, &vchi_connection, 1);
++ if (sm_state->sm_handle == NULL) {
++ pr_err("[%s]: failed to initialize shared memory service\n",
++ __func__);
++
++ ret = -EPERM;
++ goto err_free_mem;
++ }
++
++ /* Create a debug fs directory entry (root). */
++ sm_state->dir_root = debugfs_create_dir(VC_SM_DIR_ROOT_NAME, NULL);
++ if (!sm_state->dir_root) {
++ pr_err("[%s]: failed to create \'%s\' directory entry\n",
++ __func__, VC_SM_DIR_ROOT_NAME);
++
++ ret = -EPERM;
++ goto err_stop_sm_service;
++ }
++
++ sm_state->dir_state.show = &vc_sm_global_state_show;
++ sm_state->dir_state.dir_entry = debugfs_create_file(VC_SM_STATE,
++ S_IRUGO, sm_state->dir_root, &sm_state->dir_state,
++ &vc_sm_debug_fs_fops);
++
++ sm_state->dir_stats.show = &vc_sm_global_statistics_show;
++ sm_state->dir_stats.dir_entry = debugfs_create_file(VC_SM_STATS,
++ S_IRUGO, sm_state->dir_root, &sm_state->dir_stats,
++ &vc_sm_debug_fs_fops);
++
++ /* Create the proc entry children. */
++ sm_state->dir_alloc = debugfs_create_dir(VC_SM_DIR_ALLOC_NAME,
++ sm_state->dir_root);
++
++ /* Create a shared memory device. */
++ ret = vc_sm_create_sharedmemory();
++ if (ret != 0) {
++ pr_err("[%s]: failed to create shared memory device\n",
++ __func__);
++ goto err_remove_debugfs;
++ }
++
++ INIT_LIST_HEAD(&sm_state->map_list);
++ INIT_LIST_HEAD(&sm_state->resource_list);
++
++ sm_state->data_knl = vc_sm_create_priv_data(0);
++ if (sm_state->data_knl == NULL) {
++ pr_err("[%s]: failed to create kernel private data tracker\n",
++ __func__);
++ goto err_remove_shared_memory;
++ }
++
++ /* Done!
++ */
++ sm_inited = 1;
++ goto out;
++
++err_remove_shared_memory:
++ vc_sm_remove_sharedmemory();
++err_remove_debugfs:
++ debugfs_remove_recursive(sm_state->dir_root);
++err_stop_sm_service:
++ vc_vchi_sm_stop(&sm_state->sm_handle);
++err_free_mem:
++ kfree(sm_state);
++out:
++ pr_info("[%s]: end - returning %d\n", __func__, ret);
++}
++
++/* Driver loading. */
++static int __init vc_sm_init(void)
++{
++ pr_info("vc-sm: Videocore shared memory driver\n");
++ vchiq_add_connected_callback(vc_sm_connected_init);
++ return 0;
++}
++
++/* Driver unloading. */
++static void __exit vc_sm_exit(void)
++{
++ pr_debug("[%s]: start\n", __func__);
++ if (sm_inited) {
++ /* Remove shared memory device.
++ */
++ vc_sm_remove_sharedmemory();
++
++ /* Remove all proc entries.
++ */
++ debugfs_remove_recursive(sm_state->dir_root);
++
++ /* Stop the videocore shared memory service.
++ */
++ vc_vchi_sm_stop(&sm_state->sm_handle);
++
++ /* Free the memory for the state structure.
++ */
++ mutex_destroy(&(sm_state->map_lock));
++ kfree(sm_state);
++ }
++
++ pr_debug("[%s]: end\n", __func__);
++}
++
++#if defined(__KERNEL__)
++/* Allocate a shared memory handle and block. */
++int vc_sm_alloc(VC_SM_ALLOC_T *alloc, int *handle)
++{
++ struct vmcs_sm_ioctl_alloc ioparam = { 0 };
++ int ret;
++ struct SM_RESOURCE_T *resource;
++
++ /* Validate we can work with this device.
++ */
++ if (sm_state == NULL || alloc == NULL || handle == NULL) {
++ pr_err("[%s]: invalid input\n", __func__);
++ return -EPERM;
++ }
++
++ ioparam.size = alloc->base_unit;
++ ioparam.num = alloc->num_unit;
++ ioparam.cached =
++ alloc->type == VC_SM_ALLOC_CACHED ? VMCS_SM_CACHE_VC : 0;
++
++ ret = vc_sm_ioctl_alloc(sm_state->data_knl, &ioparam);
++
++ if (ret == 0) {
++ resource =
++ vmcs_sm_acquire_resource(sm_state->data_knl,
++ ioparam.handle);
++ if (resource) {
++ resource->pid = 0;
++ vmcs_sm_release_resource(resource, 0);
++
++ /* Assign valid handle at this time.
++ */
++ *handle = ioparam.handle;
++ } else {
++ ret = -ENOMEM;
++ }
++ }
++
++ return ret;
++}
++EXPORT_SYMBOL_GPL(vc_sm_alloc);
++
++/* Get an internal resource handle mapped from the external one.
++*/
++int vc_sm_int_handle(int handle)
++{
++ struct SM_RESOURCE_T *resource;
++ int ret = 0;
++
++ /* Validate we can work with this device.
++ */
++ if (sm_state == NULL || handle == 0) {
++ pr_err("[%s]: invalid input\n", __func__);
++ return 0;
++ }
++
++ /* Locate resource from GUID.
++ */
++ resource = vmcs_sm_acquire_resource(sm_state->data_knl, handle);
++ if (resource) {
++ ret = resource->res_handle;
++ vmcs_sm_release_resource(resource, 0);
++ }
++
++ return ret;
++}
++EXPORT_SYMBOL_GPL(vc_sm_int_handle);
++
++/* Free a previously allocated shared memory handle and block.
++*/
++int vc_sm_free(int handle)
++{
++ struct vmcs_sm_ioctl_free ioparam = { handle };
++
++ /* Validate we can work with this device.
++ */
++ if (sm_state == NULL || handle == 0) {
++ pr_err("[%s]: invalid input\n", __func__);
++ return -EPERM;
++ }
++
++ return vc_sm_ioctl_free(sm_state->data_knl, &ioparam);
++}
++EXPORT_SYMBOL_GPL(vc_sm_free);
++
++/* Lock a memory handle for use by kernel.
++*/
++int vc_sm_lock(int handle, VC_SM_LOCK_CACHE_MODE_T mode,
++ long unsigned int *data)
++{
++ struct vmcs_sm_ioctl_lock_unlock ioparam;
++ int ret;
++
++ /* Validate we can work with this device.
++ */
++ if (sm_state == NULL || handle == 0 || data == NULL) {
++ pr_err("[%s]: invalid input\n", __func__);
++ return -EPERM;
++ }
++
++ *data = 0;
++
++ ioparam.handle = handle;
++ ret = vc_sm_ioctl_lock(sm_state->data_knl,
++ &ioparam,
++ 1,
++ ((mode ==
++ VC_SM_LOCK_CACHED) ? VMCS_SM_CACHE_HOST :
++ VMCS_SM_CACHE_NONE), 0);
++
++ *data = ioparam.addr;
++ return ret;
++}
++EXPORT_SYMBOL_GPL(vc_sm_lock);
++
++/* Unlock a memory handle in use by kernel.
++*/
++int vc_sm_unlock(int handle, int flush, int no_vc_unlock)
++{
++ struct vmcs_sm_ioctl_lock_unlock ioparam;
++
++ /* Validate we can work with this device.
++ */
++ if (sm_state == NULL || handle == 0) {
++ pr_err("[%s]: invalid input\n", __func__);
++ return -EPERM;
++ }
++
++ ioparam.handle = handle;
++ return vc_sm_ioctl_unlock(sm_state->data_knl,
++ &ioparam, flush, 0, no_vc_unlock);
++}
++EXPORT_SYMBOL_GPL(vc_sm_unlock);
++
++/* Map a shared memory region for use by kernel.
++*/
++int vc_sm_map(int handle, unsigned int sm_addr, VC_SM_LOCK_CACHE_MODE_T mode,
++ long unsigned int *data)
++{
++ struct vmcs_sm_ioctl_lock_unlock ioparam;
++ int ret;
++
++ /* Validate we can work with this device.
++ */
++ if (sm_state == NULL || handle == 0 || data == NULL || sm_addr == 0) {
++ pr_err("[%s]: invalid input\n", __func__);
++ return -EPERM;
++ }
++
++ *data = 0;
++
++ ioparam.handle = handle;
++ ret = vc_sm_ioctl_lock(sm_state->data_knl,
++ &ioparam,
++ 1,
++ ((mode ==
++ VC_SM_LOCK_CACHED) ? VMCS_SM_CACHE_HOST :
++ VMCS_SM_CACHE_NONE), sm_addr);
++
++ *data = ioparam.addr;
++ return ret;
++}
++EXPORT_SYMBOL_GPL(vc_sm_map);
++#endif
++
++late_initcall(vc_sm_init);
++module_exit(vc_sm_exit);
++
++MODULE_AUTHOR("Broadcom");
++MODULE_DESCRIPTION("VideoCore SharedMemory Driver");
++MODULE_LICENSE("GPL v2");
+diff -Nur linux-3.12.33/drivers/char/hw_random/bcm2708-rng.c linux-3.12.33-rpi/drivers/char/hw_random/bcm2708-rng.c
+--- linux-3.12.33/drivers/char/hw_random/bcm2708-rng.c 1969-12-31 18:00:00.000000000 -0600
++++ linux-3.12.33-rpi/drivers/char/hw_random/bcm2708-rng.c 2014-12-03 19:13:34.236418001 -0600
@@ -0,0 +1,117 @@
+/**
+ * Copyright (c) 2010-2012 Broadcom. All rights reserved.
@@ -9134,9 +14849,9 @@ diff -Nur linux-3.12.26.orig/drivers/char/hw_random/bcm2708-rng.c linux-3.12.26/
+
+MODULE_DESCRIPTION("BCM2708 H/W Random Number Generator (RNG) driver");
+MODULE_LICENSE("GPL and additional rights");
-diff -Nur linux-3.12.26.orig/drivers/char/hw_random/Kconfig linux-3.12.26/drivers/char/hw_random/Kconfig
---- linux-3.12.26.orig/drivers/char/hw_random/Kconfig 2014-07-30 18:02:44.000000000 +0200
-+++ linux-3.12.26/drivers/char/hw_random/Kconfig 2014-08-06 16:50:13.945958005 +0200
+diff -Nur linux-3.12.33/drivers/char/hw_random/Kconfig linux-3.12.33-rpi/drivers/char/hw_random/Kconfig
+--- linux-3.12.33/drivers/char/hw_random/Kconfig 2014-11-15 06:28:07.000000000 -0600
++++ linux-3.12.33-rpi/drivers/char/hw_random/Kconfig 2014-12-03 19:13:34.236418001 -0600
@@ -314,3 +314,14 @@
module will be called tpm-rng.
@@ -9152,29 +14867,17 @@ diff -Nur linux-3.12.26.orig/drivers/char/hw_random/Kconfig linux-3.12.26/driver
+ module will be called bcm2708-rng.
+
+ If unsure, say N.
-diff -Nur linux-3.12.26.orig/drivers/char/hw_random/Makefile linux-3.12.26/drivers/char/hw_random/Makefile
---- linux-3.12.26.orig/drivers/char/hw_random/Makefile 2014-07-30 18:02:44.000000000 +0200
-+++ linux-3.12.26/drivers/char/hw_random/Makefile 2014-08-06 16:50:13.945958005 +0200
+diff -Nur linux-3.12.33/drivers/char/hw_random/Makefile linux-3.12.33-rpi/drivers/char/hw_random/Makefile
+--- linux-3.12.33/drivers/char/hw_random/Makefile 2014-11-15 06:28:07.000000000 -0600
++++ linux-3.12.33-rpi/drivers/char/hw_random/Makefile 2014-12-03 19:13:34.236418001 -0600
@@ -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.26.orig/drivers/char/ipmi/ipmi_bt_sm.c linux-3.12.26/drivers/char/ipmi/ipmi_bt_sm.c
---- linux-3.12.26.orig/drivers/char/ipmi/ipmi_bt_sm.c 2014-07-30 18:02:44.000000000 +0200
-+++ linux-3.12.26/drivers/char/ipmi/ipmi_bt_sm.c 2014-08-06 16:50:13.961958130 +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.26.orig/drivers/char/Kconfig linux-3.12.26/drivers/char/Kconfig
---- linux-3.12.26.orig/drivers/char/Kconfig 2014-07-30 18:02:44.000000000 +0200
-+++ linux-3.12.26/drivers/char/Kconfig 2014-08-06 16:50:14.009958507 +0200
+diff -Nur linux-3.12.33/drivers/char/Kconfig linux-3.12.33-rpi/drivers/char/Kconfig
+--- linux-3.12.33/drivers/char/Kconfig 2014-11-15 06:28:07.000000000 -0600
++++ linux-3.12.33-rpi/drivers/char/Kconfig 2014-12-03 19:13:34.232418001 -0600
@@ -574,6 +574,8 @@
source "drivers/s390/char/Kconfig"
@@ -9184,18 +14887,18 @@ diff -Nur linux-3.12.26.orig/drivers/char/Kconfig linux-3.12.26/drivers/char/Kco
config MSM_SMD_PKT
bool "Enable device interface for some SMD packet ports"
default n
-diff -Nur linux-3.12.26.orig/drivers/char/Makefile linux-3.12.26/drivers/char/Makefile
---- linux-3.12.26.orig/drivers/char/Makefile 2014-07-30 18:02:44.000000000 +0200
-+++ linux-3.12.26/drivers/char/Makefile 2014-08-06 16:50:14.021958601 +0200
+diff -Nur linux-3.12.33/drivers/char/Makefile linux-3.12.33-rpi/drivers/char/Makefile
+--- linux-3.12.33/drivers/char/Makefile 2014-11-15 06:28:07.000000000 -0600
++++ linux-3.12.33-rpi/drivers/char/Makefile 2014-12-03 19:13:34.232418001 -0600
@@ -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.26.orig/drivers/cpufreq/bcm2835-cpufreq.c linux-3.12.26/drivers/cpufreq/bcm2835-cpufreq.c
---- linux-3.12.26.orig/drivers/cpufreq/bcm2835-cpufreq.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-3.12.26/drivers/cpufreq/bcm2835-cpufreq.c 2014-08-06 16:50:14.021958601 +0200
+diff -Nur linux-3.12.33/drivers/cpufreq/bcm2835-cpufreq.c linux-3.12.33-rpi/drivers/cpufreq/bcm2835-cpufreq.c
+--- linux-3.12.33/drivers/cpufreq/bcm2835-cpufreq.c 1969-12-31 18:00:00.000000000 -0600
++++ linux-3.12.33-rpi/drivers/cpufreq/bcm2835-cpufreq.c 2014-12-03 19:13:34.264418001 -0600
@@ -0,0 +1,239 @@
+/*****************************************************************************
+* Copyright 2011 Broadcom Corporation. All rights reserved.
@@ -9436,9 +15139,9 @@ diff -Nur linux-3.12.26.orig/drivers/cpufreq/bcm2835-cpufreq.c linux-3.12.26/dri
+
+module_init(bcm2835_cpufreq_module_init);
+module_exit(bcm2835_cpufreq_module_exit);
-diff -Nur linux-3.12.26.orig/drivers/cpufreq/Kconfig.arm linux-3.12.26/drivers/cpufreq/Kconfig.arm
---- linux-3.12.26.orig/drivers/cpufreq/Kconfig.arm 2014-07-30 18:02:44.000000000 +0200
-+++ linux-3.12.26/drivers/cpufreq/Kconfig.arm 2014-08-06 16:50:14.021958601 +0200
+diff -Nur linux-3.12.33/drivers/cpufreq/Kconfig.arm linux-3.12.33-rpi/drivers/cpufreq/Kconfig.arm
+--- linux-3.12.33/drivers/cpufreq/Kconfig.arm 2014-11-15 06:28:07.000000000 -0600
++++ linux-3.12.33-rpi/drivers/cpufreq/Kconfig.arm 2014-12-03 19:13:34.264418001 -0600
@@ -228,6 +228,14 @@
help
This adds the CPUFreq driver support for SPEAr SOCs.
@@ -9454,9 +15157,9 @@ diff -Nur linux-3.12.26.orig/drivers/cpufreq/Kconfig.arm linux-3.12.26/drivers/c
config ARM_TEGRA_CPUFREQ
bool "TEGRA CPUFreq support"
depends on ARCH_TEGRA
-diff -Nur linux-3.12.26.orig/drivers/cpufreq/Makefile linux-3.12.26/drivers/cpufreq/Makefile
---- linux-3.12.26.orig/drivers/cpufreq/Makefile 2014-07-30 18:02:44.000000000 +0200
-+++ linux-3.12.26/drivers/cpufreq/Makefile 2014-08-06 16:50:14.021958601 +0200
+diff -Nur linux-3.12.33/drivers/cpufreq/Makefile linux-3.12.33-rpi/drivers/cpufreq/Makefile
+--- linux-3.12.33/drivers/cpufreq/Makefile 2014-11-15 06:28:07.000000000 -0600
++++ linux-3.12.33-rpi/drivers/cpufreq/Makefile 2014-12-03 19:13:34.264418001 -0600
@@ -76,6 +76,7 @@
obj-$(CONFIG_ARM_SA1100_CPUFREQ) += sa1100-cpufreq.o
obj-$(CONFIG_ARM_SA1110_CPUFREQ) += sa1110-cpufreq.o
@@ -9465,238 +15168,18 @@ diff -Nur linux-3.12.26.orig/drivers/cpufreq/Makefile linux-3.12.26/drivers/cpuf
obj-$(CONFIG_ARM_TEGRA_CPUFREQ) += tegra-cpufreq.o
##################################################################################
-diff -Nur linux-3.12.26.orig/drivers/cpufreq/powernow-k6.c linux-3.12.26/drivers/cpufreq/powernow-k6.c
---- linux-3.12.26.orig/drivers/cpufreq/powernow-k6.c 2014-07-30 18:02:44.000000000 +0200
-+++ linux-3.12.26/drivers/cpufreq/powernow-k6.c 2014-08-06 16:50:14.025958632 +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.26.orig/drivers/dma/bcm2708-dmaengine.c linux-3.12.26/drivers/dma/bcm2708-dmaengine.c
---- linux-3.12.26.orig/drivers/dma/bcm2708-dmaengine.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-3.12.26/drivers/dma/bcm2708-dmaengine.c 2014-08-06 16:50:14.025958632 +0200
-@@ -0,0 +1,588 @@
+diff -Nur linux-3.12.33/drivers/dma/bcm2708-dmaengine.c linux-3.12.33-rpi/drivers/dma/bcm2708-dmaengine.c
+--- linux-3.12.33/drivers/dma/bcm2708-dmaengine.c 1969-12-31 18:00:00.000000000 -0600
++++ linux-3.12.33-rpi/drivers/dma/bcm2708-dmaengine.c 2014-12-03 19:13:34.288418001 -0600
+@@ -0,0 +1,1041 @@
+/*
-+ * BCM2708 DMA engine support
++ * BCM2835 DMA engine support
+ *
-+ * This driver only supports cyclic DMA transfers
-+ * as needed for the I2S module.
++ * This driver supports cyclic and scatter/gather DMA transfers.
+ *
+ * Author: Florian Meier <florian.meier@koalo.de>
-+ * Copyright 2013
++ * Gellert Weisz <gellert@raspberrypi.org>
++ * Copyright 2013-2014
+ *
+ * Based on
+ * OMAP DMAengine support by Russell King
@@ -9720,6 +15203,7 @@ diff -Nur linux-3.12.26.orig/drivers/dma/bcm2708-dmaengine.c linux-3.12.26/drive
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
++
+#include <linux/dmaengine.h>
+#include <linux/dma-mapping.h>
+#include <linux/err.h>
@@ -9731,21 +15215,40 @@ diff -Nur linux-3.12.26.orig/drivers/dma/bcm2708-dmaengine.c linux-3.12.26/drive
+#include <linux/slab.h>
+#include <linux/io.h>
+#include <linux/spinlock.h>
-+#include <linux/irq.h>
+
-+#include "virt-dma.h"
++#ifndef CONFIG_OF
+
++/* dma manager */
+#include <mach/dma.h>
-+#include <mach/irqs.h>
+
-+struct bcm2708_dmadev {
++#define DMA_COMPLETE DMA_SUCCESS
++
++#endif
++
++#include <linux/of.h>
++#include <linux/of_dma.h>
++
++#include "virt-dma.h"
++
++
++struct bcm2835_dmadev {
+ struct dma_device ddev;
+ spinlock_t lock;
+ void __iomem *base;
+ struct device_dma_parameters dma_parms;
+};
+
-+struct bcm2708_chan {
++struct bcm2835_dma_cb {
++ uint32_t info;
++ uint32_t src;
++ uint32_t dst;
++ uint32_t length;
++ uint32_t stride;
++ uint32_t next;
++ uint32_t pad[2];
++};
++
++struct bcm2835_chan {
+ struct virt_dma_chan vc;
+ struct list_head node;
+
@@ -9753,48 +15256,106 @@ diff -Nur linux-3.12.26.orig/drivers/dma/bcm2708-dmaengine.c linux-3.12.26/drive
+ bool cyclic;
+
+ int ch;
-+ struct bcm2708_desc *desc;
++ struct bcm2835_desc *desc;
+
+ void __iomem *chan_base;
+ int irq_number;
++
++ unsigned int dreq;
+};
+
-+struct bcm2708_desc {
++struct bcm2835_desc {
+ struct virt_dma_desc vd;
+ enum dma_transfer_direction dir;
+
+ unsigned int control_block_size;
-+ struct bcm2708_dma_cb *control_block_base;
++ struct bcm2835_dma_cb *control_block_base;
+ dma_addr_t control_block_base_phys;
+
-+ unsigned frames;
++ unsigned int frames;
+ size_t size;
+};
+
-+#define BCM2708_DMA_DATA_TYPE_S8 1
-+#define BCM2708_DMA_DATA_TYPE_S16 2
-+#define BCM2708_DMA_DATA_TYPE_S32 4
-+#define BCM2708_DMA_DATA_TYPE_S128 16
++#define BCM2835_DMA_CS 0x00
++#define BCM2835_DMA_ADDR 0x04
++#define BCM2835_DMA_SOURCE_AD 0x0c
++#define BCM2835_DMA_DEST_AD 0x10
++#define BCM2835_DMA_NEXTCB 0x1C
++
++/* DMA CS Control and Status bits */
++#define BCM2835_DMA_ACTIVE BIT(0)
++#define BCM2835_DMA_INT BIT(2)
++#define BCM2835_DMA_ISPAUSED BIT(4) /* Pause requested or not active */
++#define BCM2835_DMA_ISHELD BIT(5) /* Is held by DREQ flow control */
++#define BCM2835_DMA_ERR BIT(8)
++#define BCM2835_DMA_ABORT BIT(30) /* Stop current CB, go to next, WO */
++#define BCM2835_DMA_RESET BIT(31) /* WO, self clearing */
++
++#define BCM2835_DMA_INT_EN BIT(0)
++#define BCM2835_DMA_WAIT_RESP BIT(3)
++#define BCM2835_DMA_D_INC BIT(4)
++#define BCM2835_DMA_D_WIDTH BIT(5)
++#define BCM2835_DMA_D_DREQ BIT(6)
++#define BCM2835_DMA_S_INC BIT(8)
++#define BCM2835_DMA_S_WIDTH BIT(9)
++#define BCM2835_DMA_S_DREQ BIT(10)
++
++#define BCM2835_DMA_PER_MAP(x) ((x) << 16)
++#define BCM2835_DMA_WAITS(x) (((x)&0x1f) << 21)
++
++#define SDHCI_BCM_DMA_WAITS 20 /* delays slowing DMA transfers: 0-31 */
++
++#define BCM2835_DMA_DATA_TYPE_S8 1
++#define BCM2835_DMA_DATA_TYPE_S16 2
++#define BCM2835_DMA_DATA_TYPE_S32 4
++#define BCM2835_DMA_DATA_TYPE_S128 16
++
++#define BCM2835_DMA_BULK_MASK BIT(0)
++#define BCM2835_DMA_FIQ_MASK (BIT(2) | BIT(3))
++
+
-+static inline struct bcm2708_dmadev *to_bcm2708_dma_dev(struct dma_device *d)
++/* Valid only for channels 0 - 14, 15 has its own base address */
++#define BCM2835_DMA_CHAN(n) ((n) << 8) /* Base address */
++#define BCM2835_DMA_CHANIO(base, n) ((base) + BCM2835_DMA_CHAN(n))
++
++#define MAX_LITE_TRANSFER 32768
++#define MAX_NORMAL_TRANSFER 1073741824
++
++static inline struct bcm2835_dmadev *to_bcm2835_dma_dev(struct dma_device *d)
+{
-+ return container_of(d, struct bcm2708_dmadev, ddev);
++ return container_of(d, struct bcm2835_dmadev, ddev);
+}
+
-+static inline struct bcm2708_chan *to_bcm2708_dma_chan(struct dma_chan *c)
++static inline struct bcm2835_chan *to_bcm2835_dma_chan(struct dma_chan *c)
+{
-+ return container_of(c, struct bcm2708_chan, vc.chan);
++ return container_of(c, struct bcm2835_chan, vc.chan);
+}
+
-+static inline struct bcm2708_desc *to_bcm2708_dma_desc(
++static inline struct bcm2835_desc *to_bcm2835_dma_desc(
+ struct dma_async_tx_descriptor *t)
+{
-+ return container_of(t, struct bcm2708_desc, vd.tx);
++ return container_of(t, struct bcm2835_desc, vd.tx);
++}
++
++static void dma_dumpregs(struct bcm2835_chan *c)
++{
++ pr_debug("-------------DMA DUMPREGS-------------\n");
++ pr_debug("CS= %u\n",
++ readl(c->chan_base + BCM2835_DMA_CS));
++ pr_debug("ADDR= %u\n",
++ readl(c->chan_base + BCM2835_DMA_ADDR));
++ pr_debug("SOURCE_ADDR= %u\n",
++ readl(c->chan_base + BCM2835_DMA_SOURCE_AD));
++ pr_debug("DEST_AD= %u\n",
++ readl(c->chan_base + BCM2835_DMA_DEST_AD));
++ pr_debug("NEXTCB= %u\n",
++ readl(c->chan_base + BCM2835_DMA_NEXTCB));
++ pr_debug("--------------------------------------\n");
+}
+
-+static void bcm2708_dma_desc_free(struct virt_dma_desc *vd)
++static void bcm2835_dma_desc_free(struct virt_dma_desc *vd)
+{
-+ struct bcm2708_desc *desc = container_of(vd, struct bcm2708_desc, vd);
++ struct bcm2835_desc *desc = container_of(vd, struct bcm2835_desc, vd);
+ dma_free_coherent(desc->vd.tx.chan->device->dev,
+ desc->control_block_size,
+ desc->control_block_base,
@@ -9802,10 +15363,46 @@ diff -Nur linux-3.12.26.orig/drivers/dma/bcm2708-dmaengine.c linux-3.12.26/drive
+ kfree(desc);
+}
+
-+static void bcm2708_dma_start_desc(struct bcm2708_chan *c)
++static int bcm2835_dma_abort(void __iomem *chan_base)
++{
++ unsigned long cs;
++ long int timeout = 10000;
++
++ cs = readl(chan_base + BCM2835_DMA_CS);
++ if (!(cs & BCM2835_DMA_ACTIVE))
++ return 0;
++
++ /* Write 0 to the active bit - Pause the DMA */
++ writel(0, chan_base + BCM2835_DMA_CS);
++
++ /* Wait for any current AXI transfer to complete */
++ while ((cs & BCM2835_DMA_ISPAUSED) && --timeout) {
++ cpu_relax();
++ cs = readl(chan_base + BCM2835_DMA_CS);
++ }
++
++ /* We'll un-pause when we set of our next DMA */
++ if (!timeout)
++ return -ETIMEDOUT;
++
++ if (!(cs & BCM2835_DMA_ACTIVE))
++ return 0;
++
++ /* Terminate the control block chain */
++ writel(0, chan_base + BCM2835_DMA_NEXTCB);
++
++ /* Abort the whole DMA */
++ writel(BCM2835_DMA_ABORT | BCM2835_DMA_ACTIVE,
++ chan_base + BCM2835_DMA_CS);
++
++ return 0;
++}
++
++
++static void bcm2835_dma_start_desc(struct bcm2835_chan *c)
+{
+ struct virt_dma_desc *vd = vchan_next_desc(&c->vc);
-+ struct bcm2708_desc *d;
++ struct bcm2835_desc *d;
+
+ if (!vd) {
+ c->desc = NULL;
@@ -9814,49 +15411,62 @@ diff -Nur linux-3.12.26.orig/drivers/dma/bcm2708-dmaengine.c linux-3.12.26/drive
+
+ list_del(&vd->node);
+
-+ c->desc = d = to_bcm2708_dma_desc(&vd->tx);
++ c->desc = d = to_bcm2835_dma_desc(&vd->tx);
++
++ writel(d->control_block_base_phys, c->chan_base + BCM2835_DMA_ADDR);
++ writel(BCM2835_DMA_ACTIVE, c->chan_base + BCM2835_DMA_CS);
+
-+ bcm_dma_start(c->chan_base, d->control_block_base_phys);
+}
+
-+static irqreturn_t bcm2708_dma_callback(int irq, void *data)
++static irqreturn_t bcm2835_dma_callback(int irq, void *data)
+{
-+ struct bcm2708_chan *c = data;
-+ struct bcm2708_desc *d;
++ struct bcm2835_chan *c = data;
++ struct bcm2835_desc *d;
+ unsigned long flags;
+
+ spin_lock_irqsave(&c->vc.lock, flags);
+
+ /* Acknowledge interrupt */
-+ writel(BCM2708_DMA_INT, c->chan_base + BCM2708_DMA_CS);
++ writel(BCM2835_DMA_INT, c->chan_base + BCM2835_DMA_CS);
+
+ d = c->desc;
+
+ if (d) {
-+ /* TODO Only works for cyclic DMA */
-+ vchan_cyclic_callback(&d->vd);
-+ }
++ if (c->cyclic) {
++ vchan_cyclic_callback(&d->vd);
+
-+ /* Keep the DMA engine running */
-+ dsb(); /* ARM synchronization barrier */
-+ writel(BCM2708_DMA_ACTIVE, c->chan_base + BCM2708_DMA_CS);
++ /* Keep the DMA engine running */
++ writel(BCM2835_DMA_ACTIVE,
++ c->chan_base + BCM2835_DMA_CS);
++
++ } else {
++ vchan_cookie_complete(&c->desc->vd);
++ bcm2835_dma_start_desc(c);
++ }
++ }
+
+ spin_unlock_irqrestore(&c->vc.lock, flags);
+
+ return IRQ_HANDLED;
+}
+
-+static int bcm2708_dma_alloc_chan_resources(struct dma_chan *chan)
++static int bcm2835_dma_alloc_chan_resources(struct dma_chan *chan)
+{
-+ struct bcm2708_chan *c = to_bcm2708_dma_chan(chan);
++ struct bcm2835_chan *c = to_bcm2835_dma_chan(chan);
++ int ret;
++
++ dev_dbg(c->vc.chan.device->dev,
++ "Allocating DMA channel %d\n", c->ch);
++
++ ret = request_irq(c->irq_number,
++ bcm2835_dma_callback, 0, "DMA IRQ", c);
+
-+ return request_irq(c->irq_number,
-+ bcm2708_dma_callback, 0, "DMA IRQ", c);
++ return ret;
+}
+
-+static void bcm2708_dma_free_chan_resources(struct dma_chan *chan)
++static void bcm2835_dma_free_chan_resources(struct dma_chan *chan)
+{
-+ struct bcm2708_chan *c = to_bcm2708_dma_chan(chan);
++ struct bcm2835_chan *c = to_bcm2835_dma_chan(chan);
+
+ vchan_free_chan_resources(&c->vc);
+ free_irq(c->irq_number, c);
@@ -9864,18 +15474,18 @@ diff -Nur linux-3.12.26.orig/drivers/dma/bcm2708-dmaengine.c linux-3.12.26/drive
+ dev_dbg(c->vc.chan.device->dev, "Freeing DMA channel %u\n", c->ch);
+}
+
-+static size_t bcm2708_dma_desc_size(struct bcm2708_desc *d)
++static size_t bcm2835_dma_desc_size(struct bcm2835_desc *d)
+{
+ return d->size;
+}
+
-+static size_t bcm2708_dma_desc_size_pos(struct bcm2708_desc *d, dma_addr_t addr)
++static size_t bcm2835_dma_desc_size_pos(struct bcm2835_desc *d, dma_addr_t addr)
+{
-+ unsigned i;
++ unsigned int i;
+ size_t size;
+
+ for (size = i = 0; i < d->frames; i++) {
-+ struct bcm2708_dma_cb *control_block =
++ struct bcm2835_dma_cb *control_block =
+ &d->control_block_base[i];
+ size_t this_size = control_block->length;
+ dma_addr_t dma;
@@ -9894,35 +15504,36 @@ diff -Nur linux-3.12.26.orig/drivers/dma/bcm2708-dmaengine.c linux-3.12.26/drive
+ return size;
+}
+
-+static enum dma_status bcm2708_dma_tx_status(struct dma_chan *chan,
++static enum dma_status bcm2835_dma_tx_status(struct dma_chan *chan,
+ dma_cookie_t cookie, struct dma_tx_state *txstate)
+{
-+ struct bcm2708_chan *c = to_bcm2708_dma_chan(chan);
++ struct bcm2835_chan *c = to_bcm2835_dma_chan(chan);
++ struct bcm2835_desc *d;
+ struct virt_dma_desc *vd;
+ enum dma_status ret;
+ unsigned long flags;
++ dma_addr_t pos;
+
+ ret = dma_cookie_status(chan, cookie, txstate);
-+ if (ret == DMA_SUCCESS || !txstate)
++ if (ret == DMA_COMPLETE || !txstate)
+ return ret;
+
+ spin_lock_irqsave(&c->vc.lock, flags);
+ vd = vchan_find_desc(&c->vc, cookie);
+ if (vd) {
+ txstate->residue =
-+ bcm2708_dma_desc_size(to_bcm2708_dma_desc(&vd->tx));
++ bcm2835_dma_desc_size(to_bcm2835_dma_desc(&vd->tx));
+ } else if (c->desc && c->desc->vd.tx.cookie == cookie) {
-+ struct bcm2708_desc *d = c->desc;
-+ dma_addr_t pos;
++ d = c->desc;
+
+ if (d->dir == DMA_MEM_TO_DEV)
-+ pos = readl(c->chan_base + BCM2708_DMA_SOURCE_AD);
++ pos = readl(c->chan_base + BCM2835_DMA_SOURCE_AD);
+ else if (d->dir == DMA_DEV_TO_MEM)
-+ pos = readl(c->chan_base + BCM2708_DMA_DEST_AD);
++ pos = readl(c->chan_base + BCM2835_DMA_DEST_AD);
+ else
+ pos = 0;
+
-+ txstate->residue = bcm2708_dma_desc_size_pos(d, pos);
++ txstate->residue = bcm2835_dma_desc_size_pos(d, pos);
+ } else {
+ txstate->residue = 0;
+ }
@@ -9932,50 +15543,50 @@ diff -Nur linux-3.12.26.orig/drivers/dma/bcm2708-dmaengine.c linux-3.12.26/drive
+ return ret;
+}
+
-+static void bcm2708_dma_issue_pending(struct dma_chan *chan)
++static void bcm2835_dma_issue_pending(struct dma_chan *chan)
+{
-+ struct bcm2708_chan *c = to_bcm2708_dma_chan(chan);
++ struct bcm2835_chan *c = to_bcm2835_dma_chan(chan);
+ unsigned long flags;
+
-+ c->cyclic = true; /* Nothing else is implemented */
-+
+ spin_lock_irqsave(&c->vc.lock, flags);
+ if (vchan_issue_pending(&c->vc) && !c->desc)
-+ bcm2708_dma_start_desc(c);
++ bcm2835_dma_start_desc(c);
+
+ spin_unlock_irqrestore(&c->vc.lock, flags);
+}
+
-+static struct dma_async_tx_descriptor *bcm2708_dma_prep_dma_cyclic(
++static struct dma_async_tx_descriptor *bcm2835_dma_prep_dma_cyclic(
+ struct dma_chan *chan, dma_addr_t buf_addr, size_t buf_len,
+ size_t period_len, enum dma_transfer_direction direction,
+ unsigned long flags, void *context)
+{
-+ struct bcm2708_chan *c = to_bcm2708_dma_chan(chan);
++ struct bcm2835_chan *c = to_bcm2835_dma_chan(chan);
+ enum dma_slave_buswidth dev_width;
-+ struct bcm2708_desc *d;
++ struct bcm2835_desc *d;
+ dma_addr_t dev_addr;
-+ unsigned es, sync_type;
-+ unsigned frame;
++ unsigned int es, sync_type;
++ unsigned int frame;
+
+ /* Grab configuration */
++ if (!is_slave_direction(direction)) {
++ dev_err(chan->device->dev, "%s: bad direction?\n", __func__);
++ return NULL;
++ }
++
+ if (direction == DMA_DEV_TO_MEM) {
+ dev_addr = c->cfg.src_addr;
+ dev_width = c->cfg.src_addr_width;
-+ sync_type = BCM2708_DMA_S_DREQ;
-+ } else if (direction == DMA_MEM_TO_DEV) {
++ sync_type = BCM2835_DMA_S_DREQ;
++ } else {
+ dev_addr = c->cfg.dst_addr;
+ dev_width = c->cfg.dst_addr_width;
-+ sync_type = BCM2708_DMA_D_DREQ;
-+ } else {
-+ dev_err(chan->device->dev, "%s: bad direction?\n", __func__);
-+ return NULL;
++ sync_type = BCM2835_DMA_D_DREQ;
+ }
+
+ /* Bus width translates to the element size (ES) */
+ switch (dev_width) {
+ case DMA_SLAVE_BUSWIDTH_4_BYTES:
-+ es = BCM2708_DMA_DATA_TYPE_S32;
++ es = BCM2835_DMA_DATA_TYPE_S32;
+ break;
+ default:
+ return NULL;
@@ -9990,7 +15601,7 @@ diff -Nur linux-3.12.26.orig/drivers/dma/bcm2708-dmaengine.c linux-3.12.26/drive
+ d->frames = buf_len / period_len;
+
+ /* Allocate memory for control blocks */
-+ d->control_block_size = d->frames * sizeof(struct bcm2708_dma_cb);
++ d->control_block_size = d->frames * sizeof(struct bcm2835_dma_cb);
+ d->control_block_base = dma_zalloc_coherent(chan->device->dev,
+ d->control_block_size, &d->control_block_base_phys,
+ GFP_NOWAIT);
@@ -10005,22 +15616,22 @@ diff -Nur linux-3.12.26.orig/drivers/dma/bcm2708-dmaengine.c linux-3.12.26/drive
+ * for each frame and link them together.
+ */
+ for (frame = 0; frame < d->frames; frame++) {
-+ struct bcm2708_dma_cb *control_block =
++ struct bcm2835_dma_cb *control_block =
+ &d->control_block_base[frame];
+
+ /* Setup adresses */
+ if (d->dir == DMA_DEV_TO_MEM) {
-+ control_block->info = BCM2708_DMA_D_INC;
++ control_block->info = BCM2835_DMA_D_INC;
+ control_block->src = dev_addr;
+ control_block->dst = buf_addr + frame * period_len;
+ } else {
-+ control_block->info = BCM2708_DMA_S_INC;
++ control_block->info = BCM2835_DMA_S_INC;
+ control_block->src = buf_addr + frame * period_len;
+ control_block->dst = dev_addr;
+ }
+
+ /* Enable interrupt */
-+ control_block->info |= BCM2708_DMA_INT_EN;
++ control_block->info |= BCM2835_DMA_INT_EN;
+
+ /* Setup synchronization */
+ if (sync_type != 0)
@@ -10029,7 +15640,7 @@ diff -Nur linux-3.12.26.orig/drivers/dma/bcm2708-dmaengine.c linux-3.12.26/drive
+ /* Setup DREQ channel */
+ if (c->cfg.slave_id != 0)
+ control_block->info |=
-+ BCM2708_DMA_PER_MAP(c->cfg.slave_id);
++ BCM2835_DMA_PER_MAP(c->cfg.slave_id);
+
+ /* Length of a frame */
+ control_block->length = period_len;
@@ -10037,18 +15648,166 @@ diff -Nur linux-3.12.26.orig/drivers/dma/bcm2708-dmaengine.c linux-3.12.26/drive
+
+ /*
+ * Next block is the next frame.
-+ * This DMA engine driver currently only supports cyclic DMA.
++ * This function is called on cyclic DMA transfers.
+ * Therefore, wrap around at number of frames.
+ */
+ control_block->next = d->control_block_base_phys +
-+ sizeof(struct bcm2708_dma_cb)
++ sizeof(struct bcm2835_dma_cb)
+ * ((frame + 1) % d->frames);
+ }
+
++ c->cyclic = true;
++
++ return vchan_tx_prep(&c->vc, &d->vd, flags);
++}
++
++
++static struct dma_async_tx_descriptor *bcm2835_dma_prep_slave_sg(
++ struct dma_chan *chan, struct scatterlist *sgl,
++ unsigned int sg_len, enum dma_transfer_direction direction,
++ unsigned long flags, void *context)
++{
++ struct bcm2835_chan *c = to_bcm2835_dma_chan(chan);
++ enum dma_slave_buswidth dev_width;
++ struct bcm2835_desc *d;
++ dma_addr_t dev_addr;
++ struct scatterlist *sgent;
++ unsigned int es, sync_type;
++ unsigned int i, j, splitct, max_size;
++
++ if (!is_slave_direction(direction)) {
++ dev_err(chan->device->dev, "%s: bad direction?\n", __func__);
++ return NULL;
++ }
++
++ if (direction == DMA_DEV_TO_MEM) {
++ dev_addr = c->cfg.src_addr;
++ dev_width = c->cfg.src_addr_width;
++ sync_type = BCM2835_DMA_S_DREQ;
++ } else {
++ dev_addr = c->cfg.dst_addr;
++ dev_width = c->cfg.dst_addr_width;
++ sync_type = BCM2835_DMA_D_DREQ;
++ }
++
++ /* Bus width translates to the element size (ES) */
++ switch (dev_width) {
++ case DMA_SLAVE_BUSWIDTH_4_BYTES:
++ es = BCM2835_DMA_DATA_TYPE_S32;
++ break;
++ default:
++ return NULL;
++ }
++
++ /* Now allocate and setup the descriptor. */
++ d = kzalloc(sizeof(*d), GFP_NOWAIT);
++ if (!d)
++ return NULL;
++
++ d->dir = direction;
++
++ if (c->ch >= 8) /* we have a LITE channel */
++ max_size = MAX_LITE_TRANSFER;
++ else
++ max_size = MAX_NORMAL_TRANSFER;
++
++ /* We store the length of the SG list in d->frames
++ taking care to account for splitting up transfers
++ too large for a LITE channel */
++
++ d->frames = 0;
++ for_each_sg(sgl, sgent, sg_len, i) {
++ uint32_t len = sg_dma_len(sgent);
++ d->frames += 1 + len / max_size;
++ }
++
++ /* Allocate memory for control blocks */
++ d->control_block_size = d->frames * sizeof(struct bcm2835_dma_cb);
++ d->control_block_base = dma_zalloc_coherent(chan->device->dev,
++ d->control_block_size, &d->control_block_base_phys,
++ GFP_NOWAIT);
++
++ if (!d->control_block_base) {
++ kfree(d);
++ return NULL;
++ }
++
++ /*
++ * Iterate over all SG entries, create a control block
++ * for each frame and link them together.
++ */
++
++ /* we count the number of times an SG entry had to be splitct
++ as a result of using a LITE channel */
++ splitct = 0;
++
++ for_each_sg(sgl, sgent, sg_len, i) {
++ dma_addr_t addr = sg_dma_address(sgent);
++ uint32_t len = sg_dma_len(sgent);
++
++ for (j = 0; j < len; j += max_size) {
++ struct bcm2835_dma_cb *control_block =
++ &d->control_block_base[i+splitct];
++
++ /* Setup adresses */
++ if (d->dir == DMA_DEV_TO_MEM) {
++ control_block->info = BCM2835_DMA_D_INC |
++ BCM2835_DMA_D_WIDTH | BCM2835_DMA_S_DREQ;
++ control_block->src = dev_addr;
++ control_block->dst = addr + (dma_addr_t)j;
++ } else {
++ control_block->info = BCM2835_DMA_S_INC |
++ BCM2835_DMA_S_WIDTH | BCM2835_DMA_D_DREQ;
++ control_block->src = addr + (dma_addr_t)j;
++ control_block->dst = dev_addr;
++ }
++
++ /* Common part */
++ control_block->info |= BCM2835_DMA_WAITS(SDHCI_BCM_DMA_WAITS);
++ control_block->info |= BCM2835_DMA_WAIT_RESP;
++
++ /* Enable */
++ if (i == sg_len-1 && len-j <= max_size)
++ control_block->info |= BCM2835_DMA_INT_EN;
++
++ /* Setup synchronization */
++ if (sync_type != 0)
++ control_block->info |= sync_type;
++
++ /* Setup DREQ channel */
++ c->dreq = c->cfg.slave_id; /* DREQ loaded from config */
++
++ if (c->dreq != 0)
++ control_block->info |=
++ BCM2835_DMA_PER_MAP(c->dreq);
++
++ /* Length of a frame */
++ control_block->length = min(len-j, max_size);
++ d->size += control_block->length;
++
++ /*
++ * Next block is the next frame.
++ */
++ if (i < sg_len-1 || len-j > max_size) {
++ /* next block is the next frame. */
++ control_block->next = d->control_block_base_phys +
++ sizeof(struct bcm2835_dma_cb) * (i + splitct + 1);
++ } else {
++ /* next block is empty. */
++ control_block->next = 0;
++ }
++
++ if (len-j > max_size)
++ splitct++;
++ }
++ }
++
++ c->cyclic = false;
++
+ return vchan_tx_prep(&c->vc, &d->vd, flags);
+}
+
-+static int bcm2708_dma_slave_config(struct bcm2708_chan *c,
++static int bcm2835_dma_slave_config(struct bcm2835_chan *c,
+ struct dma_slave_config *cfg)
+{
+ if ((cfg->direction == DMA_DEV_TO_MEM &&
@@ -10064,9 +15823,9 @@ diff -Nur linux-3.12.26.orig/drivers/dma/bcm2708-dmaengine.c linux-3.12.26/drive
+ return 0;
+}
+
-+static int bcm2708_dma_terminate_all(struct bcm2708_chan *c)
++static int bcm2835_dma_terminate_all(struct bcm2835_chan *c)
+{
-+ struct bcm2708_dmadev *d = to_bcm2708_dma_dev(c->vc.chan.device);
++ struct bcm2835_dmadev *d = to_bcm2835_dma_dev(c->vc.chan.device);
+ unsigned long flags;
+ int timeout = 10000;
+ LIST_HEAD(head);
@@ -10085,19 +15844,18 @@ diff -Nur linux-3.12.26.orig/drivers/dma/bcm2708-dmaengine.c linux-3.12.26/drive
+ */
+ if (c->desc) {
+ c->desc = NULL;
-+ bcm_dma_abort(c->chan_base);
++ bcm2835_dma_abort(c->chan_base);
+
+ /* Wait for stopping */
-+ while (timeout > 0) {
-+ timeout--;
-+ if (!(readl(c->chan_base + BCM2708_DMA_CS) &
-+ BCM2708_DMA_ACTIVE))
++ while (--timeout) {
++ if (!(readl(c->chan_base + BCM2835_DMA_CS) &
++ BCM2835_DMA_ACTIVE))
+ break;
+
+ cpu_relax();
+ }
+
-+ if (timeout <= 0)
++ if (!timeout)
+ dev_err(d->ddev.dev, "DMA transfer could not be terminated\n");
+ }
+
@@ -10108,34 +15866,57 @@ diff -Nur linux-3.12.26.orig/drivers/dma/bcm2708-dmaengine.c linux-3.12.26/drive
+ return 0;
+}
+
-+static int bcm2708_dma_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd,
++static int bcm2835_dma_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd,
+ unsigned long arg)
+{
-+ struct bcm2708_chan *c = to_bcm2708_dma_chan(chan);
++ struct bcm2835_chan *c = to_bcm2835_dma_chan(chan);
+
+ switch (cmd) {
+ case DMA_SLAVE_CONFIG:
-+ return bcm2708_dma_slave_config(c,
++ return bcm2835_dma_slave_config(c,
+ (struct dma_slave_config *)arg);
+
+ case DMA_TERMINATE_ALL:
-+ return bcm2708_dma_terminate_all(c);
++ return bcm2835_dma_terminate_all(c);
+
+ default:
+ return -ENXIO;
+ }
+}
+
-+static int bcm2708_dma_chan_init(struct bcm2708_dmadev *d, void __iomem* chan_base,
-+ int chan_id, int irq)
++#ifdef CONFIG_OF
++static int bcm2835_dma_chan_init(struct bcm2835_dmadev *d, int chan_id, int irq)
++{
++ struct bcm2835_chan *c;
++
++ c = devm_kzalloc(d->ddev.dev, sizeof(*c), GFP_KERNEL);
++ if (!c)
++ return -ENOMEM;
++
++ c->vc.desc_free = bcm2835_dma_desc_free;
++ vchan_init(&c->vc, &d->ddev);
++ INIT_LIST_HEAD(&c->node);
++
++ d->ddev.chancnt++;
++
++ c->chan_base = BCM2835_DMA_CHANIO(d->base, chan_id);
++ c->ch = chan_id;
++ c->irq_number = irq;
++
++ return 0;
++}
++#endif
++
++static int bcm2708_dma_chan_init(struct bcm2835_dmadev *d,
++ void __iomem *chan_base, int chan_id, int irq)
+{
-+ struct bcm2708_chan *c;
++ struct bcm2835_chan *c;
+
+ c = devm_kzalloc(d->ddev.dev, sizeof(*c), GFP_KERNEL);
+ if (!c)
+ return -ENOMEM;
+
-+ c->vc.desc_free = bcm2708_dma_desc_free;
++ c->vc.desc_free = bcm2835_dma_desc_free;
+ vchan_init(&c->vc, &d->ddev);
+ INIT_LIST_HEAD(&c->node);
+
@@ -10148,30 +15929,81 @@ diff -Nur linux-3.12.26.orig/drivers/dma/bcm2708-dmaengine.c linux-3.12.26/drive
+ return 0;
+}
+
-+static void bcm2708_dma_free(struct bcm2708_dmadev *od)
++
++static void bcm2835_dma_free(struct bcm2835_dmadev *od)
+{
-+ while (!list_empty(&od->ddev.channels)) {
-+ struct bcm2708_chan *c = list_first_entry(&od->ddev.channels,
-+ struct bcm2708_chan, vc.chan.device_node);
++ struct bcm2835_chan *c, *next;
+
++ list_for_each_entry_safe(c, next, &od->ddev.channels,
++ vc.chan.device_node) {
+ list_del(&c->vc.chan.device_node);
+ tasklet_kill(&c->vc.task);
+ }
+}
+
-+static int bcm2708_dma_probe(struct platform_device *pdev)
++static const struct of_device_id bcm2835_dma_of_match[] = {
++ { .compatible = "brcm,bcm2835-dma", },
++ {},
++};
++MODULE_DEVICE_TABLE(of, bcm2835_dma_of_match);
++
++#ifdef CONFIG_OF
++static struct dma_chan *bcm2835_dma_xlate(struct of_phandle_args *spec,
++ struct of_dma *ofdma)
++{
++ struct bcm2835_dmadev *d = ofdma->of_dma_data;
++ struct dma_chan *chan;
++
++ chan = dma_get_any_slave_channel(&d->ddev);
++ if (!chan)
++ return NULL;
++
++ /* Set DREQ from param */
++ to_bcm2835_dma_chan(chan)->dreq = spec->args[0];
++
++ return chan;
++}
++#endif
++
++static int bcm2835_dma_device_slave_caps(struct dma_chan *dchan,
++ struct dma_slave_caps *caps)
+{
-+ struct bcm2708_dmadev *od;
-+ int rc, i;
++ caps->src_addr_widths = BIT(DMA_SLAVE_BUSWIDTH_4_BYTES);
++ caps->dstn_addr_widths = BIT(DMA_SLAVE_BUSWIDTH_4_BYTES);
++ caps->directions = BIT(DMA_DEV_TO_MEM) | BIT(DMA_MEM_TO_DEV);
++ caps->cmd_pause = false;
++ caps->cmd_terminate = true;
++
++ return 0;
++}
++
++static int bcm2835_dma_probe(struct platform_device *pdev)
++{
++ struct bcm2835_dmadev *od;
++#ifdef CONFIG_OF
++ struct resource *res;
++ void __iomem *base;
++ uint32_t chans_available;
++#endif
++ int rc;
++ int i;
++ int irq;
++
+
+ if (!pdev->dev.dma_mask)
+ pdev->dev.dma_mask = &pdev->dev.coherent_dma_mask;
+
++ /* If CONFIG_OF is selected, device tree is used */
++ /* hence the difference between probing */
++
++#ifndef CONFIG_OF
++
+ rc = dma_set_mask(&pdev->dev, DMA_BIT_MASK(32));
+ if (rc)
+ return rc;
+ dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32));
+
++
+ od = devm_kzalloc(&pdev->dev, sizeof(*od), GFP_KERNEL);
+ if (!od)
+ return -ENOMEM;
@@ -10179,25 +16011,29 @@ diff -Nur linux-3.12.26.orig/drivers/dma/bcm2708-dmaengine.c linux-3.12.26/drive
+ pdev->dev.dma_parms = &od->dma_parms;
+ dma_set_max_seg_size(&pdev->dev, 0x3FFFFFFF);
+
++
+ dma_cap_set(DMA_SLAVE, od->ddev.cap_mask);
++ dma_cap_set(DMA_PRIVATE, od->ddev.cap_mask);
+ dma_cap_set(DMA_CYCLIC, od->ddev.cap_mask);
-+ od->ddev.device_alloc_chan_resources = bcm2708_dma_alloc_chan_resources;
-+ od->ddev.device_free_chan_resources = bcm2708_dma_free_chan_resources;
-+ od->ddev.device_tx_status = bcm2708_dma_tx_status;
-+ od->ddev.device_issue_pending = bcm2708_dma_issue_pending;
-+ od->ddev.device_prep_dma_cyclic = bcm2708_dma_prep_dma_cyclic;
-+ od->ddev.device_control = bcm2708_dma_control;
++ od->ddev.device_alloc_chan_resources = bcm2835_dma_alloc_chan_resources;
++ od->ddev.device_free_chan_resources = bcm2835_dma_free_chan_resources;
++ od->ddev.device_tx_status = bcm2835_dma_tx_status;
++ od->ddev.device_issue_pending = bcm2835_dma_issue_pending;
++ od->ddev.device_slave_caps = bcm2835_dma_device_slave_caps;
++ od->ddev.device_prep_dma_cyclic = bcm2835_dma_prep_dma_cyclic;
++ od->ddev.device_prep_slave_sg = bcm2835_dma_prep_slave_sg;
++ od->ddev.device_control = bcm2835_dma_control;
+ od->ddev.dev = &pdev->dev;
+ INIT_LIST_HEAD(&od->ddev.channels);
+ spin_lock_init(&od->lock);
+
+ platform_set_drvdata(pdev, od);
+
-+ for (i = 0; i < 16; i++) {
-+ void __iomem* chan_base;
-+ int chan_id, irq;
++ for (i = 0; i < 5; i++) {
++ void __iomem *chan_base;
++ int chan_id;
+
-+ chan_id = bcm_dma_chan_alloc(BCM_DMA_FEATURE_FAST,
++ chan_id = bcm_dma_chan_alloc(BCM_DMA_FEATURE_LITE,
+ &chan_base,
+ &irq);
+
@@ -10205,38 +16041,121 @@ diff -Nur linux-3.12.26.orig/drivers/dma/bcm2708-dmaengine.c linux-3.12.26/drive
+ break;
+
+ rc = bcm2708_dma_chan_init(od, chan_base, chan_id, irq);
-+ if (rc) {
-+ bcm2708_dma_free(od);
-+ return rc;
++ if (rc)
++ goto err_no_dma;
++ }
++#else
++ rc = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32));
++ if (rc)
++ return rc;
++
++
++ od = devm_kzalloc(&pdev->dev, sizeof(*od), GFP_KERNEL);
++ if (!od)
++ return -ENOMEM;
++
++ pdev->dev.dma_parms = &od->dma_parms;
++ dma_set_max_seg_size(&pdev->dev, 0x3FFFFFFF);
++
++
++ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++ base = devm_ioremap_resource(&pdev->dev, res);
++ if (IS_ERR(base))
++ return PTR_ERR(base);
++
++ od->base = base;
++
++
++ dma_cap_set(DMA_SLAVE, od->ddev.cap_mask);
++ dma_cap_set(DMA_PRIVATE, od->ddev.cap_mask);
++ dma_cap_set(DMA_CYCLIC, od->ddev.cap_mask);
++ od->ddev.device_alloc_chan_resources = bcm2835_dma_alloc_chan_resources;
++ od->ddev.device_free_chan_resources = bcm2835_dma_free_chan_resources;
++ od->ddev.device_tx_status = bcm2835_dma_tx_status;
++ od->ddev.device_issue_pending = bcm2835_dma_issue_pending;
++ od->ddev.device_slave_caps = bcm2835_dma_device_slave_caps;
++ od->ddev.device_prep_dma_cyclic = bcm2835_dma_prep_dma_cyclic;
++ od->ddev.device_prep_slave_sg = bcm2835_dma_prep_slave_sg;
++ od->ddev.device_control = bcm2835_dma_control;
++ od->ddev.dev = &pdev->dev;
++ INIT_LIST_HEAD(&od->ddev.channels);
++ spin_lock_init(&od->lock);
++
++ platform_set_drvdata(pdev, od);
++
++
++ /* Request DMA channel mask from device tree */
++ if (of_property_read_u32(pdev->dev.of_node,
++ "brcm,dma-channel-mask",
++ &chans_available)) {
++ dev_err(&pdev->dev, "Failed to get channel mask\n");
++ rc = -EINVAL;
++ goto err_no_dma;
++ }
++
++
++ /*
++ * Do not use the FIQ and BULK channels,
++ * because they are used by the GPU.
++ */
++ chans_available &= ~(BCM2835_DMA_FIQ_MASK | BCM2835_DMA_BULK_MASK);
++
++
++ for (i = 0; i < pdev->num_resources; i++) {
++ irq = platform_get_irq(pdev, i);
++ if (irq < 0)
++ break;
++
++ if (chans_available & (1 << i)) {
++ rc = bcm2835_dma_chan_init(od, i, irq);
++ if (rc)
++ goto err_no_dma;
+ }
+ }
+
++ dev_dbg(&pdev->dev, "Initialized %i DMA channels\n", i);
++
++ /* Device-tree DMA controller registration */
++ rc = of_dma_controller_register(pdev->dev.of_node,
++ bcm2835_dma_xlate, od);
++ if (rc) {
++ dev_err(&pdev->dev, "Failed to register DMA controller\n");
++ goto err_no_dma;
++ }
++#endif
++
+ rc = dma_async_device_register(&od->ddev);
+ if (rc) {
+ dev_err(&pdev->dev,
+ "Failed to register slave DMA engine device: %d\n", rc);
-+ bcm2708_dma_free(od);
-+ return rc;
++ goto err_no_dma;
+ }
+
-+ dev_dbg(&pdev->dev, "Load BCM2708 DMA engine driver\n");
++ dev_info(&pdev->dev, "Load BCM2835 DMA engine driver\n");
+
++ return 0;
++
++err_no_dma:
++ bcm2835_dma_free(od);
+ return rc;
+}
+
-+static int bcm2708_dma_remove(struct platform_device *pdev)
++static int bcm2835_dma_remove(struct platform_device *pdev)
+{
-+ struct bcm2708_dmadev *od = platform_get_drvdata(pdev);
++ struct bcm2835_dmadev *od = platform_get_drvdata(pdev);
+
+ dma_async_device_unregister(&od->ddev);
-+ bcm2708_dma_free(od);
++ bcm2835_dma_free(od);
+
+ return 0;
+}
+
-+static struct platform_driver bcm2708_dma_driver = {
-+ .probe = bcm2708_dma_probe,
-+ .remove = bcm2708_dma_remove,
++#ifndef CONFIG_OF
++
++
++static struct platform_driver bcm2835_dma_driver = {
++ .probe = bcm2835_dma_probe,
++ .remove = bcm2835_dma_remove,
+ .driver = {
+ .name = "bcm2708-dmaengine",
+ .owner = THIS_MODULE,
@@ -10245,41 +16164,58 @@ diff -Nur linux-3.12.26.orig/drivers/dma/bcm2708-dmaengine.c linux-3.12.26/drive
+
+static struct platform_device *pdev;
+
-+static const struct platform_device_info bcm2708_dma_dev_info = {
++static const struct platform_device_info bcm2835_dma_dev_info = {
+ .name = "bcm2708-dmaengine",
+ .id = -1,
+};
+
-+static int bcm2708_dma_init(void)
++static int bcm2835_dma_init(void)
+{
-+ int rc = platform_driver_register(&bcm2708_dma_driver);
++ int rc = platform_driver_register(&bcm2835_dma_driver);
+
+ if (rc == 0) {
-+ pdev = platform_device_register_full(&bcm2708_dma_dev_info);
++ pdev = platform_device_register_full(&bcm2835_dma_dev_info);
+ if (IS_ERR(pdev)) {
-+ platform_driver_unregister(&bcm2708_dma_driver);
++ platform_driver_unregister(&bcm2835_dma_driver);
+ rc = PTR_ERR(pdev);
+ }
+ }
+
+ return rc;
+}
-+subsys_initcall(bcm2708_dma_init);
++module_init(bcm2835_dma_init); /* preferable to subsys_initcall */
+
-+static void __exit bcm2708_dma_exit(void)
++static void __exit bcm2835_dma_exit(void)
+{
+ platform_device_unregister(pdev);
-+ platform_driver_unregister(&bcm2708_dma_driver);
++ platform_driver_unregister(&bcm2835_dma_driver);
+}
-+module_exit(bcm2708_dma_exit);
++module_exit(bcm2835_dma_exit);
++
++#else
+
-+MODULE_ALIAS("platform:bcm2708-dma");
-+MODULE_DESCRIPTION("BCM2708 DMA engine driver");
++static struct platform_driver bcm2835_dma_driver = {
++ .probe = bcm2835_dma_probe,
++ .remove = bcm2835_dma_remove,
++ .driver = {
++ .name = "bcm2835-dma",
++ .owner = THIS_MODULE,
++ .of_match_table = of_match_ptr(bcm2835_dma_of_match),
++ },
++};
++
++module_platform_driver(bcm2835_dma_driver);
++
++#endif
++
++MODULE_ALIAS("platform:bcm2835-dma");
++MODULE_DESCRIPTION("BCM2835 DMA engine driver");
+MODULE_AUTHOR("Florian Meier <florian.meier@koalo.de>");
++MODULE_AUTHOR("Gellert Weisz <gellert@raspberrypi.org>");
+MODULE_LICENSE("GPL v2");
-diff -Nur linux-3.12.26.orig/drivers/dma/Kconfig linux-3.12.26/drivers/dma/Kconfig
---- linux-3.12.26.orig/drivers/dma/Kconfig 2014-07-30 18:02:44.000000000 +0200
-+++ linux-3.12.26/drivers/dma/Kconfig 2014-08-06 16:50:14.053958853 +0200
+diff -Nur linux-3.12.33/drivers/dma/Kconfig linux-3.12.33-rpi/drivers/dma/Kconfig
+--- linux-3.12.33/drivers/dma/Kconfig 2014-11-15 06:28:07.000000000 -0600
++++ linux-3.12.33-rpi/drivers/dma/Kconfig 2014-12-03 19:13:34.284418001 -0600
@@ -288,6 +288,12 @@
select DMA_ENGINE
select DMA_VIRTUAL_CHANNELS
@@ -10293,9 +16229,9 @@ diff -Nur linux-3.12.26.orig/drivers/dma/Kconfig linux-3.12.26/drivers/dma/Kconf
config TI_CPPI41
tristate "AM33xx CPPI41 DMA support"
depends on ARCH_OMAP
-diff -Nur linux-3.12.26.orig/drivers/dma/Makefile linux-3.12.26/drivers/dma/Makefile
---- linux-3.12.26.orig/drivers/dma/Makefile 2014-07-30 18:02:44.000000000 +0200
-+++ linux-3.12.26/drivers/dma/Makefile 2014-08-06 16:50:14.053958853 +0200
+diff -Nur linux-3.12.33/drivers/dma/Makefile linux-3.12.33-rpi/drivers/dma/Makefile
+--- linux-3.12.33/drivers/dma/Makefile 2014-11-15 06:28:07.000000000 -0600
++++ linux-3.12.33-rpi/drivers/dma/Makefile 2014-12-03 19:13:34.284418001 -0600
@@ -37,6 +37,7 @@
obj-$(CONFIG_DMA_SA11X0) += sa11x0-dma.o
obj-$(CONFIG_MMP_TDMA) += mmp_tdma.o
@@ -10304,309 +16240,36 @@ diff -Nur linux-3.12.26.orig/drivers/dma/Makefile linux-3.12.26/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.26.orig/drivers/gpu/drm/cirrus/cirrus_fbdev.c linux-3.12.26/drivers/gpu/drm/cirrus/cirrus_fbdev.c
---- linux-3.12.26.orig/drivers/gpu/drm/cirrus/cirrus_fbdev.c 2014-07-30 18:02:44.000000000 +0200
-+++ linux-3.12.26/drivers/gpu/drm/cirrus/cirrus_fbdev.c 2014-08-06 16:50:14.081959072 +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.26.orig/drivers/gpu/drm/cirrus/cirrus_mode.c linux-3.12.26/drivers/gpu/drm/cirrus/cirrus_mode.c
---- linux-3.12.26.orig/drivers/gpu/drm/cirrus/cirrus_mode.c 2014-07-30 18:02:44.000000000 +0200
-+++ linux-3.12.26/drivers/gpu/drm/cirrus/cirrus_mode.c 2014-08-06 16:50:14.109959292 +0200
-@@ -497,12 +497,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.26.orig/drivers/gpu/drm/drm_edid.c linux-3.12.26/drivers/gpu/drm/drm_edid.c
---- linux-3.12.26.orig/drivers/gpu/drm/drm_edid.c 2014-07-30 18:02:44.000000000 +0200
-+++ linux-3.12.26/drivers/gpu/drm/drm_edid.c 2014-08-06 16:50:14.129959449 +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.26.orig/drivers/gpu/drm/drm_fb_helper.c linux-3.12.26/drivers/gpu/drm/drm_fb_helper.c
---- linux-3.12.26.orig/drivers/gpu/drm/drm_fb_helper.c 2014-07-30 18:02:44.000000000 +0200
-+++ linux-3.12.26/drivers/gpu/drm/drm_fb_helper.c 2014-08-06 16:50:14.181959858 +0200
-@@ -1163,7 +1163,6 @@
- {
- struct drm_cmdline_mode *cmdline_mode;
- struct drm_display_mode *mode = NULL;
-- bool prefer_non_interlace;
+diff -Nur linux-3.12.33/drivers/hid/usbhid/hid-core.c linux-3.12.33-rpi/drivers/hid/usbhid/hid-core.c
+--- linux-3.12.33/drivers/hid/usbhid/hid-core.c 2014-11-15 06:28:07.000000000 -0600
++++ linux-3.12.33-rpi/drivers/hid/usbhid/hid-core.c 2014-12-03 19:13:37.380418001 -0600
+@@ -49,7 +49,7 @@
+ * Module parameters.
+ */
- 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;
+-static unsigned int hid_mousepoll_interval;
++static unsigned int hid_mousepoll_interval = ~0;
+ module_param_named(mousepoll, hid_mousepoll_interval, uint, 0644);
+ MODULE_PARM_DESC(mousepoll, "Polling interval of mice");
-- 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;
+@@ -1081,8 +1081,12 @@
}
- 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.26.orig/drivers/gpu/drm/i915/intel_display.c linux-3.12.26/drivers/gpu/drm/i915/intel_display.c
---- linux-3.12.26.orig/drivers/gpu/drm/i915/intel_display.c 2014-07-30 18:02:44.000000000 +0200
-+++ linux-3.12.26/drivers/gpu/drm/i915/intel_display.c 2014-08-06 16:50:14.209960077 +0200
-@@ -10084,7 +10084,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.26.orig/drivers/gpu/drm/radeon/dce6_afmt.c linux-3.12.26/drivers/gpu/drm/radeon/dce6_afmt.c
---- linux-3.12.26.orig/drivers/gpu/drm/radeon/dce6_afmt.c 2014-07-30 18:02:44.000000000 +0200
-+++ linux-3.12.26/drivers/gpu/drm/radeon/dce6_afmt.c 2014-08-06 16:50:14.209960077 +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.26.orig/drivers/gpu/drm/radeon/evergreen_hdmi.c linux-3.12.26/drivers/gpu/drm/radeon/evergreen_hdmi.c
---- linux-3.12.26.orig/drivers/gpu/drm/radeon/evergreen_hdmi.c 2014-07-30 18:02:44.000000000 +0200
-+++ linux-3.12.26/drivers/gpu/drm/radeon/evergreen_hdmi.c 2014-08-06 16:50:14.237960297 +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.26.orig/drivers/gpu/drm/radeon/r600_audio.c linux-3.12.26/drivers/gpu/drm/radeon/r600_audio.c
---- linux-3.12.26.orig/drivers/gpu/drm/radeon/r600_audio.c 2014-07-30 18:02:44.000000000 +0200
-+++ linux-3.12.26/drivers/gpu/drm/radeon/r600_audio.c 2014-08-06 16:50:14.245960360 +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.26.orig/drivers/gpu/drm/radeon/r600_hdmi.c linux-3.12.26/drivers/gpu/drm/radeon/r600_hdmi.c
---- linux-3.12.26.orig/drivers/gpu/drm/radeon/r600_hdmi.c 2014-07-30 18:02:44.000000000 +0200
-+++ linux-3.12.26/drivers/gpu/drm/radeon/r600_hdmi.c 2014-08-06 16:50:14.257960454 +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.26.orig/drivers/gpu/drm/radeon/radeon.h linux-3.12.26/drivers/gpu/drm/radeon/radeon.h
---- linux-3.12.26.orig/drivers/gpu/drm/radeon/radeon.h 2014-07-30 18:02:44.000000000 +0200
-+++ linux-3.12.26/drivers/gpu/drm/radeon/radeon.h 2014-08-06 16:50:14.257960454 +0200
-@@ -2723,12 +2723,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);
+ /* Change the polling interval of mice. */
+- if (hid->collection->usage == HID_GD_MOUSE && hid_mousepoll_interval > 0)
+- interval = hid_mousepoll_interval;
++ if (hid->collection->usage == HID_GD_MOUSE) {
++ if (hid_mousepoll_interval == ~0 && interval < 16)
++ interval = 16;
++ else if (hid_mousepoll_interval != ~0 && hid_mousepoll_interval != 0)
++ interval = hid_mousepoll_interval;
++ }
- /*
- * R600 vram scratch functions
-diff -Nur linux-3.12.26.orig/drivers/hwmon/bcm2835-hwmon.c linux-3.12.26/drivers/hwmon/bcm2835-hwmon.c
---- linux-3.12.26.orig/drivers/hwmon/bcm2835-hwmon.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-3.12.26/drivers/hwmon/bcm2835-hwmon.c 2014-08-06 16:50:14.257960454 +0200
+ ret = -ENOMEM;
+ if (usb_endpoint_dir_in(endpoint)) {
+diff -Nur linux-3.12.33/drivers/hwmon/bcm2835-hwmon.c linux-3.12.33-rpi/drivers/hwmon/bcm2835-hwmon.c
+--- linux-3.12.33/drivers/hwmon/bcm2835-hwmon.c 1969-12-31 18:00:00.000000000 -0600
++++ linux-3.12.33-rpi/drivers/hwmon/bcm2835-hwmon.c 2014-12-03 19:13:37.388418001 -0600
@@ -0,0 +1,219 @@
+/*****************************************************************************
+* Copyright 2011 Broadcom Corporation. All rights reserved.
@@ -10827,9 +16490,9 @@ diff -Nur linux-3.12.26.orig/drivers/hwmon/bcm2835-hwmon.c linux-3.12.26/drivers
+MODULE_DESCRIPTION("HW Monitor driver for bcm2835 chip");
+
+module_platform_driver(bcm2835_hwmon_driver);
-diff -Nur linux-3.12.26.orig/drivers/hwmon/Kconfig linux-3.12.26/drivers/hwmon/Kconfig
---- linux-3.12.26.orig/drivers/hwmon/Kconfig 2014-07-30 18:02:44.000000000 +0200
-+++ linux-3.12.26/drivers/hwmon/Kconfig 2014-08-06 16:50:14.281960643 +0200
+diff -Nur linux-3.12.33/drivers/hwmon/Kconfig linux-3.12.33-rpi/drivers/hwmon/Kconfig
+--- linux-3.12.33/drivers/hwmon/Kconfig 2014-11-15 06:28:07.000000000 -0600
++++ linux-3.12.33-rpi/drivers/hwmon/Kconfig 2014-12-03 19:13:37.384418001 -0600
@@ -1553,6 +1553,16 @@
help
Support for the A/D converter on MC13783 and MC13892 PMIC.
@@ -10847,9 +16510,9 @@ diff -Nur linux-3.12.26.orig/drivers/hwmon/Kconfig linux-3.12.26/drivers/hwmon/K
if ACPI
comment "ACPI drivers"
-diff -Nur linux-3.12.26.orig/drivers/hwmon/Makefile linux-3.12.26/drivers/hwmon/Makefile
---- linux-3.12.26.orig/drivers/hwmon/Makefile 2014-07-30 18:02:44.000000000 +0200
-+++ linux-3.12.26/drivers/hwmon/Makefile 2014-08-06 16:50:14.281960643 +0200
+diff -Nur linux-3.12.33/drivers/hwmon/Makefile linux-3.12.33-rpi/drivers/hwmon/Makefile
+--- linux-3.12.33/drivers/hwmon/Makefile 2014-11-15 06:28:07.000000000 -0600
++++ linux-3.12.33-rpi/drivers/hwmon/Makefile 2014-12-03 19:13:37.384418001 -0600
@@ -142,6 +142,7 @@
obj-$(CONFIG_SENSORS_W83L786NG) += w83l786ng.o
obj-$(CONFIG_SENSORS_WM831X) += wm831x-hwmon.o
@@ -10858,10 +16521,10 @@ diff -Nur linux-3.12.26.orig/drivers/hwmon/Makefile linux-3.12.26/drivers/hwmon/
obj-$(CONFIG_PMBUS) += pmbus/
-diff -Nur linux-3.12.26.orig/drivers/i2c/busses/i2c-bcm2708.c linux-3.12.26/drivers/i2c/busses/i2c-bcm2708.c
---- linux-3.12.26.orig/drivers/i2c/busses/i2c-bcm2708.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-3.12.26/drivers/i2c/busses/i2c-bcm2708.c 2014-08-06 16:50:14.285960674 +0200
-@@ -0,0 +1,408 @@
+diff -Nur linux-3.12.33/drivers/i2c/busses/i2c-bcm2708.c linux-3.12.33-rpi/drivers/i2c/busses/i2c-bcm2708.c
+--- linux-3.12.33/drivers/i2c/busses/i2c-bcm2708.c 1969-12-31 18:00:00.000000000 -0600
++++ linux-3.12.33-rpi/drivers/i2c/busses/i2c-bcm2708.c 2014-12-03 19:13:37.412418001 -0600
+@@ -0,0 +1,448 @@
+/*
+ * Driver for Broadcom BCM2708 BSC Controllers
+ *
@@ -10938,6 +16601,9 @@ diff -Nur linux-3.12.26.orig/drivers/i2c/busses/i2c-bcm2708.c linux-3.12.26/driv
+module_param(baudrate, uint, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP);
+MODULE_PARM_DESC(baudrate, "The I2C baudrate");
+
++static bool combined = false;
++module_param(combined, bool, 0644);
++MODULE_PARM_DESC(combined, "Use combined transactions");
+
+struct bcm2708_i2c {
+ struct i2c_adapter adapter;
@@ -10967,7 +16633,7 @@ diff -Nur linux-3.12.26.orig/drivers/i2c/busses/i2c-bcm2708.c linux-3.12.26/driv
+#define SET_GPIO_ALT(g,a) *(gpio+(((g)/10))) |= (((a)<=3?(a)+4:(a)==4?3:2)<<(((g)%10)*3))
+
+ int pin;
-+ u32 *gpio = ioremap(0x20200000, SZ_16K);
++ u32 *gpio = ioremap(GPIO_BASE, SZ_16K);
+
+ BUG_ON(id != 0 && id != 1);
+ /* BSC0 is on GPIO 0 & 1, BSC1 is on GPIO 2 & 3 */
@@ -11014,11 +16680,13 @@ diff -Nur linux-3.12.26.orig/drivers/i2c/busses/i2c-bcm2708.c linux-3.12.26/driv
+static inline void bcm2708_bsc_setup(struct bcm2708_i2c *bi)
+{
+ unsigned long bus_hz;
-+ u32 cdiv;
++ u32 cdiv, s;
+ u32 c = BSC_C_I2CEN | BSC_C_INTD | BSC_C_ST | BSC_C_CLEAR_1;
+
+ bus_hz = clk_get_rate(bi->clk);
+ cdiv = bus_hz / baudrate;
++ if (cdiv > 0xffff)
++ cdiv = 0xffff;
+
+ if (bi->msg->flags & I2C_M_RD)
+ c |= BSC_C_INTR | BSC_C_READ;
@@ -11028,6 +16696,32 @@ diff -Nur linux-3.12.26.orig/drivers/i2c/busses/i2c-bcm2708.c linux-3.12.26/driv
+ bcm2708_wr(bi, BSC_DIV, cdiv);
+ bcm2708_wr(bi, BSC_A, bi->msg->addr);
+ bcm2708_wr(bi, BSC_DLEN, bi->msg->len);
++ if (combined)
++ {
++ /* Do the next two messages meet combined transaction criteria?
++ - Current message is a write, next message is a read
++ - Both messages to same slave address
++ - Write message can fit inside FIFO (16 bytes or less) */
++ if ( (bi->nmsgs > 1) &&
++ !(bi->msg[0].flags & I2C_M_RD) && (bi->msg[1].flags & I2C_M_RD) &&
++ (bi->msg[0].addr == bi->msg[1].addr) && (bi->msg[0].len <= 16)) {
++ /* Fill FIFO with entire write message (16 byte FIFO) */
++ while (bi->pos < bi->msg->len)
++ bcm2708_wr(bi, BSC_FIFO, bi->msg->buf[bi->pos++]);
++ /* Start write transfer (no interrupts, don't clear FIFO) */
++ bcm2708_wr(bi, BSC_C, BSC_C_I2CEN | BSC_C_ST);
++ /* poll for transfer start bit (should only take 1-20 polls) */
++ do {
++ s = bcm2708_rd(bi, BSC_S);
++ } while (!(s & (BSC_S_TA | BSC_S_ERR | BSC_S_CLKT | BSC_S_DONE)));
++ /* Send next read message before the write transfer finishes. */
++ bi->nmsgs--;
++ bi->msg++;
++ bi->pos = 0;
++ bcm2708_wr(bi, BSC_DLEN, bi->msg->len);
++ c = BSC_C_I2CEN | BSC_C_INTD | BSC_C_INTR | BSC_C_ST | BSC_C_READ;
++ }
++ }
+ bcm2708_wr(bi, BSC_C, c);
+}
+
@@ -11132,6 +16826,8 @@ diff -Nur linux-3.12.26.orig/drivers/i2c/busses/i2c-bcm2708.c linux-3.12.26/driv
+ struct clk *clk;
+ struct bcm2708_i2c *bi;
+ struct i2c_adapter *adap;
++ unsigned long bus_hz;
++ u32 cdiv;
+
+ regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!regs) {
@@ -11207,8 +16903,15 @@ diff -Nur linux-3.12.26.orig/drivers/i2c/busses/i2c-bcm2708.c linux-3.12.26/driv
+ goto out_free_irq;
+ }
+
-+ dev_info(&pdev->dev, "BSC%d Controller at 0x%08lx (irq %d) (baudrate %dk)\n",
-+ pdev->id, (unsigned long)regs->start, irq, baudrate/1000);
++ bus_hz = clk_get_rate(bi->clk);
++ cdiv = bus_hz / baudrate;
++ if (cdiv > 0xffff) {
++ cdiv = 0xffff;
++ baudrate = bus_hz / cdiv;
++ }
++
++ dev_info(&pdev->dev, "BSC%d Controller at 0x%08lx (irq %d) (baudrate %d)\n",
++ pdev->id, (unsigned long)regs->start, irq, baudrate);
+
+ return 0;
+
@@ -11270,9 +16973,9 @@ diff -Nur linux-3.12.26.orig/drivers/i2c/busses/i2c-bcm2708.c linux-3.12.26/driv
+MODULE_AUTHOR("Chris Boot <bootc@bootc.net>");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:" DRV_NAME);
-diff -Nur linux-3.12.26.orig/drivers/i2c/busses/Kconfig linux-3.12.26/drivers/i2c/busses/Kconfig
---- linux-3.12.26.orig/drivers/i2c/busses/Kconfig 2014-07-30 18:02:44.000000000 +0200
-+++ linux-3.12.26/drivers/i2c/busses/Kconfig 2014-08-06 16:50:14.309960862 +0200
+diff -Nur linux-3.12.33/drivers/i2c/busses/Kconfig linux-3.12.33-rpi/drivers/i2c/busses/Kconfig
+--- linux-3.12.33/drivers/i2c/busses/Kconfig 2014-11-15 06:28:07.000000000 -0600
++++ linux-3.12.33-rpi/drivers/i2c/busses/Kconfig 2014-12-03 19:13:37.408418001 -0600
@@ -348,6 +348,25 @@
This support is also available as a module. If so, the module
will be called i2c-bcm2835.
@@ -11299,9 +17002,9 @@ diff -Nur linux-3.12.26.orig/drivers/i2c/busses/Kconfig linux-3.12.26/drivers/i2
config I2C_BLACKFIN_TWI
tristate "Blackfin TWI I2C support"
depends on BLACKFIN
-diff -Nur linux-3.12.26.orig/drivers/i2c/busses/Makefile linux-3.12.26/drivers/i2c/busses/Makefile
---- linux-3.12.26.orig/drivers/i2c/busses/Makefile 2014-07-30 18:02:44.000000000 +0200
-+++ linux-3.12.26/drivers/i2c/busses/Makefile 2014-08-06 16:50:14.309960862 +0200
+diff -Nur linux-3.12.33/drivers/i2c/busses/Makefile linux-3.12.33-rpi/drivers/i2c/busses/Makefile
+--- linux-3.12.33/drivers/i2c/busses/Makefile 2014-11-15 06:28:07.000000000 -0600
++++ linux-3.12.33-rpi/drivers/i2c/busses/Makefile 2014-12-03 19:13:37.408418001 -0600
@@ -32,6 +32,7 @@
obj-$(CONFIG_I2C_AT91) += i2c-at91.o
obj-$(CONFIG_I2C_AU1550) += i2c-au1550.o
@@ -11310,79 +17013,10 @@ diff -Nur linux-3.12.26.orig/drivers/i2c/busses/Makefile linux-3.12.26/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.26.orig/drivers/isdn/isdnloop/isdnloop.c linux-3.12.26/drivers/isdn/isdnloop/isdnloop.c
---- linux-3.12.26.orig/drivers/isdn/isdnloop/isdnloop.c 2014-07-30 18:02:44.000000000 +0200
-+++ linux-3.12.26/drivers/isdn/isdnloop/isdnloop.c 2014-08-06 16:50:14.333961051 +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.26.orig/drivers/media/platform/bcm2835/bcm2835-camera.c linux-3.12.26/drivers/media/platform/bcm2835/bcm2835-camera.c
---- linux-3.12.26.orig/drivers/media/platform/bcm2835/bcm2835-camera.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-3.12.26/drivers/media/platform/bcm2835/bcm2835-camera.c 2014-08-06 16:50:14.349961177 +0200
-@@ -0,0 +1,1719 @@
+diff -Nur linux-3.12.33/drivers/media/platform/bcm2835/bcm2835-camera.c linux-3.12.33-rpi/drivers/media/platform/bcm2835/bcm2835-camera.c
+--- linux-3.12.33/drivers/media/platform/bcm2835/bcm2835-camera.c 1969-12-31 18:00:00.000000000 -0600
++++ linux-3.12.33-rpi/drivers/media/platform/bcm2835/bcm2835-camera.c 2014-12-03 19:13:38.012418001 -0600
+@@ -0,0 +1,1827 @@
+/*
+ * Broadcom BM2835 V4L2 driver
+ *
@@ -11439,6 +17073,26 @@ diff -Nur linux-3.12.26.orig/drivers/media/platform/bcm2835/bcm2835-camera.c lin
+module_param_named(debug, bcm2835_v4l2_debug, int, 0644);
+MODULE_PARM_DESC(bcm2835_v4l2_debug, "Debug level 0-2");
+
++int max_video_width = MAX_VIDEO_MODE_WIDTH;
++int max_video_height = MAX_VIDEO_MODE_HEIGHT;
++module_param(max_video_width, int, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
++MODULE_PARM_DESC(max_video_width, "Threshold for video mode");
++module_param(max_video_height, int, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
++MODULE_PARM_DESC(max_video_height, "Threshold for video mode");
++
++/* Gstreamer bug https://bugzilla.gnome.org/show_bug.cgi?id=726521
++ * v4l2src does bad (and actually wrong) things when the vidioc_enum_framesizes
++ * function says type V4L2_FRMSIZE_TYPE_STEPWISE, which we do by default.
++ * It's happier if we just don't say anything at all, when it then
++ * sets up a load of defaults that it thinks might work.
++ * If gst_v4l2src_is_broken is non-zero, then we remove the function from
++ * our function table list (actually switch to an alternate set, but same
++ * result).
++ */
++int gst_v4l2src_is_broken = 0;
++module_param(gst_v4l2src_is_broken, int, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
++MODULE_PARM_DESC(gst_v4l2src_is_broken, "If non-zero, enable workaround for Gstreamer");
++
+static struct bm2835_mmal_dev *gdev; /* global device data */
+
+#define FPS_MIN 1
@@ -11556,6 +17210,14 @@ diff -Nur linux-3.12.26.orig/drivers/media/platform/bcm2835/bcm2835-camera.c lin
+ .depth = 12,
+ .mmal_component = MMAL_COMPONENT_CAMERA,
+ },
++ {
++ .name = "RGB32 (BE)",
++ .fourcc = V4L2_PIX_FMT_BGR32,
++ .flags = 0,
++ .mmal = MMAL_ENCODING_BGRA,
++ .depth = 32,
++ .mmal_component = MMAL_COMPONENT_CAMERA,
++ },
+};
+
+static struct mmal_fmt *get_format(struct v4l2_format *f)
@@ -12213,20 +17875,13 @@ diff -Nur linux-3.12.26.orig/drivers/media/platform/bcm2835/bcm2835-camera.c lin
+ f->fmt.pix.height = dev->capture.height;
+ f->fmt.pix.field = V4L2_FIELD_NONE;
+ f->fmt.pix.pixelformat = dev->capture.fmt->fourcc;
-+ f->fmt.pix.bytesperline =
-+ (f->fmt.pix.width * dev->capture.fmt->depth) >> 3;
-+ f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline;
-+ if (dev->capture.fmt->fourcc == V4L2_PIX_FMT_JPEG
-+ && f->fmt.pix.sizeimage < (100 << 10)) {
-+ /* Need a minimum size for JPEG to account for EXIF. */
-+ f->fmt.pix.sizeimage = (100 << 10);
-+ }
-+
-+ if (dev->capture.fmt->fourcc == V4L2_PIX_FMT_YUYV ||
-+ dev->capture.fmt->fourcc == V4L2_PIX_FMT_UYVY)
-+ f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
-+ else
++ f->fmt.pix.bytesperline = dev->capture.stride;
++ f->fmt.pix.sizeimage = dev->capture.buffersize;
++
++ if (dev->capture.fmt->fourcc == V4L2_PIX_FMT_RGB24)
+ f->fmt.pix.colorspace = V4L2_COLORSPACE_SRGB;
++ else
++ f->fmt.pix.colorspace = V4L2_COLORSPACE_JPEG;
+ f->fmt.pix.priv = 0;
+
+ v4l2_dump_pix_format(1, bcm2835_v4l2_debug, &dev->v4l2_dev, &f->fmt.pix,
@@ -12250,21 +17905,35 @@ diff -Nur linux-3.12.26.orig/drivers/media/platform/bcm2835/bcm2835-camera.c lin
+ }
+
+ f->fmt.pix.field = V4L2_FIELD_NONE;
-+ /* image must be a multiple of 32 pixels wide and 16 lines high */
-+ v4l_bound_align_image(&f->fmt.pix.width, 48, MAX_WIDTH, 5,
-+ &f->fmt.pix.height, 32, MAX_HEIGHT, 4, 0);
-+ f->fmt.pix.bytesperline = (f->fmt.pix.width * mfmt->depth) >> 3;
-+ f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline;
-+ if (f->fmt.pix.sizeimage < MIN_BUFFER_SIZE)
++
++ v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev,
++ "Clipping/aligning %dx%d format %08X\n",
++ f->fmt.pix.width, f->fmt.pix.height, f->fmt.pix.pixelformat);
++
++ v4l_bound_align_image(&f->fmt.pix.width, MIN_WIDTH, MAX_WIDTH, 1,
++ &f->fmt.pix.height, MIN_HEIGHT, MAX_HEIGHT, 1, 0);
++ f->fmt.pix.bytesperline = (f->fmt.pix.width * mfmt->depth)>>3;
++
++ /* Image buffer has to be padded to allow for alignment, even though
++ * we then remove that padding before delivering the buffer.
++ */
++ f->fmt.pix.sizeimage = ((f->fmt.pix.height+15)&~15) *
++ (((f->fmt.pix.width+31)&~31) * mfmt->depth) >> 3;
++
++ if ((mfmt->flags & V4L2_FMT_FLAG_COMPRESSED) &&
++ f->fmt.pix.sizeimage < MIN_BUFFER_SIZE)
+ f->fmt.pix.sizeimage = MIN_BUFFER_SIZE;
+
-+ if (mfmt->fourcc == V4L2_PIX_FMT_YUYV ||
-+ mfmt->fourcc == V4L2_PIX_FMT_UYVY)
-+ f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
-+ else
++ if (dev->capture.fmt->fourcc == V4L2_PIX_FMT_RGB24)
+ f->fmt.pix.colorspace = V4L2_COLORSPACE_SRGB;
++ else
++ f->fmt.pix.colorspace = V4L2_COLORSPACE_JPEG;
+ f->fmt.pix.priv = 0;
+
++ v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev,
++ "Now %dx%d format %08X\n",
++ f->fmt.pix.width, f->fmt.pix.height, f->fmt.pix.pixelformat);
++
+ v4l2_dump_pix_format(1, bcm2835_v4l2_debug, &dev->v4l2_dev, &f->fmt.pix,
+ __func__);
+ return 0;
@@ -12302,8 +17971,8 @@ diff -Nur linux-3.12.26.orig/drivers/media/platform/bcm2835/bcm2835-camera.c lin
+ switch (mfmt->mmal_component) {
+ case MMAL_COMPONENT_CAMERA:
+ /* Make a further decision on port based on resolution */
-+ if (f->fmt.pix.width <= MAX_VIDEO_MODE_WIDTH
-+ && f->fmt.pix.height <= MAX_VIDEO_MODE_HEIGHT)
++ if (f->fmt.pix.width <= max_video_width
++ && f->fmt.pix.height <= max_video_height)
+ camera_port = port =
+ &dev->component[MMAL_COMPONENT_CAMERA]->
+ output[MMAL_CAMERA_PORT_VIDEO];
@@ -12347,6 +18016,7 @@ diff -Nur linux-3.12.26.orig/drivers/media/platform/bcm2835/bcm2835-camera.c lin
+ camera_port->es.video.crop.height = f->fmt.pix.height;
+ camera_port->es.video.frame_rate.num = 0;
+ camera_port->es.video.frame_rate.den = 1;
++ camera_port->es.video.color_space = MMAL_COLOR_SPACE_JPEG_JFIF;
+
+ ret = vchiq_mmal_port_set_format(dev->instance, camera_port);
+
@@ -12399,7 +18069,9 @@ diff -Nur linux-3.12.26.orig/drivers/media/platform/bcm2835/bcm2835-camera.c lin
+
+ if (ret) {
+ v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev,
-+ "%s failed to set format\n", __func__);
++ "%s failed to set format %dx%d %08X\n", __func__,
++ f->fmt.pix.width, f->fmt.pix.height,
++ f->fmt.pix.pixelformat);
+ /* ensure capture is not going to be tried */
+ dev->capture.port = NULL;
+ } else {
@@ -12456,8 +18128,12 @@ diff -Nur linux-3.12.26.orig/drivers/media/platform/bcm2835/bcm2835-camera.c lin
+ if (ret)
+ v4l2_dbg(1, bcm2835_v4l2_debug,
+ &dev->v4l2_dev,
-+ "%s failed to set format\n",
-+ __func__);
++ "%s failed to set format %dx%d fmt %08X\n",
++ __func__,
++ f->fmt.pix.width,
++ f->fmt.pix.height,
++ f->fmt.pix.pixelformat
++ );
+ }
+
+ if (!ret) {
@@ -12507,6 +18183,7 @@ diff -Nur linux-3.12.26.orig/drivers/media/platform/bcm2835/bcm2835-camera.c lin
+ dev->capture.stride = f->fmt.pix.bytesperline;
+ dev->capture.width = camera_port->es.video.crop.width;
+ dev->capture.height = camera_port->es.video.crop.height;
++ dev->capture.buffersize = port->current_buffer.size;
+
+ /* select port for capture */
+ dev->capture.port = port;
@@ -12514,10 +18191,10 @@ diff -Nur linux-3.12.26.orig/drivers/media/platform/bcm2835/bcm2835-camera.c lin
+ dev->capture.encode_component = encode_component;
+ v4l2_dbg(1, bcm2835_v4l2_debug,
+ &dev->v4l2_dev,
-+ "Set dev->capture.fmt %08X, %dx%d, stride %d",
++ "Set dev->capture.fmt %08X, %dx%d, stride %d, size %d",
+ port->format.encoding,
+ dev->capture.width, dev->capture.height,
-+ dev->capture.stride);
++ dev->capture.stride, dev->capture.buffersize);
+ }
+ }
+
@@ -12707,6 +18384,47 @@ diff -Nur linux-3.12.26.orig/drivers/media/platform/bcm2835/bcm2835-camera.c lin
+ .vidioc_unsubscribe_event = v4l2_event_unsubscribe,
+};
+
++static const struct v4l2_ioctl_ops camera0_ioctl_ops_gstreamer = {
++ /* overlay */
++ .vidioc_enum_fmt_vid_overlay = vidioc_enum_fmt_vid_overlay,
++ .vidioc_g_fmt_vid_overlay = vidioc_g_fmt_vid_overlay,
++ .vidioc_try_fmt_vid_overlay = vidioc_try_fmt_vid_overlay,
++ .vidioc_s_fmt_vid_overlay = vidioc_s_fmt_vid_overlay,
++ .vidioc_overlay = vidioc_overlay,
++ .vidioc_g_fbuf = vidioc_g_fbuf,
++
++ /* inputs */
++ .vidioc_enum_input = vidioc_enum_input,
++ .vidioc_g_input = vidioc_g_input,
++ .vidioc_s_input = vidioc_s_input,
++
++ /* capture */
++ .vidioc_querycap = vidioc_querycap,
++ .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap,
++ .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap,
++ .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap,
++ .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap,
++
++ /* buffer management */
++ .vidioc_reqbufs = vb2_ioctl_reqbufs,
++ .vidioc_create_bufs = vb2_ioctl_create_bufs,
++ .vidioc_prepare_buf = vb2_ioctl_prepare_buf,
++ .vidioc_querybuf = vb2_ioctl_querybuf,
++ .vidioc_qbuf = vb2_ioctl_qbuf,
++ .vidioc_dqbuf = vb2_ioctl_dqbuf,
++ /* Remove this function ptr to fix gstreamer bug
++ .vidioc_enum_framesizes = vidioc_enum_framesizes, */
++ .vidioc_enum_frameintervals = vidioc_enum_frameintervals,
++ .vidioc_g_parm = vidioc_g_parm,
++ .vidioc_s_parm = vidioc_s_parm,
++ .vidioc_streamon = vb2_ioctl_streamon,
++ .vidioc_streamoff = vb2_ioctl_streamoff,
++
++ .vidioc_log_status = v4l2_ctrl_log_status,
++ .vidioc_subscribe_event = v4l2_ctrl_subscribe_event,
++ .vidioc_unsubscribe_event = v4l2_event_unsubscribe,
++};
++
+/* ------------------------------------------------------------------
+ Driver init/finalise
+ ------------------------------------------------------------------*/
@@ -12737,8 +18455,10 @@ diff -Nur linux-3.12.26.orig/drivers/media/platform/bcm2835/bcm2835-camera.c lin
+ .max_stills_h = MAX_HEIGHT,
+ .stills_yuv422 = 1,
+ .one_shot_stills = 1,
-+ .max_preview_video_w = 1920,
-+ .max_preview_video_h = 1088,
++ .max_preview_video_w = (max_video_width > 1920) ?
++ max_video_width : 1920,
++ .max_preview_video_h = (max_video_height > 1088) ?
++ max_video_height : 1088,
+ .num_preview_video_frames = 3,
+ .stills_capture_circular_buffer_height = 0,
+ .fast_preview_resume = 0,
@@ -12756,6 +18476,7 @@ diff -Nur linux-3.12.26.orig/drivers/media/platform/bcm2835/bcm2835-camera.c lin
+{
+ int ret;
+ struct mmal_es_format *format;
++ u32 bool_true = 1;
+
+ ret = vchiq_mmal_init(&dev->instance);
+ if (ret < 0)
@@ -12810,6 +18531,12 @@ diff -Nur linux-3.12.26.orig/drivers/media/platform/bcm2835/bcm2835-camera.c lin
+ format->es->video.frame_rate.num = 0; /* Rely on fps_range */
+ format->es->video.frame_rate.den = 1;
+
++ vchiq_mmal_port_parameter_set(dev->instance,
++ &dev->component[MMAL_COMPONENT_CAMERA]->
++ output[MMAL_CAMERA_PORT_VIDEO],
++ MMAL_PARAMETER_NO_IMAGE_PADDING,
++ &bool_true, sizeof(bool_true));
++
+ format =
+ &dev->component[MMAL_COMPONENT_CAMERA]->
+ output[MMAL_CAMERA_PORT_CAPTURE].format;
@@ -12833,6 +18560,12 @@ diff -Nur linux-3.12.26.orig/drivers/media/platform/bcm2835/bcm2835-camera.c lin
+ dev->capture.enc_profile = V4L2_MPEG_VIDEO_H264_PROFILE_HIGH;
+ dev->capture.enc_level = V4L2_MPEG_VIDEO_H264_LEVEL_4_0;
+
++ vchiq_mmal_port_parameter_set(dev->instance,
++ &dev->component[MMAL_COMPONENT_CAMERA]->
++ output[MMAL_CAMERA_PORT_CAPTURE],
++ MMAL_PARAMETER_NO_IMAGE_PADDING,
++ &bool_true, sizeof(bool_true));
++
+ /* get the preview component ready */
+ ret = vchiq_mmal_component_init(
+ dev->instance, "ril.video_render",
@@ -12938,6 +18671,11 @@ diff -Nur linux-3.12.26.orig/drivers/media/platform/bcm2835/bcm2835-camera.c lin
+ int ret;
+
+ *vfd = vdev_template;
++ if (gst_v4l2src_is_broken) {
++ v4l2_info(&dev->v4l2_dev,
++ "Work-around for gstreamer issue is active.\n");
++ vfd->ioctl_ops = &camera0_ioctl_ops_gstreamer;
++ }
+
+ vfd->v4l2_dev = &dev->v4l2_dev;
+
@@ -12954,8 +18692,9 @@ diff -Nur linux-3.12.26.orig/drivers/media/platform/bcm2835/bcm2835-camera.c lin
+ if (ret < 0)
+ return ret;
+
-+ v4l2_info(vfd->v4l2_dev, "V4L2 device registered as %s\n",
-+ video_device_node_name(vfd));
++ v4l2_info(vfd->v4l2_dev,
++ "V4L2 device registered as %s - stills mode > %dx%d\n",
++ video_device_node_name(vfd), max_video_width, max_video_height);
+
+ return 0;
+}
@@ -12963,9 +18702,9 @@ diff -Nur linux-3.12.26.orig/drivers/media/platform/bcm2835/bcm2835-camera.c lin
+static struct v4l2_format default_v4l2_format = {
+ .fmt.pix.pixelformat = V4L2_PIX_FMT_JPEG,
+ .fmt.pix.width = 1024,
-+ .fmt.pix.bytesperline = 1024 * 3 / 2,
++ .fmt.pix.bytesperline = 1024,
+ .fmt.pix.height = 768,
-+ .fmt.pix.sizeimage = 1<<18,
++ .fmt.pix.sizeimage = 1024*768,
+};
+
+static int __init bm2835_mmal_init(void)
@@ -13028,6 +18767,9 @@ diff -Nur linux-3.12.26.orig/drivers/media/platform/bcm2835/bcm2835-camera.c lin
+ if (ret < 0)
+ goto unreg_dev;
+
++ /* Really want to call vidioc_s_fmt_vid_cap with the default
++ * format, but currently the APIs don't join up.
++ */
+ ret = mmal_setup_components(dev, &default_v4l2_format);
+ if (ret < 0) {
+ v4l2_err(&dev->v4l2_dev,
@@ -13102,10 +18844,10 @@ diff -Nur linux-3.12.26.orig/drivers/media/platform/bcm2835/bcm2835-camera.c lin
+
+module_init(bm2835_mmal_init);
+module_exit(bm2835_mmal_exit);
-diff -Nur linux-3.12.26.orig/drivers/media/platform/bcm2835/bcm2835-camera.h linux-3.12.26/drivers/media/platform/bcm2835/bcm2835-camera.h
---- linux-3.12.26.orig/drivers/media/platform/bcm2835/bcm2835-camera.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-3.12.26/drivers/media/platform/bcm2835/bcm2835-camera.h 2014-08-06 16:50:14.349961177 +0200
-@@ -0,0 +1,125 @@
+diff -Nur linux-3.12.33/drivers/media/platform/bcm2835/bcm2835-camera.h linux-3.12.33-rpi/drivers/media/platform/bcm2835/bcm2835-camera.h
+--- linux-3.12.33/drivers/media/platform/bcm2835/bcm2835-camera.h 1969-12-31 18:00:00.000000000 -0600
++++ linux-3.12.33-rpi/drivers/media/platform/bcm2835/bcm2835-camera.h 2014-12-03 19:13:38.012418001 -0600
+@@ -0,0 +1,126 @@
+/*
+ * Broadcom BM2835 V4L2 driver
+ *
@@ -13123,7 +18865,7 @@ diff -Nur linux-3.12.26.orig/drivers/media/platform/bcm2835/bcm2835-camera.h lin
+ * core driver device
+ */
+
-+#define V4L2_CTRL_COUNT 27 /* number of v4l controls */
++#define V4L2_CTRL_COUNT 28 /* number of v4l controls */
+
+enum {
+ MMAL_COMPONENT_CAMERA = 0,
@@ -13178,6 +18920,7 @@ diff -Nur linux-3.12.26.orig/drivers/media/platform/bcm2835/bcm2835-camera.h lin
+ unsigned int width; /* width */
+ unsigned int height; /* height */
+ unsigned int stride; /* stride */
++ unsigned int buffersize; /* buffer size with padding */
+ struct mmal_fmt *fmt;
+ struct v4l2_fract timeperframe;
+
@@ -13231,10 +18974,10 @@ diff -Nur linux-3.12.26.orig/drivers/media/platform/bcm2835/bcm2835-camera.h lin
+ (pix_fmt)->pixelformat, (pix_fmt)->bytesperline, \
+ (pix_fmt)->sizeimage, (pix_fmt)->colorspace, (pix_fmt)->priv); \
+}
-diff -Nur linux-3.12.26.orig/drivers/media/platform/bcm2835/controls.c linux-3.12.26/drivers/media/platform/bcm2835/controls.c
---- linux-3.12.26.orig/drivers/media/platform/bcm2835/controls.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-3.12.26/drivers/media/platform/bcm2835/controls.c 2014-08-06 16:50:14.349961177 +0200
-@@ -0,0 +1,1315 @@
+diff -Nur linux-3.12.33/drivers/media/platform/bcm2835/controls.c linux-3.12.33-rpi/drivers/media/platform/bcm2835/controls.c
+--- linux-3.12.33/drivers/media/platform/bcm2835/controls.c 1969-12-31 18:00:00.000000000 -0600
++++ linux-3.12.33-rpi/drivers/media/platform/bcm2835/controls.c 2014-12-03 19:13:38.012418001 -0600
+@@ -0,0 +1,1322 @@
+/*
+ * Broadcom BM2835 V4L2 driver
+ *
@@ -14203,8 +19946,8 @@ diff -Nur linux-3.12.26.orig/drivers/media/platform/bcm2835/controls.c linux-3.1
+ },
+/* {
+ 0, MMAL_CONTROL_TYPE_CLUSTER, 3, 1, 0, NULL, 0, NULL
-+ },
-+*/ {
++ }, */
++ {
+ V4L2_CID_EXPOSURE_AUTO, MMAL_CONTROL_TYPE_STD_MENU,
+ ~0x03, 3, V4L2_EXPOSURE_AUTO, 0, NULL,
+ MMAL_PARAMETER_EXPOSURE_MODE,
@@ -14386,6 +20129,13 @@ diff -Nur linux-3.12.26.orig/drivers/media/platform/bcm2835/controls.c linux-3.1
+ &ctrl_set_scene_mode,
+ false
+ },
++ {
++ V4L2_CID_MPEG_VIDEO_H264_I_PERIOD, MMAL_CONTROL_TYPE_STD,
++ 0, 0x7FFFFFFF, 60, 1, NULL,
++ MMAL_PARAMETER_INTRAPERIOD,
++ &ctrl_set_video_encode_param_output,
++ false
++ },
+};
+
+int bm2835_mmal_set_all_camera_controls(struct bm2835_mmal_dev *dev)
@@ -14550,9 +20300,9 @@ diff -Nur linux-3.12.26.orig/drivers/media/platform/bcm2835/controls.c linux-3.1
+
+ return 0;
+}
-diff -Nur linux-3.12.26.orig/drivers/media/platform/bcm2835/Kconfig linux-3.12.26/drivers/media/platform/bcm2835/Kconfig
---- linux-3.12.26.orig/drivers/media/platform/bcm2835/Kconfig 1970-01-01 01:00:00.000000000 +0100
-+++ linux-3.12.26/drivers/media/platform/bcm2835/Kconfig 2014-08-06 16:50:14.353961208 +0200
+diff -Nur linux-3.12.33/drivers/media/platform/bcm2835/Kconfig linux-3.12.33-rpi/drivers/media/platform/bcm2835/Kconfig
+--- linux-3.12.33/drivers/media/platform/bcm2835/Kconfig 1969-12-31 18:00:00.000000000 -0600
++++ linux-3.12.33-rpi/drivers/media/platform/bcm2835/Kconfig 2014-12-03 19:13:38.012418001 -0600
@@ -0,0 +1,25 @@
+# Broadcom VideoCore IV v4l2 camera support
+
@@ -14579,18 +20329,18 @@ diff -Nur linux-3.12.26.orig/drivers/media/platform/bcm2835/Kconfig linux-3.12.2
+
+
+endif # VIDEO_BM2835
-diff -Nur linux-3.12.26.orig/drivers/media/platform/bcm2835/Makefile linux-3.12.26/drivers/media/platform/bcm2835/Makefile
---- linux-3.12.26.orig/drivers/media/platform/bcm2835/Makefile 1970-01-01 01:00:00.000000000 +0100
-+++ linux-3.12.26/drivers/media/platform/bcm2835/Makefile 2014-08-06 16:50:14.353961208 +0200
+diff -Nur linux-3.12.33/drivers/media/platform/bcm2835/Makefile linux-3.12.33-rpi/drivers/media/platform/bcm2835/Makefile
+--- linux-3.12.33/drivers/media/platform/bcm2835/Makefile 1969-12-31 18:00:00.000000000 -0600
++++ linux-3.12.33-rpi/drivers/media/platform/bcm2835/Makefile 2014-12-03 19:13:38.012418001 -0600
@@ -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.26.orig/drivers/media/platform/bcm2835/mmal-common.h linux-3.12.26/drivers/media/platform/bcm2835/mmal-common.h
---- linux-3.12.26.orig/drivers/media/platform/bcm2835/mmal-common.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-3.12.26/drivers/media/platform/bcm2835/mmal-common.h 2014-08-06 16:50:14.353961208 +0200
+diff -Nur linux-3.12.33/drivers/media/platform/bcm2835/mmal-common.h linux-3.12.33-rpi/drivers/media/platform/bcm2835/mmal-common.h
+--- linux-3.12.33/drivers/media/platform/bcm2835/mmal-common.h 1969-12-31 18:00:00.000000000 -0600
++++ linux-3.12.33-rpi/drivers/media/platform/bcm2835/mmal-common.h 2014-12-03 19:13:38.012418001 -0600
@@ -0,0 +1,53 @@
+/*
+ * Broadcom BM2835 V4L2 driver
@@ -14645,10 +20395,10 @@ diff -Nur linux-3.12.26.orig/drivers/media/platform/bcm2835/mmal-common.h linux-
+ u32 v;
+};
+
-diff -Nur linux-3.12.26.orig/drivers/media/platform/bcm2835/mmal-encodings.h linux-3.12.26/drivers/media/platform/bcm2835/mmal-encodings.h
---- linux-3.12.26.orig/drivers/media/platform/bcm2835/mmal-encodings.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-3.12.26/drivers/media/platform/bcm2835/mmal-encodings.h 2014-08-06 16:50:14.353961208 +0200
-@@ -0,0 +1,94 @@
+diff -Nur linux-3.12.33/drivers/media/platform/bcm2835/mmal-encodings.h linux-3.12.33-rpi/drivers/media/platform/bcm2835/mmal-encodings.h
+--- linux-3.12.33/drivers/media/platform/bcm2835/mmal-encodings.h 1969-12-31 18:00:00.000000000 -0600
++++ linux-3.12.33-rpi/drivers/media/platform/bcm2835/mmal-encodings.h 2014-12-03 19:13:38.012418001 -0600
+@@ -0,0 +1,127 @@
+/*
+ * Broadcom BM2835 V4L2 driver
+ *
@@ -14663,6 +20413,8 @@ diff -Nur linux-3.12.26.orig/drivers/media/platform/bcm2835/mmal-encodings.h lin
+ * Simon Mellor <simellor@broadcom.com>
+ * Luke Diamand <luked@broadcom.com>
+ */
++#ifndef MMAL_ENCODINGS_H
++#define MMAL_ENCODINGS_H
+
+#define MMAL_ENCODING_H264 MMAL_FOURCC('H', '2', '6', '4')
+#define MMAL_ENCODING_H263 MMAL_FOURCC('H', '2', '6', '3')
@@ -14743,9 +20495,40 @@ diff -Nur linux-3.12.26.orig/drivers/media/platform/bcm2835/mmal-encodings.h lin
+#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.26.orig/drivers/media/platform/bcm2835/mmal-msg-common.h linux-3.12.26/drivers/media/platform/bcm2835/mmal-msg-common.h
---- linux-3.12.26.orig/drivers/media/platform/bcm2835/mmal-msg-common.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-3.12.26/drivers/media/platform/bcm2835/mmal-msg-common.h 2014-08-06 16:50:14.389961491 +0200
++
++
++/** \defgroup MmalColorSpace List of pre-defined video color spaces
++ * This defines a list of common color spaces. This list isn't exhaustive and
++ * is only provided as a convenience to avoid clients having to use FourCC
++ * codes directly. However components are allowed to define and use their own
++ * FourCC codes.
++ */
++/* @{ */
++
++/** Unknown color space */
++#define MMAL_COLOR_SPACE_UNKNOWN 0
++/** ITU-R BT.601-5 [SDTV] */
++#define MMAL_COLOR_SPACE_ITUR_BT601 MMAL_FOURCC('Y', '6', '0', '1')
++/** ITU-R BT.709-3 [HDTV] */
++#define MMAL_COLOR_SPACE_ITUR_BT709 MMAL_FOURCC('Y', '7', '0', '9')
++/** JPEG JFIF */
++#define MMAL_COLOR_SPACE_JPEG_JFIF MMAL_FOURCC('Y', 'J', 'F', 'I')
++/** Title 47 Code of Federal Regulations (2003) 73.682 (a) (20) */
++#define MMAL_COLOR_SPACE_FCC MMAL_FOURCC('Y', 'F', 'C', 'C')
++/** Society of Motion Picture and Television Engineers 240M (1999) */
++#define MMAL_COLOR_SPACE_SMPTE240M MMAL_FOURCC('Y', '2', '4', '0')
++/** ITU-R BT.470-2 System M */
++#define MMAL_COLOR_SPACE_BT470_2_M MMAL_FOURCC('Y', '_', '_', 'M')
++/** ITU-R BT.470-2 System BG */
++#define MMAL_COLOR_SPACE_BT470_2_BG MMAL_FOURCC('Y', '_', 'B', 'G')
++/** JPEG JFIF, but with 16..255 luma */
++#define MMAL_COLOR_SPACE_JFIF_Y16_255 MMAL_FOURCC('Y', 'Y', '1', '6')
++/* @} MmalColorSpace List */
++
++#endif /* MMAL_ENCODINGS_H */
+diff -Nur linux-3.12.33/drivers/media/platform/bcm2835/mmal-msg-common.h linux-3.12.33-rpi/drivers/media/platform/bcm2835/mmal-msg-common.h
+--- linux-3.12.33/drivers/media/platform/bcm2835/mmal-msg-common.h 1969-12-31 18:00:00.000000000 -0600
++++ linux-3.12.33-rpi/drivers/media/platform/bcm2835/mmal-msg-common.h 2014-12-03 19:13:38.012418001 -0600
@@ -0,0 +1,50 @@
+/*
+ * Broadcom BM2835 V4L2 driver
@@ -14797,9 +20580,9 @@ diff -Nur linux-3.12.26.orig/drivers/media/platform/bcm2835/mmal-msg-common.h li
+};
+
+#endif /* MMAL_MSG_COMMON_H */
-diff -Nur linux-3.12.26.orig/drivers/media/platform/bcm2835/mmal-msg-format.h linux-3.12.26/drivers/media/platform/bcm2835/mmal-msg-format.h
---- linux-3.12.26.orig/drivers/media/platform/bcm2835/mmal-msg-format.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-3.12.26/drivers/media/platform/bcm2835/mmal-msg-format.h 2014-08-06 16:50:14.393961522 +0200
+diff -Nur linux-3.12.33/drivers/media/platform/bcm2835/mmal-msg-format.h linux-3.12.33-rpi/drivers/media/platform/bcm2835/mmal-msg-format.h
+--- linux-3.12.33/drivers/media/platform/bcm2835/mmal-msg-format.h 1969-12-31 18:00:00.000000000 -0600
++++ linux-3.12.33-rpi/drivers/media/platform/bcm2835/mmal-msg-format.h 2014-12-03 19:13:38.012418001 -0600
@@ -0,0 +1,81 @@
+/*
+ * Broadcom BM2835 V4L2 driver
@@ -14882,9 +20665,9 @@ diff -Nur linux-3.12.26.orig/drivers/media/platform/bcm2835/mmal-msg-format.h li
+};
+
+#endif /* MMAL_MSG_FORMAT_H */
-diff -Nur linux-3.12.26.orig/drivers/media/platform/bcm2835/mmal-msg.h linux-3.12.26/drivers/media/platform/bcm2835/mmal-msg.h
---- linux-3.12.26.orig/drivers/media/platform/bcm2835/mmal-msg.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-3.12.26/drivers/media/platform/bcm2835/mmal-msg.h 2014-08-06 16:50:14.393961522 +0200
+diff -Nur linux-3.12.33/drivers/media/platform/bcm2835/mmal-msg.h linux-3.12.33-rpi/drivers/media/platform/bcm2835/mmal-msg.h
+--- linux-3.12.33/drivers/media/platform/bcm2835/mmal-msg.h 1969-12-31 18:00:00.000000000 -0600
++++ linux-3.12.33-rpi/drivers/media/platform/bcm2835/mmal-msg.h 2014-12-03 19:13:38.012418001 -0600
@@ -0,0 +1,404 @@
+/*
+ * Broadcom BM2835 V4L2 driver
@@ -15290,9 +21073,9 @@ diff -Nur linux-3.12.26.orig/drivers/media/platform/bcm2835/mmal-msg.h linux-3.1
+ u8 payload[MMAL_MSG_MAX_PAYLOAD];
+ } u;
+};
-diff -Nur linux-3.12.26.orig/drivers/media/platform/bcm2835/mmal-msg-port.h linux-3.12.26/drivers/media/platform/bcm2835/mmal-msg-port.h
---- linux-3.12.26.orig/drivers/media/platform/bcm2835/mmal-msg-port.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-3.12.26/drivers/media/platform/bcm2835/mmal-msg-port.h 2014-08-06 16:50:14.393961522 +0200
+diff -Nur linux-3.12.33/drivers/media/platform/bcm2835/mmal-msg-port.h linux-3.12.33-rpi/drivers/media/platform/bcm2835/mmal-msg-port.h
+--- linux-3.12.33/drivers/media/platform/bcm2835/mmal-msg-port.h 1969-12-31 18:00:00.000000000 -0600
++++ linux-3.12.33-rpi/drivers/media/platform/bcm2835/mmal-msg-port.h 2014-12-03 19:13:38.012418001 -0600
@@ -0,0 +1,107 @@
+/*
+ * Broadcom BM2835 V4L2 driver
@@ -15401,10 +21184,10 @@ diff -Nur linux-3.12.26.orig/drivers/media/platform/bcm2835/mmal-msg-port.h linu
+ */
+
+};
-diff -Nur linux-3.12.26.orig/drivers/media/platform/bcm2835/mmal-parameters.h linux-3.12.26/drivers/media/platform/bcm2835/mmal-parameters.h
---- linux-3.12.26.orig/drivers/media/platform/bcm2835/mmal-parameters.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-3.12.26/drivers/media/platform/bcm2835/mmal-parameters.h 2014-08-06 16:50:14.393961522 +0200
-@@ -0,0 +1,655 @@
+diff -Nur linux-3.12.33/drivers/media/platform/bcm2835/mmal-parameters.h linux-3.12.33-rpi/drivers/media/platform/bcm2835/mmal-parameters.h
+--- linux-3.12.33/drivers/media/platform/bcm2835/mmal-parameters.h 1969-12-31 18:00:00.000000000 -0600
++++ linux-3.12.33-rpi/drivers/media/platform/bcm2835/mmal-parameters.h 2014-12-03 19:13:38.012418001 -0600
+@@ -0,0 +1,656 @@
+/*
+ * Broadcom BM2835 V4L2 driver
+ *
@@ -15464,7 +21247,8 @@ diff -Nur linux-3.12.26.orig/drivers/media/platform/bcm2835/mmal-parameters.h li
+ MMAL_PARAMETER_SEEK, /**< MMAL_PARAMETER_SEEK_T */
+ MMAL_PARAMETER_POWERMON_ENABLE, /**< MMAL_PARAMETER_BOOLEAN_T */
+ MMAL_PARAMETER_LOGGING, /**< MMAL_PARAMETER_LOGGING_T */
-+ MMAL_PARAMETER_SYSTEM_TIME /**< MMAL_PARAMETER_UINT64_T */
++ MMAL_PARAMETER_SYSTEM_TIME, /**< MMAL_PARAMETER_UINT64_T */
++ MMAL_PARAMETER_NO_IMAGE_PADDING /**< MMAL_PARAMETER_BOOLEAN_T */
+};
+
+/* camera parameters */
@@ -16060,9 +21844,9 @@ diff -Nur linux-3.12.26.orig/drivers/media/platform/bcm2835/mmal-parameters.h li
+ u32 num_effect_params;
+ u32 effect_parameter[MMAL_MAX_IMAGEFX_PARAMETERS];
+};
-diff -Nur linux-3.12.26.orig/drivers/media/platform/bcm2835/mmal-vchiq.c linux-3.12.26/drivers/media/platform/bcm2835/mmal-vchiq.c
---- linux-3.12.26.orig/drivers/media/platform/bcm2835/mmal-vchiq.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-3.12.26/drivers/media/platform/bcm2835/mmal-vchiq.c 2014-08-06 16:50:14.397961554 +0200
+diff -Nur linux-3.12.33/drivers/media/platform/bcm2835/mmal-vchiq.c linux-3.12.33-rpi/drivers/media/platform/bcm2835/mmal-vchiq.c
+--- linux-3.12.33/drivers/media/platform/bcm2835/mmal-vchiq.c 1969-12-31 18:00:00.000000000 -0600
++++ linux-3.12.33-rpi/drivers/media/platform/bcm2835/mmal-vchiq.c 2014-12-03 19:13:38.012418001 -0600
@@ -0,0 +1,1916 @@
+/*
+ * Broadcom BM2835 V4L2 driver
@@ -16808,7 +22592,7 @@ diff -Nur linux-3.12.26.orig/drivers/media/platform/bcm2835/mmal-vchiq.c linux-3
+ return ret;
+ }
+
-+ ret = wait_for_completion_timeout(&msg_context.u.sync.cmplt, HZ);
++ ret = wait_for_completion_timeout(&msg_context.u.sync.cmplt, 3*HZ);
+ if (ret <= 0) {
+ pr_err("error %d waiting for sync completion\n", ret);
+ if (ret == 0)
@@ -17980,9 +23764,9 @@ diff -Nur linux-3.12.26.orig/drivers/media/platform/bcm2835/mmal-vchiq.c linux-3
+ kfree(instance);
+ return -ENODEV;
+}
-diff -Nur linux-3.12.26.orig/drivers/media/platform/bcm2835/mmal-vchiq.h linux-3.12.26/drivers/media/platform/bcm2835/mmal-vchiq.h
---- linux-3.12.26.orig/drivers/media/platform/bcm2835/mmal-vchiq.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-3.12.26/drivers/media/platform/bcm2835/mmal-vchiq.h 2014-08-06 16:50:14.401961585 +0200
+diff -Nur linux-3.12.33/drivers/media/platform/bcm2835/mmal-vchiq.h linux-3.12.33-rpi/drivers/media/platform/bcm2835/mmal-vchiq.h
+--- linux-3.12.33/drivers/media/platform/bcm2835/mmal-vchiq.h 1969-12-31 18:00:00.000000000 -0600
++++ linux-3.12.33-rpi/drivers/media/platform/bcm2835/mmal-vchiq.h 2014-12-03 19:13:38.012418001 -0600
@@ -0,0 +1,178 @@
+/*
+ * Broadcom BM2835 V4L2 driver
@@ -18162,9 +23946,9 @@ diff -Nur linux-3.12.26.orig/drivers/media/platform/bcm2835/mmal-vchiq.h linux-3
+ struct mmal_buffer *buf);
+
+#endif /* MMAL_VCHIQ_H */
-diff -Nur linux-3.12.26.orig/drivers/media/platform/Kconfig linux-3.12.26/drivers/media/platform/Kconfig
---- linux-3.12.26.orig/drivers/media/platform/Kconfig 2014-07-30 18:02:44.000000000 +0200
-+++ linux-3.12.26/drivers/media/platform/Kconfig 2014-08-06 16:50:14.401961585 +0200
+diff -Nur linux-3.12.33/drivers/media/platform/Kconfig linux-3.12.33-rpi/drivers/media/platform/Kconfig
+--- linux-3.12.33/drivers/media/platform/Kconfig 2014-11-15 06:28:07.000000000 -0600
++++ linux-3.12.33-rpi/drivers/media/platform/Kconfig 2014-12-03 19:13:38.012418001 -0600
@@ -124,6 +124,7 @@
source "drivers/media/platform/soc_camera/Kconfig"
source "drivers/media/platform/exynos4-is/Kconfig"
@@ -18173,9 +23957,9 @@ diff -Nur linux-3.12.26.orig/drivers/media/platform/Kconfig linux-3.12.26/driver
endif # V4L_PLATFORM_DRIVERS
-diff -Nur linux-3.12.26.orig/drivers/media/platform/Makefile linux-3.12.26/drivers/media/platform/Makefile
---- linux-3.12.26.orig/drivers/media/platform/Makefile 2014-07-30 18:02:44.000000000 +0200
-+++ linux-3.12.26/drivers/media/platform/Makefile 2014-08-06 16:50:14.405961616 +0200
+diff -Nur linux-3.12.33/drivers/media/platform/Makefile linux-3.12.33-rpi/drivers/media/platform/Makefile
+--- linux-3.12.33/drivers/media/platform/Makefile 2014-11-15 06:28:07.000000000 -0600
++++ linux-3.12.33-rpi/drivers/media/platform/Makefile 2014-12-03 19:13:38.012418001 -0600
@@ -52,4 +52,6 @@
obj-$(CONFIG_ARCH_OMAP) += omap/
@@ -18183,9 +23967,9 @@ diff -Nur linux-3.12.26.orig/drivers/media/platform/Makefile linux-3.12.26/drive
+obj-$(CONFIG_VIDEO_BCM2835) += bcm2835/
+
ccflags-y += -I$(srctree)/drivers/media/i2c
-diff -Nur linux-3.12.26.orig/drivers/media/usb/dvb-usb-v2/rtl28xxu.c linux-3.12.26/drivers/media/usb/dvb-usb-v2/rtl28xxu.c
---- linux-3.12.26.orig/drivers/media/usb/dvb-usb-v2/rtl28xxu.c 2014-07-30 18:02:44.000000000 +0200
-+++ linux-3.12.26/drivers/media/usb/dvb-usb-v2/rtl28xxu.c 2014-08-06 16:50:14.405961616 +0200
+diff -Nur linux-3.12.33/drivers/media/usb/dvb-usb-v2/rtl28xxu.c linux-3.12.33-rpi/drivers/media/usb/dvb-usb-v2/rtl28xxu.c
+--- linux-3.12.33/drivers/media/usb/dvb-usb-v2/rtl28xxu.c 2014-11-15 06:28:07.000000000 -0600
++++ linux-3.12.33-rpi/drivers/media/usb/dvb-usb-v2/rtl28xxu.c 2014-12-03 19:13:38.092418001 -0600
@@ -1390,6 +1390,10 @@
&rtl2832u_props, "Compro VideoMate U620F", NULL) },
{ DVB_USB_DEVICE(USB_VID_KWORLD_2, 0xd394,
@@ -18197,26 +23981,338 @@ diff -Nur linux-3.12.26.orig/drivers/media/usb/dvb-usb-v2/rtl28xxu.c linux-3.12.
{ 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.26.orig/drivers/misc/Kconfig linux-3.12.26/drivers/misc/Kconfig
---- linux-3.12.26.orig/drivers/misc/Kconfig 2014-07-30 18:02:44.000000000 +0200
-+++ linux-3.12.26/drivers/misc/Kconfig 2014-08-06 16:50:14.405961616 +0200
+diff -Nur linux-3.12.33/drivers/media/usb/usbtv/usbtv.c linux-3.12.33-rpi/drivers/media/usb/usbtv/usbtv.c
+--- linux-3.12.33/drivers/media/usb/usbtv/usbtv.c 2014-11-15 06:28:07.000000000 -0600
++++ linux-3.12.33-rpi/drivers/media/usb/usbtv/usbtv.c 2014-12-03 19:13:38.136418001 -0600
+@@ -50,13 +50,8 @@
+ #define USBTV_ISOC_TRANSFERS 16
+ #define USBTV_ISOC_PACKETS 8
+
+-#define USBTV_WIDTH 720
+-#define USBTV_HEIGHT 480
+-
+ #define USBTV_CHUNK_SIZE 256
+ #define USBTV_CHUNK 240
+-#define USBTV_CHUNKS (USBTV_WIDTH * USBTV_HEIGHT \
+- / 4 / USBTV_CHUNK)
+
+ /* Chunk header. */
+ #define USBTV_MAGIC_OK(chunk) ((be32_to_cpu(chunk[0]) & 0xff000000) \
+@@ -65,6 +60,27 @@
+ #define USBTV_ODD(chunk) ((be32_to_cpu(chunk[0]) & 0x0000f000) >> 15)
+ #define USBTV_CHUNK_NO(chunk) (be32_to_cpu(chunk[0]) & 0x00000fff)
+
++#define USBTV_TV_STD (V4L2_STD_525_60 | V4L2_STD_PAL)
++
++/* parameters for supported TV norms */
++struct usbtv_norm_params {
++ v4l2_std_id norm;
++ int cap_width, cap_height;
++};
++
++static struct usbtv_norm_params norm_params[] = {
++ {
++ .norm = V4L2_STD_525_60,
++ .cap_width = 720,
++ .cap_height = 480,
++ },
++ {
++ .norm = V4L2_STD_PAL,
++ .cap_width = 720,
++ .cap_height = 576,
++ }
++};
++
+ /* A single videobuf2 frame buffer. */
+ struct usbtv_buf {
+ struct vb2_buffer vb;
+@@ -94,11 +110,38 @@
+ USBTV_COMPOSITE_INPUT,
+ USBTV_SVIDEO_INPUT,
+ } input;
++ v4l2_std_id norm;
++ int width, height;
++ int n_chunks;
+ int iso_size;
+ unsigned int sequence;
+ struct urb *isoc_urbs[USBTV_ISOC_TRANSFERS];
+ };
+
++static int usbtv_configure_for_norm(struct usbtv *usbtv, v4l2_std_id norm)
++{
++ int i, ret = 0;
++ struct usbtv_norm_params *params = NULL;
++
++ for (i = 0; i < ARRAY_SIZE(norm_params); i++) {
++ if (norm_params[i].norm & norm) {
++ params = &norm_params[i];
++ break;
++ }
++ }
++
++ if (params) {
++ usbtv->width = params->cap_width;
++ usbtv->height = params->cap_height;
++ usbtv->n_chunks = usbtv->width * usbtv->height
++ / 4 / USBTV_CHUNK;
++ usbtv->norm = params->norm;
++ } else
++ ret = -EINVAL;
++
++ return ret;
++}
++
+ static int usbtv_set_regs(struct usbtv *usbtv, const u16 regs[][2], int size)
+ {
+ int ret;
+@@ -158,6 +201,57 @@
+ return ret;
+ }
+
++static int usbtv_select_norm(struct usbtv *usbtv, v4l2_std_id norm)
++{
++ int ret;
++ static const u16 pal[][2] = {
++ { USBTV_BASE + 0x001a, 0x0068 },
++ { USBTV_BASE + 0x010e, 0x0072 },
++ { USBTV_BASE + 0x010f, 0x00a2 },
++ { USBTV_BASE + 0x0112, 0x00b0 },
++ { USBTV_BASE + 0x0117, 0x0001 },
++ { USBTV_BASE + 0x0118, 0x002c },
++ { USBTV_BASE + 0x012d, 0x0010 },
++ { USBTV_BASE + 0x012f, 0x0020 },
++ { USBTV_BASE + 0x024f, 0x0002 },
++ { USBTV_BASE + 0x0254, 0x0059 },
++ { USBTV_BASE + 0x025a, 0x0016 },
++ { USBTV_BASE + 0x025b, 0x0035 },
++ { USBTV_BASE + 0x0263, 0x0017 },
++ { USBTV_BASE + 0x0266, 0x0016 },
++ { USBTV_BASE + 0x0267, 0x0036 }
++ };
++
++ static const u16 ntsc[][2] = {
++ { USBTV_BASE + 0x001a, 0x0079 },
++ { USBTV_BASE + 0x010e, 0x0068 },
++ { USBTV_BASE + 0x010f, 0x009c },
++ { USBTV_BASE + 0x0112, 0x00f0 },
++ { USBTV_BASE + 0x0117, 0x0000 },
++ { USBTV_BASE + 0x0118, 0x00fc },
++ { USBTV_BASE + 0x012d, 0x0004 },
++ { USBTV_BASE + 0x012f, 0x0008 },
++ { USBTV_BASE + 0x024f, 0x0001 },
++ { USBTV_BASE + 0x0254, 0x005f },
++ { USBTV_BASE + 0x025a, 0x0012 },
++ { USBTV_BASE + 0x025b, 0x0001 },
++ { USBTV_BASE + 0x0263, 0x001c },
++ { USBTV_BASE + 0x0266, 0x0011 },
++ { USBTV_BASE + 0x0267, 0x0005 }
++ };
++
++ ret = usbtv_configure_for_norm(usbtv, norm);
++
++ if (!ret) {
++ if (norm & V4L2_STD_525_60)
++ ret = usbtv_set_regs(usbtv, ntsc, ARRAY_SIZE(ntsc));
++ else if (norm & V4L2_STD_PAL)
++ ret = usbtv_set_regs(usbtv, pal, ARRAY_SIZE(pal));
++ }
++
++ return ret;
++}
++
+ static int usbtv_setup_capture(struct usbtv *usbtv)
+ {
+ int ret;
+@@ -225,26 +319,11 @@
+
+ { USBTV_BASE + 0x0284, 0x0088 },
+ { USBTV_BASE + 0x0003, 0x0004 },
+- { USBTV_BASE + 0x001a, 0x0079 },
+ { USBTV_BASE + 0x0100, 0x00d3 },
+- { USBTV_BASE + 0x010e, 0x0068 },
+- { USBTV_BASE + 0x010f, 0x009c },
+- { USBTV_BASE + 0x0112, 0x00f0 },
+ { USBTV_BASE + 0x0115, 0x0015 },
+- { USBTV_BASE + 0x0117, 0x0000 },
+- { USBTV_BASE + 0x0118, 0x00fc },
+- { USBTV_BASE + 0x012d, 0x0004 },
+- { USBTV_BASE + 0x012f, 0x0008 },
+ { USBTV_BASE + 0x0220, 0x002e },
+ { USBTV_BASE + 0x0225, 0x0008 },
+ { USBTV_BASE + 0x024e, 0x0002 },
+- { USBTV_BASE + 0x024f, 0x0001 },
+- { USBTV_BASE + 0x0254, 0x005f },
+- { USBTV_BASE + 0x025a, 0x0012 },
+- { USBTV_BASE + 0x025b, 0x0001 },
+- { USBTV_BASE + 0x0263, 0x001c },
+- { USBTV_BASE + 0x0266, 0x0011 },
+- { USBTV_BASE + 0x0267, 0x0005 },
+ { USBTV_BASE + 0x024e, 0x0002 },
+ { USBTV_BASE + 0x024f, 0x0002 },
+ };
+@@ -253,6 +332,10 @@
+ if (ret)
+ return ret;
+
++ ret = usbtv_select_norm(usbtv, usbtv->norm);
++ if (ret)
++ return ret;
++
+ ret = usbtv_select_input(usbtv, usbtv->input);
+ if (ret)
+ return ret;
+@@ -296,7 +379,7 @@
+ frame_id = USBTV_FRAME_ID(chunk);
+ odd = USBTV_ODD(chunk);
+ chunk_no = USBTV_CHUNK_NO(chunk);
+- if (chunk_no >= USBTV_CHUNKS)
++ if (chunk_no >= usbtv->n_chunks)
+ return;
+
+ /* Beginning of a frame. */
+@@ -324,10 +407,10 @@
+ usbtv->chunks_done++;
+
+ /* Last chunk in a frame, signalling an end */
+- if (odd && chunk_no == USBTV_CHUNKS-1) {
++ if (odd && chunk_no == usbtv->n_chunks-1) {
+ int size = vb2_plane_size(&buf->vb, 0);
+ enum vb2_buffer_state state = usbtv->chunks_done ==
+- USBTV_CHUNKS ?
++ usbtv->n_chunks ?
+ VB2_BUF_STATE_DONE :
+ VB2_BUF_STATE_ERROR;
+
+@@ -500,6 +583,8 @@
+ static int usbtv_enum_input(struct file *file, void *priv,
+ struct v4l2_input *i)
+ {
++ struct usbtv *dev = video_drvdata(file);
++
+ switch (i->index) {
+ case USBTV_COMPOSITE_INPUT:
+ strlcpy(i->name, "Composite", sizeof(i->name));
+@@ -512,7 +597,7 @@
+ }
+
+ i->type = V4L2_INPUT_TYPE_CAMERA;
+- i->std = V4L2_STD_525_60;
++ i->std = dev->vdev.tvnorms;
+ return 0;
+ }
+
+@@ -531,23 +616,37 @@
+ static int usbtv_fmt_vid_cap(struct file *file, void *priv,
+ struct v4l2_format *f)
+ {
+- f->fmt.pix.width = USBTV_WIDTH;
+- f->fmt.pix.height = USBTV_HEIGHT;
++ struct usbtv *usbtv = video_drvdata(file);
++
++ f->fmt.pix.width = usbtv->width;
++ f->fmt.pix.height = usbtv->height;
+ f->fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV;
+ f->fmt.pix.field = V4L2_FIELD_INTERLACED;
+- f->fmt.pix.bytesperline = USBTV_WIDTH * 2;
++ f->fmt.pix.bytesperline = usbtv->width * 2;
+ f->fmt.pix.sizeimage = (f->fmt.pix.bytesperline * f->fmt.pix.height);
+ f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
+- f->fmt.pix.priv = 0;
++
+ return 0;
+ }
+
+ static int usbtv_g_std(struct file *file, void *priv, v4l2_std_id *norm)
+ {
+- *norm = V4L2_STD_525_60;
++ struct usbtv *usbtv = video_drvdata(file);
++ *norm = usbtv->norm;
+ return 0;
+ }
+
++static int usbtv_s_std(struct file *file, void *priv, v4l2_std_id norm)
++{
++ int ret = -EINVAL;
++ struct usbtv *usbtv = video_drvdata(file);
++
++ if ((norm & V4L2_STD_525_60) || (norm & V4L2_STD_PAL))
++ ret = usbtv_select_norm(usbtv, norm);
++
++ return ret;
++}
++
+ static int usbtv_g_input(struct file *file, void *priv, unsigned int *i)
+ {
+ struct usbtv *usbtv = video_drvdata(file);
+@@ -561,13 +660,6 @@
+ return usbtv_select_input(usbtv, i);
+ }
+
+-static int usbtv_s_std(struct file *file, void *priv, v4l2_std_id norm)
+-{
+- if (norm & V4L2_STD_525_60)
+- return 0;
+- return -EINVAL;
+-}
+-
+ struct v4l2_ioctl_ops usbtv_ioctl_ops = {
+ .vidioc_querycap = usbtv_querycap,
+ .vidioc_enum_input = usbtv_enum_input,
+@@ -604,10 +696,12 @@
+ const struct v4l2_format *v4l_fmt, unsigned int *nbuffers,
+ unsigned int *nplanes, unsigned int sizes[], void *alloc_ctxs[])
+ {
++ struct usbtv *usbtv = vb2_get_drv_priv(vq);
++
+ if (*nbuffers < 2)
+ *nbuffers = 2;
+ *nplanes = 1;
+- sizes[0] = USBTV_WIDTH * USBTV_HEIGHT / 2 * sizeof(u32);
++ sizes[0] = USBTV_CHUNK * usbtv->n_chunks * 2 * sizeof(u32);
+
+ return 0;
+ }
+@@ -690,7 +784,11 @@
+ return -ENOMEM;
+ usbtv->dev = dev;
+ usbtv->udev = usb_get_dev(interface_to_usbdev(intf));
++
+ usbtv->iso_size = size;
++
++ (void)usbtv_configure_for_norm(usbtv, V4L2_STD_525_60);
++
+ spin_lock_init(&usbtv->buflock);
+ mutex_init(&usbtv->v4l2_lock);
+ mutex_init(&usbtv->vb2q_lock);
+@@ -727,7 +825,7 @@
+ usbtv->vdev.release = video_device_release_empty;
+ usbtv->vdev.fops = &usbtv_fops;
+ usbtv->vdev.ioctl_ops = &usbtv_ioctl_ops;
+- usbtv->vdev.tvnorms = V4L2_STD_525_60;
++ usbtv->vdev.tvnorms = USBTV_TV_STD;
+ usbtv->vdev.queue = &usbtv->vb2q;
+ usbtv->vdev.lock = &usbtv->v4l2_lock;
+ set_bit(V4L2_FL_USE_FH_PRIO, &usbtv->vdev.flags);
+diff -Nur linux-3.12.33/drivers/misc/Kconfig linux-3.12.33-rpi/drivers/misc/Kconfig
+--- linux-3.12.33/drivers/misc/Kconfig 2014-11-15 06:28:07.000000000 -0600
++++ linux-3.12.33-rpi/drivers/misc/Kconfig 2014-12-03 19:13:38.208418001 -0600
@@ -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.26.orig/drivers/misc/Makefile linux-3.12.26/drivers/misc/Makefile
---- linux-3.12.26.orig/drivers/misc/Makefile 2014-07-30 18:02:44.000000000 +0200
-+++ linux-3.12.26/drivers/misc/Makefile 2014-08-06 16:50:14.421961742 +0200
+diff -Nur linux-3.12.33/drivers/misc/Makefile linux-3.12.33-rpi/drivers/misc/Makefile
+--- linux-3.12.33/drivers/misc/Makefile 2014-11-15 06:28:07.000000000 -0600
++++ linux-3.12.33-rpi/drivers/misc/Makefile 2014-12-03 19:13:38.208418001 -0600
@@ -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.26.orig/drivers/misc/vc04_services/interface/vchi/connections/connection.h linux-3.12.26/drivers/misc/vc04_services/interface/vchi/connections/connection.h
---- linux-3.12.26.orig/drivers/misc/vc04_services/interface/vchi/connections/connection.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-3.12.26/drivers/misc/vc04_services/interface/vchi/connections/connection.h 2014-08-06 16:50:14.425961773 +0200
+diff -Nur linux-3.12.33/drivers/misc/vc04_services/interface/vchi/connections/connection.h linux-3.12.33-rpi/drivers/misc/vc04_services/interface/vchi/connections/connection.h
+--- linux-3.12.33/drivers/misc/vc04_services/interface/vchi/connections/connection.h 1969-12-31 18:00:00.000000000 -0600
++++ linux-3.12.33-rpi/drivers/misc/vc04_services/interface/vchi/connections/connection.h 2014-12-03 19:13:38.224418001 -0600
@@ -0,0 +1,328 @@
+/**
+ * Copyright (c) 2010-2012 Broadcom. All rights reserved.
@@ -18546,9 +24642,9 @@ diff -Nur linux-3.12.26.orig/drivers/misc/vc04_services/interface/vchi/connectio
+#endif /* CONNECTION_H_ */
+
+/****************************** End of file **********************************/
-diff -Nur linux-3.12.26.orig/drivers/misc/vc04_services/interface/vchi/message_drivers/message.h linux-3.12.26/drivers/misc/vc04_services/interface/vchi/message_drivers/message.h
---- linux-3.12.26.orig/drivers/misc/vc04_services/interface/vchi/message_drivers/message.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-3.12.26/drivers/misc/vc04_services/interface/vchi/message_drivers/message.h 2014-08-06 16:50:14.425961773 +0200
+diff -Nur linux-3.12.33/drivers/misc/vc04_services/interface/vchi/message_drivers/message.h linux-3.12.33-rpi/drivers/misc/vc04_services/interface/vchi/message_drivers/message.h
+--- linux-3.12.33/drivers/misc/vc04_services/interface/vchi/message_drivers/message.h 1969-12-31 18:00:00.000000000 -0600
++++ linux-3.12.33-rpi/drivers/misc/vc04_services/interface/vchi/message_drivers/message.h 2014-12-03 19:13:38.224418001 -0600
@@ -0,0 +1,204 @@
+/**
+ * Copyright (c) 2010-2012 Broadcom. All rights reserved.
@@ -18754,9 +24850,9 @@ diff -Nur linux-3.12.26.orig/drivers/misc/vc04_services/interface/vchi/message_d
+#endif // _VCHI_MESSAGE_H_
+
+/****************************** End of file ***********************************/
-diff -Nur linux-3.12.26.orig/drivers/misc/vc04_services/interface/vchi/vchi_cfg.h linux-3.12.26/drivers/misc/vc04_services/interface/vchi/vchi_cfg.h
---- linux-3.12.26.orig/drivers/misc/vc04_services/interface/vchi/vchi_cfg.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-3.12.26/drivers/misc/vc04_services/interface/vchi/vchi_cfg.h 2014-08-06 16:50:14.425961773 +0200
+diff -Nur linux-3.12.33/drivers/misc/vc04_services/interface/vchi/vchi_cfg.h linux-3.12.33-rpi/drivers/misc/vc04_services/interface/vchi/vchi_cfg.h
+--- linux-3.12.33/drivers/misc/vc04_services/interface/vchi/vchi_cfg.h 1969-12-31 18:00:00.000000000 -0600
++++ linux-3.12.33-rpi/drivers/misc/vc04_services/interface/vchi/vchi_cfg.h 2014-12-03 19:13:38.224418001 -0600
@@ -0,0 +1,224 @@
+/**
+ * Copyright (c) 2010-2012 Broadcom. All rights reserved.
@@ -18982,9 +25078,9 @@ diff -Nur linux-3.12.26.orig/drivers/misc/vc04_services/interface/vchi/vchi_cfg.
+#endif /* VCHI_CFG_H_ */
+
+/****************************** End of file **********************************/
-diff -Nur linux-3.12.26.orig/drivers/misc/vc04_services/interface/vchi/vchi_cfg_internal.h linux-3.12.26/drivers/misc/vc04_services/interface/vchi/vchi_cfg_internal.h
---- linux-3.12.26.orig/drivers/misc/vc04_services/interface/vchi/vchi_cfg_internal.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-3.12.26/drivers/misc/vc04_services/interface/vchi/vchi_cfg_internal.h 2014-08-06 16:50:14.441961899 +0200
+diff -Nur linux-3.12.33/drivers/misc/vc04_services/interface/vchi/vchi_cfg_internal.h linux-3.12.33-rpi/drivers/misc/vc04_services/interface/vchi/vchi_cfg_internal.h
+--- linux-3.12.33/drivers/misc/vc04_services/interface/vchi/vchi_cfg_internal.h 1969-12-31 18:00:00.000000000 -0600
++++ linux-3.12.33-rpi/drivers/misc/vc04_services/interface/vchi/vchi_cfg_internal.h 2014-12-03 19:13:38.224418001 -0600
@@ -0,0 +1,71 @@
+/**
+ * Copyright (c) 2010-2012 Broadcom. All rights reserved.
@@ -19057,10 +25153,10 @@ diff -Nur linux-3.12.26.orig/drivers/misc/vc04_services/interface/vchi/vchi_cfg_
+//#define VCHI_RX_NANOLOCKS
+
+#endif /*VCHI_CFG_INTERNAL_H_*/
-diff -Nur linux-3.12.26.orig/drivers/misc/vc04_services/interface/vchi/vchi_common.h linux-3.12.26/drivers/misc/vc04_services/interface/vchi/vchi_common.h
---- linux-3.12.26.orig/drivers/misc/vc04_services/interface/vchi/vchi_common.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-3.12.26/drivers/misc/vc04_services/interface/vchi/vchi_common.h 2014-08-06 16:50:14.445961931 +0200
-@@ -0,0 +1,163 @@
+diff -Nur linux-3.12.33/drivers/misc/vc04_services/interface/vchi/vchi_common.h linux-3.12.33-rpi/drivers/misc/vc04_services/interface/vchi/vchi_common.h
+--- linux-3.12.33/drivers/misc/vc04_services/interface/vchi/vchi_common.h 1969-12-31 18:00:00.000000000 -0600
++++ linux-3.12.33-rpi/drivers/misc/vc04_services/interface/vchi/vchi_common.h 2014-12-03 19:13:38.224418001 -0600
+@@ -0,0 +1,174 @@
+/**
+ * Copyright (c) 2010-2012 Broadcom. All rights reserved.
+ *
@@ -19173,7 +25269,18 @@ diff -Nur linux-3.12.26.orig/drivers/misc/vc04_services/interface/vchi/vchi_comm
+ VCHI_CALLBACK_REASON_MAX
+} VCHI_CALLBACK_REASON_T;
+
-+//Calback used by all services / bulk transfers
++// service control options
++typedef enum
++{
++ VCHI_SERVICE_OPTION_MIN,
++
++ VCHI_SERVICE_OPTION_TRACE,
++
++ VCHI_SERVICE_OPTION_MAX
++} VCHI_SERVICE_OPTION_T;
++
++
++//Callback used by all services / bulk transfers
+typedef void (*VCHI_CALLBACK_T)( void *callback_param, //my service local param
+ VCHI_CALLBACK_REASON_T reason,
+ void *handle ); //for transmitting msg's only
@@ -19224,10 +25331,10 @@ diff -Nur linux-3.12.26.orig/drivers/misc/vc04_services/interface/vchi/vchi_comm
+
+
+#endif // VCHI_COMMON_H_
-diff -Nur linux-3.12.26.orig/drivers/misc/vc04_services/interface/vchi/vchi.h linux-3.12.26/drivers/misc/vc04_services/interface/vchi/vchi.h
---- linux-3.12.26.orig/drivers/misc/vc04_services/interface/vchi/vchi.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-3.12.26/drivers/misc/vc04_services/interface/vchi/vchi.h 2014-08-06 16:50:14.445961931 +0200
-@@ -0,0 +1,373 @@
+diff -Nur linux-3.12.33/drivers/misc/vc04_services/interface/vchi/vchi.h linux-3.12.33-rpi/drivers/misc/vc04_services/interface/vchi/vchi.h
+--- linux-3.12.33/drivers/misc/vc04_services/interface/vchi/vchi.h 1969-12-31 18:00:00.000000000 -0600
++++ linux-3.12.33-rpi/drivers/misc/vc04_services/interface/vchi/vchi.h 2014-12-03 19:13:38.224418001 -0600
+@@ -0,0 +1,378 @@
+/**
+ * Copyright (c) 2010-2012 Broadcom. All rights reserved.
+ *
@@ -19450,7 +25557,12 @@ diff -Nur linux-3.12.26.orig/drivers/misc/vc04_services/interface/vchi/vchi.h li
+// Routine to decrement ref count on a named service
+extern int32_t vchi_service_release( const VCHI_SERVICE_HANDLE_T handle );
+
-+// Routine to send a message accross a service
++// Routine to set a control option for a named service
++extern int32_t vchi_service_set_option( const VCHI_SERVICE_HANDLE_T handle,
++ VCHI_SERVICE_OPTION_T option,
++ int value);
++
++// Routine to send a message across a service
+extern int32_t vchi_msg_queue( VCHI_SERVICE_HANDLE_T handle,
+ const void *data,
+ uint32_t data_size,
@@ -19601,9 +25713,9 @@ diff -Nur linux-3.12.26.orig/drivers/misc/vc04_services/interface/vchi/vchi.h li
+#endif /* VCHI_H_ */
+
+/****************************** End of file **********************************/
-diff -Nur linux-3.12.26.orig/drivers/misc/vc04_services/interface/vchi/vchi_mh.h linux-3.12.26/drivers/misc/vc04_services/interface/vchi/vchi_mh.h
---- linux-3.12.26.orig/drivers/misc/vc04_services/interface/vchi/vchi_mh.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-3.12.26/drivers/misc/vc04_services/interface/vchi/vchi_mh.h 2014-08-06 16:50:14.449961962 +0200
+diff -Nur linux-3.12.33/drivers/misc/vc04_services/interface/vchi/vchi_mh.h linux-3.12.33-rpi/drivers/misc/vc04_services/interface/vchi/vchi_mh.h
+--- linux-3.12.33/drivers/misc/vc04_services/interface/vchi/vchi_mh.h 1969-12-31 18:00:00.000000000 -0600
++++ linux-3.12.33-rpi/drivers/misc/vc04_services/interface/vchi/vchi_mh.h 2014-12-03 19:13:38.224418001 -0600
@@ -0,0 +1,42 @@
+/**
+ * Copyright (c) 2010-2012 Broadcom. All rights reserved.
@@ -19647,10 +25759,10 @@ diff -Nur linux-3.12.26.orig/drivers/misc/vc04_services/interface/vchi/vchi_mh.h
+#define VCHI_MEM_HANDLE_INVALID 0
+
+#endif
-diff -Nur linux-3.12.26.orig/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_2835_arm.c linux-3.12.26/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_2835_arm.c
---- linux-3.12.26.orig/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_2835_arm.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-3.12.26/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_2835_arm.c 2014-08-06 16:50:14.449961962 +0200
-@@ -0,0 +1,561 @@
+diff -Nur linux-3.12.33/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_2835_arm.c linux-3.12.33-rpi/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_2835_arm.c
+--- linux-3.12.33/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_2835_arm.c 1969-12-31 18:00:00.000000000 -0600
++++ linux-3.12.33-rpi/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_2835_arm.c 2014-12-03 19:13:38.224418001 -0600
+@@ -0,0 +1,562 @@
+/**
+ * Copyright (c) 2010-2012 Broadcom. All rights reserved.
+ *
@@ -19709,6 +25821,7 @@ diff -Nur linux-3.12.26.orig/drivers/misc/vc04_services/interface/vchiq_arm/vchi
+#include "vchiq_arm.h"
+#include "vchiq_2835.h"
+#include "vchiq_connected.h"
++#include "vchiq_killable.h"
+
+#define MAX_FRAGMENTS (VCHIQ_NUM_CURRENT_BULKS * 2)
+
@@ -20212,9 +26325,9 @@ diff -Nur linux-3.12.26.orig/drivers/misc/vc04_services/interface/vchiq_arm/vchi
+
+ kfree(pagelist);
+}
-diff -Nur linux-3.12.26.orig/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_2835.h linux-3.12.26/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_2835.h
---- linux-3.12.26.orig/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_2835.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-3.12.26/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_2835.h 2014-08-06 16:50:14.449961962 +0200
+diff -Nur linux-3.12.33/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_2835.h linux-3.12.33-rpi/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_2835.h
+--- linux-3.12.33/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_2835.h 1969-12-31 18:00:00.000000000 -0600
++++ linux-3.12.33-rpi/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_2835.h 2014-12-03 19:13:38.224418001 -0600
@@ -0,0 +1,42 @@
+/**
+ * Copyright (c) 2010-2012 Broadcom. All rights reserved.
@@ -20258,11 +26371,12 @@ diff -Nur linux-3.12.26.orig/drivers/misc/vc04_services/interface/vchiq_arm/vchi
+#define VCHIQ_PLATFORM_FRAGMENTS_COUNT_IDX 1
+
+#endif /* VCHIQ_2835_H */
-diff -Nur linux-3.12.26.orig/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_arm.c linux-3.12.26/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_arm.c
---- linux-3.12.26.orig/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_arm.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-3.12.26/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_arm.c 2014-08-06 16:50:14.449961962 +0200
-@@ -0,0 +1,2813 @@
+diff -Nur linux-3.12.33/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_arm.c linux-3.12.33-rpi/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_arm.c
+--- linux-3.12.33/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_arm.c 1969-12-31 18:00:00.000000000 -0600
++++ linux-3.12.33-rpi/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_arm.c 2014-12-03 19:13:38.224418001 -0600
+@@ -0,0 +1,2884 @@
+/**
++ * Copyright (c) 2014 Raspberry Pi (Trading) Ltd. All rights reserved.
+ * Copyright (c) 2010-2012 Broadcom. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
@@ -20308,11 +26422,12 @@ diff -Nur linux-3.12.26.orig/drivers/misc/vc04_services/interface/vchiq_arm/vchi
+#include <linux/bug.h>
+#include <linux/semaphore.h>
+#include <linux/list.h>
-+#include <linux/proc_fs.h>
+
+#include "vchiq_core.h"
+#include "vchiq_ioctl.h"
+#include "vchiq_arm.h"
++#include "vchiq_killable.h"
++#include "vchiq_debugfs.h"
+
+#define DEVICE_NAME "vchiq"
+
@@ -20368,21 +26483,21 @@ diff -Nur linux-3.12.26.orig/drivers/misc/vc04_services/interface/vchiq_arm/vchi
+
+
+static void suspend_timer_callback(unsigned long context);
-+static int vchiq_proc_add_instance(VCHIQ_INSTANCE_T instance);
-+static void vchiq_proc_remove_instance(VCHIQ_INSTANCE_T instance);
+
+
+typedef struct user_service_struct {
+ VCHIQ_SERVICE_T *service;
+ void *userdata;
+ VCHIQ_INSTANCE_T instance;
-+ int is_vchi;
-+ int dequeue_pending;
++ char is_vchi;
++ char dequeue_pending;
++ char close_pending;
+ int message_available_pos;
+ int msg_insert;
+ int msg_remove;
+ struct semaphore insert_event;
+ struct semaphore remove_event;
++ struct semaphore close_event;
+ VCHIQ_HEADER_T * msg_queue[MSG_QUEUE_SIZE];
+} USER_SERVICE_T;
+
@@ -20405,11 +26520,13 @@ diff -Nur linux-3.12.26.orig/drivers/misc/vc04_services/interface/vchiq_arm/vchi
+ int closing;
+ int pid;
+ int mark;
++ int use_close_delivered;
++ int trace;
+
+ struct list_head bulk_waiter_list;
+ struct mutex bulk_waiter_list_mutex;
+
-+ struct proc_dir_entry *proc_entry;
++ VCHIQ_DEBUGFS_NODE_T debugfs_node;
+};
+
+typedef struct dump_context_struct {
@@ -20442,7 +26559,9 @@ diff -Nur linux-3.12.26.orig/drivers/misc/vc04_services/interface/vchiq_arm/vchi
+ "USE_SERVICE",
+ "RELEASE_SERVICE",
+ "SET_SERVICE_OPTION",
-+ "DUMP_PHYS_MEM"
++ "DUMP_PHYS_MEM",
++ "LIB_VERSION",
++ "CLOSE_DELIVERED"
+};
+
+vchiq_static_assert((sizeof(ioctl_names)/sizeof(ioctl_names[0])) ==
@@ -20494,10 +26613,13 @@ diff -Nur linux-3.12.26.orig/drivers/misc/vc04_services/interface/vchiq_arm/vchi
+ completion->service_userdata = user_service->service;
+ completion->bulk_userdata = bulk_userdata;
+
-+ if (reason == VCHIQ_SERVICE_CLOSED)
++ if (reason == VCHIQ_SERVICE_CLOSED) {
+ /* Take an extra reference, to be held until
+ this CLOSED notification is delivered. */
+ lock_service(user_service->service);
++ if (instance->use_close_delivered)
++ user_service->close_pending = 1;
++ }
+
+ /* A write barrier is needed here to ensure that the entire completion
+ record is written out before the insert point. */
@@ -20544,10 +26666,10 @@ diff -Nur linux-3.12.26.orig/drivers/misc/vc04_services/interface/vchiq_arm/vchi
+ return VCHIQ_SUCCESS;
+
+ vchiq_log_trace(vchiq_arm_log_level,
-+ "service_callback - service %lx(%d), reason %d, header %lx, "
++ "service_callback - service %lx(%d,%p), reason %d, header %lx, "
+ "instance %lx, bulk_userdata %lx",
+ (unsigned long)user_service,
-+ service->localport,
++ service->localport, user_service->userdata,
+ reason, (unsigned long)header,
+ (unsigned long)instance, (unsigned long)bulk_userdata);
+
@@ -20634,10 +26756,31 @@ diff -Nur linux-3.12.26.orig/drivers/misc/vc04_services/interface/vchiq_arm/vchi
+
+/****************************************************************************
+*
-+* vchiq_ioctl
++* close_delivered
+*
+***************************************************************************/
++static void close_delivered(USER_SERVICE_T *user_service)
++{
++ vchiq_log_info(vchiq_arm_log_level,
++ "close_delivered(handle=%x)",
++ user_service->service->handle);
++
++ if (user_service->close_pending) {
++ /* Allow the underlying service to be culled */
++ unlock_service(user_service->service);
++
++ /* Wake the user-thread blocked in close_ or remove_service */
++ up(&user_service->close_event);
++
++ user_service->close_pending = 0;
++ }
++}
+
++/****************************************************************************
++*
++* vchiq_ioctl
++*
++***************************************************************************/
+static long
+vchiq_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+{
@@ -20748,14 +26891,16 @@ diff -Nur linux-3.12.26.orig/drivers/misc/vc04_services/interface/vchiq_arm/vchi
+ user_service->service = service;
+ user_service->userdata = userdata;
+ user_service->instance = instance;
-+ user_service->is_vchi = args.is_vchi;
++ user_service->is_vchi = (args.is_vchi != 0);
+ user_service->dequeue_pending = 0;
++ user_service->close_pending = 0;
+ user_service->message_available_pos =
+ instance->completion_remove - 1;
+ user_service->msg_insert = 0;
+ user_service->msg_remove = 0;
+ sema_init(&user_service->insert_event, 0);
+ sema_init(&user_service->remove_event, 0);
++ sema_init(&user_service->close_event, 0);
+
+ if (args.is_open) {
+ status = vchiq_open_service_internal
@@ -20789,8 +26934,24 @@ diff -Nur linux-3.12.26.orig/drivers/misc/vc04_services/interface/vchiq_arm/vchi
+ VCHIQ_SERVICE_HANDLE_T handle = (VCHIQ_SERVICE_HANDLE_T)arg;
+
+ service = find_service_for_instance(instance, handle);
-+ if (service != NULL)
-+ status = vchiq_close_service(service->handle);
++ if (service != NULL) {
++ USER_SERVICE_T *user_service =
++ (USER_SERVICE_T *)service->base.userdata;
++ /* close_pending is false on first entry, and when the
++ wait in vchiq_close_service has been interrupted. */
++ if (!user_service->close_pending) {
++ status = vchiq_close_service(service->handle);
++ if (status != VCHIQ_SUCCESS)
++ break;
++ }
++
++ /* close_pending is true once the underlying service
++ has been closed until the client library calls the
++ CLOSE_DELIVERED ioctl, signalling close_event. */
++ if (user_service->close_pending &&
++ down_interruptible(&user_service->close_event))
++ status = VCHIQ_RETRY;
++ }
+ else
+ ret = -EINVAL;
+ } break;
@@ -20799,8 +26960,24 @@ diff -Nur linux-3.12.26.orig/drivers/misc/vc04_services/interface/vchiq_arm/vchi
+ VCHIQ_SERVICE_HANDLE_T handle = (VCHIQ_SERVICE_HANDLE_T)arg;
+
+ service = find_service_for_instance(instance, handle);
-+ if (service != NULL)
-+ status = vchiq_remove_service(service->handle);
++ if (service != NULL) {
++ USER_SERVICE_T *user_service =
++ (USER_SERVICE_T *)service->base.userdata;
++ /* close_pending is false on first entry, and when the
++ wait in vchiq_close_service has been interrupted. */
++ if (!user_service->close_pending) {
++ status = vchiq_remove_service(service->handle);
++ if (status != VCHIQ_SUCCESS)
++ break;
++ }
++
++ /* close_pending is true once the underlying service
++ has been closed until the client library calls the
++ CLOSE_DELIVERED ioctl, signalling close_event. */
++ if (user_service->close_pending &&
++ down_interruptible(&user_service->close_event))
++ status = VCHIQ_RETRY;
++ }
+ else
+ ret = -EINVAL;
+ } break;
@@ -21067,8 +27244,9 @@ diff -Nur linux-3.12.26.orig/drivers/misc/vc04_services/interface/vchiq_arm/vchi
+ completion->header = msgbuf;
+ }
+
-+ if (completion->reason ==
-+ VCHIQ_SERVICE_CLOSED)
++ if ((completion->reason ==
++ VCHIQ_SERVICE_CLOSED) &&
++ !instance->use_close_delivered)
+ unlock_service(service);
+
+ if (copy_to_user((void __user *)(
@@ -21246,6 +27424,28 @@ diff -Nur linux-3.12.26.orig/drivers/misc/vc04_services/interface/vchiq_arm/vchi
+ dump_phys_mem(args.virt_addr, args.num_bytes);
+ } break;
+
++ case VCHIQ_IOC_LIB_VERSION: {
++ unsigned int lib_version = (unsigned int)arg;
++
++ if (lib_version < VCHIQ_VERSION_MIN)
++ ret = -EINVAL;
++ else if (lib_version >= VCHIQ_VERSION_CLOSE_DELIVERED)
++ instance->use_close_delivered = 1;
++ } break;
++
++ case VCHIQ_IOC_CLOSE_DELIVERED: {
++ VCHIQ_SERVICE_HANDLE_T handle = (VCHIQ_SERVICE_HANDLE_T)arg;
++
++ service = find_closed_service_for_instance(instance, handle);
++ if (service != NULL) {
++ USER_SERVICE_T *user_service =
++ (USER_SERVICE_T *)service->base.userdata;
++ close_delivered(user_service);
++ }
++ else
++ ret = -EINVAL;
++ } break;
++
+ default:
+ ret = -ENOTTY;
+ break;
@@ -21312,7 +27512,7 @@ diff -Nur linux-3.12.26.orig/drivers/misc/vc04_services/interface/vchiq_arm/vchi
+ instance->state = state;
+ instance->pid = current->tgid;
+
-+ ret = vchiq_proc_add_instance(instance);
++ ret = vchiq_debugfs_add_instance(instance);
+ if (ret != 0) {
+ kfree(instance);
+ return ret;
@@ -21433,7 +27633,15 @@ diff -Nur linux-3.12.26.orig/drivers/misc/vc04_services/interface/vchiq_arm/vchi
+ (MAX_COMPLETIONS - 1)];
+ service = completion->service_userdata;
+ if (completion->reason == VCHIQ_SERVICE_CLOSED)
++ {
++ USER_SERVICE_T *user_service =
++ service->base.userdata;
++
++ /* Wake any blocked user-thread */
++ if (instance->use_close_delivered)
++ up(&user_service->close_event);
+ unlock_service(service);
++ }
+ instance->completion_remove++;
+ }
+
@@ -21457,7 +27665,7 @@ diff -Nur linux-3.12.26.orig/drivers/misc/vc04_services/interface/vchiq_arm/vchi
+ }
+ }
+
-+ vchiq_proc_remove_instance(instance);
++ vchiq_debugfs_remove_instance(instance);
+
+ kfree(instance);
+ file->private_data = NULL;
@@ -22711,6 +28919,52 @@ diff -Nur linux-3.12.26.orig/drivers/misc/vc04_services/interface/vchiq_arm/vchi
+ return vchiq_release_internal(service->state, service);
+}
+
++VCHIQ_DEBUGFS_NODE_T *
++vchiq_instance_get_debugfs_node(VCHIQ_INSTANCE_T instance)
++{
++ return &instance->debugfs_node;
++}
++
++int
++vchiq_instance_get_use_count(VCHIQ_INSTANCE_T instance)
++{
++ VCHIQ_SERVICE_T *service;
++ int use_count = 0, i;
++ i = 0;
++ while ((service = next_service_by_instance(instance->state,
++ instance, &i)) != NULL) {
++ use_count += service->service_use_count;
++ unlock_service(service);
++ }
++ return use_count;
++}
++
++int
++vchiq_instance_get_pid(VCHIQ_INSTANCE_T instance)
++{
++ return instance->pid;
++}
++
++int
++vchiq_instance_get_trace(VCHIQ_INSTANCE_T instance)
++{
++ return instance->trace;
++}
++
++void
++vchiq_instance_set_trace(VCHIQ_INSTANCE_T instance, int trace)
++{
++ VCHIQ_SERVICE_T *service;
++ int i;
++ i = 0;
++ while ((service = next_service_by_instance(instance->state,
++ instance, &i)) != NULL) {
++ service->trace = trace;
++ unlock_service(service);
++ }
++ instance->trace = (trace != 0);
++}
++
+static void suspend_timer_callback(unsigned long context)
+{
+ VCHIQ_STATE_T *state = (VCHIQ_STATE_T *)context;
@@ -22926,10 +29180,10 @@ diff -Nur linux-3.12.26.orig/drivers/misc/vc04_services/interface/vchiq_arm/vchi
+ int err;
+ void *ptr_err;
+
-+ /* create proc entries */
-+ err = vchiq_proc_init();
++ /* create debugfs entries */
++ err = vchiq_debugfs_init();
+ if (err != 0)
-+ goto failed_proc_init;
++ goto failed_debugfs_init;
+
+ err = alloc_chrdev_region(&vchiq_devid, VCHIQ_MINOR, 1, DEVICE_NAME);
+ if (err != 0) {
@@ -22979,82 +29233,12 @@ diff -Nur linux-3.12.26.orig/drivers/misc/vc04_services/interface/vchiq_arm/vchi
+failed_cdev_add:
+ unregister_chrdev_region(vchiq_devid, 1);
+failed_alloc_chrdev:
-+ vchiq_proc_deinit();
-+failed_proc_init:
++ vchiq_debugfs_deinit();
++failed_debugfs_init:
+ vchiq_log_warning(vchiq_arm_log_level, "could not load vchiq");
+ return err;
+}
+
-+static int vchiq_instance_get_use_count(VCHIQ_INSTANCE_T instance)
-+{
-+ VCHIQ_SERVICE_T *service;
-+ int use_count = 0, i;
-+ i = 0;
-+ while ((service = next_service_by_instance(instance->state,
-+ instance, &i)) != NULL) {
-+ use_count += service->service_use_count;
-+ unlock_service(service);
-+ }
-+ return use_count;
-+}
-+
-+/* read the per-process use-count */
-+static int proc_read_use_count(char *page, char **start,
-+ off_t off, int count,
-+ int *eof, void *data)
-+{
-+ VCHIQ_INSTANCE_T instance = data;
-+ int len, use_count;
-+
-+ use_count = vchiq_instance_get_use_count(instance);
-+ len = snprintf(page+off, count, "%d\n", use_count);
-+
-+ return len;
-+}
-+
-+/* add an instance (process) to the proc entries */
-+static int vchiq_proc_add_instance(VCHIQ_INSTANCE_T instance)
-+{
-+#if 1
-+ return 0;
-+#else
-+ char pidstr[32];
-+ struct proc_dir_entry *top, *use_count;
-+ struct proc_dir_entry *clients = vchiq_clients_top();
-+ int pid = instance->pid;
-+
-+ snprintf(pidstr, sizeof(pidstr), "%d", pid);
-+ top = proc_mkdir(pidstr, clients);
-+ if (!top)
-+ goto fail_top;
-+
-+ use_count = create_proc_read_entry("use_count",
-+ 0444, top,
-+ proc_read_use_count,
-+ instance);
-+ if (!use_count)
-+ goto fail_use_count;
-+
-+ instance->proc_entry = top;
-+
-+ return 0;
-+
-+fail_use_count:
-+ remove_proc_entry(top->name, clients);
-+fail_top:
-+ return -ENOMEM;
-+#endif
-+}
-+
-+static void vchiq_proc_remove_instance(VCHIQ_INSTANCE_T instance)
-+{
-+#if 0
-+ struct proc_dir_entry *clients = vchiq_clients_top();
-+ remove_proc_entry("use_count", instance->proc_entry);
-+ remove_proc_entry(instance->proc_entry->name, clients);
-+#endif
-+}
-+
+/****************************************************************************
+*
+* vchiq_exit - called when the module is unloaded.
@@ -23075,11 +29259,12 @@ diff -Nur linux-3.12.26.orig/drivers/misc/vc04_services/interface/vchiq_arm/vchi
+module_exit(vchiq_exit);
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Broadcom Corporation");
-diff -Nur linux-3.12.26.orig/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_arm.h linux-3.12.26/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_arm.h
---- linux-3.12.26.orig/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_arm.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-3.12.26/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_arm.h 2014-08-06 16:50:14.449961962 +0200
-@@ -0,0 +1,212 @@
+diff -Nur linux-3.12.33/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_arm.h linux-3.12.33-rpi/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_arm.h
+--- linux-3.12.33/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_arm.h 1969-12-31 18:00:00.000000000 -0600
++++ linux-3.12.33-rpi/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_arm.h 2014-12-03 19:13:38.224418001 -0600
+@@ -0,0 +1,223 @@
+/**
++ * Copyright (c) 2014 Raspberry Pi (Trading) Ltd. All rights reserved.
+ * Copyright (c) 2010-2012 Broadcom. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
@@ -23119,6 +29304,7 @@ diff -Nur linux-3.12.26.orig/drivers/misc/vc04_services/interface/vchiq_arm/vchi
+#include <linux/semaphore.h>
+#include <linux/atomic.h>
+#include "vchiq_core.h"
++#include "vchiq_debugfs.h"
+
+
+enum vc_suspend_status {
@@ -23236,8 +29422,7 @@ diff -Nur linux-3.12.26.orig/drivers/misc/vc04_services/interface/vchiq_arm/vchi
+
+extern void
+vchiq_check_suspend(VCHIQ_STATE_T *state);
-+
-+extern VCHIQ_STATUS_T
++ VCHIQ_STATUS_T
+vchiq_use_service(VCHIQ_SERVICE_HANDLE_T handle);
+
+extern VCHIQ_STATUS_T
@@ -23273,27 +29458,37 @@ diff -Nur linux-3.12.26.orig/drivers/misc/vc04_services/interface/vchiq_arm/vchi
+extern VCHIQ_STATUS_T
+vchiq_release_internal(VCHIQ_STATE_T *state, VCHIQ_SERVICE_T *service);
+
-+void
++extern VCHIQ_DEBUGFS_NODE_T *
++vchiq_instance_get_debugfs_node(VCHIQ_INSTANCE_T instance);
++
++extern int
++vchiq_instance_get_use_count(VCHIQ_INSTANCE_T instance);
++
++extern int
++vchiq_instance_get_pid(VCHIQ_INSTANCE_T instance);
++
++extern int
++vchiq_instance_get_trace(VCHIQ_INSTANCE_T instance);
++
++extern void
++vchiq_instance_set_trace(VCHIQ_INSTANCE_T instance, int trace);
++
++extern void
+set_suspend_state(VCHIQ_ARM_STATE_T *arm_state,
+ enum vc_suspend_status new_state);
+
-+void
++extern void
+set_resume_state(VCHIQ_ARM_STATE_T *arm_state,
+ enum vc_resume_status new_state);
+
-+void
++extern void
+start_suspend_timer(VCHIQ_ARM_STATE_T *arm_state);
+
-+extern int vchiq_proc_init(void);
-+extern void vchiq_proc_deinit(void);
-+extern struct proc_dir_entry *vchiq_proc_top(void);
-+extern struct proc_dir_entry *vchiq_clients_top(void);
-+
+
+#endif /* VCHIQ_ARM_H */
-diff -Nur linux-3.12.26.orig/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_build_info.h linux-3.12.26/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_build_info.h
---- linux-3.12.26.orig/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_build_info.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-3.12.26/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_build_info.h 2014-08-06 16:50:14.469962119 +0200
+diff -Nur linux-3.12.33/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_build_info.h linux-3.12.33-rpi/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_build_info.h
+--- linux-3.12.33/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_build_info.h 1969-12-31 18:00:00.000000000 -0600
++++ linux-3.12.33-rpi/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_build_info.h 2014-12-03 19:13:38.224418001 -0600
@@ -0,0 +1,37 @@
+/**
+ * Copyright (c) 2010-2012 Broadcom. All rights reserved.
@@ -23332,12 +29527,12 @@ diff -Nur linux-3.12.26.orig/drivers/misc/vc04_services/interface/vchiq_arm/vchi
+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.26.orig/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_cfg.h linux-3.12.26/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_cfg.h
---- linux-3.12.26.orig/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_cfg.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-3.12.26/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_cfg.h 2014-08-06 16:50:14.469962119 +0200
-@@ -0,0 +1,60 @@
+diff -Nur linux-3.12.33/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_cfg.h linux-3.12.33-rpi/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_cfg.h
+--- linux-3.12.33/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_cfg.h 1969-12-31 18:00:00.000000000 -0600
++++ linux-3.12.33-rpi/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_cfg.h 2014-12-03 19:13:38.224418001 -0600
+@@ -0,0 +1,66 @@
+/**
-+ * Copyright (c) 2010-2012 Broadcom. All rights reserved.
++ * Copyright (c) 2010-2014 Broadcom. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
@@ -23374,11 +29569,17 @@ diff -Nur linux-3.12.26.orig/drivers/misc/vc04_services/interface/vchiq_arm/vchi
+
+#define VCHIQ_MAGIC VCHIQ_MAKE_FOURCC('V', 'C', 'H', 'I')
+/* The version of VCHIQ - change with any non-trivial change */
-+#define VCHIQ_VERSION 6
++#define VCHIQ_VERSION 7
+/* The minimum compatible version - update to match VCHIQ_VERSION with any
+** incompatible change */
+#define VCHIQ_VERSION_MIN 3
+
++/* The version that introduced the VCHIQ_IOC_LIB_VERSION ioctl */
++#define VCHIQ_VERSION_LIB_VERSION 7
++
++/* The version that introduced the VCHIQ_IOC_CLOSE_DELIVERED ioctl */
++#define VCHIQ_VERSION_CLOSE_DELIVERED 7
++
+#define VCHIQ_MAX_STATES 1
+#define VCHIQ_MAX_SERVICES 4096
+#define VCHIQ_MAX_SLOTS 128
@@ -23396,10 +29597,10 @@ diff -Nur linux-3.12.26.orig/drivers/misc/vc04_services/interface/vchiq_arm/vchi
+#endif
+
+#endif /* VCHIQ_CFG_H */
-diff -Nur linux-3.12.26.orig/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_connected.c linux-3.12.26/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_connected.c
---- linux-3.12.26.orig/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_connected.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-3.12.26/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_connected.c 2014-08-06 16:50:14.469962119 +0200
-@@ -0,0 +1,119 @@
+diff -Nur linux-3.12.33/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_connected.c linux-3.12.33-rpi/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_connected.c
+--- linux-3.12.33/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_connected.c 1969-12-31 18:00:00.000000000 -0600
++++ linux-3.12.33-rpi/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_connected.c 2014-12-03 19:13:38.224418001 -0600
+@@ -0,0 +1,120 @@
+/**
+ * Copyright (c) 2010-2012 Broadcom. All rights reserved.
+ *
@@ -23435,6 +29636,7 @@ diff -Nur linux-3.12.26.orig/drivers/misc/vc04_services/interface/vchiq_arm/vchi
+
+#include "vchiq_connected.h"
+#include "vchiq_core.h"
++#include "vchiq_killable.h"
+#include <linux/module.h>
+#include <linux/mutex.h>
+
@@ -23519,9 +29721,9 @@ diff -Nur linux-3.12.26.orig/drivers/misc/vc04_services/interface/vchiq_arm/vchi
+ mutex_unlock(&g_connected_mutex);
+}
+EXPORT_SYMBOL(vchiq_add_connected_callback);
-diff -Nur linux-3.12.26.orig/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_connected.h linux-3.12.26/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_connected.h
---- linux-3.12.26.orig/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_connected.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-3.12.26/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_connected.h 2014-08-06 16:50:14.489962276 +0200
+diff -Nur linux-3.12.33/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_connected.h linux-3.12.33-rpi/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_connected.h
+--- linux-3.12.33/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_connected.h 1969-12-31 18:00:00.000000000 -0600
++++ linux-3.12.33-rpi/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_connected.h 2014-12-03 19:13:38.224418001 -0600
@@ -0,0 +1,50 @@
+/**
+ * Copyright (c) 2010-2012 Broadcom. All rights reserved.
@@ -23573,10 +29775,10 @@ diff -Nur linux-3.12.26.orig/drivers/misc/vc04_services/interface/vchiq_arm/vchi
+void vchiq_call_connected_callbacks(void);
+
+#endif /* VCHIQ_CONNECTED_H */
-diff -Nur linux-3.12.26.orig/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_core.c linux-3.12.26/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_core.c
---- linux-3.12.26.orig/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_core.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-3.12.26/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_core.c 2014-08-06 16:50:14.493962307 +0200
-@@ -0,0 +1,3824 @@
+diff -Nur linux-3.12.33/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_core.c linux-3.12.33-rpi/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_core.c
+--- linux-3.12.33/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_core.c 1969-12-31 18:00:00.000000000 -0600
++++ linux-3.12.33-rpi/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_core.c 2014-12-03 19:13:38.228418001 -0600
+@@ -0,0 +1,3862 @@
+/**
+ * Copyright (c) 2010-2012 Broadcom. All rights reserved.
+ *
@@ -23611,6 +29813,7 @@ diff -Nur linux-3.12.26.orig/drivers/misc/vc04_services/interface/vchiq_arm/vchi
+ */
+
+#include "vchiq_core.h"
++#include "vchiq_killable.h"
+
+#define VCHIQ_SLOT_HANDLER_STACK 8192
+
@@ -23626,9 +29829,12 @@ diff -Nur linux-3.12.26.orig/drivers/misc/vc04_services/interface/vchiq_arm/vchi
+#define SLOT_QUEUE_INDEX_FROM_POS(pos) \
+ ((int)((unsigned int)(pos) / VCHIQ_SLOT_SIZE))
+
-+
+#define BULK_INDEX(x) (x & (VCHIQ_NUM_SERVICE_BULKS - 1))
+
++#define SRVTRACE_LEVEL(srv) \
++ (((srv) && (srv)->trace) ? VCHIQ_LOG_TRACE : vchiq_core_msg_log_level)
++#define SRVTRACE_ENABLED(srv, lev) \
++ (((srv) && (srv)->trace) || (vchiq_core_msg_log_level >= (lev)))
+
+struct vchiq_open_payload {
+ int fourcc;
@@ -23802,6 +30008,31 @@ diff -Nur linux-3.12.26.orig/drivers/misc/vc04_services/interface/vchiq_arm/vchi
+}
+
+VCHIQ_SERVICE_T *
++find_closed_service_for_instance(VCHIQ_INSTANCE_T instance,
++ VCHIQ_SERVICE_HANDLE_T handle) {
++ VCHIQ_SERVICE_T *service;
++
++ spin_lock(&service_spinlock);
++ service = handle_to_service(handle);
++ if (service &&
++ ((service->srvstate == VCHIQ_SRVSTATE_FREE) ||
++ (service->srvstate == VCHIQ_SRVSTATE_CLOSED)) &&
++ (service->handle == handle) &&
++ (service->instance == instance)) {
++ BUG_ON(service->ref_count == 0);
++ service->ref_count++;
++ } else
++ service = NULL;
++ spin_unlock(&service_spinlock);
++
++ if (!service)
++ vchiq_log_info(vchiq_core_log_level,
++ "Invalid service handle 0x%x", handle);
++
++ return service;
++}
++
++VCHIQ_SERVICE_T *
+next_service_by_instance(VCHIQ_STATE_T *state, VCHIQ_INSTANCE_T instance,
+ int *pidx)
+{
@@ -24428,8 +30659,8 @@ diff -Nur linux-3.12.26.orig/drivers/misc/vc04_services/interface/vchiq_arm/vchi
+ return VCHIQ_ERROR;
+ }
+ if (i == 0) {
-+ if (vchiq_core_msg_log_level >=
-+ VCHIQ_LOG_INFO)
++ if (SRVTRACE_ENABLED(service,
++ VCHIQ_LOG_INFO))
+ vchiq_log_dump_mem("Sent", 0,
+ header->data + pos,
+ min(64u,
@@ -24495,7 +30726,7 @@ diff -Nur linux-3.12.26.orig/drivers/misc/vc04_services/interface/vchiq_arm/vchi
+ ? service->base.fourcc
+ : VCHIQ_MAKE_FOURCC('?', '?', '?', '?');
+
-+ vchiq_log_info(vchiq_core_msg_log_level,
++ vchiq_log_info(SRVTRACE_LEVEL(service),
+ "Sent Msg %s(%u) to %c%c%c%c s:%u d:%d len:%d",
+ msg_type_str(VCHIQ_MSG_TYPE(msgid)),
+ VCHIQ_MSG_TYPE(msgid),
@@ -24887,11 +31118,11 @@ diff -Nur linux-3.12.26.orig/drivers/misc/vc04_services/interface/vchiq_arm/vchi
+ vchiq_transfer_bulk(bulk);
+ mutex_unlock(&state->bulk_transfer_mutex);
+
-+ if (vchiq_core_msg_log_level >= VCHIQ_LOG_INFO) {
++ if (SRVTRACE_ENABLED(service, VCHIQ_LOG_INFO)) {
+ const char *header = (queue == &service->bulk_tx) ?
+ "Send Bulk to" : "Recv Bulk from";
+ if (bulk->actual != VCHIQ_BULK_ACTUAL_ABORTED)
-+ vchiq_log_info(vchiq_core_msg_log_level,
++ vchiq_log_info(SRVTRACE_LEVEL(service),
+ "%s %c%c%c%c d:%d len:%d %x<->%x",
+ header,
+ VCHIQ_FOURCC_AS_4CHARS(
@@ -24901,7 +31132,7 @@ diff -Nur linux-3.12.26.orig/drivers/misc/vc04_services/interface/vchiq_arm/vchi
+ (unsigned int)bulk->data,
+ (unsigned int)bulk->remote_data);
+ else
-+ vchiq_log_info(vchiq_core_msg_log_level,
++ vchiq_log_info(SRVTRACE_LEVEL(service),
+ "%s %c%c%c%c d:%d ABORTED - tx len:%d,"
+ " rx len:%d %x<->%x",
+ header,
@@ -24948,7 +31179,7 @@ diff -Nur linux-3.12.26.orig/drivers/misc/vc04_services/interface/vchiq_arm/vchi
+ if (queue->process != queue->local_insert) {
+ vchiq_complete_bulk(bulk);
+
-+ vchiq_log_info(vchiq_core_msg_log_level,
++ vchiq_log_info(SRVTRACE_LEVEL(service),
+ "%s %c%c%c%c d:%d ABORTED - tx len:%d, "
+ "rx len:%d",
+ is_tx ? "Send Bulk to" : "Recv Bulk from",
@@ -25200,9 +31431,11 @@ diff -Nur linux-3.12.26.orig/drivers/misc/vc04_services/interface/vchiq_arm/vchi
+ case VCHIQ_MSG_BULK_RX_DONE:
+ case VCHIQ_MSG_BULK_TX_DONE:
+ service = find_service_by_port(state, localport);
-+ if ((!service || service->remoteport != remoteport) &&
-+ (localport == 0) &&
-+ (type == VCHIQ_MSG_CLOSE)) {
++ if ((!service ||
++ ((service->remoteport != remoteport) &&
++ (service->remoteport != VCHIQ_PORT_FREE))) &&
++ (localport == 0) &&
++ (type == VCHIQ_MSG_CLOSE)) {
+ /* This could be a CLOSE from a client which
+ hadn't yet received the OPENACK - look for
+ the connected service */
@@ -25234,13 +31467,13 @@ diff -Nur linux-3.12.26.orig/drivers/misc/vc04_services/interface/vchiq_arm/vchi
+ break;
+ }
+
-+ if (vchiq_core_msg_log_level >= VCHIQ_LOG_INFO) {
++ if (SRVTRACE_ENABLED(service, VCHIQ_LOG_INFO)) {
+ int svc_fourcc;
+
+ svc_fourcc = service
+ ? service->base.fourcc
+ : VCHIQ_MAKE_FOURCC('?', '?', '?', '?');
-+ vchiq_log_info(vchiq_core_msg_log_level,
++ vchiq_log_info(SRVTRACE_LEVEL(service),
+ "Rcvd Msg %s(%u) from %c%c%c%c s:%d d:%d "
+ "len:%d",
+ msg_type_str(type), type,
@@ -26082,6 +32315,7 @@ diff -Nur linux-3.12.26.orig/drivers/misc/vc04_services/interface/vchiq_arm/vchi
+ service->auto_close = 1;
+ service->sync = 0;
+ service->closing = 0;
++ service->trace = 0;
+ atomic_set(&service->poll_flags, 0);
+ service->version = params->version;
+ service->version_min = params->version_min;
@@ -26210,6 +32444,7 @@ diff -Nur linux-3.12.26.orig/drivers/misc/vc04_services/interface/vchiq_arm/vchi
+ VCHIQ_MAKE_MSG(VCHIQ_MSG_OPEN, service->localport, 0),
+ &body, 1, sizeof(payload), 1);
+ if (status == VCHIQ_SUCCESS) {
++ /* Wait for the ACK/NAK */
+ if (down_interruptible(&service->remove_event) != 0) {
+ status = VCHIQ_RETRY;
+ vchiq_release_service_internal(service);
@@ -27091,6 +33326,11 @@ diff -Nur linux-3.12.26.orig/drivers/misc/vc04_services/interface/vchiq_arm/vchi
+ }
+ break;
+
++ case VCHIQ_SERVICE_OPTION_TRACE:
++ service->trace = value;
++ status = VCHIQ_SUCCESS;
++ break;
++
+ default:
+ break;
+ }
@@ -27401,10 +33641,10 @@ diff -Nur linux-3.12.26.orig/drivers/misc/vc04_services/interface/vchiq_arm/vchi
+ numBytes = 0;
+ }
+}
-diff -Nur linux-3.12.26.orig/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_core.h linux-3.12.26/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_core.h
---- linux-3.12.26.orig/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_core.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-3.12.26/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_core.h 2014-08-06 16:50:14.493962307 +0200
-@@ -0,0 +1,706 @@
+diff -Nur linux-3.12.33/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_core.h linux-3.12.33-rpi/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_core.h
+--- linux-3.12.33/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_core.h 1969-12-31 18:00:00.000000000 -0600
++++ linux-3.12.33-rpi/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_core.h 2014-12-03 19:13:38.228418001 -0600
+@@ -0,0 +1,711 @@
+/**
+ * Copyright (c) 2010-2012 Broadcom. All rights reserved.
+ *
@@ -27701,6 +33941,7 @@ diff -Nur linux-3.12.26.orig/drivers/misc/vc04_services/interface/vchiq_arm/vchi
+ char auto_close;
+ char sync;
+ char closing;
++ char trace;
+ atomic_t poll_flags;
+ short version;
+ short version_min;
@@ -28012,6 +34253,10 @@ diff -Nur linux-3.12.26.orig/drivers/misc/vc04_services/interface/vchiq_arm/vchi
+ VCHIQ_SERVICE_HANDLE_T handle);
+
+extern VCHIQ_SERVICE_T *
++find_closed_service_for_instance(VCHIQ_INSTANCE_T instance,
++ VCHIQ_SERVICE_HANDLE_T handle);
++
++extern VCHIQ_SERVICE_T *
+next_service_by_instance(VCHIQ_STATE_T *state, VCHIQ_INSTANCE_T instance,
+ int *pidx);
+
@@ -28111,9 +34356,452 @@ diff -Nur linux-3.12.26.orig/drivers/misc/vc04_services/interface/vchiq_arm/vchi
+ size_t numBytes);
+
+#endif
-diff -Nur linux-3.12.26.orig/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_genversion linux-3.12.26/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_genversion
---- linux-3.12.26.orig/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_genversion 1970-01-01 01:00:00.000000000 +0100
-+++ linux-3.12.26/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_genversion 2014-08-06 16:50:14.493962307 +0200
+diff -Nur linux-3.12.33/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_debugfs.c linux-3.12.33-rpi/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_debugfs.c
+--- linux-3.12.33/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_debugfs.c 1969-12-31 18:00:00.000000000 -0600
++++ linux-3.12.33-rpi/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_debugfs.c 2014-12-03 19:13:38.228418001 -0600
+@@ -0,0 +1,383 @@
++/**
++ * Copyright (c) 2014 Raspberry Pi (Trading) Ltd. All rights reserved.
++ * Copyright (c) 2010-2012 Broadcom. All rights reserved.
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions
++ * are met:
++ * 1. Redistributions of source code must retain the above copyright
++ * notice, this list of conditions, and the following disclaimer,
++ * without modification.
++ * 2. 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.
++ * 3. The names of the above-listed copyright holders may not be used
++ * to endorse or promote products derived from this software without
++ * specific prior written permission.
++ *
++ * ALTERNATIVELY, this software may be distributed under the terms of the
++ * GNU General Public License ("GPL") version 2, as published by the Free
++ * Software Foundation.
++ *
++ * 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 THE COPYRIGHT OWNER OR
++ * CONTRIBUTORS 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 <linux/debugfs.h>
++#include "vchiq_core.h"
++#include "vchiq_arm.h"
++#include "vchiq_debugfs.h"
++
++#ifdef CONFIG_DEBUG_FS
++
++/****************************************************************************
++*
++* log category entries
++*
++***************************************************************************/
++#define DEBUGFS_WRITE_BUF_SIZE 256
++
++#define VCHIQ_LOG_ERROR_STR "error"
++#define VCHIQ_LOG_WARNING_STR "warning"
++#define VCHIQ_LOG_INFO_STR "info"
++#define VCHIQ_LOG_TRACE_STR "trace"
++
++
++/* Top-level debug info */
++struct vchiq_debugfs_info {
++ /* Global 'vchiq' debugfs entry used by all instances */
++ struct dentry *vchiq_cfg_dir;
++
++ /* one entry per client process */
++ struct dentry *clients;
++
++ /* log categories */
++ struct dentry *log_categories;
++};
++
++static struct vchiq_debugfs_info debugfs_info;
++
++/* Log category debugfs entries */
++struct vchiq_debugfs_log_entry {
++ const char *name;
++ int *plevel;
++ struct dentry *dir;
++};
++
++static struct vchiq_debugfs_log_entry vchiq_debugfs_log_entries[] = {
++ { "core", &vchiq_core_log_level },
++ { "msg", &vchiq_core_msg_log_level },
++ { "sync", &vchiq_sync_log_level },
++ { "susp", &vchiq_susp_log_level },
++ { "arm", &vchiq_arm_log_level },
++};
++static int n_log_entries =
++ sizeof(vchiq_debugfs_log_entries)/sizeof(vchiq_debugfs_log_entries[0]);
++
++
++static struct dentry *vchiq_clients_top(void);
++static struct dentry *vchiq_debugfs_top(void);
++
++static int debugfs_log_show(struct seq_file *f, void *offset)
++{
++ int *levp = f->private;
++ char *log_value = NULL;
++
++ switch (*levp) {
++ case VCHIQ_LOG_ERROR:
++ log_value = VCHIQ_LOG_ERROR_STR;
++ break;
++ case VCHIQ_LOG_WARNING:
++ log_value = VCHIQ_LOG_WARNING_STR;
++ break;
++ case VCHIQ_LOG_INFO:
++ log_value = VCHIQ_LOG_INFO_STR;
++ break;
++ case VCHIQ_LOG_TRACE:
++ log_value = VCHIQ_LOG_TRACE_STR;
++ break;
++ default:
++ break;
++ }
++
++ seq_printf(f, "%s\n", log_value ? log_value : "(null)");
++
++ return 0;
++}
++
++static int debugfs_log_open(struct inode *inode, struct file *file)
++{
++ return single_open(file, debugfs_log_show, inode->i_private);
++}
++
++static int debugfs_log_write(struct file *file,
++ const char __user *buffer,
++ size_t count, loff_t *ppos)
++{
++ struct seq_file *f = (struct seq_file *)file->private_data;
++ int *levp = f->private;
++ char kbuf[DEBUGFS_WRITE_BUF_SIZE + 1];
++
++ memset(kbuf, 0, DEBUGFS_WRITE_BUF_SIZE + 1);
++ if (count >= DEBUGFS_WRITE_BUF_SIZE)
++ count = DEBUGFS_WRITE_BUF_SIZE;
++
++ if (copy_from_user(kbuf, buffer, count) != 0)
++ return -EFAULT;
++ kbuf[count - 1] = 0;
++
++ if (strncmp("error", kbuf, strlen("error")) == 0)
++ *levp = VCHIQ_LOG_ERROR;
++ else if (strncmp("warning", kbuf, strlen("warning")) == 0)
++ *levp = VCHIQ_LOG_WARNING;
++ else if (strncmp("info", kbuf, strlen("info")) == 0)
++ *levp = VCHIQ_LOG_INFO;
++ else if (strncmp("trace", kbuf, strlen("trace")) == 0)
++ *levp = VCHIQ_LOG_TRACE;
++ else
++ *levp = VCHIQ_LOG_DEFAULT;
++
++ *ppos += count;
++
++ return count;
++}
++
++static const struct file_operations debugfs_log_fops = {
++ .owner = THIS_MODULE,
++ .open = debugfs_log_open,
++ .write = debugfs_log_write,
++ .read = seq_read,
++ .llseek = seq_lseek,
++ .release = single_release,
++};
++
++/* create an entry under <debugfs>/vchiq/log for each log category */
++static int vchiq_debugfs_create_log_entries(struct dentry *top)
++{
++ struct dentry *dir;
++ size_t i;
++ int ret = 0;
++ dir = debugfs_create_dir("log", vchiq_debugfs_top());
++ if (!dir)
++ return -ENOMEM;
++ debugfs_info.log_categories = dir;
++
++ for (i = 0; i < n_log_entries; i++) {
++ void *levp = (void *)vchiq_debugfs_log_entries[i].plevel;
++ dir = debugfs_create_file(vchiq_debugfs_log_entries[i].name,
++ 0644,
++ debugfs_info.log_categories,
++ levp,
++ &debugfs_log_fops);
++ if (!dir) {
++ ret = -ENOMEM;
++ break;
++ }
++
++ vchiq_debugfs_log_entries[i].dir = dir;
++ }
++ return ret;
++}
++
++static int debugfs_usecount_show(struct seq_file *f, void *offset)
++{
++ VCHIQ_INSTANCE_T instance = f->private;
++ int use_count;
++
++ use_count = vchiq_instance_get_use_count(instance);
++ seq_printf(f, "%d\n", use_count);
++
++ return 0;
++}
++
++static int debugfs_usecount_open(struct inode *inode, struct file *file)
++{
++ return single_open(file, debugfs_usecount_show, inode->i_private);
++}
++
++static const struct file_operations debugfs_usecount_fops = {
++ .owner = THIS_MODULE,
++ .open = debugfs_usecount_open,
++ .read = seq_read,
++ .llseek = seq_lseek,
++ .release = single_release,
++};
++
++static int debugfs_trace_show(struct seq_file *f, void *offset)
++{
++ VCHIQ_INSTANCE_T instance = f->private;
++ int trace;
++
++ trace = vchiq_instance_get_trace(instance);
++ seq_printf(f, "%s\n", trace ? "Y" : "N");
++
++ return 0;
++}
++
++static int debugfs_trace_open(struct inode *inode, struct file *file)
++{
++ return single_open(file, debugfs_trace_show, inode->i_private);
++}
++
++static int debugfs_trace_write(struct file *file,
++ const char __user *buffer,
++ size_t count, loff_t *ppos)
++{
++ struct seq_file *f = (struct seq_file *)file->private_data;
++ VCHIQ_INSTANCE_T instance = f->private;
++ char firstchar;
++
++ if (copy_from_user(&firstchar, buffer, 1) != 0)
++ return -EFAULT;
++
++ switch (firstchar) {
++ case 'Y':
++ case 'y':
++ case '1':
++ vchiq_instance_set_trace(instance, 1);
++ break;
++ case 'N':
++ case 'n':
++ case '0':
++ vchiq_instance_set_trace(instance, 0);
++ break;
++ default:
++ break;
++ }
++
++ *ppos += count;
++
++ return count;
++}
++
++static const struct file_operations debugfs_trace_fops = {
++ .owner = THIS_MODULE,
++ .open = debugfs_trace_open,
++ .write = debugfs_trace_write,
++ .read = seq_read,
++ .llseek = seq_lseek,
++ .release = single_release,
++};
++
++/* add an instance (process) to the debugfs entries */
++int vchiq_debugfs_add_instance(VCHIQ_INSTANCE_T instance)
++{
++ char pidstr[16];
++ struct dentry *top, *use_count, *trace;
++ struct dentry *clients = vchiq_clients_top();
++
++ snprintf(pidstr, sizeof(pidstr), "%d",
++ vchiq_instance_get_pid(instance));
++
++ top = debugfs_create_dir(pidstr, clients);
++ if (!top)
++ goto fail_top;
++
++ use_count = debugfs_create_file("use_count",
++ 0444, top,
++ instance,
++ &debugfs_usecount_fops);
++ if (!use_count)
++ goto fail_use_count;
++
++ trace = debugfs_create_file("trace",
++ 0644, top,
++ instance,
++ &debugfs_trace_fops);
++ if (!trace)
++ goto fail_trace;
++
++ vchiq_instance_get_debugfs_node(instance)->dentry = top;
++
++ return 0;
++
++fail_trace:
++ debugfs_remove(use_count);
++fail_use_count:
++ debugfs_remove(top);
++fail_top:
++ return -ENOMEM;
++}
++
++void vchiq_debugfs_remove_instance(VCHIQ_INSTANCE_T instance)
++{
++ VCHIQ_DEBUGFS_NODE_T *node = vchiq_instance_get_debugfs_node(instance);
++ debugfs_remove_recursive(node->dentry);
++}
++
++
++int vchiq_debugfs_init(void)
++{
++ BUG_ON(debugfs_info.vchiq_cfg_dir != NULL);
++
++ debugfs_info.vchiq_cfg_dir = debugfs_create_dir("vchiq", NULL);
++ if (debugfs_info.vchiq_cfg_dir == NULL)
++ goto fail;
++
++ debugfs_info.clients = debugfs_create_dir("clients",
++ vchiq_debugfs_top());
++ if (!debugfs_info.clients)
++ goto fail;
++
++ if (vchiq_debugfs_create_log_entries(vchiq_debugfs_top()) != 0)
++ goto fail;
++
++ return 0;
++
++fail:
++ vchiq_debugfs_deinit();
++ vchiq_log_error(vchiq_arm_log_level,
++ "%s: failed to create debugfs directory",
++ __func__);
++
++ return -ENOMEM;
++}
++
++/* remove all the debugfs entries */
++void vchiq_debugfs_deinit(void)
++{
++ debugfs_remove_recursive(vchiq_debugfs_top());
++}
++
++static struct dentry *vchiq_clients_top(void)
++{
++ return debugfs_info.clients;
++}
++
++static struct dentry *vchiq_debugfs_top(void)
++{
++ BUG_ON(debugfs_info.vchiq_cfg_dir == NULL);
++ return debugfs_info.vchiq_cfg_dir;
++}
++
++#else /* CONFIG_DEBUG_FS */
++
++int vchiq_debugfs_init(void)
++{
++ return 0;
++}
++
++void vchiq_debugfs_deinit(void)
++{
++}
++
++int vchiq_debugfs_add_instance(VCHIQ_INSTANCE_T instance)
++{
++ return 0;
++}
++
++void vchiq_debugfs_remove_instance(VCHIQ_INSTANCE_T instance)
++{
++}
++
++#endif /* CONFIG_DEBUG_FS */
+diff -Nur linux-3.12.33/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_debugfs.h linux-3.12.33-rpi/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_debugfs.h
+--- linux-3.12.33/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_debugfs.h 1969-12-31 18:00:00.000000000 -0600
++++ linux-3.12.33-rpi/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_debugfs.h 2014-12-03 19:13:38.228418001 -0600
+@@ -0,0 +1,52 @@
++/**
++ * Copyright (c) 2014 Raspberry Pi (Trading) Ltd. All rights reserved.
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions
++ * are met:
++ * 1. Redistributions of source code must retain the above copyright
++ * notice, this list of conditions, and the following disclaimer,
++ * without modification.
++ * 2. 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.
++ * 3. The names of the above-listed copyright holders may not be used
++ * to endorse or promote products derived from this software without
++ * specific prior written permission.
++ *
++ * ALTERNATIVELY, this software may be distributed under the terms of the
++ * GNU General Public License ("GPL") version 2, as published by the Free
++ * Software Foundation.
++ *
++ * 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 THE COPYRIGHT OWNER OR
++ * CONTRIBUTORS 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.
++ */
++
++#ifndef VCHIQ_DEBUGFS_H
++#define VCHIQ_DEBUGFS_H
++
++#include "vchiq_core.h"
++
++typedef struct vchiq_debugfs_node_struct
++{
++ struct dentry *dentry;
++} VCHIQ_DEBUGFS_NODE_T;
++
++int vchiq_debugfs_init(void);
++
++void vchiq_debugfs_deinit(void);
++
++int vchiq_debugfs_add_instance(VCHIQ_INSTANCE_T instance);
++
++void vchiq_debugfs_remove_instance(VCHIQ_INSTANCE_T instance);
++
++#endif /* VCHIQ_DEBUGFS_H */
+diff -Nur linux-3.12.33/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_genversion linux-3.12.33-rpi/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_genversion
+--- linux-3.12.33/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_genversion 1969-12-31 18:00:00.000000000 -0600
++++ linux-3.12.33-rpi/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_genversion 2014-12-03 19:13:38.228418001 -0600
@@ -0,0 +1,87 @@
+#!/usr/bin/perl -w
+
@@ -28202,9 +34890,9 @@ diff -Nur linux-3.12.26.orig/drivers/misc/vc04_services/interface/vchiq_arm/vchi
+ return vchiq_build_time;
+}
+EOF
-diff -Nur linux-3.12.26.orig/drivers/misc/vc04_services/interface/vchiq_arm/vchiq.h linux-3.12.26/drivers/misc/vc04_services/interface/vchiq_arm/vchiq.h
---- linux-3.12.26.orig/drivers/misc/vc04_services/interface/vchiq_arm/vchiq.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-3.12.26/drivers/misc/vc04_services/interface/vchiq_arm/vchiq.h 2014-08-06 16:50:14.493962307 +0200
+diff -Nur linux-3.12.33/drivers/misc/vc04_services/interface/vchiq_arm/vchiq.h linux-3.12.33-rpi/drivers/misc/vc04_services/interface/vchiq_arm/vchiq.h
+--- linux-3.12.33/drivers/misc/vc04_services/interface/vchiq_arm/vchiq.h 1969-12-31 18:00:00.000000000 -0600
++++ linux-3.12.33-rpi/drivers/misc/vc04_services/interface/vchiq_arm/vchiq.h 2014-12-03 19:13:38.224418001 -0600
@@ -0,0 +1,40 @@
+/**
+ * Copyright (c) 2010-2012 Broadcom. All rights reserved.
@@ -28246,10 +34934,10 @@ diff -Nur linux-3.12.26.orig/drivers/misc/vc04_services/interface/vchiq_arm/vchi
+#include "vchiq_util.h"
+
+#endif
-diff -Nur linux-3.12.26.orig/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_if.h linux-3.12.26/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_if.h
---- linux-3.12.26.orig/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_if.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-3.12.26/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_if.h 2014-08-06 16:50:14.493962307 +0200
-@@ -0,0 +1,188 @@
+diff -Nur linux-3.12.33/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_if.h linux-3.12.33-rpi/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_if.h
+--- linux-3.12.33/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_if.h 1969-12-31 18:00:00.000000000 -0600
++++ linux-3.12.33-rpi/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_if.h 2014-12-03 19:13:38.228418001 -0600
+@@ -0,0 +1,189 @@
+/**
+ * Copyright (c) 2010-2012 Broadcom. All rights reserved.
+ *
@@ -28326,7 +35014,8 @@ diff -Nur linux-3.12.26.orig/drivers/misc/vc04_services/interface/vchiq_arm/vchi
+ VCHIQ_SERVICE_OPTION_AUTOCLOSE,
+ VCHIQ_SERVICE_OPTION_SLOT_QUOTA,
+ VCHIQ_SERVICE_OPTION_MESSAGE_QUOTA,
-+ VCHIQ_SERVICE_OPTION_SYNCHRONOUS
++ VCHIQ_SERVICE_OPTION_SYNCHRONOUS,
++ VCHIQ_SERVICE_OPTION_TRACE
+} VCHIQ_SERVICE_OPTION_T;
+
+typedef struct vchiq_header_struct {
@@ -28438,10 +35127,10 @@ diff -Nur linux-3.12.26.orig/drivers/misc/vc04_services/interface/vchiq_arm/vchi
+ short *peer_version);
+
+#endif /* VCHIQ_IF_H */
-diff -Nur linux-3.12.26.orig/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_ioctl.h linux-3.12.26/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_ioctl.h
---- linux-3.12.26.orig/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_ioctl.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-3.12.26/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_ioctl.h 2014-08-06 16:50:14.493962307 +0200
-@@ -0,0 +1,129 @@
+diff -Nur linux-3.12.33/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_ioctl.h linux-3.12.33-rpi/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_ioctl.h
+--- linux-3.12.33/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_ioctl.h 1969-12-31 18:00:00.000000000 -0600
++++ linux-3.12.33-rpi/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_ioctl.h 2014-12-03 19:13:38.228418001 -0600
+@@ -0,0 +1,131 @@
+/**
+ * Copyright (c) 2010-2012 Broadcom. All rights reserved.
+ *
@@ -28568,13 +35257,15 @@ diff -Nur linux-3.12.26.orig/drivers/misc/vc04_services/interface/vchiq_arm/vchi
+ _IOW(VCHIQ_IOC_MAGIC, 14, VCHIQ_SET_SERVICE_OPTION_T)
+#define VCHIQ_IOC_DUMP_PHYS_MEM \
+ _IOW(VCHIQ_IOC_MAGIC, 15, VCHIQ_DUMP_MEM_T)
-+#define VCHIQ_IOC_MAX 15
++#define VCHIQ_IOC_LIB_VERSION _IO(VCHIQ_IOC_MAGIC, 16)
++#define VCHIQ_IOC_CLOSE_DELIVERED _IO(VCHIQ_IOC_MAGIC, 17)
++#define VCHIQ_IOC_MAX 17
+
+#endif
-diff -Nur linux-3.12.26.orig/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_kern_lib.c linux-3.12.26/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_kern_lib.c
---- linux-3.12.26.orig/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_kern_lib.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-3.12.26/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_kern_lib.c 2014-08-06 16:50:14.493962307 +0200
-@@ -0,0 +1,456 @@
+diff -Nur linux-3.12.33/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_kern_lib.c linux-3.12.33-rpi/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_kern_lib.c
+--- linux-3.12.33/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_kern_lib.c 1969-12-31 18:00:00.000000000 -0600
++++ linux-3.12.33-rpi/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_kern_lib.c 2014-12-03 19:13:38.228418001 -0600
+@@ -0,0 +1,458 @@
+/**
+ * Copyright (c) 2010-2012 Broadcom. All rights reserved.
+ *
@@ -28616,6 +35307,7 @@ diff -Nur linux-3.12.26.orig/drivers/misc/vc04_services/interface/vchiq_arm/vchi
+
+#include "vchiq_core.h"
+#include "vchiq_arm.h"
++#include "vchiq_killable.h"
+
+/* ---- Public Variables ------------------------------------------------- */
+
@@ -28864,11 +35556,12 @@ diff -Nur linux-3.12.26.orig/drivers/misc/vc04_services/interface/vchiq_arm/vchi
+ NULL);
+
+ if (service) {
++ *phandle = service->handle;
+ status = vchiq_open_service_internal(service, current->pid);
-+ if (status == VCHIQ_SUCCESS)
-+ *phandle = service->handle;
-+ else
++ if (status != VCHIQ_SUCCESS) {
+ vchiq_remove_service(service->handle);
++ *phandle = VCHIQ_SERVICE_HANDLE_INVALID;
++ }
+ }
+
+failed:
@@ -29031,9 +35724,82 @@ diff -Nur linux-3.12.26.orig/drivers/misc/vc04_services/interface/vchiq_arm/vchi
+
+ return status;
+}
-diff -Nur linux-3.12.26.orig/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_memdrv.h linux-3.12.26/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_memdrv.h
---- linux-3.12.26.orig/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_memdrv.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-3.12.26/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_memdrv.h 2014-08-06 16:50:14.493962307 +0200
+diff -Nur linux-3.12.33/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_killable.h linux-3.12.33-rpi/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_killable.h
+--- linux-3.12.33/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_killable.h 1969-12-31 18:00:00.000000000 -0600
++++ linux-3.12.33-rpi/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_killable.h 2014-12-03 19:13:38.228418001 -0600
+@@ -0,0 +1,69 @@
++/**
++ * Copyright (c) 2010-2012 Broadcom. All rights reserved.
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions
++ * are met:
++ * 1. Redistributions of source code must retain the above copyright
++ * notice, this list of conditions, and the following disclaimer,
++ * without modification.
++ * 2. 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.
++ * 3. The names of the above-listed copyright holders may not be used
++ * to endorse or promote products derived from this software without
++ * specific prior written permission.
++ *
++ * ALTERNATIVELY, this software may be distributed under the terms of the
++ * GNU General Public License ("GPL") version 2, as published by the Free
++ * Software Foundation.
++ *
++ * 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 THE COPYRIGHT OWNER OR
++ * CONTRIBUTORS 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.
++ */
++
++#ifndef VCHIQ_KILLABLE_H
++#define VCHIQ_KILLABLE_H
++
++#include <linux/mutex.h>
++#include <linux/semaphore.h>
++
++#define SHUTDOWN_SIGS (sigmask(SIGKILL) | sigmask(SIGINT) | sigmask(SIGQUIT) | sigmask(SIGTRAP) | sigmask(SIGSTOP) | sigmask(SIGCONT))
++
++static inline int __must_check down_interruptible_killable(struct semaphore *sem)
++{
++ /* Allow interception of killable signals only. We don't want to be interrupted by harmless signals like SIGALRM */
++ int ret;
++ sigset_t blocked, oldset;
++ siginitsetinv(&blocked, SHUTDOWN_SIGS);
++ sigprocmask(SIG_SETMASK, &blocked, &oldset);
++ ret = down_interruptible(sem);
++ sigprocmask(SIG_SETMASK, &oldset, NULL);
++ return ret;
++}
++#define down_interruptible down_interruptible_killable
++
++
++static inline int __must_check mutex_lock_interruptible_killable(struct mutex *lock)
++{
++ /* Allow interception of killable signals only. We don't want to be interrupted by harmless signals like SIGALRM */
++ int ret;
++ sigset_t blocked, oldset;
++ siginitsetinv(&blocked, SHUTDOWN_SIGS);
++ sigprocmask(SIG_SETMASK, &blocked, &oldset);
++ ret = mutex_lock_interruptible(lock);
++ sigprocmask(SIG_SETMASK, &oldset, NULL);
++ return ret;
++}
++#define mutex_lock_interruptible mutex_lock_interruptible_killable
++
++#endif
+diff -Nur linux-3.12.33/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_memdrv.h linux-3.12.33-rpi/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_memdrv.h
+--- linux-3.12.33/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_memdrv.h 1969-12-31 18:00:00.000000000 -0600
++++ linux-3.12.33-rpi/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_memdrv.h 2014-12-03 19:13:38.228418001 -0600
@@ -0,0 +1,71 @@
+/**
+ * Copyright (c) 2010-2012 Broadcom. All rights reserved.
@@ -29106,9 +35872,9 @@ diff -Nur linux-3.12.26.orig/drivers/misc/vc04_services/interface/vchiq_arm/vchi
+ const VCHIQ_PLATFORM_DATA_T * platform_data);
+
+#endif
-diff -Nur linux-3.12.26.orig/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_pagelist.h linux-3.12.26/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_pagelist.h
---- linux-3.12.26.orig/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_pagelist.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-3.12.26/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_pagelist.h 2014-08-06 16:50:14.497962339 +0200
+diff -Nur linux-3.12.33/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_pagelist.h linux-3.12.33-rpi/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_pagelist.h
+--- linux-3.12.33/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_pagelist.h 1969-12-31 18:00:00.000000000 -0600
++++ linux-3.12.33-rpi/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_pagelist.h 2014-12-03 19:13:38.228418001 -0600
@@ -0,0 +1,58 @@
+/**
+ * Copyright (c) 2010-2012 Broadcom. All rights reserved.
@@ -29168,267 +35934,10 @@ diff -Nur linux-3.12.26.orig/drivers/misc/vc04_services/interface/vchiq_arm/vchi
+} FRAGMENTS_T;
+
+#endif /* VCHIQ_PAGELIST_H */
-diff -Nur linux-3.12.26.orig/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_proc.c linux-3.12.26/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_proc.c
---- linux-3.12.26.orig/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_proc.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-3.12.26/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_proc.c 2014-08-06 16:50:14.497962339 +0200
-@@ -0,0 +1,253 @@
-+/**
-+ * Copyright (c) 2010-2012 Broadcom. All rights reserved.
-+ *
-+ * Redistribution and use in source and binary forms, with or without
-+ * modification, are permitted provided that the following conditions
-+ * are met:
-+ * 1. Redistributions of source code must retain the above copyright
-+ * notice, this list of conditions, and the following disclaimer,
-+ * without modification.
-+ * 2. 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.
-+ * 3. The names of the above-listed copyright holders may not be used
-+ * to endorse or promote products derived from this software without
-+ * specific prior written permission.
-+ *
-+ * ALTERNATIVELY, this software may be distributed under the terms of the
-+ * GNU General Public License ("GPL") version 2, as published by the Free
-+ * Software Foundation.
-+ *
-+ * 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 THE COPYRIGHT OWNER OR
-+ * CONTRIBUTORS 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 <linux/proc_fs.h>
-+#include "vchiq_core.h"
-+#include "vchiq_arm.h"
-+
-+#if 1
-+
-+int vchiq_proc_init(void)
-+{
-+ return 0;
-+}
-+
-+void vchiq_proc_deinit(void)
-+{
-+}
-+
-+#else
-+
-+struct vchiq_proc_info {
-+ /* Global 'vc' proc entry used by all instances */
-+ struct proc_dir_entry *vc_cfg_dir;
-+
-+ /* one entry per client process */
-+ struct proc_dir_entry *clients;
-+
-+ /* log categories */
-+ struct proc_dir_entry *log_categories;
-+};
-+
-+static struct vchiq_proc_info proc_info;
-+
-+struct proc_dir_entry *vchiq_proc_top(void)
-+{
-+ BUG_ON(proc_info.vc_cfg_dir == NULL);
-+ return proc_info.vc_cfg_dir;
-+}
-+
-+/****************************************************************************
-+*
-+* log category entries
-+*
-+***************************************************************************/
-+#define PROC_WRITE_BUF_SIZE 256
-+
-+#define VCHIQ_LOG_ERROR_STR "error"
-+#define VCHIQ_LOG_WARNING_STR "warning"
-+#define VCHIQ_LOG_INFO_STR "info"
-+#define VCHIQ_LOG_TRACE_STR "trace"
-+
-+static int log_cfg_read(char *buffer,
-+ char **start,
-+ off_t off,
-+ int count,
-+ int *eof,
-+ void *data)
-+{
-+ int len = 0;
-+ char *log_value = NULL;
-+
-+ switch (*((int *)data)) {
-+ case VCHIQ_LOG_ERROR:
-+ log_value = VCHIQ_LOG_ERROR_STR;
-+ break;
-+ case VCHIQ_LOG_WARNING:
-+ log_value = VCHIQ_LOG_WARNING_STR;
-+ break;
-+ case VCHIQ_LOG_INFO:
-+ log_value = VCHIQ_LOG_INFO_STR;
-+ break;
-+ case VCHIQ_LOG_TRACE:
-+ log_value = VCHIQ_LOG_TRACE_STR;
-+ break;
-+ default:
-+ break;
-+ }
-+
-+ len += sprintf(buffer + len,
-+ "%s\n",
-+ log_value ? log_value : "(null)");
-+
-+ return len;
-+}
-+
-+
-+static int log_cfg_write(struct file *file,
-+ const char __user *buffer,
-+ unsigned long count,
-+ void *data)
-+{
-+ int *log_module = data;
-+ char kbuf[PROC_WRITE_BUF_SIZE + 1];
-+
-+ (void)file;
-+
-+ memset(kbuf, 0, PROC_WRITE_BUF_SIZE + 1);
-+ if (count >= PROC_WRITE_BUF_SIZE)
-+ count = PROC_WRITE_BUF_SIZE;
-+
-+ if (copy_from_user(kbuf,
-+ buffer,
-+ count) != 0)
-+ return -EFAULT;
-+ kbuf[count - 1] = 0;
-+
-+ if (strncmp("error", kbuf, strlen("error")) == 0)
-+ *log_module = VCHIQ_LOG_ERROR;
-+ else if (strncmp("warning", kbuf, strlen("warning")) == 0)
-+ *log_module = VCHIQ_LOG_WARNING;
-+ else if (strncmp("info", kbuf, strlen("info")) == 0)
-+ *log_module = VCHIQ_LOG_INFO;
-+ else if (strncmp("trace", kbuf, strlen("trace")) == 0)
-+ *log_module = VCHIQ_LOG_TRACE;
-+ else
-+ *log_module = VCHIQ_LOG_DEFAULT;
-+
-+ return count;
-+}
-+
-+/* Log category proc entries */
-+struct vchiq_proc_log_entry {
-+ const char *name;
-+ int *plevel;
-+ struct proc_dir_entry *dir;
-+};
-+
-+static struct vchiq_proc_log_entry vchiq_proc_log_entries[] = {
-+ { "core", &vchiq_core_log_level },
-+ { "msg", &vchiq_core_msg_log_level },
-+ { "sync", &vchiq_sync_log_level },
-+ { "susp", &vchiq_susp_log_level },
-+ { "arm", &vchiq_arm_log_level },
-+};
-+static int n_log_entries =
-+ sizeof(vchiq_proc_log_entries)/sizeof(vchiq_proc_log_entries[0]);
-+
-+/* create an entry under /proc/vc/log for each log category */
-+static int vchiq_proc_create_log_entries(struct proc_dir_entry *top)
-+{
-+ struct proc_dir_entry *dir;
-+ size_t i;
-+ int ret = 0;
-+ dir = proc_mkdir("log", proc_info.vc_cfg_dir);
-+ if (!dir)
-+ return -ENOMEM;
-+ proc_info.log_categories = dir;
-+
-+ for (i = 0; i < n_log_entries; i++) {
-+ dir = create_proc_entry(vchiq_proc_log_entries[i].name,
-+ 0644,
-+ proc_info.log_categories);
-+ if (!dir) {
-+ ret = -ENOMEM;
-+ break;
-+ }
-+
-+ dir->read_proc = &log_cfg_read;
-+ dir->write_proc = &log_cfg_write;
-+ dir->data = (void *)vchiq_proc_log_entries[i].plevel;
-+
-+ vchiq_proc_log_entries[i].dir = dir;
-+ }
-+ return ret;
-+}
-+
-+
-+int vchiq_proc_init(void)
-+{
-+ BUG_ON(proc_info.vc_cfg_dir != NULL);
-+
-+ proc_info.vc_cfg_dir = proc_mkdir("vc", NULL);
-+ if (proc_info.vc_cfg_dir == NULL)
-+ goto fail;
-+
-+ proc_info.clients = proc_mkdir("clients",
-+ proc_info.vc_cfg_dir);
-+ if (!proc_info.clients)
-+ goto fail;
-+
-+ if (vchiq_proc_create_log_entries(proc_info.vc_cfg_dir) != 0)
-+ goto fail;
-+
-+ return 0;
-+
-+fail:
-+ vchiq_proc_deinit();
-+ vchiq_log_error(vchiq_arm_log_level,
-+ "%s: failed to create proc directory",
-+ __func__);
-+
-+ return -ENOMEM;
-+}
-+
-+/* remove all the proc entries */
-+void vchiq_proc_deinit(void)
-+{
-+ /* log category entries */
-+ if (proc_info.log_categories) {
-+ size_t i;
-+ for (i = 0; i < n_log_entries; i++)
-+ if (vchiq_proc_log_entries[i].dir)
-+ remove_proc_entry(
-+ vchiq_proc_log_entries[i].name,
-+ proc_info.log_categories);
-+
-+ remove_proc_entry(proc_info.log_categories->name,
-+ proc_info.vc_cfg_dir);
-+ }
-+ if (proc_info.clients)
-+ remove_proc_entry(proc_info.clients->name,
-+ proc_info.vc_cfg_dir);
-+ if (proc_info.vc_cfg_dir)
-+ remove_proc_entry(proc_info.vc_cfg_dir->name, NULL);
-+}
-+
-+struct proc_dir_entry *vchiq_clients_top(void)
-+{
-+ return proc_info.clients;
-+}
-+
-+#endif
-diff -Nur linux-3.12.26.orig/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_shim.c linux-3.12.26/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_shim.c
---- linux-3.12.26.orig/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_shim.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-3.12.26/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_shim.c 2014-08-06 16:50:14.497962339 +0200
-@@ -0,0 +1,828 @@
+diff -Nur linux-3.12.33/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_shim.c linux-3.12.33-rpi/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_shim.c
+--- linux-3.12.33/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_shim.c 1969-12-31 18:00:00.000000000 -0600
++++ linux-3.12.33-rpi/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_shim.c 2014-12-03 19:13:38.228418001 -0600
+@@ -0,0 +1,857 @@
+/**
+ * Copyright (c) 2010-2012 Broadcom. All rights reserved.
+ *
@@ -29888,8 +36397,6 @@ diff -Nur linux-3.12.26.orig/drivers/misc/vc04_services/interface/vchiq_arm/vchi
+ * Name: vchi_initialise
+ *
+ * Arguments: VCHI_INSTANCE_T *instance_handle
-+ * VCHI_CONNECTION_T **connections
-+ * const uint32_t num_connections
+ *
+ * Description: Initialises the hardware but does not transmit anything
+ * When run as a Host App this will be called twice hence the need
@@ -30067,6 +36574,9 @@ diff -Nur linux-3.12.26.orig/drivers/misc/vc04_services/interface/vchiq_arm/vchi
+{
+ VCHIQ_INSTANCE_T instance = (VCHIQ_INSTANCE_T)instance_handle;
+ SHIM_SERVICE_T *service = service_alloc(instance, setup);
++
++ *handle = (VCHI_SERVICE_HANDLE_T)service;
++
+ if (service) {
+ VCHIQ_SERVICE_PARAMS_T params;
+ VCHIQ_STATUS_T status;
@@ -30083,11 +36593,10 @@ diff -Nur linux-3.12.26.orig/drivers/misc/vc04_services/interface/vchiq_arm/vchi
+ if (status != VCHIQ_SUCCESS) {
+ service_free(service);
+ service = NULL;
++ *handle = NULL;
+ }
+ }
+
-+ *handle = (VCHI_SERVICE_HANDLE_T)service;
-+
+ return (service != NULL) ? 0 : -1;
+}
+EXPORT_SYMBOL(vchi_service_open);
@@ -30098,6 +36607,9 @@ diff -Nur linux-3.12.26.orig/drivers/misc/vc04_services/interface/vchiq_arm/vchi
+{
+ VCHIQ_INSTANCE_T instance = (VCHIQ_INSTANCE_T)instance_handle;
+ SHIM_SERVICE_T *service = service_alloc(instance, setup);
++
++ *handle = (VCHI_SERVICE_HANDLE_T)service;
++
+ if (service) {
+ VCHIQ_SERVICE_PARAMS_T params;
+ VCHIQ_STATUS_T status;
@@ -30113,11 +36625,10 @@ diff -Nur linux-3.12.26.orig/drivers/misc/vc04_services/interface/vchiq_arm/vchi
+ if (status != VCHIQ_SUCCESS) {
+ service_free(service);
+ service = NULL;
++ *handle = NULL;
+ }
+ }
+
-+ *handle = (VCHI_SERVICE_HANDLE_T)service;
-+
+ return (service != NULL) ? 0 : -1;
+}
+EXPORT_SYMBOL(vchi_service_create);
@@ -30156,6 +36667,33 @@ diff -Nur linux-3.12.26.orig/drivers/misc/vc04_services/interface/vchiq_arm/vchi
+}
+EXPORT_SYMBOL(vchi_service_destroy);
+
++int32_t vchi_service_set_option(const VCHI_SERVICE_HANDLE_T handle,
++ VCHI_SERVICE_OPTION_T option,
++ int value)
++{
++ int32_t ret = -1;
++ SHIM_SERVICE_T *service = (SHIM_SERVICE_T *)handle;
++ VCHIQ_SERVICE_OPTION_T vchiq_option;
++ switch (option) {
++ case VCHI_SERVICE_OPTION_TRACE:
++ vchiq_option = VCHIQ_SERVICE_OPTION_TRACE;
++ break;
++ default:
++ service = NULL;
++ break;
++ }
++ if (service) {
++ VCHIQ_STATUS_T status =
++ vchiq_set_service_option(service->handle,
++ vchiq_option,
++ value);
++
++ ret = vchiq_status_to_vchi(status);
++ }
++ return ret;
++}
++EXPORT_SYMBOL(vchi_service_set_option);
++
+int32_t vchi_get_peer_version( const VCHI_SERVICE_HANDLE_T handle, short *peer_version )
+{
+ int32_t ret = -1;
@@ -30257,10 +36795,10 @@ diff -Nur linux-3.12.26.orig/drivers/misc/vc04_services/interface/vchiq_arm/vchi
+ return ret;
+}
+EXPORT_SYMBOL(vchi_service_release);
-diff -Nur linux-3.12.26.orig/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_util.c linux-3.12.26/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_util.c
---- linux-3.12.26.orig/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_util.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-3.12.26/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_util.c 2014-08-06 16:50:14.497962339 +0200
-@@ -0,0 +1,151 @@
+diff -Nur linux-3.12.33/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_util.c linux-3.12.33-rpi/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_util.c
+--- linux-3.12.33/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_util.c 1969-12-31 18:00:00.000000000 -0600
++++ linux-3.12.33-rpi/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_util.c 2014-12-03 19:13:38.228418001 -0600
+@@ -0,0 +1,152 @@
+/**
+ * Copyright (c) 2010-2012 Broadcom. All rights reserved.
+ *
@@ -30295,6 +36833,7 @@ diff -Nur linux-3.12.26.orig/drivers/misc/vc04_services/interface/vchiq_arm/vchi
+ */
+
+#include "vchiq_util.h"
++#include "vchiq_killable.h"
+
+static inline int is_pow2(int i)
+{
@@ -30412,9 +36951,9 @@ diff -Nur linux-3.12.26.orig/drivers/misc/vc04_services/interface/vchiq_arm/vchi
+
+ return header;
+}
-diff -Nur linux-3.12.26.orig/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_util.h linux-3.12.26/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_util.h
---- linux-3.12.26.orig/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_util.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-3.12.26/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_util.h 2014-08-06 16:50:14.497962339 +0200
+diff -Nur linux-3.12.33/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_util.h linux-3.12.33-rpi/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_util.h
+--- linux-3.12.33/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_util.h 1969-12-31 18:00:00.000000000 -0600
++++ linux-3.12.33-rpi/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_util.h 2014-12-03 19:13:38.228418001 -0600
@@ -0,0 +1,81 @@
+/**
+ * Copyright (c) 2010-2012 Broadcom. All rights reserved.
@@ -30497,9 +37036,9 @@ diff -Nur linux-3.12.26.orig/drivers/misc/vc04_services/interface/vchiq_arm/vchi
+extern VCHIQ_HEADER_T *vchiu_queue_pop(VCHIU_QUEUE_T *queue);
+
+#endif
-diff -Nur linux-3.12.26.orig/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_version.c linux-3.12.26/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_version.c
---- linux-3.12.26.orig/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_version.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-3.12.26/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_version.c 2014-08-06 16:50:14.497962339 +0200
+diff -Nur linux-3.12.33/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_version.c linux-3.12.33-rpi/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_version.c
+--- linux-3.12.33/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_version.c 1969-12-31 18:00:00.000000000 -0600
++++ linux-3.12.33-rpi/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_version.c 2014-12-03 19:13:38.228418001 -0600
@@ -0,0 +1,59 @@
+/**
+ * Copyright (c) 2010-2012 Broadcom. All rights reserved.
@@ -30560,9 +37099,9 @@ diff -Nur linux-3.12.26.orig/drivers/misc/vc04_services/interface/vchiq_arm/vchi
+{
+ return vchiq_build_time;
+}
-diff -Nur linux-3.12.26.orig/drivers/misc/vc04_services/Kconfig linux-3.12.26/drivers/misc/vc04_services/Kconfig
---- linux-3.12.26.orig/drivers/misc/vc04_services/Kconfig 1970-01-01 01:00:00.000000000 +0100
-+++ linux-3.12.26/drivers/misc/vc04_services/Kconfig 2014-08-06 16:50:14.497962339 +0200
+diff -Nur linux-3.12.33/drivers/misc/vc04_services/Kconfig linux-3.12.33-rpi/drivers/misc/vc04_services/Kconfig
+--- linux-3.12.33/drivers/misc/vc04_services/Kconfig 1969-12-31 18:00:00.000000000 -0600
++++ linux-3.12.33-rpi/drivers/misc/vc04_services/Kconfig 2014-12-03 19:13:38.224418001 -0600
@@ -0,0 +1,9 @@
+config BCM2708_VCHIQ
+ tristate "Videocore VCHIQ"
@@ -30573,9 +37112,9 @@ diff -Nur linux-3.12.26.orig/drivers/misc/vc04_services/Kconfig linux-3.12.26/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.26.orig/drivers/misc/vc04_services/Makefile linux-3.12.26/drivers/misc/vc04_services/Makefile
---- linux-3.12.26.orig/drivers/misc/vc04_services/Makefile 1970-01-01 01:00:00.000000000 +0100
-+++ linux-3.12.26/drivers/misc/vc04_services/Makefile 2014-08-06 16:50:14.497962339 +0200
+diff -Nur linux-3.12.33/drivers/misc/vc04_services/Makefile linux-3.12.33-rpi/drivers/misc/vc04_services/Makefile
+--- linux-3.12.33/drivers/misc/vc04_services/Makefile 1969-12-31 18:00:00.000000000 -0600
++++ linux-3.12.33-rpi/drivers/misc/vc04_services/Makefile 2014-12-03 19:13:38.224418001 -0600
@@ -0,0 +1,17 @@
+ifeq ($(CONFIG_MACH_BCM2708),y)
+
@@ -30586,7 +37125,7 @@ diff -Nur linux-3.12.26.orig/drivers/misc/vc04_services/Makefile linux-3.12.26/d
+ interface/vchiq_arm/vchiq_arm.o \
+ interface/vchiq_arm/vchiq_kern_lib.o \
+ interface/vchiq_arm/vchiq_2835_arm.o \
-+ interface/vchiq_arm/vchiq_proc.o \
++ interface/vchiq_arm/vchiq_debugfs.o \
+ interface/vchiq_arm/vchiq_shim.o \
+ interface/vchiq_arm/vchiq_util.o \
+ interface/vchiq_arm/vchiq_connected.o \
@@ -30594,9 +37133,9 @@ diff -Nur linux-3.12.26.orig/drivers/misc/vc04_services/Makefile linux-3.12.26/d
+ccflags-y += -DVCOS_VERIFY_BKPTS=1 -Idrivers/misc/vc04_services -DUSE_VCHIQ_ARM -D__VCCOREVER__=0x04000000
+
+endif
-diff -Nur linux-3.12.26.orig/drivers/mmc/card/block.c linux-3.12.26/drivers/mmc/card/block.c
---- linux-3.12.26.orig/drivers/mmc/card/block.c 2014-07-30 18:02:44.000000000 +0200
-+++ linux-3.12.26/drivers/mmc/card/block.c 2014-08-06 16:50:14.533962622 +0200
+diff -Nur linux-3.12.33/drivers/mmc/card/block.c linux-3.12.33-rpi/drivers/mmc/card/block.c
+--- linux-3.12.33/drivers/mmc/card/block.c 2014-11-15 06:28:07.000000000 -0600
++++ linux-3.12.33-rpi/drivers/mmc/card/block.c 2014-12-03 19:13:38.228418001 -0600
@@ -1361,7 +1361,7 @@
brq->data.blocks = 1;
}
@@ -30606,9 +37145,9 @@ diff -Nur linux-3.12.26.orig/drivers/mmc/card/block.c linux-3.12.26/drivers/mmc/
/* SPI multiblock writes terminate using a special
* token, not a STOP_TRANSMISSION request.
*/
-diff -Nur linux-3.12.26.orig/drivers/mmc/core/sd.c linux-3.12.26/drivers/mmc/core/sd.c
---- linux-3.12.26.orig/drivers/mmc/core/sd.c 2014-07-30 18:02:44.000000000 +0200
-+++ linux-3.12.26/drivers/mmc/core/sd.c 2014-08-06 16:50:14.553962779 +0200
+diff -Nur linux-3.12.33/drivers/mmc/core/sd.c linux-3.12.33-rpi/drivers/mmc/core/sd.c
+--- linux-3.12.33/drivers/mmc/core/sd.c 2014-11-15 06:28:07.000000000 -0600
++++ linux-3.12.33-rpi/drivers/mmc/core/sd.c 2014-12-03 19:13:38.232418001 -0600
@@ -14,6 +14,8 @@
#include <linux/sizes.h>
#include <linux/slab.h>
@@ -30763,9 +37302,1560 @@ diff -Nur linux-3.12.26.orig/drivers/mmc/core/sd.c linux-3.12.26/drivers/mmc/cor
return err;
/*
-diff -Nur linux-3.12.26.orig/drivers/mmc/host/Kconfig linux-3.12.26/drivers/mmc/host/Kconfig
---- linux-3.12.26.orig/drivers/mmc/host/Kconfig 2014-07-30 18:02:44.000000000 +0200
-+++ linux-3.12.26/drivers/mmc/host/Kconfig 2014-08-06 16:50:14.569962904 +0200
+diff -Nur linux-3.12.33/drivers/mmc/host/bcm2835-mmc.c linux-3.12.33-rpi/drivers/mmc/host/bcm2835-mmc.c
+--- linux-3.12.33/drivers/mmc/host/bcm2835-mmc.c 1969-12-31 18:00:00.000000000 -0600
++++ linux-3.12.33-rpi/drivers/mmc/host/bcm2835-mmc.c 2014-12-03 19:13:38.236418001 -0600
+@@ -0,0 +1,1547 @@
++/*
++ * BCM2835 MMC host driver.
++ *
++ * Author: Gellert Weisz <gellert@raspberrypi.org>
++ * Copyright 2014
++ *
++ * Based on
++ * sdhci-bcm2708.c by Broadcom
++ * sdhci-bcm2835.c by Stephen Warren and Oleksandr Tymoshenko
++ * sdhci.c and sdhci-pci.c by Pierre Ossman
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms and conditions of the GNU General Public License,
++ * version 2, as published by the Free Software Foundation.
++ *
++ * This program is distributed in the hope it will be useful, but WITHOUT
++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
++ * more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program. If not, see <http://www.gnu.org/licenses/>.
++ */
++
++#include <linux/delay.h>
++#include <linux/module.h>
++#include <linux/io.h>
++#include <linux/mmc/mmc.h>
++#include <linux/mmc/host.h>
++#include <linux/mmc/sd.h>
++#include <linux/scatterlist.h>
++#include <linux/of_address.h>
++#include <linux/of_irq.h>
++#include <linux/clk.h>
++#include <linux/platform_device.h>
++#include <linux/err.h>
++#include <linux/blkdev.h>
++#include <linux/dmaengine.h>
++#include <linux/dma-mapping.h>
++#include <linux/of_dma.h>
++
++#include "sdhci.h"
++
++
++#ifndef CONFIG_OF
++ #define BCM2835_CLOCK_FREQ 250000000
++#endif
++
++#define DRIVER_NAME "mmc-bcm2835"
++
++#define DBG(f, x...) \
++pr_debug(DRIVER_NAME " [%s()]: " f, __func__, ## x)
++
++#ifndef CONFIG_MMC_BCM2835_DMA
++ #define FORCE_PIO
++#endif
++
++
++/* the inclusive limit in bytes under which PIO will be used instead of DMA */
++#ifdef CONFIG_MMC_BCM2835_PIO_DMA_BARRIER
++#define PIO_DMA_BARRIER CONFIG_MMC_BCM2835_PIO_DMA_BARRIER
++#else
++#define PIO_DMA_BARRIER 00
++#endif
++
++#define MIN_FREQ 400000
++#define TIMEOUT_VAL 0xE
++#define BCM2835_SDHCI_WRITE_DELAY(f) (((2 * 1000000) / f) + 1)
++
++#ifndef BCM2708_PERI_BASE
++ #define BCM2708_PERI_BASE 0x20000000
++#endif
++
++/* FIXME: Needs IOMMU support */
++#define BCM2835_VCMMU_SHIFT (0x7E000000 - BCM2708_PERI_BASE)
++
++
++struct bcm2835_host {
++ spinlock_t lock;
++
++ void __iomem *ioaddr;
++ u32 phys_addr;
++
++ struct mmc_host *mmc;
++
++ u32 timeout;
++
++ int clock; /* Current clock speed */
++ u8 pwr; /* Current voltage */
++
++ unsigned int max_clk; /* Max possible freq */
++ unsigned int timeout_clk; /* Timeout freq (KHz) */
++ unsigned int clk_mul; /* Clock Muliplier value */
++
++ struct tasklet_struct finish_tasklet; /* Tasklet structures */
++
++ struct timer_list timer; /* Timer for timeouts */
++
++ struct sg_mapping_iter sg_miter; /* SG state for PIO */
++ unsigned int blocks; /* remaining PIO blocks */
++
++ int irq; /* Device IRQ */
++
++
++ u32 ier; /* cached registers */
++
++ struct mmc_request *mrq; /* Current request */
++ struct mmc_command *cmd; /* Current command */
++ struct mmc_data *data; /* Current data request */
++ unsigned int data_early:1; /* Data finished before cmd */
++
++ wait_queue_head_t buf_ready_int; /* Waitqueue for Buffer Read Ready interrupt */
++
++ u32 thread_isr;
++
++ u32 shadow;
++
++ /*DMA part*/
++ struct dma_chan *dma_chan_rx; /* DMA channel for reads */
++ struct dma_chan *dma_chan_tx; /* DMA channel for writes */
++ struct dma_async_tx_descriptor *tx_desc; /* descriptor */
++
++ bool have_dma;
++ bool use_dma;
++ /*end of DMA part*/
++
++ int max_delay; /* maximum length of time spent waiting */
++
++ int flags; /* Host attributes */
++#define SDHCI_USE_SDMA (1<<0) /* Host is SDMA capable */
++#define SDHCI_USE_ADMA (1<<1) /* Host is ADMA capable */
++#define SDHCI_REQ_USE_DMA (1<<2) /* Use DMA for this req. */
++#define SDHCI_DEVICE_DEAD (1<<3) /* Device unresponsive */
++#define SDHCI_AUTO_CMD12 (1<<6) /* Auto CMD12 support */
++#define SDHCI_AUTO_CMD23 (1<<7) /* Auto CMD23 support */
++#define SDHCI_PV_ENABLED (1<<8) /* Preset value enabled */
++#define SDHCI_SDIO_IRQ_ENABLED (1<<9) /* SDIO irq enabled */
++#define SDHCI_USE_PLATDMA (1<<12) /* Host uses 3rd party DMA */
++};
++
++
++static inline void bcm2835_mmc_writel(struct bcm2835_host *host, u32 val, int reg)
++{
++ writel(val, host->ioaddr + reg);
++ udelay(BCM2835_SDHCI_WRITE_DELAY(max(host->clock, MIN_FREQ)));
++}
++
++static inline void mmc_raw_writel(struct bcm2835_host *host, u32 val, int reg)
++{
++ writel(val, host->ioaddr + reg);
++}
++
++static inline u32 bcm2835_mmc_readl(struct bcm2835_host *host, int reg)
++{
++ return readl(host->ioaddr + reg);
++}
++
++static inline void bcm2835_mmc_writew(struct bcm2835_host *host, u16 val, int reg)
++{
++ u32 oldval = (reg == SDHCI_COMMAND) ? host->shadow :
++ bcm2835_mmc_readl(host, reg & ~3);
++ u32 word_num = (reg >> 1) & 1;
++ u32 word_shift = word_num * 16;
++ u32 mask = 0xffff << word_shift;
++ u32 newval = (oldval & ~mask) | (val << word_shift);
++
++ if (reg == SDHCI_TRANSFER_MODE)
++ host->shadow = newval;
++ else
++ bcm2835_mmc_writel(host, newval, reg & ~3);
++
++}
++
++static inline void bcm2835_mmc_writeb(struct bcm2835_host *host, u8 val, int reg)
++{
++ u32 oldval = bcm2835_mmc_readl(host, reg & ~3);
++ u32 byte_num = reg & 3;
++ u32 byte_shift = byte_num * 8;
++ u32 mask = 0xff << byte_shift;
++ u32 newval = (oldval & ~mask) | (val << byte_shift);
++
++ bcm2835_mmc_writel(host, newval, reg & ~3);
++}
++
++
++static inline u16 bcm2835_mmc_readw(struct bcm2835_host *host, int reg)
++{
++ u32 val = bcm2835_mmc_readl(host, (reg & ~3));
++ u32 word_num = (reg >> 1) & 1;
++ u32 word_shift = word_num * 16;
++ u32 word = (val >> word_shift) & 0xffff;
++
++ return word;
++}
++
++static inline u8 bcm2835_mmc_readb(struct bcm2835_host *host, int reg)
++{
++ u32 val = bcm2835_mmc_readl(host, (reg & ~3));
++ u32 byte_num = reg & 3;
++ u32 byte_shift = byte_num * 8;
++ u32 byte = (val >> byte_shift) & 0xff;
++
++ return byte;
++}
++
++static void bcm2835_mmc_unsignal_irqs(struct bcm2835_host *host, u32 clear)
++{
++ u32 ier;
++
++ ier = bcm2835_mmc_readl(host, SDHCI_SIGNAL_ENABLE);
++ ier &= ~clear;
++ /* change which requests generate IRQs - makes no difference to
++ the content of SDHCI_INT_STATUS, or the need to acknowledge IRQs */
++ bcm2835_mmc_writel(host, ier, SDHCI_SIGNAL_ENABLE);
++}
++
++
++static void bcm2835_mmc_dumpregs(struct bcm2835_host *host)
++{
++ pr_debug(DRIVER_NAME ": =========== REGISTER DUMP (%s)===========\n",
++ mmc_hostname(host->mmc));
++
++ pr_debug(DRIVER_NAME ": Sys addr: 0x%08x | Version: 0x%08x\n",
++ bcm2835_mmc_readl(host, SDHCI_DMA_ADDRESS),
++ bcm2835_mmc_readw(host, SDHCI_HOST_VERSION));
++ pr_debug(DRIVER_NAME ": Blk size: 0x%08x | Blk cnt: 0x%08x\n",
++ bcm2835_mmc_readw(host, SDHCI_BLOCK_SIZE),
++ bcm2835_mmc_readw(host, SDHCI_BLOCK_COUNT));
++ pr_debug(DRIVER_NAME ": Argument: 0x%08x | Trn mode: 0x%08x\n",
++ bcm2835_mmc_readl(host, SDHCI_ARGUMENT),
++ bcm2835_mmc_readw(host, SDHCI_TRANSFER_MODE));
++ pr_debug(DRIVER_NAME ": Present: 0x%08x | Host ctl: 0x%08x\n",
++ bcm2835_mmc_readl(host, SDHCI_PRESENT_STATE),
++ bcm2835_mmc_readb(host, SDHCI_HOST_CONTROL));
++ pr_debug(DRIVER_NAME ": Power: 0x%08x | Blk gap: 0x%08x\n",
++ bcm2835_mmc_readb(host, SDHCI_POWER_CONTROL),
++ bcm2835_mmc_readb(host, SDHCI_BLOCK_GAP_CONTROL));
++ pr_debug(DRIVER_NAME ": Wake-up: 0x%08x | Clock: 0x%08x\n",
++ bcm2835_mmc_readb(host, SDHCI_WAKE_UP_CONTROL),
++ bcm2835_mmc_readw(host, SDHCI_CLOCK_CONTROL));
++ pr_debug(DRIVER_NAME ": Timeout: 0x%08x | Int stat: 0x%08x\n",
++ bcm2835_mmc_readb(host, SDHCI_TIMEOUT_CONTROL),
++ bcm2835_mmc_readl(host, SDHCI_INT_STATUS));
++ pr_debug(DRIVER_NAME ": Int enab: 0x%08x | Sig enab: 0x%08x\n",
++ bcm2835_mmc_readl(host, SDHCI_INT_ENABLE),
++ bcm2835_mmc_readl(host, SDHCI_SIGNAL_ENABLE));
++ pr_debug(DRIVER_NAME ": AC12 err: 0x%08x | Slot int: 0x%08x\n",
++ bcm2835_mmc_readw(host, SDHCI_ACMD12_ERR),
++ bcm2835_mmc_readw(host, SDHCI_SLOT_INT_STATUS));
++ pr_debug(DRIVER_NAME ": Caps: 0x%08x | Caps_1: 0x%08x\n",
++ bcm2835_mmc_readl(host, SDHCI_CAPABILITIES),
++ bcm2835_mmc_readl(host, SDHCI_CAPABILITIES_1));
++ pr_debug(DRIVER_NAME ": Cmd: 0x%08x | Max curr: 0x%08x\n",
++ bcm2835_mmc_readw(host, SDHCI_COMMAND),
++ bcm2835_mmc_readl(host, SDHCI_MAX_CURRENT));
++ pr_debug(DRIVER_NAME ": Host ctl2: 0x%08x\n",
++ bcm2835_mmc_readw(host, SDHCI_HOST_CONTROL2));
++
++ pr_debug(DRIVER_NAME ": ===========================================\n");
++}
++
++
++static void bcm2835_mmc_reset(struct bcm2835_host *host, u8 mask)
++{
++ unsigned long timeout;
++
++ bcm2835_mmc_writeb(host, mask, SDHCI_SOFTWARE_RESET);
++
++ if (mask & SDHCI_RESET_ALL)
++ host->clock = 0;
++
++ /* Wait max 100 ms */
++ timeout = 100;
++
++ /* hw clears the bit when it's done */
++ while (bcm2835_mmc_readb(host, SDHCI_SOFTWARE_RESET) & mask) {
++ if (timeout == 0) {
++ pr_err("%s: Reset 0x%x never completed.\n",
++ mmc_hostname(host->mmc), (int)mask);
++ bcm2835_mmc_dumpregs(host);
++ return;
++ }
++ timeout--;
++ mdelay(1);
++ }
++
++ if (100-timeout > 10 && 100-timeout > host->max_delay) {
++ host->max_delay = 100-timeout;
++ pr_warning("Warning: MMC controller hung for %d ms\n", host->max_delay);
++ }
++}
++
++static void bcm2835_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios);
++
++static void bcm2835_mmc_init(struct bcm2835_host *host, int soft)
++{
++ if (soft)
++ bcm2835_mmc_reset(host, SDHCI_RESET_CMD|SDHCI_RESET_DATA);
++ else
++ bcm2835_mmc_reset(host, SDHCI_RESET_ALL);
++
++ host->ier = SDHCI_INT_BUS_POWER | SDHCI_INT_DATA_END_BIT |
++ SDHCI_INT_DATA_CRC | SDHCI_INT_DATA_TIMEOUT |
++ SDHCI_INT_INDEX | SDHCI_INT_END_BIT | SDHCI_INT_CRC |
++ SDHCI_INT_TIMEOUT | SDHCI_INT_DATA_END |
++ SDHCI_INT_RESPONSE;
++
++ bcm2835_mmc_writel(host, host->ier, SDHCI_INT_ENABLE);
++ bcm2835_mmc_writel(host, host->ier, SDHCI_SIGNAL_ENABLE);
++
++ if (soft) {
++ /* force clock reconfiguration */
++ host->clock = 0;
++ bcm2835_mmc_set_ios(host->mmc, &host->mmc->ios);
++ }
++}
++
++
++
++static void bcm2835_mmc_finish_data(struct bcm2835_host *host);
++
++static void bcm2835_mmc_dma_complete(void *param)
++{
++ struct bcm2835_host *host = param;
++ struct dma_chan *dma_chan;
++ unsigned long flags;
++ u32 dir_data;
++
++ spin_lock_irqsave(&host->lock, flags);
++
++ if (host->data && !(host->data->flags & MMC_DATA_WRITE)) {
++ /* otherwise handled in SDHCI IRQ */
++ dma_chan = host->dma_chan_rx;
++ dir_data = DMA_FROM_DEVICE;
++
++ dma_unmap_sg(dma_chan->device->dev,
++ host->data->sg, host->data->sg_len,
++ dir_data);
++
++ bcm2835_mmc_finish_data(host);
++ }
++
++ spin_unlock_irqrestore(&host->lock, flags);
++}
++
++static void bcm2835_bcm2835_mmc_read_block_pio(struct bcm2835_host *host)
++{
++ unsigned long flags;
++ size_t blksize, len, chunk;
++
++ u32 uninitialized_var(scratch);
++ u8 *buf;
++
++ blksize = host->data->blksz;
++ chunk = 0;
++
++ local_irq_save(flags);
++
++ while (blksize) {
++ if (!sg_miter_next(&host->sg_miter))
++ BUG();
++
++ len = min(host->sg_miter.length, blksize);
++
++ blksize -= len;
++ host->sg_miter.consumed = len;
++
++ buf = host->sg_miter.addr;
++
++ while (len) {
++ if (chunk == 0) {
++ scratch = bcm2835_mmc_readl(host, SDHCI_BUFFER);
++ chunk = 4;
++ }
++
++ *buf = scratch & 0xFF;
++
++ buf++;
++ scratch >>= 8;
++ chunk--;
++ len--;
++ }
++ }
++
++ sg_miter_stop(&host->sg_miter);
++
++ local_irq_restore(flags);
++}
++
++static void bcm2835_bcm2835_mmc_write_block_pio(struct bcm2835_host *host)
++{
++ unsigned long flags;
++ size_t blksize, len, chunk;
++ u32 scratch;
++ u8 *buf;
++
++ blksize = host->data->blksz;
++ chunk = 0;
++ chunk = 0;
++ scratch = 0;
++
++ local_irq_save(flags);
++
++ while (blksize) {
++ if (!sg_miter_next(&host->sg_miter))
++ BUG();
++
++ len = min(host->sg_miter.length, blksize);
++
++ blksize -= len;
++ host->sg_miter.consumed = len;
++
++ buf = host->sg_miter.addr;
++
++ while (len) {
++ scratch |= (u32)*buf << (chunk * 8);
++
++ buf++;
++ chunk++;
++ len--;
++
++ if ((chunk == 4) || ((len == 0) && (blksize == 0))) {
++ mmc_raw_writel(host, scratch, SDHCI_BUFFER);
++ chunk = 0;
++ scratch = 0;
++ }
++ }
++ }
++
++ sg_miter_stop(&host->sg_miter);
++
++ local_irq_restore(flags);
++}
++
++
++static void bcm2835_mmc_transfer_pio(struct bcm2835_host *host)
++{
++ u32 mask;
++
++ BUG_ON(!host->data);
++
++ if (host->blocks == 0)
++ return;
++
++ if (host->data->flags & MMC_DATA_READ)
++ mask = SDHCI_DATA_AVAILABLE;
++ else
++ mask = SDHCI_SPACE_AVAILABLE;
++
++ while (bcm2835_mmc_readl(host, SDHCI_PRESENT_STATE) & mask) {
++
++ if (host->data->flags & MMC_DATA_READ)
++ bcm2835_bcm2835_mmc_read_block_pio(host);
++ else
++ bcm2835_bcm2835_mmc_write_block_pio(host);
++
++ host->blocks--;
++
++ /* QUIRK used in sdhci.c removes the 'if' */
++ /* but it seems this is unnecessary */
++ if (host->blocks == 0)
++ break;
++
++
++ }
++}
++
++
++static void bcm2835_mmc_transfer_dma(struct bcm2835_host *host)
++{
++ u32 len, dir_data, dir_slave;
++ struct dma_async_tx_descriptor *desc = NULL;
++ struct dma_chan *dma_chan;
++
++
++ WARN_ON(!host->data);
++
++ if (!host->data)
++ return;
++
++ if (host->blocks == 0)
++ return;
++
++ if (host->data->flags & MMC_DATA_READ) {
++ dma_chan = host->dma_chan_rx;
++ dir_data = DMA_FROM_DEVICE;
++ dir_slave = DMA_DEV_TO_MEM;
++ } else {
++ dma_chan = host->dma_chan_tx;
++ dir_data = DMA_TO_DEVICE;
++ dir_slave = DMA_MEM_TO_DEV;
++ }
++
++ BUG_ON(!dma_chan->device);
++ BUG_ON(!dma_chan->device->dev);
++ BUG_ON(!host->data->sg);
++
++ len = dma_map_sg(dma_chan->device->dev, host->data->sg,
++ host->data->sg_len, dir_data);
++ if (len > 0) {
++ desc = dmaengine_prep_slave_sg(dma_chan, host->data->sg,
++ len, dir_slave,
++ DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
++ } else {
++ dev_err(mmc_dev(host->mmc), "dma_map_sg returned zero length\n");
++ }
++ if (desc) {
++ bcm2835_mmc_unsignal_irqs(host, SDHCI_INT_DATA_AVAIL |
++ SDHCI_INT_SPACE_AVAIL);
++ host->tx_desc = desc;
++ desc->callback = bcm2835_mmc_dma_complete;
++ desc->callback_param = host;
++ dmaengine_submit(desc);
++ dma_async_issue_pending(dma_chan);
++ }
++
++}
++
++
++
++static void bcm2835_mmc_set_transfer_irqs(struct bcm2835_host *host)
++{
++ u32 pio_irqs = SDHCI_INT_DATA_AVAIL | SDHCI_INT_SPACE_AVAIL;
++ u32 dma_irqs = SDHCI_INT_DMA_END | SDHCI_INT_ADMA_ERROR;
++
++ if (host->use_dma)
++ host->ier = (host->ier & ~pio_irqs) | dma_irqs;
++ else
++ host->ier = (host->ier & ~dma_irqs) | pio_irqs;
++
++ bcm2835_mmc_writel(host, host->ier, SDHCI_INT_ENABLE);
++ bcm2835_mmc_writel(host, host->ier, SDHCI_SIGNAL_ENABLE);
++}
++
++
++static void bcm2835_mmc_prepare_data(struct bcm2835_host *host, struct mmc_command *cmd)
++{
++ u8 count;
++ struct mmc_data *data = cmd->data;
++
++ WARN_ON(host->data);
++
++ if (data || (cmd->flags & MMC_RSP_BUSY)) {
++ count = TIMEOUT_VAL;
++ bcm2835_mmc_writeb(host, count, SDHCI_TIMEOUT_CONTROL);
++ }
++
++ if (!data)
++ return;
++
++ /* Sanity checks */
++ BUG_ON(data->blksz * data->blocks > 524288);
++ BUG_ON(data->blksz > host->mmc->max_blk_size);
++ BUG_ON(data->blocks > 65535);
++
++ host->data = data;
++ host->data_early = 0;
++ host->data->bytes_xfered = 0;
++
++
++ if (!(host->flags & SDHCI_REQ_USE_DMA)) {
++ int flags;
++
++ flags = SG_MITER_ATOMIC;
++ if (host->data->flags & MMC_DATA_READ)
++ flags |= SG_MITER_TO_SG;
++ else
++ flags |= SG_MITER_FROM_SG;
++ sg_miter_start(&host->sg_miter, data->sg, data->sg_len, flags);
++ host->blocks = data->blocks;
++ }
++
++ host->use_dma = host->have_dma && data->blocks > PIO_DMA_BARRIER;
++
++ bcm2835_mmc_set_transfer_irqs(host);
++
++ /* Set the DMA boundary value and block size */
++ bcm2835_mmc_writew(host, SDHCI_MAKE_BLKSZ(SDHCI_DEFAULT_BOUNDARY_ARG,
++ data->blksz), SDHCI_BLOCK_SIZE);
++ bcm2835_mmc_writew(host, data->blocks, SDHCI_BLOCK_COUNT);
++
++ BUG_ON(!host->data);
++}
++
++static void bcm2835_mmc_set_transfer_mode(struct bcm2835_host *host,
++ struct mmc_command *cmd)
++{
++ u16 mode;
++ struct mmc_data *data = cmd->data;
++
++ if (data == NULL) {
++ /* clear Auto CMD settings for no data CMDs */
++ mode = bcm2835_mmc_readw(host, SDHCI_TRANSFER_MODE);
++ bcm2835_mmc_writew(host, mode & ~(SDHCI_TRNS_AUTO_CMD12 |
++ SDHCI_TRNS_AUTO_CMD23), SDHCI_TRANSFER_MODE);
++ return;
++ }
++
++ WARN_ON(!host->data);
++
++ mode = SDHCI_TRNS_BLK_CNT_EN;
++
++ if ((mmc_op_multi(cmd->opcode) || data->blocks > 1)) {
++ mode |= SDHCI_TRNS_MULTI;
++
++ /*
++ * If we are sending CMD23, CMD12 never gets sent
++ * on successful completion (so no Auto-CMD12).
++ */
++ if (!host->mrq->sbc && (host->flags & SDHCI_AUTO_CMD12))
++ mode |= SDHCI_TRNS_AUTO_CMD12;
++ else if (host->mrq->sbc && (host->flags & SDHCI_AUTO_CMD23)) {
++ mode |= SDHCI_TRNS_AUTO_CMD23;
++ bcm2835_mmc_writel(host, host->mrq->sbc->arg, SDHCI_ARGUMENT2);
++ }
++ }
++
++ if (data->flags & MMC_DATA_READ)
++ mode |= SDHCI_TRNS_READ;
++ if (host->flags & SDHCI_REQ_USE_DMA)
++ mode |= SDHCI_TRNS_DMA;
++
++ bcm2835_mmc_writew(host, mode, SDHCI_TRANSFER_MODE);
++}
++
++void bcm2835_mmc_send_command(struct bcm2835_host *host, struct mmc_command *cmd)
++{
++ int flags;
++ u32 mask;
++ unsigned long timeout;
++
++ WARN_ON(host->cmd);
++
++ /* Wait max 10 ms */
++ timeout = 1000;
++
++ mask = SDHCI_CMD_INHIBIT;
++ if ((cmd->data != NULL) || (cmd->flags & MMC_RSP_BUSY))
++ mask |= SDHCI_DATA_INHIBIT;
++
++ /* We shouldn't wait for data inihibit for stop commands, even
++ though they might use busy signaling */
++ if (host->mrq->data && (cmd == host->mrq->data->stop))
++ mask &= ~SDHCI_DATA_INHIBIT;
++
++ while (bcm2835_mmc_readl(host, SDHCI_PRESENT_STATE) & mask) {
++ if (timeout == 0) {
++ pr_err("%s: Controller never released inhibit bit(s).\n",
++ mmc_hostname(host->mmc));
++ bcm2835_mmc_dumpregs(host);
++ cmd->error = -EIO;
++ tasklet_schedule(&host->finish_tasklet);
++ return;
++ }
++ timeout--;
++ udelay(10);
++ }
++
++ if ((1000-timeout)/100 > 1 && (1000-timeout)/100 > host->max_delay) {
++ host->max_delay = (1000-timeout)/100;
++ pr_warning("Warning: MMC controller hung for %d ms\n", host->max_delay);
++ }
++
++ timeout = jiffies;
++#ifdef CONFIG_OF
++ if (!cmd->data && cmd->busy_timeout > 9000)
++ timeout += DIV_ROUND_UP(cmd->busy_timeout, 1000) * HZ + HZ;
++ else
++#endif
++ timeout += 10 * HZ;
++ mod_timer(&host->timer, timeout);
++
++ host->cmd = cmd;
++
++ bcm2835_mmc_prepare_data(host, cmd);
++
++ bcm2835_mmc_writel(host, cmd->arg, SDHCI_ARGUMENT);
++
++ bcm2835_mmc_set_transfer_mode(host, cmd);
++
++ if ((cmd->flags & MMC_RSP_136) && (cmd->flags & MMC_RSP_BUSY)) {
++ pr_err("%s: Unsupported response type!\n",
++ mmc_hostname(host->mmc));
++ cmd->error = -EINVAL;
++ tasklet_schedule(&host->finish_tasklet);
++ return;
++ }
++
++ if (!(cmd->flags & MMC_RSP_PRESENT))
++ flags = SDHCI_CMD_RESP_NONE;
++ else if (cmd->flags & MMC_RSP_136)
++ flags = SDHCI_CMD_RESP_LONG;
++ else if (cmd->flags & MMC_RSP_BUSY)
++ flags = SDHCI_CMD_RESP_SHORT_BUSY;
++ else
++ flags = SDHCI_CMD_RESP_SHORT;
++
++ if (cmd->flags & MMC_RSP_CRC)
++ flags |= SDHCI_CMD_CRC;
++ if (cmd->flags & MMC_RSP_OPCODE)
++ flags |= SDHCI_CMD_INDEX;
++
++ if (cmd->data)
++ flags |= SDHCI_CMD_DATA;
++
++ bcm2835_mmc_writew(host, SDHCI_MAKE_CMD(cmd->opcode, flags), SDHCI_COMMAND);
++}
++
++
++static void bcm2835_mmc_finish_data(struct bcm2835_host *host)
++{
++ struct mmc_data *data;
++
++ BUG_ON(!host->data);
++
++ data = host->data;
++ host->data = NULL;
++
++ if (data->error)
++ data->bytes_xfered = 0;
++ else
++ data->bytes_xfered = data->blksz * data->blocks;
++
++ /*
++ * Need to send CMD12 if -
++ * a) open-ended multiblock transfer (no CMD23)
++ * b) error in multiblock transfer
++ */
++ if (data->stop &&
++ (data->error ||
++ !host->mrq->sbc)) {
++
++ /*
++ * The controller needs a reset of internal state machines
++ * upon error conditions.
++ */
++ if (data->error) {
++ bcm2835_mmc_reset(host, SDHCI_RESET_CMD);
++ bcm2835_mmc_reset(host, SDHCI_RESET_DATA);
++ }
++
++ bcm2835_mmc_send_command(host, data->stop);
++ } else
++ tasklet_schedule(&host->finish_tasklet);
++}
++
++static void bcm2835_mmc_finish_command(struct bcm2835_host *host)
++{
++ int i;
++
++ BUG_ON(host->cmd == NULL);
++
++ if (host->cmd->flags & MMC_RSP_PRESENT) {
++ if (host->cmd->flags & MMC_RSP_136) {
++ /* CRC is stripped so we need to do some shifting. */
++ for (i = 0; i < 4; i++) {
++ host->cmd->resp[i] = bcm2835_mmc_readl(host,
++ SDHCI_RESPONSE + (3-i)*4) << 8;
++ if (i != 3)
++ host->cmd->resp[i] |=
++ bcm2835_mmc_readb(host,
++ SDHCI_RESPONSE + (3-i)*4-1);
++ }
++ } else {
++ host->cmd->resp[0] = bcm2835_mmc_readl(host, SDHCI_RESPONSE);
++ }
++ }
++
++ host->cmd->error = 0;
++
++ /* Finished CMD23, now send actual command. */
++ if (host->cmd == host->mrq->sbc) {
++ host->cmd = NULL;
++ bcm2835_mmc_send_command(host, host->mrq->cmd);
++ } else {
++
++ /* Processed actual command. */
++ if (host->data && host->data_early)
++ bcm2835_mmc_finish_data(host);
++
++ if (!host->cmd->data)
++ tasklet_schedule(&host->finish_tasklet);
++
++ host->cmd = NULL;
++ }
++}
++
++
++static void bcm2835_mmc_timeout_timer(unsigned long data)
++{
++ struct bcm2835_host *host;
++ unsigned long flags;
++
++ host = (struct bcm2835_host *)data;
++
++ spin_lock_irqsave(&host->lock, flags);
++
++ if (host->mrq) {
++ pr_err("%s: Timeout waiting for hardware interrupt.\n",
++ mmc_hostname(host->mmc));
++ bcm2835_mmc_dumpregs(host);
++
++ if (host->data) {
++ host->data->error = -ETIMEDOUT;
++ bcm2835_mmc_finish_data(host);
++ } else {
++ if (host->cmd)
++ host->cmd->error = -ETIMEDOUT;
++ else
++ host->mrq->cmd->error = -ETIMEDOUT;
++
++ tasklet_schedule(&host->finish_tasklet);
++ }
++ }
++
++ mmiowb();
++ spin_unlock_irqrestore(&host->lock, flags);
++}
++
++
++static void bcm2835_mmc_enable_sdio_irq_nolock(struct bcm2835_host *host, int enable)
++{
++ if (!(host->flags & SDHCI_DEVICE_DEAD)) {
++ if (enable)
++ host->ier |= SDHCI_INT_CARD_INT;
++ else
++ host->ier &= ~SDHCI_INT_CARD_INT;
++
++ bcm2835_mmc_writel(host, host->ier, SDHCI_INT_ENABLE);
++ bcm2835_mmc_writel(host, host->ier, SDHCI_SIGNAL_ENABLE);
++ mmiowb();
++ }
++}
++
++static void bcm2835_mmc_enable_sdio_irq(struct mmc_host *mmc, int enable)
++{
++ struct bcm2835_host *host = mmc_priv(mmc);
++ unsigned long flags;
++
++ spin_lock_irqsave(&host->lock, flags);
++ if (enable)
++ host->flags |= SDHCI_SDIO_IRQ_ENABLED;
++ else
++ host->flags &= ~SDHCI_SDIO_IRQ_ENABLED;
++
++ bcm2835_mmc_enable_sdio_irq_nolock(host, enable);
++ spin_unlock_irqrestore(&host->lock, flags);
++}
++
++static void bcm2835_mmc_cmd_irq(struct bcm2835_host *host, u32 intmask)
++{
++
++ BUG_ON(intmask == 0);
++
++ if (!host->cmd) {
++ pr_err("%s: Got command interrupt 0x%08x even "
++ "though no command operation was in progress.\n",
++ mmc_hostname(host->mmc), (unsigned)intmask);
++ bcm2835_mmc_dumpregs(host);
++ return;
++ }
++
++ if (intmask & SDHCI_INT_TIMEOUT)
++ host->cmd->error = -ETIMEDOUT;
++ else if (intmask & (SDHCI_INT_CRC | SDHCI_INT_END_BIT |
++ SDHCI_INT_INDEX)) {
++ host->cmd->error = -EILSEQ;
++ }
++
++ if (host->cmd->error) {
++ tasklet_schedule(&host->finish_tasklet);
++ return;
++ }
++
++ if (intmask & SDHCI_INT_RESPONSE)
++ bcm2835_mmc_finish_command(host);
++
++}
++
++static void bcm2835_mmc_data_irq(struct bcm2835_host *host, u32 intmask)
++{
++ struct dma_chan *dma_chan;
++ u32 dir_data;
++
++ BUG_ON(intmask == 0);
++
++ if (!host->data) {
++ /*
++ * The "data complete" interrupt is also used to
++ * indicate that a busy state has ended. See comment
++ * above in sdhci_cmd_irq().
++ */
++ if (host->cmd && (host->cmd->flags & MMC_RSP_BUSY)) {
++ if (intmask & SDHCI_INT_DATA_END) {
++ bcm2835_mmc_finish_command(host);
++ return;
++ }
++ }
++
++ pr_debug("%s: Got data interrupt 0x%08x even "
++ "though no data operation was in progress.\n",
++ mmc_hostname(host->mmc), (unsigned)intmask);
++ bcm2835_mmc_dumpregs(host);
++
++ return;
++ }
++
++ if (intmask & SDHCI_INT_DATA_TIMEOUT)
++ host->data->error = -ETIMEDOUT;
++ else if (intmask & SDHCI_INT_DATA_END_BIT)
++ host->data->error = -EILSEQ;
++ else if ((intmask & SDHCI_INT_DATA_CRC) &&
++ SDHCI_GET_CMD(bcm2835_mmc_readw(host, SDHCI_COMMAND))
++ != MMC_BUS_TEST_R)
++ host->data->error = -EILSEQ;
++
++ if (host->use_dma) {
++ if (host->data->flags & MMC_DATA_WRITE) {
++ /* IRQ handled here */
++
++ dma_chan = host->dma_chan_tx;
++ dir_data = DMA_TO_DEVICE;
++ dma_unmap_sg(dma_chan->device->dev,
++ host->data->sg, host->data->sg_len,
++ dir_data);
++
++ bcm2835_mmc_finish_data(host);
++ }
++
++ } else {
++ if (host->data->error)
++ bcm2835_mmc_finish_data(host);
++ else {
++ if (intmask & (SDHCI_INT_DATA_AVAIL | SDHCI_INT_SPACE_AVAIL))
++ bcm2835_mmc_transfer_pio(host);
++
++ if (intmask & SDHCI_INT_DATA_END) {
++ if (host->cmd) {
++ /*
++ * Data managed to finish before the
++ * command completed. Make sure we do
++ * things in the proper order.
++ */
++ host->data_early = 1;
++ } else {
++ bcm2835_mmc_finish_data(host);
++ }
++ }
++ }
++ }
++}
++
++
++static irqreturn_t bcm2835_mmc_irq(int irq, void *dev_id)
++{
++ irqreturn_t result = IRQ_NONE;
++ struct bcm2835_host *host = dev_id;
++ u32 intmask, mask, unexpected = 0;
++ int max_loops = 16;
++#ifndef CONFIG_OF
++ int cardint = 0;
++#endif
++
++ spin_lock(&host->lock);
++
++ intmask = bcm2835_mmc_readl(host, SDHCI_INT_STATUS);
++
++ if (!intmask || intmask == 0xffffffff) {
++ result = IRQ_NONE;
++ goto out;
++ }
++
++ do {
++ /* Clear selected interrupts. */
++ mask = intmask & (SDHCI_INT_CMD_MASK | SDHCI_INT_DATA_MASK |
++ SDHCI_INT_BUS_POWER);
++ bcm2835_mmc_writel(host, mask, SDHCI_INT_STATUS);
++
++
++ if (intmask & SDHCI_INT_CMD_MASK)
++ bcm2835_mmc_cmd_irq(host, intmask & SDHCI_INT_CMD_MASK);
++
++ if (intmask & SDHCI_INT_DATA_MASK)
++ bcm2835_mmc_data_irq(host, intmask & SDHCI_INT_DATA_MASK);
++
++ if (intmask & SDHCI_INT_BUS_POWER)
++ pr_err("%s: Card is consuming too much power!\n",
++ mmc_hostname(host->mmc));
++
++ if (intmask & SDHCI_INT_CARD_INT) {
++#ifndef CONFIG_OF
++ cardint = 1;
++#else
++ bcm2835_mmc_enable_sdio_irq_nolock(host, false);
++ host->thread_isr |= SDHCI_INT_CARD_INT;
++ result = IRQ_WAKE_THREAD;
++#endif
++ }
++
++ intmask &= ~(SDHCI_INT_CARD_INSERT | SDHCI_INT_CARD_REMOVE |
++ SDHCI_INT_CMD_MASK | SDHCI_INT_DATA_MASK |
++ SDHCI_INT_ERROR | SDHCI_INT_BUS_POWER |
++ SDHCI_INT_CARD_INT);
++
++ if (intmask) {
++ unexpected |= intmask;
++ bcm2835_mmc_writel(host, intmask, SDHCI_INT_STATUS);
++ }
++
++ if (result == IRQ_NONE)
++ result = IRQ_HANDLED;
++
++ intmask = bcm2835_mmc_readl(host, SDHCI_INT_STATUS);
++ } while (intmask && --max_loops);
++out:
++ spin_unlock(&host->lock);
++
++ if (unexpected) {
++ pr_err("%s: Unexpected interrupt 0x%08x.\n",
++ mmc_hostname(host->mmc), unexpected);
++ bcm2835_mmc_dumpregs(host);
++ }
++
++#ifndef CONFIG_OF
++ if (cardint)
++ mmc_signal_sdio_irq(host->mmc);
++#endif
++
++ return result;
++}
++
++#ifdef CONFIG_OF
++static irqreturn_t bcm2835_mmc_thread_irq(int irq, void *dev_id)
++{
++ struct bcm2835_host *host = dev_id;
++ unsigned long flags;
++ u32 isr;
++
++ spin_lock_irqsave(&host->lock, flags);
++ isr = host->thread_isr;
++ host->thread_isr = 0;
++ spin_unlock_irqrestore(&host->lock, flags);
++
++ if (isr & SDHCI_INT_CARD_INT) {
++ sdio_run_irqs(host->mmc);
++
++ spin_lock_irqsave(&host->lock, flags);
++ if (host->flags & SDHCI_SDIO_IRQ_ENABLED)
++ bcm2835_mmc_enable_sdio_irq_nolock(host, true);
++ spin_unlock_irqrestore(&host->lock, flags);
++ }
++
++ return isr ? IRQ_HANDLED : IRQ_NONE;
++}
++#endif
++
++
++
++void bcm2835_mmc_set_clock(struct bcm2835_host *host, unsigned int clock)
++{
++ int div = 0; /* Initialized for compiler warning */
++ int real_div = div, clk_mul = 1;
++ u16 clk = 0;
++ unsigned long timeout;
++
++
++ host->mmc->actual_clock = 0;
++
++ bcm2835_mmc_writew(host, 0, SDHCI_CLOCK_CONTROL);
++
++ if (clock == 0)
++ return;
++
++ /* Version 3.00 divisors must be a multiple of 2. */
++ if (host->max_clk <= clock)
++ div = 1;
++ else {
++ for (div = 2; div < SDHCI_MAX_DIV_SPEC_300;
++ div += 2) {
++ if ((host->max_clk / div) <= clock)
++ break;
++ }
++ }
++
++ real_div = div;
++ div >>= 1;
++
++ if (real_div)
++ host->mmc->actual_clock = (host->max_clk * clk_mul) / real_div;
++
++ clk |= (div & SDHCI_DIV_MASK) << SDHCI_DIVIDER_SHIFT;
++ clk |= ((div & SDHCI_DIV_HI_MASK) >> SDHCI_DIV_MASK_LEN)
++ << SDHCI_DIVIDER_HI_SHIFT;
++ clk |= SDHCI_CLOCK_INT_EN;
++ bcm2835_mmc_writew(host, clk, SDHCI_CLOCK_CONTROL);
++
++ /* Wait max 20 ms */
++ timeout = 20;
++ while (!((clk = bcm2835_mmc_readw(host, SDHCI_CLOCK_CONTROL))
++ & SDHCI_CLOCK_INT_STABLE)) {
++ if (timeout == 0) {
++ pr_err("%s: Internal clock never "
++ "stabilised.\n", mmc_hostname(host->mmc));
++ bcm2835_mmc_dumpregs(host);
++ return;
++ }
++ timeout--;
++ mdelay(1);
++ }
++
++ if (20-timeout > 10 && 20-timeout > host->max_delay) {
++ host->max_delay = 20-timeout;
++ pr_warning("Warning: MMC controller hung for %d ms\n", host->max_delay);
++ }
++
++ clk |= SDHCI_CLOCK_CARD_EN;
++ bcm2835_mmc_writew(host, clk, SDHCI_CLOCK_CONTROL);
++}
++
++static void bcm2835_mmc_request(struct mmc_host *mmc, struct mmc_request *mrq)
++{
++ struct bcm2835_host *host;
++ unsigned long flags;
++
++ host = mmc_priv(mmc);
++
++ spin_lock_irqsave(&host->lock, flags);
++
++ WARN_ON(host->mrq != NULL);
++
++ host->mrq = mrq;
++ bcm2835_mmc_send_command(host, mrq->cmd);
++ mmiowb();
++ spin_unlock_irqrestore(&host->lock, flags);
++
++ if (mrq->cmd->data && host->use_dma) {
++ /* DMA transfer starts now, PIO starts after interrupt */
++ bcm2835_mmc_transfer_dma(host);
++ }
++}
++
++
++static void bcm2835_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
++{
++
++ struct bcm2835_host *host = mmc_priv(mmc);
++ unsigned long flags;
++ u8 ctrl;
++ u16 clk, ctrl_2;
++
++
++ spin_lock_irqsave(&host->lock, flags);
++
++ if (!ios->clock || ios->clock != host->clock) {
++ bcm2835_mmc_set_clock(host, ios->clock);
++ host->clock = ios->clock;
++ }
++
++ if (host->pwr != SDHCI_POWER_330) {
++ host->pwr = SDHCI_POWER_330;
++ bcm2835_mmc_writeb(host, SDHCI_POWER_330 | SDHCI_POWER_ON, SDHCI_POWER_CONTROL);
++ }
++
++ ctrl = bcm2835_mmc_readb(host, SDHCI_HOST_CONTROL);
++
++ /* set bus width */
++ ctrl &= ~SDHCI_CTRL_8BITBUS;
++ if (ios->bus_width == MMC_BUS_WIDTH_4)
++ ctrl |= SDHCI_CTRL_4BITBUS;
++ else
++ ctrl &= ~SDHCI_CTRL_4BITBUS;
++
++ ctrl &= ~SDHCI_CTRL_HISPD; /* NO_HISPD_BIT */
++
++
++ bcm2835_mmc_writeb(host, ctrl, SDHCI_HOST_CONTROL);
++ /*
++ * We only need to set Driver Strength if the
++ * preset value enable is not set.
++ */
++ ctrl_2 = bcm2835_mmc_readw(host, SDHCI_HOST_CONTROL2);
++ ctrl_2 &= ~SDHCI_CTRL_DRV_TYPE_MASK;
++ if (ios->drv_type == MMC_SET_DRIVER_TYPE_A)
++ ctrl_2 |= SDHCI_CTRL_DRV_TYPE_A;
++ else if (ios->drv_type == MMC_SET_DRIVER_TYPE_C)
++ ctrl_2 |= SDHCI_CTRL_DRV_TYPE_C;
++
++ bcm2835_mmc_writew(host, ctrl_2, SDHCI_HOST_CONTROL2);
++
++ /* Reset SD Clock Enable */
++ clk = bcm2835_mmc_readw(host, SDHCI_CLOCK_CONTROL);
++ clk &= ~SDHCI_CLOCK_CARD_EN;
++ bcm2835_mmc_writew(host, clk, SDHCI_CLOCK_CONTROL);
++
++ /* Re-enable SD Clock */
++ bcm2835_mmc_set_clock(host, host->clock);
++ bcm2835_mmc_writeb(host, ctrl, SDHCI_HOST_CONTROL);
++
++ mmiowb();
++
++ spin_unlock_irqrestore(&host->lock, flags);
++}
++
++
++static struct mmc_host_ops bcm2835_ops = {
++ .request = bcm2835_mmc_request,
++ .set_ios = bcm2835_mmc_set_ios,
++ .enable_sdio_irq = bcm2835_mmc_enable_sdio_irq,
++};
++
++
++static void bcm2835_mmc_tasklet_finish(unsigned long param)
++{
++ struct bcm2835_host *host;
++ unsigned long flags;
++ struct mmc_request *mrq;
++
++ host = (struct bcm2835_host *)param;
++
++ spin_lock_irqsave(&host->lock, flags);
++
++ /*
++ * If this tasklet gets rescheduled while running, it will
++ * be run again afterwards but without any active request.
++ */
++ if (!host->mrq) {
++ spin_unlock_irqrestore(&host->lock, flags);
++ return;
++ }
++
++ del_timer(&host->timer);
++
++ mrq = host->mrq;
++
++ /*
++ * The controller needs a reset of internal state machines
++ * upon error conditions.
++ */
++ if (!(host->flags & SDHCI_DEVICE_DEAD) &&
++ ((mrq->cmd && mrq->cmd->error) ||
++ (mrq->data && (mrq->data->error ||
++ (mrq->data->stop && mrq->data->stop->error))))) {
++
++ bcm2835_mmc_reset(host, SDHCI_RESET_CMD);
++ bcm2835_mmc_reset(host, SDHCI_RESET_DATA);
++ }
++
++ host->mrq = NULL;
++ host->cmd = NULL;
++ host->data = NULL;
++
++ mmiowb();
++
++ spin_unlock_irqrestore(&host->lock, flags);
++ mmc_request_done(host->mmc, mrq);
++}
++
++
++
++int bcm2835_mmc_add_host(struct bcm2835_host *host)
++{
++ struct mmc_host *mmc;
++#ifndef FORCE_PIO
++ struct dma_slave_config cfg;
++#endif
++ int ret;
++
++ mmc = host->mmc;
++
++ bcm2835_mmc_reset(host, SDHCI_RESET_ALL);
++
++ host->clk_mul = 0;
++
++ mmc->ops = &bcm2835_ops;
++ mmc->f_max = host->max_clk;
++ mmc->f_max = host->max_clk;
++ mmc->f_min = host->max_clk / SDHCI_MAX_DIV_SPEC_300;
++
++ /* SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK */
++ host->timeout_clk = mmc->f_max / 1000;
++#ifdef CONFIG_OF
++ mmc->max_busy_timeout = (1 << 27) / host->timeout_clk;
++#endif
++ /* host controller capabilities */
++ mmc->caps = MMC_CAP_CMD23 | MMC_CAP_ERASE | MMC_CAP_NEEDS_POLL | MMC_CAP_SDIO_IRQ |
++ MMC_CAP_SD_HIGHSPEED | MMC_CAP_MMC_HIGHSPEED | MMC_CAP_4_BIT_DATA;
++
++ host->flags = SDHCI_AUTO_CMD23;
++
++ spin_lock_init(&host->lock);
++
++
++#ifdef FORCE_PIO
++ pr_info("Forcing PIO mode\n");
++ host->have_dma = false;
++#else
++ if (!host->dma_chan_tx || !host->dma_chan_rx ||
++ IS_ERR(host->dma_chan_tx) || IS_ERR(host->dma_chan_rx)) {
++ pr_err("%s: Unable to initialise DMA channels. Falling back to PIO\n", DRIVER_NAME);
++ host->have_dma = false;
++ } else {
++ pr_info("DMA channels allocated for the MMC driver");
++ host->have_dma = true;
++
++ cfg.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
++ cfg.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
++ cfg.slave_id = 11; /* DREQ channel */
++
++ cfg.direction = DMA_MEM_TO_DEV;
++ cfg.src_addr = 0;
++ cfg.dst_addr = host->phys_addr + SDHCI_BUFFER;
++ ret = dmaengine_slave_config(host->dma_chan_tx, &cfg);
++
++ cfg.direction = DMA_DEV_TO_MEM;
++ cfg.src_addr = host->phys_addr + SDHCI_BUFFER;
++ cfg.dst_addr = 0;
++ ret = dmaengine_slave_config(host->dma_chan_rx, &cfg);
++ }
++#endif
++
++
++ mmc->max_segs = 128;
++ mmc->max_req_size = 524288;
++ mmc->max_seg_size = mmc->max_req_size;
++ mmc->max_blk_size = 512;
++ mmc->max_blk_count = 65535;
++
++ /* report supported voltage ranges */
++ mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34;
++
++ tasklet_init(&host->finish_tasklet,
++ bcm2835_mmc_tasklet_finish, (unsigned long)host);
++
++ setup_timer(&host->timer, bcm2835_mmc_timeout_timer, (unsigned long)host);
++ init_waitqueue_head(&host->buf_ready_int);
++
++ bcm2835_mmc_init(host, 0);
++#ifndef CONFIG_OF
++ ret = request_irq(host->irq, bcm2835_mmc_irq, 0 /*IRQF_SHARED*/,
++ mmc_hostname(mmc), host);
++#else
++ ret = request_threaded_irq(host->irq, bcm2835_mmc_irq, bcm2835_mmc_thread_irq,
++ IRQF_SHARED, mmc_hostname(mmc), host);
++#endif
++ if (ret) {
++ pr_err("%s: Failed to request IRQ %d: %d\n",
++ mmc_hostname(mmc), host->irq, ret);
++ goto untasklet;
++ }
++
++ mmiowb();
++ mmc_add_host(mmc);
++
++ pr_info("Load BCM2835 MMC driver\n");
++
++ return 0;
++
++untasklet:
++ tasklet_kill(&host->finish_tasklet);
++
++ return ret;
++}
++
++static int bcm2835_mmc_probe(struct platform_device *pdev)
++{
++ struct device *dev = &pdev->dev;
++#ifdef CONFIG_OF
++ struct device_node *node = dev->of_node;
++ struct clk *clk;
++#endif
++ struct resource *iomem;
++ struct bcm2835_host *host = NULL;
++
++ int ret;
++ struct mmc_host *mmc;
++#if !defined(CONFIG_OF) && !defined(FORCE_PIO)
++ dma_cap_mask_t mask;
++#endif
++
++ iomem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++ if (!iomem) {
++ ret = -ENOMEM;
++ goto err;
++ }
++
++ if (resource_size(iomem) < 0x100)
++ dev_err(&pdev->dev, "Invalid iomem size!\n");
++
++ mmc = mmc_alloc_host(sizeof(struct bcm2835_host), dev);
++ host = mmc_priv(mmc);
++ host->mmc = mmc;
++
++
++ if (IS_ERR(host)) {
++ ret = PTR_ERR(host);
++ goto err;
++ }
++
++ host->phys_addr = iomem->start + BCM2835_VCMMU_SHIFT;
++
++#ifndef CONFIG_OF
++#ifndef FORCE_PIO
++ dma_cap_zero(mask);
++ /* we don't care about the channel, any would work */
++ dma_cap_set(DMA_SLAVE, mask);
++
++ host->dma_chan_tx = dma_request_channel(mask, NULL, NULL);
++ host->dma_chan_rx = dma_request_channel(mask, NULL, NULL);
++#endif
++ host->max_clk = BCM2835_CLOCK_FREQ;
++
++#else
++#ifndef FORCE_PIO
++ host->dma_chan_tx = of_dma_request_slave_channel(node, "tx");
++ host->dma_chan_rx = of_dma_request_slave_channel(node, "rx");
++#endif
++ clk = of_clk_get(node, 0);
++ if (IS_ERR(clk)) {
++ dev_err(dev, "get CLOCK failed\n");
++ ret = PTR_ERR(clk);
++ goto out;
++ }
++ host->max_clk = (clk_get_rate(clk));
++#endif
++ host->irq = platform_get_irq(pdev, 0);
++
++ if (!request_mem_region(iomem->start, resource_size(iomem),
++ mmc_hostname(host->mmc))) {
++ dev_err(&pdev->dev, "cannot request region\n");
++ ret = -EBUSY;
++ goto err_request;
++ }
++
++ host->ioaddr = ioremap(iomem->start, resource_size(iomem));
++ if (!host->ioaddr) {
++ dev_err(&pdev->dev, "failed to remap registers\n");
++ ret = -ENOMEM;
++ goto err_remap;
++ }
++
++ platform_set_drvdata(pdev, host);
++
++
++ if (host->irq <= 0) {
++ dev_err(dev, "get IRQ failed\n");
++ ret = -EINVAL;
++ goto out;
++ }
++
++
++#ifndef CONFIG_OF
++ mmc->caps |= MMC_CAP_4_BIT_DATA;
++#else
++ mmc_of_parse(mmc);
++#endif
++ host->timeout = msecs_to_jiffies(1000);
++ spin_lock_init(&host->lock);
++ mmc->ops = &bcm2835_ops;
++ return bcm2835_mmc_add_host(host);
++
++
++err_remap:
++ release_mem_region(iomem->start, resource_size(iomem));
++err_request:
++ mmc_free_host(host->mmc);
++err:
++ dev_err(&pdev->dev, "%s failed %d\n", __func__, ret);
++ return ret;
++out:
++ if (mmc)
++ mmc_free_host(mmc);
++ return ret;
++}
++
++static int bcm2835_mmc_remove(struct platform_device *pdev)
++{
++ struct bcm2835_host *host = platform_get_drvdata(pdev);
++ struct resource *iomem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++ unsigned long flags;
++ int dead;
++ u32 scratch;
++
++ dead = 0;
++ scratch = bcm2835_mmc_readl(host, SDHCI_INT_STATUS);
++ if (scratch == (u32)-1)
++ dead = 1;
++
++
++ if (dead) {
++ spin_lock_irqsave(&host->lock, flags);
++
++ host->flags |= SDHCI_DEVICE_DEAD;
++
++ if (host->mrq) {
++ pr_err("%s: Controller removed during "
++ " transfer!\n", mmc_hostname(host->mmc));
++
++ host->mrq->cmd->error = -ENOMEDIUM;
++ tasklet_schedule(&host->finish_tasklet);
++ }
++
++ spin_unlock_irqrestore(&host->lock, flags);
++ }
++
++ mmc_remove_host(host->mmc);
++
++ if (!dead)
++ bcm2835_mmc_reset(host, SDHCI_RESET_ALL);
++
++ free_irq(host->irq, host);
++
++ del_timer_sync(&host->timer);
++
++ tasklet_kill(&host->finish_tasklet);
++
++ iounmap(host->ioaddr);
++ release_mem_region(iomem->start, resource_size(iomem));
++ mmc_free_host(host->mmc);
++ platform_set_drvdata(pdev, NULL);
++
++ return 0;
++}
++
++
++static const struct of_device_id bcm2835_mmc_match[] = {
++ { .compatible = "brcm,bcm2835-mmc" },
++ { }
++};
++MODULE_DEVICE_TABLE(of, bcm2835_mmc_match);
++
++
++
++static struct platform_driver bcm2835_mmc_driver = {
++ .probe = bcm2835_mmc_probe,
++ .remove = bcm2835_mmc_remove,
++ .driver = {
++ .name = DRIVER_NAME,
++ .owner = THIS_MODULE,
++ .of_match_table = bcm2835_mmc_match,
++ },
++};
++module_platform_driver(bcm2835_mmc_driver);
++
++MODULE_ALIAS("platform:mmc-bcm2835");
++MODULE_DESCRIPTION("BCM2835 SDHCI driver");
++MODULE_LICENSE("GPL v2");
++MODULE_AUTHOR("Gellert Weisz");
+diff -Nur linux-3.12.33/drivers/mmc/host/Kconfig linux-3.12.33-rpi/drivers/mmc/host/Kconfig
+--- linux-3.12.33/drivers/mmc/host/Kconfig 2014-11-15 06:28:07.000000000 -0600
++++ linux-3.12.33-rpi/drivers/mmc/host/Kconfig 2014-12-03 19:13:38.232418001 -0600
@@ -260,6 +260,27 @@
If you have a controller with this interface, say Y or M here.
@@ -30794,21 +38884,58 @@ diff -Nur linux-3.12.26.orig/drivers/mmc/host/Kconfig linux-3.12.26/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.26.orig/drivers/mmc/host/Makefile linux-3.12.26/drivers/mmc/host/Makefile
---- linux-3.12.26.orig/drivers/mmc/host/Makefile 2014-07-30 18:02:44.000000000 +0200
-+++ linux-3.12.26/drivers/mmc/host/Makefile 2014-08-06 16:50:14.569962904 +0200
-@@ -15,6 +15,7 @@
+@@ -271,6 +292,35 @@
+
+ If unsure, say N.
+
++config MMC_BCM2835
++ tristate "MMC support on BCM2835"
++ depends on MACH_BCM2708
++ help
++ This selects the MMC Interface on BCM2835.
++
++ If you have a controller with this interface, say Y or M here.
++
++ If unsure, say N.
++
++config MMC_BCM2835_DMA
++ bool "DMA support on BCM2835 Arasan controller"
++ depends on MMC_BCM2835
++ help
++ Enable DMA support on the Arasan SDHCI controller in Broadcom 2708
++ based chips.
++
++ If unsure, say N.
++
++config MMC_BCM2835_PIO_DMA_BARRIER
++ int "Block count limit for PIO transfers"
++ depends on MMC_BCM2835 && MMC_BCM2835_DMA
++ range 0 256
++ default 2
++ help
++ The inclusive limit in bytes under which PIO will be used instead of DMA
++
++ If unsure, say 2 here.
++
+ config MMC_OMAP
+ tristate "TI OMAP Multimedia Card Interface support"
+ depends on ARCH_OMAP
+diff -Nur linux-3.12.33/drivers/mmc/host/Makefile linux-3.12.33-rpi/drivers/mmc/host/Makefile
+--- linux-3.12.33/drivers/mmc/host/Makefile 2014-11-15 06:28:07.000000000 -0600
++++ linux-3.12.33-rpi/drivers/mmc/host/Makefile 2014-12-03 19:13:38.232418001 -0600
+@@ -15,6 +15,8 @@
obj-$(CONFIG_MMC_SDHCI_S3C) += sdhci-s3c.o
obj-$(CONFIG_MMC_SDHCI_SIRF) += sdhci-sirf.o
obj-$(CONFIG_MMC_SDHCI_SPEAR) += sdhci-spear.o
+obj-$(CONFIG_MMC_SDHCI_BCM2708) += sdhci-bcm2708.o
++obj-$(CONFIG_MMC_BCM2835) += bcm2835-mmc.o
obj-$(CONFIG_MMC_WBSD) += wbsd.o
obj-$(CONFIG_MMC_AU1X) += au1xmmc.o
obj-$(CONFIG_MMC_OMAP) += omap.o
-diff -Nur linux-3.12.26.orig/drivers/mmc/host/sdhci-bcm2708.c linux-3.12.26/drivers/mmc/host/sdhci-bcm2708.c
---- linux-3.12.26.orig/drivers/mmc/host/sdhci-bcm2708.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-3.12.26/drivers/mmc/host/sdhci-bcm2708.c 2014-08-06 16:50:14.569962904 +0200
-@@ -0,0 +1,1410 @@
+diff -Nur linux-3.12.33/drivers/mmc/host/sdhci-bcm2708.c linux-3.12.33-rpi/drivers/mmc/host/sdhci-bcm2708.c
+--- linux-3.12.33/drivers/mmc/host/sdhci-bcm2708.c 1969-12-31 18:00:00.000000000 -0600
++++ linux-3.12.33-rpi/drivers/mmc/host/sdhci-bcm2708.c 2014-12-03 19:13:38.240418001 -0600
+@@ -0,0 +1,1433 @@
+/*
+ * sdhci-bcm2708.c Support for SDHCI device on BCM2708
+ * Copyright (c) 2010 Broadcom
@@ -30880,6 +39007,9 @@ diff -Nur linux-3.12.26.orig/drivers/mmc/host/sdhci-bcm2708.c linux-3.12.26/driv
+#define DMA_SDHCI_BASE 0x7e300000 /* EMMC register block on Videocore */
+#define DMA_SDHCI_BUFFER (DMA_SDHCI_BASE + SDHCI_BUFFER)
+
++#define MAX_LITE_TRANSFER 32768
++#define MAX_NORMAL_TRANSFER 1073741824
++
+#define BCM2708_SDHCI_SLEEP_TIMEOUT 1000 /* msecs */
+
+/* Mhz clock that the EMMC core is running at. Should match the platform clockman settings */
@@ -31257,29 +39387,39 @@ diff -Nur linux-3.12.26.orig/drivers/mmc/host/sdhci-bcm2708.c linux-3.12.26/driv
+ dma_addr_t dma_addr, unsigned len,
+ int /*bool*/ is_last)
+{
-+ struct bcm2708_dma_cb *cb = &host->cb_base[ix];
-+ unsigned char dmawaits = host->dma_waits;
-+
-+ cb->info = BCM2708_DMA_PER_MAP(BCM2708_DMA_DREQ_EMMC) |
-+ BCM2708_DMA_WAITS(dmawaits) |
-+ BCM2708_DMA_S_DREQ |
-+ BCM2708_DMA_D_WIDTH |
-+ BCM2708_DMA_D_INC;
-+ cb->src = DMA_SDHCI_BUFFER; /* DATA register DMA address */
-+ cb->dst = dma_addr;
-+ cb->length = len;
-+ cb->stride = 0;
++ struct bcm2708_dma_cb *cb;
++ unsigned char dmawaits = host->dma_waits;
++ unsigned i, max_size;
+
-+ if (is_last) {
-+ cb->info |= BCM2708_DMA_INT_EN |
-+ BCM2708_DMA_WAIT_RESP;
-+ cb->next = 0;
-+ } else
-+ cb->next = host->cb_handle +
-+ (ix+1)*sizeof(struct bcm2708_dma_cb);
++ if (host->dma_chan >= 8) /* we have a LITE channel */
++ max_size = MAX_LITE_TRANSFER;
++ else
++ max_size = MAX_NORMAL_TRANSFER;
++
++ for (i = 0; i < len; i += max_size) {
++ cb = &host->cb_base[ix+i/max_size];
++
++ cb->info = BCM2708_DMA_PER_MAP(BCM2708_DMA_DREQ_EMMC) |
++ BCM2708_DMA_WAITS(dmawaits) |
++ BCM2708_DMA_WAIT_RESP |
++ BCM2708_DMA_S_DREQ |
++ BCM2708_DMA_D_WIDTH |
++ BCM2708_DMA_D_INC;
++ cb->src = DMA_SDHCI_BUFFER; /* DATA register DMA address */
++ cb->dst = dma_addr + (dma_addr_t)i;
++ cb->length = min(len-i, max_size);
++ cb->stride = 0;
++
++ if (is_last && len-i <= max_size) {
++ cb->info |= BCM2708_DMA_INT_EN;
++ cb->next = 0;
++ } else
++ cb->next = host->cb_handle +
++ (ix+1 + i/max_size)*sizeof(struct bcm2708_dma_cb);
+
-+ cb->pad[0] = 0;
-+ cb->pad[1] = 0;
++ cb->pad[0] = 0;
++ cb->pad[1] = 0;
++ }
+}
+
+static void schci_bcm2708_cb_write(struct sdhci_bcm2708_priv *host,
@@ -31288,30 +39428,42 @@ diff -Nur linux-3.12.26.orig/drivers/mmc/host/sdhci-bcm2708.c linux-3.12.26/driv
+ int /*bool*/ is_last)
+{
+ struct bcm2708_dma_cb *cb = &host->cb_base[ix];
-+ unsigned char dmawaits = host->dma_waits;
++ unsigned char dmawaits = host->dma_waits;
++ unsigned i, max_size;
+
-+ /* We can make arbitrarily large writes as long as we specify DREQ to
-+ pace the delivery of bytes to the Arasan hardware */
-+ cb->info = BCM2708_DMA_PER_MAP(BCM2708_DMA_DREQ_EMMC) |
-+ BCM2708_DMA_WAITS(dmawaits) |
-+ BCM2708_DMA_D_DREQ |
-+ BCM2708_DMA_S_WIDTH |
-+ BCM2708_DMA_S_INC;
-+ cb->src = dma_addr;
-+ cb->dst = DMA_SDHCI_BUFFER; /* DATA register DMA address */
-+ cb->length = len;
-+ cb->stride = 0;
++ if (host->dma_chan >= 8) /* we have a LITE channel */
++ max_size = MAX_LITE_TRANSFER;
++ else
++ max_size = MAX_NORMAL_TRANSFER;
+
-+ if (is_last) {
-+ cb->info |= BCM2708_DMA_INT_EN |
-+ BCM2708_DMA_WAIT_RESP;
-+ cb->next = 0;
-+ } else
-+ cb->next = host->cb_handle +
-+ (ix+1)*sizeof(struct bcm2708_dma_cb);
++ /* We can make arbitrarily large writes as long as we specify DREQ to
++ pace the delivery of bytes to the Arasan hardware. However we need
++ to take care when using LITE channels */
++
++ for (i = 0; i < len; i += max_size) {
++ cb = &host->cb_base[ix+i/max_size];
++
++ cb->info = BCM2708_DMA_PER_MAP(BCM2708_DMA_DREQ_EMMC) |
++ BCM2708_DMA_WAITS(dmawaits) |
++ BCM2708_DMA_WAIT_RESP |
++ BCM2708_DMA_D_DREQ |
++ BCM2708_DMA_S_WIDTH |
++ BCM2708_DMA_S_INC;
++ cb->src = dma_addr + (dma_addr_t)i;
++ cb->dst = DMA_SDHCI_BUFFER; /* DATA register DMA address */
++ cb->length = min(len-i, max_size);
++ cb->stride = 0;
++
++ if (is_last && len-i <= max_size) {
++ cb->info |= BCM2708_DMA_INT_EN;
++ cb->next = 0;
++ } else
++ cb->next = host->cb_handle +
++ (ix+1 + i/max_size)*sizeof(struct bcm2708_dma_cb);
+
-+ cb->pad[0] = 0;
-+ cb->pad[1] = 0;
++ cb->pad[0] = 0;
++ cb->pad[1] = 0;
++ }
+}
+
+
@@ -32217,11 +40369,9 @@ diff -Nur linux-3.12.26.orig/drivers/mmc/host/sdhci-bcm2708.c linux-3.12.26/driv
+MODULE_PARM_DESC(spurious_crc_acmd51, "Use the spurious crc quirk for reading SCR (ACMD51)");
+MODULE_PARM_DESC(enable_llm, "Enable low-latency mode");
+MODULE_PARM_DESC(extra_messages, "Enable more sdcard warning messages");
-+
-+
-diff -Nur linux-3.12.26.orig/drivers/mmc/host/sdhci.c linux-3.12.26/drivers/mmc/host/sdhci.c
---- linux-3.12.26.orig/drivers/mmc/host/sdhci.c 2014-07-30 18:02:44.000000000 +0200
-+++ linux-3.12.26/drivers/mmc/host/sdhci.c 2014-08-06 16:50:14.569962904 +0200
+diff -Nur linux-3.12.33/drivers/mmc/host/sdhci.c linux-3.12.33-rpi/drivers/mmc/host/sdhci.c
+--- linux-3.12.33/drivers/mmc/host/sdhci.c 2014-11-15 06:28:07.000000000 -0600
++++ linux-3.12.33-rpi/drivers/mmc/host/sdhci.c 2014-12-03 19:13:38.244418001 -0600
@@ -28,6 +28,7 @@
#include <linux/mmc/mmc.h>
#include <linux/mmc/host.h>
@@ -33063,9 +41213,9 @@ diff -Nur linux-3.12.26.orig/drivers/mmc/host/sdhci.c linux-3.12.26/drivers/mmc/
}
sdhci_disable_card_detection(host);
-diff -Nur linux-3.12.26.orig/drivers/mmc/host/sdhci.h linux-3.12.26/drivers/mmc/host/sdhci.h
---- linux-3.12.26.orig/drivers/mmc/host/sdhci.h 2014-07-30 18:02:44.000000000 +0200
-+++ linux-3.12.26/drivers/mmc/host/sdhci.h 2014-08-06 16:50:14.581962998 +0200
+diff -Nur linux-3.12.33/drivers/mmc/host/sdhci.h linux-3.12.33-rpi/drivers/mmc/host/sdhci.h
+--- linux-3.12.33/drivers/mmc/host/sdhci.h 2014-11-15 06:28:07.000000000 -0600
++++ linux-3.12.33-rpi/drivers/mmc/host/sdhci.h 2014-12-03 19:13:38.244418001 -0600
@@ -289,6 +289,18 @@
void (*platform_reset_enter)(struct sdhci_host *host, u8 mask);
void (*platform_reset_exit)(struct sdhci_host *host, u8 mask);
@@ -33124,234 +41274,9 @@ diff -Nur linux-3.12.26.orig/drivers/mmc/host/sdhci.h linux-3.12.26/drivers/mmc/
+
+
#endif /* __SDHCI_HW_H */
-diff -Nur linux-3.12.26.orig/drivers/net/bonding/bond_alb.c linux-3.12.26/drivers/net/bonding/bond_alb.c
---- linux-3.12.26.orig/drivers/net/bonding/bond_alb.c 2014-07-30 18:02:44.000000000 +0200
-+++ linux-3.12.26/drivers/net/bonding/bond_alb.c 2014-08-06 16:50:14.597963124 +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.26.orig/drivers/net/ethernet/broadcom/bnx2.c linux-3.12.26/drivers/net/ethernet/broadcom/bnx2.c
---- linux-3.12.26.orig/drivers/net/ethernet/broadcom/bnx2.c 2014-07-30 18:02:44.000000000 +0200
-+++ linux-3.12.26/drivers/net/ethernet/broadcom/bnx2.c 2014-08-06 16:50:14.621963313 +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.26.orig/drivers/net/ethernet/broadcom/bnx2.h linux-3.12.26/drivers/net/ethernet/broadcom/bnx2.h
---- linux-3.12.26.orig/drivers/net/ethernet/broadcom/bnx2.h 2014-07-30 18:02:44.000000000 +0200
-+++ linux-3.12.26/drivers/net/ethernet/broadcom/bnx2.h 2014-08-06 16:50:14.633963407 +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.26.orig/drivers/net/ethernet/broadcom/tg3.c linux-3.12.26/drivers/net/ethernet/broadcom/tg3.c
---- linux-3.12.26.orig/drivers/net/ethernet/broadcom/tg3.c 2014-07-30 18:02:44.000000000 +0200
-+++ linux-3.12.26/drivers/net/ethernet/broadcom/tg3.c 2014-08-06 16:50:14.645963501 +0200
-@@ -17482,6 +17482,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.
- */
-@@ -17513,8 +17515,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.26.orig/drivers/net/ethernet/freescale/fec_main.c linux-3.12.26/drivers/net/ethernet/freescale/fec_main.c
---- linux-3.12.26.orig/drivers/net/ethernet/freescale/fec_main.c 2014-07-30 18:02:44.000000000 +0200
-+++ linux-3.12.26/drivers/net/ethernet/freescale/fec_main.c 2014-08-06 16:50:14.645963501 +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.26.orig/drivers/net/ethernet/micrel/ks8851.c linux-3.12.26/drivers/net/ethernet/micrel/ks8851.c
---- linux-3.12.26.orig/drivers/net/ethernet/micrel/ks8851.c 2014-07-30 18:02:44.000000000 +0200
-+++ linux-3.12.26/drivers/net/ethernet/micrel/ks8851.c 2014-08-06 16:50:14.657963595 +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.26.orig/drivers/net/usb/smsc95xx.c linux-3.12.26/drivers/net/usb/smsc95xx.c
---- linux-3.12.26.orig/drivers/net/usb/smsc95xx.c 2014-07-30 18:02:44.000000000 +0200
-+++ linux-3.12.26/drivers/net/usb/smsc95xx.c 2014-08-06 16:50:14.681963784 +0200
+diff -Nur linux-3.12.33/drivers/net/usb/smsc95xx.c linux-3.12.33-rpi/drivers/net/usb/smsc95xx.c
+--- linux-3.12.33/drivers/net/usb/smsc95xx.c 2014-11-15 06:28:07.000000000 -0600
++++ linux-3.12.33-rpi/drivers/net/usb/smsc95xx.c 2014-12-03 19:13:38.600418001 -0600
@@ -61,6 +61,7 @@
#define SUSPEND_SUSPEND3 (0x08)
#define SUSPEND_ALLMODES (SUSPEND_SUSPEND0 | SUSPEND_SUSPEND1 | \
@@ -33431,448 +41356,9 @@ diff -Nur linux-3.12.26.orig/drivers/net/usb/smsc95xx.c linux-3.12.26/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.26.orig/drivers/net/usb/usbnet.c linux-3.12.26/drivers/net/usb/usbnet.c
---- linux-3.12.26.orig/drivers/net/usb/usbnet.c 2014-07-30 18:02:44.000000000 +0200
-+++ linux-3.12.26/drivers/net/usb/usbnet.c 2014-08-06 16:50:14.685963816 +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.26.orig/drivers/net/vxlan.c linux-3.12.26/drivers/net/vxlan.c
---- linux-3.12.26.orig/drivers/net/vxlan.c 2014-07-30 18:02:44.000000000 +0200
-+++ linux-3.12.26/drivers/net/vxlan.c 2014-08-06 16:50:14.709964003 +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.26.orig/drivers/net/xen-netback/common.h linux-3.12.26/drivers/net/xen-netback/common.h
---- linux-3.12.26.orig/drivers/net/xen-netback/common.h 2014-07-30 18:02:44.000000000 +0200
-+++ linux-3.12.26/drivers/net/xen-netback/common.h 2014-08-06 16:50:14.709964003 +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.26.orig/drivers/net/xen-netback/interface.c linux-3.12.26/drivers/net/xen-netback/interface.c
---- linux-3.12.26.orig/drivers/net/xen-netback/interface.c 2014-07-30 18:02:44.000000000 +0200
-+++ linux-3.12.26/drivers/net/xen-netback/interface.c 2014-08-06 16:50:14.709964003 +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.26.orig/drivers/net/xen-netback/netback.c linux-3.12.26/drivers/net/xen-netback/netback.c
---- linux-3.12.26.orig/drivers/net/xen-netback/netback.c 2014-07-30 18:02:44.000000000 +0200
-+++ linux-3.12.26/drivers/net/xen-netback/netback.c 2014-08-06 16:50:14.709964003 +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.26.orig/drivers/pci/host/pci-mvebu.c linux-3.12.26/drivers/pci/host/pci-mvebu.c
---- linux-3.12.26.orig/drivers/pci/host/pci-mvebu.c 2014-07-30 18:02:44.000000000 +0200
-+++ linux-3.12.26/drivers/pci/host/pci-mvebu.c 2014-08-06 16:50:14.709964003 +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.26.orig/drivers/spi/Kconfig linux-3.12.26/drivers/spi/Kconfig
---- linux-3.12.26.orig/drivers/spi/Kconfig 2014-07-30 18:02:44.000000000 +0200
-+++ linux-3.12.26/drivers/spi/Kconfig 2014-08-06 16:50:14.713964035 +0200
+diff -Nur linux-3.12.33/drivers/spi/Kconfig linux-3.12.33-rpi/drivers/spi/Kconfig
+--- linux-3.12.33/drivers/spi/Kconfig 2014-11-15 06:28:07.000000000 -0600
++++ linux-3.12.33-rpi/drivers/spi/Kconfig 2014-12-03 19:13:39.436418001 -0600
@@ -85,6 +85,14 @@
is for the regular SPI controller. Slave mode operation is not also
not supported.
@@ -33888,9 +41374,9 @@ diff -Nur linux-3.12.26.orig/drivers/spi/Kconfig linux-3.12.26/drivers/spi/Kconf
config SPI_BFIN5XX
tristate "SPI controller driver for ADI Blackfin5xx"
depends on BLACKFIN && !BF60x
-diff -Nur linux-3.12.26.orig/drivers/spi/Makefile linux-3.12.26/drivers/spi/Makefile
---- linux-3.12.26.orig/drivers/spi/Makefile 2014-07-30 18:02:44.000000000 +0200
-+++ linux-3.12.26/drivers/spi/Makefile 2014-08-06 16:50:14.713964035 +0200
+diff -Nur linux-3.12.33/drivers/spi/Makefile linux-3.12.33-rpi/drivers/spi/Makefile
+--- linux-3.12.33/drivers/spi/Makefile 2014-11-15 06:28:07.000000000 -0600
++++ linux-3.12.33-rpi/drivers/spi/Makefile 2014-12-03 19:13:39.436418001 -0600
@@ -18,6 +18,7 @@
obj-$(CONFIG_SPI_BCM63XX) += spi-bcm63xx.o
obj-$(CONFIG_SPI_BFIN5XX) += spi-bfin5xx.o
@@ -33899,9 +41385,9 @@ diff -Nur linux-3.12.26.orig/drivers/spi/Makefile linux-3.12.26/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.26.orig/drivers/spi/spi-bcm2708.c linux-3.12.26/drivers/spi/spi-bcm2708.c
---- linux-3.12.26.orig/drivers/spi/spi-bcm2708.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-3.12.26/drivers/spi/spi-bcm2708.c 2014-08-06 16:50:14.713964035 +0200
+diff -Nur linux-3.12.33/drivers/spi/spi-bcm2708.c linux-3.12.33-rpi/drivers/spi/spi-bcm2708.c
+--- linux-3.12.33/drivers/spi/spi-bcm2708.c 1969-12-31 18:00:00.000000000 -0600
++++ linux-3.12.33-rpi/drivers/spi/spi-bcm2708.c 2014-12-03 19:13:39.436418001 -0600
@@ -0,0 +1,626 @@
+/*
+ * Driver for Broadcom BCM2708 SPI Controllers
@@ -34013,7 +41499,7 @@ diff -Nur linux-3.12.26.orig/drivers/spi/spi-bcm2708.c linux-3.12.26/drivers/spi
+#define SET_GPIO_ALT(g,a) *(gpio+(((g)/10))) |= (((a)<=3?(a)+4:(a)==4?3:2)<<(((g)%10)*3))
+
+ int pin;
-+ u32 *gpio = ioremap(0x20200000, SZ_16K);
++ u32 *gpio = ioremap(GPIO_BASE, SZ_16K);
+
+ /* SPI is on GPIO 7..11 */
+ for (pin = 7; pin <= 11; pin++) {
@@ -34529,9 +42015,9 @@ diff -Nur linux-3.12.26.orig/drivers/spi/spi-bcm2708.c linux-3.12.26/drivers/spi
+MODULE_AUTHOR("Chris Boot <bootc@bootc.net>");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:" DRV_NAME);
-diff -Nur linux-3.12.26.orig/drivers/staging/media/lirc/Kconfig linux-3.12.26/drivers/staging/media/lirc/Kconfig
---- linux-3.12.26.orig/drivers/staging/media/lirc/Kconfig 2014-07-30 18:02:44.000000000 +0200
-+++ linux-3.12.26/drivers/staging/media/lirc/Kconfig 2014-08-06 16:50:14.713964035 +0200
+diff -Nur linux-3.12.33/drivers/staging/media/lirc/Kconfig linux-3.12.33-rpi/drivers/staging/media/lirc/Kconfig
+--- linux-3.12.33/drivers/staging/media/lirc/Kconfig 2014-11-15 06:28:07.000000000 -0600
++++ linux-3.12.33-rpi/drivers/staging/media/lirc/Kconfig 2014-12-03 19:13:39.736418001 -0600
@@ -38,6 +38,12 @@
help
Driver for Homebrew Parallel Port Receivers
@@ -34545,10 +42031,10 @@ diff -Nur linux-3.12.26.orig/drivers/staging/media/lirc/Kconfig linux-3.12.26/dr
config LIRC_SASEM
tristate "Sasem USB IR Remote"
depends on LIRC && USB
-diff -Nur linux-3.12.26.orig/drivers/staging/media/lirc/lirc_rpi.c linux-3.12.26/drivers/staging/media/lirc/lirc_rpi.c
---- linux-3.12.26.orig/drivers/staging/media/lirc/lirc_rpi.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-3.12.26/drivers/staging/media/lirc/lirc_rpi.c 2014-08-06 16:50:14.725964129 +0200
-@@ -0,0 +1,693 @@
+diff -Nur linux-3.12.33/drivers/staging/media/lirc/lirc_rpi.c linux-3.12.33-rpi/drivers/staging/media/lirc/lirc_rpi.c
+--- linux-3.12.33/drivers/staging/media/lirc/lirc_rpi.c 1969-12-31 18:00:00.000000000 -0600
++++ linux-3.12.33-rpi/drivers/staging/media/lirc/lirc_rpi.c 2014-12-03 19:13:39.736418001 -0600
+@@ -0,0 +1,689 @@
+/*
+ * lirc_rpi.c
+ *
@@ -34581,6 +42067,7 @@ diff -Nur linux-3.12.26.orig/drivers/staging/media/lirc/lirc_rpi.c linux-3.12.26
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/time.h>
++#include <linux/timex.h>
+#include <linux/string.h>
+#include <linux/delay.h>
+#include <linux/platform_device.h>
@@ -34588,11 +42075,14 @@ diff -Nur linux-3.12.26.orig/drivers/staging/media/lirc/lirc_rpi.c linux-3.12.26
+#include <linux/spinlock.h>
+#include <media/lirc.h>
+#include <media/lirc_dev.h>
++#include <mach/gpio.h>
+#include <linux/gpio.h>
+
++#include <linux/platform_data/bcm2708.h>
++
+#define LIRC_DRIVER_NAME "lirc_rpi"
+#define RBUF_LEN 256
-+#define LIRC_TRANSMITTER_LATENCY 256
++#define LIRC_TRANSMITTER_LATENCY 50
+
+#ifndef MAX_UDELAY_MS
+#define MAX_UDELAY_US 5000
@@ -34611,6 +42101,8 @@ diff -Nur linux-3.12.26.orig/drivers/staging/media/lirc/lirc_rpi.c linux-3.12.26
+
+/* set the default GPIO input pin */
+static int gpio_in_pin = 18;
++/* set the default pull behaviour for input pin */
++static int gpio_in_pull = BCM2708_PULL_DOWN;
+/* set the default GPIO output pin */
+static int gpio_out_pin = 17;
+/* enable debugging messages */
@@ -34631,9 +42123,6 @@ diff -Nur linux-3.12.26.orig/drivers/staging/media/lirc/lirc_rpi.c linux-3.12.26
+static void send_space(long length);
+static void lirc_rpi_exit(void);
+
-+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 };
+static struct lirc_buffer rbuf;
@@ -34658,19 +42147,15 @@ diff -Nur linux-3.12.26.orig/drivers/staging/media/lirc/lirc_rpi.c linux-3.12.26
+static int init_timing_params(unsigned int new_duty_cycle,
+ unsigned int new_freq)
+{
-+ /*
-+ * period, pulse/space width are kept with 8 binary places -
-+ * IE multiplied by 256.
-+ */
-+ if (256 * 1000000L / new_freq * new_duty_cycle / 100 <=
++ if (1000 * 1000000L / new_freq * new_duty_cycle / 100 <=
+ LIRC_TRANSMITTER_LATENCY)
+ return -EINVAL;
-+ if (256 * 1000000L / new_freq * (100 - new_duty_cycle) / 100 <=
++ if (1000 * 1000000L / new_freq * (100 - new_duty_cycle) / 100 <=
+ LIRC_TRANSMITTER_LATENCY)
+ return -EINVAL;
+ duty_cycle = new_duty_cycle;
+ freq = new_freq;
-+ period = 256 * 1000000L / freq;
++ period = 1000 * 1000000L / freq;
+ pulse_width = period * duty_cycle / 100;
+ space_width = period - pulse_width;
+ dprintk("in init_timing_params, freq=%d pulse=%ld, "
@@ -34681,11 +42166,14 @@ diff -Nur linux-3.12.26.orig/drivers/staging/media/lirc/lirc_rpi.c linux-3.12.26
+static long send_pulse_softcarrier(unsigned long length)
+{
+ int flag;
-+ unsigned long actual, target, d;
++ unsigned long actual, target;
++ unsigned long actual_us, initial_us, target_us;
+
-+ length <<= 8;
++ length *= 1000;
+
+ actual = 0; target = 0; flag = 0;
++ read_current_timer(&actual_us);
++
+ while (actual < length) {
+ if (flag) {
+ gpiochip->set(gpiochip, gpio_out_pin, invert);
@@ -34694,17 +42182,19 @@ diff -Nur linux-3.12.26.orig/drivers/staging/media/lirc/lirc_rpi.c linux-3.12.26
+ gpiochip->set(gpiochip, gpio_out_pin, !invert);
+ target += pulse_width;
+ }
-+ d = (target - actual -
-+ LIRC_TRANSMITTER_LATENCY + 128) >> 8;
++ initial_us = actual_us;
++ target_us = actual_us + (target - actual) / 1000;
+ /*
+ * Note - we've checked in ioctl that the pulse/space
+ * widths are big enough so that d is > 0
+ */
-+ udelay(d);
-+ actual += (d << 8) + LIRC_TRANSMITTER_LATENCY;
++ if ((int)(target_us - actual_us) > 0)
++ udelay(target_us - actual_us);
++ read_current_timer(&actual_us);
++ actual += (actual_us - initial_us) * 1000;
+ flag = !flag;
+ }
-+ return (actual-length) >> 8;
++ return (actual-length) / 1000;
+}
+
+static long send_pulse(unsigned long length)
@@ -34869,6 +42359,7 @@ diff -Nur linux-3.12.26.orig/drivers/staging/media/lirc/lirc_rpi.c linux-3.12.26
+ goto exit_gpio_free_out_pin;
+ }
+
++ bcm2708_gpio_setpull(gpiochip, gpio_in_pin, gpio_in_pull);
+ gpiochip->direction_input(gpiochip, gpio_in_pin);
+ gpiochip->direction_output(gpiochip, gpio_out_pin, 1);
+ gpiochip->set(gpiochip, gpio_out_pin, invert);
@@ -35148,24 +42639,13 @@ diff -Nur linux-3.12.26.orig/drivers/staging/media/lirc/lirc_rpi.c linux-3.12.26
+
+static int __init lirc_rpi_init_module(void)
+{
-+ int result, i;
++ int result;
+
+ result = lirc_rpi_init();
+ if (result)
+ return result;
+
-+ /* check if the module received valid gpio pin numbers */
-+ result = 0;
-+ if (gpio_in_pin != gpio_out_pin) {
-+ for(i = 0; (i < ARRAY_SIZE(valid_gpio_pins)) && (result != 2); i++) {
-+ if (gpio_in_pin == valid_gpio_pins[i] ||
-+ gpio_out_pin == valid_gpio_pins[i]) {
-+ result++;
-+ }
-+ }
-+ }
-+
-+ if (result != 2) {
++ if (gpio_in_pin >= BCM2708_NR_GPIOS || gpio_out_pin >= BCM2708_NR_GPIOS) {
+ result = -EINVAL;
+ printk(KERN_ERR LIRC_DRIVER_NAME
+ ": invalid GPIO pin(s) specified!\n");
@@ -35222,13 +42702,15 @@ diff -Nur linux-3.12.26.orig/drivers/staging/media/lirc/lirc_rpi.c linux-3.12.26
+
+module_param(gpio_out_pin, int, S_IRUGO);
+MODULE_PARM_DESC(gpio_out_pin, "GPIO output/transmitter pin number of the BCM"
-+ " processor. Valid pin numbers are: 0, 1, 4, 8, 7, 9, 10, 11,"
-+ " 14, 15, 17, 18, 21, 22, 23, 24, 25, default 17");
++ " processor. (default 17");
+
+module_param(gpio_in_pin, int, S_IRUGO);
+MODULE_PARM_DESC(gpio_in_pin, "GPIO input pin number of the BCM processor."
-+ " Valid pin numbers are: 0, 1, 4, 8, 7, 9, 10, 11, 14, 15,"
-+ " 17, 18, 21, 22, 23, 24, 25, default 18");
++ " (default 18");
++
++module_param(gpio_in_pull, int, S_IRUGO);
++MODULE_PARM_DESC(gpio_in_pull, "GPIO input pin pull configuration."
++ " (0 = off, 1 = up, 2 = down, default down)");
+
+module_param(sense, int, S_IRUGO);
+MODULE_PARM_DESC(sense, "Override autodetection of IR receiver circuit"
@@ -35242,9 +42724,9 @@ diff -Nur linux-3.12.26.orig/drivers/staging/media/lirc/lirc_rpi.c linux-3.12.26
+
+module_param(debug, bool, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(debug, "Enable debugging messages");
-diff -Nur linux-3.12.26.orig/drivers/staging/media/lirc/Makefile linux-3.12.26/drivers/staging/media/lirc/Makefile
---- linux-3.12.26.orig/drivers/staging/media/lirc/Makefile 2014-07-30 18:02:44.000000000 +0200
-+++ linux-3.12.26/drivers/staging/media/lirc/Makefile 2014-08-06 16:50:14.729964161 +0200
+diff -Nur linux-3.12.33/drivers/staging/media/lirc/Makefile linux-3.12.33-rpi/drivers/staging/media/lirc/Makefile
+--- linux-3.12.33/drivers/staging/media/lirc/Makefile 2014-11-15 06:28:07.000000000 -0600
++++ linux-3.12.33-rpi/drivers/staging/media/lirc/Makefile 2014-12-03 19:13:39.736418001 -0600
@@ -7,6 +7,7 @@
obj-$(CONFIG_LIRC_IGORPLUGUSB) += lirc_igorplugusb.o
obj-$(CONFIG_LIRC_IMON) += lirc_imon.o
@@ -35253,9 +42735,9 @@ diff -Nur linux-3.12.26.orig/drivers/staging/media/lirc/Makefile linux-3.12.26/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.26.orig/drivers/thermal/bcm2835-thermal.c linux-3.12.26/drivers/thermal/bcm2835-thermal.c
---- linux-3.12.26.orig/drivers/thermal/bcm2835-thermal.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-3.12.26/drivers/thermal/bcm2835-thermal.c 2014-08-06 16:50:14.729964161 +0200
+diff -Nur linux-3.12.33/drivers/thermal/bcm2835-thermal.c linux-3.12.33-rpi/drivers/thermal/bcm2835-thermal.c
+--- linux-3.12.33/drivers/thermal/bcm2835-thermal.c 1969-12-31 18:00:00.000000000 -0600
++++ linux-3.12.33-rpi/drivers/thermal/bcm2835-thermal.c 2014-12-03 19:13:40.136418001 -0600
@@ -0,0 +1,184 @@
+/*****************************************************************************
+* Copyright 2011 Broadcom Corporation. All rights reserved.
@@ -35441,9 +42923,9 @@ diff -Nur linux-3.12.26.orig/drivers/thermal/bcm2835-thermal.c linux-3.12.26/dri
+MODULE_DESCRIPTION("Thermal driver for bcm2835 chip");
+
+module_platform_driver(bcm2835_thermal_driver);
-diff -Nur linux-3.12.26.orig/drivers/thermal/Kconfig linux-3.12.26/drivers/thermal/Kconfig
---- linux-3.12.26.orig/drivers/thermal/Kconfig 2014-07-30 18:02:44.000000000 +0200
-+++ linux-3.12.26/drivers/thermal/Kconfig 2014-08-06 16:50:14.729964161 +0200
+diff -Nur linux-3.12.33/drivers/thermal/Kconfig linux-3.12.33-rpi/drivers/thermal/Kconfig
+--- linux-3.12.33/drivers/thermal/Kconfig 2014-11-15 06:28:07.000000000 -0600
++++ linux-3.12.33-rpi/drivers/thermal/Kconfig 2014-12-03 19:13:40.136418001 -0600
@@ -181,6 +181,12 @@
enforce idle time which results in more package C-state residency. The
user interface is exposed via generic thermal framework.
@@ -35457,9 +42939,9 @@ diff -Nur linux-3.12.26.orig/drivers/thermal/Kconfig linux-3.12.26/drivers/therm
config X86_PKG_TEMP_THERMAL
tristate "X86 package temperature thermal driver"
depends on X86_THERMAL_VECTOR
-diff -Nur linux-3.12.26.orig/drivers/thermal/Makefile linux-3.12.26/drivers/thermal/Makefile
---- linux-3.12.26.orig/drivers/thermal/Makefile 2014-07-30 18:02:44.000000000 +0200
-+++ linux-3.12.26/drivers/thermal/Makefile 2014-08-06 16:50:14.729964161 +0200
+diff -Nur linux-3.12.33/drivers/thermal/Makefile linux-3.12.33-rpi/drivers/thermal/Makefile
+--- linux-3.12.33/drivers/thermal/Makefile 2014-11-15 06:28:07.000000000 -0600
++++ linux-3.12.33-rpi/drivers/thermal/Makefile 2014-12-03 19:13:40.136418001 -0600
@@ -27,5 +27,6 @@
obj-$(CONFIG_IMX_THERMAL) += imx_thermal.o
obj-$(CONFIG_DB8500_CPUFREQ_COOLING) += db8500_cpufreq_cooling.o
@@ -35467,9 +42949,9 @@ diff -Nur linux-3.12.26.orig/drivers/thermal/Makefile linux-3.12.26/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.26.orig/drivers/tty/serial/amba-pl011.c linux-3.12.26/drivers/tty/serial/amba-pl011.c
---- linux-3.12.26.orig/drivers/tty/serial/amba-pl011.c 2014-07-30 18:02:44.000000000 +0200
-+++ linux-3.12.26/drivers/tty/serial/amba-pl011.c 2014-08-06 16:50:14.729964161 +0200
+diff -Nur linux-3.12.33/drivers/tty/serial/amba-pl011.c linux-3.12.33-rpi/drivers/tty/serial/amba-pl011.c
+--- linux-3.12.33/drivers/tty/serial/amba-pl011.c 2014-11-15 06:28:07.000000000 -0600
++++ linux-3.12.33-rpi/drivers/tty/serial/amba-pl011.c 2014-12-03 19:13:40.152418001 -0600
@@ -84,7 +84,7 @@
static unsigned int get_fifosize_arm(struct amba_device *dev)
@@ -35479,9 +42961,9 @@ diff -Nur linux-3.12.26.orig/drivers/tty/serial/amba-pl011.c linux-3.12.26/drive
}
static struct vendor_data vendor_arm = {
-diff -Nur linux-3.12.26.orig/drivers/usb/core/generic.c linux-3.12.26/drivers/usb/core/generic.c
---- linux-3.12.26.orig/drivers/usb/core/generic.c 2014-07-30 18:02:44.000000000 +0200
-+++ linux-3.12.26/drivers/usb/core/generic.c 2014-08-06 16:50:14.729964161 +0200
+diff -Nur linux-3.12.33/drivers/usb/core/generic.c linux-3.12.33-rpi/drivers/usb/core/generic.c
+--- linux-3.12.33/drivers/usb/core/generic.c 2014-11-15 06:28:07.000000000 -0600
++++ linux-3.12.33-rpi/drivers/usb/core/generic.c 2014-12-03 19:13:40.184418001 -0600
@@ -152,6 +152,7 @@
dev_warn(&udev->dev,
"no configuration chosen from %d choice%s\n",
@@ -35490,9 +42972,21 @@ diff -Nur linux-3.12.26.orig/drivers/usb/core/generic.c linux-3.12.26/drivers/us
}
return i;
}
-diff -Nur linux-3.12.26.orig/drivers/usb/core/message.c linux-3.12.26/drivers/usb/core/message.c
---- linux-3.12.26.orig/drivers/usb/core/message.c 2014-07-30 18:02:44.000000000 +0200
-+++ linux-3.12.26/drivers/usb/core/message.c 2014-08-06 16:50:14.733964192 +0200
+diff -Nur linux-3.12.33/drivers/usb/core/hub.c linux-3.12.33-rpi/drivers/usb/core/hub.c
+--- linux-3.12.33/drivers/usb/core/hub.c 2014-11-15 06:28:07.000000000 -0600
++++ linux-3.12.33-rpi/drivers/usb/core/hub.c 2014-12-03 19:13:40.184418001 -0600
+@@ -4845,7 +4845,7 @@
+ u16 status = 0;
+ u16 unused;
+
+- dev_dbg(hub_dev, "over-current change on port "
++ dev_notice(hub_dev, "over-current change on port "
+ "%d\n", i);
+ usb_clear_port_feature(hdev, i,
+ USB_PORT_FEAT_C_OVER_CURRENT);
+diff -Nur linux-3.12.33/drivers/usb/core/message.c linux-3.12.33-rpi/drivers/usb/core/message.c
+--- linux-3.12.33/drivers/usb/core/message.c 2014-11-15 06:28:07.000000000 -0600
++++ linux-3.12.33-rpi/drivers/usb/core/message.c 2014-12-03 19:13:40.188418001 -0600
@@ -1885,6 +1885,85 @@
if (cp->string == NULL &&
!(dev->quirks & USB_QUIRK_CONFIG_INTF_STRINGS))
@@ -35579,9 +43073,9 @@ diff -Nur linux-3.12.26.orig/drivers/usb/core/message.c linux-3.12.26/drivers/us
/* Now that the interfaces are installed, re-enable LPM. */
usb_unlocked_enable_lpm(dev);
-diff -Nur linux-3.12.26.orig/drivers/usb/core/otg_whitelist.h linux-3.12.26/drivers/usb/core/otg_whitelist.h
---- linux-3.12.26.orig/drivers/usb/core/otg_whitelist.h 2014-07-30 18:02:44.000000000 +0200
-+++ linux-3.12.26/drivers/usb/core/otg_whitelist.h 2014-08-06 16:50:14.733964192 +0200
+diff -Nur linux-3.12.33/drivers/usb/core/otg_whitelist.h linux-3.12.33-rpi/drivers/usb/core/otg_whitelist.h
+--- linux-3.12.33/drivers/usb/core/otg_whitelist.h 2014-11-15 06:28:07.000000000 -0600
++++ linux-3.12.33-rpi/drivers/usb/core/otg_whitelist.h 2014-12-03 19:13:40.188418001 -0600
@@ -19,33 +19,82 @@
static struct usb_device_id whitelist_table [] = {
@@ -35797,9 +43291,9 @@ diff -Nur linux-3.12.26.orig/drivers/usb/core/otg_whitelist.h linux-3.12.26/driv
#endif
}
-diff -Nur linux-3.12.26.orig/drivers/usb/gadget/file_storage.c linux-3.12.26/drivers/usb/gadget/file_storage.c
---- linux-3.12.26.orig/drivers/usb/gadget/file_storage.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-3.12.26/drivers/usb/gadget/file_storage.c 2014-08-06 16:50:14.733964192 +0200
+diff -Nur linux-3.12.33/drivers/usb/gadget/file_storage.c linux-3.12.33-rpi/drivers/usb/gadget/file_storage.c
+--- linux-3.12.33/drivers/usb/gadget/file_storage.c 1969-12-31 18:00:00.000000000 -0600
++++ linux-3.12.33-rpi/drivers/usb/gadget/file_storage.c 2014-12-03 19:13:40.200418001 -0600
@@ -0,0 +1,3676 @@
+/*
+ * file_storage.c -- File-backed USB Storage Gadget, for USB development
@@ -39477,9 +46971,9 @@ diff -Nur linux-3.12.26.orig/drivers/usb/gadget/file_storage.c linux-3.12.26/dri
+ kref_put(&fsg->ref, fsg_release);
+}
+module_exit(fsg_cleanup);
-diff -Nur linux-3.12.26.orig/drivers/usb/host/dwc_common_port/changes.txt linux-3.12.26/drivers/usb/host/dwc_common_port/changes.txt
---- linux-3.12.26.orig/drivers/usb/host/dwc_common_port/changes.txt 1970-01-01 01:00:00.000000000 +0100
-+++ linux-3.12.26/drivers/usb/host/dwc_common_port/changes.txt 2014-08-06 16:50:14.733964192 +0200
+diff -Nur linux-3.12.33/drivers/usb/host/dwc_common_port/changes.txt linux-3.12.33-rpi/drivers/usb/host/dwc_common_port/changes.txt
+--- linux-3.12.33/drivers/usb/host/dwc_common_port/changes.txt 1969-12-31 18:00:00.000000000 -0600
++++ linux-3.12.33-rpi/drivers/usb/host/dwc_common_port/changes.txt 2014-12-03 19:13:40.212418001 -0600
@@ -0,0 +1,174 @@
+
+dwc_read_reg32() and friends now take an additional parameter, a pointer to an
@@ -39655,9 +47149,9 @@ diff -Nur linux-3.12.26.orig/drivers/usb/host/dwc_common_port/changes.txt linux-
+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.26.orig/drivers/usb/host/dwc_common_port/doc/doxygen.cfg linux-3.12.26/drivers/usb/host/dwc_common_port/doc/doxygen.cfg
---- linux-3.12.26.orig/drivers/usb/host/dwc_common_port/doc/doxygen.cfg 1970-01-01 01:00:00.000000000 +0100
-+++ linux-3.12.26/drivers/usb/host/dwc_common_port/doc/doxygen.cfg 2014-08-06 16:50:14.737964224 +0200
+diff -Nur linux-3.12.33/drivers/usb/host/dwc_common_port/doc/doxygen.cfg linux-3.12.33-rpi/drivers/usb/host/dwc_common_port/doc/doxygen.cfg
+--- linux-3.12.33/drivers/usb/host/dwc_common_port/doc/doxygen.cfg 1969-12-31 18:00:00.000000000 -0600
++++ linux-3.12.33-rpi/drivers/usb/host/dwc_common_port/doc/doxygen.cfg 2014-12-03 19:13:40.212418001 -0600
@@ -0,0 +1,270 @@
+# Doxyfile 1.4.5
+
@@ -39929,9 +47423,9 @@ diff -Nur linux-3.12.26.orig/drivers/usb/host/dwc_common_port/doc/doxygen.cfg li
+# Configuration::additions related to the search engine
+#---------------------------------------------------------------------------
+SEARCHENGINE = NO
-diff -Nur linux-3.12.26.orig/drivers/usb/host/dwc_common_port/dwc_cc.c linux-3.12.26/drivers/usb/host/dwc_common_port/dwc_cc.c
---- linux-3.12.26.orig/drivers/usb/host/dwc_common_port/dwc_cc.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-3.12.26/drivers/usb/host/dwc_common_port/dwc_cc.c 2014-08-06 16:50:14.737964224 +0200
+diff -Nur linux-3.12.33/drivers/usb/host/dwc_common_port/dwc_cc.c linux-3.12.33-rpi/drivers/usb/host/dwc_common_port/dwc_cc.c
+--- linux-3.12.33/drivers/usb/host/dwc_common_port/dwc_cc.c 1969-12-31 18:00:00.000000000 -0600
++++ linux-3.12.33-rpi/drivers/usb/host/dwc_common_port/dwc_cc.c 2014-12-03 19:13:40.212418001 -0600
@@ -0,0 +1,532 @@
+/* =========================================================================
+ * $File: //dwh/usb_iip/dev/software/dwc_common_port_2/dwc_cc.c $
@@ -40465,9 +47959,9 @@ diff -Nur linux-3.12.26.orig/drivers/usb/host/dwc_common_port/dwc_cc.c linux-3.1
+}
+
+#endif /* DWC_CCLIB */
-diff -Nur linux-3.12.26.orig/drivers/usb/host/dwc_common_port/dwc_cc.h linux-3.12.26/drivers/usb/host/dwc_common_port/dwc_cc.h
---- linux-3.12.26.orig/drivers/usb/host/dwc_common_port/dwc_cc.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-3.12.26/drivers/usb/host/dwc_common_port/dwc_cc.h 2014-08-06 16:50:14.737964224 +0200
+diff -Nur linux-3.12.33/drivers/usb/host/dwc_common_port/dwc_cc.h linux-3.12.33-rpi/drivers/usb/host/dwc_common_port/dwc_cc.h
+--- linux-3.12.33/drivers/usb/host/dwc_common_port/dwc_cc.h 1969-12-31 18:00:00.000000000 -0600
++++ linux-3.12.33-rpi/drivers/usb/host/dwc_common_port/dwc_cc.h 2014-12-03 19:13:40.212418001 -0600
@@ -0,0 +1,224 @@
+/* =========================================================================
+ * $File: //dwh/usb_iip/dev/software/dwc_common_port_2/dwc_cc.h $
@@ -40693,9 +48187,9 @@ diff -Nur linux-3.12.26.orig/drivers/usb/host/dwc_common_port/dwc_cc.h linux-3.1
+#endif
+
+#endif /* _DWC_CC_H_ */
-diff -Nur linux-3.12.26.orig/drivers/usb/host/dwc_common_port/dwc_common_fbsd.c linux-3.12.26/drivers/usb/host/dwc_common_port/dwc_common_fbsd.c
---- linux-3.12.26.orig/drivers/usb/host/dwc_common_port/dwc_common_fbsd.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-3.12.26/drivers/usb/host/dwc_common_port/dwc_common_fbsd.c 2014-08-06 16:50:14.737964224 +0200
+diff -Nur linux-3.12.33/drivers/usb/host/dwc_common_port/dwc_common_fbsd.c linux-3.12.33-rpi/drivers/usb/host/dwc_common_port/dwc_common_fbsd.c
+--- linux-3.12.33/drivers/usb/host/dwc_common_port/dwc_common_fbsd.c 1969-12-31 18:00:00.000000000 -0600
++++ linux-3.12.33-rpi/drivers/usb/host/dwc_common_port/dwc_common_fbsd.c 2014-12-03 19:13:40.212418001 -0600
@@ -0,0 +1,1308 @@
+#include "dwc_os.h"
+#include "dwc_list.h"
@@ -42005,9 +49499,9 @@ diff -Nur linux-3.12.26.orig/drivers/usb/host/dwc_common_port/dwc_common_fbsd.c
+{
+ return wq->pending;
+}
-diff -Nur linux-3.12.26.orig/drivers/usb/host/dwc_common_port/dwc_common_linux.c linux-3.12.26/drivers/usb/host/dwc_common_port/dwc_common_linux.c
---- linux-3.12.26.orig/drivers/usb/host/dwc_common_port/dwc_common_linux.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-3.12.26/drivers/usb/host/dwc_common_port/dwc_common_linux.c 2014-08-06 16:50:14.737964224 +0200
+diff -Nur linux-3.12.33/drivers/usb/host/dwc_common_port/dwc_common_linux.c linux-3.12.33-rpi/drivers/usb/host/dwc_common_port/dwc_common_linux.c
+--- linux-3.12.33/drivers/usb/host/dwc_common_port/dwc_common_linux.c 1969-12-31 18:00:00.000000000 -0600
++++ linux-3.12.33-rpi/drivers/usb/host/dwc_common_port/dwc_common_linux.c 2014-12-03 19:13:40.212418001 -0600
@@ -0,0 +1,1432 @@
+#include <linux/kernel.h>
+#include <linux/init.h>
@@ -43441,9 +50935,9 @@ diff -Nur linux-3.12.26.orig/drivers/usb/host/dwc_common_port/dwc_common_linux.c
+MODULE_LICENSE ("GPL");
+
+#endif /* DWC_LIBMODULE */
-diff -Nur linux-3.12.26.orig/drivers/usb/host/dwc_common_port/dwc_common_nbsd.c linux-3.12.26/drivers/usb/host/dwc_common_port/dwc_common_nbsd.c
---- linux-3.12.26.orig/drivers/usb/host/dwc_common_port/dwc_common_nbsd.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-3.12.26/drivers/usb/host/dwc_common_port/dwc_common_nbsd.c 2014-08-06 16:50:14.737964224 +0200
+diff -Nur linux-3.12.33/drivers/usb/host/dwc_common_port/dwc_common_nbsd.c linux-3.12.33-rpi/drivers/usb/host/dwc_common_port/dwc_common_nbsd.c
+--- linux-3.12.33/drivers/usb/host/dwc_common_port/dwc_common_nbsd.c 1969-12-31 18:00:00.000000000 -0600
++++ linux-3.12.33-rpi/drivers/usb/host/dwc_common_port/dwc_common_nbsd.c 2014-12-03 19:13:40.212418001 -0600
@@ -0,0 +1,1275 @@
+#include "dwc_os.h"
+#include "dwc_list.h"
@@ -44720,9 +52214,9 @@ diff -Nur linux-3.12.26.orig/drivers/usb/host/dwc_common_port/dwc_common_nbsd.c
+{
+ return wq->pending;
+}
-diff -Nur linux-3.12.26.orig/drivers/usb/host/dwc_common_port/dwc_crypto.c linux-3.12.26/drivers/usb/host/dwc_common_port/dwc_crypto.c
---- linux-3.12.26.orig/drivers/usb/host/dwc_common_port/dwc_crypto.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-3.12.26/drivers/usb/host/dwc_common_port/dwc_crypto.c 2014-08-06 16:50:14.765964443 +0200
+diff -Nur linux-3.12.33/drivers/usb/host/dwc_common_port/dwc_crypto.c linux-3.12.33-rpi/drivers/usb/host/dwc_common_port/dwc_crypto.c
+--- linux-3.12.33/drivers/usb/host/dwc_common_port/dwc_crypto.c 1969-12-31 18:00:00.000000000 -0600
++++ linux-3.12.33-rpi/drivers/usb/host/dwc_common_port/dwc_crypto.c 2014-12-03 19:13:40.216418001 -0600
@@ -0,0 +1,308 @@
+/* =========================================================================
+ * $File: //dwh/usb_iip/dev/software/dwc_common_port_2/dwc_crypto.c $
@@ -45032,9 +52526,9 @@ diff -Nur linux-3.12.26.orig/drivers/usb/host/dwc_common_port/dwc_crypto.c linux
+}
+
+#endif /* DWC_CRYPTOLIB */
-diff -Nur linux-3.12.26.orig/drivers/usb/host/dwc_common_port/dwc_crypto.h linux-3.12.26/drivers/usb/host/dwc_common_port/dwc_crypto.h
---- linux-3.12.26.orig/drivers/usb/host/dwc_common_port/dwc_crypto.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-3.12.26/drivers/usb/host/dwc_common_port/dwc_crypto.h 2014-08-06 16:50:14.773964507 +0200
+diff -Nur linux-3.12.33/drivers/usb/host/dwc_common_port/dwc_crypto.h linux-3.12.33-rpi/drivers/usb/host/dwc_common_port/dwc_crypto.h
+--- linux-3.12.33/drivers/usb/host/dwc_common_port/dwc_crypto.h 1969-12-31 18:00:00.000000000 -0600
++++ linux-3.12.33-rpi/drivers/usb/host/dwc_common_port/dwc_crypto.h 2014-12-03 19:13:40.216418001 -0600
@@ -0,0 +1,111 @@
+/* =========================================================================
+ * $File: //dwh/usb_iip/dev/software/dwc_common_port_2/dwc_crypto.h $
@@ -45147,9 +52641,9 @@ diff -Nur linux-3.12.26.orig/drivers/usb/host/dwc_common_port/dwc_crypto.h linux
+#endif
+
+#endif /* _DWC_CRYPTO_H_ */
-diff -Nur linux-3.12.26.orig/drivers/usb/host/dwc_common_port/dwc_dh.c linux-3.12.26/drivers/usb/host/dwc_common_port/dwc_dh.c
---- linux-3.12.26.orig/drivers/usb/host/dwc_common_port/dwc_dh.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-3.12.26/drivers/usb/host/dwc_common_port/dwc_dh.c 2014-08-06 16:50:14.773964507 +0200
+diff -Nur linux-3.12.33/drivers/usb/host/dwc_common_port/dwc_dh.c linux-3.12.33-rpi/drivers/usb/host/dwc_common_port/dwc_dh.c
+--- linux-3.12.33/drivers/usb/host/dwc_common_port/dwc_dh.c 1969-12-31 18:00:00.000000000 -0600
++++ linux-3.12.33-rpi/drivers/usb/host/dwc_common_port/dwc_dh.c 2014-12-03 19:13:40.216418001 -0600
@@ -0,0 +1,291 @@
+/* =========================================================================
+ * $File: //dwh/usb_iip/dev/software/dwc_common_port_2/dwc_dh.c $
@@ -45442,9 +52936,9 @@ diff -Nur linux-3.12.26.orig/drivers/usb/host/dwc_common_port/dwc_dh.c linux-3.1
+#endif /* !CONFIG_MACH_IPMATE */
+
+#endif /* DWC_CRYPTOLIB */
-diff -Nur linux-3.12.26.orig/drivers/usb/host/dwc_common_port/dwc_dh.h linux-3.12.26/drivers/usb/host/dwc_common_port/dwc_dh.h
---- linux-3.12.26.orig/drivers/usb/host/dwc_common_port/dwc_dh.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-3.12.26/drivers/usb/host/dwc_common_port/dwc_dh.h 2014-08-06 16:50:14.777964537 +0200
+diff -Nur linux-3.12.33/drivers/usb/host/dwc_common_port/dwc_dh.h linux-3.12.33-rpi/drivers/usb/host/dwc_common_port/dwc_dh.h
+--- linux-3.12.33/drivers/usb/host/dwc_common_port/dwc_dh.h 1969-12-31 18:00:00.000000000 -0600
++++ linux-3.12.33-rpi/drivers/usb/host/dwc_common_port/dwc_dh.h 2014-12-03 19:13:40.216418001 -0600
@@ -0,0 +1,106 @@
+/* =========================================================================
+ * $File: //dwh/usb_iip/dev/software/dwc_common_port_2/dwc_dh.h $
@@ -45552,9 +53046,9 @@ diff -Nur linux-3.12.26.orig/drivers/usb/host/dwc_common_port/dwc_dh.h linux-3.1
+#endif
+
+#endif /* _DWC_DH_H_ */
-diff -Nur linux-3.12.26.orig/drivers/usb/host/dwc_common_port/dwc_list.h linux-3.12.26/drivers/usb/host/dwc_common_port/dwc_list.h
---- linux-3.12.26.orig/drivers/usb/host/dwc_common_port/dwc_list.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-3.12.26/drivers/usb/host/dwc_common_port/dwc_list.h 2014-08-06 16:50:14.777964537 +0200
+diff -Nur linux-3.12.33/drivers/usb/host/dwc_common_port/dwc_list.h linux-3.12.33-rpi/drivers/usb/host/dwc_common_port/dwc_list.h
+--- linux-3.12.33/drivers/usb/host/dwc_common_port/dwc_list.h 1969-12-31 18:00:00.000000000 -0600
++++ linux-3.12.33-rpi/drivers/usb/host/dwc_common_port/dwc_list.h 2014-12-03 19:13:40.216418001 -0600
@@ -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 $ */
@@ -46150,9 +53644,9 @@ diff -Nur linux-3.12.26.orig/drivers/usb/host/dwc_common_port/dwc_list.h linux-3
+#endif
+
+#endif /* _DWC_LIST_H_ */
-diff -Nur linux-3.12.26.orig/drivers/usb/host/dwc_common_port/dwc_mem.c linux-3.12.26/drivers/usb/host/dwc_common_port/dwc_mem.c
---- linux-3.12.26.orig/drivers/usb/host/dwc_common_port/dwc_mem.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-3.12.26/drivers/usb/host/dwc_common_port/dwc_mem.c 2014-08-06 16:50:14.777964537 +0200
+diff -Nur linux-3.12.33/drivers/usb/host/dwc_common_port/dwc_mem.c linux-3.12.33-rpi/drivers/usb/host/dwc_common_port/dwc_mem.c
+--- linux-3.12.33/drivers/usb/host/dwc_common_port/dwc_mem.c 1969-12-31 18:00:00.000000000 -0600
++++ linux-3.12.33-rpi/drivers/usb/host/dwc_common_port/dwc_mem.c 2014-12-03 19:13:40.216418001 -0600
@@ -0,0 +1,245 @@
+/* Memory Debugging */
+#ifdef DWC_DEBUG_MEMORY
@@ -46399,9 +53893,9 @@ diff -Nur linux-3.12.26.orig/drivers/usb/host/dwc_common_port/dwc_mem.c linux-3.
+}
+
+#endif /* DWC_DEBUG_MEMORY */
-diff -Nur linux-3.12.26.orig/drivers/usb/host/dwc_common_port/dwc_modpow.c linux-3.12.26/drivers/usb/host/dwc_common_port/dwc_modpow.c
---- linux-3.12.26.orig/drivers/usb/host/dwc_common_port/dwc_modpow.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-3.12.26/drivers/usb/host/dwc_common_port/dwc_modpow.c 2014-08-06 16:50:14.777964537 +0200
+diff -Nur linux-3.12.33/drivers/usb/host/dwc_common_port/dwc_modpow.c linux-3.12.33-rpi/drivers/usb/host/dwc_common_port/dwc_modpow.c
+--- linux-3.12.33/drivers/usb/host/dwc_common_port/dwc_modpow.c 1969-12-31 18:00:00.000000000 -0600
++++ linux-3.12.33-rpi/drivers/usb/host/dwc_common_port/dwc_modpow.c 2014-12-03 19:13:40.216418001 -0600
@@ -0,0 +1,636 @@
+/* Bignum routines adapted from PUTTY sources. PuTTY copyright notice follows.
+ *
@@ -47039,9 +54533,9 @@ diff -Nur linux-3.12.26.orig/drivers/usb/host/dwc_common_port/dwc_modpow.c linux
+#endif /* CONFIG_MACH_IPMATE */
+
+#endif /*DWC_CRYPTOLIB */
-diff -Nur linux-3.12.26.orig/drivers/usb/host/dwc_common_port/dwc_modpow.h linux-3.12.26/drivers/usb/host/dwc_common_port/dwc_modpow.h
---- linux-3.12.26.orig/drivers/usb/host/dwc_common_port/dwc_modpow.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-3.12.26/drivers/usb/host/dwc_common_port/dwc_modpow.h 2014-08-06 16:50:14.777964537 +0200
+diff -Nur linux-3.12.33/drivers/usb/host/dwc_common_port/dwc_modpow.h linux-3.12.33-rpi/drivers/usb/host/dwc_common_port/dwc_modpow.h
+--- linux-3.12.33/drivers/usb/host/dwc_common_port/dwc_modpow.h 1969-12-31 18:00:00.000000000 -0600
++++ linux-3.12.33-rpi/drivers/usb/host/dwc_common_port/dwc_modpow.h 2014-12-03 19:13:40.216418001 -0600
@@ -0,0 +1,34 @@
+/*
+ * dwc_modpow.h
@@ -47077,9 +54571,9 @@ diff -Nur linux-3.12.26.orig/drivers/usb/host/dwc_common_port/dwc_modpow.h linux
+#endif
+
+#endif /* _LINUX_BIGNUM_H */
-diff -Nur linux-3.12.26.orig/drivers/usb/host/dwc_common_port/dwc_notifier.c linux-3.12.26/drivers/usb/host/dwc_common_port/dwc_notifier.c
---- linux-3.12.26.orig/drivers/usb/host/dwc_common_port/dwc_notifier.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-3.12.26/drivers/usb/host/dwc_common_port/dwc_notifier.c 2014-08-06 16:50:14.777964537 +0200
+diff -Nur linux-3.12.33/drivers/usb/host/dwc_common_port/dwc_notifier.c linux-3.12.33-rpi/drivers/usb/host/dwc_common_port/dwc_notifier.c
+--- linux-3.12.33/drivers/usb/host/dwc_common_port/dwc_notifier.c 1969-12-31 18:00:00.000000000 -0600
++++ linux-3.12.33-rpi/drivers/usb/host/dwc_common_port/dwc_notifier.c 2014-12-03 19:13:40.216418001 -0600
@@ -0,0 +1,319 @@
+#ifdef DWC_NOTIFYLIB
+
@@ -47400,9 +54894,9 @@ diff -Nur linux-3.12.26.orig/drivers/usb/host/dwc_common_port/dwc_notifier.c lin
+}
+
+#endif /* DWC_NOTIFYLIB */
-diff -Nur linux-3.12.26.orig/drivers/usb/host/dwc_common_port/dwc_notifier.h linux-3.12.26/drivers/usb/host/dwc_common_port/dwc_notifier.h
---- linux-3.12.26.orig/drivers/usb/host/dwc_common_port/dwc_notifier.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-3.12.26/drivers/usb/host/dwc_common_port/dwc_notifier.h 2014-08-06 16:50:14.777964537 +0200
+diff -Nur linux-3.12.33/drivers/usb/host/dwc_common_port/dwc_notifier.h linux-3.12.33-rpi/drivers/usb/host/dwc_common_port/dwc_notifier.h
+--- linux-3.12.33/drivers/usb/host/dwc_common_port/dwc_notifier.h 1969-12-31 18:00:00.000000000 -0600
++++ linux-3.12.33-rpi/drivers/usb/host/dwc_common_port/dwc_notifier.h 2014-12-03 19:13:40.216418001 -0600
@@ -0,0 +1,122 @@
+
+#ifndef __DWC_NOTIFIER_H__
@@ -47526,9 +55020,9 @@ diff -Nur linux-3.12.26.orig/drivers/usb/host/dwc_common_port/dwc_notifier.h lin
+#endif
+
+#endif /* __DWC_NOTIFIER_H__ */
-diff -Nur linux-3.12.26.orig/drivers/usb/host/dwc_common_port/dwc_os.h linux-3.12.26/drivers/usb/host/dwc_common_port/dwc_os.h
---- linux-3.12.26.orig/drivers/usb/host/dwc_common_port/dwc_os.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-3.12.26/drivers/usb/host/dwc_common_port/dwc_os.h 2014-08-06 16:50:14.777964537 +0200
+diff -Nur linux-3.12.33/drivers/usb/host/dwc_common_port/dwc_os.h linux-3.12.33-rpi/drivers/usb/host/dwc_common_port/dwc_os.h
+--- linux-3.12.33/drivers/usb/host/dwc_common_port/dwc_os.h 1969-12-31 18:00:00.000000000 -0600
++++ linux-3.12.33-rpi/drivers/usb/host/dwc_common_port/dwc_os.h 2014-12-03 19:13:40.216418001 -0600
@@ -0,0 +1,1262 @@
+/* =========================================================================
+ * $File: //dwh/usb_iip/dev/software/dwc_common_port_2/dwc_os.h $
@@ -48792,9 +56286,9 @@ diff -Nur linux-3.12.26.orig/drivers/usb/host/dwc_common_port/dwc_os.h linux-3.1
+#endif
+
+#endif /* _DWC_OS_H_ */
-diff -Nur linux-3.12.26.orig/drivers/usb/host/dwc_common_port/Makefile linux-3.12.26/drivers/usb/host/dwc_common_port/Makefile
---- linux-3.12.26.orig/drivers/usb/host/dwc_common_port/Makefile 1970-01-01 01:00:00.000000000 +0100
-+++ linux-3.12.26/drivers/usb/host/dwc_common_port/Makefile 2014-08-06 16:50:14.777964537 +0200
+diff -Nur linux-3.12.33/drivers/usb/host/dwc_common_port/Makefile linux-3.12.33-rpi/drivers/usb/host/dwc_common_port/Makefile
+--- linux-3.12.33/drivers/usb/host/dwc_common_port/Makefile 1969-12-31 18:00:00.000000000 -0600
++++ linux-3.12.33-rpi/drivers/usb/host/dwc_common_port/Makefile 2014-12-03 19:13:40.212418001 -0600
@@ -0,0 +1,58 @@
+#
+# Makefile for DWC_common library
@@ -48854,9 +56348,9 @@ diff -Nur linux-3.12.26.orig/drivers/usb/host/dwc_common_port/Makefile linux-3.1
+
+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.26.orig/drivers/usb/host/dwc_common_port/Makefile.fbsd linux-3.12.26/drivers/usb/host/dwc_common_port/Makefile.fbsd
---- linux-3.12.26.orig/drivers/usb/host/dwc_common_port/Makefile.fbsd 1970-01-01 01:00:00.000000000 +0100
-+++ linux-3.12.26/drivers/usb/host/dwc_common_port/Makefile.fbsd 2014-08-06 16:50:14.777964537 +0200
+diff -Nur linux-3.12.33/drivers/usb/host/dwc_common_port/Makefile.fbsd linux-3.12.33-rpi/drivers/usb/host/dwc_common_port/Makefile.fbsd
+--- linux-3.12.33/drivers/usb/host/dwc_common_port/Makefile.fbsd 1969-12-31 18:00:00.000000000 -0600
++++ linux-3.12.33-rpi/drivers/usb/host/dwc_common_port/Makefile.fbsd 2014-12-03 19:13:40.212418001 -0600
@@ -0,0 +1,17 @@
+CFLAGS += -I/sys/i386/compile/GENERIC -I/sys/i386/include -I/usr/include
+CFLAGS += -DDWC_FREEBSD
@@ -48875,9 +56369,9 @@ diff -Nur linux-3.12.26.orig/drivers/usb/host/dwc_common_port/Makefile.fbsd linu
+ dwc_common_fbsd.c dwc_mem.c
+
+.include <bsd.kmod.mk>
-diff -Nur linux-3.12.26.orig/drivers/usb/host/dwc_common_port/Makefile.linux linux-3.12.26/drivers/usb/host/dwc_common_port/Makefile.linux
---- linux-3.12.26.orig/drivers/usb/host/dwc_common_port/Makefile.linux 1970-01-01 01:00:00.000000000 +0100
-+++ linux-3.12.26/drivers/usb/host/dwc_common_port/Makefile.linux 2014-08-06 16:50:14.777964537 +0200
+diff -Nur linux-3.12.33/drivers/usb/host/dwc_common_port/Makefile.linux linux-3.12.33-rpi/drivers/usb/host/dwc_common_port/Makefile.linux
+--- linux-3.12.33/drivers/usb/host/dwc_common_port/Makefile.linux 1969-12-31 18:00:00.000000000 -0600
++++ linux-3.12.33-rpi/drivers/usb/host/dwc_common_port/Makefile.linux 2014-12-03 19:13:40.212418001 -0600
@@ -0,0 +1,49 @@
+#
+# Makefile for DWC_common library
@@ -48928,9 +56422,9 @@ diff -Nur linux-3.12.26.orig/drivers/usb/host/dwc_common_port/Makefile.linux lin
+
+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.26.orig/drivers/usb/host/dwc_common_port/usb.h linux-3.12.26/drivers/usb/host/dwc_common_port/usb.h
---- linux-3.12.26.orig/drivers/usb/host/dwc_common_port/usb.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-3.12.26/drivers/usb/host/dwc_common_port/usb.h 2014-08-06 16:50:14.777964537 +0200
+diff -Nur linux-3.12.33/drivers/usb/host/dwc_common_port/usb.h linux-3.12.33-rpi/drivers/usb/host/dwc_common_port/usb.h
+--- linux-3.12.33/drivers/usb/host/dwc_common_port/usb.h 1969-12-31 18:00:00.000000000 -0600
++++ linux-3.12.33-rpi/drivers/usb/host/dwc_common_port/usb.h 2014-12-03 19:13:40.216418001 -0600
@@ -0,0 +1,946 @@
+/*
+ * Copyright (c) 1998 The NetBSD Foundation, Inc.
@@ -49878,9 +57372,9 @@ diff -Nur linux-3.12.26.orig/drivers/usb/host/dwc_common_port/usb.h linux-3.12.2
+#endif
+
+#endif /* _USB_H_ */
-diff -Nur linux-3.12.26.orig/drivers/usb/host/dwc_otg/doc/doxygen.cfg linux-3.12.26/drivers/usb/host/dwc_otg/doc/doxygen.cfg
---- linux-3.12.26.orig/drivers/usb/host/dwc_otg/doc/doxygen.cfg 1970-01-01 01:00:00.000000000 +0100
-+++ linux-3.12.26/drivers/usb/host/dwc_otg/doc/doxygen.cfg 2014-08-06 16:50:14.781964569 +0200
+diff -Nur linux-3.12.33/drivers/usb/host/dwc_otg/doc/doxygen.cfg linux-3.12.33-rpi/drivers/usb/host/dwc_otg/doc/doxygen.cfg
+--- linux-3.12.33/drivers/usb/host/dwc_otg/doc/doxygen.cfg 1969-12-31 18:00:00.000000000 -0600
++++ linux-3.12.33-rpi/drivers/usb/host/dwc_otg/doc/doxygen.cfg 2014-12-03 19:13:40.216418001 -0600
@@ -0,0 +1,224 @@
+# Doxyfile 1.3.9.1
+
@@ -50106,9 +57600,9 @@ diff -Nur linux-3.12.26.orig/drivers/usb/host/dwc_otg/doc/doxygen.cfg linux-3.12
+# Configuration::additions related to the search engine
+#---------------------------------------------------------------------------
+SEARCHENGINE = NO
-diff -Nur linux-3.12.26.orig/drivers/usb/host/dwc_otg/dummy_audio.c linux-3.12.26/drivers/usb/host/dwc_otg/dummy_audio.c
---- linux-3.12.26.orig/drivers/usb/host/dwc_otg/dummy_audio.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-3.12.26/drivers/usb/host/dwc_otg/dummy_audio.c 2014-08-06 16:50:14.781964569 +0200
+diff -Nur linux-3.12.33/drivers/usb/host/dwc_otg/dummy_audio.c linux-3.12.33-rpi/drivers/usb/host/dwc_otg/dummy_audio.c
+--- linux-3.12.33/drivers/usb/host/dwc_otg/dummy_audio.c 1969-12-31 18:00:00.000000000 -0600
++++ linux-3.12.33-rpi/drivers/usb/host/dwc_otg/dummy_audio.c 2014-12-03 19:13:40.216418001 -0600
@@ -0,0 +1,1575 @@
+/*
+ * zero.c -- Gadget Zero, for USB development
@@ -51685,9 +59179,9 @@ diff -Nur linux-3.12.26.orig/drivers/usb/host/dwc_otg/dummy_audio.c linux-3.12.2
+ remove_proc_entry("isoc_test", NULL);
+}
+module_exit (cleanup);
-diff -Nur linux-3.12.26.orig/drivers/usb/host/dwc_otg/dwc_cfi_common.h linux-3.12.26/drivers/usb/host/dwc_otg/dwc_cfi_common.h
---- linux-3.12.26.orig/drivers/usb/host/dwc_otg/dwc_cfi_common.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-3.12.26/drivers/usb/host/dwc_otg/dwc_cfi_common.h 2014-08-06 16:50:14.781964569 +0200
+diff -Nur linux-3.12.33/drivers/usb/host/dwc_otg/dwc_cfi_common.h linux-3.12.33-rpi/drivers/usb/host/dwc_otg/dwc_cfi_common.h
+--- linux-3.12.33/drivers/usb/host/dwc_otg/dwc_cfi_common.h 1969-12-31 18:00:00.000000000 -0600
++++ linux-3.12.33-rpi/drivers/usb/host/dwc_otg/dwc_cfi_common.h 2014-12-03 19:13:40.216418001 -0600
@@ -0,0 +1,142 @@
+/* ==========================================================================
+ * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,
@@ -51831,9 +59325,9 @@ diff -Nur linux-3.12.26.orig/drivers/usb/host/dwc_otg/dwc_cfi_common.h linux-3.1
+typedef struct cfi_string cfi_string_t;
+
+#endif
-diff -Nur linux-3.12.26.orig/drivers/usb/host/dwc_otg/dwc_otg_adp.c linux-3.12.26/drivers/usb/host/dwc_otg/dwc_otg_adp.c
---- linux-3.12.26.orig/drivers/usb/host/dwc_otg/dwc_otg_adp.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-3.12.26/drivers/usb/host/dwc_otg/dwc_otg_adp.c 2014-08-06 16:50:14.781964569 +0200
+diff -Nur linux-3.12.33/drivers/usb/host/dwc_otg/dwc_otg_adp.c linux-3.12.33-rpi/drivers/usb/host/dwc_otg/dwc_otg_adp.c
+--- linux-3.12.33/drivers/usb/host/dwc_otg/dwc_otg_adp.c 1969-12-31 18:00:00.000000000 -0600
++++ linux-3.12.33-rpi/drivers/usb/host/dwc_otg/dwc_otg_adp.c 2014-12-03 19:13:40.216418001 -0600
@@ -0,0 +1,854 @@
+/* ==========================================================================
+ * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_adp.c $
@@ -52689,9 +60183,9 @@ diff -Nur linux-3.12.26.orig/drivers/usb/host/dwc_otg/dwc_otg_adp.c linux-3.12.2
+#endif
+ return 1;
+}
-diff -Nur linux-3.12.26.orig/drivers/usb/host/dwc_otg/dwc_otg_adp.h linux-3.12.26/drivers/usb/host/dwc_otg/dwc_otg_adp.h
---- linux-3.12.26.orig/drivers/usb/host/dwc_otg/dwc_otg_adp.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-3.12.26/drivers/usb/host/dwc_otg/dwc_otg_adp.h 2014-08-06 16:50:14.781964569 +0200
+diff -Nur linux-3.12.33/drivers/usb/host/dwc_otg/dwc_otg_adp.h linux-3.12.33-rpi/drivers/usb/host/dwc_otg/dwc_otg_adp.h
+--- linux-3.12.33/drivers/usb/host/dwc_otg/dwc_otg_adp.h 1969-12-31 18:00:00.000000000 -0600
++++ linux-3.12.33-rpi/drivers/usb/host/dwc_otg/dwc_otg_adp.h 2014-12-03 19:13:40.216418001 -0600
@@ -0,0 +1,80 @@
+/* ==========================================================================
+ * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_adp.h $
@@ -52773,9 +60267,9 @@ diff -Nur linux-3.12.26.orig/drivers/usb/host/dwc_otg/dwc_otg_adp.h linux-3.12.2
+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.26.orig/drivers/usb/host/dwc_otg/dwc_otg_attr.c linux-3.12.26/drivers/usb/host/dwc_otg/dwc_otg_attr.c
---- linux-3.12.26.orig/drivers/usb/host/dwc_otg/dwc_otg_attr.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-3.12.26/drivers/usb/host/dwc_otg/dwc_otg_attr.c 2014-08-06 16:50:14.785964600 +0200
+diff -Nur linux-3.12.33/drivers/usb/host/dwc_otg/dwc_otg_attr.c linux-3.12.33-rpi/drivers/usb/host/dwc_otg/dwc_otg_attr.c
+--- linux-3.12.33/drivers/usb/host/dwc_otg/dwc_otg_attr.c 1969-12-31 18:00:00.000000000 -0600
++++ linux-3.12.33-rpi/drivers/usb/host/dwc_otg/dwc_otg_attr.c 2014-12-03 19:13:40.216418001 -0600
@@ -0,0 +1,1210 @@
+/* ==========================================================================
+ * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_attr.c $
@@ -53987,9 +61481,9 @@ diff -Nur linux-3.12.26.orig/drivers/usb/host/dwc_otg/dwc_otg_attr.c linux-3.12.
+ device_remove_file(&dev->dev, &dev_attr_sleep_status);
+#endif
+}
-diff -Nur linux-3.12.26.orig/drivers/usb/host/dwc_otg/dwc_otg_attr.h linux-3.12.26/drivers/usb/host/dwc_otg/dwc_otg_attr.h
---- linux-3.12.26.orig/drivers/usb/host/dwc_otg/dwc_otg_attr.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-3.12.26/drivers/usb/host/dwc_otg/dwc_otg_attr.h 2014-08-06 16:50:14.785964600 +0200
+diff -Nur linux-3.12.33/drivers/usb/host/dwc_otg/dwc_otg_attr.h linux-3.12.33-rpi/drivers/usb/host/dwc_otg/dwc_otg_attr.h
+--- linux-3.12.33/drivers/usb/host/dwc_otg/dwc_otg_attr.h 1969-12-31 18:00:00.000000000 -0600
++++ linux-3.12.33-rpi/drivers/usb/host/dwc_otg/dwc_otg_attr.h 2014-12-03 19:13:40.216418001 -0600
@@ -0,0 +1,89 @@
+/* ==========================================================================
+ * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_attr.h $
@@ -54080,9 +61574,9 @@ diff -Nur linux-3.12.26.orig/drivers/usb/host/dwc_otg/dwc_otg_attr.h linux-3.12.
+#endif
+ );
+#endif
-diff -Nur linux-3.12.26.orig/drivers/usb/host/dwc_otg/dwc_otg_cfi.c linux-3.12.26/drivers/usb/host/dwc_otg/dwc_otg_cfi.c
---- linux-3.12.26.orig/drivers/usb/host/dwc_otg/dwc_otg_cfi.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-3.12.26/drivers/usb/host/dwc_otg/dwc_otg_cfi.c 2014-08-06 16:50:14.793964664 +0200
+diff -Nur linux-3.12.33/drivers/usb/host/dwc_otg/dwc_otg_cfi.c linux-3.12.33-rpi/drivers/usb/host/dwc_otg/dwc_otg_cfi.c
+--- linux-3.12.33/drivers/usb/host/dwc_otg/dwc_otg_cfi.c 1969-12-31 18:00:00.000000000 -0600
++++ linux-3.12.33-rpi/drivers/usb/host/dwc_otg/dwc_otg_cfi.c 2014-12-03 19:13:40.216418001 -0600
@@ -0,0 +1,1876 @@
+/* ==========================================================================
+ * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,
@@ -55960,9 +63454,9 @@ diff -Nur linux-3.12.26.orig/drivers/usb/host/dwc_otg/dwc_otg_cfi.c linux-3.12.2
+}
+
+#endif //DWC_UTE_CFI
-diff -Nur linux-3.12.26.orig/drivers/usb/host/dwc_otg/dwc_otg_cfi.h linux-3.12.26/drivers/usb/host/dwc_otg/dwc_otg_cfi.h
---- linux-3.12.26.orig/drivers/usb/host/dwc_otg/dwc_otg_cfi.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-3.12.26/drivers/usb/host/dwc_otg/dwc_otg_cfi.h 2014-08-06 16:50:14.793964664 +0200
+diff -Nur linux-3.12.33/drivers/usb/host/dwc_otg/dwc_otg_cfi.h linux-3.12.33-rpi/drivers/usb/host/dwc_otg/dwc_otg_cfi.h
+--- linux-3.12.33/drivers/usb/host/dwc_otg/dwc_otg_cfi.h 1969-12-31 18:00:00.000000000 -0600
++++ linux-3.12.33-rpi/drivers/usb/host/dwc_otg/dwc_otg_cfi.h 2014-12-03 19:13:40.216418001 -0600
@@ -0,0 +1,320 @@
+/* ==========================================================================
+ * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,
@@ -56284,9 +63778,9 @@ diff -Nur linux-3.12.26.orig/drivers/usb/host/dwc_otg/dwc_otg_cfi.h linux-3.12.2
+int cfi_setup(struct dwc_otg_pcd *pcd, struct cfi_usb_ctrlrequest *ctrl);
+
+#endif /* (__DWC_OTG_CFI_H__) */
-diff -Nur linux-3.12.26.orig/drivers/usb/host/dwc_otg/dwc_otg_cil.c linux-3.12.26/drivers/usb/host/dwc_otg/dwc_otg_cil.c
---- linux-3.12.26.orig/drivers/usb/host/dwc_otg/dwc_otg_cil.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-3.12.26/drivers/usb/host/dwc_otg/dwc_otg_cil.c 2014-08-06 16:50:14.797964694 +0200
+diff -Nur linux-3.12.33/drivers/usb/host/dwc_otg/dwc_otg_cil.c linux-3.12.33-rpi/drivers/usb/host/dwc_otg/dwc_otg_cil.c
+--- linux-3.12.33/drivers/usb/host/dwc_otg/dwc_otg_cil.c 1969-12-31 18:00:00.000000000 -0600
++++ linux-3.12.33-rpi/drivers/usb/host/dwc_otg/dwc_otg_cil.c 2014-12-03 19:13:40.216418001 -0600
@@ -0,0 +1,7151 @@
+/* ==========================================================================
+ * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_cil.c $
@@ -63439,9 +70933,9 @@ diff -Nur linux-3.12.26.orig/drivers/usb/host/dwc_otg/dwc_otg_cil.c linux-3.12.2
+ dwc_otg_pcd_start_srp_timer(core_if);
+ return;
+}
-diff -Nur linux-3.12.26.orig/drivers/usb/host/dwc_otg/dwc_otg_cil.h linux-3.12.26/drivers/usb/host/dwc_otg/dwc_otg_cil.h
---- linux-3.12.26.orig/drivers/usb/host/dwc_otg/dwc_otg_cil.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-3.12.26/drivers/usb/host/dwc_otg/dwc_otg_cil.h 2014-08-06 16:50:14.801964726 +0200
+diff -Nur linux-3.12.33/drivers/usb/host/dwc_otg/dwc_otg_cil.h linux-3.12.33-rpi/drivers/usb/host/dwc_otg/dwc_otg_cil.h
+--- linux-3.12.33/drivers/usb/host/dwc_otg/dwc_otg_cil.h 1969-12-31 18:00:00.000000000 -0600
++++ linux-3.12.33-rpi/drivers/usb/host/dwc_otg/dwc_otg_cil.h 2014-12-03 19:13:40.216418001 -0600
@@ -0,0 +1,1464 @@
+/* ==========================================================================
+ * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_cil.h $
@@ -64907,10 +72401,10 @@ diff -Nur linux-3.12.26.orig/drivers/usb/host/dwc_otg/dwc_otg_cil.h linux-3.12.2
+//////////////////////////////////////////////////////////////////////
+
+#endif
-diff -Nur linux-3.12.26.orig/drivers/usb/host/dwc_otg/dwc_otg_cil_intr.c linux-3.12.26/drivers/usb/host/dwc_otg/dwc_otg_cil_intr.c
---- linux-3.12.26.orig/drivers/usb/host/dwc_otg/dwc_otg_cil_intr.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-3.12.26/drivers/usb/host/dwc_otg/dwc_otg_cil_intr.c 2014-08-06 16:50:14.801964726 +0200
-@@ -0,0 +1,1595 @@
+diff -Nur linux-3.12.33/drivers/usb/host/dwc_otg/dwc_otg_cil_intr.c linux-3.12.33-rpi/drivers/usb/host/dwc_otg/dwc_otg_cil_intr.c
+--- linux-3.12.33/drivers/usb/host/dwc_otg/dwc_otg_cil_intr.c 1969-12-31 18:00:00.000000000 -0600
++++ linux-3.12.33-rpi/drivers/usb/host/dwc_otg/dwc_otg_cil_intr.c 2014-12-03 19:13:40.216418001 -0600
+@@ -0,0 +1,1594 @@
+/* ==========================================================================
+ * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_cil_intr.c $
+ * $Revision: #32 $
@@ -66261,10 +73755,9 @@ diff -Nur linux-3.12.26.orig/drivers/usb/host/dwc_otg/dwc_otg_cil_intr.c linux-3
+ local_fiq_disable();
+ /* Pull in the interrupts that the FIQ has masked */
+ gintmsk.d32 |= ~(hcd->fiq_state->gintmsk_saved.d32);
++ gintmsk.d32 |= gintmsk_common.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;
++ reenable_gintmsk->d32 = gintmsk.d32;
+ local_fiq_enable();
+ }
+
@@ -66448,7 +73941,7 @@ diff -Nur linux-3.12.26.orig/drivers/usb/host/dwc_otg/dwc_otg_cil_intr.c linux-3
+// 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) {
++ if (retval && fiq_enable) {
+ DWC_WRITE_REG32(&core_if->core_global_regs->gintmsk, gintmsk_reenable.d32);
+ }
+
@@ -66506,9 +73999,9 @@ diff -Nur linux-3.12.26.orig/drivers/usb/host/dwc_otg/dwc_otg_cil_intr.c linux-3
+ DWC_SPINUNLOCK(core_if->lock);
+ return retval;
+}
-diff -Nur linux-3.12.26.orig/drivers/usb/host/dwc_otg/dwc_otg_core_if.h linux-3.12.26/drivers/usb/host/dwc_otg/dwc_otg_core_if.h
---- linux-3.12.26.orig/drivers/usb/host/dwc_otg/dwc_otg_core_if.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-3.12.26/drivers/usb/host/dwc_otg/dwc_otg_core_if.h 2014-08-06 16:50:14.801964726 +0200
+diff -Nur linux-3.12.33/drivers/usb/host/dwc_otg/dwc_otg_core_if.h linux-3.12.33-rpi/drivers/usb/host/dwc_otg/dwc_otg_core_if.h
+--- linux-3.12.33/drivers/usb/host/dwc_otg/dwc_otg_core_if.h 1969-12-31 18:00:00.000000000 -0600
++++ linux-3.12.33-rpi/drivers/usb/host/dwc_otg/dwc_otg_core_if.h 2014-12-03 19:13:40.216418001 -0600
@@ -0,0 +1,705 @@
+/* ==========================================================================
+ * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_core_if.h $
@@ -67215,9 +74708,9 @@ diff -Nur linux-3.12.26.orig/drivers/usb/host/dwc_otg/dwc_otg_core_if.h linux-3.
+/** @} */
+
+#endif /* __DWC_CORE_IF_H__ */
-diff -Nur linux-3.12.26.orig/drivers/usb/host/dwc_otg/dwc_otg_dbg.h linux-3.12.26/drivers/usb/host/dwc_otg/dwc_otg_dbg.h
---- linux-3.12.26.orig/drivers/usb/host/dwc_otg/dwc_otg_dbg.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-3.12.26/drivers/usb/host/dwc_otg/dwc_otg_dbg.h 2014-08-06 16:50:14.801964726 +0200
+diff -Nur linux-3.12.33/drivers/usb/host/dwc_otg/dwc_otg_dbg.h linux-3.12.33-rpi/drivers/usb/host/dwc_otg/dwc_otg_dbg.h
+--- linux-3.12.33/drivers/usb/host/dwc_otg/dwc_otg_dbg.h 1969-12-31 18:00:00.000000000 -0600
++++ linux-3.12.33-rpi/drivers/usb/host/dwc_otg/dwc_otg_dbg.h 2014-12-03 19:13:40.216418001 -0600
@@ -0,0 +1,117 @@
+/* ==========================================================================
+ *
@@ -67336,9 +74829,9 @@ diff -Nur linux-3.12.26.orig/drivers/usb/host/dwc_otg/dwc_otg_dbg.h linux-3.12.2
+
+#endif /*DEBUG*/
+#endif
-diff -Nur linux-3.12.26.orig/drivers/usb/host/dwc_otg/dwc_otg_driver.c linux-3.12.26/drivers/usb/host/dwc_otg/dwc_otg_driver.c
---- linux-3.12.26.orig/drivers/usb/host/dwc_otg/dwc_otg_driver.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-3.12.26/drivers/usb/host/dwc_otg/dwc_otg_driver.c 2014-08-06 16:50:14.805964758 +0200
+diff -Nur linux-3.12.33/drivers/usb/host/dwc_otg/dwc_otg_driver.c linux-3.12.33-rpi/drivers/usb/host/dwc_otg/dwc_otg_driver.c
+--- linux-3.12.33/drivers/usb/host/dwc_otg/dwc_otg_driver.c 1969-12-31 18:00:00.000000000 -0600
++++ linux-3.12.33-rpi/drivers/usb/host/dwc_otg/dwc_otg_driver.c 2014-12-03 19:13:40.220418001 -0600
@@ -0,0 +1,1749 @@
+/* ==========================================================================
+ * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_driver.c $
@@ -67585,11 +75078,11 @@ diff -Nur linux-3.12.26.orig/drivers/usb/host/dwc_otg/dwc_otg_driver.c linux-3.1
+//Global variable to switch the fiq fix on or off
+bool fiq_enable = 1;
+// Global variable to enable the split transaction fix
-+bool fiq_fsm_enable = false;
++bool fiq_fsm_enable = true;
+//Bulk split-transaction NAK holdoff in microframes
+uint16_t nak_holdoff = 8;
+
-+unsigned short fiq_fsm_mask = 0x01;
++unsigned short fiq_fsm_mask = 0x07;
+
+/**
+ * This function shows the Driver Version.
@@ -68244,9 +75737,9 @@ diff -Nur linux-3.12.26.orig/drivers/usb/host/dwc_otg/dwc_otg_driver.c linux-3.1
+ */
+
+#if defined(PLATFORM_INTERFACE)
-+ devirq = platform_get_irq(_dev, 0);
++ devirq = platform_get_irq(_dev, fiq_enable ? 0 : 1);
+#else
-+ devirq = _dev->irq;
++ devirq = _dev->irq;
+#endif
+ DWC_DEBUGPL(DBG_CIL, "registering (common) handler for irq%d\n",
+ devirq);
@@ -69089,9 +76582,9 @@ diff -Nur linux-3.12.26.orig/drivers/usb/host/dwc_otg/dwc_otg_driver.c linux-3.1
+ </td></tr>
+
+*/
-diff -Nur linux-3.12.26.orig/drivers/usb/host/dwc_otg/dwc_otg_driver.h linux-3.12.26/drivers/usb/host/dwc_otg/dwc_otg_driver.h
---- linux-3.12.26.orig/drivers/usb/host/dwc_otg/dwc_otg_driver.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-3.12.26/drivers/usb/host/dwc_otg/dwc_otg_driver.h 2014-08-06 16:50:14.805964758 +0200
+diff -Nur linux-3.12.33/drivers/usb/host/dwc_otg/dwc_otg_driver.h linux-3.12.33-rpi/drivers/usb/host/dwc_otg/dwc_otg_driver.h
+--- linux-3.12.33/drivers/usb/host/dwc_otg/dwc_otg_driver.h 1969-12-31 18:00:00.000000000 -0600
++++ linux-3.12.33-rpi/drivers/usb/host/dwc_otg/dwc_otg_driver.h 2014-12-03 19:13:40.220418001 -0600
@@ -0,0 +1,86 @@
+/* ==========================================================================
+ * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_driver.h $
@@ -69179,10 +76672,10 @@ diff -Nur linux-3.12.26.orig/drivers/usb/host/dwc_otg/dwc_otg_driver.h linux-3.1
+#endif
+
+#endif
-diff -Nur linux-3.12.26.orig/drivers/usb/host/dwc_otg/dwc_otg_fiq_fsm.c linux-3.12.26/drivers/usb/host/dwc_otg/dwc_otg_fiq_fsm.c
---- linux-3.12.26.orig/drivers/usb/host/dwc_otg/dwc_otg_fiq_fsm.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-3.12.26/drivers/usb/host/dwc_otg/dwc_otg_fiq_fsm.c 2014-08-06 16:50:14.805964758 +0200
-@@ -0,0 +1,1289 @@
+diff -Nur linux-3.12.33/drivers/usb/host/dwc_otg/dwc_otg_fiq_fsm.c linux-3.12.33-rpi/drivers/usb/host/dwc_otg/dwc_otg_fiq_fsm.c
+--- linux-3.12.33/drivers/usb/host/dwc_otg/dwc_otg_fiq_fsm.c 1969-12-31 18:00:00.000000000 -0600
++++ linux-3.12.33-rpi/drivers/usb/host/dwc_otg/dwc_otg_fiq_fsm.c 2014-12-03 19:13:40.220418001 -0600
+@@ -0,0 +1,1294 @@
+/*
+ * dwc_otg_fiq_fsm.c - The finite state machine FIQ
+ *
@@ -69471,6 +76964,7 @@ diff -Nur linux-3.12.26.orig/drivers/usb/host/dwc_otg/dwc_otg_fiq_fsm.c linux-3.
+ case FIQ_PER_CSPLIT_NYET1:
+ //case FIQ_PER_CSPLIT_POLL:
+ case FIQ_PER_ISO_OUT_ACTIVE:
++ case FIQ_PER_ISO_OUT_LAST:
+ if (st->channel[i].hub_addr == hub_addr &&
+ st->channel[i].port_addr == port_addr) {
+ in_use = 1;
@@ -69764,8 +77258,10 @@ diff -Nur linux-3.12.26.orig/drivers/usb/host/dwc_otg/dwc_otg_fiq_fsm.c linux-3.
+ fiq_fsm_restart_channel(state, n, 0);
+ state->channel[n].fsm = FIQ_PER_SSPLIT_STARTED;
+ } else {
++ /* Transaction cannot be started without risking a device babble error */
+ state->channel[n].fsm = FIQ_PER_SPLIT_TIMEOUT;
+ state->haintmsk_saved.b2.chint &= ~(1 << n);
++ FIQ_WRITE(state->dwc_regs_base + HC_START + (HC_OFFSET * n) + HCINTMSK, 0);
+ kick_irq |= 1;
+ }
+ }
@@ -69807,12 +77303,14 @@ diff -Nur linux-3.12.26.orig/drivers/usb/host/dwc_otg/dwc_otg_fiq_fsm.c linux-3.
+ break;
+
+ case FIQ_PER_SPLIT_TIMEOUT:
++ case FIQ_DEQUEUE_ISSUED:
+ /* 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);
++ FIQ_WRITE(state->dwc_regs_base + HC_START + (HC_OFFSET * n) + HCINTMSK, 0);
+ kick_irq |= 1;
+ break;
+
@@ -69876,7 +77374,11 @@ diff -Nur linux-3.12.26.orig/drivers/usb/host/dwc_otg/dwc_otg_fiq_fsm.c linux-3.
+ 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;
++ /* In some random cases we can get a NAK interrupt coincident with a Xacterr
++ * interrupt, after the device has disappeared.
++ */
++ if (!hcint.b.xacterr)
++ st->nr_errors = 0;
+ hcintmsk.b.nak = 0;
+ hcintmsk.b.ack = 0;
+ hcintmsk.b.datatglerr = 0;
@@ -69953,7 +77455,7 @@ diff -Nur linux-3.12.26.orig/drivers/usb/host/dwc_otg/dwc_otg_fiq_fsm.c linux-3.
+ handled = 1;
+ restart = 1;
+ }
-+ } else if (hcint.b.stall) {
++ } else if (hcint.b.stall || hcint.b.bblerr) {
+ /* A STALL implies either a LS bus error or a genuine STALL. */
+ st->fsm = FIQ_NP_SPLIT_LS_ABORTED;
+ } else {
@@ -70105,7 +77607,7 @@ diff -Nur linux-3.12.26.orig/drivers/usb/host/dwc_otg/dwc_otg_fiq_fsm.c linux-3.
+ } else if (hcint.b.nyet) {
+ /* Doh. Data lost. */
+ st->fsm = FIQ_PER_SPLIT_NYET_ABORTED;
-+ } else if (hcint.b.xacterr || hcint.b.stall) {
++ } else if (hcint.b.xacterr || hcint.b.stall || hcint.b.bblerr) {
+ st->fsm = FIQ_PER_SPLIT_LS_ABORTED;
+ } else {
+ st->fsm = FIQ_PER_SPLIT_HS_ABORTED;
@@ -70142,12 +77644,11 @@ diff -Nur linux-3.12.26.orig/drivers/usb/host/dwc_otg/dwc_otg_fiq_fsm.c linux-3.
+ } else if (hcint.b.nyet) {
+ st->fsm = FIQ_PER_SPLIT_NYET_ABORTED;
+ start_next_periodic = 1;
-+ } else if (hcint.b.xacterr) {
++ } else if (hcint.b.xacterr || hcint.b.stall || hcint.b.bblerr) {
+ /* 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();
++ st->fsm = FIQ_PER_SPLIT_HS_ABORTED;
+ }
+ break;
+
@@ -70186,12 +77687,9 @@ diff -Nur linux-3.12.26.orig/drivers/usb/host/dwc_otg/dwc_otg_fiq_fsm.c linux-3.
+ st->fsm = FIQ_PER_SPLIT_DONE;
+ }
+ }
-+ } else if (hcint.b.xacterr || hcint.b.stall) {
++ } else if (hcint.b.xacterr || hcint.b.stall || hcint.b.bblerr) {
+ /* 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;
+ }
@@ -70472,9 +77970,9 @@ diff -Nur linux-3.12.26.orig/drivers/usb/host/dwc_otg/dwc_otg_fiq_fsm.c linux-3.
+ state->fiq_done++;
+ mb();
+}
-diff -Nur linux-3.12.26.orig/drivers/usb/host/dwc_otg/dwc_otg_fiq_fsm.h linux-3.12.26/drivers/usb/host/dwc_otg/dwc_otg_fiq_fsm.h
---- linux-3.12.26.orig/drivers/usb/host/dwc_otg/dwc_otg_fiq_fsm.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-3.12.26/drivers/usb/host/dwc_otg/dwc_otg_fiq_fsm.h 2014-08-06 16:50:14.805964758 +0200
+diff -Nur linux-3.12.33/drivers/usb/host/dwc_otg/dwc_otg_fiq_fsm.h linux-3.12.33-rpi/drivers/usb/host/dwc_otg/dwc_otg_fiq_fsm.h
+--- linux-3.12.33/drivers/usb/host/dwc_otg/dwc_otg_fiq_fsm.h 1969-12-31 18:00:00.000000000 -0600
++++ linux-3.12.33-rpi/drivers/usb/host/dwc_otg/dwc_otg_fiq_fsm.h 2014-12-03 19:13:40.220418001 -0600
@@ -0,0 +1,353 @@
+/*
+ * dwc_otg_fiq_fsm.h - Finite state machine FIQ header definitions
@@ -70829,9 +78327,9 @@ diff -Nur linux-3.12.26.orig/drivers/usb/host/dwc_otg/dwc_otg_fiq_fsm.h linux-3.
+extern void dwc_otg_fiq_nop(struct fiq_state *state);
+
+#endif /* DWC_OTG_FIQ_FSM_H_ */
-diff -Nur linux-3.12.26.orig/drivers/usb/host/dwc_otg/dwc_otg_fiq_stub.S linux-3.12.26/drivers/usb/host/dwc_otg/dwc_otg_fiq_stub.S
---- linux-3.12.26.orig/drivers/usb/host/dwc_otg/dwc_otg_fiq_stub.S 1970-01-01 01:00:00.000000000 +0100
-+++ linux-3.12.26/drivers/usb/host/dwc_otg/dwc_otg_fiq_stub.S 2014-08-06 16:50:14.805964758 +0200
+diff -Nur linux-3.12.33/drivers/usb/host/dwc_otg/dwc_otg_fiq_stub.S linux-3.12.33-rpi/drivers/usb/host/dwc_otg/dwc_otg_fiq_stub.S
+--- linux-3.12.33/drivers/usb/host/dwc_otg/dwc_otg_fiq_stub.S 1969-12-31 18:00:00.000000000 -0600
++++ linux-3.12.33-rpi/drivers/usb/host/dwc_otg/dwc_otg_fiq_stub.S 2014-12-03 19:13:40.220418001 -0600
@@ -0,0 +1,81 @@
+/*
+ * dwc_otg_fiq_fsm.S - assembly stub for the FSM FIQ
@@ -70914,10 +78412,10 @@ diff -Nur linux-3.12.26.orig/drivers/usb/host/dwc_otg/dwc_otg_fiq_stub.S linux-3
+_dwc_otg_fiq_stub_end:
+END(_dwc_otg_fiq_stub)
+
-diff -Nur linux-3.12.26.orig/drivers/usb/host/dwc_otg/dwc_otg_hcd.c linux-3.12.26/drivers/usb/host/dwc_otg/dwc_otg_hcd.c
---- linux-3.12.26.orig/drivers/usb/host/dwc_otg/dwc_otg_hcd.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-3.12.26/drivers/usb/host/dwc_otg/dwc_otg_hcd.c 2014-08-06 16:50:14.813964820 +0200
-@@ -0,0 +1,4188 @@
+diff -Nur linux-3.12.33/drivers/usb/host/dwc_otg/dwc_otg_hcd.c linux-3.12.33-rpi/drivers/usb/host/dwc_otg/dwc_otg_hcd.c
+--- linux-3.12.33/drivers/usb/host/dwc_otg/dwc_otg_hcd.c 1969-12-31 18:00:00.000000000 -0600
++++ linux-3.12.33-rpi/drivers/usb/host/dwc_otg/dwc_otg_hcd.c 2014-12-03 19:13:40.220418001 -0600
+@@ -0,0 +1,4212 @@
+
+/* ==========================================================================
+ * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_hcd.c $
@@ -71534,11 +79032,13 @@ diff -Nur linux-3.12.26.orig/drivers/usb/host/dwc_otg/dwc_otg_hcd.c linux-3.12.2
+ /* 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)) {
++ qh->channel->halt_status = DWC_OTG_HC_XFER_URB_DEQUEUE;
++ qh->channel->halt_pending = 1;
+ hcd->fiq_state->channel[n].fsm = FIQ_DEQUEUE_ISSUED;
++ } else {
++ dwc_otg_hc_halt(hcd->core_if, qh->channel,
++ DWC_OTG_HC_XFER_URB_DEQUEUE);
+ }
-+ dwc_otg_hc_halt(hcd->core_if, qh->channel,
-+ DWC_OTG_HC_XFER_URB_DEQUEUE);
-+
+ }
+ }
+
@@ -71968,10 +79468,11 @@ diff -Nur linux-3.12.26.orig/drivers/usb/host/dwc_otg/dwc_otg_hcd.c linux-3.12.2
+ 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",
++ DWC_PRINTF("FIQ FSM acceleration enabled for :\n%s%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" : "");
++ (fiq_fsm_mask & 0x4) ? "High-Speed Isochronous Endpoints\n" : "",
++ (fiq_fsm_mask & 0x8) ? "Interrupt/Control Split Transaction hack enabled\n" : "");
+ }
+ }
+
@@ -72702,6 +80203,20 @@ diff -Nur linux-3.12.26.orig/drivers/usb/host/dwc_otg/dwc_otg_hcd.c linux-3.12.2
+ st->hcintmsk_copy.b.chhltd = 1;
+ st->hcintmsk_copy.b.ahberr = 1;
+
++ /* Hack courtesy of FreeBSD: apparently forcing Interrupt Split transactions
++ * as Control puts the transfer into the non-periodic request queue and the
++ * non-periodic handler in the hub. Makes things lots easier.
++ */
++ if ((fiq_fsm_mask & 0x8) && hc->ep_type == UE_INTERRUPT) {
++ st->hcchar_copy.b.multicnt = 0;
++ st->hcchar_copy.b.oddfrm = 0;
++ st->hcchar_copy.b.eptype = UE_CONTROL;
++ if (hc->align_buff) {
++ st->hcdma_copy.d32 = hc->align_buff;
++ } else {
++ st->hcdma_copy.d32 = ((unsigned long) hc->xfer_buff & 0xFFFFFFFF);
++ }
++ }
+ 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);
@@ -72755,6 +80270,9 @@ diff -Nur linux-3.12.26.orig/drivers/usb/host/dwc_otg/dwc_otg_hcd.c linux-3.12.2
+ }
+ }
+ }
++ if ((fiq_fsm_mask & 0x8) && hc->ep_type == UE_INTERRUPT)
++ start_immediate = 1;
++
+ 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);
@@ -72786,11 +80304,13 @@ diff -Nur linux-3.12.26.orig/drivers/usb/host/dwc_otg/dwc_otg_hcd.c linux-3.12.2
+ }
+ break;
+ case UE_INTERRUPT:
-+ if (start_immediate) {
++ if (fiq_fsm_mask & 0x8) {
++ st->fsm = FIQ_NP_SSPLIT_STARTED;
++ } else if (start_immediate) {
+ st->fsm = FIQ_PER_SSPLIT_STARTED;
-+ } else {
-+ st->fsm = FIQ_PER_SSPLIT_QUEUED;
-+ }
++ } else {
++ st->fsm = FIQ_PER_SSPLIT_QUEUED;
++ }
+ default:
+ break;
+ }
@@ -72934,17 +80454,19 @@ diff -Nur linux-3.12.26.orig/drivers/usb/host/dwc_otg/dwc_otg_hcd.c linux-3.12.2
+ * 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)) {
++ if (fiq_enable) {
++ 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;
++ } 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;
++ }
+ }
+ }
+ }
@@ -75106,9 +82628,9 @@ diff -Nur linux-3.12.26.orig/drivers/usb/host/dwc_otg/dwc_otg_hcd.c linux-3.12.2
+}
+
+#endif /* DWC_DEVICE_ONLY */
-diff -Nur linux-3.12.26.orig/drivers/usb/host/dwc_otg/dwc_otg_hcd_ddma.c linux-3.12.26/drivers/usb/host/dwc_otg/dwc_otg_hcd_ddma.c
---- linux-3.12.26.orig/drivers/usb/host/dwc_otg/dwc_otg_hcd_ddma.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-3.12.26/drivers/usb/host/dwc_otg/dwc_otg_hcd_ddma.c 2014-08-06 16:50:14.813964820 +0200
+diff -Nur linux-3.12.33/drivers/usb/host/dwc_otg/dwc_otg_hcd_ddma.c linux-3.12.33-rpi/drivers/usb/host/dwc_otg/dwc_otg_hcd_ddma.c
+--- linux-3.12.33/drivers/usb/host/dwc_otg/dwc_otg_hcd_ddma.c 1969-12-31 18:00:00.000000000 -0600
++++ linux-3.12.33-rpi/drivers/usb/host/dwc_otg/dwc_otg_hcd_ddma.c 2014-12-03 19:13:40.220418001 -0600
@@ -0,0 +1,1132 @@
+/*==========================================================================
+ * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_hcd_ddma.c $
@@ -76242,9 +83764,9 @@ diff -Nur linux-3.12.26.orig/drivers/usb/host/dwc_otg/dwc_otg_hcd_ddma.c linux-3
+}
+
+#endif /* DWC_DEVICE_ONLY */
-diff -Nur linux-3.12.26.orig/drivers/usb/host/dwc_otg/dwc_otg_hcd.h linux-3.12.26/drivers/usb/host/dwc_otg/dwc_otg_hcd.h
---- linux-3.12.26.orig/drivers/usb/host/dwc_otg/dwc_otg_hcd.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-3.12.26/drivers/usb/host/dwc_otg/dwc_otg_hcd.h 2014-08-06 16:50:14.817964852 +0200
+diff -Nur linux-3.12.33/drivers/usb/host/dwc_otg/dwc_otg_hcd.h linux-3.12.33-rpi/drivers/usb/host/dwc_otg/dwc_otg_hcd.h
+--- linux-3.12.33/drivers/usb/host/dwc_otg/dwc_otg_hcd.h 1969-12-31 18:00:00.000000000 -0600
++++ linux-3.12.33-rpi/drivers/usb/host/dwc_otg/dwc_otg_hcd.h 2014-12-03 19:13:40.220418001 -0600
@@ -0,0 +1,862 @@
+/* ==========================================================================
+ * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_hcd.h $
@@ -77108,9 +84630,9 @@ diff -Nur linux-3.12.26.orig/drivers/usb/host/dwc_otg/dwc_otg_hcd.h linux-3.12.2
+#endif
+#endif
+#endif /* DWC_DEVICE_ONLY */
-diff -Nur linux-3.12.26.orig/drivers/usb/host/dwc_otg/dwc_otg_hcd_if.h linux-3.12.26/drivers/usb/host/dwc_otg/dwc_otg_hcd_if.h
---- linux-3.12.26.orig/drivers/usb/host/dwc_otg/dwc_otg_hcd_if.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-3.12.26/drivers/usb/host/dwc_otg/dwc_otg_hcd_if.h 2014-08-06 16:50:14.817964852 +0200
+diff -Nur linux-3.12.33/drivers/usb/host/dwc_otg/dwc_otg_hcd_if.h linux-3.12.33-rpi/drivers/usb/host/dwc_otg/dwc_otg_hcd_if.h
+--- linux-3.12.33/drivers/usb/host/dwc_otg/dwc_otg_hcd_if.h 1969-12-31 18:00:00.000000000 -0600
++++ linux-3.12.33-rpi/drivers/usb/host/dwc_otg/dwc_otg_hcd_if.h 2014-12-03 19:13:40.220418001 -0600
@@ -0,0 +1,417 @@
+/* ==========================================================================
+ * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_hcd_if.h $
@@ -77529,10 +85051,10 @@ diff -Nur linux-3.12.26.orig/drivers/usb/host/dwc_otg/dwc_otg_hcd_if.h linux-3.1
+
+#endif /* __DWC_HCD_IF_H__ */
+#endif /* DWC_DEVICE_ONLY */
-diff -Nur linux-3.12.26.orig/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c linux-3.12.26/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c
---- linux-3.12.26.orig/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-3.12.26/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c 2014-08-06 16:50:14.817964852 +0200
-@@ -0,0 +1,2681 @@
+diff -Nur linux-3.12.33/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c linux-3.12.33-rpi/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c
+--- linux-3.12.33/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c 1969-12-31 18:00:00.000000000 -0600
++++ linux-3.12.33-rpi/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c 2014-12-03 19:13:40.220418001 -0600
+@@ -0,0 +1,2688 @@
+/* ==========================================================================
+ * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_hcd_intr.c $
+ * $Revision: #89 $
@@ -77634,11 +85156,12 @@ diff -Nur linux-3.12.26.orig/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c linux-3
+ DWC_SPINLOCK(dwc_otg_hcd->lock);
+ /* Check if HOST Mode */
+ if (dwc_otg_is_host_mode(core_if)) {
-+ local_fiq_disable();
-+ /* 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_enable) {
++ local_fiq_disable();
++ /* 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;
@@ -77650,7 +85173,9 @@ diff -Nur linux-3.12.26.orig/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c linux-3
+ }
+ gintsts.d32 &= gintmsk.d32;
+
-+ local_fiq_enable();
++ if (fiq_enable)
++ local_fiq_enable();
++
+ if (!gintsts.d32) {
+ goto exit_handler_routine;
+ }
@@ -77863,8 +85388,8 @@ diff -Nur linux-3.12.26.orig/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c linux-3
+ }
+ }
+ }
-+
-+ hcd->fiq_state->next_sched_frame = next_sched_frame;
++ if (fiq_enable)
++ hcd->fiq_state->next_sched_frame = next_sched_frame;
+
+ tr_type = dwc_otg_hcd_select_transactions(hcd);
+ if (tr_type != DWC_OTG_TRANSACTION_NONE) {
@@ -79921,6 +87446,8 @@ diff -Nur linux-3.12.26.orig/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c linux-3
+ 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.bblerr) {
++ handle_hc_babble_intr(hcd, hc, hc_regs, qtd);
+ } else if (hcint.b.ahberr) {
+ handle_hc_ahberr_intr(hcd, hc, hc_regs, qtd);
+ } else {
@@ -80057,6 +87584,8 @@ diff -Nur linux-3.12.26.orig/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c linux-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 if (hcint.b.bblerr) {
++ handle_hc_babble_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",
@@ -80147,7 +87676,7 @@ diff -Nur linux-3.12.26.orig/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c linux-3
+ 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) {
++ if (!dwc_otg_hcd->fiq_state->channel[num].nr_errors) {
+ qtd->error_count = 0;
+ fiq_print(FIQDBG_ERR, dwc_otg_hcd->fiq_state, "RESET ");
+ }
@@ -80214,9 +87743,9 @@ diff -Nur linux-3.12.26.orig/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c linux-3
+ return retval;
+}
+#endif /* DWC_DEVICE_ONLY */
-diff -Nur linux-3.12.26.orig/drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c linux-3.12.26/drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c
---- linux-3.12.26.orig/drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-3.12.26/drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c 2014-08-06 16:50:14.845965072 +0200
+diff -Nur linux-3.12.33/drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c linux-3.12.33-rpi/drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c
+--- linux-3.12.33/drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c 1969-12-31 18:00:00.000000000 -0600
++++ linux-3.12.33-rpi/drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c 2014-12-03 19:13:40.220418001 -0600
@@ -0,0 +1,985 @@
+
+/* ==========================================================================
@@ -80747,9 +88276,9 @@ diff -Nur linux-3.12.26.orig/drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c linux-
+ * IRQ line, and calls hcd_start method.
+ */
+#ifdef PLATFORM_INTERFACE
-+ retval = usb_add_hcd(hcd, platform_get_irq(_dev, 0), IRQF_SHARED | IRQF_DISABLED);
++ retval = usb_add_hcd(hcd, platform_get_irq(_dev, fiq_enable ? 0 : 1), IRQF_SHARED | IRQF_DISABLED);
+#else
-+ retval = usb_add_hcd(hcd, _dev->irq, IRQF_SHARED | IRQF_DISABLED);
++ retval = usb_add_hcd(hcd, _dev->irq, IRQF_SHARED | IRQF_DISABLED);
+#endif
+ if (retval < 0) {
+ goto error2;
@@ -81203,9 +88732,9 @@ diff -Nur linux-3.12.26.orig/drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c linux-
+}
+
+#endif /* DWC_DEVICE_ONLY */
-diff -Nur linux-3.12.26.orig/drivers/usb/host/dwc_otg/dwc_otg_hcd_queue.c linux-3.12.26/drivers/usb/host/dwc_otg/dwc_otg_hcd_queue.c
---- linux-3.12.26.orig/drivers/usb/host/dwc_otg/dwc_otg_hcd_queue.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-3.12.26/drivers/usb/host/dwc_otg/dwc_otg_hcd_queue.c 2014-08-06 16:50:14.845965072 +0200
+diff -Nur linux-3.12.33/drivers/usb/host/dwc_otg/dwc_otg_hcd_queue.c linux-3.12.33-rpi/drivers/usb/host/dwc_otg/dwc_otg_hcd_queue.c
+--- linux-3.12.33/drivers/usb/host/dwc_otg/dwc_otg_hcd_queue.c 1969-12-31 18:00:00.000000000 -0600
++++ linux-3.12.33-rpi/drivers/usb/host/dwc_otg/dwc_otg_hcd_queue.c 2014-12-03 19:13:40.220418001 -0600
@@ -0,0 +1,942 @@
+/* ==========================================================================
+ * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_hcd_queue.c $
@@ -81843,7 +89372,7 @@ diff -Nur linux-3.12.26.orig/drivers/usb/host/dwc_otg/dwc_otg_hcd_queue.c linux-
+ 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, hcd->fiq_state->next_sched_frame))
++ if(fiq_enable && (DWC_LIST_EMPTY(&hcd->periodic_sched_inactive) || dwc_frame_num_le(qh->sched_frame, hcd->fiq_state->next_sched_frame)))
+ {
+ hcd->fiq_state->next_sched_frame = qh->sched_frame;
+
@@ -82039,7 +89568,7 @@ diff -Nur linux-3.12.26.orig/drivers/usb/host/dwc_otg/dwc_otg_hcd_queue.c linux-
+ DWC_LIST_MOVE_HEAD(&hcd->periodic_sched_ready,
+ &qh->qh_list_entry);
+ } else {
-+ if(!dwc_frame_num_le(hcd->fiq_state->next_sched_frame, qh->sched_frame))
++ if(fiq_enable && !dwc_frame_num_le(hcd->fiq_state->next_sched_frame, qh->sched_frame))
+ {
+ hcd->fiq_state->next_sched_frame = qh->sched_frame;
+ }
@@ -82149,9 +89678,9 @@ diff -Nur linux-3.12.26.orig/drivers/usb/host/dwc_otg/dwc_otg_hcd_queue.c linux-
+}
+
+#endif /* DWC_DEVICE_ONLY */
-diff -Nur linux-3.12.26.orig/drivers/usb/host/dwc_otg/dwc_otg_os_dep.h linux-3.12.26/drivers/usb/host/dwc_otg/dwc_otg_os_dep.h
---- linux-3.12.26.orig/drivers/usb/host/dwc_otg/dwc_otg_os_dep.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-3.12.26/drivers/usb/host/dwc_otg/dwc_otg_os_dep.h 2014-08-06 16:50:14.845965072 +0200
+diff -Nur linux-3.12.33/drivers/usb/host/dwc_otg/dwc_otg_os_dep.h linux-3.12.33-rpi/drivers/usb/host/dwc_otg/dwc_otg_os_dep.h
+--- linux-3.12.33/drivers/usb/host/dwc_otg/dwc_otg_os_dep.h 1969-12-31 18:00:00.000000000 -0600
++++ linux-3.12.33-rpi/drivers/usb/host/dwc_otg/dwc_otg_os_dep.h 2014-12-03 19:13:40.220418001 -0600
@@ -0,0 +1,188 @@
+#ifndef _DWC_OS_DEP_H_
+#define _DWC_OS_DEP_H_
@@ -82341,9 +89870,9 @@ diff -Nur linux-3.12.26.orig/drivers/usb/host/dwc_otg/dwc_otg_os_dep.h linux-3.1
+
+
+#endif /* _DWC_OS_DEP_H_ */
-diff -Nur linux-3.12.26.orig/drivers/usb/host/dwc_otg/dwc_otg_pcd.c linux-3.12.26/drivers/usb/host/dwc_otg/dwc_otg_pcd.c
---- linux-3.12.26.orig/drivers/usb/host/dwc_otg/dwc_otg_pcd.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-3.12.26/drivers/usb/host/dwc_otg/dwc_otg_pcd.c 2014-08-06 16:50:14.849965104 +0200
+diff -Nur linux-3.12.33/drivers/usb/host/dwc_otg/dwc_otg_pcd.c linux-3.12.33-rpi/drivers/usb/host/dwc_otg/dwc_otg_pcd.c
+--- linux-3.12.33/drivers/usb/host/dwc_otg/dwc_otg_pcd.c 1969-12-31 18:00:00.000000000 -0600
++++ linux-3.12.33-rpi/drivers/usb/host/dwc_otg/dwc_otg_pcd.c 2014-12-03 19:13:40.220418001 -0600
@@ -0,0 +1,2708 @@
+/* ==========================================================================
+ * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_pcd.c $
@@ -85053,9 +92582,9 @@ diff -Nur linux-3.12.26.orig/drivers/usb/host/dwc_otg/dwc_otg_pcd.c linux-3.12.2
+}
+
+#endif /* DWC_HOST_ONLY */
-diff -Nur linux-3.12.26.orig/drivers/usb/host/dwc_otg/dwc_otg_pcd.h linux-3.12.26/drivers/usb/host/dwc_otg/dwc_otg_pcd.h
---- linux-3.12.26.orig/drivers/usb/host/dwc_otg/dwc_otg_pcd.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-3.12.26/drivers/usb/host/dwc_otg/dwc_otg_pcd.h 2014-08-06 16:50:14.849965104 +0200
+diff -Nur linux-3.12.33/drivers/usb/host/dwc_otg/dwc_otg_pcd.h linux-3.12.33-rpi/drivers/usb/host/dwc_otg/dwc_otg_pcd.h
+--- linux-3.12.33/drivers/usb/host/dwc_otg/dwc_otg_pcd.h 1969-12-31 18:00:00.000000000 -0600
++++ linux-3.12.33-rpi/drivers/usb/host/dwc_otg/dwc_otg_pcd.h 2014-12-03 19:13:40.220418001 -0600
@@ -0,0 +1,266 @@
+/* ==========================================================================
+ * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_pcd.h $
@@ -85323,9 +92852,9 @@ diff -Nur linux-3.12.26.orig/drivers/usb/host/dwc_otg/dwc_otg_pcd.h linux-3.12.2
+extern void do_test_mode(void *data);
+#endif
+#endif /* DWC_HOST_ONLY */
-diff -Nur linux-3.12.26.orig/drivers/usb/host/dwc_otg/dwc_otg_pcd_if.h linux-3.12.26/drivers/usb/host/dwc_otg/dwc_otg_pcd_if.h
---- linux-3.12.26.orig/drivers/usb/host/dwc_otg/dwc_otg_pcd_if.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-3.12.26/drivers/usb/host/dwc_otg/dwc_otg_pcd_if.h 2014-08-06 16:50:14.849965104 +0200
+diff -Nur linux-3.12.33/drivers/usb/host/dwc_otg/dwc_otg_pcd_if.h linux-3.12.33-rpi/drivers/usb/host/dwc_otg/dwc_otg_pcd_if.h
+--- linux-3.12.33/drivers/usb/host/dwc_otg/dwc_otg_pcd_if.h 1969-12-31 18:00:00.000000000 -0600
++++ linux-3.12.33-rpi/drivers/usb/host/dwc_otg/dwc_otg_pcd_if.h 2014-12-03 19:13:40.220418001 -0600
@@ -0,0 +1,360 @@
+/* ==========================================================================
+ * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_pcd_if.h $
@@ -85687,9 +93216,9 @@ diff -Nur linux-3.12.26.orig/drivers/usb/host/dwc_otg/dwc_otg_pcd_if.h linux-3.1
+#endif /* __DWC_PCD_IF_H__ */
+
+#endif /* DWC_HOST_ONLY */
-diff -Nur linux-3.12.26.orig/drivers/usb/host/dwc_otg/dwc_otg_pcd_intr.c linux-3.12.26/drivers/usb/host/dwc_otg/dwc_otg_pcd_intr.c
---- linux-3.12.26.orig/drivers/usb/host/dwc_otg/dwc_otg_pcd_intr.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-3.12.26/drivers/usb/host/dwc_otg/dwc_otg_pcd_intr.c 2014-08-06 16:50:14.853965134 +0200
+diff -Nur linux-3.12.33/drivers/usb/host/dwc_otg/dwc_otg_pcd_intr.c linux-3.12.33-rpi/drivers/usb/host/dwc_otg/dwc_otg_pcd_intr.c
+--- linux-3.12.33/drivers/usb/host/dwc_otg/dwc_otg_pcd_intr.c 1969-12-31 18:00:00.000000000 -0600
++++ linux-3.12.33-rpi/drivers/usb/host/dwc_otg/dwc_otg_pcd_intr.c 2014-12-03 19:13:40.220418001 -0600
@@ -0,0 +1,5147 @@
+/* ==========================================================================
+ * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_pcd_intr.c $
@@ -90838,10 +98367,10 @@ diff -Nur linux-3.12.26.orig/drivers/usb/host/dwc_otg/dwc_otg_pcd_intr.c linux-3
+}
+
+#endif /* DWC_HOST_ONLY */
-diff -Nur linux-3.12.26.orig/drivers/usb/host/dwc_otg/dwc_otg_pcd_linux.c linux-3.12.26/drivers/usb/host/dwc_otg/dwc_otg_pcd_linux.c
---- linux-3.12.26.orig/drivers/usb/host/dwc_otg/dwc_otg_pcd_linux.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-3.12.26/drivers/usb/host/dwc_otg/dwc_otg_pcd_linux.c 2014-08-06 16:50:14.853965134 +0200
-@@ -0,0 +1,1358 @@
+diff -Nur linux-3.12.33/drivers/usb/host/dwc_otg/dwc_otg_pcd_linux.c linux-3.12.33-rpi/drivers/usb/host/dwc_otg/dwc_otg_pcd_linux.c
+--- linux-3.12.33/drivers/usb/host/dwc_otg/dwc_otg_pcd_linux.c 1969-12-31 18:00:00.000000000 -0600
++++ linux-3.12.33-rpi/drivers/usb/host/dwc_otg/dwc_otg_pcd_linux.c 2014-12-03 19:13:40.224418001 -0600
+@@ -0,0 +1,1360 @@
+ /* ==========================================================================
+ * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_pcd_linux.c $
+ * $Revision: #21 $
@@ -90903,6 +98432,8 @@ diff -Nur linux-3.12.26.orig/drivers/usb/host/dwc_otg/dwc_otg_pcd_linux.c linux-
+#include "dwc_otg_driver.h"
+#include "dwc_otg_dbg.h"
+
++extern bool fiq_enable;
++
+static struct gadget_wrapper {
+ dwc_otg_pcd_t *pcd;
+
@@ -92066,13 +99597,13 @@ diff -Nur linux-3.12.26.orig/drivers/usb/host/dwc_otg/dwc_otg_pcd_linux.c linux-
+ */
+#ifdef PLATFORM_INTERFACE
+ DWC_DEBUGPL(DBG_ANY, "registering handler for irq%d\n",
-+ platform_get_irq(_dev, 0));
-+ retval = request_irq(platform_get_irq(_dev, 0), dwc_otg_pcd_irq,
++ platform_get_irq(_dev, fiq_enable ? 0 : 1));
++ retval = request_irq(platform_get_irq(_dev, fiq_enable ? 0 : 1), dwc_otg_pcd_irq,
+ IRQF_SHARED, gadget_wrapper->gadget.name,
+ otg_dev->pcd);
+ if (retval != 0) {
+ DWC_ERROR("request of irq%d failed\n",
-+ platform_get_irq(_dev, 0));
++ platform_get_irq(_dev, fiq_enable ? 0 : 1));
+ free_wrapper(gadget_wrapper);
+ return -EBUSY;
+ }
@@ -92200,9 +99731,9 @@ diff -Nur linux-3.12.26.orig/drivers/usb/host/dwc_otg/dwc_otg_pcd_linux.c linux-
+EXPORT_SYMBOL(usb_gadget_unregister_driver);
+
+#endif /* DWC_HOST_ONLY */
-diff -Nur linux-3.12.26.orig/drivers/usb/host/dwc_otg/dwc_otg_regs.h linux-3.12.26/drivers/usb/host/dwc_otg/dwc_otg_regs.h
---- linux-3.12.26.orig/drivers/usb/host/dwc_otg/dwc_otg_regs.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-3.12.26/drivers/usb/host/dwc_otg/dwc_otg_regs.h 2014-08-06 16:50:14.865965229 +0200
+diff -Nur linux-3.12.33/drivers/usb/host/dwc_otg/dwc_otg_regs.h linux-3.12.33-rpi/drivers/usb/host/dwc_otg/dwc_otg_regs.h
+--- linux-3.12.33/drivers/usb/host/dwc_otg/dwc_otg_regs.h 1969-12-31 18:00:00.000000000 -0600
++++ linux-3.12.33-rpi/drivers/usb/host/dwc_otg/dwc_otg_regs.h 2014-12-03 19:13:40.224418001 -0600
@@ -0,0 +1,2550 @@
+/* ==========================================================================
+ * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_regs.h $
@@ -94754,9 +102285,9 @@ diff -Nur linux-3.12.26.orig/drivers/usb/host/dwc_otg/dwc_otg_regs.h linux-3.12.
+} gpwrdn_data_t;
+
+#endif
-diff -Nur linux-3.12.26.orig/drivers/usb/host/dwc_otg/Makefile linux-3.12.26/drivers/usb/host/dwc_otg/Makefile
---- linux-3.12.26.orig/drivers/usb/host/dwc_otg/Makefile 1970-01-01 01:00:00.000000000 +0100
-+++ linux-3.12.26/drivers/usb/host/dwc_otg/Makefile 2014-08-06 16:50:14.865965229 +0200
+diff -Nur linux-3.12.33/drivers/usb/host/dwc_otg/Makefile linux-3.12.33-rpi/drivers/usb/host/dwc_otg/Makefile
+--- linux-3.12.33/drivers/usb/host/dwc_otg/Makefile 1969-12-31 18:00:00.000000000 -0600
++++ linux-3.12.33-rpi/drivers/usb/host/dwc_otg/Makefile 2014-12-03 19:13:40.216418001 -0600
@@ -0,0 +1,82 @@
+#
+# Makefile for DWC_otg Highspeed USB controller driver
@@ -94840,9 +102371,9 @@ diff -Nur linux-3.12.26.orig/drivers/usb/host/dwc_otg/Makefile linux-3.12.26/dri
+ rm -rf *.o *.ko .*cmd *.mod.c .tmp_versions Module.symvers
+
+endif
-diff -Nur linux-3.12.26.orig/drivers/usb/host/dwc_otg/test/dwc_otg_test.pm linux-3.12.26/drivers/usb/host/dwc_otg/test/dwc_otg_test.pm
---- linux-3.12.26.orig/drivers/usb/host/dwc_otg/test/dwc_otg_test.pm 1970-01-01 01:00:00.000000000 +0100
-+++ linux-3.12.26/drivers/usb/host/dwc_otg/test/dwc_otg_test.pm 2014-08-06 16:50:14.893965449 +0200
+diff -Nur linux-3.12.33/drivers/usb/host/dwc_otg/test/dwc_otg_test.pm linux-3.12.33-rpi/drivers/usb/host/dwc_otg/test/dwc_otg_test.pm
+--- linux-3.12.33/drivers/usb/host/dwc_otg/test/dwc_otg_test.pm 1969-12-31 18:00:00.000000000 -0600
++++ linux-3.12.33-rpi/drivers/usb/host/dwc_otg/test/dwc_otg_test.pm 2014-12-03 19:13:40.224418001 -0600
@@ -0,0 +1,337 @@
+package dwc_otg_test;
+
@@ -95181,9 +102712,9 @@ diff -Nur linux-3.12.26.orig/drivers/usb/host/dwc_otg/test/dwc_otg_test.pm linux
+);
+
+1;
-diff -Nur linux-3.12.26.orig/drivers/usb/host/dwc_otg/test/Makefile linux-3.12.26/drivers/usb/host/dwc_otg/test/Makefile
---- linux-3.12.26.orig/drivers/usb/host/dwc_otg/test/Makefile 1970-01-01 01:00:00.000000000 +0100
-+++ linux-3.12.26/drivers/usb/host/dwc_otg/test/Makefile 2014-08-06 16:50:14.893965449 +0200
+diff -Nur linux-3.12.33/drivers/usb/host/dwc_otg/test/Makefile linux-3.12.33-rpi/drivers/usb/host/dwc_otg/test/Makefile
+--- linux-3.12.33/drivers/usb/host/dwc_otg/test/Makefile 1969-12-31 18:00:00.000000000 -0600
++++ linux-3.12.33-rpi/drivers/usb/host/dwc_otg/test/Makefile 2014-12-03 19:13:40.224418001 -0600
@@ -0,0 +1,16 @@
+
+PERL=/usr/bin/perl
@@ -95201,9 +102732,9 @@ diff -Nur linux-3.12.26.orig/drivers/usb/host/dwc_otg/test/Makefile linux-3.12.2
+ else echo "=======> $$test, FAILED" ; \
+ fi \
+ done
-diff -Nur linux-3.12.26.orig/drivers/usb/host/dwc_otg/test/test_mod_param.pl linux-3.12.26/drivers/usb/host/dwc_otg/test/test_mod_param.pl
---- linux-3.12.26.orig/drivers/usb/host/dwc_otg/test/test_mod_param.pl 1970-01-01 01:00:00.000000000 +0100
-+++ linux-3.12.26/drivers/usb/host/dwc_otg/test/test_mod_param.pl 2014-08-06 16:50:14.893965449 +0200
+diff -Nur linux-3.12.33/drivers/usb/host/dwc_otg/test/test_mod_param.pl linux-3.12.33-rpi/drivers/usb/host/dwc_otg/test/test_mod_param.pl
+--- linux-3.12.33/drivers/usb/host/dwc_otg/test/test_mod_param.pl 1969-12-31 18:00:00.000000000 -0600
++++ linux-3.12.33-rpi/drivers/usb/host/dwc_otg/test/test_mod_param.pl 2014-12-03 19:13:40.224418001 -0600
@@ -0,0 +1,133 @@
+#!/usr/bin/perl -w
+#
@@ -95338,9 +102869,9 @@ diff -Nur linux-3.12.26.orig/drivers/usb/host/dwc_otg/test/test_mod_param.pl lin
+
+test_main();
+0;
-diff -Nur linux-3.12.26.orig/drivers/usb/host/dwc_otg/test/test_sysfs.pl linux-3.12.26/drivers/usb/host/dwc_otg/test/test_sysfs.pl
---- linux-3.12.26.orig/drivers/usb/host/dwc_otg/test/test_sysfs.pl 1970-01-01 01:00:00.000000000 +0100
-+++ linux-3.12.26/drivers/usb/host/dwc_otg/test/test_sysfs.pl 2014-08-06 16:50:14.893965449 +0200
+diff -Nur linux-3.12.33/drivers/usb/host/dwc_otg/test/test_sysfs.pl linux-3.12.33-rpi/drivers/usb/host/dwc_otg/test/test_sysfs.pl
+--- linux-3.12.33/drivers/usb/host/dwc_otg/test/test_sysfs.pl 1969-12-31 18:00:00.000000000 -0600
++++ linux-3.12.33-rpi/drivers/usb/host/dwc_otg/test/test_sysfs.pl 2014-12-03 19:13:40.224418001 -0600
@@ -0,0 +1,193 @@
+#!/usr/bin/perl -w
+#
@@ -95535,9 +103066,9 @@ diff -Nur linux-3.12.26.orig/drivers/usb/host/dwc_otg/test/test_sysfs.pl linux-3
+
+test_main();
+0;
-diff -Nur linux-3.12.26.orig/drivers/usb/host/Kconfig linux-3.12.26/drivers/usb/host/Kconfig
---- linux-3.12.26.orig/drivers/usb/host/Kconfig 2014-07-30 18:02:44.000000000 +0200
-+++ linux-3.12.26/drivers/usb/host/Kconfig 2014-08-06 16:50:14.897965480 +0200
+diff -Nur linux-3.12.33/drivers/usb/host/Kconfig linux-3.12.33-rpi/drivers/usb/host/Kconfig
+--- linux-3.12.33/drivers/usb/host/Kconfig 2014-11-15 06:28:07.000000000 -0600
++++ linux-3.12.33-rpi/drivers/usb/host/Kconfig 2014-12-03 19:13:40.212418001 -0600
@@ -650,6 +650,19 @@
To compile this driver a module, choose M here: the module
will be called "hwa-hc".
@@ -95558,9 +103089,9 @@ diff -Nur linux-3.12.26.orig/drivers/usb/host/Kconfig linux-3.12.26/drivers/usb/
config USB_IMX21_HCD
tristate "i.MX21 HCD support"
depends on ARM && ARCH_MXC
-diff -Nur linux-3.12.26.orig/drivers/usb/host/Makefile linux-3.12.26/drivers/usb/host/Makefile
---- linux-3.12.26.orig/drivers/usb/host/Makefile 2014-07-30 18:02:44.000000000 +0200
-+++ linux-3.12.26/drivers/usb/host/Makefile 2014-08-06 16:50:14.897965480 +0200
+diff -Nur linux-3.12.33/drivers/usb/host/Makefile linux-3.12.33-rpi/drivers/usb/host/Makefile
+--- linux-3.12.33/drivers/usb/host/Makefile 2014-11-15 06:28:07.000000000 -0600
++++ linux-3.12.33-rpi/drivers/usb/host/Makefile 2014-12-03 19:13:40.212418001 -0600
@@ -56,6 +56,8 @@
obj-$(CONFIG_USB_R8A66597_HCD) += r8a66597-hcd.o
obj-$(CONFIG_USB_ISP1760_HCD) += isp1760.o
@@ -95570,9 +103101,9 @@ diff -Nur linux-3.12.26.orig/drivers/usb/host/Makefile linux-3.12.26/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.26.orig/drivers/usb/Makefile linux-3.12.26/drivers/usb/Makefile
---- linux-3.12.26.orig/drivers/usb/Makefile 2014-07-30 18:02:44.000000000 +0200
-+++ linux-3.12.26/drivers/usb/Makefile 2014-08-06 16:50:14.897965480 +0200
+diff -Nur linux-3.12.33/drivers/usb/Makefile linux-3.12.33-rpi/drivers/usb/Makefile
+--- linux-3.12.33/drivers/usb/Makefile 2014-11-15 06:28:07.000000000 -0600
++++ linux-3.12.33-rpi/drivers/usb/Makefile 2014-12-03 19:13:40.176418001 -0600
@@ -23,6 +23,7 @@
obj-$(CONFIG_USB_R8A66597_HCD) += host/
obj-$(CONFIG_USB_HWA_HCD) += host/
@@ -95581,56 +103112,10 @@ diff -Nur linux-3.12.26.orig/drivers/usb/Makefile linux-3.12.26/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.26.orig/drivers/vhost/net.c linux-3.12.26/drivers/vhost/net.c
---- linux-3.12.26.orig/drivers/vhost/net.c 2014-07-30 18:02:44.000000000 +0200
-+++ linux-3.12.26/drivers/vhost/net.c 2014-08-06 16:50:14.921965669 +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.26.orig/drivers/video/bcm2708_fb.c linux-3.12.26/drivers/video/bcm2708_fb.c
---- linux-3.12.26.orig/drivers/video/bcm2708_fb.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-3.12.26/drivers/video/bcm2708_fb.c 2014-08-06 16:50:14.921965669 +0200
-@@ -0,0 +1,762 @@
+diff -Nur linux-3.12.33/drivers/video/bcm2708_fb.c linux-3.12.33-rpi/drivers/video/bcm2708_fb.c
+--- linux-3.12.33/drivers/video/bcm2708_fb.c 1969-12-31 18:00:00.000000000 -0600
++++ linux-3.12.33-rpi/drivers/video/bcm2708_fb.c 2014-12-03 19:13:42.492418001 -0600
+@@ -0,0 +1,817 @@
+/*
+ * linux/drivers/video/bcm2708_fb.c
+ *
@@ -95671,6 +103156,9 @@ diff -Nur linux-3.12.26.orig/drivers/video/bcm2708_fb.c linux-3.12.26/drivers/vi
+#include <linux/io.h>
+#include <linux/dma-mapping.h>
+
++//#define BCM2708_FB_DEBUG
++#define MODULE_NAME "bcm2708_fb"
++
+#ifdef BCM2708_FB_DEBUG
+#define print_debug(fmt,...) pr_debug("%s:%s:%d: "fmt, MODULE_NAME, __func__, __LINE__, ##__VA_ARGS__)
+#else
@@ -95722,6 +103210,7 @@ diff -Nur linux-3.12.26.orig/drivers/video/bcm2708_fb.c linux-3.12.26/drivers/vi
+ struct dentry *debugfs_dir;
+ wait_queue_head_t dma_waitq;
+ struct bcm2708_fb_stats stats;
++ unsigned long fb_bus_address;
+};
+
+#define to_bcm2708(info) container_of(info, struct bcm2708_fb, fb)
@@ -95897,12 +103386,6 @@ diff -Nur linux-3.12.26.orig/drivers/video/bcm2708_fb.c linux-3.12.26/drivers/vi
+ else if (var->vmode & FB_VMODE_INTERLACED)
+ yres = (yres + 1) / 2;
+
-+ if (var->xres * yres > 1920 * 1200) {
-+ pr_err("bcm2708_fb_check_var: ERROR: Pixel size >= 1920x1200; "
-+ "special treatment required! (TODO)\n");
-+ return -EINVAL;
-+ }
-+
+ return 0;
+}
+
@@ -95947,13 +103430,15 @@ diff -Nur linux-3.12.26.orig/drivers/video/bcm2708_fb.c linux-3.12.26/drivers/vi
+ else
+ fb->fb.fix.visual = FB_VISUAL_TRUECOLOR;
+
++ fb->fb_bus_address = fbinfo->base;
++ fbinfo->base &= ~0xc0000000;
+ fb->fb.fix.smem_start = fbinfo->base;
+ fb->fb.fix.smem_len = fbinfo->pitch * fbinfo->yres_virtual;
+ fb->fb.screen_size = fbinfo->screen_size;
+ if (fb->fb.screen_base)
+ iounmap(fb->fb.screen_base);
+ fb->fb.screen_base =
-+ (void *)ioremap_wc(fb->fb.fix.smem_start, fb->fb.screen_size);
++ (void *)ioremap_wc(fbinfo->base, fb->fb.screen_size);
+ if (!fb->fb.screen_base) {
+ /* the console may currently be locked */
+ console_trylock();
@@ -95964,7 +103449,7 @@ diff -Nur linux-3.12.26.orig/drivers/video/bcm2708_fb.c linux-3.12.26/drivers/vi
+ }
+ print_debug
+ ("BCM2708FB: start = %p,%p width=%d, height=%d, bpp=%d, pitch=%d size=%d success=%d\n",
-+ (void *)fb->fb.screen_base, (void *)fb->fb.fix.smem_start,
++ (void *)fb->fb.screen_base, (void *)fb->fb_bus_address,
+ fbinfo->xres, fbinfo->yres, fbinfo->bpp,
+ fbinfo->pitch, (int)fb->fb.screen_size, val);
+
@@ -96008,10 +103493,62 @@ diff -Nur linux-3.12.26.orig/drivers/video/bcm2708_fb.c linux-3.12.26/drivers/vi
+
+static int bcm2708_fb_blank(int blank_mode, struct fb_info *info)
+{
-+ /*print_debug("bcm2708_fb_blank\n"); */
-+ return -1;
++ s32 result = -1;
++ u32 p[7];
++ if ( (blank_mode == FB_BLANK_NORMAL) ||
++ (blank_mode == FB_BLANK_UNBLANK)) {
++
++ p[0] = 28; // size = sizeof u32 * length of p
++ p[1] = VCMSG_PROCESS_REQUEST; // process request
++ p[2] = VCMSG_SET_BLANK_SCREEN; // (the tag id)
++ p[3] = 4; // (size of the response buffer)
++ p[4] = 4; // (size of the request data)
++ p[5] = blank_mode;
++ p[6] = VCMSG_PROPERTY_END; // end tag
++
++ bcm_mailbox_property(&p, p[0]);
++
++ if ( p[1] == VCMSG_REQUEST_SUCCESSFUL )
++ result = 0;
++ else
++ pr_err("bcm2708_fb_blank(%d) returns=%d p[1]=0x%x\n", blank_mode, p[5], p[1]);
++ }
++ return result;
++}
++
++static int bcm2708_fb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info)
++{
++ s32 result = -1;
++ info->var.xoffset = var->xoffset;
++ info->var.yoffset = var->yoffset;
++ result = bcm2708_fb_set_par(info);
++ if (result != 0)
++ pr_err("bcm2708_fb_pan_display(%d,%d) returns=%d\n", var->xoffset, var->yoffset, result);
++ return result;
+}
+
++static int bcm2708_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg)
++{
++ s32 result = -1;
++ u32 p[7];
++ if (cmd == FBIO_WAITFORVSYNC) {
++ p[0] = 28; // size = sizeof u32 * length of p
++ p[1] = VCMSG_PROCESS_REQUEST; // process request
++ p[2] = VCMSG_SET_VSYNC; // (the tag id)
++ p[3] = 4; // (size of the response buffer)
++ p[4] = 4; // (size of the request data)
++ p[5] = 0; // dummy
++ p[6] = VCMSG_PROPERTY_END; // end tag
++
++ bcm_mailbox_property(&p, p[0]);
++
++ pr_info("bcm2708_fb_ioctl %x,%lx returns=%d p[1]=0x%x\n", cmd, arg, p[5], p[1]);
++
++ if ( p[1] == VCMSG_REQUEST_SUCCESSFUL )
++ result = 0;
++ }
++ return result;
++}
+static void bcm2708_fb_fillrect(struct fb_info *info,
+ const struct fb_fillrect *rect)
+{
@@ -96056,7 +103593,8 @@ diff -Nur linux-3.12.26.orig/drivers/video/bcm2708_fb.c linux-3.12.26/drivers/vi
+ int pixels = region->width * region->height;
+
+ /* Fallback to cfb_copyarea() if we don't like something */
-+ if (bytes_per_pixel > 4 ||
++ if (in_atomic() ||
++ bytes_per_pixel > 4 ||
+ info->var.xres * info->var.yres > 1920 * 1200 ||
+ region->width <= 0 || region->width > info->var.xres ||
+ region->height <= 0 || region->height > info->var.yres ||
@@ -96090,11 +103628,11 @@ diff -Nur linux-3.12.26.orig/drivers/video/bcm2708_fb.c linux-3.12.26/drivers/vi
+
+ for (y = 0; y < region->height; y += scanlines_per_cb) {
+ dma_addr_t src =
-+ fb->fb.fix.smem_start +
++ fb->fb_bus_address +
+ bytes_per_pixel * region->sx +
+ (region->sy + y) * fb->fb.fix.line_length;
+ dma_addr_t dst =
-+ fb->fb.fix.smem_start +
++ fb->fb_bus_address +
+ bytes_per_pixel * region->dx +
+ (region->dy + y) * fb->fb.fix.line_length;
+
@@ -96132,10 +103670,10 @@ diff -Nur linux-3.12.26.orig/drivers/video/bcm2708_fb.c linux-3.12.26/drivers/vi
+ stride = -fb->fb.fix.line_length;
+ }
+ set_dma_cb(cb, burst_size,
-+ fb->fb.fix.smem_start + dy * fb->fb.fix.line_length +
++ fb->fb_bus_address + dy * fb->fb.fix.line_length +
+ bytes_per_pixel * region->dx,
+ stride,
-+ fb->fb.fix.smem_start + sy * fb->fb.fix.line_length +
++ fb->fb_bus_address + sy * fb->fb.fix.line_length +
+ bytes_per_pixel * region->sx,
+ stride,
+ region->width * bytes_per_pixel,
@@ -96197,6 +103735,8 @@ diff -Nur linux-3.12.26.orig/drivers/video/bcm2708_fb.c linux-3.12.26/drivers/vi
+ .fb_fillrect = bcm2708_fb_fillrect,
+ .fb_copyarea = bcm2708_fb_copyarea,
+ .fb_imageblit = bcm2708_fb_imageblit,
++ .fb_pan_display = bcm2708_fb_pan_display,
++ .fb_ioctl = bcm2708_ioctl,
+};
+
+static int bcm2708_fb_register(struct bcm2708_fb *fb)
@@ -96223,8 +103763,8 @@ diff -Nur linux-3.12.26.orig/drivers/video/bcm2708_fb.c linux-3.12.26/drivers/vi
+ strncpy(fb->fb.fix.id, bcm2708_name, sizeof(fb->fb.fix.id));
+ fb->fb.fix.type = FB_TYPE_PACKED_PIXELS;
+ fb->fb.fix.type_aux = 0;
-+ fb->fb.fix.xpanstep = 0;
-+ fb->fb.fix.ypanstep = 0;
++ fb->fb.fix.xpanstep = 1;
++ fb->fb.fix.ypanstep = 1;
+ fb->fb.fix.ywrapstep = 0;
+ fb->fb.fix.accel = FB_ACCEL_NONE;
+
@@ -96393,9 +103933,9 @@ diff -Nur linux-3.12.26.orig/drivers/video/bcm2708_fb.c linux-3.12.26/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.26.orig/drivers/video/cfbimgblt.c linux-3.12.26/drivers/video/cfbimgblt.c
---- linux-3.12.26.orig/drivers/video/cfbimgblt.c 2014-07-30 18:02:44.000000000 +0200
-+++ linux-3.12.26/drivers/video/cfbimgblt.c 2014-08-06 16:50:14.921965669 +0200
+diff -Nur linux-3.12.33/drivers/video/cfbimgblt.c linux-3.12.33-rpi/drivers/video/cfbimgblt.c
+--- linux-3.12.33/drivers/video/cfbimgblt.c 2014-11-15 06:28:07.000000000 -0600
++++ linux-3.12.33-rpi/drivers/video/cfbimgblt.c 2014-12-03 19:13:42.492418001 -0600
@@ -28,6 +28,11 @@
*
* Also need to add code to deal with cards endians that are different than
@@ -96569,9 +104109,9 @@ diff -Nur linux-3.12.26.orig/drivers/video/cfbimgblt.c linux-3.12.26/drivers/vid
slow_imageblit(image, p, dst1, fgcolor, bgcolor,
start_index, pitch_index);
} else
-diff -Nur linux-3.12.26.orig/drivers/video/fbmem.c linux-3.12.26/drivers/video/fbmem.c
---- linux-3.12.26.orig/drivers/video/fbmem.c 2014-07-30 18:02:44.000000000 +0200
-+++ linux-3.12.26/drivers/video/fbmem.c 2014-08-06 16:50:14.941965825 +0200
+diff -Nur linux-3.12.33/drivers/video/fbmem.c linux-3.12.33-rpi/drivers/video/fbmem.c
+--- linux-3.12.33/drivers/video/fbmem.c 2014-11-15 06:28:07.000000000 -0600
++++ linux-3.12.33-rpi/drivers/video/fbmem.c 2014-12-03 19:13:42.500418001 -0600
@@ -1083,6 +1083,25 @@
}
EXPORT_SYMBOL(fb_blank);
@@ -96606,75 +104146,9 @@ diff -Nur linux-3.12.26.orig/drivers/video/fbmem.c linux-3.12.26/drivers/video/f
void __user *argp = (void __user *)arg;
long ret = 0;
-@@ -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);
- 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);
+@@ -1210,6 +1230,15 @@
+ 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) {
@@ -96688,7 +104162,7 @@ diff -Nur linux-3.12.26.orig/drivers/video/fbmem.c linux-3.12.26/drivers/video/f
default:
if (!lock_fb_info(info))
return -ENODEV;
-@@ -1364,6 +1385,7 @@
+@@ -1364,6 +1393,7 @@
case FBIOPAN_DISPLAY:
case FBIOGET_CON2FBMAP:
case FBIOPUT_CON2FBMAP:
@@ -96696,168 +104170,9 @@ diff -Nur linux-3.12.26.orig/drivers/video/fbmem.c linux-3.12.26/drivers/video/f
arg = (unsigned long) compat_ptr(arg);
case FBIOBLANK:
ret = do_fb_ioctl(info, cmd, arg);
-@@ -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.26.orig/drivers/video/fbsysfs.c linux-3.12.26/drivers/video/fbsysfs.c
---- linux-3.12.26.orig/drivers/video/fbsysfs.c 2014-07-30 18:02:44.000000000 +0200
-+++ linux-3.12.26/drivers/video/fbsysfs.c 2014-08-06 16:50:14.945965857 +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.26.orig/drivers/video/Kconfig linux-3.12.26/drivers/video/Kconfig
---- linux-3.12.26.orig/drivers/video/Kconfig 2014-07-30 18:02:44.000000000 +0200
-+++ linux-3.12.26/drivers/video/Kconfig 2014-08-06 16:50:14.949965888 +0200
+diff -Nur linux-3.12.33/drivers/video/Kconfig linux-3.12.33-rpi/drivers/video/Kconfig
+--- linux-3.12.33/drivers/video/Kconfig 2014-11-15 06:28:07.000000000 -0600
++++ linux-3.12.33-rpi/drivers/video/Kconfig 2014-12-03 19:13:40.336418001 -0600
@@ -310,6 +310,20 @@
help
Support the Permedia2 FIFO disconnect feature.
@@ -96879,9 +104194,9 @@ diff -Nur linux-3.12.26.orig/drivers/video/Kconfig linux-3.12.26/drivers/video/K
config FB_ARMCLCD
tristate "ARM PrimeCell PL110 support"
depends on FB && ARM && ARM_AMBA
-diff -Nur linux-3.12.26.orig/drivers/video/logo/logo_linux_clut224.ppm linux-3.12.26/drivers/video/logo/logo_linux_clut224.ppm
---- linux-3.12.26.orig/drivers/video/logo/logo_linux_clut224.ppm 2014-07-30 18:02:44.000000000 +0200
-+++ linux-3.12.26/drivers/video/logo/logo_linux_clut224.ppm 2014-08-06 16:50:14.953965920 +0200
+diff -Nur linux-3.12.33/drivers/video/logo/logo_linux_clut224.ppm linux-3.12.33-rpi/drivers/video/logo/logo_linux_clut224.ppm
+--- linux-3.12.33/drivers/video/logo/logo_linux_clut224.ppm 2014-11-15 06:28:07.000000000 -0600
++++ linux-3.12.33-rpi/drivers/video/logo/logo_linux_clut224.ppm 2014-12-03 19:13:42.524418001 -0600
@@ -1,1604 +1,883 @@
P3
-# Standard 224-color Linux logo
@@ -99368,9 +106683,9 @@ diff -Nur linux-3.12.26.orig/drivers/video/logo/logo_linux_clut224.ppm linux-3.1
+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.26.orig/drivers/video/Makefile linux-3.12.26/drivers/video/Makefile
---- linux-3.12.26.orig/drivers/video/Makefile 2014-07-30 18:02:44.000000000 +0200
-+++ linux-3.12.26/drivers/video/Makefile 2014-08-06 16:50:14.953965920 +0200
+diff -Nur linux-3.12.33/drivers/video/Makefile linux-3.12.33-rpi/drivers/video/Makefile
+--- linux-3.12.33/drivers/video/Makefile 2014-11-15 06:28:07.000000000 -0600
++++ linux-3.12.33-rpi/drivers/video/Makefile 2014-12-03 19:13:40.336418001 -0600
@@ -100,6 +100,7 @@
obj-$(CONFIG_FB_VOODOO1) += sstfb.o
obj-$(CONFIG_FB_ARMCLCD) += amba-clcd.o
@@ -99379,58 +106694,26 @@ diff -Nur linux-3.12.26.orig/drivers/video/Makefile linux-3.12.26/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.26.orig/drivers/video/sh_mobile_lcdcfb.c linux-3.12.26/drivers/video/sh_mobile_lcdcfb.c
---- linux-3.12.26.orig/drivers/video/sh_mobile_lcdcfb.c 2014-07-30 18:02:44.000000000 +0200
-+++ linux-3.12.26/drivers/video/sh_mobile_lcdcfb.c 2014-08-06 16:50:14.953965920 +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.26.orig/drivers/w1/masters/w1-gpio.c linux-3.12.26/drivers/w1/masters/w1-gpio.c
---- linux-3.12.26.orig/drivers/w1/masters/w1-gpio.c 2014-07-30 18:02:44.000000000 +0200
-+++ linux-3.12.26/drivers/w1/masters/w1-gpio.c 2014-08-06 16:50:14.961965982 +0200
-@@ -22,6 +22,9 @@
+diff -Nur linux-3.12.33/drivers/w1/masters/w1-gpio.c linux-3.12.33-rpi/drivers/w1/masters/w1-gpio.c
+--- linux-3.12.33/drivers/w1/masters/w1-gpio.c 2014-11-15 06:28:07.000000000 -0600
++++ linux-3.12.33-rpi/drivers/w1/masters/w1-gpio.c 2014-12-03 19:13:42.580418001 -0600
+@@ -22,6 +22,15 @@
#include "../w1.h"
#include "../w1_int.h"
-+static int w1_gpio_pullup = 0;
++static int w1_gpio_pullup = -1;
++static int w1_gpio_pullup_orig = -1;
+module_param_named(pullup, w1_gpio_pullup, int, 0);
++MODULE_PARM_DESC(pullup, "GPIO pin pullup number");
++static int w1_gpio_pin = -1;
++static int w1_gpio_pin_orig = -1;
++module_param_named(gpiopin, w1_gpio_pin, int, 0);
++MODULE_PARM_DESC(gpiopin, "GPIO pin number");
+
static void w1_gpio_write_bit_dir(void *data, u8 bit)
{
struct w1_gpio_platform_data *pdata = data;
-@@ -46,6 +49,16 @@
+@@ -46,6 +55,16 @@
return gpio_get_value(pdata->pin) ? 1 : 0;
}
@@ -99447,23 +106730,82 @@ diff -Nur linux-3.12.26.orig/drivers/w1/masters/w1-gpio.c linux-3.12.26/drivers/
#if defined(CONFIG_OF)
static struct of_device_id w1_gpio_dt_ids[] = {
{ .compatible = "w1-gpio" },
-@@ -127,6 +140,13 @@
+@@ -76,14 +95,16 @@
+ static int w1_gpio_probe(struct platform_device *pdev)
+ {
+ struct w1_bus_master *master;
+- struct w1_gpio_platform_data *pdata;
++ struct w1_gpio_platform_data *pdata = pdev->dev.platform_data;
+ int err;
+
+- if (of_have_populated_dt()) {
+- err = w1_gpio_probe_dt(pdev);
+- if (err < 0) {
+- dev_err(&pdev->dev, "Failed to parse DT\n");
+- return err;
++ if(pdata == NULL) {
++ if (of_have_populated_dt()) {
++ err = w1_gpio_probe_dt(pdev);
++ if (err < 0) {
++ dev_err(&pdev->dev, "Failed to parse DT\n");
++ return err;
++ }
+ }
+ }
+
+@@ -100,6 +121,19 @@
+ return -ENOMEM;
+ }
+
++ w1_gpio_pin_orig = pdata->pin;
++ w1_gpio_pullup_orig = pdata->ext_pullup_enable_pin;
++
++ if(gpio_is_valid(w1_gpio_pin)) {
++ pdata->pin = w1_gpio_pin;
++ pdata->ext_pullup_enable_pin = -1;
++ }
++ if(gpio_is_valid(w1_gpio_pullup)) {
++ pdata->ext_pullup_enable_pin = w1_gpio_pullup;
++ }
++
++ dev_info(&pdev->dev, "gpio pin %d, gpio pullup pin %d\n", pdata->pin, pdata->ext_pullup_enable_pin);
++
+ err = gpio_request(pdata->pin, "w1");
+ if (err) {
+ dev_err(&pdev->dev, "gpio_request (pin) failed\n");
+@@ -127,6 +161,14 @@
master->write_bit = w1_gpio_write_bit_dir;
}
-+ if (w1_gpio_pullup)
++ if (gpio_is_valid(w1_gpio_pullup)) {
+ if (pdata->is_open_drain)
+ printk(KERN_ERR "w1-gpio 'pullup' option "
+ "doesn't work with open drain GPIO\n");
+ else
+ master->bitbang_pullup = w1_gpio_bitbang_pullup;
++ }
+
err = w1_add_master_device(master);
if (err) {
dev_err(&pdev->dev, "w1_add_master device failed\n");
-diff -Nur linux-3.12.26.orig/drivers/w1/w1.h linux-3.12.26/drivers/w1/w1.h
---- linux-3.12.26.orig/drivers/w1/w1.h 2014-07-30 18:02:44.000000000 +0200
-+++ linux-3.12.26/drivers/w1/w1.h 2014-08-06 16:50:14.973966077 +0200
+@@ -167,8 +209,14 @@
+
+ w1_remove_master_device(master);
+ gpio_free(pdata->pin);
++ if (gpio_is_valid(pdata->ext_pullup_enable_pin))
++ gpio_free(pdata->ext_pullup_enable_pin);
++
+ kfree(master);
+
++ pdata->pin = w1_gpio_pin_orig;
++ pdata->ext_pullup_enable_pin = w1_gpio_pullup_orig;
++
+ return 0;
+ }
+
+diff -Nur linux-3.12.33/drivers/w1/w1.h linux-3.12.33-rpi/drivers/w1/w1.h
+--- linux-3.12.33/drivers/w1/w1.h 2014-11-15 06:28:07.000000000 -0600
++++ linux-3.12.33-rpi/drivers/w1/w1.h 2014-12-03 19:13:42.584418001 -0600
@@ -148,6 +148,12 @@
*/
u8 (*set_pullup)(void *, int);
@@ -99477,9 +106819,9 @@ diff -Nur linux-3.12.26.orig/drivers/w1/w1.h linux-3.12.26/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.26.orig/drivers/w1/w1_int.c linux-3.12.26/drivers/w1/w1_int.c
---- linux-3.12.26.orig/drivers/w1/w1_int.c 2014-07-30 18:02:44.000000000 +0200
-+++ linux-3.12.26/drivers/w1/w1_int.c 2014-08-06 16:50:14.973966077 +0200
+diff -Nur linux-3.12.33/drivers/w1/w1_int.c linux-3.12.33-rpi/drivers/w1/w1_int.c
+--- linux-3.12.33/drivers/w1/w1_int.c 2014-11-15 06:28:07.000000000 -0600
++++ linux-3.12.33-rpi/drivers/w1/w1_int.c 2014-12-03 19:13:42.584418001 -0600
@@ -130,6 +130,20 @@
master->set_pullup = NULL;
}
@@ -99501,9 +106843,9 @@ diff -Nur linux-3.12.26.orig/drivers/w1/w1_int.c linux-3.12.26/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.26.orig/drivers/w1/w1_io.c linux-3.12.26/drivers/w1/w1_io.c
---- linux-3.12.26.orig/drivers/w1/w1_io.c 2014-07-30 18:02:44.000000000 +0200
-+++ linux-3.12.26/drivers/w1/w1_io.c 2014-08-06 16:50:14.973966077 +0200
+diff -Nur linux-3.12.33/drivers/w1/w1_io.c linux-3.12.33-rpi/drivers/w1/w1_io.c
+--- linux-3.12.33/drivers/w1/w1_io.c 2014-11-15 06:28:07.000000000 -0600
++++ linux-3.12.33-rpi/drivers/w1/w1_io.c 2014-12-03 19:13:42.584418001 -0600
@@ -127,10 +127,22 @@
static void w1_post_write(struct w1_master *dev)
{
@@ -99530,9 +106872,9 @@ diff -Nur linux-3.12.26.orig/drivers/w1/w1_io.c linux-3.12.26/drivers/w1/w1_io.c
dev->pullup_duration = 0;
}
}
-diff -Nur linux-3.12.26.orig/drivers/watchdog/bcm2708_wdog.c linux-3.12.26/drivers/watchdog/bcm2708_wdog.c
---- linux-3.12.26.orig/drivers/watchdog/bcm2708_wdog.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-3.12.26/drivers/watchdog/bcm2708_wdog.c 2014-08-06 16:50:15.001966297 +0200
+diff -Nur linux-3.12.33/drivers/watchdog/bcm2708_wdog.c linux-3.12.33-rpi/drivers/watchdog/bcm2708_wdog.c
+--- linux-3.12.33/drivers/watchdog/bcm2708_wdog.c 1969-12-31 18:00:00.000000000 -0600
++++ linux-3.12.33-rpi/drivers/watchdog/bcm2708_wdog.c 2014-12-03 19:13:42.584418001 -0600
@@ -0,0 +1,384 @@
+/*
+ * Broadcom BCM2708 watchdog driver.
@@ -99918,9 +107260,9 @@ diff -Nur linux-3.12.26.orig/drivers/watchdog/bcm2708_wdog.c linux-3.12.26/drive
+MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
+MODULE_ALIAS_MISCDEV(TEMP_MINOR);
+MODULE_LICENSE("GPL");
-diff -Nur linux-3.12.26.orig/drivers/watchdog/Kconfig linux-3.12.26/drivers/watchdog/Kconfig
---- linux-3.12.26.orig/drivers/watchdog/Kconfig 2014-07-30 18:02:44.000000000 +0200
-+++ linux-3.12.26/drivers/watchdog/Kconfig 2014-08-06 16:50:15.017966422 +0200
+diff -Nur linux-3.12.33/drivers/watchdog/Kconfig linux-3.12.33-rpi/drivers/watchdog/Kconfig
+--- linux-3.12.33/drivers/watchdog/Kconfig 2014-11-15 06:28:07.000000000 -0600
++++ linux-3.12.33-rpi/drivers/watchdog/Kconfig 2014-12-03 19:13:42.584418001 -0600
@@ -392,6 +392,12 @@
To compile this driver as a module, choose M here: the
module will be called retu_wdt.
@@ -99934,9 +107276,9 @@ diff -Nur linux-3.12.26.orig/drivers/watchdog/Kconfig linux-3.12.26/drivers/watc
# AVR32 Architecture
config AT32AP700X_WDT
-diff -Nur linux-3.12.26.orig/drivers/watchdog/Makefile linux-3.12.26/drivers/watchdog/Makefile
---- linux-3.12.26.orig/drivers/watchdog/Makefile 2014-07-30 18:02:44.000000000 +0200
-+++ linux-3.12.26/drivers/watchdog/Makefile 2014-08-06 16:50:15.017966422 +0200
+diff -Nur linux-3.12.33/drivers/watchdog/Makefile linux-3.12.33-rpi/drivers/watchdog/Makefile
+--- linux-3.12.33/drivers/watchdog/Makefile 2014-11-15 06:28:07.000000000 -0600
++++ linux-3.12.33-rpi/drivers/watchdog/Makefile 2014-12-03 19:13:42.584418001 -0600
@@ -54,6 +54,7 @@
obj-$(CONFIG_IMX2_WDT) += imx2_wdt.o
obj-$(CONFIG_UX500_WATCHDOG) += ux500_wdt.o
@@ -99945,102 +107287,9 @@ diff -Nur linux-3.12.26.orig/drivers/watchdog/Makefile linux-3.12.26/drivers/wat
obj-$(CONFIG_BCM2835_WDT) += bcm2835_wdt.o
# AVR32 Architecture
-diff -Nur linux-3.12.26.orig/fs/ext4/inode.c linux-3.12.26/fs/ext4/inode.c
---- linux-3.12.26.orig/fs/ext4/inode.c 2014-07-30 18:02:44.000000000 +0200
-+++ linux-3.12.26/fs/ext4/inode.c 2014-08-06 16:50:15.017966422 +0200
-@@ -4463,12 +4463,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);
-@@ -4478,11 +4473,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.26.orig/fs/nfs/nfs3acl.c linux-3.12.26/fs/nfs/nfs3acl.c
---- linux-3.12.26.orig/fs/nfs/nfs3acl.c 2014-07-30 18:02:44.000000000 +0200
-+++ linux-3.12.26/fs/nfs/nfs3acl.c 2014-08-06 16:50:15.017966422 +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.26.orig/fs/nfs/nfs4xdr.c linux-3.12.26/fs/nfs/nfs4xdr.c
---- linux-3.12.26.orig/fs/nfs/nfs4xdr.c 2014-07-30 18:02:44.000000000 +0200
-+++ linux-3.12.26/fs/nfs/nfs4xdr.c 2014-08-06 16:50:15.021966454 +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.26.orig/include/drm/drm_crtc.h linux-3.12.26/include/drm/drm_crtc.h
---- linux-3.12.26.orig/include/drm/drm_crtc.h 2014-07-30 18:02:44.000000000 +0200
-+++ linux-3.12.26/include/drm/drm_crtc.h 2014-08-06 16:50:15.021966454 +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.26.orig/include/linux/broadcom/vc_cma.h linux-3.12.26/include/linux/broadcom/vc_cma.h
---- linux-3.12.26.orig/include/linux/broadcom/vc_cma.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-3.12.26/include/linux/broadcom/vc_cma.h 2014-08-06 16:50:15.041966611 +0200
+diff -Nur linux-3.12.33/include/linux/broadcom/vc_cma.h linux-3.12.33-rpi/include/linux/broadcom/vc_cma.h
+--- linux-3.12.33/include/linux/broadcom/vc_cma.h 1969-12-31 18:00:00.000000000 -0600
++++ linux-3.12.33-rpi/include/linux/broadcom/vc_cma.h 2014-12-03 19:13:43.040418001 -0600
@@ -0,0 +1,29 @@
+/*****************************************************************************
+* Copyright 2012 Broadcom Corporation. All rights reserved.
@@ -100071,38 +107320,9 @@ diff -Nur linux-3.12.26.orig/include/linux/broadcom/vc_cma.h linux-3.12.26/inclu
+#endif
+
+#endif /* VC_CMA_H */
-diff -Nur linux-3.12.26.orig/include/linux/fb.h linux-3.12.26/include/linux/fb.h
---- linux-3.12.26.orig/include/linux/fb.h 2014-07-30 18:02:44.000000000 +0200
-+++ linux-3.12.26/include/linux/fb.h 2014-08-06 16:50:15.041966611 +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.26.orig/include/linux/futex.h linux-3.12.26/include/linux/futex.h
---- linux-3.12.26.orig/include/linux/futex.h 2014-07-30 18:02:44.000000000 +0200
-+++ linux-3.12.26/include/linux/futex.h 2014-08-06 16:50:15.061966768 +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.26.orig/include/linux/mmc/host.h linux-3.12.26/include/linux/mmc/host.h
---- linux-3.12.26.orig/include/linux/mmc/host.h 2014-07-30 18:02:44.000000000 +0200
-+++ linux-3.12.26/include/linux/mmc/host.h 2014-08-06 16:50:15.069966830 +0200
+diff -Nur linux-3.12.33/include/linux/mmc/host.h linux-3.12.33-rpi/include/linux/mmc/host.h
+--- linux-3.12.33/include/linux/mmc/host.h 2014-11-15 06:28:07.000000000 -0600
++++ linux-3.12.33-rpi/include/linux/mmc/host.h 2014-12-03 19:13:43.132418001 -0600
@@ -281,6 +281,7 @@
MMC_CAP2_PACKED_WR)
#define MMC_CAP2_NO_PRESCAN_POWERUP (1 << 14) /* Don't power up before scan */
@@ -100111,9 +107331,9 @@ diff -Nur linux-3.12.26.orig/include/linux/mmc/host.h linux-3.12.26/include/linu
mmc_pm_flag_t pm_caps; /* supported pm features */
-diff -Nur linux-3.12.26.orig/include/linux/mmc/sdhci.h linux-3.12.26/include/linux/mmc/sdhci.h
---- linux-3.12.26.orig/include/linux/mmc/sdhci.h 2014-07-30 18:02:44.000000000 +0200
-+++ linux-3.12.26/include/linux/mmc/sdhci.h 2014-08-06 16:50:15.069966830 +0200
+diff -Nur linux-3.12.33/include/linux/mmc/sdhci.h linux-3.12.33-rpi/include/linux/mmc/sdhci.h
+--- linux-3.12.33/include/linux/mmc/sdhci.h 2014-11-15 06:28:07.000000000 -0600
++++ linux-3.12.33-rpi/include/linux/mmc/sdhci.h 2014-12-03 19:13:43.132418001 -0600
@@ -100,6 +100,7 @@
#define SDHCI_QUIRK2_BROKEN_HOST_CONTROL (1<<5)
@@ -100138,66 +107358,51 @@ diff -Nur linux-3.12.26.orig/include/linux/mmc/sdhci.h linux-3.12.26/include/lin
struct mmc_data *data; /* Current data request */
unsigned int data_early:1; /* Data finished before cmd */
-diff -Nur linux-3.12.26.orig/include/linux/usb/usbnet.h linux-3.12.26/include/linux/usb/usbnet.h
---- linux-3.12.26.orig/include/linux/usb/usbnet.h 2014-07-30 18:02:44.000000000 +0200
-+++ linux-3.12.26/include/linux/usb/usbnet.h 2014-08-06 16:50:15.069966830 +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.26.orig/include/net/sock.h linux-3.12.26/include/net/sock.h
---- linux-3.12.26.orig/include/net/sock.h 2014-07-30 18:02:44.000000000 +0200
-+++ linux-3.12.26/include/net/sock.h 2014-08-06 16:50:15.069966830 +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.26.orig/include/net/tcp.h linux-3.12.26/include/net/tcp.h
---- linux-3.12.26.orig/include/net/tcp.h 2014-07-30 18:02:44.000000000 +0200
-+++ linux-3.12.26/include/net/tcp.h 2014-08-06 16:50:15.069966830 +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)
+diff -Nur linux-3.12.33/include/linux/platform_data/bcm2708.h linux-3.12.33-rpi/include/linux/platform_data/bcm2708.h
+--- linux-3.12.33/include/linux/platform_data/bcm2708.h 1969-12-31 18:00:00.000000000 -0600
++++ linux-3.12.33-rpi/include/linux/platform_data/bcm2708.h 2014-12-03 19:13:43.200418001 -0600
+@@ -0,0 +1,23 @@
++/*
++ * include/linux/platform_data/bcm2708.h
++ *
++ * 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.
++ *
++ * (C) 2014 Julian Scheel <julian@jusst.de>
++ *
++ */
++#ifndef __BCM2708_H_
++#define __BCM2708_H_
++
++typedef enum {
++ BCM2708_PULL_OFF,
++ BCM2708_PULL_UP,
++ BCM2708_PULL_DOWN
++} bcm2708_gpio_pull_t;
++
++extern int bcm2708_gpio_setpull(struct gpio_chip *gc, unsigned offset,
++ bcm2708_gpio_pull_t value);
++
++#endif
+diff -Nur linux-3.12.33/include/linux/vmstat.h linux-3.12.33-rpi/include/linux/vmstat.h
+--- linux-3.12.33/include/linux/vmstat.h 2014-11-15 06:28:07.000000000 -0600
++++ linux-3.12.33-rpi/include/linux/vmstat.h 2014-12-03 19:13:43.252418001 -0600
+@@ -239,7 +239,11 @@
+ static inline void __dec_zone_state(struct zone *zone, enum zone_stat_item item)
{
-- 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 */
+ atomic_long_dec(&zone->vm_stat[item]);
++ if (item == NR_FILE_DIRTY && unlikely(atomic_long_read(&zone->vm_stat[item]) < 0))
++ atomic_long_set(&zone->vm_stat[item], 0);
+ atomic_long_dec(&vm_stat[item]);
++ if (item == NR_FILE_DIRTY && unlikely(atomic_long_read(&vm_stat[item]) < 0))
++ atomic_long_set(&vm_stat[item], 0);
}
- extern u32 __cookie_v4_init_sequence(const struct iphdr *iph,
-diff -Nur linux-3.12.26.orig/include/sound/soc-dai.h linux-3.12.26/include/sound/soc-dai.h
---- linux-3.12.26.orig/include/sound/soc-dai.h 2014-07-30 18:02:44.000000000 +0200
-+++ linux-3.12.26/include/sound/soc-dai.h 2014-08-06 16:50:15.069966830 +0200
+ static inline void __dec_zone_page_state(struct page *page,
+diff -Nur linux-3.12.33/include/sound/soc-dai.h linux-3.12.33-rpi/include/sound/soc-dai.h
+--- linux-3.12.33/include/sound/soc-dai.h 2014-11-15 06:28:07.000000000 -0600
++++ linux-3.12.33-rpi/include/sound/soc-dai.h 2014-12-03 19:13:43.360418001 -0600
@@ -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);
@@ -100215,9 +107420,9 @@ diff -Nur linux-3.12.26.orig/include/sound/soc-dai.h linux-3.12.26/include/sound
/*
* DAI format configuration
-diff -Nur linux-3.12.26.orig/include/uapi/linux/fb.h linux-3.12.26/include/uapi/linux/fb.h
---- linux-3.12.26.orig/include/uapi/linux/fb.h 2014-07-30 18:02:44.000000000 +0200
-+++ linux-3.12.26/include/uapi/linux/fb.h 2014-08-06 16:50:15.069966830 +0200
+diff -Nur linux-3.12.33/include/uapi/linux/fb.h linux-3.12.33-rpi/include/uapi/linux/fb.h
+--- linux-3.12.33/include/uapi/linux/fb.h 2014-11-15 06:28:07.000000000 -0600
++++ linux-3.12.33-rpi/include/uapi/linux/fb.h 2014-12-03 19:13:43.376418001 -0600
@@ -34,6 +34,11 @@
#define FBIOPUT_MODEINFO 0x4617
#define FBIOGET_DISPINFO 0x4618
@@ -100230,39 +107435,9 @@ diff -Nur linux-3.12.26.orig/include/uapi/linux/fb.h linux-3.12.26/include/uapi/
#define FB_TYPE_PACKED_PIXELS 0 /* Packed Pixels */
#define FB_TYPE_PLANES 1 /* Non interleaved planes */
-diff -Nur linux-3.12.26.orig/include/uapi/linux/fd.h linux-3.12.26/include/uapi/linux/fd.h
---- linux-3.12.26.orig/include/uapi/linux/fd.h 2014-07-30 18:02:44.000000000 +0200
-+++ linux-3.12.26/include/uapi/linux/fd.h 2014-08-06 16:50:15.069966830 +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.26.orig/init/Kconfig linux-3.12.26/init/Kconfig
---- linux-3.12.26.orig/init/Kconfig 2014-07-30 18:02:44.000000000 +0200
-+++ linux-3.12.26/init/Kconfig 2014-08-06 16:50:15.073966862 +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.26.orig/kernel/cgroup.c linux-3.12.26/kernel/cgroup.c
---- linux-3.12.26.orig/kernel/cgroup.c 2014-07-30 18:02:44.000000000 +0200
-+++ linux-3.12.26/kernel/cgroup.c 2014-08-06 16:50:15.073966862 +0200
+diff -Nur linux-3.12.33/kernel/cgroup.c linux-3.12.33-rpi/kernel/cgroup.c
+--- linux-3.12.33/kernel/cgroup.c 2014-11-15 06:28:07.000000000 -0600
++++ linux-3.12.33-rpi/kernel/cgroup.c 2014-12-03 19:13:43.456418001 -0600
@@ -5558,6 +5558,33 @@
}
__setup("cgroup_disable=", cgroup_disable);
@@ -100297,72 +107472,10 @@ diff -Nur linux-3.12.26.orig/kernel/cgroup.c linux-3.12.26/kernel/cgroup.c
/*
* Functons for CSS ID.
*/
-diff -Nur linux-3.12.26.orig/kernel/futex.c linux-3.12.26/kernel/futex.c
---- linux-3.12.26.orig/kernel/futex.c 2014-07-30 18:02:44.000000000 +0200
-+++ linux-3.12.26/kernel/futex.c 2014-08-06 16:50:15.089966988 +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)
-
-@@ -2866,10 +2864,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
-@@ -2883,14 +2881,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.26.orig/lib/nlattr.c linux-3.12.26/lib/nlattr.c
---- linux-3.12.26.orig/lib/nlattr.c 2014-07-30 18:02:44.000000000 +0200
-+++ linux-3.12.26/lib/nlattr.c 2014-08-06 16:50:15.089966988 +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.26.orig/mm/memcontrol.c linux-3.12.26/mm/memcontrol.c
---- linux-3.12.26.orig/mm/memcontrol.c 2014-07-30 18:02:44.000000000 +0200
-+++ linux-3.12.26/mm/memcontrol.c 2014-08-06 16:50:15.101967082 +0200
-@@ -7035,6 +7035,7 @@
+diff -Nur linux-3.12.33/mm/memcontrol.c linux-3.12.33-rpi/mm/memcontrol.c
+--- linux-3.12.33/mm/memcontrol.c 2014-11-15 06:28:07.000000000 -0600
++++ linux-3.12.33-rpi/mm/memcontrol.c 2014-12-03 19:13:43.680418001 -0600
+@@ -7066,6 +7066,7 @@
.base_cftypes = mem_cgroup_files,
.early_init = 0,
.use_id = 1,
@@ -100370,786 +107483,9 @@ diff -Nur linux-3.12.26.orig/mm/memcontrol.c linux-3.12.26/mm/memcontrol.c
};
#ifdef CONFIG_MEMCG_SWAP
-diff -Nur linux-3.12.26.orig/net/8021q/vlan.c linux-3.12.26/net/8021q/vlan.c
---- linux-3.12.26.orig/net/8021q/vlan.c 2014-07-30 18:02:44.000000000 +0200
-+++ linux-3.12.26/net/8021q/vlan.c 2014-08-06 16:50:15.101967082 +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.26.orig/net/8021q/vlan_dev.c linux-3.12.26/net/8021q/vlan_dev.c
---- linux-3.12.26.orig/net/8021q/vlan_dev.c 2014-07-30 18:02:44.000000000 +0200
-+++ linux-3.12.26/net/8021q/vlan_dev.c 2014-08-06 16:50:15.101967082 +0200
-@@ -595,9 +595,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);
- }
-
-@@ -649,8 +646,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.26.orig/net/bridge/br_multicast.c linux-3.12.26/net/bridge/br_multicast.c
---- linux-3.12.26.orig/net/bridge/br_multicast.c 2014-07-30 18:02:44.000000000 +0200
-+++ linux-3.12.26/net/bridge/br_multicast.c 2014-08-06 16:50:15.101967082 +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.26.orig/net/core/netpoll.c linux-3.12.26/net/core/netpoll.c
---- linux-3.12.26.orig/net/core/netpoll.c 2014-07-30 18:02:44.000000000 +0200
-+++ linux-3.12.26/net/core/netpoll.c 2014-08-06 16:50:15.101967082 +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.26.orig/net/core/rtnetlink.c linux-3.12.26/net/core/rtnetlink.c
---- linux-3.12.26.orig/net/core/rtnetlink.c 2014-07-30 18:02:44.000000000 +0200
-+++ linux-3.12.26/net/core/rtnetlink.c 2014-08-06 16:50:15.101967082 +0200
-@@ -2071,13 +2071,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;
-
-@@ -2115,7 +2114,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;
-@@ -2340,8 +2339,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.26.orig/net/core/sock.c linux-3.12.26/net/core/sock.c
---- linux-3.12.26.orig/net/core/sock.c 2014-07-30 18:02:44.000000000 +0200
-+++ linux-3.12.26/net/core/sock.c 2014-08-06 16:50:15.105967113 +0200
-@@ -2408,13 +2408,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.26.orig/net/ipv4/gre_demux.c linux-3.12.26/net/ipv4/gre_demux.c
---- linux-3.12.26.orig/net/ipv4/gre_demux.c 2014-07-30 18:02:44.000000000 +0200
-+++ linux-3.12.26/net/ipv4/gre_demux.c 2014-08-06 16:50:15.105967113 +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.26.orig/net/ipv4/inet_fragment.c linux-3.12.26/net/ipv4/inet_fragment.c
---- linux-3.12.26.orig/net/ipv4/inet_fragment.c 2014-07-30 18:02:44.000000000 +0200
-+++ linux-3.12.26/net/ipv4/inet_fragment.c 2014-08-06 16:50:15.105967113 +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.26.orig/net/ipv4/ipmr.c linux-3.12.26/net/ipv4/ipmr.c
---- linux-3.12.26.orig/net/ipv4/ipmr.c 2014-07-30 18:02:44.000000000 +0200
-+++ linux-3.12.26/net/ipv4/ipmr.c 2014-08-06 16:50:15.105967113 +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.26.orig/net/ipv4/ip_tunnel.c linux-3.12.26/net/ipv4/ip_tunnel.c
---- linux-3.12.26.orig/net/ipv4/ip_tunnel.c 2014-07-30 18:02:44.000000000 +0200
-+++ linux-3.12.26/net/ipv4/ip_tunnel.c 2014-08-06 16:50:15.105967113 +0200
-@@ -415,6 +415,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.26.orig/net/ipv4/ip_tunnel_core.c linux-3.12.26/net/ipv4/ip_tunnel_core.c
---- linux-3.12.26.orig/net/ipv4/ip_tunnel_core.c 2014-07-30 18:02:44.000000000 +0200
-+++ linux-3.12.26/net/ipv4/ip_tunnel_core.c 2014-08-06 16:50:15.105967113 +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.26.orig/net/ipv4/tcp_output.c linux-3.12.26/net/ipv4/tcp_output.c
---- linux-3.12.26.orig/net/ipv4/tcp_output.c 2014-07-30 18:02:44.000000000 +0200
-+++ linux-3.12.26/net/ipv4/tcp_output.c 2014-08-06 16:50:15.105967113 +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.26.orig/net/ipv6/addrconf.c linux-3.12.26/net/ipv6/addrconf.c
---- linux-3.12.26.orig/net/ipv6/addrconf.c 2014-07-30 18:02:44.000000000 +0200
-+++ linux-3.12.26/net/ipv6/addrconf.c 2014-08-06 16:50:15.109967145 +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.26.orig/net/ipv6/exthdrs_offload.c linux-3.12.26/net/ipv6/exthdrs_offload.c
---- linux-3.12.26.orig/net/ipv6/exthdrs_offload.c 2014-07-30 18:02:44.000000000 +0200
-+++ linux-3.12.26/net/ipv6/exthdrs_offload.c 2014-08-06 16:50:15.109967145 +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.26.orig/net/ipv6/icmp.c linux-3.12.26/net/ipv6/icmp.c
---- linux-3.12.26.orig/net/ipv6/icmp.c 2014-07-30 18:02:44.000000000 +0200
-+++ linux-3.12.26/net/ipv6/icmp.c 2014-08-06 16:50:15.109967145 +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.26.orig/net/ipv6/ip6mr.c linux-3.12.26/net/ipv6/ip6mr.c
---- linux-3.12.26.orig/net/ipv6/ip6mr.c 2014-07-30 18:02:44.000000000 +0200
-+++ linux-3.12.26/net/ipv6/ip6mr.c 2014-08-06 16:50:15.109967145 +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.26.orig/net/ipv6/ip6_output.c linux-3.12.26/net/ipv6/ip6_output.c
---- linux-3.12.26.orig/net/ipv6/ip6_output.c 2014-07-30 18:02:44.000000000 +0200
-+++ linux-3.12.26/net/ipv6/ip6_output.c 2014-08-06 16:50:15.113967176 +0200
-@@ -1092,19 +1092,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);
-@@ -1121,7 +1123,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;
-@@ -1203,7 +1205,6 @@
- dst_exthdrlen = 0;
- mtu = cork->fragsize;
- }
-- orig_mtu = mtu;
-
- hh_len = LL_RESERVED_SPACE(rt->dst.dev);
-
-@@ -1283,7 +1284,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;
-
-@@ -1539,8 +1541,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.26.orig/net/ipv6/mcast.c linux-3.12.26/net/ipv6/mcast.c
---- linux-3.12.26.orig/net/ipv6/mcast.c 2014-07-30 18:02:44.000000000 +0200
-+++ linux-3.12.26/net/ipv6/mcast.c 2014-08-06 16:50:15.113967176 +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.26.orig/net/ipv6/ping.c linux-3.12.26/net/ipv6/ping.c
---- linux-3.12.26.orig/net/ipv6/ping.c 2014-07-30 18:02:44.000000000 +0200
-+++ linux-3.12.26/net/ipv6/ping.c 2014-08-06 16:50:15.113967176 +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.26.orig/net/ipv6/route.c linux-3.12.26/net/ipv6/route.c
---- linux-3.12.26.orig/net/ipv6/route.c 2014-07-30 18:02:44.000000000 +0200
-+++ linux-3.12.26/net/ipv6/route.c 2014-08-06 16:50:15.113967176 +0200
-@@ -1501,7 +1501,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.26.orig/net/rds/iw.c linux-3.12.26/net/rds/iw.c
---- linux-3.12.26.orig/net/rds/iw.c 2014-07-30 18:02:44.000000000 +0200
-+++ linux-3.12.26/net/rds/iw.c 2014-08-06 16:50:15.117967208 +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.26.orig/net/sched/sch_fq.c linux-3.12.26/net/sched/sch_fq.c
---- linux-3.12.26.orig/net/sched/sch_fq.c 2014-07-30 18:02:44.000000000 +0200
-+++ linux-3.12.26/net/sched/sch_fq.c 2014-08-06 16:50:15.133967333 +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.26.orig/net/sctp/sm_make_chunk.c linux-3.12.26/net/sctp/sm_make_chunk.c
---- linux-3.12.26.orig/net/sctp/sm_make_chunk.c 2014-07-30 18:02:44.000000000 +0200
-+++ linux-3.12.26/net/sctp/sm_make_chunk.c 2014-08-06 16:50:15.133967333 +0200
-@@ -1434,8 +1434,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.26.orig/net/sctp/sm_statefuns.c linux-3.12.26/net/sctp/sm_statefuns.c
---- linux-3.12.26.orig/net/sctp/sm_statefuns.c 2014-07-30 18:02:44.000000000 +0200
-+++ linux-3.12.26/net/sctp/sm_statefuns.c 2014-08-06 16:50:15.133967333 +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.26.orig/net/socket.c linux-3.12.26/net/socket.c
---- linux-3.12.26.orig/net/socket.c 2014-07-30 18:02:44.000000000 +0200
-+++ linux-3.12.26/net/socket.c 2014-08-06 16:50:15.153967491 +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.26.orig/net/sunrpc/backchannel_rqst.c linux-3.12.26/net/sunrpc/backchannel_rqst.c
---- linux-3.12.26.orig/net/sunrpc/backchannel_rqst.c 2014-07-30 18:02:44.000000000 +0200
-+++ linux-3.12.26/net/sunrpc/backchannel_rqst.c 2014-08-06 16:50:15.157967521 +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.26.orig/net/unix/af_unix.c linux-3.12.26/net/unix/af_unix.c
---- linux-3.12.26.orig/net/unix/af_unix.c 2014-07-30 18:02:44.000000000 +0200
-+++ linux-3.12.26/net/unix/af_unix.c 2014-08-06 16:50:15.161967553 +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.26.orig/security/selinux/hooks.c linux-3.12.26/security/selinux/hooks.c
---- linux-3.12.26.orig/security/selinux/hooks.c 2014-07-30 18:02:44.000000000 +0200
-+++ linux-3.12.26/security/selinux/hooks.c 2014-08-06 16:50:15.161967553 +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.26.orig/sound/arm/bcm2835.c linux-3.12.26/sound/arm/bcm2835.c
---- linux-3.12.26.orig/sound/arm/bcm2835.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-3.12.26/sound/arm/bcm2835.c 2014-08-06 16:50:15.161967553 +0200
+diff -Nur linux-3.12.33/sound/arm/bcm2835.c linux-3.12.33-rpi/sound/arm/bcm2835.c
+--- linux-3.12.33/sound/arm/bcm2835.c 1969-12-31 18:00:00.000000000 -0600
++++ linux-3.12.33-rpi/sound/arm/bcm2835.c 2014-12-03 19:13:44.308418001 -0600
@@ -0,0 +1,420 @@
+/*****************************************************************************
+* Copyright 2011 Broadcom Corporation. All rights reserved.
@@ -101571,9 +107907,9 @@ diff -Nur linux-3.12.26.orig/sound/arm/bcm2835.c linux-3.12.26/sound/arm/bcm2835
+MODULE_DESCRIPTION("Alsa driver for BCM2835 chip");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:bcm2835_alsa");
-diff -Nur linux-3.12.26.orig/sound/arm/bcm2835-ctl.c linux-3.12.26/sound/arm/bcm2835-ctl.c
---- linux-3.12.26.orig/sound/arm/bcm2835-ctl.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-3.12.26/sound/arm/bcm2835-ctl.c 2014-08-06 16:50:15.165967585 +0200
+diff -Nur linux-3.12.33/sound/arm/bcm2835-ctl.c linux-3.12.33-rpi/sound/arm/bcm2835-ctl.c
+--- linux-3.12.33/sound/arm/bcm2835-ctl.c 1969-12-31 18:00:00.000000000 -0600
++++ linux-3.12.33-rpi/sound/arm/bcm2835-ctl.c 2014-12-03 19:13:44.308418001 -0600
@@ -0,0 +1,323 @@
+/*****************************************************************************
+* Copyright 2011 Broadcom Corporation. All rights reserved.
@@ -101898,10 +108234,10 @@ diff -Nur linux-3.12.26.orig/sound/arm/bcm2835-ctl.c linux-3.12.26/sound/arm/bcm
+ }
+ return 0;
+}
-diff -Nur linux-3.12.26.orig/sound/arm/bcm2835.h linux-3.12.26/sound/arm/bcm2835.h
---- linux-3.12.26.orig/sound/arm/bcm2835.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-3.12.26/sound/arm/bcm2835.h 2014-08-06 16:50:15.165967585 +0200
-@@ -0,0 +1,166 @@
+diff -Nur linux-3.12.33/sound/arm/bcm2835.h linux-3.12.33-rpi/sound/arm/bcm2835.h
+--- linux-3.12.33/sound/arm/bcm2835.h 1969-12-31 18:00:00.000000000 -0600
++++ linux-3.12.33-rpi/sound/arm/bcm2835.h 2014-12-03 19:13:44.308418001 -0600
+@@ -0,0 +1,167 @@
+/*****************************************************************************
+* Copyright 2011 Broadcom Corporation. All rights reserved.
+*
@@ -102014,6 +108350,7 @@ diff -Nur linux-3.12.26.orig/sound/arm/bcm2835.h linux-3.12.26/sound/arm/bcm2835
+
+ unsigned int opened;
+ unsigned int spdif_status;
++ struct mutex audio_mutex;
+} bcm2835_chip_t;
+
+typedef struct bcm2835_alsa_stream {
@@ -102068,10 +108405,10 @@ diff -Nur linux-3.12.26.orig/sound/arm/bcm2835.h linux-3.12.26/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.26.orig/sound/arm/bcm2835-pcm.c linux-3.12.26/sound/arm/bcm2835-pcm.c
---- linux-3.12.26.orig/sound/arm/bcm2835-pcm.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-3.12.26/sound/arm/bcm2835-pcm.c 2014-08-06 16:50:15.165967585 +0200
-@@ -0,0 +1,518 @@
+diff -Nur linux-3.12.33/sound/arm/bcm2835-pcm.c linux-3.12.33-rpi/sound/arm/bcm2835-pcm.c
+--- linux-3.12.33/sound/arm/bcm2835-pcm.c 1969-12-31 18:00:00.000000000 -0600
++++ linux-3.12.33-rpi/sound/arm/bcm2835-pcm.c 2014-12-03 19:13:44.308418001 -0600
+@@ -0,0 +1,552 @@
+/*****************************************************************************
+* Copyright 2011 Broadcom Corporation. All rights reserved.
+*
@@ -102193,6 +108530,11 @@ diff -Nur linux-3.12.26.orig/sound/arm/bcm2835-pcm.c linux-3.12.26/sound/arm/bcm
+
+ audio_info(" .. IN (%d)\n", substream->number);
+
++ if(mutex_lock_interruptible(&chip->audio_mutex))
++ {
++ audio_error("Interrupted whilst waiting for lock\n");
++ return -EINTR;
++ }
+ audio_info("Alsa open (%d)\n", substream->number);
+ idx = substream->number;
+
@@ -102219,7 +108561,8 @@ diff -Nur linux-3.12.26.orig/sound/arm/bcm2835-pcm.c linux-3.12.26/sound/arm/bcm
+
+ alsa_stream = kzalloc(sizeof(bcm2835_alsa_stream_t), GFP_KERNEL);
+ if (alsa_stream == NULL) {
-+ return -ENOMEM;
++ err = -ENOMEM;
++ goto out;
+ }
+
+ /* Initialise alsa_stream */
@@ -102235,6 +108578,11 @@ diff -Nur linux-3.12.26.orig/sound/arm/bcm2835-pcm.c linux-3.12.26/sound/arm/bcm
+ alsa_stream->enable_fifo_irq = 0;
+ alsa_stream->fifo_irq_handler = bcm2835_playback_fifo_irq;
+
++ err = bcm2835_audio_open(alsa_stream);
++ if (err != 0) {
++ kfree(alsa_stream);
++ return err;
++ }
+ runtime->private_data = alsa_stream;
+ runtime->private_free = snd_bcm2835_playback_free;
+ if (spdif) {
@@ -102248,11 +108596,6 @@ diff -Nur linux-3.12.26.orig/sound/arm/bcm2835-pcm.c linux-3.12.26/sound/arm/bcm
+ snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_BYTES,
+ 16);
+
-+ err = bcm2835_audio_open(alsa_stream);
-+ if (err != 0) {
-+ kfree(alsa_stream);
-+ return err;
-+ }
+ chip->alsa_stream[idx] = alsa_stream;
+
+ chip->opened |= (1 << idx);
@@ -102260,6 +108603,8 @@ diff -Nur linux-3.12.26.orig/sound/arm/bcm2835-pcm.c linux-3.12.26/sound/arm/bcm
+ alsa_stream->draining = 1;
+
+out:
++ mutex_unlock(&chip->audio_mutex);
++
+ audio_info(" .. OUT =%d\n", err);
+
+ return err;
@@ -102280,11 +108625,21 @@ diff -Nur linux-3.12.26.orig/sound/arm/bcm2835-pcm.c linux-3.12.26/sound/arm/bcm
+{
+ /* the hardware-specific codes will be here */
+
-+ 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);
++ bcm2835_chip_t *chip;
++ struct snd_pcm_runtime *runtime;
++ bcm2835_alsa_stream_t *alsa_stream;
+
+ audio_info(" .. IN\n");
++
++ chip = snd_pcm_substream_chip(substream);
++ if(mutex_lock_interruptible(&chip->audio_mutex))
++ {
++ audio_error("Interrupted whilst waiting for lock\n");
++ return -EINTR;
++ }
++ runtime = substream->runtime;
++ alsa_stream = runtime->private_data;
++
+ audio_info("Alsa close\n");
+
+ /*
@@ -102315,6 +108670,7 @@ diff -Nur linux-3.12.26.orig/sound/arm/bcm2835-pcm.c linux-3.12.26/sound/arm/bcm
+
+ chip->opened &= ~(1 << substream->number);
+
++ mutex_unlock(&chip->audio_mutex);
+ audio_info(" .. OUT\n");
+
+ return 0;
@@ -102543,6 +108899,12 @@ diff -Nur linux-3.12.26.orig/sound/arm/bcm2835-pcm.c linux-3.12.26/sound/arm/bcm
+ int err;
+
+ audio_info(" .. IN\n");
++ mutex_init(&chip->audio_mutex);
++ if(mutex_lock_interruptible(&chip->audio_mutex))
++ {
++ audio_error("Interrupted whilst waiting for lock\n");
++ return -EINTR;
++ }
+ err =
+ snd_pcm_new(chip->card, "bcm2835 ALSA", 0, MAX_SUBSTREAMS, 0, &pcm);
+ if (err < 0)
@@ -102564,6 +108926,7 @@ diff -Nur linux-3.12.26.orig/sound/arm/bcm2835-pcm.c linux-3.12.26/sound/arm/bcm
+ (GFP_KERNEL), 64 * 1024,
+ 64 * 1024);
+
++ mutex_unlock(&chip->audio_mutex);
+ audio_info(" .. OUT\n");
+
+ return 0;
@@ -102574,6 +108937,12 @@ diff -Nur linux-3.12.26.orig/sound/arm/bcm2835-pcm.c linux-3.12.26/sound/arm/bcm
+ struct snd_pcm *pcm;
+ int err;
+
++ audio_info(" .. IN\n");
++ if(mutex_lock_interruptible(&chip->audio_mutex))
++ {
++ audio_error("Interrupted whilst waiting for lock\n");
++ return -EINTR;
++ }
+ err = snd_pcm_new(chip->card, "bcm2835 ALSA", 1, 1, 0, &pcm);
+ if (err < 0)
+ return err;
@@ -102587,13 +108956,15 @@ diff -Nur linux-3.12.26.orig/sound/arm/bcm2835-pcm.c linux-3.12.26/sound/arm/bcm
+ snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_CONTINUOUS,
+ snd_dma_continuous_data (GFP_KERNEL),
+ 64 * 1024, 64 * 1024);
++ mutex_unlock(&chip->audio_mutex);
++ audio_info(" .. OUT\n");
+
+ return 0;
+}
-diff -Nur linux-3.12.26.orig/sound/arm/bcm2835-vchiq.c linux-3.12.26/sound/arm/bcm2835-vchiq.c
---- linux-3.12.26.orig/sound/arm/bcm2835-vchiq.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-3.12.26/sound/arm/bcm2835-vchiq.c 2014-08-06 16:50:15.165967585 +0200
-@@ -0,0 +1,879 @@
+diff -Nur linux-3.12.33/sound/arm/bcm2835-vchiq.c linux-3.12.33-rpi/sound/arm/bcm2835-vchiq.c
+--- linux-3.12.33/sound/arm/bcm2835-vchiq.c 1969-12-31 18:00:00.000000000 -0600
++++ linux-3.12.33-rpi/sound/arm/bcm2835-vchiq.c 2014-12-03 19:13:44.308418001 -0600
+@@ -0,0 +1,901 @@
+/*****************************************************************************
+* Copyright 2011 Broadcom Corporation. All rights reserved.
+*
@@ -102796,14 +109167,22 @@ diff -Nur linux-3.12.26.orig/sound/arm/bcm2835-vchiq.c linux-3.12.26/sound/arm/b
+ int32_t status;
+ int32_t msg_len;
+ VC_AUDIO_MSG_T m;
-+ bcm2835_alsa_stream_t *alsa_stream = 0;
-+ LOG_DBG(" .. IN instance=%p, param=%p, reason=%d, handle=%p\n",
-+ instance, param, reason, msg_handle);
++ LOG_DBG(" .. IN instance=%p, handle=%p, alsa=%p, reason=%d, handle=%p\n",
++ instance, instance ? instance->vchi_handle[0] : NULL, instance ? instance->alsa_stream : NULL, reason, msg_handle);
+
-+ if (!instance || reason != VCHI_CALLBACK_MSG_AVAILABLE) {
++ if (reason != VCHI_CALLBACK_MSG_AVAILABLE) {
+ return;
+ }
-+ alsa_stream = instance->alsa_stream;
++ if (!instance) {
++ LOG_ERR(" .. instance is null\n");
++ BUG();
++ return;
++ }
++ if (!instance->vchi_handle[0]) {
++ LOG_ERR(" .. instance->vchi_handle[0] is null\n");
++ BUG();
++ return;
++ }
+ status = vchi_msg_dequeue(instance->vchi_handle[0],
+ &m, sizeof m, &msg_len, VCHI_FLAGS_NONE);
+ if (m.type == VC_AUDIO_MSG_TYPE_RESULT) {
@@ -102813,6 +109192,7 @@ diff -Nur linux-3.12.26.orig/sound/arm/bcm2835-vchiq.c linux-3.12.26/sound/arm/b
+ instance->result = m.u.result.success;
+ complete(&instance->msg_avail_comp);
+ } else if (m.type == VC_AUDIO_MSG_TYPE_COMPLETE) {
++ bcm2835_alsa_stream_t *alsa_stream = instance->alsa_stream;
+ irq_handler_t callback = (irq_handler_t) m.u.complete.callback;
+ LOG_DBG
+ (" .. instance=%p, m.type=VC_AUDIO_MSG_TYPE_COMPLETE, complete=%d\n",
@@ -102821,11 +109201,11 @@ diff -Nur linux-3.12.26.orig/sound/arm/bcm2835-vchiq.c linux-3.12.26/sound/arm/b
+ atomic_add(m.u.complete.count, &alsa_stream->retrieved);
+ callback(0, alsa_stream);
+ } else {
-+ LOG_DBG(" .. unexpected alsa_stream=%p, callback=%p\n",
++ LOG_ERR(" .. unexpected alsa_stream=%p, callback=%p\n",
+ alsa_stream, callback);
+ }
+ } else {
-+ LOG_DBG(" .. unexpected m.type=%d\n", m.type);
++ LOG_ERR(" .. unexpected m.type=%d\n", m.type);
+ }
+ LOG_DBG(" .. OUT\n");
+}
@@ -102848,9 +109228,10 @@ diff -Nur linux-3.12.26.orig/sound/arm/bcm2835-vchiq.c linux-3.12.26/sound/arm/b
+ return NULL;
+ }
+ /* Allocate memory for this instance */
-+ instance = kmalloc(sizeof(*instance), GFP_KERNEL);
++ instance = kzalloc(sizeof(*instance), GFP_KERNEL);
++ if (!instance)
++ return NULL;
+
-+ memset(instance, 0, sizeof(*instance));
+ instance->num_connections = num_connections;
+
+ /* Create a lock for exclusive, serialized VCHI connection access */
@@ -102870,8 +109251,10 @@ diff -Nur linux-3.12.26.orig/sound/arm/bcm2835-vchiq.c linux-3.12.26/sound/arm/b
+ 0 // want crc check on bulk transfers
+ };
+
++ LOG_DBG("%s: about to open %i\n", __func__, i);
+ status = vchi_service_open(vchi_instance, &params,
+ &instance->vchi_handle[i]);
++ LOG_DBG("%s: opened %i: %p=%d\n", __func__, i, instance->vchi_handle[i], status);
+ if (status) {
+ LOG_ERR
+ ("%s: failed to open VCHI service connection (status=%d)\n",
@@ -102883,14 +109266,18 @@ diff -Nur linux-3.12.26.orig/sound/arm/bcm2835-vchiq.c linux-3.12.26/sound/arm/b
+ vchi_service_release(instance->vchi_handle[i]);
+ }
+
++ LOG_DBG("%s: okay\n", __func__);
+ return instance;
+
+err_close_services:
+ for (i = 0; i < instance->num_connections; i++) {
-+ vchi_service_close(instance->vchi_handle[i]);
++ LOG_ERR("%s: closing %i: %p\n", __func__, i, instance->vchi_handle[i]);
++ if (instance->vchi_handle[i])
++ vchi_service_close(instance->vchi_handle[i]);
+ }
+
+ kfree(instance);
++ LOG_ERR("%s: error\n", __func__);
+
+ return NULL;
+}
@@ -102941,12 +109328,13 @@ diff -Nur linux-3.12.26.orig/sound/arm/bcm2835-vchiq.c linux-3.12.26/sound/arm/b
+{
+ static VCHI_INSTANCE_T vchi_instance;
+ static VCHI_CONNECTION_T *vchi_connection;
++ static int initted;
+ AUDIO_INSTANCE_T *instance = alsa_stream->instance;
+ int ret;
+ LOG_DBG(" .. IN\n");
+
-+ LOG_INFO("%s: start", __func__);
-+ //BUG_ON(instance);
++ LOG_INFO("%s: start\n", __func__);
++ BUG_ON(instance);
+ if (instance) {
+ LOG_ERR("%s: VCHI instance already open (%p)\n",
+ __func__, instance);
@@ -102957,27 +109345,30 @@ diff -Nur linux-3.12.26.orig/sound/arm/bcm2835-vchiq.c linux-3.12.26/sound/arm/b
+ }
+
+ /* Initialize and create a VCHI connection */
-+ ret = vchi_initialise(&vchi_instance);
-+ if (ret != 0) {
-+ LOG_ERR("%s: failed to initialise VCHI instance (ret=%d)\n",
-+ __func__, ret);
-+
-+ ret = -EIO;
-+ goto err_free_mem;
-+ }
-+ ret = vchi_connect(NULL, 0, vchi_instance);
-+ if (ret != 0) {
-+ LOG_ERR("%s: failed to connect VCHI instance (ret=%d)\n",
-+ __func__, ret);
-+
-+ ret = -EIO;
-+ goto err_free_mem;
++ if (!initted) {
++ ret = vchi_initialise(&vchi_instance);
++ if (ret != 0) {
++ LOG_ERR("%s: failed to initialise VCHI instance (ret=%d)\n",
++ __func__, ret);
++
++ ret = -EIO;
++ goto err_free_mem;
++ }
++ ret = vchi_connect(NULL, 0, vchi_instance);
++ if (ret != 0) {
++ LOG_ERR("%s: failed to connect VCHI instance (ret=%d)\n",
++ __func__, ret);
++
++ ret = -EIO;
++ goto err_free_mem;
++ }
++ initted = 1;
+ }
+
+ /* Initialize an instance of the audio service */
+ instance = vc_vchi_audio_init(vchi_instance, &vchi_connection, 1);
+
-+ if (instance == NULL /*|| audio_handle != instance */ ) {
++ if (instance == NULL) {
+ LOG_ERR("%s: failed to initialize audio service\n", __func__);
+
+ ret = -EPERM;
@@ -103010,6 +109401,7 @@ diff -Nur linux-3.12.26.orig/sound/arm/bcm2835-vchiq.c linux-3.12.26/sound/arm/b
+ goto exit;
+ }
+ instance = alsa_stream->instance;
++ LOG_DBG(" instance (%p)\n", instance);
+
+ if(mutex_lock_interruptible(&instance->vchi_mutex))
+ {
@@ -103114,6 +109506,7 @@ diff -Nur linux-3.12.26.orig/sound/arm/bcm2835-vchiq.c linux-3.12.26/sound/arm/b
+ int i;
+ int ret = 0;
+ LOG_DBG(" .. IN\n");
++ LOG_DBG(" Setting ALSA dest(%d), volume(%d)\n", chip->dest, chip->volume);
+
+ /* change ctls for all substreams */
+ for (i = 0; i < MAX_SUBSTREAMS; i++) {
@@ -103126,7 +109519,7 @@ diff -Nur linux-3.12.26.orig/sound/arm/bcm2835-vchiq.c linux-3.12.26/sound/arm/b
+ else if (bcm2835_audio_set_ctls_chan /* returns 0 on success */
+ (chip->alsa_stream[i], chip) != 0)
+ {
-+ LOG_DBG("Couldn't set the controls for stream %d\n", i);
++ LOG_ERR("Couldn't set the controls for stream %d\n", i);
+ ret = -1;
+ }
+ else LOG_DBG(" Controls set for stream %d\n", i);
@@ -103244,7 +109637,7 @@ diff -Nur linux-3.12.26.orig/sound/arm/bcm2835-vchiq.c linux-3.12.26/sound/arm/b
+ VCHI_FLAGS_BLOCK_UNTIL_QUEUED, NULL);
+
+ if (success != 0) {
-+ LOG_ERR("%s: failed on vchi_msg_queue (status=%d)",
++ LOG_ERR("%s: failed on vchi_msg_queue (status=%d)\n",
+ __func__, success);
+
+ ret = -1;
@@ -103284,7 +109677,7 @@ diff -Nur linux-3.12.26.orig/sound/arm/bcm2835-vchiq.c linux-3.12.26/sound/arm/b
+ VCHI_FLAGS_BLOCK_UNTIL_QUEUED, NULL);
+
+ if (success != 0) {
-+ LOG_ERR("%s: failed on vchi_msg_queue (status=%d)",
++ LOG_ERR("%s: failed on vchi_msg_queue (status=%d)\n",
+ __func__, success);
+
+ ret = -1;
@@ -103328,7 +109721,7 @@ diff -Nur linux-3.12.26.orig/sound/arm/bcm2835-vchiq.c linux-3.12.26/sound/arm/b
+ VCHI_FLAGS_BLOCK_UNTIL_QUEUED, NULL);
+
+ if (success != 0) {
-+ LOG_ERR("%s: failed on vchi_msg_queue (status=%d)",
++ LOG_ERR("%s: failed on vchi_msg_queue (status=%d)\n",
+ __func__, success);
+ ret = -1;
+ goto unlock;
@@ -103336,12 +109729,12 @@ diff -Nur linux-3.12.26.orig/sound/arm/bcm2835-vchiq.c linux-3.12.26/sound/arm/b
+
+ ret = wait_for_completion_interruptible(&instance->msg_avail_comp);
+ if (ret) {
-+ LOG_ERR("%s: failed on waiting for event (status=%d)",
++ LOG_ERR("%s: failed on waiting for event (status=%d)\n",
+ __func__, success);
+ goto unlock;
+ }
+ if (instance->result != 0) {
-+ LOG_ERR("%s: failed result (status=%d)",
++ LOG_ERR("%s: failed result (status=%d)\n",
+ __func__, instance->result);
+
+ ret = -1;
@@ -103399,7 +109792,7 @@ diff -Nur linux-3.12.26.orig/sound/arm/bcm2835-vchiq.c linux-3.12.26/sound/arm/b
+ VCHI_FLAGS_BLOCK_UNTIL_QUEUED, NULL);
+
+ if (success != 0) {
-+ LOG_ERR("%s: failed on vchi_msg_queue (status=%d)",
++ LOG_ERR("%s: failed on vchi_msg_queue (status=%d)\n",
+ __func__, success);
+
+ ret = -1;
@@ -103428,7 +109821,7 @@ diff -Nur linux-3.12.26.orig/sound/arm/bcm2835-vchiq.c linux-3.12.26/sound/arm/b
+ }
+ if (success != 0) {
+ LOG_ERR
-+ ("%s: failed on vchi_bulk_queue_transmit (status=%d)",
++ ("%s: failed on vchi_bulk_queue_transmit (status=%d)\n",
+ __func__, success);
+
+ ret = -1;
@@ -103473,9 +109866,9 @@ diff -Nur linux-3.12.26.orig/sound/arm/bcm2835-vchiq.c linux-3.12.26/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.26.orig/sound/arm/Kconfig linux-3.12.26/sound/arm/Kconfig
---- linux-3.12.26.orig/sound/arm/Kconfig 2014-07-30 18:02:44.000000000 +0200
-+++ linux-3.12.26/sound/arm/Kconfig 2014-08-06 16:50:15.165967585 +0200
+diff -Nur linux-3.12.33/sound/arm/Kconfig linux-3.12.33-rpi/sound/arm/Kconfig
+--- linux-3.12.33/sound/arm/Kconfig 2014-11-15 06:28:07.000000000 -0600
++++ linux-3.12.33-rpi/sound/arm/Kconfig 2014-12-03 19:13:44.288418001 -0600
@@ -39,5 +39,12 @@
Say Y or M if you want to support any AC97 codec attached to
the PXA2xx AC97 interface.
@@ -103489,9 +109882,9 @@ diff -Nur linux-3.12.26.orig/sound/arm/Kconfig linux-3.12.26/sound/arm/Kconfig
+
endif # SND_ARM
-diff -Nur linux-3.12.26.orig/sound/arm/Makefile linux-3.12.26/sound/arm/Makefile
---- linux-3.12.26.orig/sound/arm/Makefile 2014-07-30 18:02:44.000000000 +0200
-+++ linux-3.12.26/sound/arm/Makefile 2014-08-06 16:50:15.165967585 +0200
+diff -Nur linux-3.12.33/sound/arm/Makefile linux-3.12.33-rpi/sound/arm/Makefile
+--- linux-3.12.33/sound/arm/Makefile 2014-11-15 06:28:07.000000000 -0600
++++ linux-3.12.33-rpi/sound/arm/Makefile 2014-12-03 19:13:44.288418001 -0600
@@ -14,3 +14,8 @@
obj-$(CONFIG_SND_PXA2XX_AC97) += snd-pxa2xx-ac97.o
@@ -103501,9 +109894,9 @@ diff -Nur linux-3.12.26.orig/sound/arm/Makefile linux-3.12.26/sound/arm/Makefile
+snd-bcm2835-objs := bcm2835.o bcm2835-ctl.o bcm2835-pcm.o bcm2835-vchiq.o
+
+ccflags-y += -Idrivers/misc/vc04_services -Idrivers/misc/vc04_services/interface/vcos/linuxkernel -D__VCCOREVER__=0x04000000
-diff -Nur linux-3.12.26.orig/sound/arm/vc_vchi_audioserv_defs.h linux-3.12.26/sound/arm/vc_vchi_audioserv_defs.h
---- linux-3.12.26.orig/sound/arm/vc_vchi_audioserv_defs.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-3.12.26/sound/arm/vc_vchi_audioserv_defs.h 2014-08-06 16:50:15.165967585 +0200
+diff -Nur linux-3.12.33/sound/arm/vc_vchi_audioserv_defs.h linux-3.12.33-rpi/sound/arm/vc_vchi_audioserv_defs.h
+--- linux-3.12.33/sound/arm/vc_vchi_audioserv_defs.h 1969-12-31 18:00:00.000000000 -0600
++++ linux-3.12.33-rpi/sound/arm/vc_vchi_audioserv_defs.h 2014-12-03 19:13:44.312418001 -0600
@@ -0,0 +1,116 @@
+/*****************************************************************************
+* Copyright 2011 Broadcom Corporation. All rights reserved.
@@ -103621,10 +110014,10 @@ diff -Nur linux-3.12.26.orig/sound/arm/vc_vchi_audioserv_defs.h linux-3.12.26/so
+} VC_AUDIO_MSG_T;
+
+#endif // _VC_AUDIO_DEFS_H_
-diff -Nur linux-3.12.26.orig/sound/soc/bcm/bcm2708-i2s.c linux-3.12.26/sound/soc/bcm/bcm2708-i2s.c
---- linux-3.12.26.orig/sound/soc/bcm/bcm2708-i2s.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-3.12.26/sound/soc/bcm/bcm2708-i2s.c 2014-08-06 16:50:15.205967899 +0200
-@@ -0,0 +1,945 @@
+diff -Nur linux-3.12.33/sound/soc/bcm/bcm2708-i2s.c linux-3.12.33-rpi/sound/soc/bcm/bcm2708-i2s.c
+--- linux-3.12.33/sound/soc/bcm/bcm2708-i2s.c 1969-12-31 18:00:00.000000000 -0600
++++ linux-3.12.33-rpi/sound/soc/bcm/bcm2708-i2s.c 2014-12-03 19:13:44.596418001 -0600
+@@ -0,0 +1,998 @@
+/*
+ * ALSA SoC I2S Audio Layer for Broadcom BCM2708 SoC
+ *
@@ -103658,6 +110051,8 @@ diff -Nur linux-3.12.26.orig/sound/soc/bcm/bcm2708-i2s.c linux-3.12.26/sound/soc
+ * General Public License for more details.
+ */
+
++#include "bcm2708-i2s.h"
++
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/device.h>
@@ -103665,6 +110060,7 @@ diff -Nur linux-3.12.26.orig/sound/soc/bcm/bcm2708-i2s.c linux-3.12.26/sound/soc
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/clk.h>
++#include <mach/gpio.h>
+
+#include <sound/core.h>
+#include <sound/pcm.h>
@@ -103673,6 +110069,8 @@ diff -Nur linux-3.12.26.orig/sound/soc/bcm/bcm2708-i2s.c linux-3.12.26/sound/soc
+#include <sound/soc.h>
+#include <sound/dmaengine_pcm.h>
+
++#include <asm/system_info.h>
++
+/* Clock registers */
+#define BCM2708_CLK_PCMCTL_REG 0x00
+#define BCM2708_CLK_PCMDIV_REG 0x04
@@ -103790,6 +110188,9 @@ diff -Nur linux-3.12.26.orig/sound/soc/bcm/bcm2708-i2s.c linux-3.12.26/sound/soc
+#define BCM2708_DMA_DREQ_PCM_TX 2
+#define BCM2708_DMA_DREQ_PCM_RX 3
+
++/* I2S pin configuration */
++static int bcm2708_i2s_gpio=BCM2708_I2S_GPIO_AUTO;
++
+/* General device struct */
+struct bcm2708_i2s_dev {
+ struct device *dev;
@@ -103801,6 +110202,12 @@ diff -Nur linux-3.12.26.orig/sound/soc/bcm/bcm2708-i2s.c linux-3.12.26/sound/soc
+ struct regmap *clk_regmap;
+};
+
++void bcm2708_i2s_set_gpio(int gpio) {
++ bcm2708_i2s_gpio=gpio;
++}
++EXPORT_SYMBOL(bcm2708_i2s_set_gpio);
++
++
+static void bcm2708_i2s_start_clock(struct bcm2708_i2s_dev *dev)
+{
+ /* Start the clock if in master mode */
@@ -103932,6 +110339,67 @@ diff -Nur linux-3.12.26.orig/sound/soc/bcm/bcm2708-i2s.c linux-3.12.26/sound/soc
+ return 0;
+}
+
++
++static int bcm2708_i2s_set_function(unsigned offset, int function)
++{
++ #define GPIOFSEL(x) (0x00+(x)*4)
++ void __iomem *gpio = __io_address(GPIO_BASE);
++ unsigned alt = function <= 3 ? function + 4: function == 4 ? 3 : 2;
++ unsigned gpiodir;
++ unsigned gpio_bank = offset / 10;
++ unsigned gpio_field_offset = (offset - 10 * gpio_bank) * 3;
++
++ if (offset >= BCM2708_NR_GPIOS)
++ return -EINVAL;
++
++ gpiodir = readl(gpio + GPIOFSEL(gpio_bank));
++ gpiodir &= ~(7 << gpio_field_offset);
++ gpiodir |= alt << gpio_field_offset;
++ writel(gpiodir, gpio + GPIOFSEL(gpio_bank));
++ return 0;
++}
++
++static void bcm2708_i2s_setup_gpio(void)
++{
++ /*
++ * This is the common way to handle the GPIO pins for
++ * the Raspberry Pi.
++ * TODO Better way would be to handle
++ * this in the device tree!
++ */
++ int pin,pinconfig,startpin,alt;
++
++ /* SPI is on different GPIOs on different boards */
++ /* for Raspberry Pi B+, this is pin GPIO18-21, for original on 28-31 */
++ if (bcm2708_i2s_gpio==BCM2708_I2S_GPIO_AUTO) {
++ if ((system_rev & 0xffffff) >= 0x10) {
++ /* Model B+ */
++ pinconfig=BCM2708_I2S_GPIO_PIN18;
++ } else {
++ /* original */
++ pinconfig=BCM2708_I2S_GPIO_PIN28;
++ }
++ } else {
++ pinconfig=bcm2708_i2s_gpio;
++ }
++
++ if (pinconfig==BCM2708_I2S_GPIO_PIN18) {
++ startpin=18;
++ alt=BCM2708_I2S_GPIO_PIN18_ALT;
++ } else if (pinconfig==BCM2708_I2S_GPIO_PIN28) {
++ startpin=28;
++ alt=BCM2708_I2S_GPIO_PIN28_ALT;
++ } else {
++ printk(KERN_INFO "Can't configure I2S GPIOs, unknown pin mode for I2S: %i\n",pinconfig);
++ return;
++ }
++
++ /* configure I2S pins to correct ALT mode */
++ for (pin = startpin; pin <= startpin+3; pin++) {
++ bcm2708_i2s_set_function(pin, alt);
++ }
++}
++
+static int bcm2708_i2s_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params,
+ struct snd_soc_dai *dai)
@@ -103961,6 +110429,9 @@ diff -Nur linux-3.12.26.orig/sound/soc/bcm/bcm2708-i2s.c linux-3.12.26/sound/soc
+ if (csreg & (BCM2708_I2S_TXON | BCM2708_I2S_RXON))
+ return 0;
+
++
++ bcm2708_i2s_setup_gpio();
++
+ /*
+ * Adjust the data length according to the format.
+ * We prefill the half frame length with an integer
@@ -103971,15 +110442,15 @@ diff -Nur linux-3.12.26.orig/sound/soc/bcm/bcm2708-i2s.c linux-3.12.26/sound/soc
+ switch (params_format(params)) {
+ case SNDRV_PCM_FORMAT_S16_LE:
+ data_length = 16;
-+ bclk_ratio = 40;
++ bclk_ratio = 50;
+ break;
+ case SNDRV_PCM_FORMAT_S24_LE:
+ data_length = 24;
-+ bclk_ratio = 40;
++ bclk_ratio = 50;
+ break;
+ case SNDRV_PCM_FORMAT_S32_LE:
+ data_length = 32;
-+ bclk_ratio = 80;
++ bclk_ratio = 100;
+ break;
+ default:
+ return -EINVAL;
@@ -104345,7 +110816,7 @@ diff -Nur linux-3.12.26.orig/sound/soc/bcm/bcm2708-i2s.c linux-3.12.26/sound/soc
+ .channels_max = 2,
+ .rates = SNDRV_PCM_RATE_8000_192000,
+ .formats = SNDRV_PCM_FMTBIT_S16_LE
-+ // | SNDRV_PCM_FMTBIT_S24_LE : disable for now, it causes white noise with xbmc
++ | SNDRV_PCM_FMTBIT_S24_LE
+ | SNDRV_PCM_FMTBIT_S32_LE
+ },
+ .capture = {
@@ -104402,6 +110873,7 @@ diff -Nur linux-3.12.26.orig/sound/soc/bcm/bcm2708-i2s.c linux-3.12.26/sound/soc
+ .precious_reg = bcm2708_i2s_precious_reg,
+ .volatile_reg = bcm2708_i2s_volatile_reg,
+ .cache_type = REGCACHE_RBTREE,
++ .name = "i2s",
+ },
+ {
+ .reg_bits = 32,
@@ -104410,6 +110882,7 @@ diff -Nur linux-3.12.26.orig/sound/soc/bcm/bcm2708-i2s.c linux-3.12.26/sound/soc
+ .max_register = BCM2708_CLK_PCMDIV_REG,
+ .volatile_reg = bcm2708_clk_volatile_reg,
+ .cache_type = REGCACHE_RBTREE,
++ .name = "clk",
+ },
+};
+
@@ -104417,31 +110890,6 @@ diff -Nur linux-3.12.26.orig/sound/soc/bcm/bcm2708-i2s.c linux-3.12.26/sound/soc
+ .name = "bcm2708-i2s-comp",
+};
+
-+
-+static void bcm2708_i2s_setup_gpio(void)
-+{
-+ /*
-+ * This is the common way to handle the GPIO pins for
-+ * the Raspberry Pi.
-+ * TODO Better way would be to handle
-+ * this in the device tree!
-+ */
-+#define INP_GPIO(g) *(gpio+((g)/10)) &= ~(7<<(((g)%10)*3))
-+#define SET_GPIO_ALT(g,a) *(gpio+(((g)/10))) |= (((a)<=3?(a)+4:(a)==4?3:2)<<(((g)%10)*3))
-+
-+ unsigned int *gpio;
-+ int pin;
-+ gpio = ioremap(GPIO_BASE, SZ_16K);
-+
-+ /* SPI is on GPIO 7..11 */
-+ for (pin = 28; pin <= 31; pin++) {
-+ INP_GPIO(pin); /* set mode to GPIO input first */
-+ SET_GPIO_ALT(pin, 2); /* set mode to ALT 0 */
-+ }
-+#undef INP_GPIO
-+#undef SET_GPIO_ALT
-+}
-+
+static const struct snd_pcm_hardware bcm2708_pcm_hardware = {
+ .info = SNDRV_PCM_INFO_INTERLEAVED |
+ SNDRV_PCM_INFO_JOINT_DUPLEX,
@@ -104492,8 +110940,6 @@ diff -Nur linux-3.12.26.orig/sound/soc/bcm/bcm2708-i2s.c linux-3.12.26/sound/soc
+ if (IS_ERR(dev))
+ return PTR_ERR(dev);
+
-+ bcm2708_i2s_setup_gpio();
-+
+ dev->i2s_regmap = regmap[0];
+ dev->clk_regmap = regmap[1];
+
@@ -104570,9 +111016,158 @@ diff -Nur linux-3.12.26.orig/sound/soc/bcm/bcm2708-i2s.c linux-3.12.26/sound/soc
+MODULE_DESCRIPTION("BCM2708 I2S interface");
+MODULE_AUTHOR("Florian Meier <florian.meier@koalo.de>");
+MODULE_LICENSE("GPL v2");
-diff -Nur linux-3.12.26.orig/sound/soc/bcm/hifiberry_dac.c linux-3.12.26/sound/soc/bcm/hifiberry_dac.c
---- linux-3.12.26.orig/sound/soc/bcm/hifiberry_dac.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-3.12.26/sound/soc/bcm/hifiberry_dac.c 2014-08-06 16:50:15.205967899 +0200
+diff -Nur linux-3.12.33/sound/soc/bcm/bcm2708-i2s.h linux-3.12.33-rpi/sound/soc/bcm/bcm2708-i2s.h
+--- linux-3.12.33/sound/soc/bcm/bcm2708-i2s.h 1969-12-31 18:00:00.000000000 -0600
++++ linux-3.12.33-rpi/sound/soc/bcm/bcm2708-i2s.h 2014-12-03 19:13:44.596418001 -0600
+@@ -0,0 +1,35 @@
++/*
++ * I2S configuration for sound cards.
++ *
++ * Copyright (c) 2014 Daniel Matuschek <daniel@hifiberry.com>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++ */
++
++#ifndef BCM2708_I2S_H
++#define BCM2708_I2S_H
++
++/* I2S pin assignment */
++#define BCM2708_I2S_GPIO_AUTO 0
++#define BCM2708_I2S_GPIO_PIN18 1
++#define BCM2708_I2S_GPIO_PIN28 2
++
++/* Alt mode to enable I2S */
++#define BCM2708_I2S_GPIO_PIN18_ALT 0
++#define BCM2708_I2S_GPIO_PIN28_ALT 2
++
++extern void bcm2708_i2s_set_gpio(int gpio);
++
++#endif
+diff -Nur linux-3.12.33/sound/soc/bcm/hifiberry_amp.c linux-3.12.33-rpi/sound/soc/bcm/hifiberry_amp.c
+--- linux-3.12.33/sound/soc/bcm/hifiberry_amp.c 1969-12-31 18:00:00.000000000 -0600
++++ linux-3.12.33-rpi/sound/soc/bcm/hifiberry_amp.c 2014-12-03 19:13:44.596418001 -0600
+@@ -0,0 +1,106 @@
++/*
++ * ASoC Driver for HifiBerry AMP
++ *
++ * Author: Sebastian Eickhoff <basti.eickhoff@googlemail.com>
++ * Copyright 2014
++ *
++ * 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_hifiberry_amp_init(struct snd_soc_pcm_runtime *rtd)
++{
++ // ToDo: init of the dsp-registers.
++ return 0;
++}
++
++static int snd_rpi_hifiberry_amp_hw_params( struct snd_pcm_substream *substream,
++ struct snd_pcm_hw_params *params )
++{
++ struct snd_soc_pcm_runtime *rtd = substream->private_data;
++ struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
++
++ return snd_soc_dai_set_bclk_ratio(cpu_dai, 64);
++}
++
++static struct snd_soc_ops snd_rpi_hifiberry_amp_ops = {
++ .hw_params = snd_rpi_hifiberry_amp_hw_params,
++};
++
++static struct snd_soc_dai_link snd_rpi_hifiberry_amp_dai[] = {
++ {
++ .name = "HifiBerry AMP",
++ .stream_name = "HifiBerry AMP HiFi",
++ .cpu_dai_name = "bcm2708-i2s.0",
++ .codec_dai_name = "tas5713-hifi",
++ .platform_name = "bcm2708-i2s.0",
++ .codec_name = "tas5713.1-001b",
++ .dai_fmt = SND_SOC_DAIFMT_I2S |
++ SND_SOC_DAIFMT_NB_NF |
++ SND_SOC_DAIFMT_CBS_CFS,
++ .ops = &snd_rpi_hifiberry_amp_ops,
++ .init = snd_rpi_hifiberry_amp_init,
++ },
++};
++
++
++static struct snd_soc_card snd_rpi_hifiberry_amp = {
++ .name = "snd_rpi_hifiberry_amp",
++ .dai_link = snd_rpi_hifiberry_amp_dai,
++ .num_links = ARRAY_SIZE(snd_rpi_hifiberry_amp_dai),
++};
++
++
++static int snd_rpi_hifiberry_amp_probe(struct platform_device *pdev)
++{
++ int ret = 0;
++
++ snd_rpi_hifiberry_amp.dev = &pdev->dev;
++
++ ret = snd_soc_register_card(&snd_rpi_hifiberry_amp);
++
++ if (ret != 0) {
++ dev_err(&pdev->dev, "snd_soc_register_card() failed: %d\n", ret);
++ }
++
++ return ret;
++}
++
++
++static int snd_rpi_hifiberry_amp_remove(struct platform_device *pdev)
++{
++ return snd_soc_unregister_card(&snd_rpi_hifiberry_amp);
++}
++
++
++static struct platform_driver snd_rpi_hifiberry_amp_driver = {
++ .driver = {
++ .name = "snd-hifiberry-amp",
++ .owner = THIS_MODULE,
++ },
++ .probe = snd_rpi_hifiberry_amp_probe,
++ .remove = snd_rpi_hifiberry_amp_remove,
++};
++
++
++module_platform_driver(snd_rpi_hifiberry_amp_driver);
++
++
++MODULE_AUTHOR("Sebastian Eickhoff <basti.eickhoff@googlemail.com>");
++MODULE_DESCRIPTION("ASoC driver for HiFiBerry-AMP");
++MODULE_LICENSE("GPL v2");
+diff -Nur linux-3.12.33/sound/soc/bcm/hifiberry_dac.c linux-3.12.33-rpi/sound/soc/bcm/hifiberry_dac.c
+--- linux-3.12.33/sound/soc/bcm/hifiberry_dac.c 1969-12-31 18:00:00.000000000 -0600
++++ linux-3.12.33-rpi/sound/soc/bcm/hifiberry_dac.c 2014-12-03 19:13:44.596418001 -0600
@@ -0,0 +1,100 @@
+/*
+ * ASoC Driver for HifiBerry DAC
@@ -104674,9 +111269,132 @@ diff -Nur linux-3.12.26.orig/sound/soc/bcm/hifiberry_dac.c linux-3.12.26/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.26.orig/sound/soc/bcm/hifiberry_digi.c linux-3.12.26/sound/soc/bcm/hifiberry_digi.c
---- linux-3.12.26.orig/sound/soc/bcm/hifiberry_digi.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-3.12.26/sound/soc/bcm/hifiberry_digi.c 2014-08-06 16:50:15.205967899 +0200
+diff -Nur linux-3.12.33/sound/soc/bcm/hifiberry_dacplus.c linux-3.12.33-rpi/sound/soc/bcm/hifiberry_dacplus.c
+--- linux-3.12.33/sound/soc/bcm/hifiberry_dacplus.c 1969-12-31 18:00:00.000000000 -0600
++++ linux-3.12.33-rpi/sound/soc/bcm/hifiberry_dacplus.c 2014-12-03 19:13:44.596418001 -0600
+@@ -0,0 +1,119 @@
++/*
++ * ASoC Driver for HiFiBerry DAC+
++ *
++ * Author: Daniel Matuschek
++ * Copyright 2014
++ * based on code by Florian Meier <florian.meier@koalo.de>
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License
++ * version 2 as published by the Free Software Foundation.
++ *
++ * 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>
++
++#include "../codecs/pcm512x.h"
++
++static int snd_rpi_hifiberry_dacplus_init(struct snd_soc_pcm_runtime *rtd)
++{
++ struct snd_soc_codec *codec = rtd->codec;
++ snd_soc_update_bits(codec, PCM512x_GPIO_EN, 0x08, 0x08);
++ snd_soc_update_bits(codec, PCM512x_GPIO_OUTPUT_4, 0xf, 0x02);
++ snd_soc_update_bits(codec, PCM512x_GPIO_CONTROL_1, 0x08,0x08);
++ return 0;
++}
++
++static int snd_rpi_hifiberry_dacplus_hw_params(struct snd_pcm_substream *substream,
++ struct snd_pcm_hw_params *params)
++{
++ struct snd_soc_pcm_runtime *rtd = substream->private_data;
++ struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
++ return snd_soc_dai_set_bclk_ratio(cpu_dai, 64);
++}
++
++static int snd_rpi_hifiberry_dacplus_startup(struct snd_pcm_substream *substream) {
++ struct snd_soc_pcm_runtime *rtd = substream->private_data;
++ struct snd_soc_codec *codec = rtd->codec;
++ snd_soc_update_bits(codec, PCM512x_GPIO_CONTROL_1, 0x08,0x08);
++ return 0;
++}
++
++static void snd_rpi_hifiberry_dacplus_shutdown(struct snd_pcm_substream *substream) {
++ struct snd_soc_pcm_runtime *rtd = substream->private_data;
++ struct snd_soc_codec *codec = rtd->codec;
++ snd_soc_update_bits(codec, PCM512x_GPIO_CONTROL_1, 0x08,0x00);
++}
++
++/* machine stream operations */
++static struct snd_soc_ops snd_rpi_hifiberry_dacplus_ops = {
++ .hw_params = snd_rpi_hifiberry_dacplus_hw_params,
++ .startup = snd_rpi_hifiberry_dacplus_startup,
++ .shutdown = snd_rpi_hifiberry_dacplus_shutdown,
++};
++
++static struct snd_soc_dai_link snd_rpi_hifiberry_dacplus_dai[] = {
++{
++ .name = "HiFiBerry DAC+",
++ .stream_name = "HiFiBerry DAC+ HiFi",
++ .cpu_dai_name = "bcm2708-i2s.0",
++ .codec_dai_name = "pcm512x-hifi",
++ .platform_name = "bcm2708-i2s.0",
++ .codec_name = "pcm512x.1-004d",
++ .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
++ SND_SOC_DAIFMT_CBS_CFS,
++ .ops = &snd_rpi_hifiberry_dacplus_ops,
++ .init = snd_rpi_hifiberry_dacplus_init,
++},
++};
++
++/* audio machine driver */
++static struct snd_soc_card snd_rpi_hifiberry_dacplus = {
++ .name = "snd_rpi_hifiberry_dacplus",
++ .dai_link = snd_rpi_hifiberry_dacplus_dai,
++ .num_links = ARRAY_SIZE(snd_rpi_hifiberry_dacplus_dai),
++};
++
++static int snd_rpi_hifiberry_dacplus_probe(struct platform_device *pdev)
++{
++ int ret = 0;
++
++ snd_rpi_hifiberry_dacplus.dev = &pdev->dev;
++ ret = snd_soc_register_card(&snd_rpi_hifiberry_dacplus);
++ if (ret)
++ dev_err(&pdev->dev,
++ "snd_soc_register_card() failed: %d\n", ret);
++
++ return ret;
++}
++
++static int snd_rpi_hifiberry_dacplus_remove(struct platform_device *pdev)
++{
++ return snd_soc_unregister_card(&snd_rpi_hifiberry_dacplus);
++}
++
++static struct platform_driver snd_rpi_hifiberry_dacplus_driver = {
++ .driver = {
++ .name = "snd-rpi-hifiberry-dacplus",
++ .owner = THIS_MODULE,
++ },
++ .probe = snd_rpi_hifiberry_dacplus_probe,
++ .remove = snd_rpi_hifiberry_dacplus_remove,
++};
++
++module_platform_driver(snd_rpi_hifiberry_dacplus_driver);
++
++MODULE_AUTHOR("Daniel Matuschek <daniel@hifiberry.com>");
++MODULE_DESCRIPTION("ASoC Driver for HiFiBerry DAC+");
++MODULE_LICENSE("GPL v2");
+diff -Nur linux-3.12.33/sound/soc/bcm/hifiberry_digi.c linux-3.12.33-rpi/sound/soc/bcm/hifiberry_digi.c
+--- linux-3.12.33/sound/soc/bcm/hifiberry_digi.c 1969-12-31 18:00:00.000000000 -0600
++++ linux-3.12.33-rpi/sound/soc/bcm/hifiberry_digi.c 2014-12-03 19:13:44.596418001 -0600
@@ -0,0 +1,153 @@
+/*
+ * ASoC Driver for HifiBerry Digi
@@ -104831,9 +111549,9 @@ diff -Nur linux-3.12.26.orig/sound/soc/bcm/hifiberry_digi.c linux-3.12.26/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.26.orig/sound/soc/bcm/iqaudio-dac.c linux-3.12.26/sound/soc/bcm/iqaudio-dac.c
---- linux-3.12.26.orig/sound/soc/bcm/iqaudio-dac.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-3.12.26/sound/soc/bcm/iqaudio-dac.c 2014-08-06 16:50:15.205967899 +0200
+diff -Nur linux-3.12.33/sound/soc/bcm/iqaudio-dac.c linux-3.12.33-rpi/sound/soc/bcm/iqaudio-dac.c
+--- linux-3.12.33/sound/soc/bcm/iqaudio-dac.c 1969-12-31 18:00:00.000000000 -0600
++++ linux-3.12.33-rpi/sound/soc/bcm/iqaudio-dac.c 2014-12-03 19:13:44.596418001 -0600
@@ -0,0 +1,111 @@
+/*
+ * ASoC Driver for IQaudIO DAC
@@ -104946,10 +111664,10 @@ diff -Nur linux-3.12.26.orig/sound/soc/bcm/iqaudio-dac.c linux-3.12.26/sound/soc
+MODULE_AUTHOR("Florian Meier <florian.meier@koalo.de>");
+MODULE_DESCRIPTION("ASoC Driver for IQAudio DAC");
+MODULE_LICENSE("GPL v2");
-diff -Nur linux-3.12.26.orig/sound/soc/bcm/Kconfig linux-3.12.26/sound/soc/bcm/Kconfig
---- linux-3.12.26.orig/sound/soc/bcm/Kconfig 1970-01-01 01:00:00.000000000 +0100
-+++ linux-3.12.26/sound/soc/bcm/Kconfig 2014-08-06 16:50:15.205967899 +0200
-@@ -0,0 +1,38 @@
+diff -Nur linux-3.12.33/sound/soc/bcm/Kconfig linux-3.12.33-rpi/sound/soc/bcm/Kconfig
+--- linux-3.12.33/sound/soc/bcm/Kconfig 1969-12-31 18:00:00.000000000 -0600
++++ linux-3.12.33-rpi/sound/soc/bcm/Kconfig 2014-12-03 19:13:44.596418001 -0600
+@@ -0,0 +1,52 @@
+config SND_BCM2708_SOC_I2S
+ tristate "SoC Audio support for the Broadcom BCM2708 I2S module"
+ depends on MACH_BCM2708
@@ -104968,6 +111686,13 @@ diff -Nur linux-3.12.26.orig/sound/soc/bcm/Kconfig linux-3.12.26/sound/soc/bcm/K
+ help
+ Say Y or M if you want to add support for HifiBerry DAC.
+
++config SND_BCM2708_SOC_HIFIBERRY_DACPLUS
++ tristate "Support for HifiBerry DAC+"
++ depends on SND_BCM2708_SOC_I2S
++ select SND_SOC_PCM512x
++ help
++ Say Y or M if you want to add support for HifiBerry DAC+.
++
+config SND_BCM2708_SOC_HIFIBERRY_DIGI
+ tristate "Support for HifiBerry Digi"
+ depends on SND_BCM2708_SOC_I2S
@@ -104975,6 +111700,13 @@ diff -Nur linux-3.12.26.orig/sound/soc/bcm/Kconfig linux-3.12.26/sound/soc/bcm/K
+ help
+ Say Y or M if you want to add support for HifiBerry Digi S/PDIF output board.
+
++config SND_BCM2708_SOC_HIFIBERRY_AMP
++ tristate "Support for the HifiBerry Amp"
++ depends on SND_BCM2708_SOC_I2S
++ select SND_SOC_TAS5713
++ help
++ Say Y or M if you want to add support for the HifiBerry Amp amplifier board.
++
+config SND_BCM2708_SOC_RPI_DAC
+ tristate "Support for RPi-DAC"
+ depends on SND_BCM2708_SOC_I2S
@@ -104988,10 +111720,10 @@ diff -Nur linux-3.12.26.orig/sound/soc/bcm/Kconfig linux-3.12.26/sound/soc/bcm/K
+ select SND_SOC_PCM512x
+ help
+ Say Y or M if you want to add support for IQaudIO-DAC.
-diff -Nur linux-3.12.26.orig/sound/soc/bcm/Makefile linux-3.12.26/sound/soc/bcm/Makefile
---- linux-3.12.26.orig/sound/soc/bcm/Makefile 1970-01-01 01:00:00.000000000 +0100
-+++ linux-3.12.26/sound/soc/bcm/Makefile 2014-08-06 16:50:15.205967899 +0200
-@@ -0,0 +1,15 @@
+diff -Nur linux-3.12.33/sound/soc/bcm/Makefile linux-3.12.33-rpi/sound/soc/bcm/Makefile
+--- linux-3.12.33/sound/soc/bcm/Makefile 1969-12-31 18:00:00.000000000 -0600
++++ linux-3.12.33-rpi/sound/soc/bcm/Makefile 2014-12-03 19:13:44.596418001 -0600
+@@ -0,0 +1,19 @@
+# BCM2708 Platform Support
+snd-soc-bcm2708-i2s-objs := bcm2708-i2s.o
+
@@ -104999,17 +111731,21 @@ diff -Nur linux-3.12.26.orig/sound/soc/bcm/Makefile linux-3.12.26/sound/soc/bcm/
+
+# BCM2708 Machine Support
+snd-soc-hifiberry-dac-objs := hifiberry_dac.o
++snd-soc-hifiberry-dacplus-objs := hifiberry_dacplus.o
+snd-soc-hifiberry-digi-objs := hifiberry_digi.o
++snd-soc-hifiberry-amp-objs := hifiberry_amp.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_DACPLUS) += snd-soc-hifiberry-dacplus.o
+obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DIGI) += snd-soc-hifiberry-digi.o
++obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_AMP) += snd-soc-hifiberry-amp.o
+obj-$(CONFIG_SND_BCM2708_SOC_RPI_DAC) += snd-soc-rpi-dac.o
+obj-$(CONFIG_SND_BCM2708_SOC_IQAUDIO_DAC) += snd-soc-iqaudio-dac.o
-diff -Nur linux-3.12.26.orig/sound/soc/bcm/rpi-dac.c linux-3.12.26/sound/soc/bcm/rpi-dac.c
---- linux-3.12.26.orig/sound/soc/bcm/rpi-dac.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-3.12.26/sound/soc/bcm/rpi-dac.c 2014-08-06 16:50:15.209967931 +0200
+diff -Nur linux-3.12.33/sound/soc/bcm/rpi-dac.c linux-3.12.33-rpi/sound/soc/bcm/rpi-dac.c
+--- linux-3.12.33/sound/soc/bcm/rpi-dac.c 1969-12-31 18:00:00.000000000 -0600
++++ linux-3.12.33-rpi/sound/soc/bcm/rpi-dac.c 2014-12-03 19:13:44.596418001 -0600
@@ -0,0 +1,97 @@
+/*
+ * ASoC Driver for RPi-DAC.
@@ -105057,8 +111793,8 @@ diff -Nur linux-3.12.26.orig/sound/soc/bcm/rpi-dac.c linux-3.12.26/sound/soc/bcm
+
+static struct snd_soc_dai_link snd_rpi_rpi_dac_dai[] = {
+{
-+ .name = "HifiBerry Mini",
-+ .stream_name = "HifiBerry Mini HiFi",
++ .name = "RPi-DAC",
++ .stream_name = "RPi-DAC HiFi",
+ .cpu_dai_name = "bcm2708-i2s.0",
+ .codec_dai_name = "pcm1794a-hifi",
+ .platform_name = "bcm2708-i2s.0",
@@ -105108,9 +111844,9 @@ diff -Nur linux-3.12.26.orig/sound/soc/bcm/rpi-dac.c linux-3.12.26/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.26.orig/sound/soc/codecs/Kconfig linux-3.12.26/sound/soc/codecs/Kconfig
---- linux-3.12.26.orig/sound/soc/codecs/Kconfig 2014-07-30 18:02:44.000000000 +0200
-+++ linux-3.12.26/sound/soc/codecs/Kconfig 2014-08-06 16:50:15.209967931 +0200
+diff -Nur linux-3.12.33/sound/soc/codecs/Kconfig linux-3.12.33-rpi/sound/soc/codecs/Kconfig
+--- linux-3.12.33/sound/soc/codecs/Kconfig 2014-11-15 06:28:07.000000000 -0600
++++ linux-3.12.33-rpi/sound/soc/codecs/Kconfig 2014-12-03 19:13:44.600418001 -0600
@@ -59,6 +59,9 @@
select SND_SOC_PCM1681 if I2C
select SND_SOC_PCM1792A if SPI_MASTER
@@ -105121,7 +111857,15 @@ diff -Nur linux-3.12.26.orig/sound/soc/codecs/Kconfig linux-3.12.26/sound/soc/co
select SND_SOC_RT5631 if I2C
select SND_SOC_RT5640 if I2C
select SND_SOC_SGTL5000 if I2C
-@@ -311,6 +314,15 @@
+@@ -71,6 +74,7 @@
+ select SND_SOC_STA529 if I2C
+ select SND_SOC_STAC9766 if SND_SOC_AC97_BUS
+ select SND_SOC_TAS5086 if I2C
++ select SND_SOC_TAS5713 if I2C
+ select SND_SOC_TLV320AIC23 if I2C
+ select SND_SOC_TLV320AIC26 if SPI_MASTER
+ select SND_SOC_TLV320AIC32X4 if I2C
+@@ -311,6 +315,15 @@
config SND_SOC_PCM3008
tristate
@@ -105137,9 +111881,19 @@ diff -Nur linux-3.12.26.orig/sound/soc/codecs/Kconfig linux-3.12.26/sound/soc/co
config SND_SOC_RT5631
tristate
-diff -Nur linux-3.12.26.orig/sound/soc/codecs/Makefile linux-3.12.26/sound/soc/codecs/Makefile
---- linux-3.12.26.orig/sound/soc/codecs/Makefile 2014-07-30 18:02:44.000000000 +0200
-+++ linux-3.12.26/sound/soc/codecs/Makefile 2014-08-06 16:50:15.209967931 +0200
+@@ -352,6 +365,9 @@
+ config SND_SOC_TAS5086
+ tristate
+
++config SND_SOC_TAS5713
++ tristate
++
+ config SND_SOC_TLV320AIC23
+ tristate
+
+diff -Nur linux-3.12.33/sound/soc/codecs/Makefile linux-3.12.33-rpi/sound/soc/codecs/Makefile
+--- linux-3.12.33/sound/soc/codecs/Makefile 2014-11-15 06:28:07.000000000 -0600
++++ linux-3.12.33-rpi/sound/soc/codecs/Makefile 2014-12-03 19:13:44.600418001 -0600
@@ -46,6 +46,9 @@
snd-soc-pcm1681-objs := pcm1681.o
snd-soc-pcm1792a-codec-objs := pcm1792a.o
@@ -105150,7 +111904,15 @@ diff -Nur linux-3.12.26.orig/sound/soc/codecs/Makefile linux-3.12.26/sound/soc/c
snd-soc-rt5631-objs := rt5631.o
snd-soc-rt5640-objs := rt5640.o
snd-soc-sgtl5000-objs := sgtl5000.o
-@@ -179,6 +182,9 @@
+@@ -62,6 +65,7 @@
+ snd-soc-sta529-objs := sta529.o
+ snd-soc-stac9766-objs := stac9766.o
+ snd-soc-tas5086-objs := tas5086.o
++snd-soc-tas5713-objs := tas5713.o
+ snd-soc-tlv320aic23-objs := tlv320aic23.o
+ snd-soc-tlv320aic26-objs := tlv320aic26.o
+ snd-soc-tlv320aic3x-objs := tlv320aic3x.o
+@@ -179,6 +183,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
@@ -105160,9 +111922,17 @@ diff -Nur linux-3.12.26.orig/sound/soc/codecs/Makefile linux-3.12.26/sound/soc/c
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.26.orig/sound/soc/codecs/pcm1794a.c linux-3.12.26/sound/soc/codecs/pcm1794a.c
---- linux-3.12.26.orig/sound/soc/codecs/pcm1794a.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-3.12.26/sound/soc/codecs/pcm1794a.c 2014-08-06 16:50:15.209967931 +0200
+@@ -192,6 +199,7 @@
+ obj-$(CONFIG_SND_SOC_STA529) += snd-soc-sta529.o
+ obj-$(CONFIG_SND_SOC_STAC9766) += snd-soc-stac9766.o
+ obj-$(CONFIG_SND_SOC_TAS5086) += snd-soc-tas5086.o
++obj-$(CONFIG_SND_SOC_TAS5713) += snd-soc-tas5713.o
+ obj-$(CONFIG_SND_SOC_TLV320AIC23) += snd-soc-tlv320aic23.o
+ obj-$(CONFIG_SND_SOC_TLV320AIC26) += snd-soc-tlv320aic26.o
+ obj-$(CONFIG_SND_SOC_TLV320AIC3X) += snd-soc-tlv320aic3x.o
+diff -Nur linux-3.12.33/sound/soc/codecs/pcm1794a.c linux-3.12.33-rpi/sound/soc/codecs/pcm1794a.c
+--- linux-3.12.33/sound/soc/codecs/pcm1794a.c 1969-12-31 18:00:00.000000000 -0600
++++ linux-3.12.33-rpi/sound/soc/codecs/pcm1794a.c 2014-12-03 19:13:44.608418001 -0600
@@ -0,0 +1,62 @@
+/*
+ * Driver for the PCM1794A codec
@@ -105226,9 +111996,9 @@ diff -Nur linux-3.12.26.orig/sound/soc/codecs/pcm1794a.c linux-3.12.26/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.26.orig/sound/soc/codecs/pcm5102a.c linux-3.12.26/sound/soc/codecs/pcm5102a.c
---- linux-3.12.26.orig/sound/soc/codecs/pcm5102a.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-3.12.26/sound/soc/codecs/pcm5102a.c 2014-08-06 16:50:15.209967931 +0200
+diff -Nur linux-3.12.33/sound/soc/codecs/pcm5102a.c linux-3.12.33-rpi/sound/soc/codecs/pcm5102a.c
+--- linux-3.12.33/sound/soc/codecs/pcm5102a.c 1969-12-31 18:00:00.000000000 -0600
++++ linux-3.12.33-rpi/sound/soc/codecs/pcm5102a.c 2014-12-03 19:13:44.608418001 -0600
@@ -0,0 +1,63 @@
+/*
+ * Driver for the PCM5102A codec
@@ -105260,7 +112030,7 @@ diff -Nur linux-3.12.26.orig/sound/soc/codecs/pcm5102a.c linux-3.12.26/sound/soc
+ .channels_max = 2,
+ .rates = SNDRV_PCM_RATE_8000_192000,
+ .formats = SNDRV_PCM_FMTBIT_S16_LE |
-+ // SNDRV_PCM_FMTBIT_S24_LE | : disable for now, it causes white noise with xbmc
++ SNDRV_PCM_FMTBIT_S24_LE |
+ SNDRV_PCM_FMTBIT_S32_LE
+ },
+};
@@ -105293,9 +112063,9 @@ diff -Nur linux-3.12.26.orig/sound/soc/codecs/pcm5102a.c linux-3.12.26/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.26.orig/sound/soc/codecs/pcm512x.c linux-3.12.26/sound/soc/codecs/pcm512x.c
---- linux-3.12.26.orig/sound/soc/codecs/pcm512x.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-3.12.26/sound/soc/codecs/pcm512x.c 2014-08-06 16:50:15.209967931 +0200
+diff -Nur linux-3.12.33/sound/soc/codecs/pcm512x.c linux-3.12.33-rpi/sound/soc/codecs/pcm512x.c
+--- linux-3.12.33/sound/soc/codecs/pcm512x.c 1969-12-31 18:00:00.000000000 -0600
++++ linux-3.12.33-rpi/sound/soc/codecs/pcm512x.c 2014-12-03 19:13:44.608418001 -0600
@@ -0,0 +1,678 @@
+/*
+ * Driver for the PCM512x CODECs
@@ -105975,9 +112745,9 @@ diff -Nur linux-3.12.26.orig/sound/soc/codecs/pcm512x.c linux-3.12.26/sound/soc/
+MODULE_DESCRIPTION("ASoC PCM512x codec driver");
+MODULE_AUTHOR("Mark Brown <broonie@linaro.org>");
+MODULE_LICENSE("GPL v2");
-diff -Nur linux-3.12.26.orig/sound/soc/codecs/pcm512x.h linux-3.12.26/sound/soc/codecs/pcm512x.h
---- linux-3.12.26.orig/sound/soc/codecs/pcm512x.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-3.12.26/sound/soc/codecs/pcm512x.h 2014-08-06 16:50:15.209967931 +0200
+diff -Nur linux-3.12.33/sound/soc/codecs/pcm512x.h linux-3.12.33-rpi/sound/soc/codecs/pcm512x.h
+--- linux-3.12.33/sound/soc/codecs/pcm512x.h 1969-12-31 18:00:00.000000000 -0600
++++ linux-3.12.33-rpi/sound/soc/codecs/pcm512x.h 2014-12-03 19:13:44.608418001 -0600
@@ -0,0 +1,142 @@
+/*
+ * Driver for the PCM512x CODECs
@@ -106121,9 +112891,597 @@ diff -Nur linux-3.12.26.orig/sound/soc/codecs/pcm512x.h linux-3.12.26/sound/soc/
+#define PCM512x_AMLR_SHIFT 0
+
+#endif
-diff -Nur linux-3.12.26.orig/sound/soc/codecs/wm8804.c linux-3.12.26/sound/soc/codecs/wm8804.c
---- linux-3.12.26.orig/sound/soc/codecs/wm8804.c 2014-07-30 18:02:44.000000000 +0200
-+++ linux-3.12.26/sound/soc/codecs/wm8804.c 2014-08-06 16:50:15.213967961 +0200
+diff -Nur linux-3.12.33/sound/soc/codecs/tas5713.c linux-3.12.33-rpi/sound/soc/codecs/tas5713.c
+--- linux-3.12.33/sound/soc/codecs/tas5713.c 1969-12-31 18:00:00.000000000 -0600
++++ linux-3.12.33-rpi/sound/soc/codecs/tas5713.c 2014-12-03 19:13:44.612418001 -0600
+@@ -0,0 +1,370 @@
++/*
++ * ASoC Driver for TAS5713
++ *
++ * Author: Sebastian Eickhoff <basti.eickhoff@googlemail.com>
++ * Copyright 2014
++ *
++ * 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/moduleparam.h>
++#include <linux/init.h>
++#include <linux/delay.h>
++#include <linux/pm.h>
++#include <linux/i2c.h>
++#include <linux/of_device.h>
++#include <linux/spi/spi.h>
++#include <linux/regmap.h>
++#include <linux/regulator/consumer.h>
++#include <linux/slab.h>
++#include <sound/core.h>
++#include <sound/pcm.h>
++#include <sound/pcm_params.h>
++#include <sound/soc.h>
++#include <sound/initval.h>
++#include <sound/tlv.h>
++
++#include <linux/kernel.h>
++#include <linux/string.h>
++#include <linux/fs.h>
++#include <asm/uaccess.h>
++
++#include "tas5713.h"
++
++
++static struct i2c_client *i2c;
++
++struct tas5713_priv {
++ struct regmap *regmap;
++ int mclk_div;
++ struct snd_soc_codec *codec;
++};
++
++static struct tas5713_priv *priv_data;
++
++
++
++
++/*
++ * _ _ ___ _ ___ _ _
++ * /_\ | | / __| /_\ / __|___ _ _| |_ _ _ ___| |___
++ * / _ \| |__\__ \/ _ \ | (__/ _ \ ' \ _| '_/ _ \ (_-<
++ * /_/ \_\____|___/_/ \_\ \___\___/_||_\__|_| \___/_/__/
++ *
++ */
++
++static const DECLARE_TLV_DB_SCALE(tas5713_vol_tlv, -10000, 50, 1);
++
++
++static const struct snd_kcontrol_new tas5713_snd_controls[] = {
++ SOC_SINGLE_TLV ("Master" , TAS5713_VOL_MASTER, 0, 248, 1, tas5713_vol_tlv),
++ SOC_DOUBLE_R_TLV("Channels" , TAS5713_VOL_CH1, TAS5713_VOL_CH2, 0, 248, 1, tas5713_vol_tlv)
++};
++
++
++
++
++/*
++ * __ __ _ _ ___ _
++ * | \/ |__ _ __| |_ (_)_ _ ___ | \ _ _(_)_ _____ _ _
++ * | |\/| / _` / _| ' \| | ' \/ -_) | |) | '_| \ V / -_) '_|
++ * |_| |_\__,_\__|_||_|_|_||_\___| |___/|_| |_|\_/\___|_|
++ *
++ */
++
++static int tas5713_hw_params(struct snd_pcm_substream *substream,
++ struct snd_pcm_hw_params *params,
++ struct snd_soc_dai *dai)
++{
++ u16 blen = 0x00;
++
++ struct snd_soc_codec *codec;
++ codec = dai->codec;
++ priv_data->codec = dai->codec;
++
++ switch (params_format(params)) {
++ case SNDRV_PCM_FORMAT_S16_LE:
++ blen = 0x03;
++ break;
++ case SNDRV_PCM_FORMAT_S20_3LE:
++ blen = 0x1;
++ break;
++ case SNDRV_PCM_FORMAT_S24_LE:
++ blen = 0x04;
++ break;
++ case SNDRV_PCM_FORMAT_S32_LE:
++ blen = 0x05;
++ break;
++ default:
++ dev_err(dai->dev, "Unsupported word length: %u\n",
++ params_format(params));
++ return -EINVAL;
++ }
++
++ // set word length
++ snd_soc_update_bits(codec, TAS5713_SERIAL_DATA_INTERFACE, 0x7, blen);
++
++ return 0;
++}
++
++
++static int tas5713_mute_stream(struct snd_soc_dai *dai, int mute, int stream)
++{
++ unsigned int val = 0;
++
++ struct tas5713_priv *tas5713;
++ struct snd_soc_codec *codec = dai->codec;
++ tas5713 = snd_soc_codec_get_drvdata(codec);
++
++ if (mute) {
++ val = TAS5713_SOFT_MUTE_ALL;
++ }
++
++ return regmap_write(tas5713->regmap, TAS5713_SOFT_MUTE, val);
++}
++
++
++static const struct snd_soc_dai_ops tas5713_dai_ops = {
++ .hw_params = tas5713_hw_params,
++ .mute_stream = tas5713_mute_stream,
++};
++
++
++static struct snd_soc_dai_driver tas5713_dai = {
++ .name = "tas5713-hifi",
++ .playback = {
++ .stream_name = "Playback",
++ .channels_min = 2,
++ .channels_max = 2,
++ .rates = SNDRV_PCM_RATE_8000_48000,
++ .formats = (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE ),
++ },
++ .ops = &tas5713_dai_ops,
++};
++
++
++
++
++/*
++ * ___ _ ___ _
++ * / __|___ __| |___ __ | \ _ _(_)_ _____ _ _
++ * | (__/ _ \/ _` / -_) _| | |) | '_| \ V / -_) '_|
++ * \___\___/\__,_\___\__| |___/|_| |_|\_/\___|_|
++ *
++ */
++
++static int tas5713_remove(struct snd_soc_codec *codec)
++{
++ struct tas5713_priv *tas5713;
++
++ tas5713 = snd_soc_codec_get_drvdata(codec);
++
++ return 0;
++}
++
++
++static int tas5713_probe(struct snd_soc_codec *codec)
++{
++ struct tas5713_priv *tas5713;
++ int i, ret;
++
++ i2c = container_of(codec->dev, struct i2c_client, dev);
++
++ tas5713 = snd_soc_codec_get_drvdata(codec);
++
++ codec->control_data = tas5713->regmap;
++
++ ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_REGMAP);
++ if (ret < 0) {
++ dev_err(codec->dev, "Failed to set cache i/o: %d\n", ret);
++ return ret;
++ }
++
++ // Reset error
++ ret = snd_soc_write(codec, TAS5713_ERROR_STATUS, 0x00);
++
++ // Trim oscillator
++ ret = snd_soc_write(codec, TAS5713_OSC_TRIM, 0x00);
++ msleep(1000);
++
++ // Reset error
++ ret = snd_soc_write(codec, TAS5713_ERROR_STATUS, 0x00);
++
++ // Clock mode: 44/48kHz, MCLK=64xfs
++ ret = snd_soc_write(codec, TAS5713_CLOCK_CTRL, 0x60);
++
++ // I2S 24bit
++ ret = snd_soc_write(codec, TAS5713_SERIAL_DATA_INTERFACE, 0x05);
++
++ // Unmute
++ ret = snd_soc_write(codec, TAS5713_SYSTEM_CTRL2, 0x00);
++ ret = snd_soc_write(codec, TAS5713_SOFT_MUTE, 0x00);
++
++ // Set volume to 0db
++ ret = snd_soc_write(codec, TAS5713_VOL_MASTER, 0x00);
++
++ // Now start programming the default initialization sequence
++ for (i = 0; i < ARRAY_SIZE(tas5713_init_sequence); ++i) {
++ ret = i2c_master_send(i2c,
++ tas5713_init_sequence[i].data,
++ tas5713_init_sequence[i].size);
++
++ if (ret < 0) {
++ printk(KERN_INFO "TAS5713 CODEC PROBE: InitSeq returns: %d\n", ret);
++ }
++ }
++
++ // Unmute
++ ret = snd_soc_write(codec, TAS5713_SYSTEM_CTRL2, 0x00);
++
++
++ return 0;
++}
++
++
++static struct snd_soc_codec_driver soc_codec_dev_tas5713 = {
++ .probe = tas5713_probe,
++ .remove = tas5713_remove,
++ .controls = tas5713_snd_controls,
++ .num_controls = ARRAY_SIZE(tas5713_snd_controls),
++};
++
++
++
++
++/*
++ * ___ ___ ___ ___ _
++ * |_ _|_ ) __| | \ _ _(_)_ _____ _ _
++ * | | / / (__ | |) | '_| \ V / -_) '_|
++ * |___/___\___| |___/|_| |_|\_/\___|_|
++ *
++ */
++
++static const struct reg_default tas5713_reg_defaults[] = {
++ { 0x07 ,0x80 }, // R7 - VOL_MASTER - -40dB
++ { 0x08 , 30 }, // R8 - VOL_CH1 - 0dB
++ { 0x09 , 30 }, // R9 - VOL_CH2 - 0dB
++ { 0x0A ,0x80 }, // R10 - VOL_HEADPHONE - -40dB
++};
++
++
++static bool tas5713_reg_volatile(struct device *dev, unsigned int reg)
++{
++ switch (reg) {
++ case TAS5713_DEVICE_ID:
++ case TAS5713_ERROR_STATUS:
++ return true;
++ default:
++ return false;
++ }
++}
++
++
++static const struct of_device_id tas5713_of_match[] = {
++ { .compatible = "ti,tas5713", },
++ { }
++};
++MODULE_DEVICE_TABLE(of, tas5713_of_match);
++
++
++static struct regmap_config tas5713_regmap_config = {
++ .reg_bits = 8,
++ .val_bits = 8,
++
++ .max_register = TAS5713_MAX_REGISTER,
++ .volatile_reg = tas5713_reg_volatile,
++
++ .cache_type = REGCACHE_RBTREE,
++ .reg_defaults = tas5713_reg_defaults,
++ .num_reg_defaults = ARRAY_SIZE(tas5713_reg_defaults),
++};
++
++
++static int tas5713_i2c_probe(struct i2c_client *i2c,
++ const struct i2c_device_id *id)
++{
++ int ret;
++
++ priv_data = devm_kzalloc(&i2c->dev, sizeof *priv_data, GFP_KERNEL);
++ if (!priv_data)
++ return -ENOMEM;
++
++ priv_data->regmap = devm_regmap_init_i2c(i2c, &tas5713_regmap_config);
++ if (IS_ERR(priv_data->regmap)) {
++ ret = PTR_ERR(priv_data->regmap);
++ return ret;
++ }
++
++ i2c_set_clientdata(i2c, priv_data);
++
++ ret = snd_soc_register_codec(&i2c->dev,
++ &soc_codec_dev_tas5713, &tas5713_dai, 1);
++
++ return ret;
++}
++
++
++static int tas5713_i2c_remove(struct i2c_client *i2c)
++{
++ snd_soc_unregister_codec(&i2c->dev);
++ i2c_set_clientdata(i2c, NULL);
++
++ kfree(priv_data);
++
++ return 0;
++}
++
++
++static const struct i2c_device_id tas5713_i2c_id[] = {
++ { "tas5713", 0 },
++ { }
++};
++
++MODULE_DEVICE_TABLE(i2c, tas5713_i2c_id);
++
++
++static struct i2c_driver tas5713_i2c_driver = {
++ .driver = {
++ .name = "tas5713",
++ .owner = THIS_MODULE,
++ .of_match_table = tas5713_of_match,
++ },
++ .probe = tas5713_i2c_probe,
++ .remove = tas5713_i2c_remove,
++ .id_table = tas5713_i2c_id
++};
++
++
++static int __init tas5713_modinit(void)
++{
++ int ret = 0;
++
++ ret = i2c_add_driver(&tas5713_i2c_driver);
++ if (ret) {
++ printk(KERN_ERR "Failed to register tas5713 I2C driver: %d\n",
++ ret);
++ }
++
++ return ret;
++}
++module_init(tas5713_modinit);
++
++
++static void __exit tas5713_exit(void)
++{
++ i2c_del_driver(&tas5713_i2c_driver);
++}
++module_exit(tas5713_exit);
++
++
++MODULE_AUTHOR("Sebastian Eickhoff <basti.eickhoff@googlemail.com>");
++MODULE_DESCRIPTION("ASoC driver for TAS5713");
++MODULE_LICENSE("GPL v2");
+diff -Nur linux-3.12.33/sound/soc/codecs/tas5713.h linux-3.12.33-rpi/sound/soc/codecs/tas5713.h
+--- linux-3.12.33/sound/soc/codecs/tas5713.h 1969-12-31 18:00:00.000000000 -0600
++++ linux-3.12.33-rpi/sound/soc/codecs/tas5713.h 2014-12-03 19:13:44.612418001 -0600
+@@ -0,0 +1,210 @@
++/*
++ * ASoC Driver for TAS5713
++ *
++ * Author: Sebastian Eickhoff <basti.eickhoff@googlemail.com>
++ * Copyright 2014
++ *
++ * 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 _TAS5713_H
++#define _TAS5713_H
++
++
++// TAS5713 I2C-bus register addresses
++
++#define TAS5713_CLOCK_CTRL 0x00
++#define TAS5713_DEVICE_ID 0x01
++#define TAS5713_ERROR_STATUS 0x02
++#define TAS5713_SYSTEM_CTRL1 0x03
++#define TAS5713_SERIAL_DATA_INTERFACE 0x04
++#define TAS5713_SYSTEM_CTRL2 0x05
++#define TAS5713_SOFT_MUTE 0x06
++#define TAS5713_VOL_MASTER 0x07
++#define TAS5713_VOL_CH1 0x08
++#define TAS5713_VOL_CH2 0x09
++#define TAS5713_VOL_HEADPHONE 0x0A
++#define TAS5713_VOL_CONFIG 0x0E
++#define TAS5713_MODULATION_LIMIT 0x10
++#define TAS5713_IC_DLY_CH1 0x11
++#define TAS5713_IC_DLY_CH2 0x12
++#define TAS5713_IC_DLY_CH3 0x13
++#define TAS5713_IC_DLY_CH4 0x14
++
++#define TAS5713_START_STOP_PERIOD 0x1A
++#define TAS5713_OSC_TRIM 0x1B
++#define TAS5713_BKND_ERR 0x1C
++
++#define TAS5713_INPUT_MUX 0x20
++#define TAS5713_SRC_SELECT_CH4 0x21
++#define TAS5713_PWM_MUX 0x25
++
++#define TAS5713_CH1_BQ0 0x29
++#define TAS5713_CH1_BQ1 0x2A
++#define TAS5713_CH1_BQ2 0x2B
++#define TAS5713_CH1_BQ3 0x2C
++#define TAS5713_CH1_BQ4 0x2D
++#define TAS5713_CH1_BQ5 0x2E
++#define TAS5713_CH1_BQ6 0x2F
++#define TAS5713_CH1_BQ7 0x58
++#define TAS5713_CH1_BQ8 0x59
++
++#define TAS5713_CH2_BQ0 0x30
++#define TAS5713_CH2_BQ1 0x31
++#define TAS5713_CH2_BQ2 0x32
++#define TAS5713_CH2_BQ3 0x33
++#define TAS5713_CH2_BQ4 0x34
++#define TAS5713_CH2_BQ5 0x35
++#define TAS5713_CH2_BQ6 0x36
++#define TAS5713_CH2_BQ7 0x5C
++#define TAS5713_CH2_BQ8 0x5D
++
++#define TAS5713_CH4_BQ0 0x5A
++#define TAS5713_CH4_BQ1 0x5B
++#define TAS5713_CH3_BQ0 0x5E
++#define TAS5713_CH3_BQ1 0x5F
++
++#define TAS5713_DRC1_SOFTENING_FILTER_ALPHA_OMEGA 0x3B
++#define TAS5713_DRC1_ATTACK_RELEASE_RATE 0x3C
++#define TAS5713_DRC2_SOFTENING_FILTER_ALPHA_OMEGA 0x3E
++#define TAS5713_DRC2_ATTACK_RELEASE_RATE 0x3F
++#define TAS5713_DRC1_ATTACK_RELEASE_THRES 0x40
++#define TAS5713_DRC2_ATTACK_RELEASE_THRES 0x43
++#define TAS5713_DRC_CTRL 0x46
++
++#define TAS5713_BANK_SW_CTRL 0x50
++#define TAS5713_CH1_OUTPUT_MIXER 0x51
++#define TAS5713_CH2_OUTPUT_MIXER 0x52
++#define TAS5713_CH1_INPUT_MIXER 0x53
++#define TAS5713_CH2_INPUT_MIXER 0x54
++#define TAS5713_OUTPUT_POST_SCALE 0x56
++#define TAS5713_OUTPUT_PRESCALE 0x57
++
++#define TAS5713_IDF_POST_SCALE 0x62
++
++#define TAS5713_CH1_INLINE_MIXER 0x70
++#define TAS5713_CH1_INLINE_DRC_EN_MIXER 0x71
++#define TAS5713_CH1_R_CHANNEL_MIXER 0x72
++#define TAS5713_CH1_L_CHANNEL_MIXER 0x73
++#define TAS5713_CH2_INLINE_MIXER 0x74
++#define TAS5713_CH2_INLINE_DRC_EN_MIXER 0x75
++#define TAS5713_CH2_L_CHANNEL_MIXER 0x76
++#define TAS5713_CH2_R_CHANNEL_MIXER 0x77
++
++#define TAS5713_UPDATE_DEV_ADDR_KEY 0xF8
++#define TAS5713_UPDATE_DEV_ADDR_REG 0xF9
++
++#define TAS5713_REGISTER_COUNT 0x46
++#define TAS5713_MAX_REGISTER 0xF9
++
++
++// Bitmasks for registers
++#define TAS5713_SOFT_MUTE_ALL 0x07
++
++
++
++struct tas5713_init_command {
++ const int size;
++ const char *const data;
++};
++
++static const struct tas5713_init_command tas5713_init_sequence[] = {
++
++ // Trim oscillator
++ { .size = 2, .data = "\x1B\x00" },
++ // System control register 1 (0x03): block DC
++ { .size = 2, .data = "\x03\x80" },
++ // Mute everything
++ { .size = 2, .data = "\x05\x40" },
++ // Modulation limit register (0x10): 97.7%
++ { .size = 2, .data = "\x10\x02" },
++ // Interchannel delay registers
++ // (0x11, 0x12, 0x13, and 0x14): BD mode
++ { .size = 2, .data = "\x11\xB8" },
++ { .size = 2, .data = "\x12\x60" },
++ { .size = 2, .data = "\x13\xA0" },
++ { .size = 2, .data = "\x14\x48" },
++ // PWM shutdown group register (0x19): no shutdown
++ { .size = 2, .data = "\x19\x00" },
++ // Input multiplexer register (0x20): BD mode
++ { .size = 2, .data = "\x20\x00\x89\x77\x72" },
++ // PWM output mux register (0x25)
++ // Channel 1 --> OUTA, channel 1 neg --> OUTB
++ // Channel 2 --> OUTC, channel 2 neg --> OUTD
++ { .size = 5, .data = "\x25\x01\x02\x13\x45" },
++ // DRC control (0x46): DRC off
++ { .size = 5, .data = "\x46\x00\x00\x00\x00" },
++ // BKND_ERR register (0x1C): 299ms reset period
++ { .size = 2, .data = "\x1C\x07" },
++ // Mute channel 3
++ { .size = 2, .data = "\x0A\xFF" },
++ // Volume configuration register (0x0E): volume slew 512 steps
++ { .size = 2, .data = "\x0E\x90" },
++ // Clock control register (0x00): 44/48kHz, MCLK=64xfs
++ { .size = 2, .data = "\x00\x60" },
++ // Bank switch and eq control (0x50): no bank switching
++ { .size = 5, .data = "\x50\x00\x00\x00\x00" },
++ // Volume registers (0x07, 0x08, 0x09, 0x0A)
++ { .size = 2, .data = "\x07\x20" },
++ { .size = 2, .data = "\x08\x30" },
++ { .size = 2, .data = "\x09\x30" },
++ { .size = 2, .data = "\x0A\xFF" },
++ // 0x72, 0x73, 0x76, 0x77 input mixer:
++ // no intermix between channels
++ { .size = 5, .data = "\x72\x00\x00\x00\x00" },
++ { .size = 5, .data = "\x73\x00\x80\x00\x00" },
++ { .size = 5, .data = "\x76\x00\x00\x00\x00" },
++ { .size = 5, .data = "\x77\x00\x80\x00\x00" },
++ // 0x70, 0x71, 0x74, 0x75 inline DRC mixer:
++ // no inline DRC inmix
++ { .size = 5, .data = "\x70\x00\x80\x00\x00" },
++ { .size = 5, .data = "\x71\x00\x00\x00\x00" },
++ { .size = 5, .data = "\x74\x00\x80\x00\x00" },
++ { .size = 5, .data = "\x75\x00\x00\x00\x00" },
++ // 0x56, 0x57 Output scale
++ { .size = 5, .data = "\x56\x00\x80\x00\x00" },
++ { .size = 5, .data = "\x57\x00\x02\x00\x00" },
++ // 0x3B, 0x3c
++ { .size = 9, .data = "\x3B\x00\x08\x00\x00\x00\x78\x00\x00" },
++ { .size = 9, .data = "\x3C\x00\x00\x01\x00\xFF\xFF\xFF\x00" },
++ { .size = 9, .data = "\x3E\x00\x08\x00\x00\x00\x78\x00\x00" },
++ { .size = 9, .data = "\x3F\x00\x00\x01\x00\xFF\xFF\xFF\x00" },
++ { .size = 9, .data = "\x40\x00\x00\x01\x00\xFF\xFF\xFF\x00" },
++ { .size = 9, .data = "\x43\x00\x00\x01\x00\xFF\xFF\xFF\x00" },
++ // 0x51, 0x52: output mixer
++ { .size = 9, .data = "\x51\x00\x80\x00\x00\x00\x00\x00\x00" },
++ { .size = 9, .data = "\x52\x00\x80\x00\x00\x00\x00\x00\x00" },
++ // PEQ defaults
++ { .size = 21, .data = "\x29\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" },
++ { .size = 21, .data = "\x2A\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" },
++ { .size = 21, .data = "\x2B\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" },
++ { .size = 21, .data = "\x2C\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" },
++ { .size = 21, .data = "\x2D\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" },
++ { .size = 21, .data = "\x2E\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" },
++ { .size = 21, .data = "\x2F\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" },
++ { .size = 21, .data = "\x30\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" },
++ { .size = 21, .data = "\x31\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" },
++ { .size = 21, .data = "\x32\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" },
++ { .size = 21, .data = "\x33\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" },
++ { .size = 21, .data = "\x34\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" },
++ { .size = 21, .data = "\x35\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" },
++ { .size = 21, .data = "\x36\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" },
++ { .size = 21, .data = "\x58\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" },
++ { .size = 21, .data = "\x59\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" },
++ { .size = 21, .data = "\x5C\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" },
++ { .size = 21, .data = "\x5D\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" },
++ { .size = 21, .data = "\x5E\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" },
++ { .size = 21, .data = "\x5F\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" },
++ { .size = 21, .data = "\x5A\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" },
++ { .size = 21, .data = "\x5B\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" },
++};
++
++
++#endif /* _TAS5713_H */
+diff -Nur linux-3.12.33/sound/soc/codecs/wm8804.c linux-3.12.33-rpi/sound/soc/codecs/wm8804.c
+--- linux-3.12.33/sound/soc/codecs/wm8804.c 2014-11-15 06:28:07.000000000 -0600
++++ linux-3.12.33-rpi/sound/soc/codecs/wm8804.c 2014-12-03 19:13:44.792418001 -0600
@@ -63,6 +63,7 @@
struct regmap *regmap;
struct regulator_bulk_data supplies[WM8804_NUM_SUPPLIES];
@@ -106209,9 +113567,9 @@ diff -Nur linux-3.12.26.orig/sound/soc/codecs/wm8804.c linux-3.12.26/sound/soc/c
.controls = wm8804_snd_controls,
.num_controls = ARRAY_SIZE(wm8804_snd_controls),
-diff -Nur linux-3.12.26.orig/sound/soc/codecs/wm8804.h linux-3.12.26/sound/soc/codecs/wm8804.h
---- linux-3.12.26.orig/sound/soc/codecs/wm8804.h 2014-07-30 18:02:44.000000000 +0200
-+++ linux-3.12.26/sound/soc/codecs/wm8804.h 2014-08-06 16:50:15.213967961 +0200
+diff -Nur linux-3.12.33/sound/soc/codecs/wm8804.h linux-3.12.33-rpi/sound/soc/codecs/wm8804.h
+--- linux-3.12.33/sound/soc/codecs/wm8804.h 2014-11-15 06:28:07.000000000 -0600
++++ linux-3.12.33-rpi/sound/soc/codecs/wm8804.h 2014-12-03 19:13:44.792418001 -0600
@@ -57,5 +57,9 @@
#define WM8804_CLKOUT_SRC_OSCCLK 4
@@ -106222,9 +113580,24 @@ diff -Nur linux-3.12.26.orig/sound/soc/codecs/wm8804.h linux-3.12.26/sound/soc/c
+#define WM8804_MCLKDIV_128FS 1
#endif /* _WM8804_H */
-diff -Nur linux-3.12.26.orig/sound/soc/Kconfig linux-3.12.26/sound/soc/Kconfig
---- linux-3.12.26.orig/sound/soc/Kconfig 2014-07-30 18:02:44.000000000 +0200
-+++ linux-3.12.26/sound/soc/Kconfig 2014-08-06 16:50:15.213967961 +0200
+diff -Nur linux-3.12.33/sound/soc/generic/simple-card.c linux-3.12.33-rpi/sound/soc/generic/simple-card.c
+--- linux-3.12.33/sound/soc/generic/simple-card.c 2014-11-15 06:28:07.000000000 -0600
++++ linux-3.12.33-rpi/sound/soc/generic/simple-card.c 2014-12-03 19:13:44.812418001 -0600
+@@ -27,6 +27,11 @@
+ if (!ret && daifmt)
+ ret = snd_soc_dai_set_fmt(dai, daifmt);
+
++ if (ret == -ENOTSUPP) {
++ dev_dbg(dai->dev, "ASoC: set_fmt is not supported\n");
++ ret = 0;
++ }
++
+ if (!ret && set->sysclk)
+ ret = snd_soc_dai_set_sysclk(dai, 0, set->sysclk, 0);
+
+diff -Nur linux-3.12.33/sound/soc/Kconfig linux-3.12.33-rpi/sound/soc/Kconfig
+--- linux-3.12.33/sound/soc/Kconfig 2014-11-15 06:28:07.000000000 -0600
++++ linux-3.12.33-rpi/sound/soc/Kconfig 2014-12-03 19:13:44.592418001 -0600
@@ -33,6 +33,7 @@
# All the supported SoCs
source "sound/soc/atmel/Kconfig"
@@ -106233,9 +113606,9 @@ diff -Nur linux-3.12.26.orig/sound/soc/Kconfig linux-3.12.26/sound/soc/Kconfig
source "sound/soc/blackfin/Kconfig"
source "sound/soc/cirrus/Kconfig"
source "sound/soc/davinci/Kconfig"
-diff -Nur linux-3.12.26.orig/sound/soc/Makefile linux-3.12.26/sound/soc/Makefile
---- linux-3.12.26.orig/sound/soc/Makefile 2014-07-30 18:02:44.000000000 +0200
-+++ linux-3.12.26/sound/soc/Makefile 2014-08-06 16:50:15.213967961 +0200
+diff -Nur linux-3.12.33/sound/soc/Makefile linux-3.12.33-rpi/sound/soc/Makefile
+--- linux-3.12.33/sound/soc/Makefile 2014-11-15 06:28:07.000000000 -0600
++++ linux-3.12.33-rpi/sound/soc/Makefile 2014-12-03 19:13:44.592418001 -0600
@@ -10,6 +10,7 @@
obj-$(CONFIG_SND_SOC) += generic/
obj-$(CONFIG_SND_SOC) += atmel/
@@ -106244,9 +113617,9 @@ diff -Nur linux-3.12.26.orig/sound/soc/Makefile linux-3.12.26/sound/soc/Makefile
obj-$(CONFIG_SND_SOC) += blackfin/
obj-$(CONFIG_SND_SOC) += cirrus/
obj-$(CONFIG_SND_SOC) += davinci/
-diff -Nur linux-3.12.26.orig/sound/soc/soc-core.c linux-3.12.26/sound/soc/soc-core.c
---- linux-3.12.26.orig/sound/soc/soc-core.c 2014-07-30 18:02:44.000000000 +0200
-+++ linux-3.12.26/sound/soc/soc-core.c 2014-08-06 16:50:15.213967961 +0200
+diff -Nur linux-3.12.33/sound/soc/soc-core.c linux-3.12.33-rpi/sound/soc/soc-core.c
+--- linux-3.12.33/sound/soc/soc-core.c 2014-11-15 06:28:07.000000000 -0600
++++ linux-3.12.33-rpi/sound/soc/soc-core.c 2014-12-03 19:13:44.828418001 -0600
@@ -3038,8 +3038,8 @@
uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
diff --git a/target/config/Config.in.kernelversion.choice b/target/config/Config.in.kernelversion.choice
index d267b936c..4ea43d591 100644
--- a/target/config/Config.in.kernelversion.choice
+++ b/target/config/Config.in.kernelversion.choice
@@ -18,8 +18,8 @@ config ADK_KERNEL_VERSION_3_14_22
boolean
select ADK_KERNEL_VERSION_3_14
-config ADK_KERNEL_VERSION_3_12_27
- prompt "3.12.27"
+config ADK_KERNEL_VERSION_3_12_33
+ prompt "3.12.33"
depends on !ADK_TARGET_SYSTEM_SOLIDRUN_IMX6
depends on !ADK_TARGET_SYSTEM_MIKROTIK_RB4XX
boolean
diff --git a/target/config/Config.in.kernelversion.default b/target/config/Config.in.kernelversion.default
index 0636c0b01..d02b41730 100644
--- a/target/config/Config.in.kernelversion.default
+++ b/target/config/Config.in.kernelversion.default
@@ -20,7 +20,7 @@ config ADK_KERNEL_VERSION
string
default "3.16.6" if ADK_KERNEL_VERSION_3_16_6
default "3.14.22" if ADK_KERNEL_VERSION_3_14_22
- default "3.12.27" if ADK_KERNEL_VERSION_3_12_27
+ default "3.12.33" if ADK_KERNEL_VERSION_3_12_33
default "3.10.53" if ADK_KERNEL_VERSION_3_10_53
default "3.4.103" if ADK_KERNEL_VERSION_3_4_103
help
diff --git a/target/linux/patches/3.12.27/bsd-compatibility.patch b/target/linux/patches/3.12.33/bsd-compatibility.patch
index b954b658f..b954b658f 100644
--- a/target/linux/patches/3.12.27/bsd-compatibility.patch
+++ b/target/linux/patches/3.12.33/bsd-compatibility.patch
diff --git a/target/linux/patches/3.12.27/cleankernel.patch b/target/linux/patches/3.12.33/cleankernel.patch
index d8c055dc3..d8c055dc3 100644
--- a/target/linux/patches/3.12.27/cleankernel.patch
+++ b/target/linux/patches/3.12.33/cleankernel.patch
diff --git a/target/linux/patches/3.12.27/defaults.patch b/target/linux/patches/3.12.33/defaults.patch
index 6cdca084e..6cdca084e 100644
--- a/target/linux/patches/3.12.27/defaults.patch
+++ b/target/linux/patches/3.12.33/defaults.patch
diff --git a/target/linux/patches/3.12.27/disable-netfilter.patch b/target/linux/patches/3.12.33/disable-netfilter.patch
index 7b1ca013a..7b1ca013a 100644
--- a/target/linux/patches/3.12.27/disable-netfilter.patch
+++ b/target/linux/patches/3.12.33/disable-netfilter.patch
diff --git a/target/linux/patches/3.12.27/export-symbol-for-exmap.patch b/target/linux/patches/3.12.33/export-symbol-for-exmap.patch
index 4f0fc8449..4f0fc8449 100644
--- a/target/linux/patches/3.12.27/export-symbol-for-exmap.patch
+++ b/target/linux/patches/3.12.33/export-symbol-for-exmap.patch
diff --git a/target/linux/patches/3.12.27/gemalto.patch b/target/linux/patches/3.12.33/gemalto.patch
index 65f7af1d7..65f7af1d7 100644
--- a/target/linux/patches/3.12.27/gemalto.patch
+++ b/target/linux/patches/3.12.33/gemalto.patch
diff --git a/target/linux/patches/3.12.27/lemote-rfkill.patch b/target/linux/patches/3.12.33/lemote-rfkill.patch
index a61488434..a61488434 100644
--- a/target/linux/patches/3.12.27/lemote-rfkill.patch
+++ b/target/linux/patches/3.12.33/lemote-rfkill.patch
diff --git a/target/linux/patches/3.12.27/microblaze-ethernet.patch b/target/linux/patches/3.12.33/microblaze-ethernet.patch
index 742ab477e..742ab477e 100644
--- a/target/linux/patches/3.12.27/microblaze-ethernet.patch
+++ b/target/linux/patches/3.12.33/microblaze-ethernet.patch
diff --git a/target/linux/patches/3.12.27/microblaze-setup.patch b/target/linux/patches/3.12.33/microblaze-setup.patch
index 43815f274..43815f274 100644
--- a/target/linux/patches/3.12.27/microblaze-setup.patch
+++ b/target/linux/patches/3.12.33/microblaze-setup.patch
diff --git a/target/linux/patches/3.12.27/mips-lzo-fix.patch b/target/linux/patches/3.12.33/mips-lzo-fix.patch
index 0740bdc6a..0740bdc6a 100644
--- a/target/linux/patches/3.12.27/mips-lzo-fix.patch
+++ b/target/linux/patches/3.12.33/mips-lzo-fix.patch
diff --git a/target/linux/patches/3.12.27/mkpiggy.patch b/target/linux/patches/3.12.33/mkpiggy.patch
index d4e815cd2..d4e815cd2 100644
--- a/target/linux/patches/3.12.27/mkpiggy.patch
+++ b/target/linux/patches/3.12.33/mkpiggy.patch
diff --git a/target/linux/patches/3.12.27/mtd-rootfs.patch b/target/linux/patches/3.12.33/mtd-rootfs.patch
index 775d5fc80..775d5fc80 100644
--- a/target/linux/patches/3.12.27/mtd-rootfs.patch
+++ b/target/linux/patches/3.12.33/mtd-rootfs.patch
diff --git a/target/linux/patches/3.12.27/non-static.patch b/target/linux/patches/3.12.33/non-static.patch
index a967703d0..a967703d0 100644
--- a/target/linux/patches/3.12.27/non-static.patch
+++ b/target/linux/patches/3.12.33/non-static.patch
diff --git a/target/linux/patches/3.12.27/patch-yaffs2 b/target/linux/patches/3.12.33/patch-yaffs2
index 306814439..306814439 100644
--- a/target/linux/patches/3.12.27/patch-yaffs2
+++ b/target/linux/patches/3.12.33/patch-yaffs2
diff --git a/target/linux/patches/3.12.27/ppc64-missing-zlib.patch b/target/linux/patches/3.12.33/ppc64-missing-zlib.patch
index c6e0616be..c6e0616be 100644
--- a/target/linux/patches/3.12.27/ppc64-missing-zlib.patch
+++ b/target/linux/patches/3.12.33/ppc64-missing-zlib.patch
diff --git a/target/linux/patches/3.12.27/relocs.patch b/target/linux/patches/3.12.33/relocs.patch
index 649b9e73e..649b9e73e 100644
--- a/target/linux/patches/3.12.27/relocs.patch
+++ b/target/linux/patches/3.12.33/relocs.patch
diff --git a/target/linux/patches/3.12.27/sgidefs.patch b/target/linux/patches/3.12.33/sgidefs.patch
index f00a284d9..f00a284d9 100644
--- a/target/linux/patches/3.12.27/sgidefs.patch
+++ b/target/linux/patches/3.12.33/sgidefs.patch
diff --git a/target/linux/patches/3.12.27/sortext.patch b/target/linux/patches/3.12.33/sortext.patch
index 8fd4e1d6b..8fd4e1d6b 100644
--- a/target/linux/patches/3.12.27/sortext.patch
+++ b/target/linux/patches/3.12.33/sortext.patch
diff --git a/target/linux/patches/3.12.27/startup.patch b/target/linux/patches/3.12.33/startup.patch
index 4cd477da1..4cd477da1 100644
--- a/target/linux/patches/3.12.27/startup.patch
+++ b/target/linux/patches/3.12.33/startup.patch
diff --git a/target/linux/patches/3.12.27/tcp-fastopen.patch b/target/linux/patches/3.12.33/tcp-fastopen.patch
index c1ff7209c..c1ff7209c 100644
--- a/target/linux/patches/3.12.27/tcp-fastopen.patch
+++ b/target/linux/patches/3.12.33/tcp-fastopen.patch
diff --git a/target/linux/patches/3.12.27/usb-defaults-off.patch b/target/linux/patches/3.12.33/usb-defaults-off.patch
index 54dff2bd4..54dff2bd4 100644
--- a/target/linux/patches/3.12.27/usb-defaults-off.patch
+++ b/target/linux/patches/3.12.33/usb-defaults-off.patch
diff --git a/target/linux/patches/3.12.27/vga-cons-default-off.patch b/target/linux/patches/3.12.33/vga-cons-default-off.patch
index 08a57f783..08a57f783 100644
--- a/target/linux/patches/3.12.27/vga-cons-default-off.patch
+++ b/target/linux/patches/3.12.33/vga-cons-default-off.patch
diff --git a/target/linux/patches/3.12.27/wlan-cf.patch b/target/linux/patches/3.12.33/wlan-cf.patch
index fc20759e2..fc20759e2 100644
--- a/target/linux/patches/3.12.27/wlan-cf.patch
+++ b/target/linux/patches/3.12.33/wlan-cf.patch
diff --git a/target/linux/patches/3.12.27/xargs.patch b/target/linux/patches/3.12.33/xargs.patch
index 2c7b3df59..2c7b3df59 100644
--- a/target/linux/patches/3.12.27/xargs.patch
+++ b/target/linux/patches/3.12.33/xargs.patch
diff --git a/target/linux/patches/3.12.27/zlib-inflate.patch b/target/linux/patches/3.12.33/zlib-inflate.patch
index 58e1f6d21..58e1f6d21 100644
--- a/target/linux/patches/3.12.27/zlib-inflate.patch
+++ b/target/linux/patches/3.12.33/zlib-inflate.patch
diff --git a/target/mips/mikrotik-rb532/patches/3.12.27/rb532-cfgfs.patch b/target/mips/mikrotik-rb532/patches/3.12.33/rb532-cfgfs.patch
index 36ce30d91..36ce30d91 100644
--- a/target/mips/mikrotik-rb532/patches/3.12.27/rb532-cfgfs.patch
+++ b/target/mips/mikrotik-rb532/patches/3.12.33/rb532-cfgfs.patch
diff --git a/target/mips/mikrotik-rb532/patches/3.12.27/rb532-pci.patch b/target/mips/mikrotik-rb532/patches/3.12.33/rb532-pci.patch
index adfa652b5..adfa652b5 100644
--- a/target/mips/mikrotik-rb532/patches/3.12.27/rb532-pci.patch
+++ b/target/mips/mikrotik-rb532/patches/3.12.33/rb532-pci.patch