diff options
Diffstat (limited to 'target/linux/generic/patches-3.7')
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); } |
