diff options
Diffstat (limited to 'target')
-rw-r--r-- | target/arm/raspberry-pi/patches/3.12.33/0001-add-support-for-rpi-proto-driver.patch | 226 | ||||
-rw-r--r-- | target/arm/raspberry-pi/patches/3.12.33/0002-enable-MMAP-by-default-allow-overide-via-use_mmap.patch | 53 | ||||
-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.choice | 4 | ||||
-rw-r--r-- | target/config/Config.in.kernelversion.default | 2 | ||||
-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 |
32 files changed, 12274 insertions, 4622 deletions
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(¤t->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(¤t->mm->mmap_sem); ++ if (__get_user(temp, (char __user *)from)) ++ goto out; ++ if (!atomic) ++ down_read(¤t->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(¤t->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, ++ ¶ms, &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(¤t->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(¤t->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(¤t->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(¤t->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(¤t->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(¤t->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(¤t->mm->mmap_sem); ++ vcsm_vma_cache_clean_page_range((unsigned long) ++ ioparam.addr, ++ (unsigned long) ++ ioparam.addr + ++ ioparam.size); ++ up_read(¤t->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(¤t->mm->mmap_sem); ++ vcsm_vma_cache_clean_page_range((unsigned long) ++ ioparam.addr, ++ (unsigned long) ++ ioparam.addr + ++ ioparam.size); ++ up_read(¤t->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(®istration_lock); -- ret = do_remove_conflicting_framebuffers(a, name, primary); -+ do_remove_conflicting_framebuffers(a, name, primary); - mutex_unlock(®istration_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, ¶ms, + &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 |