summaryrefslogtreecommitdiffstats
path: root/target/linux/generic/patches-3.7
diff options
context:
space:
mode:
Diffstat (limited to 'target/linux/generic/patches-3.7')
-rw-r--r--target/linux/generic/patches-3.7/010-mtd_mp25p80_add_gd25q32_gd25q64.patch13
-rw-r--r--target/linux/generic/patches-3.7/020-ssb_update.patch1268
-rw-r--r--target/linux/generic/patches-3.7/021-ssb-add-PCI-ID-0x4350.patch10
-rw-r--r--target/linux/generic/patches-3.7/022-ssb-handle-BCM43222-in-pmu-code.patch19
-rw-r--r--target/linux/generic/patches-3.7/025-bcma_backport.patch1518
-rw-r--r--target/linux/generic/patches-3.7/065-8139cp-fixes.patch20
-rw-r--r--target/linux/generic/patches-3.7/067-mips_mt_fix_uidgid_strict_type_check.patch41
-rw-r--r--target/linux/generic/patches-3.7/084-x86_fix_perf_uclibc_build.patch27
-rw-r--r--target/linux/generic/patches-3.7/100-overlayfs.patch14
-rw-r--r--target/linux/generic/patches-3.7/102-ehci_hcd_ignore_oc.patch2
-rw-r--r--target/linux/generic/patches-3.7/131-atm-fixes.patch6
-rw-r--r--target/linux/generic/patches-3.7/132-solos-dma.patch388
-rw-r--r--target/linux/generic/patches-3.7/203-kallsyms_uncompressed.patch108
-rw-r--r--target/linux/generic/patches-3.7/220-gc_sections.patch372
-rw-r--r--target/linux/generic/patches-3.7/221-module_exports.patch (renamed from target/linux/generic/patches-3.7/220-module_exports.patch)45
-rw-r--r--target/linux/generic/patches-3.7/250-netfilter_depends.patch2
-rw-r--r--target/linux/generic/patches-3.7/251-sound_kconfig.patch9
-rw-r--r--target/linux/generic/patches-3.7/259-regmap_dynamic.patch72
-rw-r--r--target/linux/generic/patches-3.7/260-crypto_test_dependencies.patch37
-rw-r--r--target/linux/generic/patches-3.7/261-move_bcm963xx_tag.patch233
-rw-r--r--target/linux/generic/patches-3.7/262-compressor_kconfig_hack.patch23
-rw-r--r--target/linux/generic/patches-3.7/302-mips_no_branch_likely.patch11
-rw-r--r--target/linux/generic/patches-3.7/305-mips_module_reloc.patch350
-rw-r--r--target/linux/generic/patches-3.7/307-mips_oprofile_fix.patch35
-rw-r--r--target/linux/generic/patches-3.7/308-mips-show-correct-cpu-name-for-24KEc.patch2
-rw-r--r--target/linux/generic/patches-3.7/330-mips-add-crash-and-kdump-support.patch6
-rw-r--r--target/linux/generic/patches-3.7/331-mips-kexec-enhanche-the-support.patch14
-rw-r--r--target/linux/generic/patches-3.7/332-mips-kexec-init-the-arguments-for-the-new-kernel-image.patch2
-rw-r--r--target/linux/generic/patches-3.7/333-mips-kexec-get-kernel-parameters-from-kexec-tools.patch8
-rw-r--r--target/linux/generic/patches-3.7/335-mips-kexec-cleanup-kexec-tools-parameter-handling.patch6
-rw-r--r--target/linux/generic/patches-3.7/340-module_alloc_size_check.patch2
-rw-r--r--target/linux/generic/patches-3.7/470-mtd_m25p80_add_pm25lv_flash_support.patch4
-rw-r--r--target/linux/generic/patches-3.7/473-mtd_m25p80_add_w25q128.patch2
-rw-r--r--target/linux/generic/patches-3.7/474-mtd_mp25p80_add_pm25lq032.patch10
-rw-r--r--target/linux/generic/patches-3.7/476-mtd-m25p80-allow-to-disable-small-sector-erase.patch2
-rw-r--r--target/linux/generic/patches-3.7/541-ubifs-xz-decompression-support.patch2
-rw-r--r--target/linux/generic/patches-3.7/551-ubifs-fix-default-compression-selection.patch29
-rw-r--r--target/linux/generic/patches-3.7/600-netfilter_layer7_2.22.patch2
-rw-r--r--target/linux/generic/patches-3.7/603-netfilter_layer7_2.6.36_fix.patch4
-rw-r--r--target/linux/generic/patches-3.7/604-netfilter_cisco_794x_iphone.patch131
-rw-r--r--target/linux/generic/patches-3.7/604-netfilter_conntrack_flush.patch46
-rw-r--r--target/linux/generic/patches-3.7/630-packet_socket_type.patch6
-rw-r--r--target/linux/generic/patches-3.7/651-wireless_mesh_header.patch2
-rw-r--r--target/linux/generic/patches-3.7/700-swconfig.patch10
-rw-r--r--target/linux/generic/patches-3.7/703-phy-add-detach-callback-to-struct-phy_driver.patch27
-rw-r--r--target/linux/generic/patches-3.7/710-phy-add-mdio_register_board_info.patch2
-rw-r--r--target/linux/generic/patches-3.7/721-phy_packets.patch6
-rw-r--r--target/linux/generic/patches-3.7/730-phy_b53.patch21
-rw-r--r--target/linux/generic/patches-3.7/800-usb-ohci-multiple-platform-driver-fix.patch51
-rw-r--r--target/linux/generic/patches-3.7/801-usb-ehci-multiple-platform-driver-fix.patch47
-rw-r--r--target/linux/generic/patches-3.7/810-pci_disable_common_quirks.patch34
-rw-r--r--target/linux/generic/patches-3.7/811-pci_disable_usb_common_quirks.patch67
-rw-r--r--target/linux/generic/patches-3.7/850-glamo_headers.patch2
-rw-r--r--target/linux/generic/patches-3.7/863-gpiommc.patch2
-rw-r--r--target/linux/generic/patches-3.7/901-debloat_sock_diag.patch46
-rw-r--r--target/linux/generic/patches-3.7/902-debloat_proc.patch338
-rw-r--r--target/linux/generic/patches-3.7/903-debloat_direct_io.patch84
-rw-r--r--target/linux/generic/patches-3.7/920-unable_to_open_console.patch2
-rw-r--r--target/linux/generic/patches-3.7/930-crashlog.patch2
-rw-r--r--target/linux/generic/patches-3.7/941-ocf_20120127.patch2
-rw-r--r--target/linux/generic/patches-3.7/950-vm_exports.patch8
61 files changed, 5350 insertions, 304 deletions
diff --git a/target/linux/generic/patches-3.7/010-mtd_mp25p80_add_gd25q32_gd25q64.patch b/target/linux/generic/patches-3.7/010-mtd_mp25p80_add_gd25q32_gd25q64.patch
new file mode 100644
index 000000000..4af122e11
--- /dev/null
+++ b/target/linux/generic/patches-3.7/010-mtd_mp25p80_add_gd25q32_gd25q64.patch
@@ -0,0 +1,13 @@
+--- a/drivers/mtd/devices/m25p80.c
++++ b/drivers/mtd/devices/m25p80.c
+@@ -645,6 +645,10 @@ static const struct spi_device_id m25p_i
+ /* Everspin */
+ { "mr25h256", CAT25_INFO( 32 * 1024, 1, 256, 2) },
+
++ /* GigaDevice */
++ { "gd25q32", INFO(0xc84016, 0, 64 * 1024, 64, SECT_4K) },
++ { "gd25q64", INFO(0xc84017, 0, 64 * 1024, 128, SECT_4K) },
++
+ /* Intel/Numonyx -- xxxs33b */
+ { "160s33b", INFO(0x898911, 0, 64 * 1024, 32, 0) },
+ { "320s33b", INFO(0x898912, 0, 64 * 1024, 64, 0) },
diff --git a/target/linux/generic/patches-3.7/020-ssb_update.patch b/target/linux/generic/patches-3.7/020-ssb_update.patch
new file mode 100644
index 000000000..d44c8129c
--- /dev/null
+++ b/target/linux/generic/patches-3.7/020-ssb_update.patch
@@ -0,0 +1,1268 @@
+--- a/arch/mips/bcm47xx/nvram.c
++++ b/arch/mips/bcm47xx/nvram.c
+@@ -43,8 +43,8 @@ static void early_nvram_init(void)
+ #ifdef CONFIG_BCM47XX_SSB
+ case BCM47XX_BUS_TYPE_SSB:
+ mcore_ssb = &bcm47xx_bus.ssb.mipscore;
+- base = mcore_ssb->flash_window;
+- lim = mcore_ssb->flash_window_size;
++ base = mcore_ssb->pflash.window;
++ lim = mcore_ssb->pflash.window_size;
+ break;
+ #endif
+ #ifdef CONFIG_BCM47XX_BCMA
+--- a/arch/mips/bcm47xx/wgt634u.c
++++ b/arch/mips/bcm47xx/wgt634u.c
+@@ -156,10 +156,10 @@ static int __init wgt634u_init(void)
+ SSB_CHIPCO_IRQ_GPIO);
+ }
+
+- wgt634u_flash_data.width = mcore->flash_buswidth;
+- wgt634u_flash_resource.start = mcore->flash_window;
+- wgt634u_flash_resource.end = mcore->flash_window
+- + mcore->flash_window_size
++ wgt634u_flash_data.width = mcore->pflash.buswidth;
++ wgt634u_flash_resource.start = mcore->pflash.window;
++ wgt634u_flash_resource.end = mcore->pflash.window
++ + mcore->pflash.window_size
+ - 1;
+ return platform_add_devices(wgt634u_devices,
+ ARRAY_SIZE(wgt634u_devices));
+--- a/drivers/ssb/Kconfig
++++ b/drivers/ssb/Kconfig
+@@ -136,6 +136,11 @@ config SSB_DRIVER_MIPS
+
+ If unsure, say N
+
++config SSB_SFLASH
++ bool "SSB serial flash support"
++ depends on SSB_DRIVER_MIPS && BROKEN
++ default y
++
+ # Assumption: We are on embedded, if we compile the MIPS core.
+ config SSB_EMBEDDED
+ bool
+@@ -160,4 +165,12 @@ config SSB_DRIVER_GIGE
+
+ If unsure, say N
+
++config SSB_DRIVER_GPIO
++ bool "SSB GPIO driver"
++ depends on SSB && GPIOLIB
++ help
++ Driver to provide access to the GPIO pins on the bus.
++
++ If unsure, say N
++
+ endmenu
+--- a/drivers/ssb/Makefile
++++ b/drivers/ssb/Makefile
+@@ -11,10 +11,12 @@ ssb-$(CONFIG_SSB_SDIOHOST) += sdio.o
+ # built-in drivers
+ ssb-y += driver_chipcommon.o
+ ssb-y += driver_chipcommon_pmu.o
++ssb-$(CONFIG_SSB_SFLASH) += driver_chipcommon_sflash.o
+ ssb-$(CONFIG_SSB_DRIVER_MIPS) += driver_mipscore.o
+ ssb-$(CONFIG_SSB_DRIVER_EXTIF) += driver_extif.o
+ ssb-$(CONFIG_SSB_DRIVER_PCICORE) += driver_pcicore.o
+ ssb-$(CONFIG_SSB_DRIVER_GIGE) += driver_gige.o
++ssb-$(CONFIG_SSB_DRIVER_GPIO) += driver_gpio.o
+
+ # b43 pci-ssb-bridge driver
+ # Not strictly a part of SSB, but kept here for convenience
+--- a/drivers/ssb/b43_pci_bridge.c
++++ b/drivers/ssb/b43_pci_bridge.c
+@@ -37,6 +37,7 @@ static const struct pci_device_id b43_pc
+ { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4329) },
+ { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x432b) },
+ { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x432c) },
++ { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4350) },
+ { 0, },
+ };
+ MODULE_DEVICE_TABLE(pci, b43_pci_bridge_tbl);
+--- a/drivers/ssb/driver_chipcommon.c
++++ b/drivers/ssb/driver_chipcommon.c
+@@ -4,6 +4,7 @@
+ *
+ * Copyright 2005, Broadcom Corporation
+ * Copyright 2006, 2007, Michael Buesch <m@bues.ch>
++ * Copyright 2012, Hauke Mehrtens <hauke@hauke-m.de>
+ *
+ * Licensed under the GNU/GPL. See COPYING for details.
+ */
+@@ -12,6 +13,7 @@
+ #include <linux/ssb/ssb_regs.h>
+ #include <linux/export.h>
+ #include <linux/pci.h>
++#include <linux/bcm47xx_wdt.h>
+
+ #include "ssb_private.h"
+
+@@ -280,10 +282,76 @@ static void calc_fast_powerup_delay(stru
+ cc->fast_pwrup_delay = tmp;
+ }
+
++static u32 ssb_chipco_alp_clock(struct ssb_chipcommon *cc)
++{
++ if (cc->capabilities & SSB_CHIPCO_CAP_PMU)
++ return ssb_pmu_get_alp_clock(cc);
++
++ return 20000000;
++}
++
++static u32 ssb_chipco_watchdog_get_max_timer(struct ssb_chipcommon *cc)
++{
++ u32 nb;
++
++ if (cc->capabilities & SSB_CHIPCO_CAP_PMU) {
++ if (cc->dev->id.revision < 26)
++ nb = 16;
++ else
++ nb = (cc->dev->id.revision >= 37) ? 32 : 24;
++ } else {
++ nb = 28;
++ }
++ if (nb == 32)
++ return 0xffffffff;
++ else
++ return (1 << nb) - 1;
++}
++
++u32 ssb_chipco_watchdog_timer_set_wdt(struct bcm47xx_wdt *wdt, u32 ticks)
++{
++ struct ssb_chipcommon *cc = bcm47xx_wdt_get_drvdata(wdt);
++
++ if (cc->dev->bus->bustype != SSB_BUSTYPE_SSB)
++ return 0;
++
++ return ssb_chipco_watchdog_timer_set(cc, ticks);
++}
++
++u32 ssb_chipco_watchdog_timer_set_ms(struct bcm47xx_wdt *wdt, u32 ms)
++{
++ struct ssb_chipcommon *cc = bcm47xx_wdt_get_drvdata(wdt);
++ u32 ticks;
++
++ if (cc->dev->bus->bustype != SSB_BUSTYPE_SSB)
++ return 0;
++
++ ticks = ssb_chipco_watchdog_timer_set(cc, cc->ticks_per_ms * ms);
++ return ticks / cc->ticks_per_ms;
++}
++
++static int ssb_chipco_watchdog_ticks_per_ms(struct ssb_chipcommon *cc)
++{
++ struct ssb_bus *bus = cc->dev->bus;
++
++ if (cc->capabilities & SSB_CHIPCO_CAP_PMU) {
++ /* based on 32KHz ILP clock */
++ return 32;
++ } else {
++ if (cc->dev->id.revision < 18)
++ return ssb_clockspeed(bus) / 1000;
++ else
++ return ssb_chipco_alp_clock(cc) / 1000;
++ }
++}
++
+ void ssb_chipcommon_init(struct ssb_chipcommon *cc)
+ {
+ if (!cc->dev)
+ return; /* We don't have a ChipCommon */
++
++ spin_lock_init(&cc->gpio_lock);
++
+ if (cc->dev->id.revision >= 11)
+ cc->status = chipco_read32(cc, SSB_CHIPCO_CHIPSTAT);
+ ssb_dprintk(KERN_INFO PFX "chipcommon status is 0x%x\n", cc->status);
+@@ -297,6 +365,11 @@ void ssb_chipcommon_init(struct ssb_chip
+ chipco_powercontrol_init(cc);
+ ssb_chipco_set_clockmode(cc, SSB_CLKMODE_FAST);
+ calc_fast_powerup_delay(cc);
++
++ if (cc->dev->bus->bustype == SSB_BUSTYPE_SSB) {
++ cc->ticks_per_ms = ssb_chipco_watchdog_ticks_per_ms(cc);
++ cc->max_timer_ms = ssb_chipco_watchdog_get_max_timer(cc) / cc->ticks_per_ms;
++ }
+ }
+
+ void ssb_chipco_suspend(struct ssb_chipcommon *cc)
+@@ -395,10 +468,27 @@ void ssb_chipco_timing_init(struct ssb_c
+ }
+
+ /* Set chip watchdog reset timer to fire in 'ticks' backplane cycles */
+-void ssb_chipco_watchdog_timer_set(struct ssb_chipcommon *cc, u32 ticks)
++u32 ssb_chipco_watchdog_timer_set(struct ssb_chipcommon *cc, u32 ticks)
+ {
+- /* instant NMI */
+- chipco_write32(cc, SSB_CHIPCO_WATCHDOG, ticks);
++ u32 maxt;
++ enum ssb_clkmode clkmode;
++
++ maxt = ssb_chipco_watchdog_get_max_timer(cc);
++ if (cc->capabilities & SSB_CHIPCO_CAP_PMU) {
++ if (ticks == 1)
++ ticks = 2;
++ else if (ticks > maxt)
++ ticks = maxt;
++ chipco_write32(cc, SSB_CHIPCO_PMU_WATCHDOG, ticks);
++ } else {
++ clkmode = ticks ? SSB_CLKMODE_FAST : SSB_CLKMODE_DYNAMIC;
++ ssb_chipco_set_clockmode(cc, clkmode);
++ if (ticks > maxt)
++ ticks = maxt;
++ /* instant NMI */
++ chipco_write32(cc, SSB_CHIPCO_WATCHDOG, ticks);
++ }
++ return ticks;
+ }
+
+ void ssb_chipco_irq_mask(struct ssb_chipcommon *cc, u32 mask, u32 value)
+@@ -418,28 +508,93 @@ u32 ssb_chipco_gpio_in(struct ssb_chipco
+
+ u32 ssb_chipco_gpio_out(struct ssb_chipcommon *cc, u32 mask, u32 value)
+ {
+- return chipco_write32_masked(cc, SSB_CHIPCO_GPIOOUT, mask, value);
++ unsigned long flags;
++ u32 res = 0;
++
++ spin_lock_irqsave(&cc->gpio_lock, flags);
++ res = chipco_write32_masked(cc, SSB_CHIPCO_GPIOOUT, mask, value);
++ spin_unlock_irqrestore(&cc->gpio_lock, flags);
++
++ return res;
+ }
+
+ u32 ssb_chipco_gpio_outen(struct ssb_chipcommon *cc, u32 mask, u32 value)
+ {
+- return chipco_write32_masked(cc, SSB_CHIPCO_GPIOOUTEN, mask, value);
++ unsigned long flags;
++ u32 res = 0;
++
++ spin_lock_irqsave(&cc->gpio_lock, flags);
++ res = chipco_write32_masked(cc, SSB_CHIPCO_GPIOOUTEN, mask, value);
++ spin_unlock_irqrestore(&cc->gpio_lock, flags);
++
++ return res;
+ }
+
+ u32 ssb_chipco_gpio_control(struct ssb_chipcommon *cc, u32 mask, u32 value)
+ {
+- return chipco_write32_masked(cc, SSB_CHIPCO_GPIOCTL, mask, value);
++ unsigned long flags;
++ u32 res = 0;
++
++ spin_lock_irqsave(&cc->gpio_lock, flags);
++ res = chipco_write32_masked(cc, SSB_CHIPCO_GPIOCTL, mask, value);
++ spin_unlock_irqrestore(&cc->gpio_lock, flags);
++
++ return res;
+ }
+ EXPORT_SYMBOL(ssb_chipco_gpio_control);
+
+ u32 ssb_chipco_gpio_intmask(struct ssb_chipcommon *cc, u32 mask, u32 value)
+ {
+- return chipco_write32_masked(cc, SSB_CHIPCO_GPIOIRQ, mask, value);
++ unsigned long flags;
++ u32 res = 0;
++
++ spin_lock_irqsave(&cc->gpio_lock, flags);
++ res = chipco_write32_masked(cc, SSB_CHIPCO_GPIOIRQ, mask, value);
++ spin_unlock_irqrestore(&cc->gpio_lock, flags);
++
++ return res;
+ }
+
+ u32 ssb_chipco_gpio_polarity(struct ssb_chipcommon *cc, u32 mask, u32 value)
+ {
+- return chipco_write32_masked(cc, SSB_CHIPCO_GPIOPOL, mask, value);
++ unsigned long flags;
++ u32 res = 0;
++
++ spin_lock_irqsave(&cc->gpio_lock, flags);
++ res = chipco_write32_masked(cc, SSB_CHIPCO_GPIOPOL, mask, value);
++ spin_unlock_irqrestore(&cc->gpio_lock, flags);
++
++ return res;
++}
++
++u32 ssb_chipco_gpio_pullup(struct ssb_chipcommon *cc, u32 mask, u32 value)
++{
++ unsigned long flags;
++ u32 res = 0;
++
++ if (cc->dev->id.revision < 20)
++ return 0xffffffff;
++
++ spin_lock_irqsave(&cc->gpio_lock, flags);
++ res = chipco_write32_masked(cc, SSB_CHIPCO_GPIOPULLUP, mask, value);
++ spin_unlock_irqrestore(&cc->gpio_lock, flags);
++
++ return res;
++}
++
++u32 ssb_chipco_gpio_pulldown(struct ssb_chipcommon *cc, u32 mask, u32 value)
++{
++ unsigned long flags;
++ u32 res = 0;
++
++ if (cc->dev->id.revision < 20)
++ return 0xffffffff;
++
++ spin_lock_irqsave(&cc->gpio_lock, flags);
++ res = chipco_write32_masked(cc, SSB_CHIPCO_GPIOPULLDOWN, mask, value);
++ spin_unlock_irqrestore(&cc->gpio_lock, flags);
++
++ return res;
+ }
+
+ #ifdef CONFIG_SSB_SERIAL
+@@ -473,12 +628,7 @@ int ssb_chipco_serial_init(struct ssb_ch
+ chipco_read32(cc, SSB_CHIPCO_CORECTL)
+ | SSB_CHIPCO_CORECTL_UARTCLK0);
+ } else if ((ccrev >= 11) && (ccrev != 15)) {
+- /* Fixed ALP clock */
+- baud_base = 20000000;
+- if (cc->capabilities & SSB_CHIPCO_CAP_PMU) {
+- /* FIXME: baud_base is different for devices with a PMU */
+- SSB_WARN_ON(1);
+- }
++ baud_base = ssb_chipco_alp_clock(cc);
+ div = 1;
+ if (ccrev >= 21) {
+ /* Turn off UART clock before switching clocksource. */
+--- a/drivers/ssb/driver_chipcommon_pmu.c
++++ b/drivers/ssb/driver_chipcommon_pmu.c
+@@ -346,6 +346,8 @@ static void ssb_pmu_pll_init(struct ssb_
+ chipco_write32(cc, SSB_CHIPCO_PLLCTL_DATA, 0x380005C0);
+ }
+ break;
++ case 43222:
++ break;
+ default:
+ ssb_printk(KERN_ERR PFX
+ "ERROR: PLL init unknown for device %04X\n",
+@@ -434,6 +436,7 @@ static void ssb_pmu_resources_init(struc
+ min_msk = 0xCBB;
+ break;
+ case 0x4322:
++ case 43222:
+ /* We keep the default settings:
+ * min_msk = 0xCBB
+ * max_msk = 0x7FFFF
+@@ -615,6 +618,33 @@ void ssb_pmu_set_ldo_paref(struct ssb_ch
+ EXPORT_SYMBOL(ssb_pmu_set_ldo_voltage);
+ EXPORT_SYMBOL(ssb_pmu_set_ldo_paref);
+
++static u32 ssb_pmu_get_alp_clock_clk0(struct ssb_chipcommon *cc)
++{
++ u32 crystalfreq;
++ const struct pmu0_plltab_entry *e = NULL;
++
++ crystalfreq = chipco_read32(cc, SSB_CHIPCO_PMU_CTL) &
++ SSB_CHIPCO_PMU_CTL_XTALFREQ >> SSB_CHIPCO_PMU_CTL_XTALFREQ_SHIFT;
++ e = pmu0_plltab_find_entry(crystalfreq);
++ BUG_ON(!e);
++ return e->freq * 1000;
++}
++
++u32 ssb_pmu_get_alp_clock(struct ssb_chipcommon *cc)
++{
++ struct ssb_bus *bus = cc->dev->bus;
++
++ switch (bus->chip_id) {
++ case 0x5354:
++ ssb_pmu_get_alp_clock_clk0(cc);
++ default:
++ ssb_printk(KERN_ERR PFX
++ "ERROR: PMU alp clock unknown for device %04X\n",
++ bus->chip_id);
++ return 0;
++ }
++}
++
+ u32 ssb_pmu_get_cpu_clock(struct ssb_chipcommon *cc)
+ {
+ struct ssb_bus *bus = cc->dev->bus;
+@@ -645,3 +675,32 @@ u32 ssb_pmu_get_controlclock(struct ssb_
+ return 0;
+ }
+ }
++
++void ssb_pmu_spuravoid_pllupdate(struct ssb_chipcommon *cc, int spuravoid)
++{
++ u32 pmu_ctl = 0;
++
++ switch (cc->dev->bus->chip_id) {
++ case 0x4322:
++ ssb_chipco_pll_write(cc, SSB_PMU1_PLLCTL0, 0x11100070);
++ ssb_chipco_pll_write(cc, SSB_PMU1_PLLCTL1, 0x1014140a);
++ ssb_chipco_pll_write(cc, SSB_PMU1_PLLCTL5, 0x88888854);
++ if (spuravoid == 1)
++ ssb_chipco_pll_write(cc, SSB_PMU1_PLLCTL2, 0x05201828);
++ else
++ ssb_chipco_pll_write(cc, SSB_PMU1_PLLCTL2, 0x05001828);
++ pmu_ctl = SSB_CHIPCO_PMU_CTL_PLL_UPD;
++ break;
++ case 43222:
++ /* TODO: BCM43222 requires updating PLLs too */
++ return;
++ default:
++ ssb_printk(KERN_ERR PFX
++ "Unknown spuravoidance settings for chip 0x%04X, not changing PLL\n",
++ cc->dev->bus->chip_id);
++ return;
++ }
++
++ chipco_set32(cc, SSB_CHIPCO_PMU_CTL, pmu_ctl);
++}
++EXPORT_SYMBOL_GPL(ssb_pmu_spuravoid_pllupdate);
+--- /dev/null
++++ b/drivers/ssb/driver_chipcommon_sflash.c
+@@ -0,0 +1,18 @@
++/*
++ * Sonics Silicon Backplane
++ * ChipCommon serial flash interface
++ *
++ * Licensed under the GNU/GPL. See COPYING for details.
++ */
++
++#include <linux/ssb/ssb.h>
++
++#include "ssb_private.h"
++
++/* Initialize serial flash access */
++int ssb_sflash_init(struct ssb_chipcommon *cc)
++{
++ pr_err("Serial flash support is not implemented yet!\n");
++
++ return -ENOTSUPP;
++}
+--- a/drivers/ssb/driver_extif.c
++++ b/drivers/ssb/driver_extif.c
+@@ -112,10 +112,37 @@ void ssb_extif_get_clockcontrol(struct s
+ *m = extif_read32(extif, SSB_EXTIF_CLOCK_SB);
+ }
+
+-void ssb_extif_watchdog_timer_set(struct ssb_extif *extif,
+- u32 ticks)
++u32 ssb_extif_watchdog_timer_set_wdt(struct bcm47xx_wdt *wdt, u32 ticks)
+ {
++ struct ssb_extif *extif = bcm47xx_wdt_get_drvdata(wdt);
++
++ return ssb_extif_watchdog_timer_set(extif, ticks);
++}
++
++u32 ssb_extif_watchdog_timer_set_ms(struct bcm47xx_wdt *wdt, u32 ms)
++{
++ struct ssb_extif *extif = bcm47xx_wdt_get_drvdata(wdt);
++ u32 ticks = (SSB_EXTIF_WATCHDOG_CLK / 1000) * ms;
++
++ ticks = ssb_extif_watchdog_timer_set(extif, ticks);
++
++ return (ticks * 1000) / SSB_EXTIF_WATCHDOG_CLK;
++}
++
++u32 ssb_extif_watchdog_timer_set(struct ssb_extif *extif, u32 ticks)
++{
++ if (ticks > SSB_EXTIF_WATCHDOG_MAX_TIMER)
++ ticks = SSB_EXTIF_WATCHDOG_MAX_TIMER;
+ extif_write32(extif, SSB_EXTIF_WATCHDOG, ticks);
++
++ return ticks;
++}
++
++void ssb_extif_init(struct ssb_extif *extif)
++{
++ if (!extif->dev)
++ return; /* We don't have a Extif core */
++ spin_lock_init(&extif->gpio_lock);
+ }
+
+ u32 ssb_extif_gpio_in(struct ssb_extif *extif, u32 mask)
+@@ -125,22 +152,50 @@ u32 ssb_extif_gpio_in(struct ssb_extif *
+
+ u32 ssb_extif_gpio_out(struct ssb_extif *extif, u32 mask, u32 value)
+ {
+- return extif_write32_masked(extif, SSB_EXTIF_GPIO_OUT(0),
++ unsigned long flags;
++ u32 res = 0;
++
++ spin_lock_irqsave(&extif->gpio_lock, flags);
++ res = extif_write32_masked(extif, SSB_EXTIF_GPIO_OUT(0),
+ mask, value);
++ spin_unlock_irqrestore(&extif->gpio_lock, flags);
++
++ return res;
+ }
+
+ u32 ssb_extif_gpio_outen(struct ssb_extif *extif, u32 mask, u32 value)
+ {
+- return extif_write32_masked(extif, SSB_EXTIF_GPIO_OUTEN(0),
++ unsigned long flags;
++ u32 res = 0;
++
++ spin_lock_irqsave(&extif->gpio_lock, flags);
++ res = extif_write32_masked(extif, SSB_EXTIF_GPIO_OUTEN(0),
+ mask, value);
++ spin_unlock_irqrestore(&extif->gpio_lock, flags);
++
++ return res;
+ }
+
+ u32 ssb_extif_gpio_polarity(struct ssb_extif *extif, u32 mask, u32 value)
+ {
+- return extif_write32_masked(extif, SSB_EXTIF_GPIO_INTPOL, mask, value);
++ unsigned long flags;
++ u32 res = 0;
++
++ spin_lock_irqsave(&extif->gpio_lock, flags);
++ res = extif_write32_masked(extif, SSB_EXTIF_GPIO_INTPOL, mask, value);
++ spin_unlock_irqrestore(&extif->gpio_lock, flags);
++
++ return res;
+ }
+
+ u32 ssb_extif_gpio_intmask(struct ssb_extif *extif, u32 mask, u32 value)
+ {
+- return extif_write32_masked(extif, SSB_EXTIF_GPIO_INTMASK, mask, value);
++ unsigned long flags;
++ u32 res = 0;
++
++ spin_lock_irqsave(&extif->gpio_lock, flags);
++ res = extif_write32_masked(extif, SSB_EXTIF_GPIO_INTMASK, mask, value);
++ spin_unlock_irqrestore(&extif->gpio_lock, flags);
++
++ return res;
+ }
+--- /dev/null
++++ b/drivers/ssb/driver_gpio.c
+@@ -0,0 +1,176 @@
++/*
++ * Sonics Silicon Backplane
++ * GPIO driver
++ *
++ * Copyright 2011, Broadcom Corporation
++ * Copyright 2012, Hauke Mehrtens <hauke@hauke-m.de>
++ *
++ * Licensed under the GNU/GPL. See COPYING for details.
++ */
++
++#include <linux/gpio.h>
++#include <linux/export.h>
++#include <linux/ssb/ssb.h>
++
++#include "ssb_private.h"
++
++static struct ssb_bus *ssb_gpio_get_bus(struct gpio_chip *chip)
++{
++ return container_of(chip, struct ssb_bus, gpio);
++}
++
++static int ssb_gpio_chipco_get_value(struct gpio_chip *chip, unsigned gpio)
++{
++ struct ssb_bus *bus = ssb_gpio_get_bus(chip);
++
++ return !!ssb_chipco_gpio_in(&bus->chipco, 1 << gpio);
++}
++
++static void ssb_gpio_chipco_set_value(struct gpio_chip *chip, unsigned gpio,
++ int value)
++{
++ struct ssb_bus *bus = ssb_gpio_get_bus(chip);
++
++ ssb_chipco_gpio_out(&bus->chipco, 1 << gpio, value ? 1 << gpio : 0);
++}
++
++static int ssb_gpio_chipco_direction_input(struct gpio_chip *chip,
++ unsigned gpio)
++{
++ struct ssb_bus *bus = ssb_gpio_get_bus(chip);
++
++ ssb_chipco_gpio_outen(&bus->chipco, 1 << gpio, 0);
++ return 0;
++}
++
++static int ssb_gpio_chipco_direction_output(struct gpio_chip *chip,
++ unsigned gpio, int value)
++{
++ struct ssb_bus *bus = ssb_gpio_get_bus(chip);
++
++ ssb_chipco_gpio_outen(&bus->chipco, 1 << gpio, 1 << gpio);
++ ssb_chipco_gpio_out(&bus->chipco, 1 << gpio, value ? 1 << gpio : 0);
++ return 0;
++}
++
++static int ssb_gpio_chipco_request(struct gpio_chip *chip, unsigned gpio)
++{
++ struct ssb_bus *bus = ssb_gpio_get_bus(chip);
++
++ ssb_chipco_gpio_control(&bus->chipco, 1 << gpio, 0);
++ /* clear pulldown */
++ ssb_chipco_gpio_pulldown(&bus->chipco, 1 << gpio, 0);
++ /* Set pullup */
++ ssb_chipco_gpio_pullup(&bus->chipco, 1 << gpio, 1 << gpio);
++
++ return 0;
++}
++
++static void ssb_gpio_chipco_free(struct gpio_chip *chip, unsigned gpio)
++{
++ struct ssb_bus *bus = ssb_gpio_get_bus(chip);
++
++ /* clear pullup */
++ ssb_chipco_gpio_pullup(&bus->chipco, 1 << gpio, 0);
++}
++
++static int ssb_gpio_chipco_init(struct ssb_bus *bus)
++{
++ struct gpio_chip *chip = &bus->gpio;
++
++ chip->label = "ssb_chipco_gpio";
++ chip->owner = THIS_MODULE;
++ chip->request = ssb_gpio_chipco_request;
++ chip->free = ssb_gpio_chipco_free;
++ chip->get = ssb_gpio_chipco_get_value;
++ chip->set = ssb_gpio_chipco_set_value;
++ chip->direction_input = ssb_gpio_chipco_direction_input;
++ chip->direction_output = ssb_gpio_chipco_direction_output;
++ chip->ngpio = 16;
++ /* There is just one SoC in one device and its GPIO addresses should be
++ * deterministic to address them more easily. The other buses could get
++ * a random base number. */
++ if (bus->bustype == SSB_BUSTYPE_SSB)
++ chip->base = 0;
++ else
++ chip->base = -1;
++
++ return gpiochip_add(chip);
++}
++
++#ifdef CONFIG_SSB_DRIVER_EXTIF
++
++static int ssb_gpio_extif_get_value(struct gpio_chip *chip, unsigned gpio)
++{
++ struct ssb_bus *bus = ssb_gpio_get_bus(chip);
++
++ return !!ssb_extif_gpio_in(&bus->extif, 1 << gpio);
++}
++
++static void ssb_gpio_extif_set_value(struct gpio_chip *chip, unsigned gpio,
++ int value)
++{
++ struct ssb_bus *bus = ssb_gpio_get_bus(chip);
++
++ ssb_extif_gpio_out(&bus->extif, 1 << gpio, value ? 1 << gpio : 0);
++}
++
++static int ssb_gpio_extif_direction_input(struct gpio_chip *chip,
++ unsigned gpio)
++{
++ struct ssb_bus *bus = ssb_gpio_get_bus(chip);
++
++ ssb_extif_gpio_outen(&bus->extif, 1 << gpio, 0);
++ return 0;
++}
++
++static int ssb_gpio_extif_direction_output(struct gpio_chip *chip,
++ unsigned gpio, int value)
++{
++ struct ssb_bus *bus = ssb_gpio_get_bus(chip);
++
++ ssb_extif_gpio_outen(&bus->extif, 1 << gpio, 1 << gpio);
++ ssb_extif_gpio_out(&bus->extif, 1 << gpio, value ? 1 << gpio : 0);
++ return 0;
++}
++
++static int ssb_gpio_extif_init(struct ssb_bus *bus)
++{
++ struct gpio_chip *chip = &bus->gpio;
++
++ chip->label = "ssb_extif_gpio";
++ chip->owner = THIS_MODULE;
++ chip->get = ssb_gpio_extif_get_value;
++ chip->set = ssb_gpio_extif_set_value;
++ chip->direction_input = ssb_gpio_extif_direction_input;
++ chip->direction_output = ssb_gpio_extif_direction_output;
++ chip->ngpio = 5;
++ /* There is just one SoC in one device and its GPIO addresses should be
++ * deterministic to address them more easily. The other buses could get
++ * a random base number. */
++ if (bus->bustype == SSB_BUSTYPE_SSB)
++ chip->base = 0;
++ else
++ chip->base = -1;
++
++ return gpiochip_add(chip);
++}
++
++#else
++static int ssb_gpio_extif_init(struct ssb_bus *bus)
++{
++ return -ENOTSUPP;
++}
++#endif
++
++int ssb_gpio_init(struct ssb_bus *bus)
++{
++ if (ssb_chipco_available(&bus->chipco))
++ return ssb_gpio_chipco_init(bus);
++ else if (ssb_extif_available(&bus->extif))
++ return ssb_gpio_extif_init(bus);
++ else
++ SSB_WARN_ON(1);
++
++ return -1;
++}
+--- a/drivers/ssb/driver_mipscore.c
++++ b/drivers/ssb/driver_mipscore.c
+@@ -178,9 +178,9 @@ static void ssb_mips_serial_init(struct
+ {
+ struct ssb_bus *bus = mcore->dev->bus;
+
+- if (bus->extif.dev)
++ if (ssb_extif_available(&bus->extif))
+ mcore->nr_serial_ports = ssb_extif_serial_init(&bus->extif, mcore->serial_ports);
+- else if (bus->chipco.dev)
++ else if (ssb_chipco_available(&bus->chipco))
+ mcore->nr_serial_ports = ssb_chipco_serial_init(&bus->chipco, mcore->serial_ports);
+ else
+ mcore->nr_serial_ports = 0;
+@@ -191,10 +191,11 @@ static void ssb_mips_flash_detect(struct
+ struct ssb_bus *bus = mcore->dev->bus;
+
+ /* When there is no chipcommon on the bus there is 4MB flash */
+- if (!bus->chipco.dev) {
+- mcore->flash_buswidth = 2;
+- mcore->flash_window = SSB_FLASH1;
+- mcore->flash_window_size = SSB_FLASH1_SZ;
++ if (!ssb_chipco_available(&bus->chipco)) {
++ mcore->pflash.present = true;
++ mcore->pflash.buswidth = 2;
++ mcore->pflash.window = SSB_FLASH1;
++ mcore->pflash.window_size = SSB_FLASH1_SZ;
+ return;
+ }
+
+@@ -202,17 +203,19 @@ static void ssb_mips_flash_detect(struct
+ switch (bus->chipco.capabilities & SSB_CHIPCO_CAP_FLASHT) {
+ case SSB_CHIPCO_FLASHT_STSER:
+ case SSB_CHIPCO_FLASHT_ATSER:
+- pr_err("Serial flash not supported\n");
++ pr_debug("Found serial flash\n");
++ ssb_sflash_init(&bus->chipco);
+ break;
+ case SSB_CHIPCO_FLASHT_PARA:
+ pr_debug("Found parallel flash\n");
+- mcore->flash_window = SSB_FLASH2;
+- mcore->flash_window_size = SSB_FLASH2_SZ;
++ mcore->pflash.present = true;
++ mcore->pflash.window = SSB_FLASH2;
++ mcore->pflash.window_size = SSB_FLASH2_SZ;
+ if ((ssb_read32(bus->chipco.dev, SSB_CHIPCO_FLASH_CFG)
+ & SSB_CHIPCO_CFG_DS16) == 0)
+- mcore->flash_buswidth = 1;
++ mcore->pflash.buswidth = 1;
+ else
+- mcore->flash_buswidth = 2;
++ mcore->pflash.buswidth = 2;
+ break;
+ }
+ }
+@@ -225,9 +228,9 @@ u32 ssb_cpu_clock(struct ssb_mipscore *m
+ if (bus->chipco.capabilities & SSB_CHIPCO_CAP_PMU)
+ return ssb_pmu_get_cpu_clock(&bus->chipco);
+
+- if (bus->extif.dev) {
++ if (ssb_extif_available(&bus->extif)) {
+ ssb_extif_get_clockcontrol(&bus->extif, &pll_type, &n, &m);
+- } else if (bus->chipco.dev) {
++ } else if (ssb_chipco_available(&bus->chipco)) {
+ ssb_chipco_get_clockcpu(&bus->chipco, &pll_type, &n, &m);
+ } else
+ return 0;
+@@ -263,9 +266,9 @@ void ssb_mipscore_init(struct ssb_mipsco
+ hz = 100000000;
+ ns = 1000000000 / hz;
+
+- if (bus->extif.dev)
++ if (ssb_extif_available(&bus->extif))
+ ssb_extif_timing_init(&bus->extif, ns);
+- else if (bus->chipco.dev)
++ else if (ssb_chipco_available(&bus->chipco))
+ ssb_chipco_timing_init(&bus->chipco, ns);
+
+ /* Assign IRQs to all cores on the bus, start with irq line 2, because serial usually takes 1 */
+--- a/drivers/ssb/embedded.c
++++ b/drivers/ssb/embedded.c
+@@ -4,11 +4,13 @@
+ *
+ * Copyright 2005-2008, Broadcom Corporation
+ * Copyright 2006-2008, Michael Buesch <m@bues.ch>
++ * Copyright 2012, Hauke Mehrtens <hauke@hauke-m.de>
+ *
+ * Licensed under the GNU/GPL. See COPYING for details.
+ */
+
+ #include <linux/export.h>
++#include <linux/platform_device.h>
+ #include <linux/ssb/ssb.h>
+ #include <linux/ssb/ssb_embedded.h>
+ #include <linux/ssb/ssb_driver_pci.h>
+@@ -32,6 +34,39 @@ int ssb_watchdog_timer_set(struct ssb_bu
+ }
+ EXPORT_SYMBOL(ssb_watchdog_timer_set);
+
++int ssb_watchdog_register(struct ssb_bus *bus)
++{
++ struct bcm47xx_wdt wdt = {};
++ struct platform_device *pdev;
++
++ if (ssb_chipco_available(&bus->chipco)) {
++ wdt.driver_data = &bus->chipco;
++ wdt.timer_set = ssb_chipco_watchdog_timer_set_wdt;
++ wdt.timer_set_ms = ssb_chipco_watchdog_timer_set_ms;
++ wdt.max_timer_ms = bus->chipco.max_timer_ms;
++ } else if (ssb_extif_available(&bus->extif)) {
++ wdt.driver_data = &bus->extif;
++ wdt.timer_set = ssb_extif_watchdog_timer_set_wdt;
++ wdt.timer_set_ms = ssb_extif_watchdog_timer_set_ms;
++ wdt.max_timer_ms = SSB_EXTIF_WATCHDOG_MAX_TIMER_MS;
++ } else {
++ return -ENODEV;
++ }
++
++ pdev = platform_device_register_data(NULL, "bcm47xx-wdt",
++ bus->busnumber, &wdt,
++ sizeof(wdt));
++ if (IS_ERR(pdev)) {
++ ssb_dprintk(KERN_INFO PFX
++ "can not register watchdog device, err: %li\n",
++ PTR_ERR(pdev));
++ return PTR_ERR(pdev);
++ }
++
++ bus->watchdog = pdev;
++ return 0;
++}
++
+ u32 ssb_gpio_in(struct ssb_bus *bus, u32 mask)
+ {
+ unsigned long flags;
+--- a/drivers/ssb/main.c
++++ b/drivers/ssb/main.c
+@@ -13,6 +13,7 @@
+ #include <linux/delay.h>
+ #include <linux/io.h>
+ #include <linux/module.h>
++#include <linux/platform_device.h>
+ #include <linux/ssb/ssb.h>
+ #include <linux/ssb/ssb_regs.h>
+ #include <linux/ssb/ssb_driver_gige.h>
+@@ -433,6 +434,11 @@ static void ssb_devices_unregister(struc
+ if (sdev->dev)
+ device_unregister(sdev->dev);
+ }
++
++#ifdef CONFIG_SSB_EMBEDDED
++ if (bus->bustype == SSB_BUSTYPE_SSB)
++ platform_device_unregister(bus->watchdog);
++#endif
+ }
+
+ void ssb_bus_unregister(struct ssb_bus *bus)
+@@ -561,6 +567,8 @@ static int __devinit ssb_attach_queued_b
+ if (err)
+ goto error;
+ ssb_pcicore_init(&bus->pcicore);
++ if (bus->bustype == SSB_BUSTYPE_SSB)
++ ssb_watchdog_register(bus);
+ ssb_bus_may_powerdown(bus);
+
+ err = ssb_devices_register(bus);
+@@ -796,7 +804,14 @@ static int __devinit ssb_bus_register(st
+ if (err)
+ goto err_pcmcia_exit;
+ ssb_chipcommon_init(&bus->chipco);
++ ssb_extif_init(&bus->extif);
+ ssb_mipscore_init(&bus->mipscore);
++ err = ssb_gpio_init(bus);
++ if (err == -ENOTSUPP)
++ ssb_dprintk(KERN_DEBUG PFX "GPIO driver not activated\n");
++ else if (err)
++ ssb_dprintk(KERN_ERR PFX
++ "Error registering GPIO driver: %i\n", err);
+ err = ssb_fetch_invariants(bus, get_invariants);
+ if (err) {
+ ssb_bus_may_powerdown(bus);
+@@ -1118,8 +1133,7 @@ static u32 ssb_tmslow_reject_bitmask(str
+ case SSB_IDLOW_SSBREV_27: /* same here */
+ return SSB_TMSLOW_REJECT; /* this is a guess */
+ default:
+- printk(KERN_INFO "ssb: Backplane Revision 0x%.8X\n", rev);
+- WARN_ON(1);
++ WARN(1, KERN_INFO "ssb: Backplane Revision 0x%.8X\n", rev);
+ }
+ return (SSB_TMSLOW_REJECT | SSB_TMSLOW_REJECT_23);
+ }
+--- a/drivers/ssb/ssb_private.h
++++ b/drivers/ssb/ssb_private.h
+@@ -3,6 +3,7 @@
+
+ #include <linux/ssb/ssb.h>
+ #include <linux/types.h>
++#include <linux/bcm47xx_wdt.h>
+
+
+ #define PFX "ssb: "
+@@ -210,5 +211,63 @@ static inline void b43_pci_ssb_bridge_ex
+ /* driver_chipcommon_pmu.c */
+ extern u32 ssb_pmu_get_cpu_clock(struct ssb_chipcommon *cc);
+ extern u32 ssb_pmu_get_controlclock(struct ssb_chipcommon *cc);
++extern u32 ssb_pmu_get_alp_clock(struct ssb_chipcommon *cc);
++
++extern u32 ssb_chipco_watchdog_timer_set_wdt(struct bcm47xx_wdt *wdt,
++ u32 ticks);
++extern u32 ssb_chipco_watchdog_timer_set_ms(struct bcm47xx_wdt *wdt, u32 ms);
++
++/* driver_chipcommon_sflash.c */
++#ifdef CONFIG_SSB_SFLASH
++int ssb_sflash_init(struct ssb_chipcommon *cc);
++#else
++static inline int ssb_sflash_init(struct ssb_chipcommon *cc)
++{
++ pr_err("Serial flash not supported\n");
++ return 0;
++}
++#endif /* CONFIG_SSB_SFLASH */
++
++#ifdef CONFIG_SSB_DRIVER_EXTIF
++extern u32 ssb_extif_watchdog_timer_set_wdt(struct bcm47xx_wdt *wdt, u32 ticks);
++extern u32 ssb_extif_watchdog_timer_set_ms(struct bcm47xx_wdt *wdt, u32 ms);
++#else
++static inline u32 ssb_extif_watchdog_timer_set_wdt(struct bcm47xx_wdt *wdt,
++ u32 ticks)
++{
++ return 0;
++}
++static inline u32 ssb_extif_watchdog_timer_set_ms(struct bcm47xx_wdt *wdt,
++ u32 ms)
++{
++ return 0;
++}
++#endif
++
++#ifdef CONFIG_SSB_EMBEDDED
++extern int ssb_watchdog_register(struct ssb_bus *bus);
++#else /* CONFIG_SSB_EMBEDDED */
++static inline int ssb_watchdog_register(struct ssb_bus *bus)
++{
++ return 0;
++}
++#endif /* CONFIG_SSB_EMBEDDED */
++
++#ifdef CONFIG_SSB_DRIVER_EXTIF
++extern void ssb_extif_init(struct ssb_extif *extif);
++#else
++static inline void ssb_extif_init(struct ssb_extif *extif)
++{
++}
++#endif
++
++#ifdef CONFIG_SSB_DRIVER_GPIO
++extern int ssb_gpio_init(struct ssb_bus *bus);
++#else /* CONFIG_SSB_DRIVER_GPIO */
++static inline int ssb_gpio_init(struct ssb_bus *bus)
++{
++ return -ENOTSUPP;
++}
++#endif /* CONFIG_SSB_DRIVER_GPIO */
+
+ #endif /* LINUX_SSB_PRIVATE_H_ */
+--- a/include/linux/ssb/ssb.h
++++ b/include/linux/ssb/ssb.h
+@@ -6,8 +6,10 @@
+ #include <linux/types.h>
+ #include <linux/spinlock.h>
+ #include <linux/pci.h>
++#include <linux/gpio.h>
+ #include <linux/mod_devicetable.h>
+ #include <linux/dma-mapping.h>
++#include <linux/platform_device.h>
+
+ #include <linux/ssb/ssb_regs.h>
+
+@@ -432,7 +434,11 @@ struct ssb_bus {
+ #ifdef CONFIG_SSB_EMBEDDED
+ /* Lock for GPIO register access. */
+ spinlock_t gpio_lock;
++ struct platform_device *watchdog;
+ #endif /* EMBEDDED */
++#ifdef CONFIG_SSB_DRIVER_GPIO
++ struct gpio_chip gpio;
++#endif /* DRIVER_GPIO */
+
+ /* Internal-only stuff follows. Do not touch. */
+ struct list_head list;
+--- a/include/linux/ssb/ssb_driver_chipcommon.h
++++ b/include/linux/ssb/ssb_driver_chipcommon.h
+@@ -219,6 +219,7 @@
+ #define SSB_CHIPCO_PMU_CTL 0x0600 /* PMU control */
+ #define SSB_CHIPCO_PMU_CTL_ILP_DIV 0xFFFF0000 /* ILP div mask */
+ #define SSB_CHIPCO_PMU_CTL_ILP_DIV_SHIFT 16
++#define SSB_CHIPCO_PMU_CTL_PLL_UPD 0x00000400
+ #define SSB_CHIPCO_PMU_CTL_NOILPONW 0x00000200 /* No ILP on wait */
+ #define SSB_CHIPCO_PMU_CTL_HTREQEN 0x00000100 /* HT req enable */
+ #define SSB_CHIPCO_PMU_CTL_ALPREQEN 0x00000080 /* ALP req enable */
+@@ -590,7 +591,10 @@ struct ssb_chipcommon {
+ u32 status;
+ /* Fast Powerup Delay constant */
+ u16 fast_pwrup_delay;
++ spinlock_t gpio_lock;
+ struct ssb_chipcommon_pmu pmu;
++ u32 ticks_per_ms;
++ u32 max_timer_ms;
+ };
+
+ static inline bool ssb_chipco_available(struct ssb_chipcommon *cc)
+@@ -630,8 +634,7 @@ enum ssb_clkmode {
+ extern void ssb_chipco_set_clockmode(struct ssb_chipcommon *cc,
+ enum ssb_clkmode mode);
+
+-extern void ssb_chipco_watchdog_timer_set(struct ssb_chipcommon *cc,
+- u32 ticks);
++extern u32 ssb_chipco_watchdog_timer_set(struct ssb_chipcommon *cc, u32 ticks);
+
+ void ssb_chipco_irq_mask(struct ssb_chipcommon *cc, u32 mask, u32 value);
+
+@@ -644,6 +647,8 @@ u32 ssb_chipco_gpio_outen(struct ssb_chi
+ u32 ssb_chipco_gpio_control(struct ssb_chipcommon *cc, u32 mask, u32 value);
+ u32 ssb_chipco_gpio_intmask(struct ssb_chipcommon *cc, u32 mask, u32 value);
+ u32 ssb_chipco_gpio_polarity(struct ssb_chipcommon *cc, u32 mask, u32 value);
++u32 ssb_chipco_gpio_pullup(struct ssb_chipcommon *cc, u32 mask, u32 value);
++u32 ssb_chipco_gpio_pulldown(struct ssb_chipcommon *cc, u32 mask, u32 value);
+
+ #ifdef CONFIG_SSB_SERIAL
+ extern int ssb_chipco_serial_init(struct ssb_chipcommon *cc,
+@@ -663,5 +668,6 @@ enum ssb_pmu_ldo_volt_id {
+ void ssb_pmu_set_ldo_voltage(struct ssb_chipcommon *cc,
+ enum ssb_pmu_ldo_volt_id id, u32 voltage);
+ void ssb_pmu_set_ldo_paref(struct ssb_chipcommon *cc, bool on);
++void ssb_pmu_spuravoid_pllupdate(struct ssb_chipcommon *cc, int spuravoid);
+
+ #endif /* LINUX_SSB_CHIPCO_H_ */
+--- a/include/linux/ssb/ssb_driver_extif.h
++++ b/include/linux/ssb/ssb_driver_extif.h
+@@ -152,12 +152,16 @@
+ /* watchdog */
+ #define SSB_EXTIF_WATCHDOG_CLK 48000000 /* Hz */
+
++#define SSB_EXTIF_WATCHDOG_MAX_TIMER ((1 << 28) - 1)
++#define SSB_EXTIF_WATCHDOG_MAX_TIMER_MS (SSB_EXTIF_WATCHDOG_MAX_TIMER \
++ / (SSB_EXTIF_WATCHDOG_CLK / 1000))
+
+
+ #ifdef CONFIG_SSB_DRIVER_EXTIF
+
+ struct ssb_extif {
+ struct ssb_device *dev;
++ spinlock_t gpio_lock;
+ };
+
+ static inline bool ssb_extif_available(struct ssb_extif *extif)
+@@ -171,8 +175,7 @@ extern void ssb_extif_get_clockcontrol(s
+ extern void ssb_extif_timing_init(struct ssb_extif *extif,
+ unsigned long ns);
+
+-extern void ssb_extif_watchdog_timer_set(struct ssb_extif *extif,
+- u32 ticks);
++extern u32 ssb_extif_watchdog_timer_set(struct ssb_extif *extif, u32 ticks);
+
+ /* Extif GPIO pin access */
+ u32 ssb_extif_gpio_in(struct ssb_extif *extif, u32 mask);
+@@ -205,10 +208,52 @@ void ssb_extif_get_clockcontrol(struct s
+ }
+
+ static inline
+-void ssb_extif_watchdog_timer_set(struct ssb_extif *extif,
+- u32 ticks)
++void ssb_extif_timing_init(struct ssb_extif *extif, unsigned long ns)
+ {
+ }
+
++static inline
++u32 ssb_extif_watchdog_timer_set(struct ssb_extif *extif, u32 ticks)
++{
++ return 0;
++}
++
++static inline u32 ssb_extif_gpio_in(struct ssb_extif *extif, u32 mask)
++{
++ return 0;
++}
++
++static inline u32 ssb_extif_gpio_out(struct ssb_extif *extif, u32 mask,
++ u32 value)
++{
++ return 0;
++}
++
++static inline u32 ssb_extif_gpio_outen(struct ssb_extif *extif, u32 mask,
++ u32 value)
++{
++ return 0;
++}
++
++static inline u32 ssb_extif_gpio_polarity(struct ssb_extif *extif, u32 mask,
++ u32 value)
++{
++ return 0;
++}
++
++static inline u32 ssb_extif_gpio_intmask(struct ssb_extif *extif, u32 mask,
++ u32 value)
++{
++ return 0;
++}
++
++#ifdef CONFIG_SSB_SERIAL
++static inline int ssb_extif_serial_init(struct ssb_extif *extif,
++ struct ssb_serial_port *ports)
++{
++ return 0;
++}
++#endif /* CONFIG_SSB_SERIAL */
++
+ #endif /* CONFIG_SSB_DRIVER_EXTIF */
+ #endif /* LINUX_SSB_EXTIFCORE_H_ */
+--- a/include/linux/ssb/ssb_driver_mips.h
++++ b/include/linux/ssb/ssb_driver_mips.h
+@@ -13,6 +13,12 @@ struct ssb_serial_port {
+ unsigned int reg_shift;
+ };
+
++struct ssb_pflash {
++ bool present;
++ u8 buswidth;
++ u32 window;
++ u32 window_size;
++};
+
+ struct ssb_mipscore {
+ struct ssb_device *dev;
+@@ -20,9 +26,7 @@ struct ssb_mipscore {
+ int nr_serial_ports;
+ struct ssb_serial_port serial_ports[4];
+
+- u8 flash_buswidth;
+- u32 flash_window;
+- u32 flash_window_size;
++ struct ssb_pflash pflash;
+ };
+
+ extern void ssb_mipscore_init(struct ssb_mipscore *mcore);
+--- a/include/linux/ssb/ssb_regs.h
++++ b/include/linux/ssb/ssb_regs.h
+@@ -289,11 +289,11 @@
+ #define SSB_SPROM4_ETHPHY_ET1A_SHIFT 5
+ #define SSB_SPROM4_ETHPHY_ET0M (1<<14) /* MDIO for enet0 */
+ #define SSB_SPROM4_ETHPHY_ET1M (1<<15) /* MDIO for enet1 */
+-#define SSB_SPROM4_ANTAVAIL 0x005D /* Antenna available bitfields */
+-#define SSB_SPROM4_ANTAVAIL_A 0x00FF /* A-PHY bitfield */
+-#define SSB_SPROM4_ANTAVAIL_A_SHIFT 0
+-#define SSB_SPROM4_ANTAVAIL_BG 0xFF00 /* B-PHY and G-PHY bitfield */
+-#define SSB_SPROM4_ANTAVAIL_BG_SHIFT 8
++#define SSB_SPROM4_ANTAVAIL 0x005C /* Antenna available bitfields */
++#define SSB_SPROM4_ANTAVAIL_BG 0x00FF /* B-PHY and G-PHY bitfield */
++#define SSB_SPROM4_ANTAVAIL_BG_SHIFT 0
++#define SSB_SPROM4_ANTAVAIL_A 0xFF00 /* A-PHY bitfield */
++#define SSB_SPROM4_ANTAVAIL_A_SHIFT 8
+ #define SSB_SPROM4_AGAIN01 0x005E /* Antenna Gain (in dBm Q5.2) */
+ #define SSB_SPROM4_AGAIN0 0x00FF /* Antenna 0 */
+ #define SSB_SPROM4_AGAIN0_SHIFT 0
+@@ -485,7 +485,7 @@
+ #define SSB_SPROM8_HWIQ_IQSWP_IQCAL_SWP_SHIFT 4
+ #define SSB_SPROM8_HWIQ_IQSWP_HW_IQCAL 0x0020
+ #define SSB_SPROM8_HWIQ_IQSWP_HW_IQCAL_SHIFT 5
+-#define SSB_SPROM8_TEMPDELTA 0x00BA
++#define SSB_SPROM8_TEMPDELTA 0x00BC
+ #define SSB_SPROM8_TEMPDELTA_PHYCAL 0x00ff
+ #define SSB_SPROM8_TEMPDELTA_PHYCAL_SHIFT 0
+ #define SSB_SPROM8_TEMPDELTA_PERIOD 0x0f00
+--- /dev/null
++++ b/include/linux/bcm47xx_wdt.h
+@@ -0,0 +1,19 @@
++#ifndef LINUX_BCM47XX_WDT_H_
++#define LINUX_BCM47XX_WDT_H_
++
++#include <linux/types.h>
++
++
++struct bcm47xx_wdt {
++ u32 (*timer_set)(struct bcm47xx_wdt *, u32);
++ u32 (*timer_set_ms)(struct bcm47xx_wdt *, u32);
++ u32 max_timer_ms;
++
++ void *driver_data;
++};
++
++static inline void *bcm47xx_wdt_get_drvdata(struct bcm47xx_wdt *wdt)
++{
++ return wdt->driver_data;
++}
++#endif /* LINUX_BCM47XX_WDT_H_ */
+--- a/drivers/net/wireless/b43/phy_n.c
++++ b/drivers/net/wireless/b43/phy_n.c
+@@ -5165,7 +5165,8 @@ static void b43_nphy_pmu_spur_avoid(stru
+ #endif
+ #ifdef CONFIG_B43_SSB
+ case B43_BUS_SSB:
+- /* FIXME */
++ ssb_pmu_spuravoid_pllupdate(&dev->dev->sdev->bus->chipco,
++ avoid);
+ break;
+ #endif
+ }
+--- a/drivers/ssb/pci.c
++++ b/drivers/ssb/pci.c
+@@ -339,6 +339,21 @@ static s8 r123_extract_antgain(u8 sprom_
+ return (s8)gain;
+ }
+
++static void sprom_extract_r23(struct ssb_sprom *out, const u16 *in)
++{
++ SPEX(boardflags_hi, SSB_SPROM2_BFLHI, 0xFFFF, 0);
++ SPEX(opo, SSB_SPROM2_OPO, SSB_SPROM2_OPO_VALUE, 0);
++ SPEX(pa1lob0, SSB_SPROM2_PA1LOB0, 0xFFFF, 0);
++ SPEX(pa1lob1, SSB_SPROM2_PA1LOB1, 0xFFFF, 0);
++ SPEX(pa1lob2, SSB_SPROM2_PA1LOB2, 0xFFFF, 0);
++ SPEX(pa1hib0, SSB_SPROM2_PA1HIB0, 0xFFFF, 0);
++ SPEX(pa1hib1, SSB_SPROM2_PA1HIB1, 0xFFFF, 0);
++ SPEX(pa1hib2, SSB_SPROM2_PA1HIB2, 0xFFFF, 0);
++ SPEX(maxpwr_ah, SSB_SPROM2_MAXP_A, SSB_SPROM2_MAXP_A_HI, 0);
++ SPEX(maxpwr_al, SSB_SPROM2_MAXP_A, SSB_SPROM2_MAXP_A_LO,
++ SSB_SPROM2_MAXP_A_LO_SHIFT);
++}
++
+ static void sprom_extract_r123(struct ssb_sprom *out, const u16 *in)
+ {
+ int i;
+@@ -398,8 +413,7 @@ static void sprom_extract_r123(struct ss
+ SSB_SPROM1_ITSSI_A_SHIFT);
+ SPEX(itssi_bg, SSB_SPROM1_ITSSI, SSB_SPROM1_ITSSI_BG, 0);
+ SPEX(boardflags_lo, SSB_SPROM1_BFLLO, 0xFFFF, 0);
+- if (out->revision >= 2)
+- SPEX(boardflags_hi, SSB_SPROM2_BFLHI, 0xFFFF, 0);
++
+ SPEX(alpha2[0], SSB_SPROM1_CCODE, 0xff00, 8);
+ SPEX(alpha2[1], SSB_SPROM1_CCODE, 0x00ff, 0);
+
+@@ -410,6 +424,8 @@ static void sprom_extract_r123(struct ss
+ out->antenna_gain.a1 = r123_extract_antgain(out->revision, in,
+ SSB_SPROM1_AGAIN_A,
+ SSB_SPROM1_AGAIN_A_SHIFT);
++ if (out->revision >= 2)
++ sprom_extract_r23(out, in);
+ }
+
+ /* Revs 4 5 and 8 have partially shared layout */
diff --git a/target/linux/generic/patches-3.7/021-ssb-add-PCI-ID-0x4350.patch b/target/linux/generic/patches-3.7/021-ssb-add-PCI-ID-0x4350.patch
deleted file mode 100644
index e0be83980..000000000
--- a/target/linux/generic/patches-3.7/021-ssb-add-PCI-ID-0x4350.patch
+++ /dev/null
@@ -1,10 +0,0 @@
---- a/drivers/ssb/b43_pci_bridge.c
-+++ b/drivers/ssb/b43_pci_bridge.c
-@@ -37,6 +37,7 @@ static const struct pci_device_id b43_pc
- { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4329) },
- { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x432b) },
- { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x432c) },
-+ { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4350) },
- { 0, },
- };
- MODULE_DEVICE_TABLE(pci, b43_pci_bridge_tbl);
diff --git a/target/linux/generic/patches-3.7/022-ssb-handle-BCM43222-in-pmu-code.patch b/target/linux/generic/patches-3.7/022-ssb-handle-BCM43222-in-pmu-code.patch
deleted file mode 100644
index fe7a5120a..000000000
--- a/target/linux/generic/patches-3.7/022-ssb-handle-BCM43222-in-pmu-code.patch
+++ /dev/null
@@ -1,19 +0,0 @@
---- a/drivers/ssb/driver_chipcommon_pmu.c
-+++ b/drivers/ssb/driver_chipcommon_pmu.c
-@@ -346,6 +346,8 @@ static void ssb_pmu_pll_init(struct ssb_
- chipco_write32(cc, SSB_CHIPCO_PLLCTL_DATA, 0x380005C0);
- }
- break;
-+ case 43222:
-+ break;
- default:
- ssb_printk(KERN_ERR PFX
- "ERROR: PLL init unknown for device %04X\n",
-@@ -434,6 +436,7 @@ static void ssb_pmu_resources_init(struc
- min_msk = 0xCBB;
- break;
- case 0x4322:
-+ case 43222:
- /* We keep the default settings:
- * min_msk = 0xCBB
- * max_msk = 0x7FFFF
diff --git a/target/linux/generic/patches-3.7/025-bcma_backport.patch b/target/linux/generic/patches-3.7/025-bcma_backport.patch
new file mode 100644
index 000000000..3cba3ca85
--- /dev/null
+++ b/target/linux/generic/patches-3.7/025-bcma_backport.patch
@@ -0,0 +1,1518 @@
+--- a/drivers/bcma/Kconfig
++++ b/drivers/bcma/Kconfig
+@@ -65,6 +65,14 @@ config BCMA_DRIVER_GMAC_CMN
+
+ If unsure, say N
+
++config BCMA_DRIVER_GPIO
++ bool "BCMA GPIO driver"
++ depends on BCMA && GPIOLIB
++ help
++ Driver to provide access to the GPIO pins of the bcma bus.
++
++ If unsure, say N
++
+ config BCMA_DEBUG
+ bool "BCMA debugging"
+ depends on BCMA
+--- a/drivers/bcma/Makefile
++++ b/drivers/bcma/Makefile
+@@ -6,6 +6,7 @@ bcma-y += driver_pci.o
+ bcma-$(CONFIG_BCMA_DRIVER_PCI_HOSTMODE) += driver_pci_host.o
+ bcma-$(CONFIG_BCMA_DRIVER_MIPS) += driver_mips.o
+ bcma-$(CONFIG_BCMA_DRIVER_GMAC_CMN) += driver_gmac_cmn.o
++bcma-$(CONFIG_BCMA_DRIVER_GPIO) += driver_gpio.o
+ bcma-$(CONFIG_BCMA_HOST_PCI) += host_pci.o
+ bcma-$(CONFIG_BCMA_HOST_SOC) += host_soc.o
+ obj-$(CONFIG_BCMA) += bcma.o
+--- a/drivers/bcma/bcma_private.h
++++ b/drivers/bcma/bcma_private.h
+@@ -31,6 +31,8 @@ int __init bcma_bus_early_register(struc
+ int bcma_bus_suspend(struct bcma_bus *bus);
+ int bcma_bus_resume(struct bcma_bus *bus);
+ #endif
++struct bcma_device *bcma_find_core_unit(struct bcma_bus *bus, u16 coreid,
++ u8 unit);
+
+ /* scan.c */
+ int bcma_bus_scan(struct bcma_bus *bus);
+@@ -48,8 +50,8 @@ void bcma_chipco_serial_init(struct bcma
+ #endif /* CONFIG_BCMA_DRIVER_MIPS */
+
+ /* driver_chipcommon_pmu.c */
+-u32 bcma_pmu_alp_clock(struct bcma_drv_cc *cc);
+-u32 bcma_pmu_get_clockcpu(struct bcma_drv_cc *cc);
++u32 bcma_pmu_get_alp_clock(struct bcma_drv_cc *cc);
++u32 bcma_pmu_get_cpu_clock(struct bcma_drv_cc *cc);
+
+ #ifdef CONFIG_BCMA_SFLASH
+ /* driver_chipcommon_sflash.c */
+@@ -84,9 +86,21 @@ extern void __exit bcma_host_pci_exit(vo
+ /* driver_pci.c */
+ u32 bcma_pcie_read(struct bcma_drv_pci *pc, u32 address);
+
++extern int bcma_chipco_watchdog_register(struct bcma_drv_cc *cc);
++
+ #ifdef CONFIG_BCMA_DRIVER_PCI_HOSTMODE
+ bool __devinit bcma_core_pci_is_in_hostmode(struct bcma_drv_pci *pc);
+ void __devinit bcma_core_pci_hostmode_init(struct bcma_drv_pci *pc);
+ #endif /* CONFIG_BCMA_DRIVER_PCI_HOSTMODE */
+
++#ifdef CONFIG_BCMA_DRIVER_GPIO
++/* driver_gpio.c */
++int bcma_gpio_init(struct bcma_drv_cc *cc);
++#else
++static inline int bcma_gpio_init(struct bcma_drv_cc *cc)
++{
++ return -ENOTSUPP;
++}
++#endif /* CONFIG_BCMA_DRIVER_GPIO */
++
+ #endif
+--- a/drivers/bcma/driver_chipcommon.c
++++ b/drivers/bcma/driver_chipcommon.c
+@@ -4,12 +4,15 @@
+ *
+ * Copyright 2005, Broadcom Corporation
+ * Copyright 2006, 2007, Michael Buesch <m@bues.ch>
++ * Copyright 2012, Hauke Mehrtens <hauke@hauke-m.de>
+ *
+ * Licensed under the GNU/GPL. See COPYING for details.
+ */
+
+ #include "bcma_private.h"
++#include <linux/bcm47xx_wdt.h>
+ #include <linux/export.h>
++#include <linux/platform_device.h>
+ #include <linux/bcma/bcma.h>
+
+ static inline u32 bcma_cc_write32_masked(struct bcma_drv_cc *cc, u16 offset,
+@@ -22,20 +25,120 @@ static inline u32 bcma_cc_write32_masked
+ return value;
+ }
+
+-void bcma_core_chipcommon_init(struct bcma_drv_cc *cc)
++u32 bcma_chipco_get_alp_clock(struct bcma_drv_cc *cc)
+ {
+- u32 leddc_on = 10;
+- u32 leddc_off = 90;
++ if (cc->capabilities & BCMA_CC_CAP_PMU)
++ return bcma_pmu_get_alp_clock(cc);
+
+- if (cc->setup_done)
++ return 20000000;
++}
++EXPORT_SYMBOL_GPL(bcma_chipco_get_alp_clock);
++
++static u32 bcma_chipco_watchdog_get_max_timer(struct bcma_drv_cc *cc)
++{
++ struct bcma_bus *bus = cc->core->bus;
++ u32 nb;
++
++ if (cc->capabilities & BCMA_CC_CAP_PMU) {
++ if (bus->chipinfo.id == BCMA_CHIP_ID_BCM4706)
++ nb = 32;
++ else if (cc->core->id.rev < 26)
++ nb = 16;
++ else
++ nb = (cc->core->id.rev >= 37) ? 32 : 24;
++ } else {
++ nb = 28;
++ }
++ if (nb == 32)
++ return 0xffffffff;
++ else
++ return (1 << nb) - 1;
++}
++
++static u32 bcma_chipco_watchdog_timer_set_wdt(struct bcm47xx_wdt *wdt,
++ u32 ticks)
++{
++ struct bcma_drv_cc *cc = bcm47xx_wdt_get_drvdata(wdt);
++
++ return bcma_chipco_watchdog_timer_set(cc, ticks);
++}
++
++static u32 bcma_chipco_watchdog_timer_set_ms_wdt(struct bcm47xx_wdt *wdt,
++ u32 ms)
++{
++ struct bcma_drv_cc *cc = bcm47xx_wdt_get_drvdata(wdt);
++ u32 ticks;
++
++ ticks = bcma_chipco_watchdog_timer_set(cc, cc->ticks_per_ms * ms);
++ return ticks / cc->ticks_per_ms;
++}
++
++static int bcma_chipco_watchdog_ticks_per_ms(struct bcma_drv_cc *cc)
++{
++ struct bcma_bus *bus = cc->core->bus;
++
++ if (cc->capabilities & BCMA_CC_CAP_PMU) {
++ if (bus->chipinfo.id == BCMA_CHIP_ID_BCM4706)
++ /* 4706 CC and PMU watchdogs are clocked at 1/4 of ALP clock */
++ return bcma_chipco_get_alp_clock(cc) / 4000;
++ else
++ /* based on 32KHz ILP clock */
++ return 32;
++ } else {
++ return bcma_chipco_get_alp_clock(cc) / 1000;
++ }
++}
++
++int bcma_chipco_watchdog_register(struct bcma_drv_cc *cc)
++{
++ struct bcm47xx_wdt wdt = {};
++ struct platform_device *pdev;
++
++ wdt.driver_data = cc;
++ wdt.timer_set = bcma_chipco_watchdog_timer_set_wdt;
++ wdt.timer_set_ms = bcma_chipco_watchdog_timer_set_ms_wdt;
++ wdt.max_timer_ms = bcma_chipco_watchdog_get_max_timer(cc) / cc->ticks_per_ms;
++
++ pdev = platform_device_register_data(NULL, "bcm47xx-wdt",
++ cc->core->bus->num, &wdt,
++ sizeof(wdt));
++ if (IS_ERR(pdev))
++ return PTR_ERR(pdev);
++
++ cc->watchdog = pdev;
++
++ return 0;
++}
++
++void bcma_core_chipcommon_early_init(struct bcma_drv_cc *cc)
++{
++ if (cc->early_setup_done)
+ return;
+
++ spin_lock_init(&cc->gpio_lock);
++
+ if (cc->core->id.rev >= 11)
+ cc->status = bcma_cc_read32(cc, BCMA_CC_CHIPSTAT);
+ cc->capabilities = bcma_cc_read32(cc, BCMA_CC_CAP);
+ if (cc->core->id.rev >= 35)
+ cc->capabilities_ext = bcma_cc_read32(cc, BCMA_CC_CAP_EXT);
+
++ if (cc->capabilities & BCMA_CC_CAP_PMU)
++ bcma_pmu_early_init(cc);
++
++ cc->early_setup_done = true;
++}
++
++void bcma_core_chipcommon_init(struct bcma_drv_cc *cc)
++{
++ u32 leddc_on = 10;
++ u32 leddc_off = 90;
++
++ if (cc->setup_done)
++ return;
++
++ bcma_core_chipcommon_early_init(cc);
++
+ if (cc->core->id.rev >= 20) {
+ bcma_cc_write32(cc, BCMA_CC_GPIOPULLUP, 0);
+ bcma_cc_write32(cc, BCMA_CC_GPIOPULLDOWN, 0);
+@@ -56,15 +159,33 @@ void bcma_core_chipcommon_init(struct bc
+ ((leddc_on << BCMA_CC_GPIOTIMER_ONTIME_SHIFT) |
+ (leddc_off << BCMA_CC_GPIOTIMER_OFFTIME_SHIFT)));
+ }
++ cc->ticks_per_ms = bcma_chipco_watchdog_ticks_per_ms(cc);
+
+ cc->setup_done = true;
+ }
+
+ /* Set chip watchdog reset timer to fire in 'ticks' backplane cycles */
+-void bcma_chipco_watchdog_timer_set(struct bcma_drv_cc *cc, u32 ticks)
++u32 bcma_chipco_watchdog_timer_set(struct bcma_drv_cc *cc, u32 ticks)
+ {
+- /* instant NMI */
+- bcma_cc_write32(cc, BCMA_CC_WATCHDOG, ticks);
++ u32 maxt;
++ enum bcma_clkmode clkmode;
++
++ maxt = bcma_chipco_watchdog_get_max_timer(cc);
++ if (cc->capabilities & BCMA_CC_CAP_PMU) {
++ if (ticks == 1)
++ ticks = 2;
++ else if (ticks > maxt)
++ ticks = maxt;
++ bcma_cc_write32(cc, BCMA_CC_PMU_WATCHDOG, ticks);
++ } else {
++ clkmode = ticks ? BCMA_CLKMODE_FAST : BCMA_CLKMODE_DYNAMIC;
++ bcma_core_set_clockmode(cc->core, clkmode);
++ if (ticks > maxt)
++ ticks = maxt;
++ /* instant NMI */
++ bcma_cc_write32(cc, BCMA_CC_WATCHDOG, ticks);
++ }
++ return ticks;
+ }
+
+ void bcma_chipco_irq_mask(struct bcma_drv_cc *cc, u32 mask, u32 value)
+@@ -84,28 +205,99 @@ u32 bcma_chipco_gpio_in(struct bcma_drv_
+
+ u32 bcma_chipco_gpio_out(struct bcma_drv_cc *cc, u32 mask, u32 value)
+ {
+- return bcma_cc_write32_masked(cc, BCMA_CC_GPIOOUT, mask, value);
++ unsigned long flags;
++ u32 res;
++
++ spin_lock_irqsave(&cc->gpio_lock, flags);
++ res = bcma_cc_write32_masked(cc, BCMA_CC_GPIOOUT, mask, value);
++ spin_unlock_irqrestore(&cc->gpio_lock, flags);
++
++ return res;
+ }
++EXPORT_SYMBOL_GPL(bcma_chipco_gpio_out);
+
+ u32 bcma_chipco_gpio_outen(struct bcma_drv_cc *cc, u32 mask, u32 value)
+ {
+- return bcma_cc_write32_masked(cc, BCMA_CC_GPIOOUTEN, mask, value);
++ unsigned long flags;
++ u32 res;
++
++ spin_lock_irqsave(&cc->gpio_lock, flags);
++ res = bcma_cc_write32_masked(cc, BCMA_CC_GPIOOUTEN, mask, value);
++ spin_unlock_irqrestore(&cc->gpio_lock, flags);
++
++ return res;
+ }
++EXPORT_SYMBOL_GPL(bcma_chipco_gpio_outen);
+
++/*
++ * If the bit is set to 0, chipcommon controlls this GPIO,
++ * if the bit is set to 1, it is used by some part of the chip and not our code.
++ */
+ u32 bcma_chipco_gpio_control(struct bcma_drv_cc *cc, u32 mask, u32 value)
+ {
+- return bcma_cc_write32_masked(cc, BCMA_CC_GPIOCTL, mask, value);
++ unsigned long flags;
++ u32 res;
++
++ spin_lock_irqsave(&cc->gpio_lock, flags);
++ res = bcma_cc_write32_masked(cc, BCMA_CC_GPIOCTL, mask, value);
++ spin_unlock_irqrestore(&cc->gpio_lock, flags);
++
++ return res;
+ }
+ EXPORT_SYMBOL_GPL(bcma_chipco_gpio_control);
+
+ u32 bcma_chipco_gpio_intmask(struct bcma_drv_cc *cc, u32 mask, u32 value)
+ {
+- return bcma_cc_write32_masked(cc, BCMA_CC_GPIOIRQ, mask, value);
++ unsigned long flags;
++ u32 res;
++
++ spin_lock_irqsave(&cc->gpio_lock, flags);
++ res = bcma_cc_write32_masked(cc, BCMA_CC_GPIOIRQ, mask, value);
++ spin_unlock_irqrestore(&cc->gpio_lock, flags);
++
++ return res;
+ }
+
+ u32 bcma_chipco_gpio_polarity(struct bcma_drv_cc *cc, u32 mask, u32 value)
+ {
+- return bcma_cc_write32_masked(cc, BCMA_CC_GPIOPOL, mask, value);
++ unsigned long flags;
++ u32 res;
++
++ spin_lock_irqsave(&cc->gpio_lock, flags);
++ res = bcma_cc_write32_masked(cc, BCMA_CC_GPIOPOL, mask, value);
++ spin_unlock_irqrestore(&cc->gpio_lock, flags);
++
++ return res;
++}
++
++u32 bcma_chipco_gpio_pullup(struct bcma_drv_cc *cc, u32 mask, u32 value)
++{
++ unsigned long flags;
++ u32 res;
++
++ if (cc->core->id.rev < 20)
++ return 0;
++
++ spin_lock_irqsave(&cc->gpio_lock, flags);
++ res = bcma_cc_write32_masked(cc, BCMA_CC_GPIOPULLUP, mask, value);
++ spin_unlock_irqrestore(&cc->gpio_lock, flags);
++
++ return res;
++}
++
++u32 bcma_chipco_gpio_pulldown(struct bcma_drv_cc *cc, u32 mask, u32 value)
++{
++ unsigned long flags;
++ u32 res;
++
++ if (cc->core->id.rev < 20)
++ return 0;
++
++ spin_lock_irqsave(&cc->gpio_lock, flags);
++ res = bcma_cc_write32_masked(cc, BCMA_CC_GPIOPULLDOWN, mask, value);
++ spin_unlock_irqrestore(&cc->gpio_lock, flags);
++
++ return res;
+ }
+
+ #ifdef CONFIG_BCMA_DRIVER_MIPS
+@@ -118,8 +310,7 @@ void bcma_chipco_serial_init(struct bcma
+ struct bcma_serial_port *ports = cc->serial_ports;
+
+ if (ccrev >= 11 && ccrev != 15) {
+- /* Fixed ALP clock */
+- baud_base = bcma_pmu_alp_clock(cc);
++ baud_base = bcma_chipco_get_alp_clock(cc);
+ if (ccrev >= 21) {
+ /* Turn off UART clock before switching clocksource. */
+ bcma_cc_write32(cc, BCMA_CC_CORECTL,
+--- a/drivers/bcma/driver_chipcommon_nflash.c
++++ b/drivers/bcma/driver_chipcommon_nflash.c
+@@ -32,6 +32,9 @@ int bcma_nflash_init(struct bcma_drv_cc
+ }
+
+ cc->nflash.present = true;
++ if (cc->core->id.rev == 38 &&
++ (cc->status & BCMA_CC_CHIPST_5357_NAND_BOOT))
++ cc->nflash.boot = true;
+
+ /* Prepare platform device, but don't register it yet. It's too early,
+ * malloc (required by device_private_init) is not available yet. */
+--- a/drivers/bcma/driver_chipcommon_pmu.c
++++ b/drivers/bcma/driver_chipcommon_pmu.c
+@@ -13,12 +13,13 @@
+ #include <linux/export.h>
+ #include <linux/bcma/bcma.h>
+
+-static u32 bcma_chipco_pll_read(struct bcma_drv_cc *cc, u32 offset)
++u32 bcma_chipco_pll_read(struct bcma_drv_cc *cc, u32 offset)
+ {
+ bcma_cc_write32(cc, BCMA_CC_PLLCTL_ADDR, offset);
+ bcma_cc_read32(cc, BCMA_CC_PLLCTL_ADDR);
+ return bcma_cc_read32(cc, BCMA_CC_PLLCTL_DATA);
+ }
++EXPORT_SYMBOL_GPL(bcma_chipco_pll_read);
+
+ void bcma_chipco_pll_write(struct bcma_drv_cc *cc, u32 offset, u32 value)
+ {
+@@ -144,7 +145,7 @@ static void bcma_pmu_workarounds(struct
+ }
+ }
+
+-void bcma_pmu_init(struct bcma_drv_cc *cc)
++void bcma_pmu_early_init(struct bcma_drv_cc *cc)
+ {
+ u32 pmucap;
+
+@@ -153,7 +154,10 @@ void bcma_pmu_init(struct bcma_drv_cc *c
+
+ bcma_debug(cc->core->bus, "Found rev %u PMU (capabilities 0x%08X)\n",
+ cc->pmu.rev, pmucap);
++}
+
++void bcma_pmu_init(struct bcma_drv_cc *cc)
++{
+ if (cc->pmu.rev == 1)
+ bcma_cc_mask32(cc, BCMA_CC_PMU_CTL,
+ ~BCMA_CC_PMU_CTL_NOILPONW);
+@@ -165,24 +169,40 @@ void bcma_pmu_init(struct bcma_drv_cc *c
+ bcma_pmu_workarounds(cc);
+ }
+
+-u32 bcma_pmu_alp_clock(struct bcma_drv_cc *cc)
++u32 bcma_pmu_get_alp_clock(struct bcma_drv_cc *cc)
+ {
+ struct bcma_bus *bus = cc->core->bus;
+
+ switch (bus->chipinfo.id) {
++ case BCMA_CHIP_ID_BCM4313:
++ case BCMA_CHIP_ID_BCM43224:
++ case BCMA_CHIP_ID_BCM43225:
++ case BCMA_CHIP_ID_BCM43227:
++ case BCMA_CHIP_ID_BCM43228:
++ case BCMA_CHIP_ID_BCM4331:
++ case BCMA_CHIP_ID_BCM43421:
++ case BCMA_CHIP_ID_BCM43428:
++ case BCMA_CHIP_ID_BCM43431:
+ case BCMA_CHIP_ID_BCM4716:
+- case BCMA_CHIP_ID_BCM4748:
+ case BCMA_CHIP_ID_BCM47162:
+- case BCMA_CHIP_ID_BCM4313:
+- case BCMA_CHIP_ID_BCM5357:
++ case BCMA_CHIP_ID_BCM4748:
+ case BCMA_CHIP_ID_BCM4749:
++ case BCMA_CHIP_ID_BCM5357:
+ case BCMA_CHIP_ID_BCM53572:
++ case BCMA_CHIP_ID_BCM6362:
+ /* always 20Mhz */
+ return 20000 * 1000;
+- case BCMA_CHIP_ID_BCM5356:
+ case BCMA_CHIP_ID_BCM4706:
++ case BCMA_CHIP_ID_BCM5356:
+ /* always 25Mhz */
+ return 25000 * 1000;
++ case BCMA_CHIP_ID_BCM43460:
++ case BCMA_CHIP_ID_BCM4352:
++ case BCMA_CHIP_ID_BCM4360:
++ if (cc->status & BCMA_CC_CHIPST_4360_XTAL_40MZ)
++ return 40000 * 1000;
++ else
++ return 20000 * 1000;
+ default:
+ bcma_warn(bus, "No ALP clock specified for %04X device, pmu rev. %d, using default %d Hz\n",
+ bus->chipinfo.id, cc->pmu.rev, BCMA_CC_PMU_ALP_CLOCK);
+@@ -193,7 +213,7 @@ u32 bcma_pmu_alp_clock(struct bcma_drv_c
+ /* Find the output of the "m" pll divider given pll controls that start with
+ * pllreg "pll0" i.e. 12 for main 6 for phy, 0 for misc.
+ */
+-static u32 bcma_pmu_clock(struct bcma_drv_cc *cc, u32 pll0, u32 m)
++static u32 bcma_pmu_pll_clock(struct bcma_drv_cc *cc, u32 pll0, u32 m)
+ {
+ u32 tmp, div, ndiv, p1, p2, fc;
+ struct bcma_bus *bus = cc->core->bus;
+@@ -222,14 +242,14 @@ static u32 bcma_pmu_clock(struct bcma_dr
+ ndiv = (tmp & BCMA_CC_PPL_NDIV_MASK) >> BCMA_CC_PPL_NDIV_SHIFT;
+
+ /* Do calculation in Mhz */
+- fc = bcma_pmu_alp_clock(cc) / 1000000;
++ fc = bcma_pmu_get_alp_clock(cc) / 1000000;
+ fc = (p1 * ndiv * fc) / p2;
+
+ /* Return clock in Hertz */
+ return (fc / div) * 1000000;
+ }
+
+-static u32 bcma_pmu_clock_bcm4706(struct bcma_drv_cc *cc, u32 pll0, u32 m)
++static u32 bcma_pmu_pll_clock_bcm4706(struct bcma_drv_cc *cc, u32 pll0, u32 m)
+ {
+ u32 tmp, ndiv, p1div, p2div;
+ u32 clock;
+@@ -260,7 +280,7 @@ static u32 bcma_pmu_clock_bcm4706(struct
+ }
+
+ /* query bus clock frequency for PMU-enabled chipcommon */
+-static u32 bcma_pmu_get_clockcontrol(struct bcma_drv_cc *cc)
++static u32 bcma_pmu_get_bus_clock(struct bcma_drv_cc *cc)
+ {
+ struct bcma_bus *bus = cc->core->bus;
+
+@@ -268,40 +288,42 @@ static u32 bcma_pmu_get_clockcontrol(str
+ case BCMA_CHIP_ID_BCM4716:
+ case BCMA_CHIP_ID_BCM4748:
+ case BCMA_CHIP_ID_BCM47162:
+- return bcma_pmu_clock(cc, BCMA_CC_PMU4716_MAINPLL_PLL0,
+- BCMA_CC_PMU5_MAINPLL_SSB);
++ return bcma_pmu_pll_clock(cc, BCMA_CC_PMU4716_MAINPLL_PLL0,
++ BCMA_CC_PMU5_MAINPLL_SSB);
+ case BCMA_CHIP_ID_BCM5356:
+- return bcma_pmu_clock(cc, BCMA_CC_PMU5356_MAINPLL_PLL0,
+- BCMA_CC_PMU5_MAINPLL_SSB);
++ return bcma_pmu_pll_clock(cc, BCMA_CC_PMU5356_MAINPLL_PLL0,
++ BCMA_CC_PMU5_MAINPLL_SSB);
+ case BCMA_CHIP_ID_BCM5357:
+ case BCMA_CHIP_ID_BCM4749:
+- return bcma_pmu_clock(cc, BCMA_CC_PMU5357_MAINPLL_PLL0,
+- BCMA_CC_PMU5_MAINPLL_SSB);
++ return bcma_pmu_pll_clock(cc, BCMA_CC_PMU5357_MAINPLL_PLL0,
++ BCMA_CC_PMU5_MAINPLL_SSB);
+ case BCMA_CHIP_ID_BCM4706:
+- return bcma_pmu_clock_bcm4706(cc, BCMA_CC_PMU4706_MAINPLL_PLL0,
+- BCMA_CC_PMU5_MAINPLL_SSB);
++ return bcma_pmu_pll_clock_bcm4706(cc,
++ BCMA_CC_PMU4706_MAINPLL_PLL0,
++ BCMA_CC_PMU5_MAINPLL_SSB);
+ case BCMA_CHIP_ID_BCM53572:
+ return 75000000;
+ default:
+- bcma_warn(bus, "No backplane clock specified for %04X device, pmu rev. %d, using default %d Hz\n",
++ bcma_warn(bus, "No bus clock specified for %04X device, pmu rev. %d, using default %d Hz\n",
+ bus->chipinfo.id, cc->pmu.rev, BCMA_CC_PMU_HT_CLOCK);
+ }
+ return BCMA_CC_PMU_HT_CLOCK;
+ }
+
+ /* query cpu clock frequency for PMU-enabled chipcommon */
+-u32 bcma_pmu_get_clockcpu(struct bcma_drv_cc *cc)
++u32 bcma_pmu_get_cpu_clock(struct bcma_drv_cc *cc)
+ {
+ struct bcma_bus *bus = cc->core->bus;
+
+ if (bus->chipinfo.id == BCMA_CHIP_ID_BCM53572)
+ return 300000000;
+
++ /* New PMUs can have different clock for bus and CPU */
+ if (cc->pmu.rev >= 5) {
+ u32 pll;
+ switch (bus->chipinfo.id) {
+ case BCMA_CHIP_ID_BCM4706:
+- return bcma_pmu_clock_bcm4706(cc,
++ return bcma_pmu_pll_clock_bcm4706(cc,
+ BCMA_CC_PMU4706_MAINPLL_PLL0,
+ BCMA_CC_PMU5_MAINPLL_CPU);
+ case BCMA_CHIP_ID_BCM5356:
+@@ -316,10 +338,11 @@ u32 bcma_pmu_get_clockcpu(struct bcma_dr
+ break;
+ }
+
+- return bcma_pmu_clock(cc, pll, BCMA_CC_PMU5_MAINPLL_CPU);
++ return bcma_pmu_pll_clock(cc, pll, BCMA_CC_PMU5_MAINPLL_CPU);
+ }
+
+- return bcma_pmu_get_clockcontrol(cc);
++ /* On old PMUs CPU has the same clock as the bus */
++ return bcma_pmu_get_bus_clock(cc);
+ }
+
+ static void bcma_pmu_spuravoid_pll_write(struct bcma_drv_cc *cc, u32 offset,
+@@ -365,7 +388,7 @@ void bcma_pmu_spuravoid_pllupdate(struct
+ tmp |= (bcm5357_bcm43236_ndiv[spuravoid]) << BCMA_CC_PMU1_PLL0_PC2_NDIV_INT_SHIFT;
+ bcma_cc_write32(cc, BCMA_CC_PLLCTL_DATA, tmp);
+
+- tmp = 1 << 10;
++ tmp = BCMA_CC_PMU_CTL_PLL_UPD;
+ break;
+
+ case BCMA_CHIP_ID_BCM4331:
+@@ -386,7 +409,7 @@ void bcma_pmu_spuravoid_pllupdate(struct
+ bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL2,
+ 0x03000a08);
+ }
+- tmp = 1 << 10;
++ tmp = BCMA_CC_PMU_CTL_PLL_UPD;
+ break;
+
+ case BCMA_CHIP_ID_BCM43224:
+@@ -419,7 +442,7 @@ void bcma_pmu_spuravoid_pllupdate(struct
+ bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL5,
+ 0x88888815);
+ }
+- tmp = 1 << 10;
++ tmp = BCMA_CC_PMU_CTL_PLL_UPD;
+ break;
+
+ case BCMA_CHIP_ID_BCM4716:
+@@ -453,7 +476,7 @@ void bcma_pmu_spuravoid_pllupdate(struct
+ 0x88888815);
+ }
+
+- tmp = 3 << 9;
++ tmp = BCMA_CC_PMU_CTL_PLL_UPD | BCMA_CC_PMU_CTL_NOILPONW;
+ break;
+
+ case BCMA_CHIP_ID_BCM43227:
+@@ -489,7 +512,7 @@ void bcma_pmu_spuravoid_pllupdate(struct
+ bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL5,
+ 0x88888815);
+ }
+- tmp = 1 << 10;
++ tmp = BCMA_CC_PMU_CTL_PLL_UPD;
+ break;
+ default:
+ bcma_err(bus, "Unknown spuravoidance settings for chip 0x%04X, not changing PLL\n",
+--- a/drivers/bcma/driver_chipcommon_sflash.c
++++ b/drivers/bcma/driver_chipcommon_sflash.c
+@@ -12,7 +12,7 @@
+
+ static struct resource bcma_sflash_resource = {
+ .name = "bcma_sflash",
+- .start = BCMA_SFLASH,
++ .start = BCMA_SOC_FLASH2,
+ .end = 0,
+ .flags = IORESOURCE_MEM | IORESOURCE_READONLY,
+ };
+@@ -31,15 +31,42 @@ struct bcma_sflash_tbl_e {
+ };
+
+ static struct bcma_sflash_tbl_e bcma_sflash_st_tbl[] = {
+- { "", 0x14, 0x10000, 32, },
++ { "M25P20", 0x11, 0x10000, 4, },
++ { "M25P40", 0x12, 0x10000, 8, },
++
++ { "M25P16", 0x14, 0x10000, 32, },
++ { "M25P32", 0x15, 0x10000, 64, },
++ { "M25P64", 0x16, 0x10000, 128, },
++ { "M25FL128", 0x17, 0x10000, 256, },
+ { 0 },
+ };
+
+ static struct bcma_sflash_tbl_e bcma_sflash_sst_tbl[] = {
++ { "SST25WF512", 1, 0x1000, 16, },
++ { "SST25VF512", 0x48, 0x1000, 16, },
++ { "SST25WF010", 2, 0x1000, 32, },
++ { "SST25VF010", 0x49, 0x1000, 32, },
++ { "SST25WF020", 3, 0x1000, 64, },
++ { "SST25VF020", 0x43, 0x1000, 64, },
++ { "SST25WF040", 4, 0x1000, 128, },
++ { "SST25VF040", 0x44, 0x1000, 128, },
++ { "SST25VF040B", 0x8d, 0x1000, 128, },
++ { "SST25WF080", 5, 0x1000, 256, },
++ { "SST25VF080B", 0x8e, 0x1000, 256, },
++ { "SST25VF016", 0x41, 0x1000, 512, },
++ { "SST25VF032", 0x4a, 0x1000, 1024, },
++ { "SST25VF064", 0x4b, 0x1000, 2048, },
+ { 0 },
+ };
+
+ static struct bcma_sflash_tbl_e bcma_sflash_at_tbl[] = {
++ { "AT45DB011", 0xc, 256, 512, },
++ { "AT45DB021", 0x14, 256, 1024, },
++ { "AT45DB041", 0x1c, 256, 2048, },
++ { "AT45DB081", 0x24, 256, 4096, },
++ { "AT45DB161", 0x2c, 512, 4096, },
++ { "AT45DB321", 0x34, 512, 8192, },
++ { "AT45DB642", 0x3c, 1024, 8192, },
+ { 0 },
+ };
+
+@@ -84,6 +111,8 @@ int bcma_sflash_init(struct bcma_drv_cc
+ break;
+ }
+ break;
++ case 0x13:
++ return -ENOTSUPP;
+ default:
+ for (e = bcma_sflash_st_tbl; e->name; e++) {
+ if (e->id == id)
+@@ -116,7 +145,7 @@ int bcma_sflash_init(struct bcma_drv_cc
+ return -ENOTSUPP;
+ }
+
+- sflash->window = BCMA_SFLASH;
++ sflash->window = BCMA_SOC_FLASH2;
+ sflash->blocksize = e->blocksize;
+ sflash->numblocks = e->numblocks;
+ sflash->size = sflash->blocksize * sflash->numblocks;
+--- /dev/null
++++ b/drivers/bcma/driver_gpio.c
+@@ -0,0 +1,98 @@
++/*
++ * Broadcom specific AMBA
++ * GPIO driver
++ *
++ * Copyright 2011, Broadcom Corporation
++ * Copyright 2012, Hauke Mehrtens <hauke@hauke-m.de>
++ *
++ * Licensed under the GNU/GPL. See COPYING for details.
++ */
++
++#include <linux/gpio.h>
++#include <linux/export.h>
++#include <linux/bcma/bcma.h>
++
++#include "bcma_private.h"
++
++static inline struct bcma_drv_cc *bcma_gpio_get_cc(struct gpio_chip *chip)
++{
++ return container_of(chip, struct bcma_drv_cc, gpio);
++}
++
++static int bcma_gpio_get_value(struct gpio_chip *chip, unsigned gpio)
++{
++ struct bcma_drv_cc *cc = bcma_gpio_get_cc(chip);
++
++ return !!bcma_chipco_gpio_in(cc, 1 << gpio);
++}
++
++static void bcma_gpio_set_value(struct gpio_chip *chip, unsigned gpio,
++ int value)
++{
++ struct bcma_drv_cc *cc = bcma_gpio_get_cc(chip);
++
++ bcma_chipco_gpio_out(cc, 1 << gpio, value ? 1 << gpio : 0);
++}
++
++static int bcma_gpio_direction_input(struct gpio_chip *chip, unsigned gpio)
++{
++ struct bcma_drv_cc *cc = bcma_gpio_get_cc(chip);
++
++ bcma_chipco_gpio_outen(cc, 1 << gpio, 0);
++ return 0;
++}
++
++static int bcma_gpio_direction_output(struct gpio_chip *chip, unsigned gpio,
++ int value)
++{
++ struct bcma_drv_cc *cc = bcma_gpio_get_cc(chip);
++
++ bcma_chipco_gpio_outen(cc, 1 << gpio, 1 << gpio);
++ bcma_chipco_gpio_out(cc, 1 << gpio, value ? 1 << gpio : 0);
++ return 0;
++}
++
++static int bcma_gpio_request(struct gpio_chip *chip, unsigned gpio)
++{
++ struct bcma_drv_cc *cc = bcma_gpio_get_cc(chip);
++
++ bcma_chipco_gpio_control(cc, 1 << gpio, 0);
++ /* clear pulldown */
++ bcma_chipco_gpio_pulldown(cc, 1 << gpio, 0);
++ /* Set pullup */
++ bcma_chipco_gpio_pullup(cc, 1 << gpio, 1 << gpio);
++
++ return 0;
++}
++
++static void bcma_gpio_free(struct gpio_chip *chip, unsigned gpio)
++{
++ struct bcma_drv_cc *cc = bcma_gpio_get_cc(chip);
++
++ /* clear pullup */
++ bcma_chipco_gpio_pullup(cc, 1 << gpio, 0);
++}
++
++int bcma_gpio_init(struct bcma_drv_cc *cc)
++{
++ struct gpio_chip *chip = &cc->gpio;
++
++ chip->label = "bcma_gpio";
++ chip->owner = THIS_MODULE;
++ chip->request = bcma_gpio_request;
++ chip->free = bcma_gpio_free;
++ chip->get = bcma_gpio_get_value;
++ chip->set = bcma_gpio_set_value;
++ chip->direction_input = bcma_gpio_direction_input;
++ chip->direction_output = bcma_gpio_direction_output;
++ chip->ngpio = 16;
++ /* There is just one SoC in one device and its GPIO addresses should be
++ * deterministic to address them more easily. The other buses could get
++ * a random base number. */
++ if (cc->core->bus->hosttype == BCMA_HOSTTYPE_SOC)
++ chip->base = 0;
++ else
++ chip->base = -1;
++
++ return gpiochip_add(chip);
++}
+--- a/drivers/bcma/driver_mips.c
++++ b/drivers/bcma/driver_mips.c
+@@ -74,11 +74,16 @@ static u32 bcma_core_mips_irqflag(struct
+ return dev->core_index;
+ flag = bcma_aread32(dev, BCMA_MIPS_OOBSELOUTA30);
+
+- return flag & 0x1F;
++ if (flag)
++ return flag & 0x1F;
++ else
++ return 0x3f;
+ }
+
+ /* Get the MIPS IRQ assignment for a specified device.
+ * If unassigned, 0 is returned.
++ * If disabled, 5 is returned.
++ * If not supported, 6 is returned.
+ */
+ unsigned int bcma_core_mips_irq(struct bcma_device *dev)
+ {
+@@ -87,13 +92,15 @@ unsigned int bcma_core_mips_irq(struct b
+ unsigned int irq;
+
+ irqflag = bcma_core_mips_irqflag(dev);
++ if (irqflag == 0x3f)
++ return 6;
+
+- for (irq = 1; irq <= 4; irq++)
++ for (irq = 0; irq <= 4; irq++)
+ if (bcma_read32(mdev, BCMA_MIPS_MIPS74K_INTMASK(irq)) &
+ (1 << irqflag))
+ return irq;
+
+- return 0;
++ return 5;
+ }
+ EXPORT_SYMBOL(bcma_core_mips_irq);
+
+@@ -114,7 +121,7 @@ static void bcma_core_mips_set_irq(struc
+ bcma_write32(mdev, BCMA_MIPS_MIPS74K_INTMASK(0),
+ bcma_read32(mdev, BCMA_MIPS_MIPS74K_INTMASK(0)) &
+ ~(1 << irqflag));
+- else
++ else if (oldirq != 5)
+ bcma_write32(mdev, BCMA_MIPS_MIPS74K_INTMASK(oldirq), 0);
+
+ /* assign the new one */
+@@ -123,9 +130,9 @@ static void bcma_core_mips_set_irq(struc
+ bcma_read32(mdev, BCMA_MIPS_MIPS74K_INTMASK(0)) |
+ (1 << irqflag));
+ } else {
+- u32 oldirqflag = bcma_read32(mdev,
+- BCMA_MIPS_MIPS74K_INTMASK(irq));
+- if (oldirqflag) {
++ u32 irqinitmask = bcma_read32(mdev,
++ BCMA_MIPS_MIPS74K_INTMASK(irq));
++ if (irqinitmask) {
+ struct bcma_device *core;
+
+ /* backplane irq line is in use, find out who uses
+@@ -133,7 +140,7 @@ static void bcma_core_mips_set_irq(struc
+ */
+ list_for_each_entry(core, &bus->cores, list) {
+ if ((1 << bcma_core_mips_irqflag(core)) ==
+- oldirqflag) {
++ irqinitmask) {
+ bcma_core_mips_set_irq(core, 0);
+ break;
+ }
+@@ -143,15 +150,31 @@ static void bcma_core_mips_set_irq(struc
+ 1 << irqflag);
+ }
+
+- bcma_info(bus, "set_irq: core 0x%04x, irq %d => %d\n",
+- dev->id.id, oldirq + 2, irq + 2);
++ bcma_debug(bus, "set_irq: core 0x%04x, irq %d => %d\n",
++ dev->id.id, oldirq <= 4 ? oldirq + 2 : 0, irq + 2);
++}
++
++static void bcma_core_mips_set_irq_name(struct bcma_bus *bus, unsigned int irq,
++ u16 coreid, u8 unit)
++{
++ struct bcma_device *core;
++
++ core = bcma_find_core_unit(bus, coreid, unit);
++ if (!core) {
++ bcma_warn(bus,
++ "Can not find core (id: 0x%x, unit %i) for IRQ configuration.\n",
++ coreid, unit);
++ return;
++ }
++
++ bcma_core_mips_set_irq(core, irq);
+ }
+
+ static void bcma_core_mips_print_irq(struct bcma_device *dev, unsigned int irq)
+ {
+ int i;
+ static const char *irq_name[] = {"2(S)", "3", "4", "5", "6", "D", "I"};
+- printk(KERN_INFO KBUILD_MODNAME ": core 0x%04x, irq :", dev->id.id);
++ printk(KERN_DEBUG KBUILD_MODNAME ": core 0x%04x, irq :", dev->id.id);
+ for (i = 0; i <= 6; i++)
+ printk(" %s%s", irq_name[i], i == irq ? "*" : " ");
+ printk("\n");
+@@ -171,7 +194,7 @@ u32 bcma_cpu_clock(struct bcma_drv_mips
+ struct bcma_bus *bus = mcore->core->bus;
+
+ if (bus->drv_cc.capabilities & BCMA_CC_CAP_PMU)
+- return bcma_pmu_get_clockcpu(&bus->drv_cc);
++ return bcma_pmu_get_cpu_clock(&bus->drv_cc);
+
+ bcma_err(bus, "No PMU available, need this to get the cpu clock\n");
+ return 0;
+@@ -181,85 +204,109 @@ EXPORT_SYMBOL(bcma_cpu_clock);
+ static void bcma_core_mips_flash_detect(struct bcma_drv_mips *mcore)
+ {
+ struct bcma_bus *bus = mcore->core->bus;
++ struct bcma_drv_cc *cc = &bus->drv_cc;
+
+- switch (bus->drv_cc.capabilities & BCMA_CC_CAP_FLASHT) {
++ switch (cc->capabilities & BCMA_CC_CAP_FLASHT) {
+ case BCMA_CC_FLASHT_STSER:
+ case BCMA_CC_FLASHT_ATSER:
+ bcma_debug(bus, "Found serial flash\n");
+- bcma_sflash_init(&bus->drv_cc);
++ bcma_sflash_init(cc);
+ break;
+ case BCMA_CC_FLASHT_PARA:
+ bcma_debug(bus, "Found parallel flash\n");
+- bus->drv_cc.pflash.window = 0x1c000000;
+- bus->drv_cc.pflash.window_size = 0x02000000;
++ cc->pflash.present = true;
++ cc->pflash.window = BCMA_SOC_FLASH2;
++ cc->pflash.window_size = BCMA_SOC_FLASH2_SZ;
+
+- if ((bcma_read32(bus->drv_cc.core, BCMA_CC_FLASH_CFG) &
++ if ((bcma_read32(cc->core, BCMA_CC_FLASH_CFG) &
+ BCMA_CC_FLASH_CFG_DS) == 0)
+- bus->drv_cc.pflash.buswidth = 1;
++ cc->pflash.buswidth = 1;
+ else
+- bus->drv_cc.pflash.buswidth = 2;
++ cc->pflash.buswidth = 2;
+ break;
+ default:
+ bcma_err(bus, "Flash type not supported\n");
+ }
+
+- if (bus->drv_cc.core->id.rev == 38 ||
++ if (cc->core->id.rev == 38 ||
+ bus->chipinfo.id == BCMA_CHIP_ID_BCM4706) {
+- if (bus->drv_cc.capabilities & BCMA_CC_CAP_NFLASH) {
++ if (cc->capabilities & BCMA_CC_CAP_NFLASH) {
+ bcma_debug(bus, "Found NAND flash\n");
+- bcma_nflash_init(&bus->drv_cc);
++ bcma_nflash_init(cc);
+ }
+ }
+ }
+
++void bcma_core_mips_early_init(struct bcma_drv_mips *mcore)
++{
++ struct bcma_bus *bus = mcore->core->bus;
++
++ if (mcore->early_setup_done)
++ return;
++
++ bcma_chipco_serial_init(&bus->drv_cc);
++ bcma_core_mips_flash_detect(mcore);
++
++ mcore->early_setup_done = true;
++}
++
+ void bcma_core_mips_init(struct bcma_drv_mips *mcore)
+ {
+ struct bcma_bus *bus;
+ struct bcma_device *core;
+ bus = mcore->core->bus;
+
+- bcma_info(bus, "Initializing MIPS core...\n");
++ if (mcore->setup_done)
++ return;
+
+- if (!mcore->setup_done)
+- mcore->assigned_irqs = 1;
++ bcma_debug(bus, "Initializing MIPS core...\n");
+
+- /* Assign IRQs to all cores on the bus */
+- list_for_each_entry(core, &bus->cores, list) {
+- int mips_irq;
+- if (core->irq)
+- continue;
+-
+- mips_irq = bcma_core_mips_irq(core);
+- if (mips_irq > 4)
+- core->irq = 0;
+- else
+- core->irq = mips_irq + 2;
+- if (core->irq > 5)
+- continue;
+- switch (core->id.id) {
+- case BCMA_CORE_PCI:
+- case BCMA_CORE_PCIE:
+- case BCMA_CORE_ETHERNET:
+- case BCMA_CORE_ETHERNET_GBIT:
+- case BCMA_CORE_MAC_GBIT:
+- case BCMA_CORE_80211:
+- case BCMA_CORE_USB20_HOST:
+- /* These devices get their own IRQ line if available,
+- * the rest goes on IRQ0
+- */
+- if (mcore->assigned_irqs <= 4)
+- bcma_core_mips_set_irq(core,
+- mcore->assigned_irqs++);
+- break;
++ bcma_core_mips_early_init(mcore);
++
++ switch (bus->chipinfo.id) {
++ case BCMA_CHIP_ID_BCM4716:
++ case BCMA_CHIP_ID_BCM4748:
++ bcma_core_mips_set_irq_name(bus, 1, BCMA_CORE_80211, 0);
++ bcma_core_mips_set_irq_name(bus, 2, BCMA_CORE_MAC_GBIT, 0);
++ bcma_core_mips_set_irq_name(bus, 3, BCMA_CORE_USB20_HOST, 0);
++ bcma_core_mips_set_irq_name(bus, 4, BCMA_CORE_PCIE, 0);
++ bcma_core_mips_set_irq_name(bus, 0, BCMA_CORE_CHIPCOMMON, 0);
++ bcma_core_mips_set_irq_name(bus, 0, BCMA_CORE_I2S, 0);
++ break;
++ case BCMA_CHIP_ID_BCM5356:
++ case BCMA_CHIP_ID_BCM47162:
++ case BCMA_CHIP_ID_BCM53572:
++ bcma_core_mips_set_irq_name(bus, 1, BCMA_CORE_80211, 0);
++ bcma_core_mips_set_irq_name(bus, 2, BCMA_CORE_MAC_GBIT, 0);
++ bcma_core_mips_set_irq_name(bus, 0, BCMA_CORE_CHIPCOMMON, 0);
++ break;
++ case BCMA_CHIP_ID_BCM5357:
++ case BCMA_CHIP_ID_BCM4749:
++ bcma_core_mips_set_irq_name(bus, 1, BCMA_CORE_80211, 0);
++ bcma_core_mips_set_irq_name(bus, 2, BCMA_CORE_MAC_GBIT, 0);
++ bcma_core_mips_set_irq_name(bus, 3, BCMA_CORE_USB20_HOST, 0);
++ bcma_core_mips_set_irq_name(bus, 0, BCMA_CORE_CHIPCOMMON, 0);
++ bcma_core_mips_set_irq_name(bus, 0, BCMA_CORE_I2S, 0);
++ break;
++ case BCMA_CHIP_ID_BCM4706:
++ bcma_core_mips_set_irq_name(bus, 1, BCMA_CORE_PCIE, 0);
++ bcma_core_mips_set_irq_name(bus, 2, BCMA_CORE_4706_MAC_GBIT,
++ 0);
++ bcma_core_mips_set_irq_name(bus, 3, BCMA_CORE_PCIE, 1);
++ bcma_core_mips_set_irq_name(bus, 4, BCMA_CORE_USB20_HOST, 0);
++ bcma_core_mips_set_irq_name(bus, 0, BCMA_CORE_4706_CHIPCOMMON,
++ 0);
++ break;
++ default:
++ list_for_each_entry(core, &bus->cores, list) {
++ core->irq = bcma_core_mips_irq(core) + 2;
+ }
++ bcma_err(bus,
++ "Unknown device (0x%x) found, can not configure IRQs\n",
++ bus->chipinfo.id);
+ }
+- bcma_info(bus, "IRQ reconfiguration done\n");
++ bcma_debug(bus, "IRQ reconfiguration done\n");
+ bcma_core_mips_dump_irq(bus);
+
+- if (mcore->setup_done)
+- return;
+-
+- bcma_chipco_serial_init(&bus->drv_cc);
+- bcma_core_mips_flash_detect(mcore);
+ mcore->setup_done = true;
+ }
+--- a/drivers/bcma/driver_pci_host.c
++++ b/drivers/bcma/driver_pci_host.c
+@@ -35,11 +35,6 @@ bool __devinit bcma_core_pci_is_in_hostm
+ chipid_top != 0x5300)
+ return false;
+
+- if (bus->sprom.boardflags_lo & BCMA_CORE_PCI_BFL_NOPCI) {
+- bcma_info(bus, "This PCI core is disabled and not working\n");
+- return false;
+- }
+-
+ bcma_core_enable(pc->core, 0);
+
+ return !mips_busprobe32(tmp, pc->core->io_addr);
+@@ -396,6 +391,11 @@ void __devinit bcma_core_pci_hostmode_in
+
+ bcma_info(bus, "PCIEcore in host mode found\n");
+
++ if (bus->sprom.boardflags_lo & BCMA_CORE_PCI_BFL_NOPCI) {
++ bcma_info(bus, "This PCIE core is disabled and not working\n");
++ return;
++ }
++
+ pc_host = kzalloc(sizeof(*pc_host), GFP_KERNEL);
+ if (!pc_host) {
+ bcma_err(bus, "can not allocate memory");
+@@ -452,6 +452,8 @@ void __devinit bcma_core_pci_hostmode_in
+ pc_host->mem_resource.start = BCMA_SOC_PCI_MEM;
+ pc_host->mem_resource.end = BCMA_SOC_PCI_MEM +
+ BCMA_SOC_PCI_MEM_SZ - 1;
++ pc_host->io_resource.start = 0x100;
++ pc_host->io_resource.end = 0x47F;
+ pci_membase_1G = BCMA_SOC_PCIE_DMA_H32;
+ pcicore_write32(pc, BCMA_CORE_PCI_SBTOPCI0,
+ tmp | BCMA_SOC_PCI_MEM);
+@@ -459,6 +461,8 @@ void __devinit bcma_core_pci_hostmode_in
+ pc_host->mem_resource.start = BCMA_SOC_PCI1_MEM;
+ pc_host->mem_resource.end = BCMA_SOC_PCI1_MEM +
+ BCMA_SOC_PCI_MEM_SZ - 1;
++ pc_host->io_resource.start = 0x480;
++ pc_host->io_resource.end = 0x7FF;
+ pci_membase_1G = BCMA_SOC_PCIE1_DMA_H32;
+ pc_host->host_cfg_addr = BCMA_SOC_PCI1_CFG;
+ pcicore_write32(pc, BCMA_CORE_PCI_SBTOPCI0,
+@@ -534,7 +538,7 @@ DECLARE_PCI_FIXUP_EARLY(PCI_ANY_ID, PCI_
+ static void bcma_core_pci_fixup_addresses(struct pci_dev *dev)
+ {
+ struct resource *res;
+- int pos;
++ int pos, err;
+
+ if (dev->bus->ops->read != bcma_core_pci_hostmode_read_config) {
+ /* This is not a device on the PCI-core bridge. */
+@@ -547,8 +551,12 @@ static void bcma_core_pci_fixup_addresse
+
+ for (pos = 0; pos < 6; pos++) {
+ res = &dev->resource[pos];
+- if (res->flags & (IORESOURCE_IO | IORESOURCE_MEM))
+- pci_assign_resource(dev, pos);
++ if (res->flags & (IORESOURCE_IO | IORESOURCE_MEM)) {
++ err = pci_assign_resource(dev, pos);
++ if (err)
++ pr_err("PCI: Problem fixing up the addresses on %s\n",
++ pci_name(dev));
++ }
+ }
+ }
+ DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID, PCI_ANY_ID, bcma_core_pci_fixup_addresses);
+--- a/drivers/bcma/host_pci.c
++++ b/drivers/bcma/host_pci.c
+@@ -238,7 +238,7 @@ static void __devexit bcma_host_pci_remo
+ pci_set_drvdata(dev, NULL);
+ }
+
+-#ifdef CONFIG_PM
++#ifdef CONFIG_PM_SLEEP
+ static int bcma_host_pci_suspend(struct device *dev)
+ {
+ struct pci_dev *pdev = to_pci_dev(dev);
+@@ -261,11 +261,11 @@ static SIMPLE_DEV_PM_OPS(bcma_pm_ops, bc
+ bcma_host_pci_resume);
+ #define BCMA_PM_OPS (&bcma_pm_ops)
+
+-#else /* CONFIG_PM */
++#else /* CONFIG_PM_SLEEP */
+
+ #define BCMA_PM_OPS NULL
+
+-#endif /* CONFIG_PM */
++#endif /* CONFIG_PM_SLEEP */
+
+ static DEFINE_PCI_DEVICE_TABLE(bcma_pci_bridge_tbl) = {
+ { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x0576) },
+--- a/drivers/bcma/main.c
++++ b/drivers/bcma/main.c
+@@ -81,6 +81,18 @@ struct bcma_device *bcma_find_core(struc
+ }
+ EXPORT_SYMBOL_GPL(bcma_find_core);
+
++struct bcma_device *bcma_find_core_unit(struct bcma_bus *bus, u16 coreid,
++ u8 unit)
++{
++ struct bcma_device *core;
++
++ list_for_each_entry(core, &bus->cores, list) {
++ if (core->id.id == coreid && core->core_unit == unit)
++ return core;
++ }
++ return NULL;
++}
++
+ static void bcma_release_core_dev(struct device *dev)
+ {
+ struct bcma_device *core = container_of(dev, struct bcma_device, dev);
+@@ -152,6 +164,17 @@ static int bcma_register_cores(struct bc
+ bcma_err(bus, "Error registering NAND flash\n");
+ }
+ #endif
++ err = bcma_gpio_init(&bus->drv_cc);
++ if (err == -ENOTSUPP)
++ bcma_debug(bus, "GPIO driver not activated\n");
++ else if (err)
++ bcma_err(bus, "Error registering GPIO driver: %i\n", err);
++
++ if (bus->hosttype == BCMA_HOSTTYPE_SOC) {
++ err = bcma_chipco_watchdog_register(&bus->drv_cc);
++ if (err)
++ bcma_err(bus, "Error registering watchdog driver\n");
++ }
+
+ return 0;
+ }
+@@ -165,6 +188,8 @@ static void bcma_unregister_cores(struct
+ if (core->dev_registered)
+ device_unregister(&core->dev);
+ }
++ if (bus->hosttype == BCMA_HOSTTYPE_SOC)
++ platform_device_unregister(bus->drv_cc.watchdog);
+ }
+
+ int __devinit bcma_bus_register(struct bcma_bus *bus)
+@@ -183,6 +208,20 @@ int __devinit bcma_bus_register(struct b
+ return -1;
+ }
+
++ /* Early init CC core */
++ core = bcma_find_core(bus, bcma_cc_core_id(bus));
++ if (core) {
++ bus->drv_cc.core = core;
++ bcma_core_chipcommon_early_init(&bus->drv_cc);
++ }
++
++ /* Try to get SPROM */
++ err = bcma_sprom_get(bus);
++ if (err == -ENOENT) {
++ bcma_err(bus, "No SPROM available\n");
++ } else if (err)
++ bcma_err(bus, "Failed to get SPROM: %d\n", err);
++
+ /* Init CC core */
+ core = bcma_find_core(bus, bcma_cc_core_id(bus));
+ if (core) {
+@@ -198,10 +237,17 @@ int __devinit bcma_bus_register(struct b
+ }
+
+ /* Init PCIE core */
+- core = bcma_find_core(bus, BCMA_CORE_PCIE);
++ core = bcma_find_core_unit(bus, BCMA_CORE_PCIE, 0);
+ if (core) {
+- bus->drv_pci.core = core;
+- bcma_core_pci_init(&bus->drv_pci);
++ bus->drv_pci[0].core = core;
++ bcma_core_pci_init(&bus->drv_pci[0]);
++ }
++
++ /* Init PCIE core */
++ core = bcma_find_core_unit(bus, BCMA_CORE_PCIE, 1);
++ if (core) {
++ bus->drv_pci[1].core = core;
++ bcma_core_pci_init(&bus->drv_pci[1]);
+ }
+
+ /* Init GBIT MAC COMMON core */
+@@ -211,13 +257,6 @@ int __devinit bcma_bus_register(struct b
+ bcma_core_gmac_cmn_init(&bus->drv_gmac_cmn);
+ }
+
+- /* Try to get SPROM */
+- err = bcma_sprom_get(bus);
+- if (err == -ENOENT) {
+- bcma_err(bus, "No SPROM available\n");
+- } else if (err)
+- bcma_err(bus, "Failed to get SPROM: %d\n", err);
+-
+ /* Register found cores */
+ bcma_register_cores(bus);
+
+@@ -275,18 +314,18 @@ int __init bcma_bus_early_register(struc
+ return -1;
+ }
+
+- /* Init CC core */
++ /* Early init CC core */
+ core = bcma_find_core(bus, bcma_cc_core_id(bus));
+ if (core) {
+ bus->drv_cc.core = core;
+- bcma_core_chipcommon_init(&bus->drv_cc);
++ bcma_core_chipcommon_early_init(&bus->drv_cc);
+ }
+
+- /* Init MIPS core */
++ /* Early init MIPS core */
+ core = bcma_find_core(bus, BCMA_CORE_MIPS_74K);
+ if (core) {
+ bus->drv_mips.core = core;
+- bcma_core_mips_init(&bus->drv_mips);
++ bcma_core_mips_early_init(&bus->drv_mips);
+ }
+
+ bcma_info(bus, "Early bus registered\n");
+--- a/drivers/bcma/sprom.c
++++ b/drivers/bcma/sprom.c
+@@ -595,8 +595,11 @@ int bcma_sprom_get(struct bcma_bus *bus)
+ bcma_chipco_bcm4331_ext_pa_lines_ctl(&bus->drv_cc, true);
+
+ err = bcma_sprom_valid(sprom);
+- if (err)
++ if (err) {
++ bcma_warn(bus, "invalid sprom read from the PCIe card, try to use fallback sprom\n");
++ err = bcma_fill_sprom_with_fallback(bus, &bus->sprom);
+ goto out;
++ }
+
+ bcma_sprom_extract_r8(bus, sprom);
+
+--- a/include/linux/bcma/bcma.h
++++ b/include/linux/bcma/bcma.h
+@@ -134,6 +134,7 @@ struct bcma_host_ops {
+ #define BCMA_CORE_I2S 0x834
+ #define BCMA_CORE_SDR_DDR1_MEM_CTL 0x835 /* SDR/DDR1 memory controller core */
+ #define BCMA_CORE_SHIM 0x837 /* SHIM component in ubus/6362 */
++#define BCMA_CORE_ARM_CR4 0x83e
+ #define BCMA_CORE_DEFAULT 0xFFF
+
+ #define BCMA_MAX_NR_CORES 16
+@@ -157,6 +158,7 @@ struct bcma_host_ops {
+
+ /* Chip IDs of SoCs */
+ #define BCMA_CHIP_ID_BCM4706 0x5300
++#define BCMA_PKG_ID_BCM4706L 1
+ #define BCMA_CHIP_ID_BCM4716 0x4716
+ #define BCMA_PKG_ID_BCM4716 8
+ #define BCMA_PKG_ID_BCM4717 9
+@@ -166,7 +168,11 @@ struct bcma_host_ops {
+ #define BCMA_CHIP_ID_BCM4749 0x4749
+ #define BCMA_CHIP_ID_BCM5356 0x5356
+ #define BCMA_CHIP_ID_BCM5357 0x5357
++#define BCMA_PKG_ID_BCM5358 9
++#define BCMA_PKG_ID_BCM47186 10
++#define BCMA_PKG_ID_BCM5357 11
+ #define BCMA_CHIP_ID_BCM53572 53572
++#define BCMA_PKG_ID_BCM47188 9
+
+ struct bcma_device {
+ struct bcma_bus *bus;
+@@ -251,7 +257,7 @@ struct bcma_bus {
+ u8 num;
+
+ struct bcma_drv_cc drv_cc;
+- struct bcma_drv_pci drv_pci;
++ struct bcma_drv_pci drv_pci[2];
+ struct bcma_drv_mips drv_mips;
+ struct bcma_drv_gmac_cmn drv_gmac_cmn;
+
+@@ -345,6 +351,7 @@ extern void bcma_core_set_clockmode(stru
+ enum bcma_clkmode clkmode);
+ extern void bcma_core_pll_ctl(struct bcma_device *core, u32 req, u32 status,
+ bool on);
++extern u32 bcma_chipco_pll_read(struct bcma_drv_cc *cc, u32 offset);
+ #define BCMA_DMA_TRANSLATION_MASK 0xC0000000
+ #define BCMA_DMA_TRANSLATION_NONE 0x00000000
+ #define BCMA_DMA_TRANSLATION_DMA32_CMT 0x40000000 /* Client Mode Translation for 32-bit DMA */
+--- a/include/linux/bcma/bcma_driver_chipcommon.h
++++ b/include/linux/bcma/bcma_driver_chipcommon.h
+@@ -1,6 +1,9 @@
+ #ifndef LINUX_BCMA_DRIVER_CC_H_
+ #define LINUX_BCMA_DRIVER_CC_H_
+
++#include <linux/platform_device.h>
++#include <linux/gpio.h>
++
+ /** ChipCommon core registers. **/
+ #define BCMA_CC_ID 0x0000
+ #define BCMA_CC_ID_ID 0x0000FFFF
+@@ -101,6 +104,7 @@
+ #define BCMA_CC_CHIPST_4706_MIPS_BENDIAN BIT(3) /* 0: little, 1: big endian */
+ #define BCMA_CC_CHIPST_4706_PCIE1_DISABLE BIT(5) /* PCIE1 enable strap pin */
+ #define BCMA_CC_CHIPST_5357_NAND_BOOT BIT(4) /* NAND boot, valid for CC rev 38 and/or BCM5357 */
++#define BCMA_CC_CHIPST_4360_XTAL_40MZ 0x00000001
+ #define BCMA_CC_JCMD 0x0030 /* Rev >= 10 only */
+ #define BCMA_CC_JCMD_START 0x80000000
+ #define BCMA_CC_JCMD_BUSY 0x80000000
+@@ -312,6 +316,9 @@
+ #define BCMA_CC_PMU_CTL 0x0600 /* PMU control */
+ #define BCMA_CC_PMU_CTL_ILP_DIV 0xFFFF0000 /* ILP div mask */
+ #define BCMA_CC_PMU_CTL_ILP_DIV_SHIFT 16
++#define BCMA_CC_PMU_CTL_RES 0x00006000 /* reset control mask */
++#define BCMA_CC_PMU_CTL_RES_SHIFT 13
++#define BCMA_CC_PMU_CTL_RES_RELOAD 0x2 /* reload POR values */
+ #define BCMA_CC_PMU_CTL_PLL_UPD 0x00000400
+ #define BCMA_CC_PMU_CTL_NOILPONW 0x00000200 /* No ILP on wait */
+ #define BCMA_CC_PMU_CTL_HTREQEN 0x00000100 /* HT req enable */
+@@ -510,6 +517,7 @@ struct bcma_chipcommon_pmu {
+
+ #ifdef CONFIG_BCMA_DRIVER_MIPS
+ struct bcma_pflash {
++ bool present;
+ u8 buswidth;
+ u32 window;
+ u32 window_size;
+@@ -532,6 +540,7 @@ struct mtd_info;
+
+ struct bcma_nflash {
+ bool present;
++ bool boot; /* This is the flash the SoC boots from */
+
+ struct mtd_info *mtd;
+ };
+@@ -552,6 +561,7 @@ struct bcma_drv_cc {
+ u32 capabilities;
+ u32 capabilities_ext;
+ u8 setup_done:1;
++ u8 early_setup_done:1;
+ /* Fast Powerup Delay constant */
+ u16 fast_pwrup_delay;
+ struct bcma_chipcommon_pmu pmu;
+@@ -567,6 +577,14 @@ struct bcma_drv_cc {
+ int nr_serial_ports;
+ struct bcma_serial_port serial_ports[4];
+ #endif /* CONFIG_BCMA_DRIVER_MIPS */
++ u32 ticks_per_ms;
++ struct platform_device *watchdog;
++
++ /* Lock for GPIO register access. */
++ spinlock_t gpio_lock;
++#ifdef CONFIG_BCMA_DRIVER_GPIO
++ struct gpio_chip gpio;
++#endif
+ };
+
+ /* Register access */
+@@ -583,14 +601,16 @@ struct bcma_drv_cc {
+ bcma_cc_write32(cc, offset, (bcma_cc_read32(cc, offset) & (mask)) | (set))
+
+ extern void bcma_core_chipcommon_init(struct bcma_drv_cc *cc);
++extern void bcma_core_chipcommon_early_init(struct bcma_drv_cc *cc);
+
+ extern void bcma_chipco_suspend(struct bcma_drv_cc *cc);
+ extern void bcma_chipco_resume(struct bcma_drv_cc *cc);
+
+ void bcma_chipco_bcm4331_ext_pa_lines_ctl(struct bcma_drv_cc *cc, bool enable);
+
+-extern void bcma_chipco_watchdog_timer_set(struct bcma_drv_cc *cc,
+- u32 ticks);
++extern u32 bcma_chipco_watchdog_timer_set(struct bcma_drv_cc *cc, u32 ticks);
++
++extern u32 bcma_chipco_get_alp_clock(struct bcma_drv_cc *cc);
+
+ void bcma_chipco_irq_mask(struct bcma_drv_cc *cc, u32 mask, u32 value);
+
+@@ -603,9 +623,12 @@ u32 bcma_chipco_gpio_outen(struct bcma_d
+ u32 bcma_chipco_gpio_control(struct bcma_drv_cc *cc, u32 mask, u32 value);
+ u32 bcma_chipco_gpio_intmask(struct bcma_drv_cc *cc, u32 mask, u32 value);
+ u32 bcma_chipco_gpio_polarity(struct bcma_drv_cc *cc, u32 mask, u32 value);
++u32 bcma_chipco_gpio_pullup(struct bcma_drv_cc *cc, u32 mask, u32 value);
++u32 bcma_chipco_gpio_pulldown(struct bcma_drv_cc *cc, u32 mask, u32 value);
+
+ /* PMU support */
+ extern void bcma_pmu_init(struct bcma_drv_cc *cc);
++extern void bcma_pmu_early_init(struct bcma_drv_cc *cc);
+
+ extern void bcma_chipco_pll_write(struct bcma_drv_cc *cc, u32 offset,
+ u32 value);
+--- a/include/linux/bcma/bcma_driver_mips.h
++++ b/include/linux/bcma/bcma_driver_mips.h
+@@ -35,13 +35,15 @@ struct bcma_device;
+ struct bcma_drv_mips {
+ struct bcma_device *core;
+ u8 setup_done:1;
+- unsigned int assigned_irqs;
++ u8 early_setup_done:1;
+ };
+
+ #ifdef CONFIG_BCMA_DRIVER_MIPS
+ extern void bcma_core_mips_init(struct bcma_drv_mips *mcore);
++extern void bcma_core_mips_early_init(struct bcma_drv_mips *mcore);
+ #else
+ static inline void bcma_core_mips_init(struct bcma_drv_mips *mcore) { }
++static inline void bcma_core_mips_early_init(struct bcma_drv_mips *mcore) { }
+ #endif
+
+ extern u32 bcma_cpu_clock(struct bcma_drv_mips *mcore);
+--- a/include/linux/bcma/bcma_regs.h
++++ b/include/linux/bcma/bcma_regs.h
+@@ -37,6 +37,7 @@
+ #define BCMA_IOST_BIST_DONE 0x8000
+ #define BCMA_RESET_CTL 0x0800
+ #define BCMA_RESET_CTL_RESET 0x0001
++#define BCMA_RESET_ST 0x0804
+
+ /* BCMA PCI config space registers. */
+ #define BCMA_PCI_PMCSR 0x44
+@@ -85,6 +86,9 @@
+ * (2 ZettaBytes), high 32 bits
+ */
+
+-#define BCMA_SFLASH 0x1c000000
++#define BCMA_SOC_FLASH1 0x1fc00000 /* MIPS Flash Region 1 */
++#define BCMA_SOC_FLASH1_SZ 0x00400000 /* MIPS Size of Flash Region 1 */
++#define BCMA_SOC_FLASH2 0x1c000000 /* Flash Region 2 (region 1 shadowed here) */
++#define BCMA_SOC_FLASH2_SZ 0x02000000 /* Size of Flash Region 2 */
+
+ #endif /* LINUX_BCMA_REGS_H_ */
+--- a/drivers/net/wireless/b43/main.c
++++ b/drivers/net/wireless/b43/main.c
+@@ -4684,7 +4684,7 @@ static int b43_wireless_core_init(struct
+ switch (dev->dev->bus_type) {
+ #ifdef CONFIG_B43_BCMA
+ case B43_BUS_BCMA:
+- bcma_core_pci_irq_ctl(&dev->dev->bdev->bus->drv_pci,
++ bcma_core_pci_irq_ctl(&dev->dev->bdev->bus->drv_pci[0],
+ dev->dev->bdev, true);
+ break;
+ #endif
+--- a/drivers/net/wireless/brcm80211/brcmsmac/aiutils.c
++++ b/drivers/net/wireless/brcm80211/brcmsmac/aiutils.c
+@@ -692,7 +692,7 @@ void ai_pci_up(struct si_pub *sih)
+ sii = container_of(sih, struct si_info, pub);
+
+ if (sii->icbus->hosttype == BCMA_HOSTTYPE_PCI)
+- bcma_core_pci_extend_L1timer(&sii->icbus->drv_pci, true);
++ bcma_core_pci_extend_L1timer(&sii->icbus->drv_pci[0], true);
+ }
+
+ /* Unconfigure and/or apply various WARs when going down */
+@@ -703,7 +703,7 @@ void ai_pci_down(struct si_pub *sih)
+ sii = container_of(sih, struct si_info, pub);
+
+ if (sii->icbus->hosttype == BCMA_HOSTTYPE_PCI)
+- bcma_core_pci_extend_L1timer(&sii->icbus->drv_pci, false);
++ bcma_core_pci_extend_L1timer(&sii->icbus->drv_pci[0], false);
+ }
+
+ /* Enable BT-COEX & Ex-PA for 4313 */
+--- a/drivers/net/wireless/brcm80211/brcmsmac/main.c
++++ b/drivers/net/wireless/brcm80211/brcmsmac/main.c
+@@ -5077,7 +5077,7 @@ static int brcms_b_up_prep(struct brcms_
+ * Configure pci/pcmcia here instead of in brcms_c_attach()
+ * to allow mfg hotswap: down, hotswap (chip power cycle), up.
+ */
+- bcma_core_pci_irq_ctl(&wlc_hw->d11core->bus->drv_pci, wlc_hw->d11core,
++ bcma_core_pci_irq_ctl(&wlc_hw->d11core->bus->drv_pci[0], wlc_hw->d11core,
+ true);
+
+ /*
diff --git a/target/linux/generic/patches-3.7/065-8139cp-fixes.patch b/target/linux/generic/patches-3.7/065-8139cp-fixes.patch
index 33ca1a128..71c53f9cb 100644
--- a/target/linux/generic/patches-3.7/065-8139cp-fixes.patch
+++ b/target/linux/generic/patches-3.7/065-8139cp-fixes.patch
@@ -66,11 +66,9 @@ Date: Sun Nov 25 15:52:09 2012 -0500
Signed-off-by: David S. Miller <davem@davemloft.net>
-diff --git a/drivers/net/ethernet/realtek/8139cp.c b/drivers/net/ethernet/realtek/8139cp.c
-index b01f83a..6cb96b4 100644
--- a/drivers/net/ethernet/realtek/8139cp.c
+++ b/drivers/net/ethernet/realtek/8139cp.c
-@@ -648,6 +648,7 @@ static void cp_tx (struct cp_private *cp)
+@@ -648,6 +648,7 @@ static void cp_tx (struct cp_private *cp
{
unsigned tx_head = cp->tx_head;
unsigned tx_tail = cp->tx_tail;
@@ -78,7 +76,7 @@ index b01f83a..6cb96b4 100644
while (tx_tail != tx_head) {
struct cp_desc *txd = cp->tx_ring + tx_tail;
-@@ -666,6 +667,9 @@ static void cp_tx (struct cp_private *cp)
+@@ -666,6 +667,9 @@ static void cp_tx (struct cp_private *cp
le32_to_cpu(txd->opts1) & 0xffff,
PCI_DMA_TODEVICE);
@@ -88,7 +86,7 @@ index b01f83a..6cb96b4 100644
if (status & LastFrag) {
if (status & (TxError | TxFIFOUnder)) {
netif_dbg(cp, tx_err, cp->dev,
-@@ -697,6 +701,7 @@ static void cp_tx (struct cp_private *cp)
+@@ -697,6 +701,7 @@ static void cp_tx (struct cp_private *cp
cp->tx_tail = tx_tail;
@@ -96,7 +94,7 @@ index b01f83a..6cb96b4 100644
if (TX_BUFFS_AVAIL(cp) > (MAX_SKB_FRAGS + 1))
netif_wake_queue(cp->dev);
}
-@@ -843,6 +848,8 @@ static netdev_tx_t cp_start_xmit (struct sk_buff *skb,
+@@ -843,6 +848,8 @@ static netdev_tx_t cp_start_xmit (struct
wmb();
}
cp->tx_head = entry;
@@ -105,7 +103,7 @@ index b01f83a..6cb96b4 100644
netif_dbg(cp, tx_queued, cp->dev, "tx queued, slot %d, skblen %d\n",
entry, skb->len);
if (TX_BUFFS_AVAIL(cp) <= (MAX_SKB_FRAGS + 1))
-@@ -937,6 +944,8 @@ static void cp_stop_hw (struct cp_private *cp)
+@@ -937,6 +944,8 @@ static void cp_stop_hw (struct cp_privat
cp->rx_tail = 0;
cp->tx_head = cp->tx_tail = 0;
@@ -114,7 +112,7 @@ index b01f83a..6cb96b4 100644
}
static void cp_reset_hw (struct cp_private *cp)
-@@ -957,8 +966,38 @@ static void cp_reset_hw (struct cp_private *cp)
+@@ -957,8 +966,38 @@ static void cp_reset_hw (struct cp_priva
static inline void cp_start_hw (struct cp_private *cp)
{
@@ -153,7 +151,7 @@ index b01f83a..6cb96b4 100644
}
static void cp_enable_irq(struct cp_private *cp)
-@@ -969,7 +1008,6 @@ static void cp_enable_irq(struct cp_private *cp)
+@@ -969,7 +1008,6 @@ static void cp_enable_irq(struct cp_priv
static void cp_init_hw (struct cp_private *cp)
{
struct net_device *dev = cp->dev;
@@ -161,7 +159,7 @@ index b01f83a..6cb96b4 100644
cp_reset_hw(cp);
-@@ -992,17 +1030,6 @@ static void cp_init_hw (struct cp_private *cp)
+@@ -992,17 +1030,6 @@ static void cp_init_hw (struct cp_privat
cpw8(Config5, cpr8(Config5) & PMEStatus);
@@ -179,7 +177,7 @@ index b01f83a..6cb96b4 100644
cpw16(MultiIntr, 0);
cpw8_f(Cfg9346, Cfg9346_Lock);
-@@ -1192,6 +1219,7 @@ static void cp_tx_timeout(struct net_device *dev)
+@@ -1197,6 +1224,7 @@ static void cp_tx_timeout(struct net_dev
cp_clean_rings(cp);
rc = cp_init_rings(cp);
cp_start_hw(cp);
diff --git a/target/linux/generic/patches-3.7/067-mips_mt_fix_uidgid_strict_type_check.patch b/target/linux/generic/patches-3.7/067-mips_mt_fix_uidgid_strict_type_check.patch
new file mode 100644
index 000000000..14252297b
--- /dev/null
+++ b/target/linux/generic/patches-3.7/067-mips_mt_fix_uidgid_strict_type_check.patch
@@ -0,0 +1,41 @@
+From 0714f2ec1e950d7b825093d05ae8eacf1d66ce58 Mon Sep 17 00:00:00 2001
+From: Florian Fainelli <florian@openwrt.org>
+Date: Mon, 10 Dec 2012 15:52:07 +0100
+Subject: [PATCH 3.7-rc8] MIPS: MT: fix build with CONFIG_UIDGID_STRICT_TYPE_CHECKS=y
+
+When CONFIG_UIDGID_STRICT_TYPE_CHECKS is enabled, plain integer checking
+between different uids/gids is explicitely turned into a build failure
+by making the k{uid,gid}_t types a structure containing a value:
+
+arch/mips/kernel/mips-mt-fpaff.c: In function 'check_same_owner':
+arch/mips/kernel/mips-mt-fpaff.c:53:22: error: invalid operands to
+binary == (have 'kuid_t' and 'kuid_t')
+arch/mips/kernel/mips-mt-fpaff.c:54:15: error: invalid operands to
+binary == (have 'kuid_t' and 'kuid_t')
+
+This problem got introduced with commit 17c04139 (MIPS: MT: Fix FPU affinity.)
+
+In order to ensure proper comparison between uids, using the helper
+function uid_eq() which performs the right thing whenever this config
+option is turned on or off.
+
+Signed-off-by: Florian Fainelli <florian@openwrt.org>
+---
+Ralf, I think you might want to sneak this into 3.7-rc8 if possible at all.
+
+ arch/mips/kernel/mips-mt-fpaff.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+--- a/arch/mips/kernel/mips-mt-fpaff.c
++++ b/arch/mips/kernel/mips-mt-fpaff.c
+@@ -50,8 +50,8 @@ static bool check_same_owner(struct task
+
+ rcu_read_lock();
+ pcred = __task_cred(p);
+- match = (cred->euid == pcred->euid ||
+- cred->euid == pcred->uid);
++ match = (uid_eq(cred->euid, pcred->euid) ||
++ uid_eq(cred->euid, pcred->uid));
+ rcu_read_unlock();
+ return match;
+ }
diff --git a/target/linux/generic/patches-3.7/084-x86_fix_perf_uclibc_build.patch b/target/linux/generic/patches-3.7/084-x86_fix_perf_uclibc_build.patch
new file mode 100644
index 000000000..95163a43a
--- /dev/null
+++ b/target/linux/generic/patches-3.7/084-x86_fix_perf_uclibc_build.patch
@@ -0,0 +1,27 @@
+From 031d8ad2c3cee85c515e551fc8c0054bdedb7b8b Mon Sep 17 00:00:00 2001
+From: Florian Fainelli <florian@openwrt.org>
+Date: Thu, 13 Dec 2012 18:02:11 +0100
+Subject: [PATCH] x86: fix perf build with uclibc toolchains
+
+libio.h is not provided by uClibc, in order to be able to test the
+definition of __UCLIBC__ we need to include stdlib.h, which also
+includes stddef.h, providing the definition of 'NULL'
+
+Signed-off-by: Florian Fainelli <florian@openwrt.org>
+---
+ tools/perf/arch/x86/util/dwarf-regs.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
+--- a/tools/perf/arch/x86/util/dwarf-regs.c
++++ b/tools/perf/arch/x86/util/dwarf-regs.c
+@@ -20,7 +20,10 @@
+ *
+ */
+
++#include <stdlib.h>
++#ifndef __UCLIBC__
+ #include <libio.h>
++#endif
+ #include <dwarf-regs.h>
+
+ /*
diff --git a/target/linux/generic/patches-3.7/100-overlayfs.patch b/target/linux/generic/patches-3.7/100-overlayfs.patch
index 3bc777287..ea29ddb57 100644
--- a/target/linux/generic/patches-3.7/100-overlayfs.patch
+++ b/target/linux/generic/patches-3.7/100-overlayfs.patch
@@ -301,7 +301,7 @@
/**
* sb_permission - Check superblock-level permissions
-@@ -2883,9 +2884,12 @@ finish_open_created:
+@@ -2888,9 +2889,12 @@ finish_open_created:
error = may_open(&nd->path, acc_mode, open_flag);
if (error)
goto out;
@@ -3102,7 +3102,7 @@
+module_exit(ovl_exit);
--- a/fs/splice.c
+++ b/fs/splice.c
-@@ -1308,6 +1308,7 @@ long do_splice_direct(struct file *in, l
+@@ -1310,6 +1310,7 @@ long do_splice_direct(struct file *in, l
return ret;
}
@@ -3125,7 +3125,7 @@
/**
* enum positive_aop_returns - aop return codes with specific semantics
*
-@@ -1321,6 +1327,11 @@ struct super_block {
+@@ -1319,6 +1325,11 @@ struct super_block {
/* Being remounted read-only */
int s_readonly_remount;
@@ -3137,7 +3137,7 @@
};
/* superblock cache pruning functions */
-@@ -1578,6 +1589,7 @@ struct inode_operations {
+@@ -1576,6 +1587,7 @@ struct inode_operations {
int (*atomic_open)(struct inode *, struct dentry *,
struct file *, unsigned open_flag,
umode_t create_mode, int *opened);
@@ -3145,7 +3145,7 @@
} ____cacheline_aligned;
struct seq_file;
-@@ -2009,6 +2021,7 @@ extern struct file *file_open_name(struc
+@@ -2007,6 +2019,7 @@ extern struct file *file_open_name(struc
extern struct file *filp_open(const char *, int, umode_t);
extern struct file *file_open_root(struct dentry *, struct vfsmount *,
const char *, int);
@@ -3153,7 +3153,7 @@
extern struct file * dentry_open(const struct path *, int, const struct cred *);
extern int filp_close(struct file *, fl_owner_t id);
-@@ -2215,6 +2228,7 @@ extern sector_t bmap(struct inode *, sec
+@@ -2212,6 +2225,7 @@ extern sector_t bmap(struct inode *, sec
#endif
extern int notify_change(struct dentry *, struct iattr *);
extern int inode_permission(struct inode *, int);
@@ -3175,7 +3175,7 @@
int flags, const char *name,
--- a/MAINTAINERS
+++ b/MAINTAINERS
-@@ -5450,6 +5450,13 @@ F: drivers/scsi/osd/
+@@ -5458,6 +5458,13 @@ F: drivers/scsi/osd/
F: include/scsi/osd_*
F: fs/exofs/
diff --git a/target/linux/generic/patches-3.7/102-ehci_hcd_ignore_oc.patch b/target/linux/generic/patches-3.7/102-ehci_hcd_ignore_oc.patch
index bf1815a2e..dfcfc2638 100644
--- a/target/linux/generic/patches-3.7/102-ehci_hcd_ignore_oc.patch
+++ b/target/linux/generic/patches-3.7/102-ehci_hcd_ignore_oc.patch
@@ -20,7 +20,7 @@
mask = PORT_CSC | PORT_PEC | PORT_OCC;
else
mask = PORT_CSC | PORT_PEC;
-@@ -804,7 +804,7 @@ static int ehci_hub_control (
+@@ -808,7 +808,7 @@ static int ehci_hub_control (
if (temp & PORT_PEC)
status |= USB_PORT_STAT_C_ENABLE << 16;
diff --git a/target/linux/generic/patches-3.7/131-atm-fixes.patch b/target/linux/generic/patches-3.7/131-atm-fixes.patch
index 4cc3e5708..64e50b394 100644
--- a/target/linux/generic/patches-3.7/131-atm-fixes.patch
+++ b/target/linux/generic/patches-3.7/131-atm-fixes.patch
@@ -452,7 +452,7 @@ Date: Sun Nov 25 12:06:52 2012 +0000
return;
}
-@@ -1011,9 +989,12 @@ static uint32_t fpga_tx(struct solos_car
+@@ -1012,9 +990,12 @@ static uint32_t fpga_tx(struct solos_car
if (vcc) {
atomic_inc(&vcc->stats->tx);
solos_pop(vcc, oldskb);
@@ -467,7 +467,7 @@ Date: Sun Nov 25 12:06:52 2012 +0000
}
}
/* For non-DMA TX, write the 'TX start' bit for all four ports simultaneously */
-@@ -1248,7 +1229,7 @@ static int atm_init(struct solos_card *c
+@@ -1249,7 +1230,7 @@ static int atm_init(struct solos_card *c
card->atmdev[i]->phy_data = (void *)(unsigned long)i;
atm_dev_signal_change(card->atmdev[i], ATM_PHY_SIG_FOUND);
@@ -476,7 +476,7 @@ Date: Sun Nov 25 12:06:52 2012 +0000
if (!skb) {
dev_warn(&card->dev->dev, "Failed to allocate sk_buff in atm_init()\n");
continue;
-@@ -1345,6 +1326,8 @@ static struct pci_driver fpga_driver = {
+@@ -1346,6 +1327,8 @@ static struct pci_driver fpga_driver = {
static int __init solos_pci_init(void)
{
diff --git a/target/linux/generic/patches-3.7/132-solos-dma.patch b/target/linux/generic/patches-3.7/132-solos-dma.patch
new file mode 100644
index 000000000..0b761eaa0
--- /dev/null
+++ b/target/linux/generic/patches-3.7/132-solos-dma.patch
@@ -0,0 +1,388 @@
+commit 152a2a8b5e1d4cbe91a7c66f1028db15164a3766
+Author: David Woodhouse <David.Woodhouse@intel.com>
+Date: Wed Dec 19 11:01:21 2012 +0000
+
+ solos-pci: ensure all TX packets are aligned to 4 bytes
+
+ The FPGA can't handled unaligned DMA (yet). So copy into an aligned buffer,
+ if skb->data isn't suitably aligned.
+
+ Signed-off-by: David Woodhouse <David.Woodhouse@intel.com>
+ Signed-off-by: David S. Miller <davem@davemloft.net>
+
+commit 13af816469db3449c072afbae6c4c1bd9ccecccb
+Author: Nathan Williams <nathan@traverse.com.au>
+Date: Wed Dec 19 11:01:20 2012 +0000
+
+ solos-pci: add firmware upgrade support for new models
+
+ Signed-off-by: Nathan Williams <nathan@traverse.com.au>
+ Signed-off-by: David Woodhouse <David.Woodhouse@intel.com>
+ Signed-off-by: David S. Miller <davem@davemloft.net>
+
+commit 7fbdadb5e951e4f0c0fc991ff5f50295568786e6
+Author: Nathan Williams <nathan@traverse.com.au>
+Date: Wed Dec 19 11:01:19 2012 +0000
+
+ solos-pci: remove superfluous debug output
+
+ Signed-off-by: Nathan Williams <nathan@traverse.com.au>
+ Signed-off-by: David Woodhouse <David.Woodhouse@intel.com>
+ Signed-off-by: David S. Miller <davem@davemloft.net>
+
+commit f9baad02e7411d9f38d5ebe1a1cdcde4ceec100d
+Author: Nathan Williams <nathan@traverse.com.au>
+Date: Wed Dec 19 11:01:18 2012 +0000
+
+ solos-pci: add GPIO support for newer versions on Geos board
+
+ dwmw2: Tidy up a little, simpler matching on which GPIO is being accessed,
+ only register on newer boards, register under PCI device instead of
+ duplicating them under each ATM device.
+
+ Signed-off-by: Nathan Williams <nathan@traverse.com.au>
+ Signed-off-by: David Woodhouse <David.Woodhouse@intel.com>
+ Signed-off-by: David S. Miller <davem@davemloft.net>
+
+==
+There is a typo here so we do a double lock instead of an unlock.
+
+Signed-off-by: Dan Carpenter <dan.carpenter@oracle.com>
+---
+Only needed in linux-next. Introduced in f9baad02e7411d9 [14/17]
+solos-pci: add GPIO support for newer versions on Geos board
+
+
+--- a/drivers/atm/solos-pci.c
++++ b/drivers/atm/solos-pci.c
+@@ -42,7 +42,8 @@
+ #include <linux/swab.h>
+ #include <linux/slab.h>
+
+-#define VERSION "0.07"
++#define VERSION "1.04"
++#define DRIVER_VERSION 0x01
+ #define PTAG "solos-pci"
+
+ #define CONFIG_RAM_SIZE 128
+@@ -56,16 +57,21 @@
+ #define FLASH_BUSY 0x60
+ #define FPGA_MODE 0x5C
+ #define FLASH_MODE 0x58
++#define GPIO_STATUS 0x54
++#define DRIVER_VER 0x50
+ #define TX_DMA_ADDR(port) (0x40 + (4 * (port)))
+ #define RX_DMA_ADDR(port) (0x30 + (4 * (port)))
+
+ #define DATA_RAM_SIZE 32768
+ #define BUF_SIZE 2048
+ #define OLD_BUF_SIZE 4096 /* For FPGA versions <= 2*/
+-#define FPGA_PAGE 528 /* FPGA flash page size*/
+-#define SOLOS_PAGE 512 /* Solos flash page size*/
+-#define FPGA_BLOCK (FPGA_PAGE * 8) /* FPGA flash block size*/
+-#define SOLOS_BLOCK (SOLOS_PAGE * 8) /* Solos flash block size*/
++/* Old boards use ATMEL AD45DB161D flash */
++#define ATMEL_FPGA_PAGE 528 /* FPGA flash page size*/
++#define ATMEL_SOLOS_PAGE 512 /* Solos flash page size*/
++#define ATMEL_FPGA_BLOCK (ATMEL_FPGA_PAGE * 8) /* FPGA block size*/
++#define ATMEL_SOLOS_BLOCK (ATMEL_SOLOS_PAGE * 8) /* Solos block size*/
++/* Current boards use M25P/M25PE SPI flash */
++#define SPI_FLASH_BLOCK (256 * 64)
+
+ #define RX_BUF(card, nr) ((card->buffers) + (nr)*(card->buffer_size)*2)
+ #define TX_BUF(card, nr) ((card->buffers) + (nr)*(card->buffer_size)*2 + (card->buffer_size))
+@@ -123,11 +129,14 @@ struct solos_card {
+ struct sk_buff_head cli_queue[4];
+ struct sk_buff *tx_skb[4];
+ struct sk_buff *rx_skb[4];
++ unsigned char *dma_bounce;
+ wait_queue_head_t param_wq;
+ wait_queue_head_t fw_wq;
+ int using_dma;
++ int dma_alignment;
+ int fpga_version;
+ int buffer_size;
++ int atmel_flash;
+ };
+
+
+@@ -452,7 +461,6 @@ static ssize_t console_show(struct devic
+
+ len = skb->len;
+ memcpy(buf, skb->data, len);
+- dev_dbg(&card->dev->dev, "len: %d\n", len);
+
+ kfree_skb(skb);
+ return len;
+@@ -499,6 +507,78 @@ static ssize_t console_store(struct devi
+ return err?:count;
+ }
+
++struct geos_gpio_attr {
++ struct device_attribute attr;
++ int offset;
++};
++
++#define SOLOS_GPIO_ATTR(_name, _mode, _show, _store, _offset) \
++ struct geos_gpio_attr gpio_attr_##_name = { \
++ .attr = __ATTR(_name, _mode, _show, _store), \
++ .offset = _offset }
++
++static ssize_t geos_gpio_store(struct device *dev, struct device_attribute *attr,
++ const char *buf, size_t count)
++{
++ struct pci_dev *pdev = container_of(dev, struct pci_dev, dev);
++ struct geos_gpio_attr *gattr = container_of(attr, struct geos_gpio_attr, attr);
++ struct solos_card *card = pci_get_drvdata(pdev);
++ uint32_t data32;
++
++ if (count != 1 && (count != 2 || buf[1] != '\n'))
++ return -EINVAL;
++
++ spin_lock_irq(&card->param_queue_lock);
++ data32 = ioread32(card->config_regs + GPIO_STATUS);
++ if (buf[0] == '1') {
++ data32 |= 1 << gattr->offset;
++ iowrite32(data32, card->config_regs + GPIO_STATUS);
++ } else if (buf[0] == '0') {
++ data32 &= ~(1 << gattr->offset);
++ iowrite32(data32, card->config_regs + GPIO_STATUS);
++ } else {
++ count = -EINVAL;
++ }
++ spin_unlock_irq(&card->param_queue_lock);
++ return count;
++}
++
++static ssize_t geos_gpio_show(struct device *dev, struct device_attribute *attr,
++ char *buf)
++{
++ struct pci_dev *pdev = container_of(dev, struct pci_dev, dev);
++ struct geos_gpio_attr *gattr = container_of(attr, struct geos_gpio_attr, attr);
++ struct solos_card *card = pci_get_drvdata(pdev);
++ uint32_t data32;
++
++ data32 = ioread32(card->config_regs + GPIO_STATUS);
++ data32 = (data32 >> gattr->offset) & 1;
++
++ return sprintf(buf, "%d\n", data32);
++}
++
++static ssize_t hardware_show(struct device *dev, struct device_attribute *attr,
++ char *buf)
++{
++ struct pci_dev *pdev = container_of(dev, struct pci_dev, dev);
++ struct geos_gpio_attr *gattr = container_of(attr, struct geos_gpio_attr, attr);
++ struct solos_card *card = pci_get_drvdata(pdev);
++ uint32_t data32;
++
++ data32 = ioread32(card->config_regs + GPIO_STATUS);
++ switch (gattr->offset) {
++ case 0:
++ /* HardwareVersion */
++ data32 = data32 & 0x1F;
++ break;
++ case 1:
++ /* HardwareVariant */
++ data32 = (data32 >> 5) & 0x0F;
++ break;
++ }
++ return sprintf(buf, "%d\n", data32);
++}
++
+ static DEVICE_ATTR(console, 0644, console_show, console_store);
+
+
+@@ -507,6 +587,14 @@ static DEVICE_ATTR(console, 0644, consol
+
+ #include "solos-attrlist.c"
+
++static SOLOS_GPIO_ATTR(GPIO1, 0644, geos_gpio_show, geos_gpio_store, 9);
++static SOLOS_GPIO_ATTR(GPIO2, 0644, geos_gpio_show, geos_gpio_store, 10);
++static SOLOS_GPIO_ATTR(GPIO3, 0644, geos_gpio_show, geos_gpio_store, 11);
++static SOLOS_GPIO_ATTR(GPIO4, 0644, geos_gpio_show, geos_gpio_store, 12);
++static SOLOS_GPIO_ATTR(GPIO5, 0644, geos_gpio_show, geos_gpio_store, 13);
++static SOLOS_GPIO_ATTR(PushButton, 0444, geos_gpio_show, NULL, 14);
++static SOLOS_GPIO_ATTR(HardwareVersion, 0444, hardware_show, NULL, 0);
++static SOLOS_GPIO_ATTR(HardwareVariant, 0444, hardware_show, NULL, 1);
+ #undef SOLOS_ATTR_RO
+ #undef SOLOS_ATTR_RW
+
+@@ -523,6 +611,23 @@ static struct attribute_group solos_attr
+ .name = "parameters",
+ };
+
++static struct attribute *gpio_attrs[] = {
++ &gpio_attr_GPIO1.attr.attr,
++ &gpio_attr_GPIO2.attr.attr,
++ &gpio_attr_GPIO3.attr.attr,
++ &gpio_attr_GPIO4.attr.attr,
++ &gpio_attr_GPIO5.attr.attr,
++ &gpio_attr_PushButton.attr.attr,
++ &gpio_attr_HardwareVersion.attr.attr,
++ &gpio_attr_HardwareVariant.attr.attr,
++ NULL
++};
++
++static struct attribute_group gpio_attr_group = {
++ .attrs = gpio_attrs,
++ .name = "gpio",
++};
++
+ static int flash_upgrade(struct solos_card *card, int chip)
+ {
+ const struct firmware *fw;
+@@ -534,16 +639,25 @@ static int flash_upgrade(struct solos_ca
+ switch (chip) {
+ case 0:
+ fw_name = "solos-FPGA.bin";
+- blocksize = FPGA_BLOCK;
++ if (card->atmel_flash)
++ blocksize = ATMEL_FPGA_BLOCK;
++ else
++ blocksize = SPI_FLASH_BLOCK;
+ break;
+ case 1:
+ fw_name = "solos-Firmware.bin";
+- blocksize = SOLOS_BLOCK;
++ if (card->atmel_flash)
++ blocksize = ATMEL_SOLOS_BLOCK;
++ else
++ blocksize = SPI_FLASH_BLOCK;
+ break;
+ case 2:
+ if (card->fpga_version > LEGACY_BUFFERS){
+ fw_name = "solos-db-FPGA.bin";
+- blocksize = FPGA_BLOCK;
++ if (card->atmel_flash)
++ blocksize = ATMEL_FPGA_BLOCK;
++ else
++ blocksize = SPI_FLASH_BLOCK;
+ } else {
+ dev_info(&card->dev->dev, "FPGA version doesn't support"
+ " daughter board upgrades\n");
+@@ -553,7 +667,10 @@ static int flash_upgrade(struct solos_ca
+ case 3:
+ if (card->fpga_version > LEGACY_BUFFERS){
+ fw_name = "solos-Firmware.bin";
+- blocksize = SOLOS_BLOCK;
++ if (card->atmel_flash)
++ blocksize = ATMEL_SOLOS_BLOCK;
++ else
++ blocksize = SPI_FLASH_BLOCK;
+ } else {
+ dev_info(&card->dev->dev, "FPGA version doesn't support"
+ " daughter board upgrades\n");
+@@ -569,6 +686,9 @@ static int flash_upgrade(struct solos_ca
+
+ dev_info(&card->dev->dev, "Flash upgrade starting\n");
+
++ /* New FPGAs require driver version before permitting flash upgrades */
++ iowrite32(DRIVER_VERSION, card->config_regs + DRIVER_VER);
++
+ numblocks = fw->size / blocksize;
+ dev_info(&card->dev->dev, "Firmware size: %zd\n", fw->size);
+ dev_info(&card->dev->dev, "Number of blocks: %d\n", numblocks);
+@@ -598,9 +718,13 @@ static int flash_upgrade(struct solos_ca
+ /* dev_info(&card->dev->dev, "Set FPGA Flash mode to Block Write\n"); */
+ iowrite32(((chip * 2) + 1), card->config_regs + FLASH_MODE);
+
+- /* Copy block to buffer, swapping each 16 bits */
++ /* Copy block to buffer, swapping each 16 bits for Atmel flash */
+ for(i = 0; i < blocksize; i += 4) {
+- uint32_t word = swahb32p((uint32_t *)(fw->data + offset + i));
++ uint32_t word;
++ if (card->atmel_flash)
++ word = swahb32p((uint32_t *)(fw->data + offset + i));
++ else
++ word = *(uint32_t *)(fw->data + offset + i);
+ if(card->fpga_version > LEGACY_BUFFERS)
+ iowrite32(word, FLASH_BUF + i);
+ else
+@@ -961,7 +1085,12 @@ static uint32_t fpga_tx(struct solos_car
+ tx_started |= 1 << port;
+ oldskb = skb; /* We're done with this skb already */
+ } else if (skb && card->using_dma) {
+- SKB_CB(skb)->dma_addr = pci_map_single(card->dev, skb->data,
++ unsigned char *data = skb->data;
++ if ((unsigned long)data & card->dma_alignment) {
++ data = card->dma_bounce + (BUF_SIZE * port);
++ memcpy(data, skb->data, skb->len);
++ }
++ SKB_CB(skb)->dma_addr = pci_map_single(card->dev, data,
+ skb->len, PCI_DMA_TODEVICE);
+ card->tx_skb[port] = skb;
+ iowrite32(SKB_CB(skb)->dma_addr,
+@@ -1135,18 +1264,33 @@ static int fpga_probe(struct pci_dev *de
+ db_fpga_upgrade = db_firmware_upgrade = 0;
+ }
+
++ /* Stopped using Atmel flash after 0.03-38 */
++ if (fpga_ver < 39)
++ card->atmel_flash = 1;
++ else
++ card->atmel_flash = 0;
++
++ data32 = ioread32(card->config_regs + PORTS);
++ card->nr_ports = (data32 & 0x000000FF);
++
+ if (card->fpga_version >= DMA_SUPPORTED) {
+ pci_set_master(dev);
+ card->using_dma = 1;
++ if (1) { /* All known FPGA versions so far */
++ card->dma_alignment = 3;
++ card->dma_bounce = kmalloc(card->nr_ports * BUF_SIZE, GFP_KERNEL);
++ if (!card->dma_bounce) {
++ dev_warn(&card->dev->dev, "Failed to allocate DMA bounce buffers\n");
++ /* Fallback to MMIO doesn't work */
++ goto out_unmap_both;
++ }
++ }
+ } else {
+ card->using_dma = 0;
+ /* Set RX empty flag for all ports */
+ iowrite32(0xF0, card->config_regs + FLAGS_ADDR);
+ }
+
+- data32 = ioread32(card->config_regs + PORTS);
+- card->nr_ports = (data32 & 0x000000FF);
+-
+ pci_set_drvdata(dev, card);
+
+ tasklet_init(&card->tlet, solos_bh, (unsigned long)card);
+@@ -1181,6 +1325,10 @@ static int fpga_probe(struct pci_dev *de
+ if (err)
+ goto out_free_irq;
+
++ if (card->fpga_version >= DMA_SUPPORTED &&
++ sysfs_create_group(&card->dev->dev.kobj, &gpio_attr_group))
++ dev_err(&card->dev->dev, "Could not register parameter group for GPIOs\n");
++
+ return 0;
+
+ out_free_irq:
+@@ -1189,6 +1337,7 @@ static int fpga_probe(struct pci_dev *de
+ tasklet_kill(&card->tlet);
+
+ out_unmap_both:
++ kfree(card->dma_bounce);
+ pci_set_drvdata(dev, NULL);
+ pci_iounmap(dev, card->buffers);
+ out_unmap_config:
+@@ -1291,11 +1440,16 @@ static void fpga_remove(struct pci_dev *
+ iowrite32(1, card->config_regs + FPGA_MODE);
+ (void)ioread32(card->config_regs + FPGA_MODE);
+
++ if (card->fpga_version >= DMA_SUPPORTED)
++ sysfs_remove_group(&card->dev->dev.kobj, &gpio_attr_group);
++
+ atm_remove(card);
+
+ free_irq(dev->irq, card);
+ tasklet_kill(&card->tlet);
+
++ kfree(card->dma_bounce);
++
+ /* Release device from reset */
+ iowrite32(0, card->config_regs + FPGA_MODE);
+ (void)ioread32(card->config_regs + FPGA_MODE);
diff --git a/target/linux/generic/patches-3.7/203-kallsyms_uncompressed.patch b/target/linux/generic/patches-3.7/203-kallsyms_uncompressed.patch
new file mode 100644
index 000000000..c3da46c07
--- /dev/null
+++ b/target/linux/generic/patches-3.7/203-kallsyms_uncompressed.patch
@@ -0,0 +1,108 @@
+--- a/scripts/kallsyms.c
++++ b/scripts/kallsyms.c
+@@ -54,6 +54,7 @@ static struct text_range text_ranges[] =
+ static struct sym_entry *table;
+ static unsigned int table_size, table_cnt;
+ static int all_symbols = 0;
++static int uncompressed = 0;
+ static char symbol_prefix_char = '\0';
+
+ int token_profit[0x10000];
+@@ -360,6 +361,9 @@ static void write_src(void)
+
+ free(markers);
+
++ if (uncompressed)
++ return;
++
+ output_label("kallsyms_token_table");
+ off = 0;
+ for (i = 0; i < 256; i++) {
+@@ -418,6 +422,9 @@ static void *find_token(unsigned char *s
+ {
+ int i;
+
++ if (uncompressed)
++ return NULL;
++
+ for (i = 0; i < len - 1; i++) {
+ if (str[i] == token[0] && str[i+1] == token[1])
+ return &str[i];
+@@ -490,6 +497,9 @@ static void optimize_result(void)
+ {
+ int i, best;
+
++ if (uncompressed)
++ return;
++
+ /* using the '\0' symbol last allows compress_symbols to use standard
+ * fast string functions */
+ for (i = 255; i >= 0; i--) {
+@@ -646,7 +656,9 @@ int main(int argc, char **argv)
+ if ((*p == '"' && *(p+2) == '"') || (*p == '\'' && *(p+2) == '\''))
+ p++;
+ symbol_prefix_char = *p;
+- } else
++ } else if (strcmp(argv[i], "--uncompressed") == 0)
++ uncompressed = 1;
++ else
+ usage();
+ }
+ } else if (argc != 1)
+--- a/init/Kconfig
++++ b/init/Kconfig
+@@ -1194,6 +1194,17 @@ config KALLSYMS_ALL
+
+ Say N unless you really need all symbols.
+
++config KALLSYMS_UNCOMPRESSED
++ bool "Keep kallsyms uncompressed"
++ depends on KALLSYMS
++ help
++ Normally kallsyms contains compressed symbols (using a token table),
++ reducing the uncompressed kernel image size. Keeping the symbol table
++ uncompressed significantly improves the size of this part in compressed
++ kernel images.
++
++ Say N unless you need compressed kernel images to be small.
++
+ config HOTPLUG
+ def_bool y
+
+--- a/scripts/link-vmlinux.sh
++++ b/scripts/link-vmlinux.sh
+@@ -83,6 +83,10 @@ kallsyms()
+ kallsymopt="${kallsymopt} --all-symbols"
+ fi
+
++ if [ -n "${CONFIG_KALLSYMS_UNCOMPRESSED}" ]; then
++ kallsymopt="${kallsymopt} --uncompressed"
++ fi
++
+ local aflags="${KBUILD_AFLAGS} ${KBUILD_AFLAGS_KERNEL} \
+ ${NOSTDINC_FLAGS} ${LINUXINCLUDE} ${KBUILD_CPPFLAGS}"
+
+--- a/kernel/kallsyms.c
++++ b/kernel/kallsyms.c
+@@ -106,6 +106,11 @@ static unsigned int kallsyms_expand_symb
+ * For every byte on the compressed symbol data, copy the table
+ * entry for that byte.
+ */
++#ifdef CONFIG_KALLSYMS_UNCOMPRESSED
++ memcpy(result, data + 1, len - 1);
++ result += len - 1;
++ len = 0;
++#endif
+ while (len) {
+ tptr = &kallsyms_token_table[kallsyms_token_index[*data]];
+ data++;
+@@ -133,6 +138,9 @@ static unsigned int kallsyms_expand_symb
+ */
+ static char kallsyms_get_symbol_type(unsigned int off)
+ {
++#ifdef CONFIG_KALLSYMS_UNCOMPRESSED
++ return kallsyms_names[off + 1];
++#endif
+ /*
+ * Get just the first code, look it up in the token table,
+ * and return the first char from this token.
diff --git a/target/linux/generic/patches-3.7/220-gc_sections.patch b/target/linux/generic/patches-3.7/220-gc_sections.patch
new file mode 100644
index 000000000..bdafdfe9c
--- /dev/null
+++ b/target/linux/generic/patches-3.7/220-gc_sections.patch
@@ -0,0 +1,372 @@
+--- a/arch/mips/Makefile
++++ b/arch/mips/Makefile
+@@ -89,10 +89,12 @@ all-$(CONFIG_SYS_SUPPORTS_ZBOOT)+= vmlin
+ #
+ cflags-y += -G 0 -mno-abicalls -fno-pic -pipe
+ cflags-y += -msoft-float
+-LDFLAGS_vmlinux += -G 0 -static -n -nostdlib
++LDFLAGS_vmlinux += -G 0 -static -n -nostdlib --gc-sections
+ KBUILD_AFLAGS_MODULE += -mlong-calls
+ KBUILD_CFLAGS_MODULE += -mlong-calls
+
++KBUILD_CFLAGS_KERNEL += -ffunction-sections -fdata-sections
++
+ cflags-y += -ffreestanding
+
+ #
+--- a/arch/mips/kernel/vmlinux.lds.S
++++ b/arch/mips/kernel/vmlinux.lds.S
+@@ -66,7 +66,7 @@ SECTIONS
+ /* Exception table for data bus errors */
+ __dbe_table : {
+ __start___dbe_table = .;
+- *(__dbe_table)
++ KEEP(*(__dbe_table))
+ __stop___dbe_table = .;
+ }
+
+@@ -111,7 +111,7 @@ SECTIONS
+ . = ALIGN(4);
+ .mips.machines.init : AT(ADDR(.mips.machines.init) - LOAD_OFFSET) {
+ __mips_machines_start = .;
+- *(.mips.machines.init)
++ KEEP(*(.mips.machines.init))
+ __mips_machines_end = .;
+ }
+
+--- a/include/asm-generic/vmlinux.lds.h
++++ b/include/asm-generic/vmlinux.lds.h
+@@ -101,7 +101,7 @@
+ #ifdef CONFIG_FTRACE_MCOUNT_RECORD
+ #define MCOUNT_REC() . = ALIGN(8); \
+ VMLINUX_SYMBOL(__start_mcount_loc) = .; \
+- *(__mcount_loc) \
++ KEEP(*(__mcount_loc)) \
+ VMLINUX_SYMBOL(__stop_mcount_loc) = .;
+ #else
+ #define MCOUNT_REC()
+@@ -109,7 +109,7 @@
+
+ #ifdef CONFIG_TRACE_BRANCH_PROFILING
+ #define LIKELY_PROFILE() VMLINUX_SYMBOL(__start_annotated_branch_profile) = .; \
+- *(_ftrace_annotated_branch) \
++ KEEP(*(_ftrace_annotated_branch)) \
+ VMLINUX_SYMBOL(__stop_annotated_branch_profile) = .;
+ #else
+ #define LIKELY_PROFILE()
+@@ -117,7 +117,7 @@
+
+ #ifdef CONFIG_PROFILE_ALL_BRANCHES
+ #define BRANCH_PROFILE() VMLINUX_SYMBOL(__start_branch_profile) = .; \
+- *(_ftrace_branch) \
++ KEEP(*(_ftrace_branch)) \
+ VMLINUX_SYMBOL(__stop_branch_profile) = .;
+ #else
+ #define BRANCH_PROFILE()
+@@ -126,7 +126,7 @@
+ #ifdef CONFIG_EVENT_TRACING
+ #define FTRACE_EVENTS() . = ALIGN(8); \
+ VMLINUX_SYMBOL(__start_ftrace_events) = .; \
+- *(_ftrace_events) \
++ KEEP(*(_ftrace_events)) \
+ VMLINUX_SYMBOL(__stop_ftrace_events) = .;
+ #else
+ #define FTRACE_EVENTS()
+@@ -134,7 +134,7 @@
+
+ #ifdef CONFIG_TRACING
+ #define TRACE_PRINTKS() VMLINUX_SYMBOL(__start___trace_bprintk_fmt) = .; \
+- *(__trace_printk_fmt) /* Trace_printk fmt' pointer */ \
++ KEEP(*(__trace_printk_fmt)) /* Trace_printk fmt' pointer */ \
+ VMLINUX_SYMBOL(__stop___trace_bprintk_fmt) = .;
+ #else
+ #define TRACE_PRINTKS()
+@@ -143,7 +143,7 @@
+ #ifdef CONFIG_FTRACE_SYSCALLS
+ #define TRACE_SYSCALLS() . = ALIGN(8); \
+ VMLINUX_SYMBOL(__start_syscalls_metadata) = .; \
+- *(__syscalls_metadata) \
++ KEEP(*(__syscalls_metadata)) \
+ VMLINUX_SYMBOL(__stop_syscalls_metadata) = .;
+ #else
+ #define TRACE_SYSCALLS()
+@@ -153,7 +153,7 @@
+ #define KERNEL_DTB() \
+ STRUCT_ALIGN(); \
+ VMLINUX_SYMBOL(__dtb_start) = .; \
+- *(.dtb.init.rodata) \
++ KEEP(*(.dtb.init.rodata)) \
+ VMLINUX_SYMBOL(__dtb_end) = .;
+
+ /* .data section */
+@@ -173,15 +173,16 @@
+ /* implement dynamic printk debug */ \
+ . = ALIGN(8); \
+ VMLINUX_SYMBOL(__start___jump_table) = .; \
+- *(__jump_table) \
++ KEEP(*(__jump_table)) \
+ VMLINUX_SYMBOL(__stop___jump_table) = .; \
+ . = ALIGN(8); \
+ VMLINUX_SYMBOL(__start___verbose) = .; \
+- *(__verbose) \
++ KEEP(*(__verbose)) \
+ VMLINUX_SYMBOL(__stop___verbose) = .; \
+ LIKELY_PROFILE() \
+ BRANCH_PROFILE() \
+- TRACE_PRINTKS()
++ TRACE_PRINTKS() \
++ *(.data.[a-zA-Z_]*)
+
+ /*
+ * Data section helpers
+@@ -235,39 +236,39 @@
+ /* PCI quirks */ \
+ .pci_fixup : AT(ADDR(.pci_fixup) - LOAD_OFFSET) { \
+ VMLINUX_SYMBOL(__start_pci_fixups_early) = .; \
+- *(.pci_fixup_early) \
++ KEEP(*(.pci_fixup_early)) \
+ VMLINUX_SYMBOL(__end_pci_fixups_early) = .; \
+ VMLINUX_SYMBOL(__start_pci_fixups_header) = .; \
+- *(.pci_fixup_header) \
++ KEEP(*(.pci_fixup_header)) \
+ VMLINUX_SYMBOL(__end_pci_fixups_header) = .; \
+ VMLINUX_SYMBOL(__start_pci_fixups_final) = .; \
+- *(.pci_fixup_final) \
++ KEEP(*(.pci_fixup_final)) \
+ VMLINUX_SYMBOL(__end_pci_fixups_final) = .; \
+ VMLINUX_SYMBOL(__start_pci_fixups_enable) = .; \
+- *(.pci_fixup_enable) \
++ KEEP(*(.pci_fixup_enable)) \
+ VMLINUX_SYMBOL(__end_pci_fixups_enable) = .; \
+ VMLINUX_SYMBOL(__start_pci_fixups_resume) = .; \
+- *(.pci_fixup_resume) \
++ KEEP(*(.pci_fixup_resume)) \
+ VMLINUX_SYMBOL(__end_pci_fixups_resume) = .; \
+ VMLINUX_SYMBOL(__start_pci_fixups_resume_early) = .; \
+- *(.pci_fixup_resume_early) \
++ KEEP(*(.pci_fixup_resume_early)) \
+ VMLINUX_SYMBOL(__end_pci_fixups_resume_early) = .; \
+ VMLINUX_SYMBOL(__start_pci_fixups_suspend) = .; \
+- *(.pci_fixup_suspend) \
++ KEEP(*(.pci_fixup_suspend)) \
+ VMLINUX_SYMBOL(__end_pci_fixups_suspend) = .; \
+ } \
+ \
+ /* Built-in firmware blobs */ \
+ .builtin_fw : AT(ADDR(.builtin_fw) - LOAD_OFFSET) { \
+ VMLINUX_SYMBOL(__start_builtin_fw) = .; \
+- *(.builtin_fw) \
++ KEEP(*(.builtin_fw)) \
+ VMLINUX_SYMBOL(__end_builtin_fw) = .; \
+ } \
+ \
+ /* RapidIO route ops */ \
+ .rio_ops : AT(ADDR(.rio_ops) - LOAD_OFFSET) { \
+ VMLINUX_SYMBOL(__start_rio_switch_ops) = .; \
+- *(.rio_switch_ops) \
++ KEEP(*(.rio_switch_ops)) \
+ VMLINUX_SYMBOL(__end_rio_switch_ops) = .; \
+ } \
+ \
+@@ -276,49 +277,49 @@
+ /* Kernel symbol table: Normal symbols */ \
+ __ksymtab : AT(ADDR(__ksymtab) - LOAD_OFFSET) { \
+ VMLINUX_SYMBOL(__start___ksymtab) = .; \
+- *(SORT(___ksymtab+*)) \
++ KEEP(*(SORT(___ksymtab+*))) \
+ VMLINUX_SYMBOL(__stop___ksymtab) = .; \
+ } \
+ \
+ /* Kernel symbol table: GPL-only symbols */ \
+ __ksymtab_gpl : AT(ADDR(__ksymtab_gpl) - LOAD_OFFSET) { \
+ VMLINUX_SYMBOL(__start___ksymtab_gpl) = .; \
+- *(SORT(___ksymtab_gpl+*)) \
++ KEEP(*(SORT(___ksymtab_gpl+*))) \
+ VMLINUX_SYMBOL(__stop___ksymtab_gpl) = .; \
+ } \
+ \
+ /* Kernel symbol table: Normal unused symbols */ \
+ __ksymtab_unused : AT(ADDR(__ksymtab_unused) - LOAD_OFFSET) { \
+ VMLINUX_SYMBOL(__start___ksymtab_unused) = .; \
+- *(SORT(___ksymtab_unused+*)) \
++ KEEP(*(SORT(___ksymtab_unused+*))) \
+ VMLINUX_SYMBOL(__stop___ksymtab_unused) = .; \
+ } \
+ \
+ /* Kernel symbol table: GPL-only unused symbols */ \
+ __ksymtab_unused_gpl : AT(ADDR(__ksymtab_unused_gpl) - LOAD_OFFSET) { \
+ VMLINUX_SYMBOL(__start___ksymtab_unused_gpl) = .; \
+- *(SORT(___ksymtab_unused_gpl+*)) \
++ KEEP(*(SORT(___ksymtab_unused_gpl+*))) \
+ VMLINUX_SYMBOL(__stop___ksymtab_unused_gpl) = .; \
+ } \
+ \
+ /* Kernel symbol table: GPL-future-only symbols */ \
+ __ksymtab_gpl_future : AT(ADDR(__ksymtab_gpl_future) - LOAD_OFFSET) { \
+ VMLINUX_SYMBOL(__start___ksymtab_gpl_future) = .; \
+- *(SORT(___ksymtab_gpl_future+*)) \
++ KEEP(*(SORT(___ksymtab_gpl_future+*))) \
+ VMLINUX_SYMBOL(__stop___ksymtab_gpl_future) = .; \
+ } \
+ \
+ /* Kernel symbol table: Normal symbols */ \
+ __kcrctab : AT(ADDR(__kcrctab) - LOAD_OFFSET) { \
+ VMLINUX_SYMBOL(__start___kcrctab) = .; \
+- *(SORT(___kcrctab+*)) \
++ KEEP(*(SORT(___kcrctab+*))) \
+ VMLINUX_SYMBOL(__stop___kcrctab) = .; \
+ } \
+ \
+ /* Kernel symbol table: GPL-only symbols */ \
+ __kcrctab_gpl : AT(ADDR(__kcrctab_gpl) - LOAD_OFFSET) { \
+ VMLINUX_SYMBOL(__start___kcrctab_gpl) = .; \
+- *(SORT(___kcrctab_gpl+*)) \
++ KEEP(*(SORT(___kcrctab_gpl+*))) \
+ VMLINUX_SYMBOL(__stop___kcrctab_gpl) = .; \
+ } \
+ \
+@@ -332,14 +333,14 @@
+ /* Kernel symbol table: GPL-only unused symbols */ \
+ __kcrctab_unused_gpl : AT(ADDR(__kcrctab_unused_gpl) - LOAD_OFFSET) { \
+ VMLINUX_SYMBOL(__start___kcrctab_unused_gpl) = .; \
+- *(SORT(___kcrctab_unused_gpl+*)) \
++ KEEP(*(SORT(___kcrctab_unused_gpl+*))) \
+ VMLINUX_SYMBOL(__stop___kcrctab_unused_gpl) = .; \
+ } \
+ \
+ /* Kernel symbol table: GPL-future-only symbols */ \
+ __kcrctab_gpl_future : AT(ADDR(__kcrctab_gpl_future) - LOAD_OFFSET) { \
+ VMLINUX_SYMBOL(__start___kcrctab_gpl_future) = .; \
+- *(SORT(___kcrctab_gpl_future+*)) \
++ KEEP(*(SORT(___kcrctab_gpl_future+*))) \
+ VMLINUX_SYMBOL(__stop___kcrctab_gpl_future) = .; \
+ } \
+ \
+@@ -362,14 +363,14 @@
+ /* Built-in module parameters. */ \
+ __param : AT(ADDR(__param) - LOAD_OFFSET) { \
+ VMLINUX_SYMBOL(__start___param) = .; \
+- *(__param) \
++ KEEP(*(__param)) \
+ VMLINUX_SYMBOL(__stop___param) = .; \
+ } \
+ \
+ /* Built-in module versions. */ \
+ __modver : AT(ADDR(__modver) - LOAD_OFFSET) { \
+ VMLINUX_SYMBOL(__start___modver) = .; \
+- *(__modver) \
++ KEEP(*(__modver)) \
+ VMLINUX_SYMBOL(__stop___modver) = .; \
+ . = ALIGN((align)); \
+ VMLINUX_SYMBOL(__end_rodata) = .; \
+@@ -429,7 +430,7 @@
+ #define ENTRY_TEXT \
+ ALIGN_FUNCTION(); \
+ VMLINUX_SYMBOL(__entry_text_start) = .; \
+- *(.entry.text) \
++ KEEP(*(.entry.text)) \
+ VMLINUX_SYMBOL(__entry_text_end) = .;
+
+ #ifdef CONFIG_FUNCTION_GRAPH_TRACER
+@@ -457,7 +458,7 @@
+ . = ALIGN(align); \
+ __ex_table : AT(ADDR(__ex_table) - LOAD_OFFSET) { \
+ VMLINUX_SYMBOL(__start___ex_table) = .; \
+- *(__ex_table) \
++ KEEP(*(__ex_table)) \
+ VMLINUX_SYMBOL(__stop___ex_table) = .; \
+ }
+
+@@ -473,7 +474,7 @@
+ #ifdef CONFIG_CONSTRUCTORS
+ #define KERNEL_CTORS() . = ALIGN(8); \
+ VMLINUX_SYMBOL(__ctors_start) = .; \
+- *(.ctors) \
++ KEEP(*(.ctors)) \
+ VMLINUX_SYMBOL(__ctors_end) = .;
+ #else
+ #define KERNEL_CTORS()
+@@ -526,7 +527,7 @@
+ #define SBSS(sbss_align) \
+ . = ALIGN(sbss_align); \
+ .sbss : AT(ADDR(.sbss) - LOAD_OFFSET) { \
+- *(.sbss) \
++ *(.sbss .sbss.*) \
+ *(.scommon) \
+ }
+
+@@ -544,7 +545,7 @@
+ BSS_FIRST_SECTIONS \
+ *(.bss..page_aligned) \
+ *(.dynbss) \
+- *(.bss) \
++ *(.bss .bss.*) \
+ *(COMMON) \
+ }
+
+@@ -593,7 +594,7 @@
+ . = ALIGN(8); \
+ __bug_table : AT(ADDR(__bug_table) - LOAD_OFFSET) { \
+ VMLINUX_SYMBOL(__start___bug_table) = .; \
+- *(__bug_table) \
++ KEEP(*(__bug_table)) \
+ VMLINUX_SYMBOL(__stop___bug_table) = .; \
+ }
+ #else
+@@ -605,7 +606,7 @@
+ . = ALIGN(4); \
+ .tracedata : AT(ADDR(.tracedata) - LOAD_OFFSET) { \
+ VMLINUX_SYMBOL(__tracedata_start) = .; \
+- *(.tracedata) \
++ KEEP(*(.tracedata)) \
+ VMLINUX_SYMBOL(__tracedata_end) = .; \
+ }
+ #else
+@@ -622,17 +623,17 @@
+ #define INIT_SETUP(initsetup_align) \
+ . = ALIGN(initsetup_align); \
+ VMLINUX_SYMBOL(__setup_start) = .; \
+- *(.init.setup) \
++ KEEP(*(.init.setup)) \
+ VMLINUX_SYMBOL(__setup_end) = .;
+
+ #define INIT_CALLS_LEVEL(level) \
+ VMLINUX_SYMBOL(__initcall##level##_start) = .; \
+- *(.initcall##level##.init) \
+- *(.initcall##level##s.init) \
++ KEEP(*(.initcall##level##.init)) \
++ KEEP(*(.initcall##level##s.init)) \
+
+ #define INIT_CALLS \
+ VMLINUX_SYMBOL(__initcall_start) = .; \
+- *(.initcallearly.init) \
++ KEEP(*(.initcallearly.init)) \
+ INIT_CALLS_LEVEL(0) \
+ INIT_CALLS_LEVEL(1) \
+ INIT_CALLS_LEVEL(2) \
+@@ -646,21 +647,21 @@
+
+ #define CON_INITCALL \
+ VMLINUX_SYMBOL(__con_initcall_start) = .; \
+- *(.con_initcall.init) \
++ KEEP(*(.con_initcall.init)) \
+ VMLINUX_SYMBOL(__con_initcall_end) = .;
+
+ #define SECURITY_INITCALL \
+ VMLINUX_SYMBOL(__security_initcall_start) = .; \
+- *(.security_initcall.init) \
++ KEEP(*(.security_initcall.init)) \
+ VMLINUX_SYMBOL(__security_initcall_end) = .;
+
+ #ifdef CONFIG_BLK_DEV_INITRD
+ #define INIT_RAM_FS \
+ . = ALIGN(4); \
+ VMLINUX_SYMBOL(__initramfs_start) = .; \
+- *(.init.ramfs) \
++ KEEP(*(.init.ramfs)) \
+ . = ALIGN(8); \
+- *(.init.ramfs.info)
++ KEEP(*(.init.ramfs.info))
+ #else
+ #define INIT_RAM_FS
+ #endif
diff --git a/target/linux/generic/patches-3.7/220-module_exports.patch b/target/linux/generic/patches-3.7/221-module_exports.patch
index fc382c16f..da08de626 100644
--- a/target/linux/generic/patches-3.7/220-module_exports.patch
+++ b/target/linux/generic/patches-3.7/221-module_exports.patch
@@ -1,29 +1,27 @@
--- a/include/asm-generic/vmlinux.lds.h
+++ b/include/asm-generic/vmlinux.lds.h
-@@ -52,6 +52,18 @@
+@@ -52,6 +52,16 @@
#define LOAD_OFFSET 0
#endif
-+#ifndef SYMTAB_KEEP_STR
-+#define SYMTAB_KEEP *(SORT(___ksymtab+*))
-+#define SYMTAB_KEEP_GPL *(SORT(___ksymtab_gpl+*))
-+#define SYMTAB_KEEP_STR *(__ksymtab_strings+*)
++#ifndef SYMTAB_KEEP
++#define SYMTAB_KEEP KEEP(*(SORT(___ksymtab+*)))
++#define SYMTAB_KEEP_GPL KEEP(*(SORT(___ksymtab_gpl+*)))
+#endif
+
+#ifndef SYMTAB_DISCARD
+#define SYMTAB_DISCARD
+#define SYMTAB_DISCARD_GPL
-+#define SYMTAB_DISCARD_STR
+#endif
+
#ifndef SYMBOL_PREFIX
#define VMLINUX_SYMBOL(sym) sym
#else
-@@ -276,14 +288,14 @@
+@@ -277,14 +287,14 @@
/* Kernel symbol table: Normal symbols */ \
__ksymtab : AT(ADDR(__ksymtab) - LOAD_OFFSET) { \
VMLINUX_SYMBOL(__start___ksymtab) = .; \
-- *(SORT(___ksymtab+*)) \
+- KEEP(*(SORT(___ksymtab+*))) \
+ SYMTAB_KEEP \
VMLINUX_SYMBOL(__stop___ksymtab) = .; \
} \
@@ -31,30 +29,40 @@
/* Kernel symbol table: GPL-only symbols */ \
__ksymtab_gpl : AT(ADDR(__ksymtab_gpl) - LOAD_OFFSET) { \
VMLINUX_SYMBOL(__start___ksymtab_gpl) = .; \
-- *(SORT(___ksymtab_gpl+*)) \
+- KEEP(*(SORT(___ksymtab_gpl+*))) \
+ SYMTAB_KEEP_GPL \
VMLINUX_SYMBOL(__stop___ksymtab_gpl) = .; \
} \
\
-@@ -345,7 +357,7 @@
+@@ -346,7 +356,7 @@
\
/* Kernel symbol table: strings */ \
__ksymtab_strings : AT(ADDR(__ksymtab_strings) - LOAD_OFFSET) { \
- *(__ksymtab_strings) \
-+ SYMTAB_KEEP_STR \
++ *(__ksymtab_strings+*) \
} \
\
/* __*init sections */ \
-@@ -679,6 +691,9 @@
+@@ -680,6 +690,8 @@
EXIT_TEXT \
EXIT_DATA \
EXIT_CALL \
+ SYMTAB_DISCARD \
+ SYMTAB_DISCARD_GPL \
-+ SYMTAB_DISCARD_STR \
*(.discard) \
*(.discard.*) \
}
+--- a/scripts/Makefile.build
++++ b/scripts/Makefile.build
+@@ -348,7 +348,7 @@ targets += $(extra-y) $(MAKECMDGOALS) $(
+ # Linker scripts preprocessor (.lds.S -> .lds)
+ # ---------------------------------------------------------------------------
+ quiet_cmd_cpp_lds_S = LDS $@
+- cmd_cpp_lds_S = $(CPP) $(cpp_flags) -P -C -U$(ARCH) \
++ cmd_cpp_lds_S = $(CPP) $(EXTRA_LDSFLAGS) $(cpp_flags) -P -C -U$(ARCH) \
+ -D__ASSEMBLY__ -DLINKER_SCRIPT -o $@ $<
+
+ $(obj)/%.lds: $(src)/%.lds.S FORCE
--- a/include/linux/export.h
+++ b/include/linux/export.h
@@ -45,12 +45,19 @@ extern struct module __this_module;
@@ -78,14 +86,3 @@
= MODULE_SYMBOL_PREFIX #sym; \
static const struct kernel_symbol __ksymtab_##sym \
__used \
---- a/scripts/Makefile.build
-+++ b/scripts/Makefile.build
-@@ -348,7 +348,7 @@ targets += $(extra-y) $(MAKECMDGOALS) $(
- # Linker scripts preprocessor (.lds.S -> .lds)
- # ---------------------------------------------------------------------------
- quiet_cmd_cpp_lds_S = LDS $@
-- cmd_cpp_lds_S = $(CPP) $(cpp_flags) -P -C -U$(ARCH) \
-+ cmd_cpp_lds_S = $(CPP) $(EXTRA_LDSFLAGS) $(cpp_flags) -P -C -U$(ARCH) \
- -D__ASSEMBLY__ -DLINKER_SCRIPT -o $@ $<
-
- $(obj)/%.lds: $(src)/%.lds.S FORCE
diff --git a/target/linux/generic/patches-3.7/250-netfilter_depends.patch b/target/linux/generic/patches-3.7/250-netfilter_depends.patch
index 3c9013400..218df4cfb 100644
--- a/target/linux/generic/patches-3.7/250-netfilter_depends.patch
+++ b/target/linux/generic/patches-3.7/250-netfilter_depends.patch
@@ -8,7 +8,7 @@
depends on NETFILTER_ADVANCED
help
H.323 is a VoIP signalling protocol from ITU-T. As one of the most
-@@ -750,7 +749,6 @@ config NETFILTER_XT_TARGET_SECMARK
+@@ -757,7 +756,6 @@ config NETFILTER_XT_TARGET_SECMARK
config NETFILTER_XT_TARGET_TCPMSS
tristate '"TCPMSS" target support'
diff --git a/target/linux/generic/patches-3.7/251-sound_kconfig.patch b/target/linux/generic/patches-3.7/251-sound_kconfig.patch
index f374009a6..916363c81 100644
--- a/target/linux/generic/patches-3.7/251-sound_kconfig.patch
+++ b/target/linux/generic/patches-3.7/251-sound_kconfig.patch
@@ -1,6 +1,6 @@
--- a/sound/core/Kconfig
+++ b/sound/core/Kconfig
-@@ -7,7 +7,7 @@ config SND_PCM
+@@ -7,13 +7,13 @@ config SND_PCM
select SND_TIMER
config SND_HWDEP
@@ -9,3 +9,10 @@
config SND_RAWMIDI
tristate
+
+ config SND_COMPRESS_OFFLOAD
+- tristate
++ tristate "Compression offloading support"
+
+ # To be effective this also requires INPUT - users should say:
+ # select SND_JACK if INPUT=y || INPUT=SND
diff --git a/target/linux/generic/patches-3.7/259-regmap_dynamic.patch b/target/linux/generic/patches-3.7/259-regmap_dynamic.patch
new file mode 100644
index 000000000..6da165eef
--- /dev/null
+++ b/target/linux/generic/patches-3.7/259-regmap_dynamic.patch
@@ -0,0 +1,72 @@
+--- a/drivers/base/regmap/Kconfig
++++ b/drivers/base/regmap/Kconfig
+@@ -3,20 +3,24 @@
+ # subsystems should select the appropriate symbols.
+
+ config REGMAP
+- default y if (REGMAP_I2C || REGMAP_SPI || REGMAP_MMIO || REGMAP_IRQ)
+ select LZO_COMPRESS
+ select LZO_DECOMPRESS
+ select IRQ_DOMAIN if REGMAP_IRQ
+- bool
++ tristate "Regmap"
+
+ config REGMAP_I2C
+- tristate
++ select REGMAP
++ tristate "Regmap I2C"
+
+ config REGMAP_SPI
+- tristate
++ select REGMAP
++ depends on SPI_MASTER
++ tristate "Regmap SPI"
+
+ config REGMAP_MMIO
++ select REGMAP
+ tristate
+
+ config REGMAP_IRQ
++ select REGMAP
+ bool
+--- a/include/linux/regmap.h
++++ b/include/linux/regmap.h
+@@ -43,7 +43,7 @@ struct reg_default {
+ unsigned int def;
+ };
+
+-#ifdef CONFIG_REGMAP
++#if IS_ENABLED(CONFIG_REGMAP)
+
+ enum regmap_endian {
+ /* Unspecified -> 0 -> Backwards compatible default */
+--- a/drivers/base/regmap/Makefile
++++ b/drivers/base/regmap/Makefile
+@@ -1,6 +1,8 @@
+-obj-$(CONFIG_REGMAP) += regmap.o regcache.o
+-obj-$(CONFIG_REGMAP) += regcache-rbtree.o regcache-lzo.o
+-obj-$(CONFIG_DEBUG_FS) += regmap-debugfs.o
++regmap-core-objs = regmap.o regcache.o regcache-rbtree.o regcache-lzo.o
++ifdef CONFIG_DEBUG_FS
++regmap-core-objs += regmap-debugfs.o
++endif
++obj-$(CONFIG_REGMAP) += regmap-core.o
+ obj-$(CONFIG_REGMAP_I2C) += regmap-i2c.o
+ obj-$(CONFIG_REGMAP_SPI) += regmap-spi.o
+ obj-$(CONFIG_REGMAP_MMIO) += regmap-mmio.o
+--- a/drivers/base/regmap/regmap.c
++++ b/drivers/base/regmap/regmap.c
+@@ -13,6 +13,7 @@
+ #include <linux/device.h>
+ #include <linux/slab.h>
+ #include <linux/export.h>
++#include <linux/module.h>
+ #include <linux/mutex.h>
+ #include <linux/err.h>
+ #include <linux/rbtree.h>
+@@ -1413,3 +1414,5 @@ static int __init regmap_initcall(void)
+ return 0;
+ }
+ postcore_initcall(regmap_initcall);
++
++MODULE_LICENSE("GPL");
diff --git a/target/linux/generic/patches-3.7/260-crypto_test_dependencies.patch b/target/linux/generic/patches-3.7/260-crypto_test_dependencies.patch
new file mode 100644
index 000000000..8cc15e470
--- /dev/null
+++ b/target/linux/generic/patches-3.7/260-crypto_test_dependencies.patch
@@ -0,0 +1,37 @@
+--- a/crypto/Kconfig
++++ b/crypto/Kconfig
+@@ -95,10 +95,10 @@ config CRYPTO_MANAGER
+
+ config CRYPTO_MANAGER2
+ def_tristate CRYPTO_MANAGER || (CRYPTO_MANAGER!=n && CRYPTO_ALGAPI=y)
+- select CRYPTO_AEAD2
+- select CRYPTO_HASH2
+- select CRYPTO_BLKCIPHER2
+- select CRYPTO_PCOMP2
++ select CRYPTO_AEAD2 if !CRYPTO_MANAGER_DISABLE_TESTS
++ select CRYPTO_HASH2 if !CRYPTO_MANAGER_DISABLE_TESTS
++ select CRYPTO_BLKCIPHER2 if !CRYPTO_MANAGER_DISABLE_TESTS
++ select CRYPTO_PCOMP2 if !CRYPTO_MANAGER_DISABLE_TESTS
+
+ config CRYPTO_USER
+ tristate "Userspace cryptographic algorithm configuration"
+--- a/crypto/algboss.c
++++ b/crypto/algboss.c
+@@ -247,6 +247,9 @@ static int cryptomgr_schedule_test(struc
+ type = alg->cra_flags;
+
+ /* This piece of crap needs to disappear into per-type test hooks. */
++#ifdef CONFIG_CRYPTO_MANAGER_DISABLE_TESTS
++ type |= CRYPTO_ALG_TESTED;
++#else
+ if ((!((type ^ CRYPTO_ALG_TYPE_BLKCIPHER) &
+ CRYPTO_ALG_TYPE_BLKCIPHER_MASK) && !(type & CRYPTO_ALG_GENIV) &&
+ ((alg->cra_flags & CRYPTO_ALG_TYPE_MASK) ==
+@@ -255,6 +258,7 @@ static int cryptomgr_schedule_test(struc
+ (!((type ^ CRYPTO_ALG_TYPE_AEAD) & CRYPTO_ALG_TYPE_MASK) &&
+ alg->cra_type == &crypto_nivaead_type && alg->cra_aead.ivsize))
+ type |= CRYPTO_ALG_TESTED;
++#endif
+
+ param->type = type;
+
diff --git a/target/linux/generic/patches-3.7/261-move_bcm963xx_tag.patch b/target/linux/generic/patches-3.7/261-move_bcm963xx_tag.patch
new file mode 100644
index 000000000..7e465f04a
--- /dev/null
+++ b/target/linux/generic/patches-3.7/261-move_bcm963xx_tag.patch
@@ -0,0 +1,233 @@
+From b00c6f1a96a2cee4b9e63a8aa4f10ed0473f437b Mon Sep 17 00:00:00 2001
+From: Jonas Gorski <jogo@openwrt.org>
+Date: Tue, 29 Jan 2013 10:24:12 +0100
+Subject: [PATCH 001/118] MIPS: BCM63XX: export bcm63xx tag to userspace
+
+---
+ arch/mips/include/asm/mach-bcm63xx/bcm963xx_tag.h | 96 ---------------------
+ drivers/mtd/bcm63xxpart.c | 2 +-
+ include/uapi/linux/Kbuild | 1 +
+ include/uapi/linux/bcm963xx_tag.h | 96 +++++++++++++++++++++
+ 4 files changed, 98 insertions(+), 97 deletions(-)
+ delete mode 100644 arch/mips/include/asm/mach-bcm63xx/bcm963xx_tag.h
+ create mode 100644 include/uapi/linux/bcm963xx_tag.h
+
+--- a/arch/mips/include/asm/mach-bcm63xx/bcm963xx_tag.h
++++ /dev/null
+@@ -1,96 +0,0 @@
+-#ifndef __BCM963XX_TAG_H
+-#define __BCM963XX_TAG_H
+-
+-#define TAGVER_LEN 4 /* Length of Tag Version */
+-#define TAGLAYOUT_LEN 4 /* Length of FlashLayoutVer */
+-#define SIG1_LEN 20 /* Company Signature 1 Length */
+-#define SIG2_LEN 14 /* Company Signature 2 Length */
+-#define BOARDID_LEN 16 /* Length of BoardId */
+-#define ENDIANFLAG_LEN 2 /* Endian Flag Length */
+-#define CHIPID_LEN 6 /* Chip Id Length */
+-#define IMAGE_LEN 10 /* Length of Length Field */
+-#define ADDRESS_LEN 12 /* Length of Address field */
+-#define DUALFLAG_LEN 2 /* Dual Image flag Length */
+-#define INACTIVEFLAG_LEN 2 /* Inactie Flag Length */
+-#define RSASIG_LEN 20 /* Length of RSA Signature in tag */
+-#define TAGINFO1_LEN 30 /* Length of vendor information field1 in tag */
+-#define FLASHLAYOUTVER_LEN 4 /* Length of Flash Layout Version String tag */
+-#define TAGINFO2_LEN 16 /* Length of vendor information field2 in tag */
+-#define ALTTAGINFO_LEN 54 /* Alternate length for vendor information; Pirelli */
+-
+-#define NUM_PIRELLI 2
+-#define IMAGETAG_CRC_START 0xFFFFFFFF
+-
+-#define PIRELLI_BOARDS { \
+- "AGPF-S0", \
+- "DWV-S0", \
+-}
+-
+-/*
+- * The broadcom firmware assumes the rootfs starts the image,
+- * therefore uses the rootfs start (flash_image_address)
+- * to determine where to flash the image. Since we have the kernel first
+- * we have to give it the kernel address, but the crc uses the length
+- * associated with this address (root_length), which is added to the kernel
+- * length (kernel_length) to determine the length of image to flash and thus
+- * needs to be rootfs + deadcode (jffs2 EOF marker)
+-*/
+-
+-struct bcm_tag {
+- /* 0-3: Version of the image tag */
+- char tag_version[TAGVER_LEN];
+- /* 4-23: Company Line 1 */
+- char sig_1[SIG1_LEN];
+- /* 24-37: Company Line 2 */
+- char sig_2[SIG2_LEN];
+- /* 38-43: Chip this image is for */
+- char chip_id[CHIPID_LEN];
+- /* 44-59: Board name */
+- char board_id[BOARDID_LEN];
+- /* 60-61: Map endianness -- 1 BE 0 LE */
+- char big_endian[ENDIANFLAG_LEN];
+- /* 62-71: Total length of image */
+- char total_length[IMAGE_LEN];
+- /* 72-83: Address in memory of CFE */
+- char cfe__address[ADDRESS_LEN];
+- /* 84-93: Size of CFE */
+- char cfe_length[IMAGE_LEN];
+- /* 94-105: Address in memory of image start
+- * (kernel for OpenWRT, rootfs for stock firmware)
+- */
+- char flash_image_start[ADDRESS_LEN];
+- /* 106-115: Size of rootfs */
+- char root_length[IMAGE_LEN];
+- /* 116-127: Address in memory of kernel */
+- char kernel_address[ADDRESS_LEN];
+- /* 128-137: Size of kernel */
+- char kernel_length[IMAGE_LEN];
+- /* 138-139: Unused at the moment */
+- char dual_image[DUALFLAG_LEN];
+- /* 140-141: Unused at the moment */
+- char inactive_flag[INACTIVEFLAG_LEN];
+- /* 142-161: RSA Signature (not used; some vendors may use this) */
+- char rsa_signature[RSASIG_LEN];
+- /* 162-191: Compilation and related information (not used in OpenWrt) */
+- char information1[TAGINFO1_LEN];
+- /* 192-195: Version flash layout */
+- char flash_layout_ver[FLASHLAYOUTVER_LEN];
+- /* 196-199: kernel+rootfs CRC32 */
+- __u32 fskernel_crc;
+- /* 200-215: Unused except on Alice Gate where is is information */
+- char information2[TAGINFO2_LEN];
+- /* 216-219: CRC32 of image less imagetag (kernel for Alice Gate) */
+- __u32 image_crc;
+- /* 220-223: CRC32 of rootfs partition */
+- __u32 rootfs_crc;
+- /* 224-227: CRC32 of kernel partition */
+- __u32 kernel_crc;
+- /* 228-235: Unused at present */
+- char reserved1[8];
+- /* 236-239: CRC32 of header excluding last 20 bytes */
+- __u32 header_crc;
+- /* 240-255: Unused at present */
+- char reserved2[16];
+-};
+-
+-#endif /* __BCM63XX_TAG_H */
+--- a/drivers/mtd/bcm63xxpart.c
++++ b/drivers/mtd/bcm63xxpart.c
+@@ -32,7 +32,7 @@
+ #include <linux/mtd/mtd.h>
+ #include <linux/mtd/partitions.h>
+
+-#include <asm/mach-bcm63xx/bcm963xx_tag.h>
++#include <linux/bcm963xx_tag.h>
+ #include <asm/mach-bcm63xx/board_bcm963xx.h>
+
+ #define BCM63XX_EXTENDED_SIZE 0xBFC00000 /* Extended flash address */
+--- a/include/uapi/linux/Kbuild
++++ b/include/uapi/linux/Kbuild
+@@ -67,6 +67,7 @@ header-y += binfmts.h
+ header-y += blkpg.h
+ header-y += blktrace_api.h
+ header-y += bpqether.h
++header-y += bcm963xx_tag.h
+ header-y += bsg.h
+ header-y += can.h
+ header-y += capability.h
+--- /dev/null
++++ b/include/uapi/linux/bcm963xx_tag.h
+@@ -0,0 +1,96 @@
++#ifndef __BCM963XX_TAG_H
++#define __BCM963XX_TAG_H
++
++#define TAGVER_LEN 4 /* Length of Tag Version */
++#define TAGLAYOUT_LEN 4 /* Length of FlashLayoutVer */
++#define SIG1_LEN 20 /* Company Signature 1 Length */
++#define SIG2_LEN 14 /* Company Signature 2 Length */
++#define BOARDID_LEN 16 /* Length of BoardId */
++#define ENDIANFLAG_LEN 2 /* Endian Flag Length */
++#define CHIPID_LEN 6 /* Chip Id Length */
++#define IMAGE_LEN 10 /* Length of Length Field */
++#define ADDRESS_LEN 12 /* Length of Address field */
++#define DUALFLAG_LEN 2 /* Dual Image flag Length */
++#define INACTIVEFLAG_LEN 2 /* Inactie Flag Length */
++#define RSASIG_LEN 20 /* Length of RSA Signature in tag */
++#define TAGINFO1_LEN 30 /* Length of vendor information field1 in tag */
++#define FLASHLAYOUTVER_LEN 4 /* Length of Flash Layout Version String tag */
++#define TAGINFO2_LEN 16 /* Length of vendor information field2 in tag */
++#define ALTTAGINFO_LEN 54 /* Alternate length for vendor information; Pirelli */
++
++#define NUM_PIRELLI 2
++#define IMAGETAG_CRC_START 0xFFFFFFFF
++
++#define PIRELLI_BOARDS { \
++ "AGPF-S0", \
++ "DWV-S0", \
++}
++
++/*
++ * The broadcom firmware assumes the rootfs starts the image,
++ * therefore uses the rootfs start (flash_image_address)
++ * to determine where to flash the image. Since we have the kernel first
++ * we have to give it the kernel address, but the crc uses the length
++ * associated with this address (root_length), which is added to the kernel
++ * length (kernel_length) to determine the length of image to flash and thus
++ * needs to be rootfs + deadcode (jffs2 EOF marker)
++*/
++
++struct bcm_tag {
++ /* 0-3: Version of the image tag */
++ char tag_version[TAGVER_LEN];
++ /* 4-23: Company Line 1 */
++ char sig_1[SIG1_LEN];
++ /* 24-37: Company Line 2 */
++ char sig_2[SIG2_LEN];
++ /* 38-43: Chip this image is for */
++ char chip_id[CHIPID_LEN];
++ /* 44-59: Board name */
++ char board_id[BOARDID_LEN];
++ /* 60-61: Map endianness -- 1 BE 0 LE */
++ char big_endian[ENDIANFLAG_LEN];
++ /* 62-71: Total length of image */
++ char total_length[IMAGE_LEN];
++ /* 72-83: Address in memory of CFE */
++ char cfe__address[ADDRESS_LEN];
++ /* 84-93: Size of CFE */
++ char cfe_length[IMAGE_LEN];
++ /* 94-105: Address in memory of image start
++ * (kernel for OpenWRT, rootfs for stock firmware)
++ */
++ char flash_image_start[ADDRESS_LEN];
++ /* 106-115: Size of rootfs */
++ char root_length[IMAGE_LEN];
++ /* 116-127: Address in memory of kernel */
++ char kernel_address[ADDRESS_LEN];
++ /* 128-137: Size of kernel */
++ char kernel_length[IMAGE_LEN];
++ /* 138-139: Unused at the moment */
++ char dual_image[DUALFLAG_LEN];
++ /* 140-141: Unused at the moment */
++ char inactive_flag[INACTIVEFLAG_LEN];
++ /* 142-161: RSA Signature (not used; some vendors may use this) */
++ char rsa_signature[RSASIG_LEN];
++ /* 162-191: Compilation and related information (not used in OpenWrt) */
++ char information1[TAGINFO1_LEN];
++ /* 192-195: Version flash layout */
++ char flash_layout_ver[FLASHLAYOUTVER_LEN];
++ /* 196-199: kernel+rootfs CRC32 */
++ __u32 fskernel_crc;
++ /* 200-215: Unused except on Alice Gate where is is information */
++ char information2[TAGINFO2_LEN];
++ /* 216-219: CRC32 of image less imagetag (kernel for Alice Gate) */
++ __u32 image_crc;
++ /* 220-223: CRC32 of rootfs partition */
++ __u32 rootfs_crc;
++ /* 224-227: CRC32 of kernel partition */
++ __u32 kernel_crc;
++ /* 228-235: Unused at present */
++ char reserved1[8];
++ /* 236-239: CRC32 of header excluding last 20 bytes */
++ __u32 header_crc;
++ /* 240-255: Unused at present */
++ char reserved2[16];
++};
++
++#endif /* __BCM63XX_TAG_H */
diff --git a/target/linux/generic/patches-3.7/262-compressor_kconfig_hack.patch b/target/linux/generic/patches-3.7/262-compressor_kconfig_hack.patch
new file mode 100644
index 000000000..cadc029e9
--- /dev/null
+++ b/target/linux/generic/patches-3.7/262-compressor_kconfig_hack.patch
@@ -0,0 +1,23 @@
+--- a/lib/Kconfig
++++ b/lib/Kconfig
+@@ -175,16 +175,16 @@ config AUDIT_GENERIC
+ # compression support is select'ed if needed
+ #
+ config ZLIB_INFLATE
+- tristate
++ tristate "ZLIB inflate support"
+
+ config ZLIB_DEFLATE
+- tristate
++ tristate "ZLIB deflate support"
+
+ config LZO_COMPRESS
+- tristate
++ tristate "LZO compress support"
+
+ config LZO_DECOMPRESS
+- tristate
++ tristate "LZO decompress support"
+
+ source "lib/xz/Kconfig"
+
diff --git a/target/linux/generic/patches-3.7/302-mips_no_branch_likely.patch b/target/linux/generic/patches-3.7/302-mips_no_branch_likely.patch
new file mode 100644
index 000000000..44c6b04fc
--- /dev/null
+++ b/target/linux/generic/patches-3.7/302-mips_no_branch_likely.patch
@@ -0,0 +1,11 @@
+--- a/arch/mips/Makefile
++++ b/arch/mips/Makefile
+@@ -87,7 +87,7 @@ all-$(CONFIG_SYS_SUPPORTS_ZBOOT)+= vmlin
+ # machines may also. Since BFD is incredibly buggy with respect to
+ # crossformat linking we rely on the elf2ecoff tool for format conversion.
+ #
+-cflags-y += -G 0 -mno-abicalls -fno-pic -pipe
++cflags-y += -G 0 -mno-abicalls -fno-pic -pipe -mno-branch-likely
+ cflags-y += -msoft-float
+ LDFLAGS_vmlinux += -G 0 -static -n -nostdlib --gc-sections
+ KBUILD_AFLAGS_MODULE += -mlong-calls
diff --git a/target/linux/generic/patches-3.7/305-mips_module_reloc.patch b/target/linux/generic/patches-3.7/305-mips_module_reloc.patch
new file mode 100644
index 000000000..f0f513741
--- /dev/null
+++ b/target/linux/generic/patches-3.7/305-mips_module_reloc.patch
@@ -0,0 +1,350 @@
+--- a/arch/mips/Makefile
++++ b/arch/mips/Makefile
+@@ -90,8 +90,13 @@ all-$(CONFIG_SYS_SUPPORTS_ZBOOT)+= vmlin
+ cflags-y += -G 0 -mno-abicalls -fno-pic -pipe -mno-branch-likely
+ cflags-y += -msoft-float
+ LDFLAGS_vmlinux += -G 0 -static -n -nostdlib --gc-sections
++ifdef CONFIG_64BIT
+ KBUILD_AFLAGS_MODULE += -mlong-calls
+ KBUILD_CFLAGS_MODULE += -mlong-calls
++else
++KBUILD_AFLAGS_MODULE += -mno-long-calls
++KBUILD_CFLAGS_MODULE += -mno-long-calls
++endif
+
+ KBUILD_CFLAGS_KERNEL += -ffunction-sections -fdata-sections
+
+--- a/arch/mips/include/asm/module.h
++++ b/arch/mips/include/asm/module.h
+@@ -11,6 +11,11 @@ struct mod_arch_specific {
+ const struct exception_table_entry *dbe_start;
+ const struct exception_table_entry *dbe_end;
+ struct mips_hi16 *r_mips_hi16_list;
++
++ void *phys_plt_tbl;
++ void *virt_plt_tbl;
++ unsigned int phys_plt_offset;
++ unsigned int virt_plt_offset;
+ };
+
+ typedef uint8_t Elf64_Byte; /* Type for a 8-bit quantity. */
+--- a/arch/mips/kernel/module.c
++++ b/arch/mips/kernel/module.c
+@@ -42,14 +42,219 @@ struct mips_hi16 {
+ static LIST_HEAD(dbe_list);
+ static DEFINE_SPINLOCK(dbe_lock);
+
+-#ifdef MODULE_START
++/*
++ * Get the potential max trampolines size required of the init and
++ * non-init sections. Only used if we cannot find enough contiguous
++ * physically mapped memory to put the module into.
++ */
++static unsigned int
++get_plt_size(const Elf_Ehdr *hdr, const Elf_Shdr *sechdrs,
++ const char *secstrings, unsigned int symindex, bool is_init)
++{
++ unsigned long ret = 0;
++ unsigned int i, j;
++ Elf_Sym *syms;
++
++ /* Everything marked ALLOC (this includes the exported symbols) */
++ for (i = 1; i < hdr->e_shnum; ++i) {
++ unsigned int info = sechdrs[i].sh_info;
++
++ if (sechdrs[i].sh_type != SHT_REL
++ && sechdrs[i].sh_type != SHT_RELA)
++ continue;
++
++ /* Not a valid relocation section? */
++ if (info >= hdr->e_shnum)
++ continue;
++
++ /* Don't bother with non-allocated sections */
++ if (!(sechdrs[info].sh_flags & SHF_ALLOC))
++ continue;
++
++ /* If it's called *.init*, and we're not init, we're
++ not interested */
++ if ((strstr(secstrings + sechdrs[i].sh_name, ".init") != 0)
++ != is_init)
++ continue;
++
++ syms = (Elf_Sym *) sechdrs[symindex].sh_addr;
++ if (sechdrs[i].sh_type == SHT_REL) {
++ Elf_Mips_Rel *rel = (void *) sechdrs[i].sh_addr;
++ unsigned int size = sechdrs[i].sh_size / sizeof(*rel);
++
++ for (j = 0; j < size; ++j) {
++ Elf_Sym *sym;
++
++ if (ELF_MIPS_R_TYPE(rel[j]) != R_MIPS_26)
++ continue;
++
++ sym = syms + ELF_MIPS_R_SYM(rel[j]);
++ if (!is_init && sym->st_shndx != SHN_UNDEF)
++ continue;
++
++ ret += 4 * sizeof(int);
++ }
++ } else {
++ Elf_Mips_Rela *rela = (void *) sechdrs[i].sh_addr;
++ unsigned int size = sechdrs[i].sh_size / sizeof(*rela);
++
++ for (j = 0; j < size; ++j) {
++ Elf_Sym *sym;
++
++ if (ELF_MIPS_R_TYPE(rela[j]) != R_MIPS_26)
++ continue;
++
++ sym = syms + ELF_MIPS_R_SYM(rela[j]);
++ if (!is_init && sym->st_shndx != SHN_UNDEF)
++ continue;
++
++ ret += 4 * sizeof(int);
++ }
++ }
++ }
++
++ return ret;
++}
++
++#ifndef MODULE_START
++static void *alloc_phys(unsigned long size)
++{
++ unsigned order;
++ struct page *page;
++ struct page *p;
++
++ size = PAGE_ALIGN(size);
++ order = get_order(size);
++
++ page = alloc_pages(GFP_KERNEL | __GFP_NORETRY | __GFP_NOWARN |
++ __GFP_THISNODE, order);
++ if (!page)
++ return NULL;
++
++ split_page(page, order);
++
++ for (p = page + (size >> PAGE_SHIFT); p < page + (1 << order); ++p)
++ __free_page(p);
++
++ return page_address(page);
++}
++#endif
++
++static void free_phys(void *ptr, unsigned long size)
++{
++ struct page *page;
++ struct page *end;
++
++ page = virt_to_page(ptr);
++ end = page + (PAGE_ALIGN(size) >> PAGE_SHIFT);
++
++ for (; page < end; ++page)
++ __free_page(page);
++}
++
++
+ void *module_alloc(unsigned long size)
+ {
++#ifdef MODULE_START
+ return __vmalloc_node_range(size, 1, MODULE_START, MODULE_END,
+ GFP_KERNEL, PAGE_KERNEL, -1,
+ __builtin_return_address(0));
++#else
++ void *ptr;
++
++ if (size == 0)
++ return NULL;
++
++ ptr = alloc_phys(size);
++
++ /* If we failed to allocate physically contiguous memory,
++ * fall back to regular vmalloc. The module loader code will
++ * create jump tables to handle long jumps */
++ if (!ptr)
++ return vmalloc(size);
++
++ return ptr;
++#endif
+ }
++
++static inline bool is_phys_addr(void *ptr)
++{
++#ifdef CONFIG_64BIT
++ return (KSEGX((unsigned long)ptr) == CKSEG0);
++#else
++ return (KSEGX(ptr) == KSEG0);
+ #endif
++}
++
++/* Free memory returned from module_alloc */
++void module_free(struct module *mod, void *module_region)
++{
++ if (is_phys_addr(module_region)) {
++ if (mod->module_init == module_region)
++ free_phys(module_region, mod->init_size);
++ else if (mod->module_core == module_region)
++ free_phys(module_region, mod->core_size);
++ else
++ BUG();
++ } else {
++ vfree(module_region);
++ }
++}
++
++static void *__module_alloc(int size, bool phys)
++{
++ void *ptr;
++
++ if (phys)
++ ptr = kmalloc(size, GFP_KERNEL);
++ else
++ ptr = vmalloc(size);
++ return ptr;
++}
++
++static void __module_free(void *ptr)
++{
++ if (is_phys_addr(ptr))
++ kfree(ptr);
++ else
++ vfree(ptr);
++}
++
++int module_frob_arch_sections(Elf_Ehdr *hdr, Elf_Shdr *sechdrs,
++ char *secstrings, struct module *mod)
++{
++ unsigned int symindex = 0;
++ unsigned int core_size, init_size;
++ int i;
++
++ for (i = 1; i < hdr->e_shnum; i++)
++ if (sechdrs[i].sh_type == SHT_SYMTAB)
++ symindex = i;
++
++ core_size = get_plt_size(hdr, sechdrs, secstrings, symindex, false);
++ init_size = get_plt_size(hdr, sechdrs, secstrings, symindex, true);
++
++ mod->arch.phys_plt_offset = 0;
++ mod->arch.virt_plt_offset = 0;
++ mod->arch.phys_plt_tbl = NULL;
++ mod->arch.virt_plt_tbl = NULL;
++
++ if ((core_size + init_size) == 0)
++ return 0;
++
++ mod->arch.phys_plt_tbl = __module_alloc(core_size + init_size, 1);
++ if (!mod->arch.phys_plt_tbl)
++ return -ENOMEM;
++
++ mod->arch.virt_plt_tbl = __module_alloc(core_size + init_size, 0);
++ if (!mod->arch.virt_plt_tbl) {
++ __module_free(mod->arch.phys_plt_tbl);
++ mod->arch.phys_plt_tbl = NULL;
++ return -ENOMEM;
++ }
++
++ return 0;
++}
+
+ int apply_r_mips_none(struct module *me, u32 *location, Elf_Addr v)
+ {
+@@ -63,8 +268,39 @@ static int apply_r_mips_32_rel(struct mo
+ return 0;
+ }
+
++static Elf_Addr add_plt_entry_to(unsigned *plt_offset,
++ void *start, Elf_Addr v)
++{
++ unsigned *tramp = start + *plt_offset;
++ *plt_offset += 4 * sizeof(int);
++
++ /* adjust carry for addiu */
++ if (v & 0x00008000)
++ v += 0x10000;
++
++ tramp[0] = 0x3c190000 | (v >> 16); /* lui t9, hi16 */
++ tramp[1] = 0x27390000 | (v & 0xffff); /* addiu t9, t9, lo16 */
++ tramp[2] = 0x03200008; /* jr t9 */
++ tramp[3] = 0x00000000; /* nop */
++
++ return (Elf_Addr) tramp;
++}
++
++static Elf_Addr add_plt_entry(struct module *me, void *location, Elf_Addr v)
++{
++ if (is_phys_addr(location))
++ return add_plt_entry_to(&me->arch.phys_plt_offset,
++ me->arch.phys_plt_tbl, v);
++ else
++ return add_plt_entry_to(&me->arch.virt_plt_offset,
++ me->arch.virt_plt_tbl, v);
++
++}
++
+ static int apply_r_mips_26_rel(struct module *me, u32 *location, Elf_Addr v)
+ {
++ u32 ofs = *location & 0x03ffffff;
++
+ if (v % 4) {
+ pr_err("module %s: dangerous R_MIPS_26 REL relocation\n",
+ me->name);
+@@ -72,14 +308,17 @@ static int apply_r_mips_26_rel(struct mo
+ }
+
+ if ((v & 0xf0000000) != (((unsigned long)location + 4) & 0xf0000000)) {
+- printk(KERN_ERR
+- "module %s: relocation overflow\n",
+- me->name);
+- return -ENOEXEC;
++ v = add_plt_entry(me, location, v + (ofs << 2));
++ if (!v) {
++ printk(KERN_ERR
++ "module %s: relocation overflow\n",
++ me->name);
++ return -ENOEXEC;
++ }
++ ofs = 0;
+ }
+
+- *location = (*location & ~0x03ffffff) |
+- ((*location + (v >> 2)) & 0x03ffffff);
++ *location = (*location & ~0x03ffffff) | ((ofs + (v >> 2)) & 0x03ffffff);
+
+ return 0;
+ }
+@@ -286,11 +525,32 @@ int module_finalize(const Elf_Ehdr *hdr,
+ list_add(&me->arch.dbe_list, &dbe_list);
+ spin_unlock_irq(&dbe_lock);
+ }
++
++ /* Get rid of the fixup trampoline if we're running the module
++ * from physically mapped address space */
++ if (me->arch.phys_plt_offset == 0) {
++ __module_free(me->arch.phys_plt_tbl);
++ me->arch.phys_plt_tbl = NULL;
++ }
++ if (me->arch.virt_plt_offset == 0) {
++ __module_free(me->arch.virt_plt_tbl);
++ me->arch.virt_plt_tbl = NULL;
++ }
++
+ return 0;
+ }
+
+ void module_arch_cleanup(struct module *mod)
+ {
++ if (mod->arch.phys_plt_tbl) {
++ __module_free(mod->arch.phys_plt_tbl);
++ mod->arch.phys_plt_tbl = NULL;
++ }
++ if (mod->arch.virt_plt_tbl) {
++ __module_free(mod->arch.virt_plt_tbl);
++ mod->arch.virt_plt_tbl = NULL;
++ }
++
+ spin_lock_irq(&dbe_lock);
+ list_del(&mod->arch.dbe_list);
+ spin_unlock_irq(&dbe_lock);
diff --git a/target/linux/generic/patches-3.7/307-mips_oprofile_fix.patch b/target/linux/generic/patches-3.7/307-mips_oprofile_fix.patch
deleted file mode 100644
index bed578645..000000000
--- a/target/linux/generic/patches-3.7/307-mips_oprofile_fix.patch
+++ /dev/null
@@ -1,35 +0,0 @@
---- a/arch/mips/oprofile/op_model_mipsxx.c
-+++ b/arch/mips/oprofile/op_model_mipsxx.c
-@@ -303,6 +303,11 @@ static irqreturn_t mipsxx_perfcount_int(
- return mipsxx_perfcount_handler();
- }
-
-+static irqreturn_t mipsxx_perfcount_int(int irq, void *dev_id)
-+{
-+ return mipsxx_perfcount_handler();
-+}
-+
- static int __init mipsxx_init(void)
- {
- int counters;
-@@ -385,6 +390,10 @@ static int __init mipsxx_init(void)
- return request_irq(cp0_perfcount_irq, mipsxx_perfcount_int,
- 0, "Perfcounter", save_perf_irq);
-
-+ if (cp0_perfcount_irq >= 0)
-+ return request_irq(cp0_perfcount_irq, mipsxx_perfcount_int,
-+ IRQF_SHARED, "Perfcounter", save_perf_irq);
-+
- return 0;
- }
-
-@@ -395,6 +404,9 @@ static void mipsxx_exit(void)
- if ((cp0_perfcount_irq >= 0) && (cp0_compare_irq != cp0_perfcount_irq))
- free_irq(cp0_perfcount_irq, save_perf_irq);
-
-+ if (cp0_perfcount_irq >= 0)
-+ free_irq(cp0_perfcount_irq, save_perf_irq);
-+
- counters = counters_per_cpu_to_total(counters);
- on_each_cpu(reset_counters, (void *)(long)counters, 1);
-
diff --git a/target/linux/generic/patches-3.7/308-mips-show-correct-cpu-name-for-24KEc.patch b/target/linux/generic/patches-3.7/308-mips-show-correct-cpu-name-for-24KEc.patch
index e3b172853..923992e81 100644
--- a/target/linux/generic/patches-3.7/308-mips-show-correct-cpu-name-for-24KEc.patch
+++ b/target/linux/generic/patches-3.7/308-mips-show-correct-cpu-name-for-24KEc.patch
@@ -1,6 +1,6 @@
--- a/arch/mips/kernel/cpu-probe.c
+++ b/arch/mips/kernel/cpu-probe.c
-@@ -839,10 +839,13 @@ static inline void cpu_probe_mips(struct
+@@ -838,10 +838,13 @@ static inline void cpu_probe_mips(struct
__cpu_name[cpu] = "MIPS 20Kc";
break;
case PRID_IMP_24K:
diff --git a/target/linux/generic/patches-3.7/330-mips-add-crash-and-kdump-support.patch b/target/linux/generic/patches-3.7/330-mips-add-crash-and-kdump-support.patch
index def970fd3..479d7d806 100644
--- a/target/linux/generic/patches-3.7/330-mips-add-crash-and-kdump-support.patch
+++ b/target/linux/generic/patches-3.7/330-mips-add-crash-and-kdump-support.patch
@@ -437,7 +437,7 @@ Signed-off-by: Wu Zhangjin <wuzhangjin@gmail.com>
#include <asm/addrspace.h>
#include <asm/bootinfo.h>
-@@ -522,12 +523,62 @@ static void __init arch_mem_init(char **
+@@ -536,12 +537,62 @@ static void __init arch_mem_init(char **
}
bootmem_init();
@@ -500,7 +500,7 @@ Signed-off-by: Wu Zhangjin <wuzhangjin@gmail.com>
static void __init resource_init(void)
{
int i;
-@@ -543,6 +594,8 @@ static void __init resource_init(void)
+@@ -557,6 +608,8 @@ static void __init resource_init(void)
/*
* Request address space for all standard RAM.
*/
@@ -509,7 +509,7 @@ Signed-off-by: Wu Zhangjin <wuzhangjin@gmail.com>
for (i = 0; i < boot_mem_map.nr_map; i++) {
struct resource *res;
unsigned long start, end;
-@@ -579,6 +632,7 @@ static void __init resource_init(void)
+@@ -593,6 +646,7 @@ static void __init resource_init(void)
*/
request_resource(res, &code_resource);
request_resource(res, &data_resource);
diff --git a/target/linux/generic/patches-3.7/331-mips-kexec-enhanche-the-support.patch b/target/linux/generic/patches-3.7/331-mips-kexec-enhanche-the-support.patch
index 53a9191b2..efcd42d4e 100644
--- a/target/linux/generic/patches-3.7/331-mips-kexec-enhanche-the-support.patch
+++ b/target/linux/generic/patches-3.7/331-mips-kexec-enhanche-the-support.patch
@@ -57,20 +57,18 @@ Signed-off-by: Wu Zhangjin <wuzhangjin@gmail.com>
extern int (*_machine_kexec_prepare)(struct kimage *);
--- a/arch/mips/kernel/machine_kexec.c
+++ b/arch/mips/kernel/machine_kexec.c
-@@ -13,12 +13,6 @@
- #include <asm/cacheflush.h>
+@@ -14,10 +14,6 @@
#include <asm/page.h>
--extern const unsigned char relocate_new_kernel[];
+ extern const unsigned char relocate_new_kernel[];
-extern const size_t relocate_new_kernel_size;
-
-extern unsigned long kexec_start_address;
-extern unsigned long kexec_indirection_page;
--
+
int (*_machine_kexec_prepare)(struct kimage *) = NULL;
void (*_machine_kexec_shutdown)(void) = NULL;
- void (*_machine_crash_shutdown)(struct pt_regs *regs) = NULL;
-@@ -61,21 +55,34 @@ typedef void (*noretfun_t)(void) __attri
+@@ -61,21 +57,34 @@ typedef void (*noretfun_t)(void) __attri
void
machine_kexec(struct kimage *image)
{
@@ -107,7 +105,7 @@ Signed-off-by: Wu Zhangjin <wuzhangjin@gmail.com>
/*
* The generic kexec code builds a page list with physical
-@@ -96,8 +103,8 @@ machine_kexec(struct kimage *image)
+@@ -96,8 +105,8 @@ machine_kexec(struct kimage *image)
*/
local_irq_disable();
@@ -118,7 +116,7 @@ Signed-off-by: Wu Zhangjin <wuzhangjin@gmail.com>
__flush_cache_all();
#ifdef CONFIG_SMP
/* All secondary cpus now may jump to kexec_wait cycle */
-@@ -108,4 +115,3 @@ machine_kexec(struct kimage *image)
+@@ -108,4 +117,3 @@ machine_kexec(struct kimage *image)
#endif
((noretfun_t) reboot_code_buffer)();
}
diff --git a/target/linux/generic/patches-3.7/332-mips-kexec-init-the-arguments-for-the-new-kernel-image.patch b/target/linux/generic/patches-3.7/332-mips-kexec-init-the-arguments-for-the-new-kernel-image.patch
index 5507dde64..07d0af9e7 100644
--- a/target/linux/generic/patches-3.7/332-mips-kexec-init-the-arguments-for-the-new-kernel-image.patch
+++ b/target/linux/generic/patches-3.7/332-mips-kexec-init-the-arguments-for-the-new-kernel-image.patch
@@ -19,7 +19,7 @@ Signed-off-by: Wu Zhangjin <wuzhangjin@gmail.com>
#include <asm/cacheflush.h>
#include <asm/page.h>
-@@ -21,9 +22,30 @@ void (*relocated_kexec_smp_wait) (void *
+@@ -23,9 +24,30 @@ void (*relocated_kexec_smp_wait) (void *
atomic_t kexec_ready_to_reboot = ATOMIC_INIT(0);
#endif
diff --git a/target/linux/generic/patches-3.7/333-mips-kexec-get-kernel-parameters-from-kexec-tools.patch b/target/linux/generic/patches-3.7/333-mips-kexec-get-kernel-parameters-from-kexec-tools.patch
index 9da936314..44380dae6 100644
--- a/target/linux/generic/patches-3.7/333-mips-kexec-get-kernel-parameters-from-kexec-tools.patch
+++ b/target/linux/generic/patches-3.7/333-mips-kexec-get-kernel-parameters-from-kexec-tools.patch
@@ -19,9 +19,9 @@ Signed-off-by: Wu Zhangjin <wuzhangjin@gmail.com>
#include <asm/page.h>
+#include <asm/uaccess.h>
- int (*_machine_kexec_prepare)(struct kimage *) = NULL;
- void (*_machine_kexec_shutdown)(void) = NULL;
-@@ -35,6 +36,56 @@ static void machine_kexec_init_args(void
+ extern const unsigned char relocate_new_kernel[];
+
+@@ -37,6 +38,56 @@ static void machine_kexec_init_args(void
pr_info("kexec_args[3] (desc): %p\n", (void *)kexec_args[3]);
}
@@ -78,7 +78,7 @@ Signed-off-by: Wu Zhangjin <wuzhangjin@gmail.com>
int
machine_kexec_prepare(struct kimage *kimage)
{
-@@ -45,6 +96,7 @@ machine_kexec_prepare(struct kimage *kim
+@@ -47,6 +98,7 @@ machine_kexec_prepare(struct kimage *kim
* This can be overrided by _machine_kexec_prepare().
*/
machine_kexec_init_args();
diff --git a/target/linux/generic/patches-3.7/335-mips-kexec-cleanup-kexec-tools-parameter-handling.patch b/target/linux/generic/patches-3.7/335-mips-kexec-cleanup-kexec-tools-parameter-handling.patch
index f7a8eed00..e0a1103eb 100644
--- a/target/linux/generic/patches-3.7/335-mips-kexec-cleanup-kexec-tools-parameter-handling.patch
+++ b/target/linux/generic/patches-3.7/335-mips-kexec-cleanup-kexec-tools-parameter-handling.patch
@@ -1,6 +1,6 @@
--- a/arch/mips/kernel/machine_kexec.c
+++ b/arch/mips/kernel/machine_kexec.c
-@@ -23,67 +23,104 @@ void (*relocated_kexec_smp_wait) (void *
+@@ -25,67 +25,104 @@ void (*relocated_kexec_smp_wait) (void *
atomic_t kexec_ready_to_reboot = ATOMIC_INIT(0);
#endif
@@ -151,7 +151,7 @@
}
int
-@@ -95,8 +132,14 @@ machine_kexec_prepare(struct kimage *kim
+@@ -97,8 +134,14 @@ machine_kexec_prepare(struct kimage *kim
*
* This can be overrided by _machine_kexec_prepare().
*/
@@ -168,7 +168,7 @@
if (_machine_kexec_prepare)
return _machine_kexec_prepare(kimage);
-@@ -152,11 +195,13 @@ machine_kexec(struct kimage *image)
+@@ -154,11 +197,13 @@ machine_kexec(struct kimage *image)
pr_info("kexec_indirection_page = %p\n",
(void *)kexec_indirection_page);
diff --git a/target/linux/generic/patches-3.7/340-module_alloc_size_check.patch b/target/linux/generic/patches-3.7/340-module_alloc_size_check.patch
index 2459b6183..99411ac73 100644
--- a/target/linux/generic/patches-3.7/340-module_alloc_size_check.patch
+++ b/target/linux/generic/patches-3.7/340-module_alloc_size_check.patch
@@ -1,6 +1,6 @@
--- a/kernel/module.c
+++ b/kernel/module.c
-@@ -2378,12 +2378,15 @@ static void dynamic_debug_remove(struct
+@@ -2398,12 +2398,15 @@ static void dynamic_debug_remove(struct
void * __weak module_alloc(unsigned long size)
{
diff --git a/target/linux/generic/patches-3.7/470-mtd_m25p80_add_pm25lv_flash_support.patch b/target/linux/generic/patches-3.7/470-mtd_m25p80_add_pm25lv_flash_support.patch
index 5ad171346..28e2fa80c 100644
--- a/target/linux/generic/patches-3.7/470-mtd_m25p80_add_pm25lv_flash_support.patch
+++ b/target/linux/generic/patches-3.7/470-mtd_m25p80_add_pm25lv_flash_support.patch
@@ -16,7 +16,7 @@
};
#define INFO(_jedec_id, _ext_id, _sector_size, _n_sectors, _flags) \
-@@ -667,6 +669,10 @@ static const struct spi_device_id m25p_i
+@@ -671,6 +673,10 @@ static const struct spi_device_id m25p_i
{ "n25q128", INFO(0x20ba18, 0, 64 * 1024, 256, 0) },
{ "n25q256a", INFO(0x20ba19, 0, 64 * 1024, 512, SECT_4K) },
@@ -27,7 +27,7 @@
/* Spansion -- single (large) sector size only, at least
* for the chips listed here (without boot sectors).
*/
-@@ -907,6 +913,9 @@ static int __devinit m25p_probe(struct s
+@@ -911,6 +917,9 @@ static int __devinit m25p_probe(struct s
if (info->flags & SECT_4K) {
flash->erase_opcode = OPCODE_BE_4K;
flash->mtd.erasesize = 4096;
diff --git a/target/linux/generic/patches-3.7/473-mtd_m25p80_add_w25q128.patch b/target/linux/generic/patches-3.7/473-mtd_m25p80_add_w25q128.patch
index 7466f3b87..293b6f21b 100644
--- a/target/linux/generic/patches-3.7/473-mtd_m25p80_add_w25q128.patch
+++ b/target/linux/generic/patches-3.7/473-mtd_m25p80_add_w25q128.patch
@@ -1,6 +1,6 @@
--- a/drivers/mtd/devices/m25p80.c
+++ b/drivers/mtd/devices/m25p80.c
-@@ -751,6 +751,7 @@ static const struct spi_device_id m25p_i
+@@ -755,6 +755,7 @@ static const struct spi_device_id m25p_i
{ "w25x64", INFO(0xef3017, 0, 64 * 1024, 128, SECT_4K) },
{ "w25q64", INFO(0xef4017, 0, 64 * 1024, 128, SECT_4K) },
{ "w25q80", INFO(0xef5014, 0, 64 * 1024, 16, SECT_4K) },
diff --git a/target/linux/generic/patches-3.7/474-mtd_mp25p80_add_pm25lq032.patch b/target/linux/generic/patches-3.7/474-mtd_mp25p80_add_pm25lq032.patch
new file mode 100644
index 000000000..e4b29ccec
--- /dev/null
+++ b/target/linux/generic/patches-3.7/474-mtd_mp25p80_add_pm25lq032.patch
@@ -0,0 +1,10 @@
+--- a/drivers/mtd/devices/m25p80.c
++++ b/drivers/mtd/devices/m25p80.c
+@@ -676,6 +676,7 @@ static const struct spi_device_id m25p_i
+ /* PMC -- pm25x "blocks" are 32K, sectors are 4K */
+ { "pm25lv512", INFO(0, 0, 32 * 1024, 2, SECT_4K_PMC) },
+ { "pm25lv010", INFO(0, 0, 32 * 1024, 4, SECT_4K_PMC) },
++ { "pm25lq032", INFO(0x7F9D46, 0, 64 * 1024, 64, SECT_4K) },
+
+ /* Spansion -- single (large) sector size only, at least
+ * for the chips listed here (without boot sectors).
diff --git a/target/linux/generic/patches-3.7/476-mtd-m25p80-allow-to-disable-small-sector-erase.patch b/target/linux/generic/patches-3.7/476-mtd-m25p80-allow-to-disable-small-sector-erase.patch
index 2a2541bff..d720b6932 100644
--- a/target/linux/generic/patches-3.7/476-mtd-m25p80-allow-to-disable-small-sector-erase.patch
+++ b/target/linux/generic/patches-3.7/476-mtd-m25p80-allow-to-disable-small-sector-erase.patch
@@ -30,7 +30,7 @@
/****************************************************************************/
struct m25p {
-@@ -911,7 +917,7 @@ static int __devinit m25p_probe(struct s
+@@ -916,7 +922,7 @@ static int __devinit m25p_probe(struct s
flash->mtd._write = m25p80_write;
/* prefer "small sector" erase if possible */
diff --git a/target/linux/generic/patches-3.7/541-ubifs-xz-decompression-support.patch b/target/linux/generic/patches-3.7/541-ubifs-xz-decompression-support.patch
index e06974186..f85689c58 100644
--- a/target/linux/generic/patches-3.7/541-ubifs-xz-decompression-support.patch
+++ b/target/linux/generic/patches-3.7/541-ubifs-xz-decompression-support.patch
@@ -42,7 +42,7 @@
+ .capi_name = "xz",
+};
+#else
-+static struct ubifs_compressor zlib_compr = {
++static struct ubifs_compressor xz_compr = {
+ .compr_type = UBIFS_COMPR_XZ,
+ .name = "xz",
+};
diff --git a/target/linux/generic/patches-3.7/551-ubifs-fix-default-compression-selection.patch b/target/linux/generic/patches-3.7/551-ubifs-fix-default-compression-selection.patch
new file mode 100644
index 000000000..1b0f30718
--- /dev/null
+++ b/target/linux/generic/patches-3.7/551-ubifs-fix-default-compression-selection.patch
@@ -0,0 +1,29 @@
+--- a/fs/ubifs/sb.c
++++ b/fs/ubifs/sb.c
+@@ -63,6 +63,17 @@
+ /* Default time granularity in nanoseconds */
+ #define DEFAULT_TIME_GRAN 1000000000
+
++static int get_default_compressor(void)
++{
++ if (ubifs_compr_present(UBIFS_COMPR_LZO))
++ return UBIFS_COMPR_LZO;
++
++ if (ubifs_compr_present(UBIFS_COMPR_ZLIB))
++ return UBIFS_COMPR_ZLIB;
++
++ return UBIFS_COMPR_NONE;
++}
++
+ /**
+ * create_default_filesystem - format empty UBI volume.
+ * @c: UBIFS file-system description object
+@@ -183,7 +194,7 @@ static int create_default_filesystem(str
+ if (c->mount_opts.override_compr)
+ sup->default_compr = cpu_to_le16(c->mount_opts.compr_type);
+ else
+- sup->default_compr = cpu_to_le16(UBIFS_COMPR_LZO);
++ sup->default_compr = cpu_to_le16(get_default_compressor());
+
+ generate_random_uuid(sup->uuid);
+
diff --git a/target/linux/generic/patches-3.7/600-netfilter_layer7_2.22.patch b/target/linux/generic/patches-3.7/600-netfilter_layer7_2.22.patch
index 0c8c5e890..55daeab7a 100644
--- a/target/linux/generic/patches-3.7/600-netfilter_layer7_2.22.patch
+++ b/target/linux/generic/patches-3.7/600-netfilter_layer7_2.22.patch
@@ -1,6 +1,6 @@
--- a/net/netfilter/Kconfig
+++ b/net/netfilter/Kconfig
-@@ -1176,6 +1176,27 @@ config NETFILTER_XT_MATCH_STATE
+@@ -1183,6 +1183,27 @@ config NETFILTER_XT_MATCH_STATE
To compile it as a module, choose M here. If unsure, say N.
diff --git a/target/linux/generic/patches-3.7/603-netfilter_layer7_2.6.36_fix.patch b/target/linux/generic/patches-3.7/603-netfilter_layer7_2.6.36_fix.patch
index 23a1b1b26..e3f203289 100644
--- a/target/linux/generic/patches-3.7/603-netfilter_layer7_2.6.36_fix.patch
+++ b/target/linux/generic/patches-3.7/603-netfilter_layer7_2.6.36_fix.patch
@@ -1,6 +1,6 @@
--- a/net/netfilter/Kconfig
+++ b/net/netfilter/Kconfig
-@@ -980,6 +980,27 @@ config NETFILTER_XT_MATCH_IPVS
+@@ -987,6 +987,27 @@ config NETFILTER_XT_MATCH_IPVS
If unsure, say N.
@@ -28,7 +28,7 @@
config NETFILTER_XT_MATCH_LENGTH
tristate '"length" match support'
depends on NETFILTER_ADVANCED
-@@ -1176,26 +1197,11 @@ config NETFILTER_XT_MATCH_STATE
+@@ -1183,26 +1204,11 @@ config NETFILTER_XT_MATCH_STATE
To compile it as a module, choose M here. If unsure, say N.
diff --git a/target/linux/generic/patches-3.7/604-netfilter_cisco_794x_iphone.patch b/target/linux/generic/patches-3.7/604-netfilter_cisco_794x_iphone.patch
deleted file mode 100644
index e24f16afc..000000000
--- a/target/linux/generic/patches-3.7/604-netfilter_cisco_794x_iphone.patch
+++ /dev/null
@@ -1,131 +0,0 @@
---- a/include/linux/netfilter/nf_conntrack_sip.h
-+++ b/include/linux/netfilter/nf_conntrack_sip.h
-@@ -4,12 +4,15 @@
-
- #include <net/netfilter/nf_conntrack_expect.h>
-
-+#include <linux/types.h>
-+
- #define SIP_PORT 5060
- #define SIP_TIMEOUT 3600
-
- struct nf_ct_sip_master {
- unsigned int register_cseq;
- unsigned int invite_cseq;
-+ __be16 forced_dport;
- };
-
- enum sip_expectation_classes {
---- a/net/netfilter/nf_nat_sip.c
-+++ b/net/netfilter/nf_nat_sip.c
-@@ -95,11 +95,14 @@ static int map_addr(struct sk_buff *skb,
- enum ip_conntrack_info ctinfo;
- struct nf_conn *ct = nf_ct_get(skb, &ctinfo);
- enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo);
-+ struct nf_ct_sip_master *ct_sip_info;
- char buffer[INET6_ADDRSTRLEN + sizeof("[]:nnnnn")];
- unsigned int buflen;
- union nf_inet_addr newaddr;
- __be16 newport;
-
-+ ct_sip_info = nfct_help_data(ct->master);
-+
- if (nf_inet_addr_cmp(&ct->tuplehash[dir].tuple.src.u3, addr) &&
- ct->tuplehash[dir].tuple.src.u.udp.port == port) {
- newaddr = ct->tuplehash[!dir].tuple.dst.u3;
-@@ -107,7 +110,8 @@ static int map_addr(struct sk_buff *skb,
- } else if (nf_inet_addr_cmp(&ct->tuplehash[dir].tuple.dst.u3, addr) &&
- ct->tuplehash[dir].tuple.dst.u.udp.port == port) {
- newaddr = ct->tuplehash[!dir].tuple.src.u3;
-- newport = ct->tuplehash[!dir].tuple.src.u.udp.port;
-+ newport = ct_sip_info->forced_dport ? :
-+ ct->tuplehash[!dir].tuple.src.u.udp.port;
- } else
- return 1;
-
-@@ -144,6 +148,7 @@ static unsigned int nf_nat_sip(struct sk
- enum ip_conntrack_info ctinfo;
- struct nf_conn *ct = nf_ct_get(skb, &ctinfo);
- enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo);
-+ struct nf_conn_help *help = nfct_help(ct);
- unsigned int coff, matchoff, matchlen;
- enum sip_header_types hdr;
- union nf_inet_addr addr;
-@@ -258,6 +263,22 @@ next:
- !map_sip_addr(skb, protoff, dataoff, dptr, datalen, SIP_HDR_TO))
- return NF_DROP;
-
-+ struct nf_ct_sip_master *ct_sip_info = nfct_help_data(ct->master);
-+
-+ /* Mangle destination port for Cisco phones, then fix up checksums */
-+ if (dir == IP_CT_DIR_REPLY && ct_sip_info->forced_dport) {
-+ struct udphdr *uh;
-+
-+ if (!skb_make_writable(skb, skb->len))
-+ return NF_DROP;
-+
-+ uh = (struct udphdr *)(skb->data + ip_hdrlen(skb));
-+ uh->dest = ct_sip_info->forced_dport;
-+
-+ if (!nf_nat_mangle_udp_packet(skb, ct, ctinfo, 0, 0, NULL, 0))
-+ return NF_DROP;
-+ }
-+
- return NF_ACCEPT;
- }
-
-@@ -311,10 +332,13 @@ static unsigned int nf_nat_sip_expect(st
- enum ip_conntrack_info ctinfo;
- struct nf_conn *ct = nf_ct_get(skb, &ctinfo);
- enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo);
-+ struct nf_conn_help *help = nfct_help(ct);
- union nf_inet_addr newaddr;
- u_int16_t port;
-+ __be16 srcport;
- char buffer[INET6_ADDRSTRLEN + sizeof("[]:nnnnn")];
- unsigned int buflen;
-+ struct nf_ct_sip_master *ct_sip_info = nfct_help_data(ct->master);
-
- /* Connection will come from reply */
- if (nf_inet_addr_cmp(&ct->tuplehash[dir].tuple.src.u3,
-@@ -326,8 +350,9 @@ static unsigned int nf_nat_sip_expect(st
- /* If the signalling port matches the connection's source port in the
- * original direction, try to use the destination port in the opposite
- * direction. */
-- if (exp->tuple.dst.u.udp.port ==
-- ct->tuplehash[dir].tuple.src.u.udp.port)
-+ srcport = ct_sip_info->forced_dport ? :
-+ ct->tuplehash[dir].tuple.src.u.udp.port;
-+ if (exp->tuple.dst.u.udp.port == srcport)
- port = ntohs(ct->tuplehash[!dir].tuple.dst.u.udp.port);
- else
- port = ntohs(exp->tuple.dst.u.udp.port);
---- a/net/netfilter/nf_conntrack_sip.c
-+++ b/net/netfilter/nf_conntrack_sip.c
-@@ -1440,8 +1440,26 @@ static int process_sip_request(struct sk
- {
- enum ip_conntrack_info ctinfo;
- struct nf_conn *ct = nf_ct_get(skb, &ctinfo);
-+ struct nf_conn_help *help = nfct_help(ct);
-+ enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo);
- unsigned int matchoff, matchlen;
- unsigned int cseq, i;
-+ union nf_inet_addr addr;
-+ __be16 port;
-+ struct nf_ct_sip_master *ct_sip_info = nfct_help_data(ct->master);
-+
-+ /* Many Cisco IP phones use a high source port for SIP requests, but
-+ * listen for the response on port 5060. If we are the local
-+ * router for one of these phones, save the port number from the
-+ * Via: header so that nf_nat_sip can redirect the responses to
-+ * the correct port.
-+ */
-+ if (ct_sip_parse_header_uri(ct, *dptr, NULL, *datalen,
-+ SIP_HDR_VIA_UDP, NULL, &matchoff,
-+ &matchlen, &addr, &port) > 0 &&
-+ port != ct->tuplehash[dir].tuple.src.u.udp.port &&
-+ nf_inet_addr_cmp(&addr, &ct->tuplehash[dir].tuple.src.u3))
-+ ct_sip_info->forced_dport = port;
-
- for (i = 0; i < ARRAY_SIZE(sip_handlers); i++) {
- const struct sip_handler *handler;
diff --git a/target/linux/generic/patches-3.7/604-netfilter_conntrack_flush.patch b/target/linux/generic/patches-3.7/604-netfilter_conntrack_flush.patch
new file mode 100644
index 000000000..3ee5e4982
--- /dev/null
+++ b/target/linux/generic/patches-3.7/604-netfilter_conntrack_flush.patch
@@ -0,0 +1,46 @@
+--- a/net/netfilter/nf_conntrack_standalone.c
++++ b/net/netfilter/nf_conntrack_standalone.c
+@@ -267,10 +267,34 @@ static int ct_open(struct inode *inode,
+ sizeof(struct ct_iter_state));
+ }
+
++static int kill_all(struct nf_conn *i, void *data)
++{
++ return 1;
++}
++
++static ssize_t ct_file_write(struct file *file, const char __user *buf,
++ size_t count, loff_t *ppos)
++{
++ struct seq_file *seq = file->private_data;
++ struct net *net = seq_file_net(seq);
++
++ if (count) {
++ char c;
++
++ if (get_user(c, buf))
++ return -EFAULT;
++
++ if (c == 'f')
++ nf_ct_iterate_cleanup(net, kill_all, NULL);
++ }
++ return count;
++}
++
+ static const struct file_operations ct_file_ops = {
+ .owner = THIS_MODULE,
+ .open = ct_open,
+ .read = seq_read,
++ .write = ct_file_write,
+ .llseek = seq_lseek,
+ .release = seq_release_net,
+ };
+@@ -372,7 +396,7 @@ static int nf_conntrack_standalone_init_
+ {
+ struct proc_dir_entry *pde;
+
+- pde = proc_net_fops_create(net, "nf_conntrack", 0440, &ct_file_ops);
++ pde = proc_net_fops_create(net, "nf_conntrack", 0660, &ct_file_ops);
+ if (!pde)
+ goto out_nf_conntrack;
+
diff --git a/target/linux/generic/patches-3.7/630-packet_socket_type.patch b/target/linux/generic/patches-3.7/630-packet_socket_type.patch
index 27a46078e..40200377c 100644
--- a/target/linux/generic/patches-3.7/630-packet_socket_type.patch
+++ b/target/linux/generic/patches-3.7/630-packet_socket_type.patch
@@ -83,7 +83,7 @@ Signed-off-by: Felix Fietkau <nbd@openwrt.org>
if (!net_eq(dev_net(dev), sock_net(sk)))
goto drop;
-@@ -2511,6 +2513,7 @@ static int packet_create(struct net *net
+@@ -2513,6 +2515,7 @@ static int packet_create(struct net *net
spin_lock_init(&po->bind_lock);
mutex_init(&po->pg_vec_lock);
po->prot_hook.func = packet_rcv;
@@ -91,7 +91,7 @@ Signed-off-by: Felix Fietkau <nbd@openwrt.org>
if (sock->type == SOCK_PACKET)
po->prot_hook.func = packet_rcv_spkt;
-@@ -3111,6 +3114,16 @@ packet_setsockopt(struct socket *sock, i
+@@ -3113,6 +3116,16 @@ packet_setsockopt(struct socket *sock, i
return fanout_add(sk, val & 0xffff, val >> 16);
}
@@ -108,7 +108,7 @@ Signed-off-by: Felix Fietkau <nbd@openwrt.org>
default:
return -ENOPROTOOPT;
}
-@@ -3165,6 +3178,13 @@ static int packet_getsockopt(struct sock
+@@ -3167,6 +3180,13 @@ static int packet_getsockopt(struct sock
case PACKET_VNET_HDR:
val = po->has_vnet_hdr;
break;
diff --git a/target/linux/generic/patches-3.7/651-wireless_mesh_header.patch b/target/linux/generic/patches-3.7/651-wireless_mesh_header.patch
index ff3f0979f..c21b00777 100644
--- a/target/linux/generic/patches-3.7/651-wireless_mesh_header.patch
+++ b/target/linux/generic/patches-3.7/651-wireless_mesh_header.patch
@@ -1,6 +1,6 @@
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
-@@ -134,7 +134,7 @@ static inline bool dev_xmit_complete(int
+@@ -137,7 +137,7 @@ static inline bool dev_xmit_complete(int
*/
#if defined(CONFIG_WLAN) || IS_ENABLED(CONFIG_AX25)
diff --git a/target/linux/generic/patches-3.7/700-swconfig.patch b/target/linux/generic/patches-3.7/700-swconfig.patch
index 0a5b76eb3..1c1111de0 100644
--- a/target/linux/generic/patches-3.7/700-swconfig.patch
+++ b/target/linux/generic/patches-3.7/700-swconfig.patch
@@ -27,3 +27,13 @@
obj-$(CONFIG_MARVELL_PHY) += marvell.o
obj-$(CONFIG_DAVICOM_PHY) += davicom.o
obj-$(CONFIG_CICADA_PHY) += cicada.o
+--- a/include/uapi/linux/Kbuild
++++ b/include/uapi/linux/Kbuild
+@@ -356,6 +356,7 @@ header-y += stddef.h
+ header-y += string.h
+ header-y += suspend_ioctls.h
+ header-y += swab.h
++header-y += switch.h
+ header-y += synclink.h
+ header-y += sysctl.h
+ header-y += sysinfo.h
diff --git a/target/linux/generic/patches-3.7/703-phy-add-detach-callback-to-struct-phy_driver.patch b/target/linux/generic/patches-3.7/703-phy-add-detach-callback-to-struct-phy_driver.patch
new file mode 100644
index 000000000..b98f35333
--- /dev/null
+++ b/target/linux/generic/patches-3.7/703-phy-add-detach-callback-to-struct-phy_driver.patch
@@ -0,0 +1,27 @@
+--- a/drivers/net/phy/phy_device.c
++++ b/drivers/net/phy/phy_device.c
+@@ -613,6 +613,9 @@ EXPORT_SYMBOL(phy_attach);
+ */
+ void phy_detach(struct phy_device *phydev)
+ {
++ if (phydev->drv && phydev->drv->detach)
++ phydev->drv->detach(phydev);
++
+ phydev->attached_dev->phydev = NULL;
+ phydev->attached_dev = NULL;
+
+--- a/include/linux/phy.h
++++ b/include/linux/phy.h
+@@ -432,6 +432,12 @@ struct phy_driver {
+ */
+ int (*did_interrupt)(struct phy_device *phydev);
+
++ /*
++ * Called before an ethernet device is detached
++ * from the PHY.
++ */
++ void (*detach)(struct phy_device *phydev);
++
+ /* Clears up any memory if needed */
+ void (*remove)(struct phy_device *phydev);
+
diff --git a/target/linux/generic/patches-3.7/710-phy-add-mdio_register_board_info.patch b/target/linux/generic/patches-3.7/710-phy-add-mdio_register_board_info.patch
index a1c5b1d4b..9a68feaca 100644
--- a/target/linux/generic/patches-3.7/710-phy-add-mdio_register_board_info.patch
+++ b/target/linux/generic/patches-3.7/710-phy-add-mdio_register_board_info.patch
@@ -45,7 +45,7 @@
phy_device_free(phydev);
--- a/include/linux/phy.h
+++ b/include/linux/phy.h
-@@ -575,4 +575,22 @@ int __init mdio_bus_init(void);
+@@ -581,4 +581,22 @@ int __init mdio_bus_init(void);
void mdio_bus_exit(void);
extern struct bus_type mdio_bus_type;
diff --git a/target/linux/generic/patches-3.7/721-phy_packets.patch b/target/linux/generic/patches-3.7/721-phy_packets.patch
index 8dda0934b..78b2d69b4 100644
--- a/target/linux/generic/patches-3.7/721-phy_packets.patch
+++ b/target/linux/generic/patches-3.7/721-phy_packets.patch
@@ -1,6 +1,6 @@
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
-@@ -1074,6 +1074,11 @@ struct net_device {
+@@ -1077,6 +1077,11 @@ struct net_device {
const struct net_device_ops *netdev_ops;
const struct ethtool_ops *ethtool_ops;
@@ -12,7 +12,7 @@
/* Hardware header description */
const struct header_ops *header_ops;
-@@ -1130,6 +1135,9 @@ struct net_device {
+@@ -1133,6 +1138,9 @@ struct net_device {
void *ax25_ptr; /* AX.25 specific data */
struct wireless_dev *ieee80211_ptr; /* IEEE 802.11 specific data,
assign before registering */
@@ -145,7 +145,7 @@
+ struct sk_buff *skb = __netdev_alloc_skb(dev, length + NET_IP_ALIGN, gfp);
+
+#ifdef CONFIG_ETHERNET_PACKET_MANGLE
-+ if (dev->priv_flags & IFF_NO_IP_ALIGN)
++ if (dev && (dev->priv_flags & IFF_NO_IP_ALIGN))
+ return skb;
+#endif
+
diff --git a/target/linux/generic/patches-3.7/730-phy_b53.patch b/target/linux/generic/patches-3.7/730-phy_b53.patch
new file mode 100644
index 000000000..75972e58d
--- /dev/null
+++ b/target/linux/generic/patches-3.7/730-phy_b53.patch
@@ -0,0 +1,21 @@
+--- a/drivers/net/phy/Kconfig
++++ b/drivers/net/phy/Kconfig
+@@ -252,6 +252,8 @@ config RTL8367B_PHY
+
+ endif # RTL8366_SMI
+
++source "drivers/net/phy/b53/Kconfig"
++
+ endif # PHYLIB
+
+ config MICREL_KS8995MA
+--- a/drivers/net/phy/Makefile
++++ b/drivers/net/phy/Makefile
+@@ -31,6 +31,7 @@ obj-$(CONFIG_RTL8367B_PHY) += rtl8367b.o
+ obj-$(CONFIG_LSI_ET1011C_PHY) += et1011c.o
+ obj-$(CONFIG_MICREL_PHY) += micrel.o
+ obj-$(CONFIG_PSB6970_PHY) += psb6970.o
++obj-$(CONFIG_B53) += b53/
+ obj-$(CONFIG_FIXED_PHY) += fixed.o
+ obj-$(CONFIG_MDIO_BITBANG) += mdio-bitbang.o
+ obj-$(CONFIG_MDIO_GPIO) += mdio-gpio.o
diff --git a/target/linux/generic/patches-3.7/800-usb-ohci-multiple-platform-driver-fix.patch b/target/linux/generic/patches-3.7/800-usb-ohci-multiple-platform-driver-fix.patch
new file mode 100644
index 000000000..11075d579
--- /dev/null
+++ b/target/linux/generic/patches-3.7/800-usb-ohci-multiple-platform-driver-fix.patch
@@ -0,0 +1,51 @@
+--- a/drivers/usb/host/ohci-hcd.c
++++ b/drivers/usb/host/ohci-hcd.c
+@@ -1117,7 +1117,7 @@ MODULE_LICENSE ("GPL");
+
+ #ifdef CONFIG_USB_OHCI_HCD_PLATFORM
+ #include "ohci-platform.c"
+-#define PLATFORM_DRIVER ohci_platform_driver
++#define OHCI_PLATFORM_DRIVER ohci_platform_driver
+ #endif
+
+ #if !defined(PCI_DRIVER) && \
+@@ -1128,7 +1128,8 @@ MODULE_LICENSE ("GPL");
+ !defined(SA1111_DRIVER) && \
+ !defined(PS3_SYSTEM_BUS_DRIVER) && \
+ !defined(SM501_OHCI_DRIVER) && \
+- !defined(TMIO_OHCI_DRIVER)
++ !defined(TMIO_OHCI_DRIVER) && \
++ !defined(OHCI_PLATFORM_DRIVER)
+ #error "missing bus glue for ohci-hcd"
+ #endif
+
+@@ -1206,9 +1207,19 @@ static int __init ohci_hcd_mod_init(void
+ goto error_tmio;
+ #endif
+
++#ifdef OHCI_PLATFORM_DRIVER
++ retval = platform_driver_register(&OHCI_PLATFORM_DRIVER);
++ if (retval < 0)
++ goto error_ohci;
++#endif
++
+ return retval;
+
+ /* Error path */
++#ifdef OHCI_PLATFORM_DRIVER
++ platform_driver_unregister(&OHCI_PLATFORM_DRIVER);
++ error_ohci:
++#endif
+ #ifdef TMIO_OHCI_DRIVER
+ platform_driver_unregister(&TMIO_OHCI_DRIVER);
+ error_tmio:
+@@ -1258,6 +1269,9 @@ module_init(ohci_hcd_mod_init);
+
+ static void __exit ohci_hcd_mod_exit(void)
+ {
++#ifdef OHCI_PLATFORM_DRIVER
++ platform_driver_unregister(&OHCI_PLATFORM_DRIVER);
++#endif
+ #ifdef TMIO_OHCI_DRIVER
+ platform_driver_unregister(&TMIO_OHCI_DRIVER);
+ #endif
diff --git a/target/linux/generic/patches-3.7/801-usb-ehci-multiple-platform-driver-fix.patch b/target/linux/generic/patches-3.7/801-usb-ehci-multiple-platform-driver-fix.patch
new file mode 100644
index 000000000..e80304447
--- /dev/null
+++ b/target/linux/generic/patches-3.7/801-usb-ehci-multiple-platform-driver-fix.patch
@@ -0,0 +1,47 @@
+--- a/drivers/usb/host/ehci-hcd.c
++++ b/drivers/usb/host/ehci-hcd.c
+@@ -1336,12 +1336,12 @@ MODULE_LICENSE ("GPL");
+
+ #ifdef CONFIG_USB_EHCI_HCD_PLATFORM
+ #include "ehci-platform.c"
+-#define PLATFORM_DRIVER ehci_platform_driver
++#define EHCI_PLATFORM_DRIVER ehci_platform_driver
+ #endif
+
+ #if !defined(PCI_DRIVER) && !defined(PLATFORM_DRIVER) && \
+ !defined(PS3_SYSTEM_BUS_DRIVER) && !defined(OF_PLATFORM_DRIVER) && \
+- !defined(XILINX_OF_PLATFORM_DRIVER)
++ !defined(XILINX_OF_PLATFORM_DRIVER) && !defined(EHCI_PLATFORM_DRIVER)
+ #error "missing bus glue for ehci-hcd"
+ #endif
+
+@@ -1401,8 +1401,19 @@ static int __init ehci_hcd_init(void)
+ if (retval < 0)
+ goto clean4;
+ #endif
++
++#ifdef EHCI_PLATFORM_DRIVER
++ retval = platform_driver_register(&EHCI_PLATFORM_DRIVER);
++ if (retval < 0)
++ goto clean5;
++#endif
++
+ return retval;
+
++#ifdef EHCI_PLATFORM_DRIVER
++ platform_driver_unregister(&EHCI_PLATFORM_DRIVER);
++clean5:
++#endif
+ #ifdef XILINX_OF_PLATFORM_DRIVER
+ /* platform_driver_unregister(&XILINX_OF_PLATFORM_DRIVER); */
+ clean4:
+@@ -1435,6 +1446,9 @@ module_init(ehci_hcd_init);
+
+ static void __exit ehci_hcd_cleanup(void)
+ {
++#ifdef EHCI_PLATFORM_DRIVER
++ platform_driver_unregister(&EHCI_PLATFORM_DRIVER);
++#endif
+ #ifdef XILINX_OF_PLATFORM_DRIVER
+ platform_driver_unregister(&XILINX_OF_PLATFORM_DRIVER);
+ #endif
diff --git a/target/linux/generic/patches-3.7/810-pci_disable_common_quirks.patch b/target/linux/generic/patches-3.7/810-pci_disable_common_quirks.patch
index 255b33ed8..ff1a6b1e9 100644
--- a/target/linux/generic/patches-3.7/810-pci_disable_common_quirks.patch
+++ b/target/linux/generic/patches-3.7/810-pci_disable_common_quirks.patch
@@ -23,21 +23,29 @@
/* The Mellanox Tavor device gives false positive parity errors
* Mark this device with a broken_parity_status, to allow
* PCI scanning code to "skip" this now blacklisted device.
-@@ -1933,7 +1934,9 @@ static void __devinit fixup_rev1_53c810(
+@@ -2847,6 +2848,7 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_I
+ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x65f9, quirk_intel_mc_errata);
+ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x65fa, quirk_intel_mc_errata);
+
++#endif /* !CONFIG_PCI_DISABLE_COMMON_QUIRKS */
+
+ static ktime_t fixup_debug_start(struct pci_dev *dev,
+ void (*fn)(struct pci_dev *dev))
+@@ -2878,6 +2880,8 @@ static void fixup_debug_report(struct pc
}
}
- DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_NCR, PCI_DEVICE_ID_NCR_53C810, fixup_rev1_53c810);
-+#endif /* !CONFIG_PCI_DISABLE_COMMON_QUIRKS */
+#ifndef CONFIG_PCI_DISABLE_COMMON_QUIRKS
- /* Enable 1k I/O space granularity on the Intel P64H2 */
- static void __devinit quirk_p64h2_1k_io(struct pci_dev *dev)
- {
-@@ -2605,6 +2608,7 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AT
- DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATTANSIC, 0x1083,
- quirk_msi_intx_disable_bug);
- #endif /* CONFIG_PCI_MSI */
-+#endif /* !CONFIG_PCI_DISABLE_COMMON_QUIRKS */
++
+ /*
+ * Some BIOS implementations leave the Intel GPU interrupts enabled,
+ * even though no one is handling them (f.e. i915 driver is never loaded).
+@@ -2912,6 +2916,8 @@ static void __devinit disable_igfx_irq(s
+ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x0102, disable_igfx_irq);
+ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x010a, disable_igfx_irq);
- /* Allow manual resource allocation for PCI hotplug bridges
- * via pci=hpmemsize=nnM and pci=hpiosize=nnM parameters. For
++#endif /* !CONFIG_PCI_DISABLE_COMMON_QUIRKS */
++
+ /*
+ * Some devices may pass our check in pci_intx_mask_supported if
+ * PCI_COMMAND_INTX_DISABLE works though they actually do not properly
diff --git a/target/linux/generic/patches-3.7/811-pci_disable_usb_common_quirks.patch b/target/linux/generic/patches-3.7/811-pci_disable_usb_common_quirks.patch
index abe0230fd..da73f6719 100644
--- a/target/linux/generic/patches-3.7/811-pci_disable_usb_common_quirks.patch
+++ b/target/linux/generic/patches-3.7/811-pci_disable_usb_common_quirks.patch
@@ -1,8 +1,37 @@
--- a/drivers/usb/host/pci-quirks.c
+++ b/drivers/usb/host/pci-quirks.c
-@@ -434,6 +434,8 @@ reset_needed:
+@@ -79,6 +79,8 @@
+ #define USB_INTEL_USB3_PSSEN 0xD8
+ #define USB_INTEL_USB3PRM 0xDC
+
++#ifndef CONFIG_PCI_DISABLE_COMMON_QUIRKS
++
+ static struct amd_chipset_info {
+ struct pci_dev *nb_dev;
+ struct pci_dev *smbus_dev;
+@@ -353,6 +355,10 @@ void usb_amd_dev_put(void)
+ }
+ EXPORT_SYMBOL_GPL(usb_amd_dev_put);
+
++#endif /* CONFIG_PCI_DISABLE_COMMON_QUIRKS */
++
++#if IS_ENABLED(CONFIG_USB_UHCI_HCD)
++
+ /*
+ * Make sure the controller is completely inactive, unable to
+ * generate interrupts or do DMA.
+@@ -432,8 +438,17 @@ reset_needed:
+ uhci_reset_hc(pdev, base);
+ return 1;
}
++#else
++int uhci_check_and_reset_hc(struct pci_dev *pdev, unsigned long base)
++{
++ return 0;
++}
++
++#endif
EXPORT_SYMBOL_GPL(uhci_check_and_reset_hc);
+#ifndef CONFIG_PCI_DISABLE_COMMON_QUIRKS
@@ -10,8 +39,42 @@
static inline int io_type_enabled(struct pci_dev *pdev, unsigned int mask)
{
u16 cmd;
-@@ -971,3 +973,4 @@ static void __devinit quirk_usb_early_ha
+@@ -974,3 +989,4 @@ static void __devinit quirk_usb_early_ha
}
DECLARE_PCI_FIXUP_CLASS_FINAL(PCI_ANY_ID, PCI_ANY_ID,
PCI_CLASS_SERIAL_USB, 8, quirk_usb_early_handoff);
+#endif
+--- a/drivers/usb/host/pci-quirks.h
++++ b/drivers/usb/host/pci-quirks.h
+@@ -4,18 +4,26 @@
+ #ifdef CONFIG_PCI
+ void uhci_reset_hc(struct pci_dev *pdev, unsigned long base);
+ int uhci_check_and_reset_hc(struct pci_dev *pdev, unsigned long base);
++bool usb_is_intel_switchable_xhci(struct pci_dev *pdev);
++void usb_enable_xhci_ports(struct pci_dev *xhci_pdev);
++void usb_disable_xhci_ports(struct pci_dev *xhci_pdev);
++#else
++static inline void usb_disable_xhci_ports(struct pci_dev *xhci_pdev) {}
++#endif /* CONFIG_PCI */
++
++#if defined(CONFIG_PCI) && !defined(CONFIG_PCI_DISABLE_COMMON_QUIRKS)
+ int usb_amd_find_chipset_info(void);
+ void usb_amd_dev_put(void);
+ void usb_amd_quirk_pll_disable(void);
+ void usb_amd_quirk_pll_enable(void);
+-bool usb_is_intel_switchable_xhci(struct pci_dev *pdev);
+-void usb_enable_xhci_ports(struct pci_dev *xhci_pdev);
+-void usb_disable_xhci_ports(struct pci_dev *xhci_pdev);
+ #else
++static inline int usb_amd_find_chipset_info(void)
++{
++ return 0;
++}
+ static inline void usb_amd_quirk_pll_disable(void) {}
+ static inline void usb_amd_quirk_pll_enable(void) {}
+ static inline void usb_amd_dev_put(void) {}
+-static inline void usb_disable_xhci_ports(struct pci_dev *xhci_pdev) {}
+-#endif /* CONFIG_PCI */
++#endif
+
+ #endif /* __LINUX_USB_PCI_QUIRKS_H */
diff --git a/target/linux/generic/patches-3.7/850-glamo_headers.patch b/target/linux/generic/patches-3.7/850-glamo_headers.patch
index 363070d0a..689d14d62 100644
--- a/target/linux/generic/patches-3.7/850-glamo_headers.patch
+++ b/target/linux/generic/patches-3.7/850-glamo_headers.patch
@@ -10,7 +10,7 @@
#define FB_ACCEL_NEOMAGIC_NM2093 92 /* NeoMagic NM2093 */
--- a/include/uapi/linux/Kbuild
+++ b/include/uapi/linux/Kbuild
-@@ -130,6 +130,8 @@ header-y += gen_stats.h
+@@ -131,6 +131,8 @@ header-y += gen_stats.h
header-y += genetlink.h
header-y += gfs2_ondisk.h
header-y += gigaset_dev.h
diff --git a/target/linux/generic/patches-3.7/863-gpiommc.patch b/target/linux/generic/patches-3.7/863-gpiommc.patch
index a75b380c4..5a2b4e171 100644
--- a/target/linux/generic/patches-3.7/863-gpiommc.patch
+++ b/target/linux/generic/patches-3.7/863-gpiommc.patch
@@ -830,7 +830,7 @@
+be done automatically.
--- a/MAINTAINERS
+++ b/MAINTAINERS
-@@ -3401,6 +3401,11 @@ L: linuxppc-dev@lists.ozlabs.org
+@@ -3409,6 +3409,11 @@ L: linuxppc-dev@lists.ozlabs.org
S: Odd Fixes
F: drivers/tty/hvc/
diff --git a/target/linux/generic/patches-3.7/901-debloat_sock_diag.patch b/target/linux/generic/patches-3.7/901-debloat_sock_diag.patch
new file mode 100644
index 000000000..4065f8aea
--- /dev/null
+++ b/target/linux/generic/patches-3.7/901-debloat_sock_diag.patch
@@ -0,0 +1,46 @@
+--- a/net/Kconfig
++++ b/net/Kconfig
+@@ -87,6 +87,9 @@ source "net/netlabel/Kconfig"
+
+ endif # if INET
+
++config SOCK_DIAG
++ bool
++
+ config NETWORK_SECMARK
+ bool "Security Marking"
+ help
+--- a/net/core/Makefile
++++ b/net/core/Makefile
+@@ -8,9 +8,9 @@ obj-y := sock.o request_sock.o skbuff.o
+ obj-$(CONFIG_SYSCTL) += sysctl_net_core.o
+
+ obj-y += dev.o ethtool.o dev_addr_lists.o dst.o netevent.o \
+- neighbour.o rtnetlink.o utils.o link_watch.o filter.o \
+- sock_diag.o
++ neighbour.o rtnetlink.o utils.o link_watch.o filter.o
+
++obj-$(CONFIG_SOCK_DIAG) += sock_diag.o
+ obj-$(CONFIG_XFRM) += flow.o
+ obj-y += net-sysfs.o
+ obj-$(CONFIG_NET_PKTGEN) += pktgen.o
+--- a/net/ipv4/Kconfig
++++ b/net/ipv4/Kconfig
+@@ -404,6 +404,7 @@ config INET_LRO
+
+ config INET_DIAG
+ tristate "INET: socket monitoring interface"
++ select SOCK_DIAG
+ default y
+ ---help---
+ Support for INET (TCP, DCCP, etc) socket monitoring interface used by
+--- a/net/unix/Kconfig
++++ b/net/unix/Kconfig
+@@ -22,6 +22,7 @@ config UNIX
+ config UNIX_DIAG
+ tristate "UNIX: socket monitoring interface"
+ depends on UNIX
++ select SOCK_DIAG
+ default n
+ ---help---
+ Support for UNIX socket monitoring interface used by the ss tool.
diff --git a/target/linux/generic/patches-3.7/902-debloat_proc.patch b/target/linux/generic/patches-3.7/902-debloat_proc.patch
new file mode 100644
index 000000000..eb877a7bd
--- /dev/null
+++ b/target/linux/generic/patches-3.7/902-debloat_proc.patch
@@ -0,0 +1,338 @@
+--- a/fs/locks.c
++++ b/fs/locks.c
+@@ -2267,6 +2267,8 @@ static const struct file_operations proc
+
+ static int __init proc_locks_init(void)
+ {
++ if (IS_ENABLED(CONFIG_PROC_STRIPPED))
++ return 0;
+ proc_create("locks", 0, NULL, &proc_locks_operations);
+ return 0;
+ }
+--- a/fs/proc/Kconfig
++++ b/fs/proc/Kconfig
+@@ -67,3 +67,8 @@ config PROC_PAGE_MONITOR
+ /proc/pid/smaps, /proc/pid/clear_refs, /proc/pid/pagemap,
+ /proc/kpagecount, and /proc/kpageflags. Disabling these
+ interfaces will reduce the size of the kernel by approximately 4kb.
++
++config PROC_STRIPPED
++ default n
++ depends on EXPERT
++ bool "Strip non-essential /proc functionality to reduce code size"
+--- a/fs/proc/consoles.c
++++ b/fs/proc/consoles.c
+@@ -108,6 +108,9 @@ static const struct file_operations proc
+
+ static int __init proc_consoles_init(void)
+ {
++ if (IS_ENABLED(CONFIG_PROC_STRIPPED))
++ return 0;
++
+ proc_create("consoles", 0, NULL, &proc_consoles_operations);
+ return 0;
+ }
+--- a/fs/proc/proc_tty.c
++++ b/fs/proc/proc_tty.c
+@@ -143,7 +143,10 @@ static const struct file_operations proc
+ void proc_tty_register_driver(struct tty_driver *driver)
+ {
+ struct proc_dir_entry *ent;
+-
++
++ if (IS_ENABLED(CONFIG_PROC_STRIPPED))
++ return;
++
+ if (!driver->driver_name || driver->proc_entry ||
+ !driver->ops->proc_fops)
+ return;
+@@ -160,6 +163,9 @@ void proc_tty_unregister_driver(struct t
+ {
+ struct proc_dir_entry *ent;
+
++ if (IS_ENABLED(CONFIG_PROC_STRIPPED))
++ return;
++
+ ent = driver->proc_entry;
+ if (!ent)
+ return;
+@@ -174,6 +180,9 @@ void proc_tty_unregister_driver(struct t
+ */
+ void __init proc_tty_init(void)
+ {
++ if (IS_ENABLED(CONFIG_PROC_STRIPPED))
++ return;
++
+ if (!proc_mkdir("tty", NULL))
+ return;
+ proc_tty_ldisc = proc_mkdir("tty/ldisc", NULL);
+--- a/kernel/exec_domain.c
++++ b/kernel/exec_domain.c
+@@ -173,6 +173,8 @@ static const struct file_operations exec
+
+ static int __init proc_execdomains_init(void)
+ {
++ if (IS_ENABLED(CONFIG_PROC_STRIPPED))
++ return 0;
+ proc_create("execdomains", 0, NULL, &execdomains_proc_fops);
+ return 0;
+ }
+--- a/kernel/irq/proc.c
++++ b/kernel/irq/proc.c
+@@ -311,6 +311,9 @@ void register_irq_proc(unsigned int irq,
+ {
+ char name [MAX_NAMELEN];
+
++ if (IS_ENABLED(CONFIG_PROC_STRIPPED) && !IS_ENABLED(CONFIG_SMP))
++ return;
++
+ if (!root_irq_dir || (desc->irq_data.chip == &no_irq_chip) || desc->dir)
+ return;
+
+@@ -347,6 +350,9 @@ void unregister_irq_proc(unsigned int ir
+ {
+ char name [MAX_NAMELEN];
+
++ if (IS_ENABLED(CONFIG_PROC_STRIPPED) && !IS_ENABLED(CONFIG_SMP))
++ return;
++
+ if (!root_irq_dir || !desc->dir)
+ return;
+ #ifdef CONFIG_SMP
+@@ -386,6 +392,9 @@ void init_irq_proc(void)
+ unsigned int irq;
+ struct irq_desc *desc;
+
++ if (IS_ENABLED(CONFIG_PROC_STRIPPED) && !IS_ENABLED(CONFIG_SMP))
++ return;
++
+ /* create /proc/irq */
+ root_irq_dir = proc_mkdir("irq", NULL);
+ if (!root_irq_dir)
+--- a/kernel/time/timer_list.c
++++ b/kernel/time/timer_list.c
+@@ -293,6 +293,8 @@ static int __init init_timer_list_procfs
+ {
+ struct proc_dir_entry *pe;
+
++ if (IS_ENABLED(CONFIG_PROC_STRIPPED))
++ return 0;
+ pe = proc_create("timer_list", 0444, NULL, &timer_list_fops);
+ if (!pe)
+ return -ENOMEM;
+--- a/mm/vmalloc.c
++++ b/mm/vmalloc.c
+@@ -2638,6 +2638,8 @@ static const struct file_operations proc
+
+ static int __init proc_vmalloc_init(void)
+ {
++ if (IS_ENABLED(CONFIG_PROC_STRIPPED))
++ return 0;
+ proc_create("vmallocinfo", S_IRUSR, NULL, &proc_vmalloc_operations);
+ return 0;
+ }
+--- a/mm/vmstat.c
++++ b/mm/vmstat.c
+@@ -1224,10 +1224,12 @@ static int __init setup_vmstat(void)
+ start_cpu_timer(cpu);
+ #endif
+ #ifdef CONFIG_PROC_FS
+- proc_create("buddyinfo", S_IRUGO, NULL, &fragmentation_file_operations);
+- proc_create("pagetypeinfo", S_IRUGO, NULL, &pagetypeinfo_file_ops);
++ if (!IS_ENABLED(CONFIG_PROC_STRIPPED)) {
++ proc_create("buddyinfo", S_IRUGO, NULL, &fragmentation_file_operations);
++ proc_create("pagetypeinfo", S_IRUGO, NULL, &pagetypeinfo_file_ops);
++ proc_create("zoneinfo", S_IRUGO, NULL, &proc_zoneinfo_file_operations);
++ }
+ proc_create("vmstat", S_IRUGO, NULL, &proc_vmstat_file_operations);
+- proc_create("zoneinfo", S_IRUGO, NULL, &proc_zoneinfo_file_operations);
+ #endif
+ return 0;
+ }
+--- a/net/8021q/vlanproc.c
++++ b/net/8021q/vlanproc.c
+@@ -127,6 +127,9 @@ void vlan_proc_cleanup(struct net *net)
+ {
+ struct vlan_net *vn = net_generic(net, vlan_net_id);
+
++ if (IS_ENABLED(CONFIG_PROC_STRIPPED))
++ return;
++
+ if (vn->proc_vlan_conf)
+ remove_proc_entry(name_conf, vn->proc_vlan_dir);
+
+@@ -146,6 +149,9 @@ int __net_init vlan_proc_init(struct net
+ {
+ struct vlan_net *vn = net_generic(net, vlan_net_id);
+
++ if (IS_ENABLED(CONFIG_PROC_STRIPPED))
++ return 0;
++
+ vn->proc_vlan_dir = proc_net_mkdir(net, name_root, net->proc_net);
+ if (!vn->proc_vlan_dir)
+ goto err;
+--- a/net/core/dev.c
++++ b/net/core/dev.c
+@@ -4478,9 +4478,11 @@ static int __net_init dev_proc_net_init(
+
+ if (!proc_net_fops_create(net, "dev", S_IRUGO, &dev_seq_fops))
+ goto out;
+- if (!proc_net_fops_create(net, "softnet_stat", S_IRUGO, &softnet_seq_fops))
++ if (!IS_ENABLED(CONFIG_PROC_STRIPPED) &&
++ !proc_net_fops_create(net, "softnet_stat", S_IRUGO, &softnet_seq_fops))
+ goto out_dev;
+- if (!proc_net_fops_create(net, "ptype", S_IRUGO, &ptype_seq_fops))
++ if (!IS_ENABLED(CONFIG_PROC_STRIPPED) &&
++ !proc_net_fops_create(net, "ptype", S_IRUGO, &ptype_seq_fops))
+ goto out_softnet;
+
+ if (wext_proc_init(net))
+@@ -4489,9 +4491,11 @@ static int __net_init dev_proc_net_init(
+ out:
+ return rc;
+ out_ptype:
+- proc_net_remove(net, "ptype");
++ if (!IS_ENABLED(CONFIG_PROC_STRIPPED))
++ proc_net_remove(net, "ptype");
+ out_softnet:
+- proc_net_remove(net, "softnet_stat");
++ if (!IS_ENABLED(CONFIG_PROC_STRIPPED))
++ proc_net_remove(net, "softnet_stat");
+ out_dev:
+ proc_net_remove(net, "dev");
+ goto out;
+@@ -4501,8 +4505,10 @@ static void __net_exit dev_proc_net_exit
+ {
+ wext_proc_exit(net);
+
+- proc_net_remove(net, "ptype");
+- proc_net_remove(net, "softnet_stat");
++ if (!IS_ENABLED(CONFIG_PROC_STRIPPED)) {
++ proc_net_remove(net, "ptype");
++ proc_net_remove(net, "softnet_stat");
++ }
+ proc_net_remove(net, "dev");
+ }
+
+--- a/net/core/sock.c
++++ b/net/core/sock.c
+@@ -2773,6 +2773,8 @@ static __net_initdata struct pernet_oper
+
+ static int __init proto_init(void)
+ {
++ if (IS_ENABLED(CONFIG_PROC_STRIPPED))
++ return 0;
+ return register_pernet_subsys(&proto_net_ops);
+ }
+
+--- a/net/ipv4/fib_trie.c
++++ b/net/ipv4/fib_trie.c
+@@ -2607,10 +2607,12 @@ static const struct file_operations fib_
+
+ int __net_init fib_proc_init(struct net *net)
+ {
+- if (!proc_net_fops_create(net, "fib_trie", S_IRUGO, &fib_trie_fops))
++ if (!IS_ENABLED(CONFIG_PROC_STRIPPED) &&
++ !proc_net_fops_create(net, "fib_trie", S_IRUGO, &fib_trie_fops))
+ goto out1;
+
+- if (!proc_net_fops_create(net, "fib_triestat", S_IRUGO,
++ if (!IS_ENABLED(CONFIG_PROC_STRIPPED) &&
++ !proc_net_fops_create(net, "fib_triestat", S_IRUGO,
+ &fib_triestat_fops))
+ goto out2;
+
+@@ -2629,8 +2631,10 @@ out1:
+
+ void __net_exit fib_proc_exit(struct net *net)
+ {
+- proc_net_remove(net, "fib_trie");
+- proc_net_remove(net, "fib_triestat");
++ if (!IS_ENABLED(CONFIG_PROC_STRIPPED)) {
++ proc_net_remove(net, "fib_trie");
++ proc_net_remove(net, "fib_triestat");
++ }
+ proc_net_remove(net, "route");
+ }
+
+--- a/net/ipv4/igmp.c
++++ b/net/ipv4/igmp.c
+@@ -2673,6 +2673,8 @@ static struct pernet_operations igmp_net
+
+ int __init igmp_mc_proc_init(void)
+ {
++ if (IS_ENABLED(CONFIG_PROC_STRIPPED))
++ return 0;
+ return register_pernet_subsys(&igmp_net_ops);
+ }
+ #endif
+--- a/net/ipv4/proc.c
++++ b/net/ipv4/proc.c
+@@ -502,6 +502,9 @@ static __net_initdata struct pernet_oper
+
+ int __init ip_misc_proc_init(void)
+ {
++ if (IS_ENABLED(CONFIG_PROC_STRIPPED))
++ return 0;
++
+ return register_pernet_subsys(&ip_proc_ops);
+ }
+
+--- a/net/ipv4/route.c
++++ b/net/ipv4/route.c
+@@ -427,6 +427,9 @@ static struct pernet_operations ip_rt_pr
+
+ static int __init ip_rt_proc_init(void)
+ {
++ if (IS_ENABLED(CONFIG_PROC_STRIPPED))
++ return 0;
++
+ return register_pernet_subsys(&ip_rt_proc_ops);
+ }
+
+--- a/ipc/msg.c
++++ b/ipc/msg.c
+@@ -135,6 +135,9 @@ void __init msg_init(void)
+ printk(KERN_INFO "msgmni has been set to %d\n",
+ init_ipc_ns.msg_ctlmni);
+
++ if (IS_ENABLED(CONFIG_PROC_STRIPPED))
++ return;
++
+ ipc_init_proc_interface("sysvipc/msg",
+ " key msqid perms cbytes qnum lspid lrpid uid gid cuid cgid stime rtime ctime\n",
+ IPC_MSG_IDS, sysvipc_msg_proc_show);
+--- a/ipc/sem.c
++++ b/ipc/sem.c
+@@ -185,6 +185,8 @@ void sem_exit_ns(struct ipc_namespace *n
+ void __init sem_init (void)
+ {
+ sem_init_ns(&init_ipc_ns);
++ if (IS_ENABLED(CONFIG_PROC_STRIPPED))
++ return;
+ ipc_init_proc_interface("sysvipc/sem",
+ " key semid perms nsems uid gid cuid cgid otime ctime\n",
+ IPC_SEM_IDS, sysvipc_sem_proc_show);
+--- a/ipc/shm.c
++++ b/ipc/shm.c
+@@ -115,6 +115,8 @@ pure_initcall(ipc_ns_init);
+
+ void __init shm_init (void)
+ {
++ if (IS_ENABLED(CONFIG_PROC_STRIPPED))
++ return;
+ ipc_init_proc_interface("sysvipc/shm",
+ #if BITS_PER_LONG <= 32
+ " key shmid perms size cpid lpid nattch uid gid cuid cgid atime dtime ctime rss swap\n",
+--- a/ipc/util.c
++++ b/ipc/util.c
+@@ -148,6 +148,9 @@ void __init ipc_init_proc_interface(cons
+ struct proc_dir_entry *pde;
+ struct ipc_proc_iface *iface;
+
++ if (IS_ENABLED(CONFIG_PROC_STRIPPED))
++ return;
++
+ iface = kmalloc(sizeof(*iface), GFP_KERNEL);
+ if (!iface)
+ return;
diff --git a/target/linux/generic/patches-3.7/903-debloat_direct_io.patch b/target/linux/generic/patches-3.7/903-debloat_direct_io.patch
new file mode 100644
index 000000000..5cc5e7801
--- /dev/null
+++ b/target/linux/generic/patches-3.7/903-debloat_direct_io.patch
@@ -0,0 +1,84 @@
+--- a/fs/Kconfig
++++ b/fs/Kconfig
+@@ -62,6 +62,11 @@ config FILE_LOCKING
+ for filesystems like NFS and for the flock() system
+ call. Disabling this option saves about 11k.
+
++config DIRECT_IO
++ bool "Enable O_DIRECT support" if EXPERT
++ depends on BLOCK
++ default y
++
+ source "fs/notify/Kconfig"
+
+ source "fs/quota/Kconfig"
+--- a/fs/Makefile
++++ b/fs/Makefile
+@@ -14,7 +14,8 @@ obj-y := open.o read_write.o file_table.
+ stack.o fs_struct.o statfs.o
+
+ ifeq ($(CONFIG_BLOCK),y)
+-obj-y += buffer.o bio.o block_dev.o direct-io.o mpage.o ioprio.o
++obj-y += buffer.o bio.o block_dev.o mpage.o ioprio.o
++obj-$(CONFIG_DIRECT_IO) += direct-io.o
+ else
+ obj-y += no-block.o
+ endif
+--- a/include/linux/fs.h
++++ b/include/linux/fs.h
+@@ -2444,12 +2444,26 @@ enum {
+ DIO_SKIP_HOLES = 0x02,
+ };
+
++#ifdef CONFIG_DIRECT_IO
+ void dio_end_io(struct bio *bio, int error);
+
+ ssize_t __blockdev_direct_IO(int rw, struct kiocb *iocb, struct inode *inode,
+ struct block_device *bdev, const struct iovec *iov, loff_t offset,
+ unsigned long nr_segs, get_block_t get_block, dio_iodone_t end_io,
+ dio_submit_t submit_io, int flags);
++#else
++static inline void dio_end_io(struct bio *bio, int error)
++{
++}
++static inline ssize_t __blockdev_direct_IO(int rw, struct kiocb *iocb, struct inode *inode,
++ struct block_device *bdev, const struct iovec *iov, loff_t offset,
++ unsigned long nr_segs, get_block_t get_block, dio_iodone_t end_io,
++ dio_submit_t submit_io, int flags)
++{
++ return -EOPNOTSUPP;
++}
++#endif
++
+
+ static inline ssize_t blockdev_direct_IO(int rw, struct kiocb *iocb,
+ struct inode *inode, const struct iovec *iov, loff_t offset,
+--- a/fs/fcntl.c
++++ b/fs/fcntl.c
+@@ -51,8 +51,10 @@ static int setfl(int fd, struct file * f
+ arg |= O_NONBLOCK;
+
+ if (arg & O_DIRECT) {
++#ifdef CONFIG_DIRECT_IO
+ if (!filp->f_mapping || !filp->f_mapping->a_ops ||
+ !filp->f_mapping->a_ops->direct_IO)
++#endif
+ return -EINVAL;
+ }
+
+--- a/fs/open.c
++++ b/fs/open.c
+@@ -630,9 +630,12 @@ int open_check_o_direct(struct file *f)
+ {
+ /* NB: we're sure to have correct a_ops only after f_op->open */
+ if (f->f_flags & O_DIRECT) {
++#ifdef CONFIG_DIRECT_IO
+ if (!f->f_mapping->a_ops ||
+ ((!f->f_mapping->a_ops->direct_IO) &&
+- (!f->f_mapping->a_ops->get_xip_mem))) {
++ (!f->f_mapping->a_ops->get_xip_mem)))
++#endif
++ {
+ return -EINVAL;
+ }
+ }
diff --git a/target/linux/generic/patches-3.7/920-unable_to_open_console.patch b/target/linux/generic/patches-3.7/920-unable_to_open_console.patch
index f9e12ac61..731fe457a 100644
--- a/target/linux/generic/patches-3.7/920-unable_to_open_console.patch
+++ b/target/linux/generic/patches-3.7/920-unable_to_open_console.patch
@@ -1,6 +1,6 @@
--- a/init/main.c
+++ b/init/main.c
-@@ -877,7 +877,7 @@ static void __init kernel_init_freeable(
+@@ -877,7 +877,7 @@ static noinline void __init kernel_init_
/* Open the /dev/console on the rootfs, this should never fail */
if (sys_open((const char __user *) "/dev/console", O_RDWR, 0) < 0)
diff --git a/target/linux/generic/patches-3.7/930-crashlog.patch b/target/linux/generic/patches-3.7/930-crashlog.patch
index a58a13bae..a241c45e8 100644
--- a/target/linux/generic/patches-3.7/930-crashlog.patch
+++ b/target/linux/generic/patches-3.7/930-crashlog.patch
@@ -26,7 +26,7 @@
+config CRASHLOG
+ bool "Crash logging"
-+ depends on (!NO_BOOTMEM || HAVE_MEMBLOCK) && !(ARM || SPARC)
++ depends on (!NO_BOOTMEM || HAVE_MEMBLOCK) && !(ARM || SPARC || PPC)
+
config BLK_DEV_INITRD
bool "Initial RAM filesystem and RAM disk (initramfs/initrd) support"
diff --git a/target/linux/generic/patches-3.7/941-ocf_20120127.patch b/target/linux/generic/patches-3.7/941-ocf_20120127.patch
index 46fd02a2f..326471421 100644
--- a/target/linux/generic/patches-3.7/941-ocf_20120127.patch
+++ b/target/linux/generic/patches-3.7/941-ocf_20120127.patch
@@ -90,7 +90,7 @@
* Entropy extraction routines
--- a/fs/fcntl.c
+++ b/fs/fcntl.c
-@@ -146,6 +146,7 @@ pid_t f_getown(struct file *filp)
+@@ -148,6 +148,7 @@ pid_t f_getown(struct file *filp)
read_unlock(&filp->f_owner.lock);
return pid;
}
diff --git a/target/linux/generic/patches-3.7/950-vm_exports.patch b/target/linux/generic/patches-3.7/950-vm_exports.patch
index eaf3e2333..d72f132d6 100644
--- a/target/linux/generic/patches-3.7/950-vm_exports.patch
+++ b/target/linux/generic/patches-3.7/950-vm_exports.patch
@@ -1,6 +1,6 @@
--- a/mm/shmem.c
+++ b/mm/shmem.c
-@@ -2769,6 +2769,15 @@ EXPORT_SYMBOL_GPL(shmem_truncate_range);
+@@ -2781,6 +2781,15 @@ EXPORT_SYMBOL_GPL(shmem_truncate_range);
/* common code */
@@ -16,7 +16,7 @@
/**
* shmem_file_setup - get an unlinked file living in tmpfs
* @name: name for dentry (to be seen in /proc/<pid>/maps
-@@ -2845,11 +2854,8 @@ int shmem_zero_setup(struct vm_area_stru
+@@ -2857,11 +2866,8 @@ int shmem_zero_setup(struct vm_area_stru
file = shmem_file_setup("dev/zero", size, vma->vm_flags);
if (IS_ERR(file))
return PTR_ERR(file);
@@ -59,7 +59,7 @@
* When we die, we re-parent all our children, and try to:
--- a/kernel/sched/core.c
+++ b/kernel/sched/core.c
-@@ -3565,6 +3565,7 @@ int can_nice(const struct task_struct *p
+@@ -3566,6 +3566,7 @@ int can_nice(const struct task_struct *p
return (nice_rlim <= task_rlimit(p, RLIMIT_NICE) ||
capable(CAP_SYS_NICE));
}
@@ -69,7 +69,7 @@
--- a/mm/memory.c
+++ b/mm/memory.c
-@@ -1415,6 +1415,7 @@ void zap_page_range(struct vm_area_struc
+@@ -1420,6 +1420,7 @@ void zap_page_range(struct vm_area_struc
mmu_notifier_invalidate_range_end(mm, start, end);
tlb_finish_mmu(&tlb, start, end);
}