kernel: remove kernel 3.6

kernel 3.6 is not used by any target any more, remove it.

Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>

SVN-Revision: 41834
This commit is contained in:
Hauke Mehrtens 2014-07-26 12:23:56 +00:00
parent e7ece301fe
commit 009e36806b
168 changed files with 0 additions and 38924 deletions

View file

@ -1,195 +0,0 @@
CONFIG_ALIGNMENT_TRAP=y
CONFIG_ARCH_BINFMT_ELF_RANDOMIZE_PIE=y
CONFIG_ARCH_EP93XX=y
CONFIG_ARCH_HAS_CPU_IDLE_WAIT=y
CONFIG_ARCH_HAS_HOLES_MEMORYMODEL=y
CONFIG_ARCH_NR_GPIO=0
CONFIG_ARCH_REQUIRE_GPIOLIB=y
# CONFIG_ARCH_SELECT_MEMORY_MODEL is not set
# CONFIG_ARCH_SPARSEMEM_DEFAULT is not set
CONFIG_ARCH_SUSPEND_POSSIBLE=y
CONFIG_ARCH_USES_GETTIMEOFFSET=y
CONFIG_ARM=y
CONFIG_ARM_AMBA=y
# CONFIG_ARM_CPU_SUSPEND is not set
CONFIG_ARM_L1_CACHE_SHIFT=5
CONFIG_ARM_NR_BANKS=16
CONFIG_ARM_PATCH_PHYS_VIRT=y
# CONFIG_ARM_SP805_WATCHDOG is not set
CONFIG_ARM_THUMB=y
CONFIG_ARM_VIC=y
CONFIG_ARM_VIC_NR=2
# CONFIG_ARPD is not set
# CONFIG_BLK_DEV_INITRD is not set
# CONFIG_CACHE_L2X0 is not set
CONFIG_CC_OPTIMIZE_FOR_SIZE=y
CONFIG_CLKDEV_LOOKUP=y
CONFIG_CMDLINE="console=ttyAM0,57600 init=/etc/preinit"
CONFIG_CMDLINE_FROM_BOOTLOADER=y
CONFIG_CONSOLE_TRANSLATIONS=y
CONFIG_CPU_32v4T=y
CONFIG_CPU_ABRT_EV4T=y
CONFIG_CPU_ARM920T=y
CONFIG_CPU_CACHE_V4WT=y
CONFIG_CPU_CACHE_VIVT=y
CONFIG_CPU_COPY_V4WB=y
CONFIG_CPU_CP15=y
CONFIG_CPU_CP15_MMU=y
# CONFIG_CPU_DCACHE_WRITETHROUGH is not set
# CONFIG_CPU_ICACHE_DISABLE is not set
CONFIG_CPU_PABRT_LEGACY=y
CONFIG_CPU_TLB_V4WBI=y
CONFIG_CPU_USE_DOMAINS=y
CONFIG_CRC7=y
CONFIG_CRC_ITU_T=y
CONFIG_CRUNCH=y
# CONFIG_DEBUG_USER is not set
CONFIG_DUMMY_CONSOLE=y
CONFIG_ELF_CORE=y
# CONFIG_ENABLE_WARN_DEPRECATED is not set
CONFIG_EP93XX_EARLY_UART1=y
# CONFIG_EP93XX_EARLY_UART2 is not set
# CONFIG_EP93XX_EARLY_UART3 is not set
CONFIG_EP93XX_ETH=y
# CONFIG_EP93XX_PWM is not set
CONFIG_EP93XX_SDCE0_PHYS_OFFSET=y
# CONFIG_EP93XX_SDCE1_PHYS_OFFSET is not set
# CONFIG_EP93XX_SDCE2_PHYS_OFFSET is not set
# CONFIG_EP93XX_SDCE3_ASYNC_PHYS_OFFSET is not set
# CONFIG_EP93XX_SDCE3_SYNC_PHYS_OFFSET is not set
CONFIG_EP93XX_WATCHDOG=y
CONFIG_FONTS=y
# CONFIG_FONT_10x18 is not set
# CONFIG_FONT_6x11 is not set
# CONFIG_FONT_7x14 is not set
CONFIG_FONT_8x16=y
CONFIG_FONT_8x8=y
# CONFIG_FONT_ACORN_8x8 is not set
# CONFIG_FONT_MINI_4x6 is not set
# CONFIG_FONT_PEARL_8x8 is not set
# CONFIG_FONT_SUN12x22 is not set
# CONFIG_FONT_SUN8x16 is not set
CONFIG_FRAMEBUFFER_CONSOLE=y
# CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY is not set
# CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set
CONFIG_FRAME_POINTER=y
CONFIG_GENERIC_ATOMIC64=y
CONFIG_GENERIC_BUG=y
CONFIG_GENERIC_GPIO=y
CONFIG_GENERIC_IRQ_SHOW=y
CONFIG_GENERIC_PCI_IOMAP=y
CONFIG_GPIOLIB=y
CONFIG_GPIO_EP93XX=y
CONFIG_GPIO_GENERIC=y
# CONFIG_GPIO_PL061 is not set
# CONFIG_HAMRADIO is not set
CONFIG_HARDIRQS_SW_RESEND=y
CONFIG_HAS_DMA=y
CONFIG_HAS_IOMEM=y
CONFIG_HAS_IOPORT=y
CONFIG_HAVE_AOUT=y
CONFIG_HAVE_ARCH_KGDB=y
CONFIG_HAVE_ARCH_PFN_VALID=y
CONFIG_HAVE_CLK=y
CONFIG_HAVE_C_RECORDMCOUNT=y
CONFIG_HAVE_DMA_API_DEBUG=y
CONFIG_HAVE_DYNAMIC_FTRACE=y
CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y
CONFIG_HAVE_FUNCTION_TRACER=y
CONFIG_HAVE_GENERIC_DMA_COHERENT=y
CONFIG_HAVE_GENERIC_HARDIRQS=y
CONFIG_HAVE_IRQ_WORK=y
CONFIG_HAVE_KERNEL_GZIP=y
CONFIG_HAVE_KERNEL_LZMA=y
CONFIG_HAVE_KERNEL_LZO=y
CONFIG_HAVE_KERNEL_XZ=y
CONFIG_HAVE_LATENCYTOP_SUPPORT=y
CONFIG_HAVE_MEMBLOCK=y
CONFIG_HAVE_OPROFILE=y
CONFIG_HAVE_PERF_EVENTS=y
CONFIG_HAVE_PROC_CPU=y
CONFIG_HAVE_REGS_AND_STACK_ACCESS_API=y
CONFIG_HAVE_SPARSE_IRQ=y
CONFIG_HW_CONSOLE=y
CONFIG_I2C=y
CONFIG_I2C_ALGOBIT=y
CONFIG_I2C_BOARDINFO=y
CONFIG_I2C_CHARDEV=y
CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y
CONFIG_INPUT=y
# CONFIG_INPUT_MISC is not set
CONFIG_INPUT_TOUCHSCREEN=y
CONFIG_IRQ_DOMAIN=y
CONFIG_KTIME_SCALAR=y
CONFIG_LOGO=y
CONFIG_LOGO_LINUX_CLUT224=y
CONFIG_LOGO_LINUX_MONO=y
CONFIG_LOGO_LINUX_VGA16=y
CONFIG_LOG_BUF_SHIFT=16
# CONFIG_MACH_EDB9302A is not set
# CONFIG_MACH_EDB9307A is not set
# CONFIG_MACH_EDB9315A is not set
CONFIG_MACH_SIM_ONE=y
# CONFIG_MACH_SNAPPER_CL15 is not set
# CONFIG_MACH_VISION_EP9307 is not set
# CONFIG_MFD_T7L66XB is not set
CONFIG_MMC=y
CONFIG_MMC_BLOCK=y
CONFIG_MMC_SPI=y
CONFIG_MODULE_FORCE_UNLOAD=y
CONFIG_MTD_CFI_ADV_OPTIONS=y
# CONFIG_MTD_CFI_GEOMETRY is not set
CONFIG_MTD_CFI_STAA=y
# CONFIG_MTD_COMPLEX_MAPPINGS is not set
CONFIG_MTD_PHYSMAP=y
CONFIG_MTD_RAM=y
CONFIG_MULTI_IRQ_HANDLER=y
CONFIG_NEED_DMA_MAP_STATE=y
CONFIG_NEED_MACH_MEMORY_H=y
CONFIG_NEED_PER_CPU_KM=y
CONFIG_PAGEFLAGS_EXTENDED=y
CONFIG_PAGE_OFFSET=0xC0000000
# CONFIG_PCI_SYSCALL is not set
CONFIG_PERF_USE_VMALLOC=y
# CONFIG_PREEMPT_RCU is not set
# CONFIG_SCSI_DMA is not set
# CONFIG_SERIAL_8250 is not set
CONFIG_SERIAL_AMBA_PL010=y
CONFIG_SERIAL_AMBA_PL010_CONSOLE=y
# CONFIG_SERIAL_AMBA_PL011 is not set
CONFIG_SPI=y
CONFIG_SPI_BITBANG=y
CONFIG_SPI_EP93XX=y
CONFIG_SPI_MASTER=y
CONFIG_SPLIT_PTLOCK_CPUS=999999
CONFIG_SYS_SUPPORTS_APM_EMULATION=y
# CONFIG_TCP_CONG_ADVANCED is not set
# CONFIG_TOUCHSCREEN_ATMEL_MXT is not set
# CONFIG_TOUCHSCREEN_AUO_PIXCIR is not set
# CONFIG_TOUCHSCREEN_BU21013 is not set
# CONFIG_TOUCHSCREEN_DYNAPRO is not set
# CONFIG_TOUCHSCREEN_EGALAX is not set
# CONFIG_TOUCHSCREEN_EP93XX is not set
# CONFIG_TOUCHSCREEN_HAMPSHIRE is not set
# CONFIG_TOUCHSCREEN_MAX11801 is not set
# CONFIG_TOUCHSCREEN_PIXCIR is not set
# CONFIG_TOUCHSCREEN_ST1232 is not set
# CONFIG_TOUCHSCREEN_TSC2005 is not set
# CONFIG_TOUCHSCREEN_TSC_SERIO is not set
CONFIG_UID16=y
# CONFIG_USB_ARCH_HAS_EHCI is not set
# CONFIG_USB_ARCH_HAS_XHCI is not set
CONFIG_USB_SUPPORT=y
CONFIG_VECTORS_BASE=0xffff0000
CONFIG_VIDEO_OUTPUT_CONTROL=y
CONFIG_VM_EVENT_COUNTERS=y
CONFIG_VT=y
CONFIG_VT_CONSOLE=y
# CONFIG_VT_HW_CONSOLE_BINDING is not set
CONFIG_XZ_DEC_ARM=y
CONFIG_XZ_DEC_BCJ=y
CONFIG_ZBOOT_ROM_BSS=0x0
CONFIG_ZBOOT_ROM_TEXT=0x0
CONFIG_ZONE_DMA_FLAG=0

View file

@ -1,70 +0,0 @@
This patch puts the EP93xx chip revision and unique ID into /proc/cpuinfo.
This is necessary to be able to set a unique MAC address for DHCP purposes
by adding a line to /etc/network/interfaces:
# Generate a unique locally-assigned MAC address from the CPU serial number
pre-up ifconfig eth0 hw ether `sed -n 's/^Serial.* 000000/02/p' /proc/cpuinfo`
It uses the chip revision reading code in the ep93xx-chip-revision patch.
Really, this is wrong, since /proc/cpuinfo should report the revision and
serial number of the ARM920T processor, while these are the rev and serial
of the EP93xx SoC. In a future kernel (>2.6.34) there may be a new file
/proc/socinfo for this information.
-martinwguy 14 May 2010
--- a/arch/arm/kernel/setup.c
+++ b/arch/arm/kernel/setup.c
@@ -56,6 +56,12 @@
#include <asm/unwind.h>
#include <asm/memblock.h>
+#if defined(CONFIG_ARCH_EP93XX)
+#include <asm/io.h>
+#include <mach/platform.h>
+#include <mach/ep93xx-regs.h>
+#endif
+
#if defined(CONFIG_DEPRECATED_PARAM_STRUCT)
#include "compat.h"
#endif
@@ -1107,9 +1113,16 @@ static int c_show(struct seq_file *m, vo
seq_puts(m, "\n");
seq_printf(m, "Hardware\t: %s\n", machine_name);
+#if defined(CONFIG_ARCH_EP93XX)
+ seq_printf(m, "Revision\t: %04x\n",
+ ep93xx_chip_revision());
+ seq_printf(m, "Serial\t\t: %016x\n",
+ *((unsigned int *)EP93XX_SECURITY_UNIQID));
+#else
seq_printf(m, "Revision\t: %04x\n", system_rev);
seq_printf(m, "Serial\t\t: %08x%08x\n",
system_serial_high, system_serial_low);
+#endif
return 0;
}
--- a/arch/arm/mach-ep93xx/soc.h
+++ b/arch/arm/mach-ep93xx/soc.h
@@ -82,8 +82,6 @@
#define EP93XX_I2S_PHYS_BASE EP93XX_APB_PHYS(0x00020000)
#define EP93XX_I2S_BASE EP93XX_APB_IOMEM(0x00020000)
-#define EP93XX_SECURITY_BASE EP93XX_APB_IOMEM(0x00030000)
-
#define EP93XX_AAC_PHYS_BASE EP93XX_APB_PHYS(0x00080000)
#define EP93XX_AAC_BASE EP93XX_APB_IOMEM(0x00080000)
--- a/arch/arm/mach-ep93xx/include/mach/ep93xx-regs.h
+++ b/arch/arm/mach-ep93xx/include/mach/ep93xx-regs.h
@@ -38,4 +38,8 @@
#define EP93XX_UART3_PHYS_BASE EP93XX_APB_PHYS(0x000e0000)
#define EP93XX_UART3_BASE EP93XX_APB_IOMEM(0x000e0000)
+#define EP93XX_SECURITY_BASE EP93XX_APB_IOMEM(0x00030000)
+#define EP93XX_SECURITY_REG(x) (EP93XX_SECURITY_BASE + (x))
+#define EP93XX_SECURITY_UNIQID EP93XX_SECURITY_REG(0x2440)
+
#endif

File diff suppressed because it is too large Load diff

View file

@ -1,180 +0,0 @@
This enables the mmc-over-spi driver for the Sim.One board, based on Mika's
patch, which used a GPIO for chip select in stead of the default SFRMOUT pin.
I've modified it to use the usual SFRMOUT; if you've modified your Sim.One
board to use a GPIO instead, uncomment and modify
// #define MMC_CHIP_SELECT_GPIO EP93XX_GPIO_LINE_EGPIO15
in the source file.
-martinwguy, 14 May 2010
From: Mika Westerberg <mika.westerberg@iki.fi>
Date: Wed, 28 Apr 2010 08:42:46 +0300
Subject: [PATCH] ep93xx: simone: added board specific SPI support for MMC/SD cards
This includes setting up EGPIOs 0 and 9 for card detection and chip select
respectively.
--- a/arch/arm/mach-ep93xx/simone.c
+++ b/arch/arm/mach-ep93xx/simone.c
@@ -18,12 +18,17 @@
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/platform_device.h>
+#include <linux/gpio.h>
#include <linux/i2c.h>
#include <linux/i2c-gpio.h>
+#include <linux/mmc/host.h>
+#include <linux/spi/spi.h>
+#include <linux/spi/mmc_spi.h>
#include <mach/hardware.h>
#include <mach/fb.h>
#include <mach/gpio-ep93xx.h>
+#include <mach/ep93xx_spi.h>
#include <asm/hardware/vic.h>
#include <asm/mach-types.h>
@@ -41,6 +46,135 @@ static struct ep93xxfb_mach_info __initd
.flags = EP93XXFB_USE_SDCSN0 | EP93XXFB_PCLK_FALLING,
};
+/*
+ * GPIO lines used for MMC card detection.
+ */
+#define MMC_CARD_DETECT_GPIO EP93XX_GPIO_LINE_EGPIO0
+
+/*
+ * If you have hacked your Sim.One to use a GPIO as SD card chip select
+ * (SD pin 1), uncomment the following line.
+ * The example, EGPIO15, is on TP17 near the CPU.
+ */
+// #define MMC_CHIP_SELECT_GPIO EP93XX_GPIO_LINE_EGPIO15
+
+/*
+ * MMC SPI chip select GPIO handling. If you are using SFRMOUT (SFRM1) signal,
+ * you can leave these empty and pass NULL as .controller_data.
+ */
+
+#ifdef MMC_CHIP_SELECT_GPIO
+static int simone_mmc_spi_setup(struct spi_device *spi)
+{
+ unsigned int gpio = MMC_CHIP_SELECT_GPIO;
+ int err;
+
+ err = gpio_request(gpio, spi->modalias);
+ if (err)
+ return err;
+
+ err = gpio_direction_output(gpio, 1);
+ if (err) {
+ gpio_free(gpio);
+ return err;
+ }
+
+ return 0;
+}
+
+static void simone_mmc_spi_cleanup(struct spi_device *spi)
+{
+ unsigned int gpio = MMC_CHIP_SELECT_GPIO;
+
+ gpio_set_value(gpio, 1);
+ gpio_direction_input(gpio);
+ gpio_free(gpio);
+}
+
+static void simone_mmc_spi_cs_control(struct spi_device *spi, int value)
+{
+ gpio_set_value(MMC_CHIP_SELECT_GPIO, value);
+}
+
+static struct ep93xx_spi_chip_ops simone_mmc_spi_ops = {
+ .setup = simone_mmc_spi_setup,
+ .cleanup = simone_mmc_spi_cleanup,
+ .cs_control = simone_mmc_spi_cs_control,
+};
+#endif
+
+/*
+ * MMC card detection GPIO setup.
+ */
+static int simone_mmc_spi_init(struct device *dev,
+ irqreturn_t (*irq_handler)(int, void *), void *mmc)
+{
+ unsigned int gpio = MMC_CARD_DETECT_GPIO;
+ int irq, err;
+
+ err = gpio_request(gpio, dev_name(dev));
+ if (err)
+ return err;
+
+ err = gpio_direction_input(gpio);
+ if (err)
+ goto fail;
+
+ irq = gpio_to_irq(gpio);
+ if (irq < 0)
+ goto fail;
+
+ err = request_irq(irq, irq_handler, IRQF_TRIGGER_FALLING,
+ "MMC card detect", mmc);
+ if (err)
+ goto fail;
+
+ printk(KERN_INFO "%s: using irq %d for MMC card detection\n",
+ dev_name(dev), irq);
+
+ return 0;
+fail:
+ gpio_free(gpio);
+ return err;
+}
+
+static void simone_mmc_spi_exit(struct device *dev, void *mmc)
+{
+ unsigned int gpio = MMC_CARD_DETECT_GPIO;
+
+ free_irq(gpio_to_irq(gpio), mmc);
+ gpio_free(gpio);
+}
+
+static struct mmc_spi_platform_data simone_mmc_spi_data = {
+ .init = simone_mmc_spi_init,
+ .exit = simone_mmc_spi_exit,
+ .detect_delay = 500,
+ .ocr_mask = MMC_VDD_32_33 | MMC_VDD_33_34,
+};
+
+static struct spi_board_info simone_spi_devices[] __initdata = {
+ {
+ .modalias = "mmc_spi",
+#ifdef MMC_CHIP_SELECT_GPIO
+ .controller_data = &simone_mmc_spi_ops,
+#endif
+ .platform_data = &simone_mmc_spi_data,
+ /*
+ * We use 10 MHz even though the maximum is 3.7 MHz. The driver
+ * will limit it automatically to max. frequency.
+ */
+ .max_speed_hz = 10 * 1000 * 1000,
+ .bus_num = 0,
+ .chip_select = 0,
+ .mode = SPI_MODE_3,
+ },
+};
+
+static struct ep93xx_spi_info simone_spi_info __initdata = {
+ .num_chipselect = ARRAY_SIZE(simone_spi_devices),
+};
+
static struct i2c_gpio_platform_data __initdata simone_i2c_gpio_data = {
.sda_pin = EP93XX_GPIO_LINE_EEDAT,
.sda_is_open_drain = 0,
@@ -75,6 +209,8 @@ static void __init simone_init_machine(v
ep93xx_register_fb(&simone_fb_info);
ep93xx_register_i2c(&simone_i2c_gpio_data, simone_i2c_board_info,
ARRAY_SIZE(simone_i2c_board_info));
+ ep93xx_register_spi(&simone_spi_info, simone_spi_devices,
+ ARRAY_SIZE(simone_spi_devices));
simone_register_audio();
}

File diff suppressed because it is too large Load diff

View file

@ -1,36 +0,0 @@
From 86e4cb35f2260374df4139c2352afe7fe247cb60 Mon Sep 17 00:00:00 2001
From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
Date: Mon, 6 Aug 2012 18:06:53 -0700
Subject: [PATCH] usb: host: ehci-platform: BUG_ON() to WARN_ON() on probe
Commit 86e4cb35f2260374df4139c2352afe7fe247cb60 upstream.
usb_ehci_pdata is certainly required in ehci-platform driver.
This patch avoids using BUG_ON() from driver,
and return from probe with WARN_ON() if pdata was NULL.
Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
Acked-by: Alan Stern <stern@rowland.harvard.edu>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/usb/host/ehci-platform.c | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
--- a/drivers/usb/host/ehci-platform.c
+++ b/drivers/usb/host/ehci-platform.c
@@ -82,10 +82,14 @@ static int __devinit ehci_platform_probe
{
struct usb_hcd *hcd;
struct resource *res_mem;
+ struct usb_ehci_pdata *pdata = dev->dev.platform_data;
int irq;
int err = -ENOMEM;
- BUG_ON(!dev->dev.platform_data);
+ if (!pdata) {
+ WARN_ON(1);
+ return -ENODEV;
+ }
if (usb_disabled())
return -ENODEV;

View file

@ -1,36 +0,0 @@
From b6dd245c4594482d46507a0bfd100439be367952 Mon Sep 17 00:00:00 2001
From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
Date: Mon, 6 Aug 2012 18:07:30 -0700
Subject: [PATCH] usb: host: ohci-platform: BUG_ON() to WARN_ON() on probe
Commit b6dd245c4594482d46507a0bfd100439be367952 upstream.
usb_ohci_pdata is certainly required in ohci-platform driver.
This patch avoids using BUG_ON() from driver,
and return from probe with WARN_ON() if pdata was NULL.
Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
Acked-by: Alan Stern <stern@rowland.harvard.edu>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/usb/host/ohci-platform.c | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
--- a/drivers/usb/host/ohci-platform.c
+++ b/drivers/usb/host/ohci-platform.c
@@ -83,10 +83,14 @@ static int __devinit ohci_platform_probe
{
struct usb_hcd *hcd;
struct resource *res_mem;
+ struct usb_ohci_pdata *pdata = dev->dev.platform_data;
int irq;
int err = -ENOMEM;
- BUG_ON(!dev->dev.platform_data);
+ if (!pdata) {
+ WARN_ON(1);
+ return -ENODEV;
+ }
if (usb_disabled())
return -ENODEV;

View file

@ -1,119 +0,0 @@
From 04216bedafb1b3992a6c2b7f1518281d2ba5fc7b Mon Sep 17 00:00:00 2001
From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
Date: Mon, 6 Aug 2012 18:08:39 -0700
Subject: [PATCH] usb: host: ehci-platform: add platform specific power callback
Commit 04216bedafb1b3992a6c2b7f1518281d2ba5fc7b upstream.
This patch enables to call platform specific power callback function.
Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
Acked-by: Alan Stern <stern@rowland.harvard.edu>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/usb/host/ehci-platform.c | 40 +++++++++++++++++++++++++++++++++++---
include/linux/usb/ehci_pdriver.h | 8 ++++++++
2 files changed, 45 insertions(+), 3 deletions(-)
--- a/drivers/usb/host/ehci-platform.c
+++ b/drivers/usb/host/ehci-platform.c
@@ -105,10 +105,18 @@ static int __devinit ehci_platform_probe
return -ENXIO;
}
+ if (pdata->power_on) {
+ err = pdata->power_on(dev);
+ if (err < 0)
+ return err;
+ }
+
hcd = usb_create_hcd(&ehci_platform_hc_driver, &dev->dev,
dev_name(&dev->dev));
- if (!hcd)
- return -ENOMEM;
+ if (!hcd) {
+ err = -ENOMEM;
+ goto err_power;
+ }
hcd->rsrc_start = res_mem->start;
hcd->rsrc_len = resource_size(res_mem);
@@ -136,12 +144,17 @@ err_release_region:
release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
err_put_hcd:
usb_put_hcd(hcd);
+err_power:
+ if (pdata->power_off)
+ pdata->power_off(dev);
+
return err;
}
static int __devexit ehci_platform_remove(struct platform_device *dev)
{
struct usb_hcd *hcd = platform_get_drvdata(dev);
+ struct usb_ehci_pdata *pdata = dev->dev.platform_data;
usb_remove_hcd(hcd);
iounmap(hcd->regs);
@@ -149,6 +162,9 @@ static int __devexit ehci_platform_remov
usb_put_hcd(hcd);
platform_set_drvdata(dev, NULL);
+ if (pdata->power_off)
+ pdata->power_off(dev);
+
return 0;
}
@@ -157,14 +173,32 @@ static int __devexit ehci_platform_remov
static int ehci_platform_suspend(struct device *dev)
{
struct usb_hcd *hcd = dev_get_drvdata(dev);
+ struct usb_ehci_pdata *pdata = dev->platform_data;
+ struct platform_device *pdev =
+ container_of(dev, struct platform_device, dev);
bool do_wakeup = device_may_wakeup(dev);
+ int ret;
+
+ ret = ehci_suspend(hcd, do_wakeup);
- return ehci_suspend(hcd, do_wakeup);
+ if (pdata->power_suspend)
+ pdata->power_suspend(pdev);
+
+ return ret;
}
static int ehci_platform_resume(struct device *dev)
{
struct usb_hcd *hcd = dev_get_drvdata(dev);
+ struct usb_ehci_pdata *pdata = dev->platform_data;
+ struct platform_device *pdev =
+ container_of(dev, struct platform_device, dev);
+
+ if (pdata->power_on) {
+ int err = pdata->power_on(pdev);
+ if (err < 0)
+ return err;
+ }
ehci_resume(hcd, false);
return 0;
--- a/include/linux/usb/ehci_pdriver.h
+++ b/include/linux/usb/ehci_pdriver.h
@@ -41,6 +41,14 @@ struct usb_ehci_pdata {
unsigned big_endian_mmio:1;
unsigned port_power_on:1;
unsigned port_power_off:1;
+
+ /* Turn on all power and clocks */
+ int (*power_on)(struct platform_device *pdev);
+ /* Turn off all power and clocks */
+ void (*power_off)(struct platform_device *pdev);
+ /* Turn on only VBUS suspend power and hotplug detection,
+ * turn off everything else */
+ void (*power_suspend)(struct platform_device *pdev);
};
#endif /* __USB_CORE_EHCI_PDRIVER_H */

View file

@ -1,114 +0,0 @@
From e4d37aeb373a5edceecc1dadc76fabbe8bc18e44 Mon Sep 17 00:00:00 2001
From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
Date: Mon, 6 Aug 2012 18:09:10 -0700
Subject: [PATCH] usb: host: ohci-platform: add platform specific power callback
Commit e4d37aeb373a5edceecc1dadc76fabbe8bc18e44 upstream.
This patch enables to call platform specific power callback function.
Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
Acked-by: Alan Stern <stern@rowland.harvard.edu>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/usb/host/ohci-platform.c | 36 ++++++++++++++++++++++++++++++++++--
include/linux/usb/ohci_pdriver.h | 8 ++++++++
2 files changed, 42 insertions(+), 2 deletions(-)
--- a/drivers/usb/host/ohci-platform.c
+++ b/drivers/usb/host/ohci-platform.c
@@ -107,10 +107,18 @@ static int __devinit ohci_platform_probe
return -ENXIO;
}
+ if (pdata->power_on) {
+ err = pdata->power_on(dev);
+ if (err < 0)
+ return err;
+ }
+
hcd = usb_create_hcd(&ohci_platform_hc_driver, &dev->dev,
dev_name(&dev->dev));
- if (!hcd)
- return -ENOMEM;
+ if (!hcd) {
+ err = -ENOMEM;
+ goto err_power;
+ }
hcd->rsrc_start = res_mem->start;
hcd->rsrc_len = resource_size(res_mem);
@@ -138,12 +146,17 @@ err_release_region:
release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
err_put_hcd:
usb_put_hcd(hcd);
+err_power:
+ if (pdata->power_off)
+ pdata->power_off(dev);
+
return err;
}
static int __devexit ohci_platform_remove(struct platform_device *dev)
{
struct usb_hcd *hcd = platform_get_drvdata(dev);
+ struct usb_ohci_pdata *pdata = dev->dev.platform_data;
usb_remove_hcd(hcd);
iounmap(hcd->regs);
@@ -151,6 +164,9 @@ static int __devexit ohci_platform_remov
usb_put_hcd(hcd);
platform_set_drvdata(dev, NULL);
+ if (pdata->power_off)
+ pdata->power_off(dev);
+
return 0;
}
@@ -158,12 +174,28 @@ static int __devexit ohci_platform_remov
static int ohci_platform_suspend(struct device *dev)
{
+ struct usb_ohci_pdata *pdata = dev->platform_data;
+ struct platform_device *pdev =
+ container_of(dev, struct platform_device, dev);
+
+ if (pdata->power_suspend)
+ pdata->power_suspend(pdev);
+
return 0;
}
static int ohci_platform_resume(struct device *dev)
{
struct usb_hcd *hcd = dev_get_drvdata(dev);
+ struct usb_ohci_pdata *pdata = dev->platform_data;
+ struct platform_device *pdev =
+ container_of(dev, struct platform_device, dev);
+
+ if (pdata->power_on) {
+ int err = pdata->power_on(pdev);
+ if (err < 0)
+ return err;
+ }
ohci_finish_controller_resume(hcd);
return 0;
--- a/include/linux/usb/ohci_pdriver.h
+++ b/include/linux/usb/ohci_pdriver.h
@@ -33,6 +33,14 @@ struct usb_ohci_pdata {
unsigned big_endian_desc:1;
unsigned big_endian_mmio:1;
unsigned no_big_frame_no:1;
+
+ /* Turn on all power and clocks */
+ int (*power_on)(struct platform_device *pdev);
+ /* Turn off all power and clocks */
+ void (*power_off)(struct platform_device *pdev);
+ /* Turn on only VBUS suspend power and hotplug detection,
+ * turn off everything else */
+ void (*power_suspend)(struct platform_device *pdev);
};
#endif /* __USB_CORE_OHCI_PDRIVER_H */

View file

@ -1,40 +0,0 @@
From 35e57e1b49a351aa804dab6010cd46ae6112a541 Mon Sep 17 00:00:00 2001
From: Daniel Gimpelevich <daniel@gimpelevich.san-francisco.ca.us>
Date: Wed, 21 Aug 2013 01:43:07 -0700
Subject: [PATCH 1/2] hso: Earlier catch of error condition
There is no need to get an interface specification if we know it's the
wrong one.
Signed-off-by: Daniel Gimpelevich <daniel@gimpelevich.san-francisco.ca.us>
Acked-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
---
drivers/net/usb/hso.c | 9 +++++----
1 file changed, 5 insertions(+), 4 deletions(-)
--- a/drivers/net/usb/hso.c
+++ b/drivers/net/usb/hso.c
@@ -2908,6 +2908,11 @@ static int hso_probe(struct usb_interfac
struct hso_shared_int *shared_int;
struct hso_device *tmp_dev = NULL;
+ if (interface->cur_altsetting->desc.bInterfaceClass != 0xFF) {
+ dev_err(&interface->dev, "Not our interface\n");
+ return -ENODEV;
+ }
+
if_num = interface->altsetting->desc.bInterfaceNumber;
/* Get the interface/port specification from either driver_info or from
@@ -2917,10 +2922,6 @@ static int hso_probe(struct usb_interfac
else
port_spec = hso_get_config_data(interface);
- if (interface->cur_altsetting->desc.bInterfaceClass != 0xFF) {
- dev_err(&interface->dev, "Not our interface\n");
- return -ENODEV;
- }
/* Check if we need to switch to alt interfaces prior to port
* configuration */
if (interface->num_altsetting > 1)

View file

@ -1,48 +0,0 @@
From e75dc677ff8d06ffa61bef6fee436227ae5440c6 Mon Sep 17 00:00:00 2001
From: Daniel Gimpelevich <daniel@gimpelevich.san-francisco.ca.us>
Date: Wed, 21 Aug 2013 01:43:19 -0700
Subject: [PATCH 2/2] hso: Fix stack corruption on some architectures
As Sergei Shtylyov explained in the #mipslinux IRC channel:
[Mon 2013-08-19 12:28:21 PM PDT] <headless> guys, are you sure it's not "DMA off stack" case?
[Mon 2013-08-19 12:28:35 PM PDT] <headless> it's a known stack corruptor on non-coherent arches
[Mon 2013-08-19 12:31:48 PM PDT] <DonkeyHotei> headless: for usb/ehci?
[Mon 2013-08-19 12:34:11 PM PDT] <DonkeyHotei> headless: explain
[Mon 2013-08-19 12:35:38 PM PDT] <headless> usb_control_msg() (or other such func) should not use buffer on stack. DMA from/to stack is prohibited
[Mon 2013-08-19 12:35:58 PM PDT] <headless> and EHCI uses DMA on control xfers (as well as all the others)
Signed-off-by: Daniel Gimpelevich <daniel@gimpelevich.san-francisco.ca.us>
Acked-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
---
drivers/net/usb/hso.c | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
--- a/drivers/net/usb/hso.c
+++ b/drivers/net/usb/hso.c
@@ -2838,13 +2838,16 @@ exit:
static int hso_get_config_data(struct usb_interface *interface)
{
struct usb_device *usbdev = interface_to_usbdev(interface);
- u8 config_data[17];
+ u8 *config_data = kmalloc(17, GFP_KERNEL);
u32 if_num = interface->altsetting->desc.bInterfaceNumber;
s32 result;
+ if (!config_data)
+ return -ENOMEM;
if (usb_control_msg(usbdev, usb_rcvctrlpipe(usbdev, 0),
0x86, 0xC0, 0, 0, config_data, 17,
USB_CTRL_SET_TIMEOUT) != 0x11) {
+ kfree(config_data);
return -EIO;
}
@@ -2895,6 +2898,7 @@ static int hso_get_config_data(struct us
if (config_data[16] & 0x1)
result |= HSO_INFO_CRC_BUG;
+ kfree(config_data);
return result;
}

View file

@ -1,13 +0,0 @@
--- a/drivers/mtd/devices/m25p80.c
+++ b/drivers/mtd/devices/m25p80.c
@@ -642,6 +642,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) },

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -1,36 +0,0 @@
--- a/drivers/net/usb/hso.c
+++ b/drivers/net/usb/hso.c
@@ -468,8 +468,10 @@ static const struct usb_device_id hso_id
{USB_DEVICE(0x0af0, 0x8400)},
{USB_DEVICE(0x0af0, 0x8600)},
{USB_DEVICE(0x0af0, 0x8800)},
- {USB_DEVICE(0x0af0, 0x8900)},
- {USB_DEVICE(0x0af0, 0x9000)},
+ {USB_DEVICE(0x0af0, 0x8900)}, /* GTM 67xx */
+ {USB_DEVICE(0x0af0, 0x9000)}, /* GTM 66xx */
+ {USB_DEVICE(0x0af0, 0x9200)}, /* GTM 67xxWFS */
+ {USB_DEVICE(0x0af0, 0x9300)}, /* GTM 66xxWFS */
{USB_DEVICE(0x0af0, 0xd035)},
{USB_DEVICE(0x0af0, 0xd055)},
{USB_DEVICE(0x0af0, 0xd155)},
--- a/drivers/usb/storage/unusual_devs.h
+++ b/drivers/usb/storage/unusual_devs.h
@@ -1237,6 +1237,18 @@ UNUSUAL_DEV( 0x0af0, 0x8304, 0x0000, 0x0
USB_SC_DEVICE, USB_PR_DEVICE, NULL,
0 ),
+UNUSUAL_DEV( 0x0af0, 0x9200, 0x0000, 0x0000,
+ "Option",
+ "Globetrotter 67xxWFS SD-Card",
+ USB_SC_DEVICE, USB_PR_DEVICE, NULL,
+ 0 ),
+
+UNUSUAL_DEV( 0x0af0, 0x9300, 0x0000, 0x0000,
+ "Option",
+ "Globetrotter 66xxWFS SD-Card",
+ USB_SC_DEVICE, USB_PR_DEVICE, NULL,
+ 0 ),
+
UNUSUAL_DEV( 0x0af0, 0xc100, 0x0000, 0x0000,
"Option",
"GI 070x SD-Card",

View file

@ -1,61 +0,0 @@
From patchwork Mon Aug 6 21:04:43 2012
Content-Type: text/plain; charset="utf-8"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
Subject: [net-next] tcp: ecn: dont delay ACKS after CE
Date: Mon, 06 Aug 2012 11:04:43 -0000
From: Eric Dumazet <eric.dumazet@gmail.com>
X-Patchwork-Id: 175453
Message-Id: <1344287083.26674.83.camel@edumazet-glaptop>
To: David Miller <davem@davemloft.net>
Cc: netdev <netdev@vger.kernel.org>,
Neal Cardwell <ncardwell@google.com>
From: Eric Dumazet <edumazet@google.com>
While playing with CoDel and ECN marking, I discovered a
non optimal behavior of receiver of CE (Congestion Encountered)
segments.
In pathological cases, sender has reduced its cwnd to low values,
and receiver delays its ACK (by 40 ms).
While RFC 3168 6.1.3 (The TCP Receiver) doesn't explicitly recommend
to send immediate ACKS, we believe its better to not delay ACKS, because
a CE segment should give same signal than a dropped segment, and its
quite important to reduce RTT to give ECE/CWR signals as fast as
possible.
Note we already call tcp_enter_quickack_mode() from TCP_ECN_check_ce()
if we receive a retransmit, for the same reason.
Signed-off-by: Eric Dumazet <edumazet@google.com>
Cc: Neal Cardwell <ncardwell@google.com>
Acked-by: Neal Cardwell <ncardwell@google.com>
---
net/ipv4/tcp_input.c | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
--- a/net/ipv4/tcp_input.c
+++ b/net/ipv4/tcp_input.c
@@ -237,7 +237,11 @@ static inline void TCP_ECN_check_ce(stru
tcp_enter_quickack_mode((struct sock *)tp);
break;
case INET_ECN_CE:
- tp->ecn_flags |= TCP_ECN_DEMAND_CWR;
+ if (!(tp->ecn_flags & TCP_ECN_DEMAND_CWR)) {
+ /* Better not delay acks, sender can have a very low cwnd */
+ tcp_enter_quickack_mode((struct sock *)tp);
+ tp->ecn_flags |= TCP_ECN_DEMAND_CWR;
+ }
/* fallinto */
default:
tp->ecn_flags |= TCP_ECN_SEEN;

View file

@ -1,10 +0,0 @@
--- a/arch/arm/boot/compressed/decompress.c
+++ b/arch/arm/boot/compressed/decompress.c
@@ -47,6 +47,7 @@ extern void error(char *);
#ifdef CONFIG_KERNEL_XZ
#define memmove memmove
#define memcpy memcpy
+extern char * strstr(const char *, const char *);
#include "../../../../lib/decompress_unxz.c"
#endif

View file

@ -1,66 +0,0 @@
From 0db3db45f5bd6df4bdc03bbd5dec672e16164c4e Mon Sep 17 00:00:00 2001
From: Florian Fainelli <florian@openwrt.org>
Date: Mon, 12 Nov 2012 12:31:55 +0100
Subject: [PATCH] MIPS: decompressor: fix build failure on memcpy() in
decompress.c
The decompress.c file includes linux/kernel.h which causes the following
inclusion chain to be pulled:
linux/kernel.h ->
linux/dynamic_debug.h ->
linux/string.h ->
asm/string.h
We end up having a the GCC builtin + architecture specific memcpy() expanding
into this:
void *({ size_t __len = (size_t n); void *__ret; if
(__builtin_constant_p(size_t n) && __len >= 64) __ret = memcpy((void *dest),
(const void *src), __len); else __ret = __builtin_memcpy((void *dest), (const
void *src), __len); __ret; })
{
[memcpy implementation in decompress.c starts here]
int i;
const char *s = src;
char *d = dest;
for (i = 0; i < n; i++)
d[i] = s[i];
return dest;
}
raising the following compilation error:
arch/mips/boot/compressed/decompress.c:46:8: error: expected identifier or '('
before '{' token
There are at least three possibilities to fix this issue:
1) define _LINUX_STRING_H_ at the beginning of decompress.c to prevent
further linux/string.h definitions and declarations from being used, and add
an explicit strstr() declaration for linux/dynamic_debug.h
2) remove the inclusion of linux/kernel.h because we actually use no definition
or declaration from this header file
3) undefine memcpy or re-define memcpy to memcpy thus resulting in picking up
the local memcpy() implementation to this compilation unit
This patch uses the second option which is the less intrusive one.
Signed-off-by: Florian Fainelli <florian@openwrt.org>
---
arch/mips/boot/compressed/decompress.c | 2 --
1 file changed, 2 deletions(-)
--- a/arch/mips/boot/compressed/decompress.c
+++ b/arch/mips/boot/compressed/decompress.c
@@ -10,9 +10,7 @@
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*/
-
#include <linux/types.h>
-#include <linux/kernel.h>
#include <asm/addrspace.h>

View file

@ -1,174 +0,0 @@
commit 01ffc0a7f1c1801a2354719dedbc32aff45b987d
Author: David Woodhouse <dwmw2@infradead.org>
Date: Sat Nov 24 12:11:21 2012 +0000
8139cp: re-enable interrupts after tx timeout
Recovery doesn't work too well if we leave interrupts disabled...
Signed-off-by: David Woodhouse <David.Woodhouse@intel.com>
Acked-by: Francois Romieu <romieu@fr.zoreil.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
commit 871f0d4c153e1258d4becf306eca6761bf38b629
Author: David Woodhouse <dwmw2@infradead.org>
Date: Thu Nov 22 03:16:58 2012 +0000
8139cp: enable bql
This adds support for byte queue limits on RTL8139C+
Tested on real hardware.
Signed-off-by: David Woodhouse <David.Woodhouse@intel.com>
Acked-By: Dave Täht <dave.taht@bufferbloat.net>
Signed-off-by: David S. Miller <davem@davemloft.net>
commit a9dbe40fc10cea2efe6e1ff9e03c62dd7579c5ba
Author: David Woodhouse <dwmw2@infradead.org>
Date: Wed Nov 21 10:27:19 2012 +0000
8139cp: set ring address after enabling C+ mode
This fixes (for me) a regression introduced by commit b01af457 ("8139cp:
set ring address before enabling receiver"). That commit configured the
descriptor ring addresses earlier in the initialisation sequence, in
order to avoid the possibility of triggering stray DMA before the
correct address had been set up.
Unfortunately, it seems that the hardware will scribble garbage into the
TxRingAddr registers when we enable "plus mode" Tx in the CpCmd
register. Observed on a Traverse Geos router board.
To deal with this, while not reintroducing the problem which led to the
original commit, we augment cp_start_hw() to write to the CpCmd register
*first*, then set the descriptor ring addresses, and then finally to
enable Rx and Tx in the original 8139 Cmd register. The datasheet
actually indicates that we should enable Tx/Rx in the Cmd register
*before* configuring the descriptor addresses, but that would appear to
re-introduce the problem that the offending commit b01af457 was trying
to solve. And this variant appears to work fine on real hardware.
Signed-off-by: David Woodhouse <David.Woodhouse@intel.com>
Cc: stable@kernel.org [3.5+]
Signed-off-by: David S. Miller <davem@davemloft.net>
--- 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
{
unsigned tx_head = cp->tx_head;
unsigned tx_tail = cp->tx_tail;
+ unsigned bytes_compl = 0, pkts_compl = 0;
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
le32_to_cpu(txd->opts1) & 0xffff,
PCI_DMA_TODEVICE);
+ bytes_compl += skb->len;
+ pkts_compl++;
+
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
cp->tx_tail = tx_tail;
+ netdev_completed_queue(cp->dev, pkts_compl, bytes_compl);
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
wmb();
}
cp->tx_head = entry;
+
+ netdev_sent_queue(dev, skb->len);
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_privat
cp->rx_tail = 0;
cp->tx_head = cp->tx_tail = 0;
+
+ netdev_reset_queue(cp->dev);
}
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)
{
+ dma_addr_t ring_dma;
+
cpw16(CpCmd, cp->cpcmd);
+
+ /*
+ * These (at least TxRingAddr) need to be configured after the
+ * corresponding bits in CpCmd are enabled. Datasheet v1.6 §6.33
+ * (C+ Command Register) recommends that these and more be configured
+ * *after* the [RT]xEnable bits in CpCmd are set. And on some hardware
+ * it's been observed that the TxRingAddr is actually reset to garbage
+ * when C+ mode Tx is enabled in CpCmd.
+ */
+ cpw32_f(HiTxRingAddr, 0);
+ cpw32_f(HiTxRingAddr + 4, 0);
+
+ ring_dma = cp->ring_dma;
+ cpw32_f(RxRingAddr, ring_dma & 0xffffffff);
+ cpw32_f(RxRingAddr + 4, (ring_dma >> 16) >> 16);
+
+ ring_dma += sizeof(struct cp_desc) * CP_RX_RING_SIZE;
+ cpw32_f(TxRingAddr, ring_dma & 0xffffffff);
+ cpw32_f(TxRingAddr + 4, (ring_dma >> 16) >> 16);
+
+ /*
+ * Strictly speaking, the datasheet says this should be enabled
+ * *before* setting the descriptor addresses. But what, then, would
+ * prevent it from doing DMA to random unconfigured addresses?
+ * This variant appears to work fine.
+ */
cpw8(Cmd, RxOn | TxOn);
+
+ netdev_reset_queue(cp->dev);
}
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;
- dma_addr_t ring_dma;
cp_reset_hw(cp);
@@ -992,17 +1030,6 @@ static void cp_init_hw (struct cp_privat
cpw8(Config5, cpr8(Config5) & PMEStatus);
- cpw32_f(HiTxRingAddr, 0);
- cpw32_f(HiTxRingAddr + 4, 0);
-
- ring_dma = cp->ring_dma;
- cpw32_f(RxRingAddr, ring_dma & 0xffffffff);
- cpw32_f(RxRingAddr + 4, (ring_dma >> 16) >> 16);
-
- ring_dma += sizeof(struct cp_desc) * CP_RX_RING_SIZE;
- cpw32_f(TxRingAddr, ring_dma & 0xffffffff);
- cpw32_f(TxRingAddr + 4, (ring_dma >> 16) >> 16);
-
cpw16(MultiIntr, 0);
cpw8_f(Cfg9346, Cfg9346_Lock);
@@ -1192,6 +1219,7 @@ static void cp_tx_timeout(struct net_dev
cp_clean_rings(cp);
rc = cp_init_rings(cp);
cp_start_hw(cp);
+ cp_enable_irq(cp);
netif_wake_queue(dev);

View file

@ -1,35 +0,0 @@
From 7b45f21c2e42f265f6fd469e43857e98e2fdf01c Mon Sep 17 00:00:00 2001
From: Irina Tirdea <irina.tirdea@intel.com>
Date: Sat, 8 Sep 2012 03:43:21 +0300
Subject: [PATCH] perf tools: replace mkostemp with mkstemp
The mkostemp function is only available in glibc. This leads to compile
error in Android, since bionic is derived from BSD.
Replacing mkostemp with mkstemp. mkstemp is available on both glibc and
bionic.
Signed-off-by: Irina Tirdea <irina.tirdea@intel.com>
Cc: David Ahern <dsahern@gmail.com>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: Namhyung Kim <namhyung.kim@lge.com>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Steven Rostedt <rostedt@goodmis.org>
Link: http://lkml.kernel.org/r/1347065004-15306-10-git-send-email-irina.tirdea@intel.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
tools/perf/util/dso-test-data.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
--- a/tools/perf/util/dso-test-data.c
+++ b/tools/perf/util/dso-test-data.c
@@ -23,7 +23,7 @@ static char *test_file(int size)
int fd, i;
unsigned char *buf;
- fd = mkostemp(templ, O_CREAT|O_WRONLY|O_TRUNC);
+ fd = mkstemp(templ);
buf = malloc(size);
if (!buf) {

View file

@ -1,27 +0,0 @@
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>
/*

View file

@ -1,27 +0,0 @@
From 6e601a53566d84e1ffd25e7b6fe0b6894ffd79c0 Mon Sep 17 00:00:00 2001
From: Mathias Krause <minipli@googlemail.com>
Date: Sat, 23 Feb 2013 01:13:47 +0000
Subject: sock_diag: Fix out-of-bounds access to sock_diag_handlers[]
Userland can send a netlink message requesting SOCK_DIAG_BY_FAMILY
with a family greater or equal then AF_MAX -- the array size of
sock_diag_handlers[]. The current code does not test for this
condition therefore is vulnerable to an out-of-bound access opening
doors for a privilege escalation.
Signed-off-by: Mathias Krause <minipli@googlemail.com>
Acked-by: Eric Dumazet <edumazet@google.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
---
--- a/net/core/sock_diag.c
+++ b/net/core/sock_diag.c
@@ -121,6 +121,9 @@ static int __sock_diag_rcv_msg(struct sk
if (nlmsg_len(nlh) < sizeof(*req))
return -EINVAL;
+ if (req->sdiag_family >= AF_MAX)
+ return -EINVAL;
+
hndl = sock_diag_lock_handler(req->sdiag_family);
if (hndl == NULL)
err = -ENOENT;

File diff suppressed because it is too large Load diff

View file

@ -1,41 +0,0 @@
--- a/drivers/usb/host/ehci-hcd.c
+++ b/drivers/usb/host/ehci-hcd.c
@@ -645,7 +645,7 @@ static int ehci_run (struct usb_hcd *hcd
"USB %x.%x started, EHCI %x.%02x%s\n",
((ehci->sbrn & 0xf0)>>4), (ehci->sbrn & 0x0f),
temp >> 8, temp & 0xff,
- ignore_oc ? ", overcurrent ignored" : "");
+ (ignore_oc || ehci->ignore_oc) ? ", overcurrent ignored" : "");
ehci_writel(ehci, INTR_MASK,
&ehci->regs->intr_enable); /* Turn On Interrupts */
--- a/drivers/usb/host/ehci-hub.c
+++ b/drivers/usb/host/ehci-hub.c
@@ -585,7 +585,7 @@ ehci_hub_status_data (struct usb_hcd *hc
* always set, seem to clear PORT_OCC and PORT_CSC when writing to
* PORT_POWER; that's surprising, but maybe within-spec.
*/
- if (!ignore_oc)
+ if (!ignore_oc && !ehci->ignore_oc)
mask = PORT_CSC | PORT_PEC | PORT_OCC;
else
mask = PORT_CSC | PORT_PEC;
@@ -804,7 +804,7 @@ static int ehci_hub_control (
if (temp & PORT_PEC)
status |= USB_PORT_STAT_C_ENABLE << 16;
- if ((temp & PORT_OCC) && !ignore_oc){
+ if ((temp & PORT_OCC) && (!ignore_oc && !ehci->ignore_oc)){
status |= USB_PORT_STAT_C_OVERCURRENT << 16;
/*
--- a/drivers/usb/host/ehci.h
+++ b/drivers/usb/host/ehci.h
@@ -197,6 +197,7 @@ struct ehci_hcd { /* one per controlle
unsigned use_dummy_qh:1; /* AMD Frame List table quirk*/
unsigned has_synopsys_hc_bug:1; /* Synopsys HC */
unsigned frame_index_bug:1; /* MosChip (AKA NetMos) */
+ unsigned ignore_oc:1;
/* required for usb32 quirk */
#define OHCI_CTRL_HCFS (3 << 6)

View file

@ -1,10 +0,0 @@
--- a/include/linux/mtd/physmap.h
+++ b/include/linux/mtd/physmap.h
@@ -17,6 +17,7 @@
#include <linux/mtd/mtd.h>
#include <linux/mtd/partitions.h>
+#include <linux/platform_device.h>
struct map_info;
struct platform_device;

View file

@ -1,900 +0,0 @@
commit d7d3d8f1ee4435e32bc6c93187798b7e2e3170a9
Author: David Woodhouse <David.Woodhouse@intel.com>
Date: Thu Nov 29 23:28:30 2012 +0000
solos-pci: remove list_vccs() debugging function
No idea why we've gone so long dumping a list of VCCs with vci==0 on
every ->open() call...
Signed-off-by: David Woodhouse <David.Woodhouse@intel.com>
commit c93967bfd3a3dffa759a3f28370167bf3cdbc3d0
Author: David Woodhouse <David.Woodhouse@intel.com>
Date: Thu Nov 29 23:27:20 2012 +0000
solos-pci: use GFP_KERNEL where possible, not GFP_ATOMIC
Signed-off-by: David Woodhouse <David.Woodhouse@intel.com>
commit ad6999e17ae4f7b99f6d28f425ae970acb115347
Author: David Woodhouse <David.Woodhouse@intel.com>
Date: Thu Nov 29 23:15:30 2012 +0000
solos-pci: clean up pclose() function
- Flush pending TX skbs from the queue rather than waiting for them all to
complete (suggested by Krzysztof Mazur <krzysiek@podlesie.net>).
- Clear ATM_VF_ADDR only when the PKT_PCLOSE packet has been submitted.
- Don't clear ATM_VF_READY at all — vcc_destroy_socket() does that for us.
Signed-off-by: David Woodhouse <David.Woodhouse@intel.com>
commit 2547e97f29d6d69d567947d5ef90b6b4fbcaf565
Author: David Woodhouse <David.Woodhouse@intel.com>
Date: Wed Nov 28 10:15:05 2012 +0000
pppoatm: optimise PPP channel wakeups after sock_owned_by_user()
We don't need to schedule the wakeup tasklet on *every* unlock; only if we
actually blocked the channel in the first place.
Signed-off-by: David Woodhouse <David.Woodhouse@intel.com>
Acked-by: Krzysztof Mazur <krzysiek@podlesie.net>
commit 990b0884a2e9668c08e9daa4d70a54d65329cb6f
Author: Krzysztof Mazur <krzysiek@podlesie.net>
Date: Wed Nov 28 09:08:04 2012 +0100
br2684: allow assign only on a connected socket
The br2684 does not check if used vcc is in connected state,
causing potential Oops in pppoatm_send() when vcc->send() is called
on not fully connected socket.
Now br2684 can be assigned only on connected sockets; otherwise
-EINVAL error is returned.
Signed-off-by: Krzysztof Mazur <krzysiek@podlesie.net>
Signed-off-by: David Woodhouse <David.Woodhouse@intel.com>
commit f49b6da01f0abebb17f6241473d53018d923f6b0
Author: Nathan Williams <nathan@traverse.com.au>
Date: Tue Nov 27 17:34:09 2012 +1100
solos-pci: Fix leak of skb received for unknown vcc
... and ensure that the next skb is set up for RX in the DMA case.
Signed-off-by: Nathan Williams <nathan@traverse.com.au>
Signed-off-by: David Woodhouse <David.Woodhouse@intel.com>
commit a61d37ff4a555886c4ebe31d2c6d893afb6f4d3c
Author: David Woodhouse <David.Woodhouse@intel.com>
Date: Wed Nov 28 00:46:45 2012 +0000
br2684: fix module_put() race
The br2684 code used module_put() during unassignment from vcc with
hope that we have BKL. This assumption is no longer true.
Now owner field in atmvcc is used to move this module_put()
to vcc_destroy_socket().
Signed-off-by: David Woodhouse <David.Woodhouse@intel.com>
Acked-by: Krzysztof Mazur <krzysiek@podlesie.net>
commit c52f40629884ddc62c7af445fd5d620fdb466fb2
Author: David Woodhouse <David.Woodhouse@intel.com>
Date: Wed Nov 28 00:05:52 2012 +0000
pppoatm: fix missing wakeup in pppoatm_send()
Now that we can return zero from pppoatm_send() for reasons *other* than
the queue being full, that means we can't depend on a subsequent call to
pppoatm_pop() waking the queue, and we might leave it stalled
indefinitely.
Use the ->release_cb() callback to wake the queue after the sock is
unlocked.
Signed-off-by: David Woodhouse <David.Woodhouse@intel.com>
Acked-by: Krzysztof Mazur <krzysiek@podlesie.net>
commit 35826e7372fe39b7db7930eda0267c82d68d1a4c
Author: David Woodhouse <dwmw2@infradead.org>
Date: Tue Nov 27 23:28:36 2012 +0000
br2684: don't send frames on not-ready vcc
Avoid submitting packets to a vcc which is being closed. Things go badly
wrong when the ->pop method gets later called after everything's been
torn down.
Use the ATM socket lock for synchronisation with vcc_destroy_socket(),
which clears the ATM_VF_READY bit under the same lock. Otherwise, we
could end up submitting a packet to the device driver even after its
->ops->close method has been called. And it could call the vcc's ->pop
method after the protocol has been shut down. Which leads to a panic.
Signed-off-by: David Woodhouse <David.Woodhouse@intel.com>
Acked-by: Krzysztof Mazur <krzysiek@podlesie.net>
commit 7f940dde65de4a707f3dd723bb6ce9de90ca1eab
Author: David Woodhouse <David.Woodhouse@intel.com>
Date: Wed Nov 28 00:03:11 2012 +0000
atm: add release_cb() callback to vcc
The immediate use case for this is that it will allow us to ensure that a
pppoatm queue is woken after it has to drop a packet due to the sock being
locked.
Note that 'release_cb' is called when the socket is *unlocked*. This is
not to be confused with vcc_release() — which probably ought to be called
vcc_close().
Signed-off-by: David Woodhouse <David.Woodhouse@intel.com>
Acked-by: Krzysztof Mazur <krzysiek@podlesie.net>
commit def1b2f9083f84d0a77730e537c76429914d17c1
Author: David Woodhouse <David.Woodhouse@intel.com>
Date: Tue Nov 27 23:49:24 2012 +0000
solos-pci: wait for pending TX to complete when releasing vcc
We should no longer be calling the old pop routine for the vcc, after
vcc_release() has completed. Make sure we wait for any pending TX skbs
to complete, by waiting for our own PKT_PCLOSE control skb to be sent.
Signed-off-by: David Woodhouse <David.Woodhouse@intel.com>
commit 397ff16dce53888ec693b3718640be2560204751
Author: Krzysztof Mazur <krzysiek@podlesie.net>
Date: Tue Nov 6 23:17:02 2012 +0100
pppoatm: do not inline pppoatm_may_send()
The pppoatm_may_send() is quite heavy and it's called three times
in pppoatm_send() and inlining costs more than 200 bytes of code
(more than 10% of total pppoatm driver code size).
add/remove: 1/0 grow/shrink: 0/1 up/down: 132/-367 (-235)
function old new delta
pppoatm_may_send - 132 +132
pppoatm_send 900 533 -367
Signed-off-by: Krzysztof Mazur <krzysiek@podlesie.net>
Signed-off-by: David Woodhouse <David.Woodhouse@intel.com>
commit 071d93931a75dc1f82f0baa9959613af81c5a032
Author: Krzysztof Mazur <krzysiek@podlesie.net>
Date: Sat Nov 10 23:33:19 2012 +0100
pppoatm: drop frames to not-ready vcc
The vcc_destroy_socket() closes vcc before the protocol is detached
from vcc by calling vcc->push() with NULL skb. This leaves some time
window, where the protocol may call vcc->send() on closed vcc
and crash.
Now pppoatm_send(), like vcc_sendmsg(), checks for vcc flags that
indicate that vcc is not ready. If the vcc is not ready we just
drop frame. Queueing frames is much more complicated because we
don't have callbacks that inform us about vcc flags changes.
Signed-off-by: Krzysztof Mazur <krzysiek@podlesie.net>
Signed-off-by: David Woodhouse <David.Woodhouse@intel.com>
commit 3ac108006fd7f20cb8fc8ea2287f1497bcda00a1
Author: Krzysztof Mazur <krzysiek@podlesie.net>
Date: Tue Nov 6 23:17:00 2012 +0100
pppoatm: take ATM socket lock in pppoatm_send()
The pppoatm_send() does not take any lock that will prevent concurrent
vcc_sendmsg(). This causes two problems:
- there is no locking between checking the send queue size
with atm_may_send() and incrementing sk_wmem_alloc,
and the real queue size can be a little higher than sk_sndbuf
- the vcc->sendmsg() can be called concurrently. I'm not sure
if it's allowed. Some drivers (eni, nicstar, ...) seem
to assume it will never happen.
Now pppoatm_send() takes ATM socket lock, the same that is used
in vcc_sendmsg() and other ATM socket functions. The pppoatm_send()
is called with BH disabled, so bh_lock_sock() is used instead
of lock_sock().
Signed-off-by: Krzysztof Mazur <krzysiek@podlesie.net>
Cc: Chas Williams - CONTRACTOR <chas@cmf.nrl.navy.mil>
Signed-off-by: David Woodhouse <David.Woodhouse@intel.com>
commit e41faed9cde1acce657f75a0b19a1787e9850d3f
Author: Krzysztof Mazur <krzysiek@podlesie.net>
Date: Tue Nov 6 23:16:59 2012 +0100
pppoatm: fix module_put() race
The pppoatm used module_put() during unassignment from vcc with
hope that we have BKL. This assumption is no longer true.
Now owner field in atmvcc is used to move this module_put()
to vcc_destroy_socket().
Signed-off-by: Krzysztof Mazur <krzysiek@podlesie.net>
Signed-off-by: David Woodhouse <David.Woodhouse@intel.com>
commit 3b1a914595f3f9beb9e38ff3ddc7bdafa092ba22
Author: Krzysztof Mazur <krzysiek@podlesie.net>
Date: Tue Nov 6 23:16:58 2012 +0100
pppoatm: allow assign only on a connected socket
The pppoatm does not check if used vcc is in connected state,
causing an Oops in pppoatm_send() when vcc->send() is called
on not fully connected socket.
Now pppoatm can be assigned only on connected sockets; otherwise
-EINVAL error is returned.
Signed-off-by: Krzysztof Mazur <krzysiek@podlesie.net>
Cc: Chas Williams - CONTRACTOR <chas@cmf.nrl.navy.mil>
Signed-off-by: David Woodhouse <David.Woodhouse@intel.com>
commit ec809bd817dfa1905283468e4c813684ed4efe78
Author: Krzysztof Mazur <krzysiek@podlesie.net>
Date: Tue Nov 6 23:16:57 2012 +0100
atm: add owner of push() callback to atmvcc
The atm is using atmvcc->push(vcc, NULL) callback to notify protocol
that vcc will be closed and protocol must detach from it. This callback
is usually used by protocol to decrement module usage count by module_put(),
but it leaves small window then module is still used after module_put().
Now the owner of push() callback is kept in atmvcc and
module_put(atmvcc->owner) is called after the protocol is detached from vcc.
Signed-off-by: Krzysztof Mazur <krzysiek@podlesie.net>
Signed-off-by: David Woodhouse <David.Woodhouse@intel.com>
Acked-by: Chas Williams <chas@cmf.nrl.navy.mil>
commit ae088d663beebb3cad0e7abaac67ee61a7c578d5
Author: David Woodhouse <dwmw2@infradead.org>
Date: Sun Nov 25 12:06:52 2012 +0000
atm: br2684: Fix excessive queue bloat
There's really no excuse for an additional wmem_default of buffering
between the netdev queue and the ATM device. Two packets (one in-flight,
and one ready to send) ought to be fine. It's not as if it should take
long to get another from the netdev queue when we need it.
If necessary we can make the queue space configurable later, but I don't
think it's likely to be necessary.
cf. commit 9d02daf754238adac48fa075ee79e7edd3d79ed3 (pppoatm: Fix
excessive queue bloat) which did something very similar for PPPoATM.
Note that there is a tremendously unlikely race condition which may
result in qspace temporarily going negative. If a CPU running the
br2684_pop() function goes off into the weeds for a long period of time
after incrementing qspace to 1, but before calling netdev_wake_queue()...
and another CPU ends up calling br2684_start_xmit() and *stopping* the
queue again before the first CPU comes back, the netdev queue could
end up being woken when qspace has already reached zero.
An alternative approach to coping with this race would be to check in
br2684_start_xmit() for qspace==0 and return NETDEV_TX_BUSY, but just
using '> 0' and '< 1' for comparison instead of '== 0' and '!= 0' is
simpler. It just warranted a mention of *why* we do it that way...
Move the call to atmvcc->send() to happen *after* the accounting and
potentially stopping the netdev queue, in br2684_xmit_vcc(). This matters
if the ->send() call suffers an immediate failure, because it'll call
br2684_pop() with the offending skb before returning. We want that to
happen *after* we've done the initial accounting for the packet in
question. Also make it return an appropriate success/failure indication
while we're at it.
Tested by running 'ping -l 1000 bottomless.aaisp.net.uk' from within my
network, with only a single PPPoE-over-BR2684 link running. And after
setting txqueuelen on the nas0 interface to something low (5, in fact).
Before the patch, we'd see about 15 packets being queued and a resulting
latency of ~56ms being reached. After the patch, we see only about 8,
which is fairly much what we expect. And a max latency of ~36ms. On this
OpenWRT box, wmem_default is 163840.
Signed-off-by: David Woodhouse <David.Woodhouse@intel.com>
Reviewed-by: Krzysztof Mazur <krzysiek@podlesie.net>
Signed-off-by: David S. Miller <davem@davemloft.net>
--- a/drivers/atm/solos-pci.c
+++ b/drivers/atm/solos-pci.c
@@ -92,6 +92,7 @@ struct pkt_hdr {
};
struct solos_skb_cb {
+ struct completion c;
struct atm_vcc *vcc;
uint32_t dma_addr;
};
@@ -164,7 +165,6 @@ static void fpga_queue(struct solos_card
static uint32_t fpga_tx(struct solos_card *);
static irqreturn_t solos_irq(int irq, void *dev_id);
static struct atm_vcc* find_vcc(struct atm_dev *dev, short vpi, int vci);
-static int list_vccs(int vci);
static int atm_init(struct solos_card *, struct device *);
static void atm_remove(struct solos_card *);
static int send_command(struct solos_card *card, int dev, const char *buf, size_t size);
@@ -710,7 +710,8 @@ void solos_bh(unsigned long card_arg)
dev_warn(&card->dev->dev, "Received packet for unknown VPI.VCI %d.%d on port %d\n",
le16_to_cpu(header->vpi), le16_to_cpu(header->vci),
port);
- continue;
+ dev_kfree_skb_any(skb);
+ break;
}
atm_charge(vcc, skb->truesize);
vcc->push(vcc, skb);
@@ -790,44 +791,6 @@ static struct atm_vcc *find_vcc(struct a
return vcc;
}
-static int list_vccs(int vci)
-{
- struct hlist_head *head;
- struct atm_vcc *vcc;
- struct hlist_node *node;
- struct sock *s;
- int num_found = 0;
- int i;
-
- read_lock(&vcc_sklist_lock);
- if (vci != 0){
- head = &vcc_hash[vci & (VCC_HTABLE_SIZE -1)];
- sk_for_each(s, node, head) {
- num_found ++;
- vcc = atm_sk(s);
- printk(KERN_DEBUG "Device: %d Vpi: %d Vci: %d\n",
- vcc->dev->number,
- vcc->vpi,
- vcc->vci);
- }
- } else {
- for(i = 0; i < VCC_HTABLE_SIZE; i++){
- head = &vcc_hash[i];
- sk_for_each(s, node, head) {
- num_found ++;
- vcc = atm_sk(s);
- printk(KERN_DEBUG "Device: %d Vpi: %d Vci: %d\n",
- vcc->dev->number,
- vcc->vpi,
- vcc->vci);
- }
- }
- }
- read_unlock(&vcc_sklist_lock);
- return num_found;
-}
-
-
static int popen(struct atm_vcc *vcc)
{
struct solos_card *card = vcc->dev->dev_data;
@@ -840,7 +803,7 @@ static int popen(struct atm_vcc *vcc)
return -EINVAL;
}
- skb = alloc_skb(sizeof(*header), GFP_ATOMIC);
+ skb = alloc_skb(sizeof(*header), GFP_KERNEL);
if (!skb) {
if (net_ratelimit())
dev_warn(&card->dev->dev, "Failed to allocate sk_buff in popen()\n");
@@ -857,8 +820,6 @@ static int popen(struct atm_vcc *vcc)
set_bit(ATM_VF_ADDR, &vcc->flags);
set_bit(ATM_VF_READY, &vcc->flags);
- list_vccs(0);
-
return 0;
}
@@ -866,10 +827,21 @@ static int popen(struct atm_vcc *vcc)
static void pclose(struct atm_vcc *vcc)
{
struct solos_card *card = vcc->dev->dev_data;
- struct sk_buff *skb;
+ unsigned char port = SOLOS_CHAN(vcc->dev);
+ struct sk_buff *skb, *tmpskb;
struct pkt_hdr *header;
- skb = alloc_skb(sizeof(*header), GFP_ATOMIC);
+ /* Remove any yet-to-be-transmitted packets from the pending queue */
+ spin_lock(&card->tx_queue_lock);
+ skb_queue_walk_safe(&card->tx_queue[port], skb, tmpskb) {
+ if (SKB_CB(skb)->vcc == vcc) {
+ skb_unlink(skb, &card->tx_queue[port]);
+ solos_pop(vcc, skb);
+ }
+ }
+ spin_unlock(&card->tx_queue_lock);
+
+ skb = alloc_skb(sizeof(*header), GFP_KERNEL);
if (!skb) {
dev_warn(&card->dev->dev, "Failed to allocate sk_buff in pclose()\n");
return;
@@ -881,15 +853,21 @@ static void pclose(struct atm_vcc *vcc)
header->vci = cpu_to_le16(vcc->vci);
header->type = cpu_to_le16(PKT_PCLOSE);
- fpga_queue(card, SOLOS_CHAN(vcc->dev), skb, NULL);
+ init_completion(&SKB_CB(skb)->c);
- clear_bit(ATM_VF_ADDR, &vcc->flags);
- clear_bit(ATM_VF_READY, &vcc->flags);
+ fpga_queue(card, port, skb, NULL);
+
+ if (!wait_for_completion_timeout(&SKB_CB(skb)->c, 5 * HZ))
+ dev_warn(&card->dev->dev, "Timeout waiting for VCC close on port %d\n",
+ port);
/* Hold up vcc_destroy_socket() (our caller) until solos_bh() in the
tasklet has finished processing any incoming packets (and, more to
the point, using the vcc pointer). */
tasklet_unlock_wait(&card->tlet);
+
+ clear_bit(ATM_VF_ADDR, &vcc->flags);
+
return;
}
@@ -1011,9 +989,12 @@ static uint32_t fpga_tx(struct solos_car
if (vcc) {
atomic_inc(&vcc->stats->tx);
solos_pop(vcc, oldskb);
- } else
+ } else {
+ struct pkt_hdr *header = (void *)oldskb->data;
+ if (le16_to_cpu(header->type) == PKT_PCLOSE)
+ complete(&SKB_CB(oldskb)->c);
dev_kfree_skb_irq(oldskb);
-
+ }
}
}
/* 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
card->atmdev[i]->phy_data = (void *)(unsigned long)i;
atm_dev_signal_change(card->atmdev[i], ATM_PHY_SIG_FOUND);
- skb = alloc_skb(sizeof(*header), GFP_ATOMIC);
+ skb = alloc_skb(sizeof(*header), GFP_KERNEL);
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 = {
static int __init solos_pci_init(void)
{
+ BUILD_BUG_ON(sizeof(struct solos_skb_cb) > sizeof(((struct sk_buff *)0)->cb));
+
printk(KERN_INFO "Solos PCI Driver Version %s\n", VERSION);
return pci_register_driver(&fpga_driver);
}
--- a/include/linux/atmdev.h
+++ b/include/linux/atmdev.h
@@ -308,6 +308,7 @@ struct atm_vcc {
struct atm_dev *dev; /* device back pointer */
struct atm_qos qos; /* QOS */
struct atm_sap sap; /* SAP */
+ void (*release_cb)(struct atm_vcc *vcc); /* release_sock callback */
void (*push)(struct atm_vcc *vcc,struct sk_buff *skb);
void (*pop)(struct atm_vcc *vcc,struct sk_buff *skb); /* optional */
int (*push_oam)(struct atm_vcc *vcc,void *cell);
@@ -315,6 +316,7 @@ struct atm_vcc {
void *dev_data; /* per-device data */
void *proto_data; /* per-protocol data */
struct k_atm_aal_stats *stats; /* pointer to AAL stats group */
+ struct module *owner; /* owner of ->push function */
/* SVC part --- may move later ------------------------------------- */
short itf; /* interface number */
struct sockaddr_atmsvc local;
--- a/net/atm/br2684.c
+++ b/net/atm/br2684.c
@@ -68,12 +68,15 @@ struct br2684_vcc {
/* keep old push, pop functions for chaining */
void (*old_push)(struct atm_vcc *vcc, struct sk_buff *skb);
void (*old_pop)(struct atm_vcc *vcc, struct sk_buff *skb);
+ void (*old_release_cb)(struct atm_vcc *vcc);
+ struct module *old_owner;
enum br2684_encaps encaps;
struct list_head brvccs;
#ifdef CONFIG_ATM_BR2684_IPFILTER
struct br2684_filter filter;
#endif /* CONFIG_ATM_BR2684_IPFILTER */
unsigned int copies_needed, copies_failed;
+ atomic_t qspace;
};
struct br2684_dev {
@@ -181,18 +184,15 @@ static struct notifier_block atm_dev_not
static void br2684_pop(struct atm_vcc *vcc, struct sk_buff *skb)
{
struct br2684_vcc *brvcc = BR2684_VCC(vcc);
- struct net_device *net_dev = skb->dev;
- pr_debug("(vcc %p ; net_dev %p )\n", vcc, net_dev);
+ pr_debug("(vcc %p ; net_dev %p )\n", vcc, brvcc->device);
brvcc->old_pop(vcc, skb);
- if (!net_dev)
- return;
-
- if (atm_may_send(vcc, 0))
- netif_wake_queue(net_dev);
-
+ /* If the queue space just went up from zero, wake */
+ if (atomic_inc_return(&brvcc->qspace) == 1)
+ netif_wake_queue(brvcc->device);
}
+
/*
* Send a packet out a particular vcc. Not to useful right now, but paves
* the way for multiple vcc's per itf. Returns true if we can send,
@@ -256,16 +256,30 @@ static int br2684_xmit_vcc(struct sk_buf
ATM_SKB(skb)->atm_options = atmvcc->atm_options;
dev->stats.tx_packets++;
dev->stats.tx_bytes += skb->len;
- atmvcc->send(atmvcc, skb);
- if (!atm_may_send(atmvcc, 0)) {
+ if (atomic_dec_return(&brvcc->qspace) < 1) {
+ /* No more please! */
netif_stop_queue(brvcc->device);
- /*check for race with br2684_pop*/
- if (atm_may_send(atmvcc, 0))
- netif_start_queue(brvcc->device);
+ /* We might have raced with br2684_pop() */
+ if (unlikely(atomic_read(&brvcc->qspace) > 0))
+ netif_wake_queue(brvcc->device);
}
- return 1;
+ /* If this fails immediately, the skb will be freed and br2684_pop()
+ will wake the queue if appropriate. Just return an error so that
+ the stats are updated correctly */
+ return !atmvcc->send(atmvcc, skb);
+}
+
+static void br2684_release_cb(struct atm_vcc *atmvcc)
+{
+ struct br2684_vcc *brvcc = BR2684_VCC(atmvcc);
+
+ if (atomic_read(&brvcc->qspace) > 0)
+ netif_wake_queue(brvcc->device);
+
+ if (brvcc->old_release_cb)
+ brvcc->old_release_cb(atmvcc);
}
static inline struct br2684_vcc *pick_outgoing_vcc(const struct sk_buff *skb,
@@ -279,6 +293,8 @@ static netdev_tx_t br2684_start_xmit(str
{
struct br2684_dev *brdev = BRPRIV(dev);
struct br2684_vcc *brvcc;
+ struct atm_vcc *atmvcc;
+ netdev_tx_t ret = NETDEV_TX_OK;
pr_debug("skb_dst(skb)=%p\n", skb_dst(skb));
read_lock(&devs_lock);
@@ -289,9 +305,26 @@ static netdev_tx_t br2684_start_xmit(str
dev->stats.tx_carrier_errors++;
/* netif_stop_queue(dev); */
dev_kfree_skb(skb);
- read_unlock(&devs_lock);
- return NETDEV_TX_OK;
+ goto out_devs;
}
+ atmvcc = brvcc->atmvcc;
+
+ bh_lock_sock(sk_atm(atmvcc));
+
+ if (test_bit(ATM_VF_RELEASED, &atmvcc->flags) ||
+ test_bit(ATM_VF_CLOSE, &atmvcc->flags) ||
+ !test_bit(ATM_VF_READY, &atmvcc->flags)) {
+ dev->stats.tx_dropped++;
+ dev_kfree_skb(skb);
+ goto out;
+ }
+
+ if (sock_owned_by_user(sk_atm(atmvcc))) {
+ netif_stop_queue(brvcc->device);
+ ret = NETDEV_TX_BUSY;
+ goto out;
+ }
+
if (!br2684_xmit_vcc(skb, dev, brvcc)) {
/*
* We should probably use netif_*_queue() here, but that
@@ -303,8 +336,11 @@ static netdev_tx_t br2684_start_xmit(str
dev->stats.tx_errors++;
dev->stats.tx_fifo_errors++;
}
+ out:
+ bh_unlock_sock(sk_atm(atmvcc));
+ out_devs:
read_unlock(&devs_lock);
- return NETDEV_TX_OK;
+ return ret;
}
/*
@@ -377,9 +413,10 @@ static void br2684_close_vcc(struct br26
list_del(&brvcc->brvccs);
write_unlock_irq(&devs_lock);
brvcc->atmvcc->user_back = NULL; /* what about vcc->recvq ??? */
+ brvcc->atmvcc->release_cb = brvcc->old_release_cb;
brvcc->old_push(brvcc->atmvcc, NULL); /* pass on the bad news */
+ module_put(brvcc->old_owner);
kfree(brvcc);
- module_put(THIS_MODULE);
}
/* when AAL5 PDU comes in: */
@@ -504,6 +541,13 @@ static int br2684_regvcc(struct atm_vcc
brvcc = kzalloc(sizeof(struct br2684_vcc), GFP_KERNEL);
if (!brvcc)
return -ENOMEM;
+ /*
+ * Allow two packets in the ATM queue. One actually being sent, and one
+ * for the ATM 'TX done' handler to send. It shouldn't take long to get
+ * the next one from the netdev queue, when we need it. More than that
+ * would be bufferbloat.
+ */
+ atomic_set(&brvcc->qspace, 2);
write_lock_irq(&devs_lock);
net_dev = br2684_find_dev(&be.ifspec);
if (net_dev == NULL) {
@@ -546,9 +590,13 @@ static int br2684_regvcc(struct atm_vcc
brvcc->encaps = (enum br2684_encaps)be.encaps;
brvcc->old_push = atmvcc->push;
brvcc->old_pop = atmvcc->pop;
+ brvcc->old_release_cb = atmvcc->release_cb;
+ brvcc->old_owner = atmvcc->owner;
barrier();
atmvcc->push = br2684_push;
atmvcc->pop = br2684_pop;
+ atmvcc->release_cb = br2684_release_cb;
+ atmvcc->owner = THIS_MODULE;
/* initialize netdev carrier state */
if (atmvcc->dev->signal == ATM_PHY_SIG_LOST)
@@ -687,10 +735,13 @@ static int br2684_ioctl(struct socket *s
return -ENOIOCTLCMD;
if (!capable(CAP_NET_ADMIN))
return -EPERM;
- if (cmd == ATM_SETBACKEND)
+ if (cmd == ATM_SETBACKEND) {
+ if (sock->state != SS_CONNECTED)
+ return -EINVAL;
return br2684_regvcc(atmvcc, argp);
- else
+ } else {
return br2684_create(argp);
+ }
#ifdef CONFIG_ATM_BR2684_IPFILTER
case BR2684_SETFILT:
if (atmvcc->push != br2684_push)
--- a/net/atm/common.c
+++ b/net/atm/common.c
@@ -126,10 +126,19 @@ static void vcc_write_space(struct sock
rcu_read_unlock();
}
+static void vcc_release_cb(struct sock *sk)
+{
+ struct atm_vcc *vcc = atm_sk(sk);
+
+ if (vcc->release_cb)
+ vcc->release_cb(vcc);
+}
+
static struct proto vcc_proto = {
.name = "VCC",
.owner = THIS_MODULE,
.obj_size = sizeof(struct atm_vcc),
+ .release_cb = vcc_release_cb,
};
int vcc_create(struct net *net, struct socket *sock, int protocol, int family)
@@ -156,7 +165,9 @@ int vcc_create(struct net *net, struct s
atomic_set(&sk->sk_rmem_alloc, 0);
vcc->push = NULL;
vcc->pop = NULL;
+ vcc->owner = NULL;
vcc->push_oam = NULL;
+ vcc->release_cb = NULL;
vcc->vpi = vcc->vci = 0; /* no VCI/VPI yet */
vcc->atm_options = vcc->aal_options = 0;
sk->sk_destruct = vcc_sock_destruct;
@@ -175,6 +186,7 @@ static void vcc_destroy_socket(struct so
vcc->dev->ops->close(vcc);
if (vcc->push)
vcc->push(vcc, NULL); /* atmarpd has no push */
+ module_put(vcc->owner);
while ((skb = skb_dequeue(&sk->sk_receive_queue)) != NULL) {
atm_return(vcc, skb->truesize);
--- a/net/atm/pppoatm.c
+++ b/net/atm/pppoatm.c
@@ -60,6 +60,8 @@ struct pppoatm_vcc {
struct atm_vcc *atmvcc; /* VCC descriptor */
void (*old_push)(struct atm_vcc *, struct sk_buff *);
void (*old_pop)(struct atm_vcc *, struct sk_buff *);
+ void (*old_release_cb)(struct atm_vcc *);
+ struct module *old_owner;
/* keep old push/pop for detaching */
enum pppoatm_encaps encaps;
atomic_t inflight;
@@ -107,6 +109,24 @@ static void pppoatm_wakeup_sender(unsign
ppp_output_wakeup((struct ppp_channel *) arg);
}
+static void pppoatm_release_cb(struct atm_vcc *atmvcc)
+{
+ struct pppoatm_vcc *pvcc = atmvcc_to_pvcc(atmvcc);
+
+ /*
+ * As in pppoatm_pop(), it's safe to clear the BLOCKED bit here because
+ * the wakeup *can't* race with pppoatm_send(). They both hold the PPP
+ * channel's ->downl lock. And the potential race with *setting* it,
+ * which leads to the double-check dance in pppoatm_may_send(), doesn't
+ * exist here. In the sock_owned_by_user() case in pppoatm_send(), we
+ * set the BLOCKED bit while the socket is still locked. We know that
+ * ->release_cb() can't be called until that's done.
+ */
+ if (test_and_clear_bit(BLOCKED, &pvcc->blocked))
+ tasklet_schedule(&pvcc->wakeup_tasklet);
+ if (pvcc->old_release_cb)
+ pvcc->old_release_cb(atmvcc);
+}
/*
* This gets called every time the ATM card has finished sending our
* skb. The ->old_pop will take care up normal atm flow control,
@@ -151,12 +171,11 @@ static void pppoatm_unassign_vcc(struct
pvcc = atmvcc_to_pvcc(atmvcc);
atmvcc->push = pvcc->old_push;
atmvcc->pop = pvcc->old_pop;
+ atmvcc->release_cb = pvcc->old_release_cb;
tasklet_kill(&pvcc->wakeup_tasklet);
ppp_unregister_channel(&pvcc->chan);
atmvcc->user_back = NULL;
kfree(pvcc);
- /* Gee, I hope we have the big kernel lock here... */
- module_put(THIS_MODULE);
}
/* Called when an AAL5 PDU comes in */
@@ -165,9 +184,13 @@ static void pppoatm_push(struct atm_vcc
struct pppoatm_vcc *pvcc = atmvcc_to_pvcc(atmvcc);
pr_debug("\n");
if (skb == NULL) { /* VCC was closed */
+ struct module *module;
+
pr_debug("removing ATMPPP VCC %p\n", pvcc);
+ module = pvcc->old_owner;
pppoatm_unassign_vcc(atmvcc);
atmvcc->push(atmvcc, NULL); /* Pass along bad news */
+ module_put(module);
return;
}
atm_return(atmvcc, skb->truesize);
@@ -211,7 +234,7 @@ error:
ppp_input_error(&pvcc->chan, 0);
}
-static inline int pppoatm_may_send(struct pppoatm_vcc *pvcc, int size)
+static int pppoatm_may_send(struct pppoatm_vcc *pvcc, int size)
{
/*
* It's not clear that we need to bother with using atm_may_send()
@@ -269,10 +292,33 @@ static inline int pppoatm_may_send(struc
static int pppoatm_send(struct ppp_channel *chan, struct sk_buff *skb)
{
struct pppoatm_vcc *pvcc = chan_to_pvcc(chan);
+ struct atm_vcc *vcc;
+ int ret;
+
ATM_SKB(skb)->vcc = pvcc->atmvcc;
pr_debug("(skb=0x%p, vcc=0x%p)\n", skb, pvcc->atmvcc);
if (skb->data[0] == '\0' && (pvcc->flags & SC_COMP_PROT))
(void) skb_pull(skb, 1);
+
+ vcc = ATM_SKB(skb)->vcc;
+ bh_lock_sock(sk_atm(vcc));
+ if (sock_owned_by_user(sk_atm(vcc))) {
+ /*
+ * Needs to happen (and be flushed, hence test_and_) before we unlock
+ * the socket. It needs to be seen by the time our ->release_cb gets
+ * called.
+ */
+ test_and_set_bit(BLOCKED, &pvcc->blocked);
+ goto nospace;
+ }
+ if (test_bit(ATM_VF_RELEASED, &vcc->flags) ||
+ test_bit(ATM_VF_CLOSE, &vcc->flags) ||
+ !test_bit(ATM_VF_READY, &vcc->flags)) {
+ bh_unlock_sock(sk_atm(vcc));
+ kfree_skb(skb);
+ return DROP_PACKET;
+ }
+
switch (pvcc->encaps) { /* LLC encapsulation needed */
case e_llc:
if (skb_headroom(skb) < LLC_LEN) {
@@ -285,8 +331,10 @@ static int pppoatm_send(struct ppp_chann
}
consume_skb(skb);
skb = n;
- if (skb == NULL)
+ if (skb == NULL) {
+ bh_unlock_sock(sk_atm(vcc));
return DROP_PACKET;
+ }
} else if (!pppoatm_may_send(pvcc, skb->truesize))
goto nospace;
memcpy(skb_push(skb, LLC_LEN), pppllc, LLC_LEN);
@@ -296,6 +344,7 @@ static int pppoatm_send(struct ppp_chann
goto nospace;
break;
case e_autodetect:
+ bh_unlock_sock(sk_atm(vcc));
pr_debug("Trying to send without setting encaps!\n");
kfree_skb(skb);
return 1;
@@ -305,9 +354,12 @@ static int pppoatm_send(struct ppp_chann
ATM_SKB(skb)->atm_options = ATM_SKB(skb)->vcc->atm_options;
pr_debug("atm_skb(%p)->vcc(%p)->dev(%p)\n",
skb, ATM_SKB(skb)->vcc, ATM_SKB(skb)->vcc->dev);
- return ATM_SKB(skb)->vcc->send(ATM_SKB(skb)->vcc, skb)
+ ret = ATM_SKB(skb)->vcc->send(ATM_SKB(skb)->vcc, skb)
? DROP_PACKET : 1;
+ bh_unlock_sock(sk_atm(vcc));
+ return ret;
nospace:
+ bh_unlock_sock(sk_atm(vcc));
/*
* We don't have space to send this SKB now, but we might have
* already applied SC_COMP_PROT compression, so may need to undo
@@ -362,6 +414,8 @@ static int pppoatm_assign_vcc(struct atm
atomic_set(&pvcc->inflight, NONE_INFLIGHT);
pvcc->old_push = atmvcc->push;
pvcc->old_pop = atmvcc->pop;
+ pvcc->old_owner = atmvcc->owner;
+ pvcc->old_release_cb = atmvcc->release_cb;
pvcc->encaps = (enum pppoatm_encaps) be.encaps;
pvcc->chan.private = pvcc;
pvcc->chan.ops = &pppoatm_ops;
@@ -377,7 +431,9 @@ static int pppoatm_assign_vcc(struct atm
atmvcc->user_back = pvcc;
atmvcc->push = pppoatm_push;
atmvcc->pop = pppoatm_pop;
+ atmvcc->release_cb = pppoatm_release_cb;
__module_get(THIS_MODULE);
+ atmvcc->owner = THIS_MODULE;
/* re-process everything received between connection setup and
backend setup */
@@ -406,6 +462,8 @@ static int pppoatm_ioctl(struct socket *
return -ENOIOCTLCMD;
if (!capable(CAP_NET_ADMIN))
return -EPERM;
+ if (sock->state != SS_CONNECTED)
+ return -EINVAL;
return pppoatm_assign_vcc(atmvcc, argp);
}
case PPPIOCGCHAN:

View file

@ -1,417 +0,0 @@
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>
commit cae49ede00ec3d0cda290b03fee55b72b49efc11
Author: David Woodhouse <dwmw2@infradead.org>
Date: Tue Dec 11 14:57:14 2012 +0000
solos-pci: fix double-free of TX skb in DMA mode
We weren't clearing card->tx_skb[port] when processing the TX done interrupt.
If there wasn't another skb ready to transmit immediately, this led to a
double-free because we'd free it *again* next time we did have a packet to
send.
Signed-off-by: David Woodhouse <David.Woodhouse@intel.com>
Cc: stable@kernel.org
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
@@ -945,10 +1069,11 @@ static uint32_t fpga_tx(struct solos_car
for (port = 0; tx_pending; tx_pending >>= 1, port++) {
if (tx_pending & 1) {
struct sk_buff *oldskb = card->tx_skb[port];
- if (oldskb)
+ if (oldskb) {
pci_unmap_single(card->dev, SKB_CB(oldskb)->dma_addr,
oldskb->len, PCI_DMA_TODEVICE);
-
+ card->tx_skb[port] = NULL;
+ }
spin_lock(&card->tx_queue_lock);
skb = skb_dequeue(&card->tx_queue[port]);
if (!skb)
@@ -960,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,
@@ -1134,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);
@@ -1180,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:
@@ -1188,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:
@@ -1290,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);

View file

@ -1,11 +0,0 @@
--- a/scripts/setlocalversion
+++ b/scripts/setlocalversion
@@ -167,7 +167,7 @@ else
# annotated or signed tagged state (as git describe only
# looks at signed or annotated tags - git tag -a/-s) and
# LOCALVERSION= is not specified
- if test "${LOCALVERSION+set}" != "set"; then
+ if test "${CONFIG_LOCALVERSION+set}" != "set"; then
scm=$(scm_version --short)
res="$res${scm:++}"
fi

View file

@ -1,14 +0,0 @@
--- a/Makefile
+++ b/Makefile
@@ -556,9 +556,9 @@ endif # $(dot-config)
all: vmlinux
ifdef CONFIG_CC_OPTIMIZE_FOR_SIZE
-KBUILD_CFLAGS += -Os
+KBUILD_CFLAGS += -Os $(EXTRA_OPTIMIZATION)
else
-KBUILD_CFLAGS += -O2
+KBUILD_CFLAGS += -O2 -fno-reorder-blocks -fno-tree-ch $(EXTRA_OPTIMIZATION)
endif
include $(srctree)/arch/$(SRCARCH)/Makefile

View file

@ -1,11 +0,0 @@
--- a/Makefile
+++ b/Makefile
@@ -369,7 +369,7 @@ KBUILD_CFLAGS_KERNEL :=
KBUILD_AFLAGS := -D__ASSEMBLY__
KBUILD_AFLAGS_MODULE := -DMODULE
KBUILD_CFLAGS_MODULE := -DMODULE
-KBUILD_LDFLAGS_MODULE := -T $(srctree)/scripts/module-common.lds
+KBUILD_LDFLAGS_MODULE = -T $(srctree)/scripts/module-common.lds $(if $(CONFIG_PROFILING),,-s)
# Read KERNELRELEASE from include/config/kernel.release (if it exists)
KERNELRELEASE = $(shell cat include/config/kernel.release 2> /dev/null)

View file

@ -1,17 +0,0 @@
--- a/include/linux/stddef.h
+++ b/include/linux/stddef.h
@@ -12,6 +12,7 @@ enum {
false = 0,
true = 1
};
+#endif /* __KERNEL__ */
#undef offsetof
#ifdef __compiler_offsetof
@@ -19,6 +20,5 @@ enum {
#else
#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
#endif
-#endif /* __KERNEL__ */
#endif

View file

@ -1,53 +0,0 @@
--- a/tools/include/tools/be_byteshift.h
+++ b/tools/include/tools/be_byteshift.h
@@ -1,7 +1,11 @@
#ifndef _TOOLS_BE_BYTESHIFT_H
#define _TOOLS_BE_BYTESHIFT_H
+#ifdef __linux__
#include <linux/types.h>
+#else
+#include "linux_types.h"
+#endif
static inline __u16 __get_unaligned_be16(const __u8 *p)
{
--- a/tools/include/tools/le_byteshift.h
+++ b/tools/include/tools/le_byteshift.h
@@ -1,7 +1,11 @@
#ifndef _TOOLS_LE_BYTESHIFT_H
#define _TOOLS_LE_BYTESHIFT_H
+#ifdef __linux__
#include <linux/types.h>
+#else
+#include "linux_types.h"
+#endif
static inline __u16 __get_unaligned_le16(const __u8 *p)
{
--- /dev/null
+++ b/tools/include/tools/linux_types.h
@@ -0,0 +1,22 @@
+#ifndef __LINUX_TYPES_H
+#define __LINUX_TYPES_H
+
+#include <stdint.h>
+
+typedef uint8_t __u8;
+typedef uint8_t __be8;
+typedef uint8_t __le8;
+
+typedef uint16_t __u16;
+typedef uint16_t __be16;
+typedef uint16_t __le16;
+
+typedef uint32_t __u32;
+typedef uint32_t __be32;
+typedef uint32_t __le32;
+
+typedef uint64_t __u64;
+typedef uint64_t __be64;
+typedef uint64_t __le64;
+
+#endif

View file

@ -1,91 +0,0 @@
--- a/include/asm-generic/vmlinux.lds.h
+++ b/include/asm-generic/vmlinux.lds.h
@@ -52,6 +52,18 @@
#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+*)
+#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 @@
/* Kernel symbol table: Normal symbols */ \
__ksymtab : AT(ADDR(__ksymtab) - LOAD_OFFSET) { \
VMLINUX_SYMBOL(__start___ksymtab) = .; \
- *(SORT(___ksymtab+*)) \
+ SYMTAB_KEEP \
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+*)) \
+ SYMTAB_KEEP_GPL \
VMLINUX_SYMBOL(__stop___ksymtab_gpl) = .; \
} \
\
@@ -345,7 +357,7 @@
\
/* Kernel symbol table: strings */ \
__ksymtab_strings : AT(ADDR(__ksymtab_strings) - LOAD_OFFSET) { \
- *(__ksymtab_strings) \
+ SYMTAB_KEEP_STR \
} \
\
/* __*init sections */ \
@@ -670,6 +682,9 @@
EXIT_TEXT \
EXIT_DATA \
EXIT_CALL \
+ SYMTAB_DISCARD \
+ SYMTAB_DISCARD_GPL \
+ SYMTAB_DISCARD_STR \
*(.discard) \
*(.discard.*) \
}
--- a/include/linux/export.h
+++ b/include/linux/export.h
@@ -45,12 +45,19 @@ extern struct module __this_module;
#define __CRC_SYMBOL(sym, sec)
#endif
+#ifdef MODULE
+#define __EXPORT_SUFFIX(sym)
+#else
+#define __EXPORT_SUFFIX(sym) "+" #sym
+#endif
+
/* For every exported symbol, place a struct in the __ksymtab section */
#define __EXPORT_SYMBOL(sym, sec) \
extern typeof(sym) sym; \
__CRC_SYMBOL(sym, sec) \
static const char __kstrtab_##sym[] \
- __attribute__((section("__ksymtab_strings"), aligned(1))) \
+ __attribute__((section("__ksymtab_strings" \
+ __EXPORT_SUFFIX(sym)), aligned(1))) \
= 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

View file

@ -1,54 +0,0 @@
--- a/scripts/Makefile.lib
+++ b/scripts/Makefile.lib
@@ -296,7 +296,7 @@ cmd_bzip2 = (cat $(filter-out FORCE,$^)
quiet_cmd_lzma = LZMA $@
cmd_lzma = (cat $(filter-out FORCE,$^) | \
- lzma -9 && $(call size_append, $(filter-out FORCE,$^))) > $@ || \
+ lzma e -d20 -lc1 -lp2 -pb2 -eos -si -so && $(call size_append, $(filter-out FORCE,$^))) > $@ || \
(rm -f $@ ; false)
quiet_cmd_lzo = LZO $@
--- a/scripts/gen_initramfs_list.sh
+++ b/scripts/gen_initramfs_list.sh
@@ -226,7 +226,7 @@ cpio_list=
output="/dev/stdout"
output_file=""
is_cpio_compressed=
-compr="gzip -n -9 -f"
+compr="gzip -n -9 -f -"
arg="$1"
case "$arg" in
@@ -240,9 +240,9 @@ case "$arg" in
output_file="$1"
cpio_list="$(mktemp ${TMPDIR:-/tmp}/cpiolist.XXXXXX)"
output=${cpio_list}
- echo "$output_file" | grep -q "\.gz$" && compr="gzip -n -9 -f"
- echo "$output_file" | grep -q "\.bz2$" && compr="bzip2 -9 -f"
- echo "$output_file" | grep -q "\.lzma$" && compr="lzma -9 -f"
+ echo "$output_file" | grep -q "\.gz$" && compr="gzip -n -9 -f -"
+ echo "$output_file" | grep -q "\.bz2$" && compr="bzip2 -9 -f -"
+ echo "$output_file" | grep -q "\.lzma$" && compr="lzma e -d20 -lc1 -lp2 -pb2 -eos -si -so"
echo "$output_file" | grep -q "\.xz$" && \
compr="xz --check=crc32 --lzma2=dict=1MiB"
echo "$output_file" | grep -q "\.lzo$" && compr="lzop -9 -f"
@@ -303,7 +303,7 @@ if [ ! -z ${output_file} ]; then
if [ "${is_cpio_compressed}" = "compressed" ]; then
cat ${cpio_tfile} > ${output_file}
else
- (cat ${cpio_tfile} | ${compr} - > ${output_file}) \
+ (cat ${cpio_tfile} | ${compr} > ${output_file}) \
|| (rm -f ${output_file} ; false)
fi
[ -z ${cpio_file} ] && rm ${cpio_tfile}
--- a/lib/decompress.c
+++ b/lib/decompress.c
@@ -40,6 +40,7 @@ static const struct compress_format {
{ {037, 0236}, "gzip", gunzip },
{ {0x42, 0x5a}, "bzip2", bunzip2 },
{ {0x5d, 0x00}, "lzma", unlzma },
+ { {0x6d, 0x00}, "lzma-openwrt", unlzma },
{ {0xfd, 0x37}, "xz", unxz },
{ {0x89, 0x4c}, "lzo", unlzo },
{ {0, 0}, NULL, NULL }

View file

@ -1,18 +0,0 @@
--- a/net/netfilter/Kconfig
+++ b/net/netfilter/Kconfig
@@ -191,7 +191,6 @@ config NF_CONNTRACK_FTP
config NF_CONNTRACK_H323
tristate "H.323 protocol support"
- depends on (IPV6 || IPV6=n)
depends on NETFILTER_ADVANCED
help
H.323 is a VoIP signalling protocol from ITU-T. As one of the most
@@ -693,7 +692,6 @@ config NETFILTER_XT_TARGET_SECMARK
config NETFILTER_XT_TARGET_TCPMSS
tristate '"TCPMSS" target support'
- depends on (IPV6 || IPV6=n)
default m if NETFILTER_ADVANCED=n
---help---
This option adds a `TCPMSS' target, which allows you to alter the

View file

@ -1,18 +0,0 @@
--- a/sound/core/Kconfig
+++ b/sound/core/Kconfig
@@ -7,13 +7,13 @@ config SND_PCM
select SND_TIMER
config SND_HWDEP
- tristate
+ tristate "Sound hardware support"
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

View file

@ -1,10 +0,0 @@
--- a/drivers/crypto/Kconfig
+++ b/drivers/crypto/Kconfig
@@ -164,6 +164,7 @@ config CRYPTO_DEV_MV_CESA
depends on PLAT_ORION
select CRYPTO_ALGAPI
select CRYPTO_AES
+ select CRYPTO_HASH2
select CRYPTO_BLKCIPHER2
select CRYPTO_HASH
help

View file

@ -1,29 +0,0 @@
--- a/drivers/ssb/Kconfig
+++ b/drivers/ssb/Kconfig
@@ -29,6 +29,7 @@ config SSB_SPROM
config SSB_BLOCKIO
bool
depends on SSB
+ default y
config SSB_PCIHOST_POSSIBLE
bool
@@ -49,7 +50,7 @@ config SSB_PCIHOST
config SSB_B43_PCI_BRIDGE
bool
depends on SSB_PCIHOST
- default n
+ default y
config SSB_PCMCIAHOST_POSSIBLE
bool
--- a/drivers/bcma/Kconfig
+++ b/drivers/bcma/Kconfig
@@ -17,6 +17,7 @@ config BCMA
config BCMA_BLOCKIO
bool
depends on BCMA
+ default y
config BCMA_HOST_PCI_POSSIBLE
bool

View file

@ -1,23 +0,0 @@
--- a/lib/Kconfig
+++ b/lib/Kconfig
@@ -277,16 +277,16 @@ config BCH_CONST_T
# Textsearch support is select'ed if needed
#
config TEXTSEARCH
- boolean
+ boolean "Textsearch support"
config TEXTSEARCH_KMP
- tristate
+ tristate "Textsearch KMP"
config TEXTSEARCH_BM
- tristate
+ tristate "Textsearch BM"
config TEXTSEARCH_FSM
- tristate
+ tristate "Textsearch FSM"
config BTREE
boolean

View file

@ -1,19 +0,0 @@
--- a/net/wireless/Kconfig
+++ b/net/wireless/Kconfig
@@ -150,13 +150,13 @@ config LIB80211
you want this built into your kernel.
config LIB80211_CRYPT_WEP
- tristate
+ tristate "LIB80211_CRYPT_WEP"
config LIB80211_CRYPT_CCMP
- tristate
+ tristate "LIB80211_CRYPT_CCMP"
config LIB80211_CRYPT_TKIP
- tristate
+ tristate "LIB80211_CRYPT_TKIP"
config LIB80211_DEBUG
bool "lib80211 debugging messages"

View file

@ -1,47 +0,0 @@
--- a/crypto/Kconfig
+++ b/crypto/Kconfig
@@ -31,7 +31,7 @@ config CRYPTO_FIPS
this is.
config CRYPTO_ALGAPI
- tristate
+ tristate "ALGAPI"
select CRYPTO_ALGAPI2
help
This option provides the API for cryptographic algorithms.
@@ -40,7 +40,7 @@ config CRYPTO_ALGAPI2
tristate
config CRYPTO_AEAD
- tristate
+ tristate "AEAD"
select CRYPTO_AEAD2
select CRYPTO_ALGAPI
@@ -49,7 +49,7 @@ config CRYPTO_AEAD2
select CRYPTO_ALGAPI2
config CRYPTO_BLKCIPHER
- tristate
+ tristate "BLKCIPHER"
select CRYPTO_BLKCIPHER2
select CRYPTO_ALGAPI
@@ -60,7 +60,7 @@ config CRYPTO_BLKCIPHER2
select CRYPTO_WORKQUEUE
config CRYPTO_HASH
- tristate
+ tristate "HASH"
select CRYPTO_HASH2
select CRYPTO_ALGAPI
@@ -69,7 +69,7 @@ config CRYPTO_HASH2
select CRYPTO_ALGAPI2
config CRYPTO_RNG
- tristate
+ tristate "RNG"
select CRYPTO_RNG2
select CRYPTO_ALGAPI

View file

@ -1,22 +0,0 @@
--- a/net/wireless/Kconfig
+++ b/net/wireless/Kconfig
@@ -1,5 +1,5 @@
config WIRELESS_EXT
- bool
+ bool "Wireless extensions"
config WEXT_CORE
def_bool y
@@ -11,10 +11,10 @@ config WEXT_PROC
depends on WEXT_CORE
config WEXT_SPY
- bool
+ bool "WEXT_SPY"
config WEXT_PRIV
- bool
+ bool "WEXT_PRIV"
config CFG80211
tristate "cfg80211 - wireless configuration API"

View file

@ -1,11 +0,0 @@
--- a/net/netfilter/Kconfig
+++ b/net/netfilter/Kconfig
@@ -2,7 +2,7 @@ menu "Core Netfilter Configuration"
depends on NET && INET && NETFILTER
config NETFILTER_NETLINK
- tristate
+ tristate "Netfilter NFNETLINK interface"
config NETFILTER_NETLINK_ACCT
tristate "Netfilter NFACCT over NFNETLINK interface"

View file

@ -1,23 +0,0 @@
--- 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"

View file

@ -1,219 +0,0 @@
--- 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/linux/Kbuild
+++ b/include/linux/Kbuild
@@ -78,6 +78,7 @@ header-y += blk_types.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/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 */

View file

@ -1,67 +0,0 @@
--- a/drivers/base/regmap/Kconfig
+++ b/drivers/base/regmap/Kconfig
@@ -3,19 +3,21 @@
# subsystems should select the appropriate symbols.
config REGMAP
- default y if (REGMAP_I2C || REGMAP_SPI)
select LZO_COMPRESS
select LZO_DECOMPRESS
select IRQ_DOMAIN if REGMAP_IRQ
- bool
+ tristate
config REGMAP_I2C
+ select REGMAP
tristate
config REGMAP_SPI
+ select REGMAP
tristate
config REGMAP_MMIO
+ select REGMAP
tristate
config REGMAP_IRQ
--- 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>
@@ -1418,3 +1419,5 @@ static int __init regmap_initcall(void)
return 0;
}
postcore_initcall(regmap_initcall);
+
+MODULE_LICENSE("GPL");

View file

@ -1,39 +0,0 @@
From: Mark Miller <mark@mirell.org>
This exposes the CONFIG_BOOT_RAW symbol in Kconfig. This is needed on
certain Broadcom chipsets running CFE in order to load the kernel.
Signed-off-by: Mark Miller <mark@mirell.org>
Acked-by: Rob Landley <rob@landley.net>
---
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -894,9 +894,6 @@ config ARC
config ARCH_MAY_HAVE_PC_FDC
bool
-config BOOT_RAW
- bool
-
config CEVT_BCM1480
bool
@@ -2367,6 +2364,18 @@ config USE_OF
help
Include support for flattened device tree machine descriptions.
+config BOOT_RAW
+ bool "Enable the kernel to be executed from the load address"
+ default n
+ help
+ Allow the kernel to be executed from the load address for
+ bootloaders which cannot read the ELF format. This places
+ a jump to start_kernel at the load address.
+
+ If unsure, say N.
+
+
+
endmenu
config LOCKDEP_SUPPORT

View file

@ -1,28 +0,0 @@
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -993,6 +993,10 @@ config SYNC_R4K
config MIPS_MACHINE
def_bool n
+config IMAGE_CMDLINE_HACK
+ bool "OpenWrt specific image command line hack"
+ default n
+
config NO_IOPORT
def_bool n
--- a/arch/mips/kernel/head.S
+++ b/arch/mips/kernel/head.S
@@ -141,6 +141,12 @@ FEXPORT(__kernel_entry)
j kernel_entry
#endif
+#ifdef CONFIG_IMAGE_CMDLINE_HACK
+ .ascii "CMDLINE:"
+EXPORT(__image_cmdline)
+ .fill 0x400
+#endif /* CONFIG_IMAGE_CMDLINE_HACK */
+
__REF
NESTED(kernel_entry, 16, sp) # kernel entry point

View file

@ -1,11 +0,0 @@
--- 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
KBUILD_AFLAGS_MODULE += -mlong-calls

View file

@ -1,11 +0,0 @@
--- a/arch/mips/kernel/machine_kexec.c
+++ b/arch/mips/kernel/machine_kexec.c
@@ -52,7 +52,7 @@ machine_kexec(struct kimage *image)
reboot_code_buffer =
(unsigned long)page_address(image->control_code_page);
- kexec_start_address = image->start;
+ kexec_start_address = (unsigned long) phys_to_virt(image->start);
kexec_indirection_page =
(unsigned long) phys_to_virt(image->head & PAGE_MASK);

View file

@ -1,160 +0,0 @@
MIPS: allow disabling the kernel FPU emulator
This patch allows turning off the in-kernel Algorithmics
FPU emulator support, which allows one to save a couple of
precious blocks on an embedded system.
Signed-off-by: Florian Fainelli <florian@openwrt.org>
--
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -978,6 +978,17 @@ config I8259
config MIPS_BONITO64
bool
+config MIPS_FPU_EMU
+ bool "Enable FPU emulation"
+ default y
+ help
+ This option allows building a kernel with or without the Algorithmics
+ FPU emulator enabled. Turning off this option results in a kernel which
+ does not catch floating operations exceptions. Make sure that your toolchain
+ is configured to enable software floating point emulation in that case.
+
+ If unsure say Y here.
+
config MIPS_MSC
bool
--- a/arch/mips/math-emu/Makefile
+++ b/arch/mips/math-emu/Makefile
@@ -2,11 +2,13 @@
# Makefile for the Linux/MIPS kernel FPU emulation.
#
-obj-y := cp1emu.o ieee754m.o ieee754d.o ieee754dp.o ieee754sp.o ieee754.o \
+obj-y := kernel_linkage.o dsemul.o cp1emu.o
+
+obj-$(CONFIG_MIPS_FPU_EMU) += ieee754m.o ieee754d.o ieee754dp.o ieee754sp.o ieee754.o \
ieee754xcpt.o dp_frexp.o dp_modf.o dp_div.o dp_mul.o dp_sub.o \
dp_add.o dp_fsp.o dp_cmp.o dp_logb.o dp_scalb.o dp_simple.o \
dp_tint.o dp_fint.o dp_tlong.o dp_flong.o sp_frexp.o sp_modf.o \
sp_div.o sp_mul.o sp_sub.o sp_add.o sp_fdp.o sp_cmp.o sp_logb.o \
sp_scalb.o sp_simple.o sp_tint.o sp_fint.o sp_tlong.o sp_flong.o \
- dp_sqrt.o sp_sqrt.o kernel_linkage.o dsemul.o
+ dp_sqrt.o sp_sqrt.o
--- a/arch/mips/math-emu/cp1emu.c
+++ b/arch/mips/math-emu/cp1emu.c
@@ -58,7 +58,11 @@
#define __mips 4
/* Function which emulates a floating point instruction. */
+#ifdef CONFIG_DEBUG_FS
+DEFINE_PER_CPU(struct mips_fpu_emulator_stats, fpuemustats);
+#endif
+#ifdef CONFIG_MIPS_FPU_EMU
static int fpu_emu(struct pt_regs *, struct mips_fpu_struct *,
mips_instruction);
@@ -69,10 +73,6 @@ static int fpux_emu(struct pt_regs *,
/* Further private data for which no space exists in mips_fpu_struct */
-#ifdef CONFIG_DEBUG_FS
-DEFINE_PER_CPU(struct mips_fpu_emulator_stats, fpuemustats);
-#endif
-
/* Control registers */
#define FPCREG_RID 0 /* $0 = revision id */
@@ -1360,7 +1360,6 @@ int fpu_emulator_cop1Handler(struct pt_r
return sig;
}
-
#ifdef CONFIG_DEBUG_FS
static int fpuemu_stat_get(void *data, u64 *val)
@@ -1409,4 +1408,11 @@ static int __init debugfs_fpuemu(void)
return 0;
}
__initcall(debugfs_fpuemu);
-#endif
+#endif /* CONFIG_DEBUGFS */
+#else
+int fpu_emulator_cop1Handler(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
+ int has_fpu)
+{
+ return 0;
+}
+#endif /* CONFIG_MIPS_FPU_EMU */
--- a/arch/mips/math-emu/dsemul.c
+++ b/arch/mips/math-emu/dsemul.c
@@ -108,6 +108,7 @@ int mips_dsemul(struct pt_regs *regs, mi
return SIGILL; /* force out of emulation loop */
}
+#ifdef CONFIG_MIPS_FPU_EMU
int do_dsemulret(struct pt_regs *xcp)
{
struct emuframe __user *fr;
@@ -164,3 +165,9 @@ int do_dsemulret(struct pt_regs *xcp)
return 1;
}
+#else
+int do_dsemulret(struct pt_regs *xcp)
+{
+ return 0;
+}
+#endif /* CONFIG_MIPS_FPU_EMU */
--- a/arch/mips/math-emu/kernel_linkage.c
+++ b/arch/mips/math-emu/kernel_linkage.c
@@ -29,6 +29,7 @@
#define SIGNALLING_NAN 0x7ff800007ff80000LL
+#ifdef CONFIG_MIPS_FPU_EMU
void fpu_emulator_init_fpu(void)
{
static int first = 1;
@@ -112,4 +113,36 @@ int fpu_emulator_restore_context32(struc
return err;
}
-#endif
+#endif /* CONFIG_64BIT */
+#else
+
+void fpu_emulator_init_fpu(void)
+{
+ printk(KERN_INFO "FPU emulator disabled, make sure your toolchain"
+ "was compiled with software floating point support (soft-float)\n");
+ return;
+}
+
+int fpu_emulator_save_context(struct sigcontext __user *sc)
+{
+ return 0;
+}
+
+int fpu_emulator_restore_context(struct sigcontext __user *sc)
+{
+ return 0;
+}
+
+int fpu_emulator_save_context32(struct sigcontext32 __user *sc)
+{
+ return 0;
+}
+
+int fpu_emulator_restore_context32(struct sigcontext32 __user *sc)
+{
+ return 0;
+}
+
+#ifdef CONFIG_64BIT
+#endif /* CONFIG_64BIT */
+#endif /* CONFIG_MIPS_FPU_EMU */

View file

@ -1,371 +0,0 @@
--- a/arch/mips/Makefile
+++ b/arch/mips/Makefile
@@ -90,8 +90,8 @@ 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
-KBUILD_AFLAGS_MODULE += -mlong-calls
-KBUILD_CFLAGS_MODULE += -mlong-calls
+KBUILD_AFLAGS_MODULE += -mno-long-calls
+KBUILD_CFLAGS_MODULE += -mno-long-calls
cflags-y += -ffreestanding
--- 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;
+}
static int apply_r_mips_none(struct module *me, u32 *location, Elf_Addr v)
{
@@ -70,28 +275,36 @@ static int apply_r_mips_32_rela(struct m
return 0;
}
-static int apply_r_mips_26_rel(struct module *me, u32 *location, Elf_Addr v)
+static Elf_Addr add_plt_entry_to(unsigned *plt_offset,
+ void *start, Elf_Addr v)
{
- if (v % 4) {
- pr_err("module %s: dangerous R_MIPS_26 REL relocation\n",
- me->name);
- return -ENOEXEC;
- }
+ unsigned *tramp = start + *plt_offset;
+ *plt_offset += 4 * sizeof(int);
- if ((v & 0xf0000000) != (((unsigned long)location + 4) & 0xf0000000)) {
- printk(KERN_ERR
- "module %s: relocation overflow\n",
- me->name);
- return -ENOEXEC;
- }
+ /* adjust carry for addiu */
+ if (v & 0x00008000)
+ v += 0x10000;
- *location = (*location & ~0x03ffffff) |
- ((*location + (v >> 2)) & 0x03ffffff);
+ 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 0;
+ return (Elf_Addr) tramp;
}
-static int apply_r_mips_26_rela(struct module *me, u32 *location, Elf_Addr v)
+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 set_r_mips_26(struct module *me, u32 *location, u32 ofs, Elf_Addr v)
{
if (v % 4) {
pr_err("module %s: dangerous R_MIPS_26 RELArelocation\n",
@@ -100,17 +313,31 @@ static int apply_r_mips_26_rela(struct m
}
if ((v & 0xf0000000) != (((unsigned long)location + 4) & 0xf0000000)) {
- printk(KERN_ERR
+ v = add_plt_entry(me, location, v + (ofs << 2));
+ if (!v) {
+ printk(KERN_ERR
"module %s: relocation overflow\n",
me->name);
- return -ENOEXEC;
+ return -ENOEXEC;
+ }
+ ofs = 0;
}
- *location = (*location & ~0x03ffffff) | ((v >> 2) & 0x03ffffff);
+ *location = (*location & ~0x03ffffff) | ((ofs + (v >> 2)) & 0x03ffffff);
return 0;
}
+static int apply_r_mips_26_rel(struct module *me, u32 *location, Elf_Addr v)
+{
+ return set_r_mips_26(me, location, *location & 0x03ffffff, v);
+}
+
+static int apply_r_mips_26_rela(struct module *me, u32 *location, Elf_Addr v)
+{
+ return set_r_mips_26(me, location, 0, v);
+}
+
static int apply_r_mips_hi16_rel(struct module *me, u32 *location, Elf_Addr v)
{
struct mips_hi16 *n;
@@ -405,11 +632,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);

View file

@ -1,83 +0,0 @@
--- a/arch/mips/include/asm/string.h
+++ b/arch/mips/include/asm/string.h
@@ -133,11 +133,44 @@ strncmp(__const__ char *__cs, __const__
#define __HAVE_ARCH_MEMSET
extern void *memset(void *__s, int __c, size_t __count);
+#define memset(__s, __c, len) \
+({ \
+ size_t __len = (len); \
+ void *__ret; \
+ if (__builtin_constant_p(len) && __len >= 64) \
+ __ret = memset((__s), (__c), __len); \
+ else \
+ __ret = __builtin_memset((__s), (__c), __len); \
+ __ret; \
+})
#define __HAVE_ARCH_MEMCPY
extern void *memcpy(void *__to, __const__ void *__from, size_t __n);
+#define memcpy(dst, src, len) \
+({ \
+ size_t __len = (len); \
+ void *__ret; \
+ if (__builtin_constant_p(len) && __len >= 64) \
+ __ret = memcpy((dst), (src), __len); \
+ else \
+ __ret = __builtin_memcpy((dst), (src), __len); \
+ __ret; \
+})
#define __HAVE_ARCH_MEMMOVE
extern void *memmove(void *__dest, __const__ void *__src, size_t __n);
+#define memmove(dst, src, len) \
+({ \
+ size_t __len = (len); \
+ void *__ret; \
+ if (__builtin_constant_p(len) && __len >= 64) \
+ __ret = memmove((dst), (src), __len); \
+ else \
+ __ret = __builtin_memmove((dst), (src), __len); \
+ __ret; \
+})
+
+#define __HAVE_ARCH_MEMCMP
+#define memcmp(src1, src2, len) __builtin_memcmp((src1), (src2), (len))
#endif /* _ASM_STRING_H */
--- a/arch/mips/lib/Makefile
+++ b/arch/mips/lib/Makefile
@@ -3,7 +3,7 @@
#
lib-y += csum_partial.o delay.o memcpy.o memset.o \
- strlen_user.o strncpy_user.o strnlen_user.o uncached.o
+ strlen_user.o strncpy_user.o strnlen_user.o uncached.o memcmp.o
obj-y += iomap.o
obj-$(CONFIG_PCI) += iomap-pci.o
--- /dev/null
+++ b/arch/mips/lib/memcmp.c
@@ -0,0 +1,22 @@
+/*
+ * copied from linux/lib/string.c
+ *
+ * Copyright (C) 1991, 1992 Linus Torvalds
+ */
+
+#include <linux/module.h>
+#include <linux/string.h>
+
+#undef memcmp
+int memcmp(const void *cs, const void *ct, size_t count)
+{
+ const unsigned char *su1, *su2;
+ int res = 0;
+
+ for (su1 = cs, su2 = ct; 0 < count; ++su1, ++su2, count--)
+ if ((res = *su1 - *su2) != 0)
+ break;
+ return res;
+}
+EXPORT_SYMBOL(memcmp);
+

View file

@ -1,17 +0,0 @@
--- a/arch/mips/kernel/cpu-probe.c
+++ b/arch/mips/kernel/cpu-probe.c
@@ -833,10 +833,13 @@ static inline void cpu_probe_mips(struct
__cpu_name[cpu] = "MIPS 20Kc";
break;
case PRID_IMP_24K:
- case PRID_IMP_24KE:
c->cputype = CPU_24K;
__cpu_name[cpu] = "MIPS 24Kc";
break;
+ case PRID_IMP_24KE:
+ c->cputype = CPU_24K;
+ __cpu_name[cpu] = "MIPS 24KEc";
+ break;
case PRID_IMP_25KF:
c->cputype = CPU_25KF;
__cpu_name[cpu] = "MIPS 25Kc";

View file

@ -1,32 +0,0 @@
--- a/arch/mips/mm/cache.c
+++ b/arch/mips/mm/cache.c
@@ -39,6 +39,7 @@ void (*__flush_kernel_vmap_range)(unsign
void (*__invalidate_kernel_vmap_range)(unsigned long vaddr, int size);
EXPORT_SYMBOL_GPL(__flush_kernel_vmap_range);
+EXPORT_SYMBOL(__flush_cache_all);
/* MIPS specific cache operations */
void (*flush_cache_sigtramp)(unsigned long addr);
--- a/fs/fuse/dev.c
+++ b/fs/fuse/dev.c
@@ -19,6 +19,9 @@
#include <linux/pipe_fs_i.h>
#include <linux/swap.h>
#include <linux/splice.h>
+#ifdef CONFIG_MIPS
+#include <asm/cacheflush.h>
+#endif
MODULE_ALIAS_MISCDEV(FUSE_MINOR);
MODULE_ALIAS("devname:fuse");
@@ -655,6 +658,9 @@ static int fuse_copy_fill(struct fuse_co
static int fuse_copy_do(struct fuse_copy_state *cs, void **val, unsigned *size)
{
unsigned ncpy = min(*size, cs->len);
+#ifdef CONFIG_MIPS
+ __flush_cache_all();
+#endif
if (val) {
if (cs->write)
memcpy(cs->buf, *val, ncpy);

View file

@ -1,13 +0,0 @@
--- a/arch/arm/kernel/module.c
+++ b/arch/arm/kernel/module.c
@@ -81,6 +81,10 @@ apply_relocate(Elf32_Shdr *sechdrs, cons
return -ENOEXEC;
}
+ if ((IS_ERR_VALUE(sym->st_value) || !sym->st_value) &&
+ ELF_ST_BIND(sym->st_info) == STB_WEAK)
+ continue;
+
loc = dstsec->sh_addr + rel->r_offset;
switch (ELF32_R_TYPE(rel->r_info)) {

View file

@ -1,31 +0,0 @@
Upstream doesn't optimize the kernel and bootwrappers for ppc44x because
they still want to support gcc 3.3 -- well, we don't.
--- a/arch/powerpc/Makefile
+++ b/arch/powerpc/Makefile
@@ -119,7 +119,8 @@ ifeq ($(CONFIG_FUNCTION_TRACER),y)
KBUILD_CFLAGS += -mno-sched-epilog
endif
-cpu-as-$(CONFIG_4xx) += -Wa,-m405
+cpu-as-$(CONFIG_40x) += -Wa,-m405
+cpu-as-$(CONFIG_44x) += -Wa,-m440
cpu-as-$(CONFIG_ALTIVEC) += -Wa,-maltivec
cpu-as-$(CONFIG_E500) += -Wa,-me500
cpu-as-$(CONFIG_E200) += -Wa,-me200
--- a/arch/powerpc/boot/Makefile
+++ b/arch/powerpc/boot/Makefile
@@ -38,10 +38,10 @@ BOOTCFLAGS += -I$(obj) -I$(srctree)/$(ob
DTC_FLAGS ?= -p 1024
$(obj)/4xx.o: BOOTCFLAGS += -mcpu=405
-$(obj)/ebony.o: BOOTCFLAGS += -mcpu=405
+$(obj)/ebony.o: BOOTCFLAGS += -mcpu=440
$(obj)/cuboot-hotfoot.o: BOOTCFLAGS += -mcpu=405
-$(obj)/cuboot-taishan.o: BOOTCFLAGS += -mcpu=405
-$(obj)/cuboot-katmai.o: BOOTCFLAGS += -mcpu=405
+$(obj)/cuboot-taishan.o: BOOTCFLAGS += -mcpu=440
+$(obj)/cuboot-katmai.o: BOOTCFLAGS += -mcpu=440
$(obj)/cuboot-acadia.o: BOOTCFLAGS += -mcpu=405
$(obj)/treeboot-walnut.o: BOOTCFLAGS += -mcpu=405
$(obj)/treeboot-iss4xx.o: BOOTCFLAGS += -mcpu=405

View file

@ -1,10 +0,0 @@
--- a/arch/powerpc/Makefile
+++ b/arch/powerpc/Makefile
@@ -86,7 +86,6 @@ CPP = $(CC) -E $(KBUILD_CFLAGS)
CHECKFLAGS += -m$(CONFIG_WORD_SIZE) -D__powerpc__ -D__powerpc$(CONFIG_WORD_SIZE)__
-KBUILD_LDFLAGS_MODULE += arch/powerpc/lib/crtsavres.o
# No AltiVec or VSX instructions when building kernel
KBUILD_CFLAGS += $(call cc-option,-mno-altivec)

View file

@ -1,10 +0,0 @@
--- a/drivers/crypto/amcc/crypto4xx_core.c
+++ b/drivers/crypto/amcc/crypto4xx_core.c
@@ -19,6 +19,7 @@
*/
#include <linux/kernel.h>
+#include <linux/module.h>
#include <linux/interrupt.h>
#include <linux/spinlock_types.h>
#include <linux/random.h>

View file

@ -1,616 +0,0 @@
From eee16330c9de9adf7880cce9f1d32e13f89706bb Mon Sep 17 00:00:00 2001
From: Wu Zhangjin <wuzhangjin@gmail.com>
Date: Tue, 11 Jan 2011 13:16:47 +0000
Subject: MIPS: Add crash and kdump support
From: http://patchwork.linux-mips.org/patch/1025/
Hello folks,
Please find here MIPS crash and kdump patches.
This is patch set of 3 patches:
1. generic MIPS changes (kernel);
2. MIPS Cavium Octeon board kexec/kdump code (kernel);
3. Kexec user space MIPS changes.
Patches were tested on the latest linux-mips@ git kernel and the latest
kexec-tools git on Cavium Octeon 50xx board.
I also made the same code working on RMI XLR/XLS boards for both
mips32 and mips64 kernels.
Best regards,
Maxim Uvarov.
------
[ Zhangjin: Several trivial building failure has been fixed.
Note: the 2nd patch can not be cleanly applied, but may be a good
reference for the other board development:
+ MIPS Cavium Octeon board kexec,kdump support
http://patchwork.linux-mips.org/patch/1026/
And the 3rd patch has already been merged into the mainline kexec-tools:
+ some kexec MIPS improvements
http://patchwork.linux-mips.org/patch/1027/
kexec-tools is available here:
+ http://horms.net/projects/kexec/
git://git.kernel.org/pub/scm/utils/kernel/kexec/kexec-tools.git
]
Signed-off-by: Wu Zhangjin <wuzhangjin@gmail.com>
---
(limited to 'arch/mips/kernel')
--- a/arch/mips/kernel/Makefile
+++ b/arch/mips/kernel/Makefile
@@ -97,7 +97,8 @@ obj-$(CONFIG_I8253) += i8253.o
obj-$(CONFIG_GPIO_TXX9) += gpio_txx9.o
-obj-$(CONFIG_KEXEC) += machine_kexec.o relocate_kernel.o
+obj-$(CONFIG_KEXEC) += machine_kexec.o relocate_kernel.o crash.o
+obj-$(CONFIG_CRASH_DUMP) += crash_dump.o
obj-$(CONFIG_EARLY_PRINTK) += early_printk.o
obj-$(CONFIG_SPINLOCK_TEST) += spinlock_test.o
obj-$(CONFIG_MIPS_MACHINE) += mips_machine.o
--- /dev/null
+++ b/arch/mips/kernel/crash.c
@@ -0,0 +1,75 @@
+#include <linux/kernel.h>
+#include <linux/smp.h>
+#include <linux/reboot.h>
+#include <linux/kexec.h>
+#include <linux/bootmem.h>
+#include <linux/crash_dump.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/irq.h>
+#include <linux/types.h>
+#include <linux/sched.h>
+
+#ifdef CONFIG_CRASH_DUMP
+unsigned long long elfcorehdr_addr = ELFCORE_ADDR_MAX;
+#endif
+
+/* This keeps a track of which one is crashing cpu. */
+int crashing_cpu = -1;
+static cpumask_t cpus_in_crash = CPU_MASK_NONE;
+
+#ifdef CONFIG_SMP
+void crash_shutdown_secondary(void *ignore)
+{
+ struct pt_regs *regs;
+ int cpu = smp_processor_id();
+
+ regs = task_pt_regs(current);
+
+ if (!cpu_online(cpu))
+ return;
+
+ local_irq_disable();
+ if (!cpu_isset(cpu, cpus_in_crash))
+ crash_save_cpu(regs, cpu);
+ cpu_set(cpu, cpus_in_crash);
+
+ while (!atomic_read(&kexec_ready_to_reboot))
+ cpu_relax();
+ relocated_kexec_smp_wait(NULL);
+ /* NOTREACHED */
+}
+
+static void crash_kexec_prepare_cpus(void)
+{
+ unsigned int msecs;
+
+ unsigned int ncpus = num_online_cpus() - 1;/* Excluding the panic cpu */
+
+ dump_send_ipi(crash_shutdown_secondary);
+ smp_wmb();
+
+ /*
+ * The crash CPU sends an IPI and wait for other CPUs to
+ * respond. Delay of at least 10 seconds.
+ */
+ printk(KERN_EMERG "Sending IPI to other cpus...\n");
+ msecs = 10000;
+ while ((cpus_weight(cpus_in_crash) < ncpus) && (--msecs > 0)) {
+ cpu_relax();
+ mdelay(1);
+ }
+}
+
+#else
+static void crash_kexec_prepare_cpus(void) {}
+#endif
+
+void default_machine_crash_shutdown(struct pt_regs *regs)
+{
+ local_irq_disable();
+ crashing_cpu = smp_processor_id();
+ crash_save_cpu(regs, crashing_cpu);
+ crash_kexec_prepare_cpus();
+ cpu_set(crashing_cpu, cpus_in_crash);
+}
--- /dev/null
+++ b/arch/mips/kernel/crash_dump.c
@@ -0,0 +1,86 @@
+#include <linux/highmem.h>
+#include <linux/bootmem.h>
+#include <linux/crash_dump.h>
+#include <asm/uaccess.h>
+
+#ifdef CONFIG_PROC_VMCORE
+static int __init parse_elfcorehdr(char *p)
+{
+ if (p)
+ elfcorehdr_addr = memparse(p, &p);
+ return 1;
+}
+__setup("elfcorehdr=", parse_elfcorehdr);
+#endif
+
+static int __init parse_savemaxmem(char *p)
+{
+ if (p)
+ saved_max_pfn = (memparse(p, &p) >> PAGE_SHIFT) - 1;
+
+ return 1;
+}
+__setup("savemaxmem=", parse_savemaxmem);
+
+
+static void *kdump_buf_page;
+
+/**
+ * copy_oldmem_page - copy one page from "oldmem"
+ * @pfn: page frame number to be copied
+ * @buf: target memory address for the copy; this can be in kernel address
+ * space or user address space (see @userbuf)
+ * @csize: number of bytes to copy
+ * @offset: offset in bytes into the page (based on pfn) to begin the copy
+ * @userbuf: if set, @buf is in user address space, use copy_to_user(),
+ * otherwise @buf is in kernel address space, use memcpy().
+ *
+ * Copy a page from "oldmem". For this page, there is no pte mapped
+ * in the current kernel.
+ *
+ * Calling copy_to_user() in atomic context is not desirable. Hence first
+ * copying the data to a pre-allocated kernel page and then copying to user
+ * space in non-atomic context.
+ */
+ssize_t copy_oldmem_page(unsigned long pfn, char *buf,
+ size_t csize, unsigned long offset, int userbuf)
+{
+ void *vaddr;
+
+ if (!csize)
+ return 0;
+
+ vaddr = kmap_atomic_pfn(pfn, KM_PTE0);
+
+ if (!userbuf) {
+ memcpy(buf, (vaddr + offset), csize);
+ kunmap_atomic(vaddr, KM_PTE0);
+ } else {
+ if (!kdump_buf_page) {
+ printk(KERN_WARNING "Kdump: Kdump buffer page not"
+ " allocated\n");
+ return -EFAULT;
+ }
+ copy_page(kdump_buf_page, vaddr);
+ kunmap_atomic(vaddr, KM_PTE0);
+ if (copy_to_user(buf, (kdump_buf_page + offset), csize))
+ return -EFAULT;
+ }
+
+ return csize;
+}
+
+static int __init kdump_buf_page_init(void)
+{
+ int ret = 0;
+
+ kdump_buf_page = kmalloc(PAGE_SIZE, GFP_KERNEL);
+ if (!kdump_buf_page) {
+ printk(KERN_WARNING "Kdump: Failed to allocate kdump buffer"
+ " page\n");
+ ret = -ENOMEM;
+ }
+
+ return ret;
+}
+arch_initcall(kdump_buf_page_init);
--- a/arch/mips/kernel/machine_kexec.c
+++ b/arch/mips/kernel/machine_kexec.c
@@ -19,9 +19,19 @@ extern const size_t relocate_new_kernel_
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;
+#ifdef CONFIG_SMP
+void (*relocated_kexec_smp_wait) (void *);
+atomic_t kexec_ready_to_reboot = ATOMIC_INIT(0);
+#endif
+
int
machine_kexec_prepare(struct kimage *kimage)
{
+ if (_machine_kexec_prepare)
+ return _machine_kexec_prepare(kimage);
return 0;
}
@@ -33,11 +43,17 @@ machine_kexec_cleanup(struct kimage *kim
void
machine_shutdown(void)
{
+ if (_machine_kexec_shutdown)
+ _machine_kexec_shutdown();
}
void
machine_crash_shutdown(struct pt_regs *regs)
{
+ if (_machine_crash_shutdown)
+ _machine_crash_shutdown(regs);
+ else
+ default_machine_crash_shutdown(regs);
}
typedef void (*noretfun_t)(void) __attribute__((noreturn));
@@ -52,7 +68,9 @@ machine_kexec(struct kimage *image)
reboot_code_buffer =
(unsigned long)page_address(image->control_code_page);
- kexec_start_address = (unsigned long) phys_to_virt(image->start);
+ kexec_start_address =
+ (unsigned long) phys_to_virt(image->start);
+
kexec_indirection_page =
(unsigned long) phys_to_virt(image->head & PAGE_MASK);
@@ -63,7 +81,7 @@ machine_kexec(struct kimage *image)
* The generic kexec code builds a page list with physical
* addresses. they are directly accessible through KSEG0 (or
* CKSEG0 or XPHYS if on 64bit system), hence the
- * pys_to_virt() call.
+ * phys_to_virt() call.
*/
for (ptr = &image->head; (entry = *ptr) && !(entry &IND_DONE);
ptr = (entry & IND_INDIRECTION) ?
@@ -81,5 +99,13 @@ machine_kexec(struct kimage *image)
printk("Will call new kernel at %08lx\n", image->start);
printk("Bye ...\n");
__flush_cache_all();
+#ifdef CONFIG_SMP
+ /* All secondary cpus now may jump to kexec_wait cycle */
+ relocated_kexec_smp_wait = reboot_code_buffer +
+ (void *)(kexec_smp_wait - relocate_new_kernel);
+ smp_wmb();
+ atomic_set(&kexec_ready_to_reboot, 1);
+#endif
((noretfun_t) reboot_code_buffer)();
}
+
--- a/arch/mips/kernel/relocate_kernel.S
+++ b/arch/mips/kernel/relocate_kernel.S
@@ -15,6 +15,11 @@
#include <asm/addrspace.h>
LEAF(relocate_new_kernel)
+ PTR_L a0, arg0
+ PTR_L a1, arg1
+ PTR_L a2, arg2
+ PTR_L a3, arg3
+
PTR_L s0, kexec_indirection_page
PTR_L s1, kexec_start_address
@@ -26,7 +31,6 @@ process_entry:
and s3, s2, 0x1
beq s3, zero, 1f
and s4, s2, ~0x1 /* store destination addr in s4 */
- move a0, s4
b process_entry
1:
@@ -60,23 +64,100 @@ copy_word:
b process_entry
done:
+#ifdef CONFIG_SMP
+ /* kexec_flag reset is signal to other CPUs what kernel
+ was moved to it's location. Note - we need relocated address
+ of kexec_flag. */
+
+ bal 1f
+ 1: move t1,ra;
+ PTR_LA t2,1b
+ PTR_LA t0,kexec_flag
+ PTR_SUB t0,t0,t2;
+ PTR_ADD t0,t1,t0;
+ LONG_S zero,(t0)
+#endif
+
+ sync
/* jump to kexec_start_address */
j s1
END(relocate_new_kernel)
-kexec_start_address:
- EXPORT(kexec_start_address)
+#ifdef CONFIG_SMP
+/*
+ * Other CPUs should wait until code is relocated and
+ * then start at entry (?) point.
+ */
+LEAF(kexec_smp_wait)
+ PTR_L a0, s_arg0
+ PTR_L a1, s_arg1
+ PTR_L a2, s_arg2
+ PTR_L a3, s_arg3
+ PTR_L s1, kexec_start_address
+
+ /* Non-relocated address works for args and kexec_start_address ( old
+ * kernel is not overwritten). But we need relocated address of
+ * kexec_flag.
+ */
+
+ bal 1f
+1: move t1,ra;
+ PTR_LA t2,1b
+ PTR_LA t0,kexec_flag
+ PTR_SUB t0,t0,t2;
+ PTR_ADD t0,t1,t0;
+
+1: LONG_L s0, (t0)
+ bne s0, zero,1b
+
+ sync
+ j s1
+ END(kexec_smp_wait)
+#endif
+
+#ifdef __mips64
+ /* all PTR's must be aligned to 8 byte in 64-bit mode */
+ .align 3
+#endif
+
+/* All parameters to new kernel are passed in registers a0-a3.
+ * kexec_args[0..3] are uses to prepare register values.
+ */
+
+EXPORT(kexec_args)
+arg0: PTR 0x0
+arg1: PTR 0x0
+arg2: PTR 0x0
+arg3: PTR 0x0
+ .size kexec_args,PTRSIZE*4
+
+#ifdef CONFIG_SMP
+/*
+ * Secondary CPUs may have different kernel parameters in
+ * their registers a0-a3. secondary_kexec_args[0..3] are used
+ * to prepare register values.
+ */
+EXPORT(secondary_kexec_args)
+s_arg0: PTR 0x0
+s_arg1: PTR 0x0
+s_arg2: PTR 0x0
+s_arg3: PTR 0x0
+ .size secondary_kexec_args,PTRSIZE*4
+kexec_flag:
+ LONG 0x1
+
+#endif
+
+EXPORT(kexec_start_address)
PTR 0x0
.size kexec_start_address, PTRSIZE
-kexec_indirection_page:
- EXPORT(kexec_indirection_page)
+EXPORT(kexec_indirection_page)
PTR 0
.size kexec_indirection_page, PTRSIZE
relocate_new_kernel_end:
-relocate_new_kernel_size:
- EXPORT(relocate_new_kernel_size)
+EXPORT(relocate_new_kernel_size)
PTR relocate_new_kernel_end - relocate_new_kernel
.size relocate_new_kernel_size, PTRSIZE
--- a/arch/mips/kernel/setup.c
+++ b/arch/mips/kernel/setup.c
@@ -22,6 +22,7 @@
#include <linux/console.h>
#include <linux/pfn.h>
#include <linux/debugfs.h>
+#include <linux/kexec.h>
#include <asm/addrspace.h>
#include <asm/bootinfo.h>
@@ -522,12 +523,62 @@ static void __init arch_mem_init(char **
}
bootmem_init();
+#ifdef CONFIG_KEXEC
+ if (crashk_res.start != crashk_res.end)
+ reserve_bootmem(crashk_res.start,
+ crashk_res.end - crashk_res.start + 1,
+ BOOTMEM_DEFAULT);
+#endif
device_tree_init();
sparse_init();
plat_swiotlb_setup();
paging_init();
}
+#ifdef CONFIG_KEXEC
+static inline unsigned long long get_total_mem(void)
+{
+ unsigned long long total;
+ total = max_pfn - min_low_pfn;
+ return total << PAGE_SHIFT;
+}
+
+static void __init mips_parse_crashkernel(void)
+{
+ unsigned long long total_mem;
+ unsigned long long crash_size, crash_base;
+ int ret;
+
+ total_mem = get_total_mem();
+ ret = parse_crashkernel(boot_command_line, total_mem,
+ &crash_size, &crash_base);
+ if (ret != 0 || crash_size <= 0)
+ return;
+
+ crashk_res.start = crash_base;
+ crashk_res.end = crash_base + crash_size - 1;
+}
+static void __init request_crashkernel(struct resource *res)
+{
+ int ret;
+
+ ret = request_resource(res, &crashk_res);
+ if (!ret)
+ printk(KERN_INFO "Reserving %ldMB of memory at %ldMB "
+ "for crashkernel\n",
+ (unsigned long)((crashk_res.end -
+ crashk_res.start + 1) >> 20),
+ (unsigned long)(crashk_res.start >> 20));
+}
+#else
+static void __init mips_parse_crashkernel(void)
+{
+}
+static void __init request_crashkernel(struct resource *res)
+{
+}
+#endif
+
static void __init resource_init(void)
{
int i;
@@ -543,6 +594,8 @@ static void __init resource_init(void)
/*
* Request address space for all standard RAM.
*/
+ mips_parse_crashkernel();
+
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)
*/
request_resource(res, &code_resource);
request_resource(res, &data_resource);
+ request_crashkernel(res);
}
}
--- a/arch/mips/kernel/smp.c
+++ b/arch/mips/kernel/smp.c
@@ -386,3 +386,21 @@ void flush_tlb_one(unsigned long vaddr)
EXPORT_SYMBOL(flush_tlb_page);
EXPORT_SYMBOL(flush_tlb_one);
+
+#if defined(CONFIG_KEXEC)
+void (*dump_ipi_function_ptr)(void *) = NULL;
+void dump_send_ipi(void (*dump_ipi_callback)(void *))
+{
+ int i;
+ int cpu = smp_processor_id();
+
+ dump_ipi_function_ptr = dump_ipi_callback;
+ smp_mb();
+ for_each_online_cpu(i)
+ if (i != cpu)
+ core_send_ipi(i, SMP_DUMP);
+
+}
+EXPORT_SYMBOL(dump_send_ipi);
+#endif
+
--- a/arch/mips/include/asm/kexec.h
+++ b/arch/mips/include/asm/kexec.h
@@ -9,22 +9,45 @@
#ifndef _MIPS_KEXEC
# define _MIPS_KEXEC
+#include <asm/stacktrace.h>
+
+extern unsigned long long elfcorehdr_addr;
+
/* Maximum physical address we can use pages from */
#define KEXEC_SOURCE_MEMORY_LIMIT (0x20000000)
/* Maximum address we can reach in physical address mode */
#define KEXEC_DESTINATION_MEMORY_LIMIT (0x20000000)
/* Maximum address we can use for the control code buffer */
#define KEXEC_CONTROL_MEMORY_LIMIT (0x20000000)
-
-#define KEXEC_CONTROL_PAGE_SIZE 4096
+/* Reserve 3*4096 bytes for board-specific info */
+#define KEXEC_CONTROL_PAGE_SIZE (4096 + 3*4096)
/* The native architecture */
#define KEXEC_ARCH KEXEC_ARCH_MIPS
+#define MAX_NOTE_BYTES 1024
static inline void crash_setup_regs(struct pt_regs *newregs,
- struct pt_regs *oldregs)
+ struct pt_regs *oldregs)
{
- /* Dummy implementation for now */
+ if (oldregs)
+ memcpy(newregs, oldregs, sizeof(*newregs));
+ else
+ prepare_frametrace(newregs);
}
+#ifdef CONFIG_KEXEC
+struct kimage;
+extern unsigned long kexec_args[4];
+extern int (*_machine_kexec_prepare)(struct kimage *);
+extern void (*_machine_kexec_shutdown)(void);
+extern void (*_machine_crash_shutdown)(struct pt_regs *regs);
+extern void default_machine_crash_shutdown(struct pt_regs *regs);
+#ifdef CONFIG_SMP
+extern const unsigned char kexec_smp_wait[];
+extern unsigned long secondary_kexec_args[4];
+extern void (*relocated_kexec_smp_wait) (void *);
+extern atomic_t kexec_ready_to_reboot;
+#endif
+#endif
+
#endif /* !_MIPS_KEXEC */
--- a/arch/mips/include/asm/smp.h
+++ b/arch/mips/include/asm/smp.h
@@ -40,6 +40,8 @@ extern int __cpu_logical_map[NR_CPUS];
#define SMP_CALL_FUNCTION 0x2
/* Octeon - Tell another core to flush its icache */
#define SMP_ICACHE_FLUSH 0x4
+/* Used by kexec crashdump to save all cpu's state */
+#define SMP_DUMP 0x8
extern volatile cpumask_t cpu_callin_map;
@@ -91,4 +93,9 @@ static inline void arch_send_call_functi
mp_ops->send_ipi_mask(mask, SMP_CALL_FUNCTION);
}
+extern void core_send_ipi(int cpu, unsigned int action);
+#if defined(CONFIG_KEXEC)
+extern void (*dump_ipi_function_ptr)(void *);
+void dump_send_ipi(void (*dump_ipi_callback)(void *));
+#endif
#endif /* __ASM_SMP_H */

View file

@ -1,157 +0,0 @@
From 03cd81fbca6b91317ec1a7b3b3c09fb8d08f83a6 Mon Sep 17 00:00:00 2001
From: Wu Zhangjin <wuzhangjin@gmail.com>
Date: Tue, 11 Jan 2011 18:42:08 +0000
Subject: MIPS: Kexec: Enhance the support
Changes:
o Print more information in machine_kexec() for debugging
E.g. with this information, the kexec_start_address has been found
it was wrong with 64bit kernel / o32 kexec-tools. Which must be
fixed later.
o Link relocate_kernel.S to a section for future extension
This allows more functions can be added for the kexec relocation
part even written in C. to add code into that section, you just need
to mark your function or data with __kexec or
__attribute__((__section__(".__kexec.relocate")))
TODO:
1. Make 64bit kernel / o32|n32|64 kexec-tools works
Fix the user-space kexec-tools, seems the tool only work for 32bit
machine. So, we need to add 64bit support for it. The address of the
entry point(kexec_start_address) is wrong and make the "kexec -e" fail.
the real entry point must be read from the new kernel image by the
user-space kexec-tools, otherwise, it will not work. The above 64bit
support tested is 64bit kernel with o32 user-space kexec-tools. The root
cause may be the different definition of virt_to_phys() and
phys_to_virt() in the kexec-tools and kernel space for 64bit system /
o32 kernel.
Ref: http://www.linux-mips.org/archives/linux-mips/2009-08/msg00149.html
2. Pass the arguments from kexec-tools to the new kernel image
Please refer to: "MIPS: Loongson: Kexec: Pass parameters to new kernel"
Signed-off-by: Wu Zhangjin <wuzhangjin@gmail.com>
---
--- a/arch/mips/include/asm/kexec.h
+++ b/arch/mips/include/asm/kexec.h
@@ -36,6 +36,16 @@ static inline void crash_setup_regs(stru
}
#ifdef CONFIG_KEXEC
+
+#define __kexec __attribute__((__section__(".__kexec.relocate")))
+
+/* The linker tells us where the relocate_new_kernel part is. */
+extern const unsigned char __start___kexec_relocate;
+extern const unsigned char __end___kexec_relocate;
+
+extern unsigned long kexec_start_address;
+extern unsigned long kexec_indirection_page;
+
struct kimage;
extern unsigned long kexec_args[4];
extern int (*_machine_kexec_prepare)(struct kimage *);
--- a/arch/mips/kernel/machine_kexec.c
+++ b/arch/mips/kernel/machine_kexec.c
@@ -14,10 +14,6 @@
#include <asm/page.h>
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;
@@ -61,21 +57,34 @@ typedef void (*noretfun_t)(void) __attri
void
machine_kexec(struct kimage *image)
{
+ unsigned long kexec_relocate_size;
unsigned long reboot_code_buffer;
unsigned long entry;
unsigned long *ptr;
+ kexec_relocate_size = (unsigned long)(&__end___kexec_relocate) -
+ (unsigned long)(&__start___kexec_relocate);
+ pr_info("kexec_relocate_size = %lu\n", kexec_relocate_size);
+
reboot_code_buffer =
(unsigned long)page_address(image->control_code_page);
+ pr_info("reboot_code_buffer = %p\n", (void *)reboot_code_buffer);
kexec_start_address =
(unsigned long) phys_to_virt(image->start);
+ pr_info("kexec_start_address(entry point of new kernel) = %p\n",
+ (void *)kexec_start_address);
kexec_indirection_page =
(unsigned long) phys_to_virt(image->head & PAGE_MASK);
+ pr_info("kexec_indirection_page = %p\n",
+ (void *)kexec_indirection_page);
- memcpy((void*)reboot_code_buffer, relocate_new_kernel,
- relocate_new_kernel_size);
+ memcpy((void *)reboot_code_buffer, &__start___kexec_relocate,
+ kexec_relocate_size);
+
+ pr_info("Copy kexec_relocate section from %p to reboot_code_buffer: %p\n",
+ &__start___kexec_relocate, (void *)reboot_code_buffer);
/*
* The generic kexec code builds a page list with physical
@@ -96,8 +105,8 @@ machine_kexec(struct kimage *image)
*/
local_irq_disable();
- printk("Will call new kernel at %08lx\n", image->start);
- printk("Bye ...\n");
+ pr_info("Will call new kernel at %p\n", (void *)kexec_start_address);
+ pr_info("Bye ...\n");
__flush_cache_all();
#ifdef CONFIG_SMP
/* All secondary cpus now may jump to kexec_wait cycle */
@@ -108,4 +117,3 @@ machine_kexec(struct kimage *image)
#endif
((noretfun_t) reboot_code_buffer)();
}
-
--- a/arch/mips/kernel/relocate_kernel.S
+++ b/arch/mips/kernel/relocate_kernel.S
@@ -14,6 +14,8 @@
#include <asm/stackframe.h>
#include <asm/addrspace.h>
+ .section .kexec.relocate, "ax"
+
LEAF(relocate_new_kernel)
PTR_L a0, arg0
PTR_L a1, arg1
@@ -155,9 +157,3 @@ EXPORT(kexec_start_address)
EXPORT(kexec_indirection_page)
PTR 0
.size kexec_indirection_page, PTRSIZE
-
-relocate_new_kernel_end:
-
-EXPORT(relocate_new_kernel_size)
- PTR relocate_new_kernel_end - relocate_new_kernel
- .size relocate_new_kernel_size, PTRSIZE
--- a/arch/mips/kernel/vmlinux.lds.S
+++ b/arch/mips/kernel/vmlinux.lds.S
@@ -51,6 +51,10 @@ SECTIONS
*(.text.*)
*(.fixup)
*(.gnu.warning)
+ __start___kexec_relocate = .;
+ KEEP(*(.kexec.relocate))
+ KEEP(*(.__kexec.relocate))
+ __end___kexec_relocate = .;
} :text = 0
_etext = .; /* End of text section */

View file

@ -1,52 +0,0 @@
From 49d07a29653b1f2c6ae273b3d8fe93d981f43004 Mon Sep 17 00:00:00 2001
From: Wu Zhangjin <wuzhangjin@gmail.com>
Date: Wed, 12 Jan 2011 20:59:32 +0000
Subject: MIPS: Kexec: Init the arguments for the new kernel image
Whenever the kexec-tools pass the command lines to the new kernel image,
init the arguments as the ones for the 1st kernel image. This fixed the
booting failure of Kexec on YeeLoong.
Signed-off-by: Wu Zhangjin <wuzhangjin@gmail.com>
---
--- a/arch/mips/kernel/machine_kexec.c
+++ b/arch/mips/kernel/machine_kexec.c
@@ -10,6 +10,7 @@
#include <linux/mm.h>
#include <linux/delay.h>
+#include <asm/bootinfo.h>
#include <asm/cacheflush.h>
#include <asm/page.h>
@@ -23,9 +24,30 @@ void (*relocated_kexec_smp_wait) (void *
atomic_t kexec_ready_to_reboot = ATOMIC_INIT(0);
#endif
+static void machine_kexec_init_args(void)
+{
+ kexec_args[0] = fw_arg0;
+ kexec_args[1] = fw_arg1;
+ kexec_args[2] = fw_arg2;
+ kexec_args[3] = fw_arg3;
+
+ pr_info("kexec_args[0] (argc): %lu\n", kexec_args[0]);
+ pr_info("kexec_args[1] (argv): %p\n", (void *)kexec_args[1]);
+ pr_info("kexec_args[2] (env ): %p\n", (void *)kexec_args[2]);
+ pr_info("kexec_args[3] (desc): %p\n", (void *)kexec_args[3]);
+}
+
int
machine_kexec_prepare(struct kimage *kimage)
{
+ /*
+ * Whenever arguments passed from kexec-tools, Init the arguments as
+ * the original ones to avoid booting failure.
+ *
+ * This can be overrided by _machine_kexec_prepare().
+ */
+ machine_kexec_init_args();
+
if (_machine_kexec_prepare)
return _machine_kexec_prepare(kimage);
return 0;

View file

@ -1,88 +0,0 @@
From 240c76841b26f1b09aaced33414ee1d08b6454cf Mon Sep 17 00:00:00 2001
From: Wu Zhangjin <wuzhangjin@gmail.com>
Date: Sat, 15 Jan 2011 12:46:03 +0000
Subject: MIPS: Get kernel parameters from kexec-tools
Before, we simply use the command lines from the original bootloader,
but it is not convenient. Now, we accept the kernel parameters from the
--command-line or --append option of the kexec-tools. But If not
--command-line or --apend option indicated, will fall back to use the
ones from the original bootloader.
Signed-off-by: Wu Zhangjin <wuzhangjin@gmail.com>
---
--- a/arch/mips/kernel/machine_kexec.c
+++ b/arch/mips/kernel/machine_kexec.c
@@ -13,6 +13,7 @@
#include <asm/bootinfo.h>
#include <asm/cacheflush.h>
#include <asm/page.h>
+#include <asm/uaccess.h>
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]);
}
+#define ARGV_MAX_ARGS (COMMAND_LINE_SIZE / 15)
+
+int machine_kexec_pass_args(struct kimage *image)
+{
+ int i, argc = 0;
+ char *bootloader = "kexec";
+ int *kexec_argv = (int *)kexec_args[1];
+
+ for (i = 0; i < image->nr_segments; i++) {
+ if (!strncmp(bootloader, (char *)image->segment[i].buf,
+ strlen(bootloader))) {
+ /*
+ * convert command line string to array
+ * of parameters (as bootloader does).
+ */
+ /*
+ * Note: we do treat the 1st string "kexec" as an
+ * argument ;-) so, argc here is 1.
+ */
+ char *str = (char *)image->segment[i].buf;
+ char *ptr = strchr(str, ' ');
+ char *kbuf = (char *)kexec_argv[0];
+ /* Whenever --command-line or --append used, "kexec" is copied */
+ argc = 1;
+ /* Parse the offset */
+ while (ptr && (ARGV_MAX_ARGS > argc)) {
+ *ptr = '\0';
+ if (ptr[1] != ' ' && ptr[1] != '\0') {
+ int offt = (int)(ptr - str + 1);
+ kexec_argv[argc] = (int)kbuf + offt;
+ argc++;
+ }
+ ptr = strchr(ptr + 1, ' ');
+ }
+ if (argc > 1) {
+ /* Copy to kernel space */
+ copy_from_user(kbuf, (char *)image->segment[i].buf, image->segment[i].bufsz);
+ fw_arg0 = kexec_args[0] = argc;
+ }
+ break;
+ }
+ }
+
+ pr_info("argc = %lu\n", kexec_args[0]);
+ for (i = 0; i < kexec_args[0]; i++)
+ pr_info("argv[%d] = %p, %s\n", i, (char *)kexec_argv[i], (char *)kexec_argv[i]);
+
+ return 0;
+}
+
int
machine_kexec_prepare(struct kimage *kimage)
{
@@ -47,6 +98,7 @@ machine_kexec_prepare(struct kimage *kim
* This can be overrided by _machine_kexec_prepare().
*/
machine_kexec_init_args();
+ machine_kexec_pass_args(kimage);
if (_machine_kexec_prepare)
return _machine_kexec_prepare(kimage);

View file

@ -1,83 +0,0 @@
From 4aded085fa0057a9a1e1dcec631f950307360c1f Mon Sep 17 00:00:00 2001
From: Wu Zhangjin <wuzhangjin@gmail.com>
Date: Tue, 11 Jan 2011 13:46:19 +0000
Subject: MIPS: Fix compiling failure of relocate_kernel.S
The following errors is fixed with the help of <asm/asm_nosec.h>. for
this file need to put different symbols in the same section, the
original LEAF, NESTED and EXPORT (without explicit section indication)
must be used, <asm/asm_nosec.h> does it.
arch/mips/kernel/relocate_kernel.S: Assembler messages:
arch/mips/kernel/relocate_kernel.S:162: Error: operation combines symbols in different segments
Signed-off-by: Wu Zhangjin <wuzhangjin@gmail.com>
---
(limited to 'arch/mips/kernel')
--- a/arch/mips/kernel/relocate_kernel.S
+++ b/arch/mips/kernel/relocate_kernel.S
@@ -7,6 +7,7 @@
*/
#include <asm/asm.h>
+#include <asm/asm_nosec.h>
#include <asm/asmmacro.h>
#include <asm/regdef.h>
#include <asm/page.h>
--- /dev/null
+++ b/arch/mips/include/asm/asm_nosec.h
@@ -0,0 +1,53 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 1995, 1996, 1997, 1999, 2001 by Ralf Baechle
+ * Copyright (C) 1999 by Silicon Graphics, Inc.
+ * Copyright (C) 2001 MIPS Technologies, Inc.
+ * Copyright (C) 2002 Maciej W. Rozycki
+ * Copyright (C) 2010 Wu Zhangjin <wuzhangjin@gmail.com>
+ *
+ * Derive from <asm/asm.h>
+ *
+ * Override the macros without -ffunction-sections and -fdata-sections support.
+ * If several functions or data must be put in the same section, please include
+ * this header file after the <asm/asm.h> to override the generic definition.
+ */
+
+#ifndef __ASM_ASM_NOSEC_H
+#define __ASM_ASM_NOSEC_H
+
+#undef LEAF
+#undef NESTED
+#undef EXPORT
+
+/*
+ * LEAF - declare leaf routine
+ */
+#define LEAF(symbol) \
+ .globl symbol; \
+ .align 2; \
+ .type symbol, @function; \
+ .ent symbol, 0; \
+symbol: .frame sp, 0, ra
+
+/*
+ * NESTED - declare nested routine entry point
+ */
+#define NESTED(symbol, framesize, rpc) \
+ .globl symbol; \
+ .align 2; \
+ .type symbol, @function; \
+ .ent symbol, 0; \
+symbol: .frame sp, framesize, rpc
+
+/*
+ * EXPORT - export definition of symbol
+ */
+#define EXPORT(symbol) \
+ .globl symbol; \
+symbol:
+
+#endif /* __ASM_ASM_NOSEC_H */

View file

@ -1,186 +0,0 @@
--- a/arch/mips/kernel/machine_kexec.c
+++ b/arch/mips/kernel/machine_kexec.c
@@ -25,67 +25,104 @@ void (*relocated_kexec_smp_wait) (void *
atomic_t kexec_ready_to_reboot = ATOMIC_INIT(0);
#endif
-static void machine_kexec_init_args(void)
+#define KEXEC_MIPS_ARGV_BUF_SIZE COMMAND_LINE_SIZE
+#define KEXEC_MIPS_ARGV_MAX_ARGS (COMMAND_LINE_SIZE / 15)
+
+char kexec_argv_buf[KEXEC_MIPS_ARGV_BUF_SIZE] __kexec;
+char *kexec_argv[KEXEC_MIPS_ARGV_MAX_ARGS] __kexec;
+
+static void
+machine_kexec_print_args(void)
{
- kexec_args[0] = fw_arg0;
- kexec_args[1] = fw_arg1;
- kexec_args[2] = fw_arg2;
- kexec_args[3] = fw_arg3;
+ int i;
pr_info("kexec_args[0] (argc): %lu\n", kexec_args[0]);
pr_info("kexec_args[1] (argv): %p\n", (void *)kexec_args[1]);
pr_info("kexec_args[2] (env ): %p\n", (void *)kexec_args[2]);
pr_info("kexec_args[3] (desc): %p\n", (void *)kexec_args[3]);
-}
-#define ARGV_MAX_ARGS (COMMAND_LINE_SIZE / 15)
+ for (i = 0; i < kexec_args[0]; i++)
+ pr_info("kexec_argv[%d] = %p, %s\n", i,
+ (char *)kexec_argv[i], (char *)kexec_argv[i]);
+}
-int machine_kexec_pass_args(struct kimage *image)
+static void
+machine_kexec_init_argv(struct kimage *image)
{
- int i, argc = 0;
- char *bootloader = "kexec";
- int *kexec_argv = (int *)kexec_args[1];
+ void __user *buf = NULL;
+ size_t bufsz;
+ size_t size;
+ int i;
+ bufsz = 0;
for (i = 0; i < image->nr_segments; i++) {
- if (!strncmp(bootloader, (char *)image->segment[i].buf,
- strlen(bootloader))) {
- /*
- * convert command line string to array
- * of parameters (as bootloader does).
- */
- /*
- * Note: we do treat the 1st string "kexec" as an
- * argument ;-) so, argc here is 1.
- */
- char *str = (char *)image->segment[i].buf;
- char *ptr = strchr(str, ' ');
- char *kbuf = (char *)kexec_argv[0];
- /* Whenever --command-line or --append used, "kexec" is copied */
- argc = 1;
- /* Parse the offset */
- while (ptr && (ARGV_MAX_ARGS > argc)) {
- *ptr = '\0';
- if (ptr[1] != ' ' && ptr[1] != '\0') {
- int offt = (int)(ptr - str + 1);
- kexec_argv[argc] = (int)kbuf + offt;
- argc++;
- }
- ptr = strchr(ptr + 1, ' ');
- }
- if (argc > 1) {
- /* Copy to kernel space */
- copy_from_user(kbuf, (char *)image->segment[i].buf, image->segment[i].bufsz);
- fw_arg0 = kexec_args[0] = argc;
- }
- break;
+ struct kexec_segment *seg;
+
+ seg = &image->segment[i];
+ if (seg->bufsz < 6)
+ continue;
+
+ if (strncmp((char *) seg->buf, "kexec", 5))
+ continue;
+
+ /* don't copy "kexec" */
+ buf = seg->buf + 5;
+ bufsz = seg->bufsz - 5;
+ break;
+ }
+
+ if (!buf)
+ return;
+
+ size = KEXEC_MIPS_ARGV_BUF_SIZE - 1;
+ size = min(size, bufsz);
+ if (size < bufsz)
+ pr_warn("kexec command line truncated to %zd bytes\n", size);
+
+ /* Copy to kernel space */
+ copy_from_user(kexec_argv_buf, buf, size);
+}
+
+static void
+machine_kexec_parse_argv(struct kimage *image)
+{
+ char *reboot_code_buffer;
+ int reloc_delta;
+ char *ptr;
+ int argc;
+ int i;
+
+ ptr = kexec_argv_buf;
+ argc = 0;
+
+ /*
+ * convert command line string to array of parameters
+ * (as bootloader does).
+ */
+ while (ptr && *ptr && (KEXEC_MIPS_ARGV_MAX_ARGS > argc)) {
+ if (*ptr == ' ') {
+ *ptr++ = '\0';
+ continue;
}
+
+ kexec_argv[argc++] = ptr;
+ ptr = strchr(ptr, ' ');
}
- pr_info("argc = %lu\n", kexec_args[0]);
- for (i = 0; i < kexec_args[0]; i++)
- pr_info("argv[%d] = %p, %s\n", i, (char *)kexec_argv[i], (char *)kexec_argv[i]);
+ if (!argc)
+ return;
- return 0;
+ kexec_args[0] = argc;
+ kexec_args[1] = (unsigned long)kexec_argv;
+ kexec_args[2] = 0;
+ kexec_args[3] = 0;
+
+ reboot_code_buffer = page_address(image->control_code_page);
+ reloc_delta = reboot_code_buffer - (char *) &__start___kexec_relocate;
+
+ kexec_args[1] += reloc_delta;
+ for (i = 0; i < argc; i++)
+ kexec_argv[i] += reloc_delta;
}
int
@@ -97,8 +134,14 @@ machine_kexec_prepare(struct kimage *kim
*
* This can be overrided by _machine_kexec_prepare().
*/
- machine_kexec_init_args();
- machine_kexec_pass_args(kimage);
+
+ kexec_args[0] = fw_arg0;
+ kexec_args[1] = fw_arg1;
+ kexec_args[2] = fw_arg2;
+ kexec_args[3] = fw_arg3;
+
+ machine_kexec_init_argv(kimage);
+ machine_kexec_parse_argv(kimage);
if (_machine_kexec_prepare)
return _machine_kexec_prepare(kimage);
@@ -154,11 +197,13 @@ machine_kexec(struct kimage *image)
pr_info("kexec_indirection_page = %p\n",
(void *)kexec_indirection_page);
+ pr_info("Copy kexec_relocate section from %p to reboot_code_buffer: %p\n",
+ &__start___kexec_relocate, (void *)reboot_code_buffer);
+
memcpy((void *)reboot_code_buffer, &__start___kexec_relocate,
kexec_relocate_size);
- pr_info("Copy kexec_relocate section from %p to reboot_code_buffer: %p\n",
- &__start___kexec_relocate, (void *)reboot_code_buffer);
+ machine_kexec_print_args();
/*
* The generic kexec code builds a page list with physical

View file

@ -1,20 +0,0 @@
--- a/kernel/module.c
+++ b/kernel/module.c
@@ -2358,12 +2358,15 @@ static void dynamic_debug_remove(struct
void * __weak module_alloc(unsigned long size)
{
- return size == 0 ? NULL : vmalloc_exec(size);
+ return vmalloc_exec(size);
}
static void *module_alloc_update_bounds(unsigned long size)
{
- void *ret = module_alloc(size);
+ void *ret = NULL;
+
+ if (size)
+ ret = module_alloc(size);
if (ret) {
mutex_lock(&module_mutex);

View file

@ -1,327 +0,0 @@
--- a/drivers/mtd/Kconfig
+++ b/drivers/mtd/Kconfig
@@ -23,6 +23,14 @@ config MTD_TESTS
WARNING: some of the tests will ERASE entire MTD device which they
test. Do not use these tests unless you really know what you do.
+config MTD_ROOTFS_ROOT_DEV
+ bool "Automatically set 'rootfs' partition to be root filesystem"
+ default y
+
+config MTD_ROOTFS_SPLIT
+ bool "Automatically split 'rootfs' partition for squashfs"
+ default y
+
config MTD_REDBOOT_PARTS
tristate "RedBoot partition table parsing"
---help---
--- a/drivers/mtd/mtdpart.c
+++ b/drivers/mtd/mtdpart.c
@@ -29,6 +29,8 @@
#include <linux/kmod.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/partitions.h>
+#include <linux/root_dev.h>
+#include <linux/magic.h>
#include <linux/err.h>
#include "mtdcore.h"
@@ -50,7 +52,7 @@ struct mtd_part {
* the pointer to that structure with this macro.
*/
#define PART(x) ((struct mtd_part *)(x))
-
+#define IS_PART(mtd) (mtd->_read == part_read)
/*
* MTD methods which simply translate the effective address and pass through
@@ -613,6 +615,155 @@ int mtd_del_partition(struct mtd_info *m
}
EXPORT_SYMBOL_GPL(mtd_del_partition);
+#ifdef CONFIG_MTD_ROOTFS_SPLIT
+#define ROOTFS_SPLIT_NAME "rootfs_data"
+#define ROOTFS_REMOVED_NAME "<removed>"
+
+struct squashfs_super_block {
+ __le32 s_magic;
+ __le32 pad0[9];
+ __le64 bytes_used;
+};
+
+
+static int split_squashfs(struct mtd_info *master, int offset, int *split_offset)
+{
+ struct squashfs_super_block sb;
+ int len, ret;
+
+ ret = mtd_read(master, offset, sizeof(sb), &len, (void *) &sb);
+ if (ret || (len != sizeof(sb))) {
+ printk(KERN_ALERT "split_squashfs: error occured while reading "
+ "from \"%s\"\n", master->name);
+ return -EINVAL;
+ }
+
+ if (SQUASHFS_MAGIC != le32_to_cpu(sb.s_magic) ) {
+ printk(KERN_ALERT "split_squashfs: no squashfs found in \"%s\"\n",
+ master->name);
+ *split_offset = 0;
+ return 0;
+ }
+
+ if (le64_to_cpu((sb.bytes_used)) <= 0) {
+ printk(KERN_ALERT "split_squashfs: squashfs is empty in \"%s\"\n",
+ master->name);
+ *split_offset = 0;
+ return 0;
+ }
+
+ len = (u32) le64_to_cpu(sb.bytes_used);
+ len += (offset & 0x000fffff);
+ len += (master->erasesize - 1);
+ len &= ~(master->erasesize - 1);
+ len -= (offset & 0x000fffff);
+ *split_offset = offset + len;
+
+ return 0;
+}
+
+static int split_rootfs_data(struct mtd_info *master, struct mtd_info *rpart, const struct mtd_partition *part)
+{
+ struct mtd_partition *dpart;
+ struct mtd_part *slave = NULL;
+ struct mtd_part *spart;
+ int ret, split_offset = 0;
+
+ spart = PART(rpart);
+ ret = split_squashfs(master, spart->offset, &split_offset);
+ if (ret)
+ return ret;
+
+ if (split_offset <= 0)
+ return 0;
+
+ dpart = kmalloc(sizeof(*part)+sizeof(ROOTFS_SPLIT_NAME)+1, GFP_KERNEL);
+ if (dpart == NULL) {
+ printk(KERN_INFO "split_squashfs: no memory for partition \"%s\"\n",
+ ROOTFS_SPLIT_NAME);
+ return -ENOMEM;
+ }
+
+ memcpy(dpart, part, sizeof(*part));
+ dpart->name = (unsigned char *)&dpart[1];
+ strcpy(dpart->name, ROOTFS_SPLIT_NAME);
+
+ dpart->size = rpart->size - (split_offset - spart->offset);
+ dpart->offset = split_offset;
+
+ if (dpart == NULL)
+ return 1;
+
+ printk(KERN_INFO "mtd: partition \"%s\" created automatically, ofs=%llX, len=%llX \n",
+ ROOTFS_SPLIT_NAME, dpart->offset, dpart->size);
+
+ slave = allocate_partition(master, dpart, 0, split_offset);
+ if (IS_ERR(slave))
+ return PTR_ERR(slave);
+ mutex_lock(&mtd_partitions_mutex);
+ list_add(&slave->list, &mtd_partitions);
+ mutex_unlock(&mtd_partitions_mutex);
+
+ add_mtd_device(&slave->mtd);
+
+ rpart->split = &slave->mtd;
+
+ return 0;
+}
+
+static int refresh_rootfs_split(struct mtd_info *mtd)
+{
+ struct mtd_partition tpart;
+ struct mtd_part *part;
+ char *name;
+ //int index = 0;
+ int offset, size;
+ int ret;
+
+ part = PART(mtd);
+
+ /* check for the new squashfs offset first */
+ ret = split_squashfs(part->master, part->offset, &offset);
+ if (ret)
+ return ret;
+
+ if ((offset > 0) && !mtd->split) {
+ printk(KERN_INFO "%s: creating new split partition for \"%s\"\n", __func__, mtd->name);
+ /* if we don't have a rootfs split partition, create a new one */
+ tpart.name = (char *) mtd->name;
+ tpart.size = mtd->size;
+ tpart.offset = part->offset;
+
+ return split_rootfs_data(part->master, &part->mtd, &tpart);
+ } else if ((offset > 0) && mtd->split) {
+ /* update the offsets of the existing partition */
+ size = mtd->size + part->offset - offset;
+
+ part = PART(mtd->split);
+ part->offset = offset;
+ part->mtd.size = size;
+ printk(KERN_INFO "%s: %s partition \"" ROOTFS_SPLIT_NAME "\", offset: 0x%06x (0x%06x)\n",
+ __func__, (!strcmp(part->mtd.name, ROOTFS_SPLIT_NAME) ? "updating" : "creating"),
+ (u32) part->offset, (u32) part->mtd.size);
+ name = kmalloc(sizeof(ROOTFS_SPLIT_NAME) + 1, GFP_KERNEL);
+ strcpy(name, ROOTFS_SPLIT_NAME);
+ part->mtd.name = name;
+ } else if ((offset <= 0) && mtd->split) {
+ printk(KERN_INFO "%s: removing partition \"%s\"\n", __func__, mtd->split->name);
+
+ /* mark existing partition as removed */
+ part = PART(mtd->split);
+ name = kmalloc(sizeof(ROOTFS_SPLIT_NAME) + 1, GFP_KERNEL);
+ strcpy(name, ROOTFS_REMOVED_NAME);
+ part->mtd.name = name;
+ part->offset = 0;
+ part->mtd.size = 0;
+ }
+
+ return 0;
+}
+#endif /* CONFIG_MTD_ROOTFS_SPLIT */
+
/*
* This function, given a master MTD object and a partition table, creates
* and registers slave MTD objects which are bound to the master according to
@@ -629,6 +780,9 @@ int add_mtd_partitions(struct mtd_info *
struct mtd_part *slave;
uint64_t cur_offset = 0;
int i;
+#ifdef CONFIG_MTD_ROOTFS_SPLIT
+ int ret;
+#endif
printk(KERN_NOTICE "Creating %d MTD partitions on \"%s\":\n", nbparts, master->name);
@@ -643,12 +797,53 @@ int add_mtd_partitions(struct mtd_info *
add_mtd_device(&slave->mtd);
+ if (!strcmp(parts[i].name, "rootfs")) {
+#ifdef CONFIG_MTD_ROOTFS_ROOT_DEV
+ if (ROOT_DEV == 0) {
+ printk(KERN_NOTICE "mtd: partition \"rootfs\" "
+ "set to be root filesystem\n");
+ ROOT_DEV = MKDEV(MTD_BLOCK_MAJOR, slave->mtd.index);
+ }
+#endif
+#ifdef CONFIG_MTD_ROOTFS_SPLIT
+ ret = split_rootfs_data(master, &slave->mtd, &parts[i]);
+ /* if (ret == 0)
+ * j++; */
+#endif
+ }
+
cur_offset = slave->offset + slave->mtd.size;
}
return 0;
}
+int mtd_device_refresh(struct mtd_info *mtd)
+{
+ int ret = 0;
+
+ if (IS_PART(mtd)) {
+ struct mtd_part *part;
+ struct mtd_info *master;
+
+ part = PART(mtd);
+ master = part->master;
+ if (master->refresh_device)
+ ret = master->refresh_device(master);
+ }
+
+ if (!ret && mtd->refresh_device)
+ ret = mtd->refresh_device(mtd);
+
+#ifdef CONFIG_MTD_ROOTFS_SPLIT
+ if (!ret && IS_PART(mtd) && !strcmp(mtd->name, "rootfs"))
+ refresh_rootfs_split(mtd);
+#endif
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(mtd_device_refresh);
+
static DEFINE_SPINLOCK(part_parser_lock);
static LIST_HEAD(part_parsers);
--- a/drivers/mtd/mtdchar.c
+++ b/drivers/mtd/mtdchar.c
@@ -1012,6 +1012,12 @@ static int mtdchar_ioctl(struct file *fi
break;
}
+ case MTDREFRESH:
+ {
+ ret = mtd_device_refresh(mtd);
+ break;
+ }
+
default:
ret = -ENOTTY;
}
--- a/include/linux/mtd/mtd.h
+++ b/include/linux/mtd/mtd.h
@@ -114,6 +114,7 @@ struct nand_ecclayout {
struct module; /* only needed for owner field in mtd_info */
+struct mtd_info;
struct mtd_info {
u_char type;
uint32_t flags;
@@ -226,6 +227,9 @@ struct mtd_info {
int (*_block_markbad) (struct mtd_info *mtd, loff_t ofs);
int (*_suspend) (struct mtd_info *mtd);
void (*_resume) (struct mtd_info *mtd);
+ int (*refresh_device)(struct mtd_info *mtd);
+ struct mtd_info *split;
+
/*
* If the driver is something smart, like UBI, it may need to maintain
* its own reference counting. The below functions are only for driver.
@@ -375,6 +379,7 @@ extern int mtd_device_parse_register(str
int defnr_parts);
#define mtd_device_register(master, parts, nr_parts) \
mtd_device_parse_register(master, NULL, NULL, parts, nr_parts)
+extern int mtd_device_refresh(struct mtd_info *master);
extern int mtd_device_unregister(struct mtd_info *master);
extern struct mtd_info *get_mtd_device(struct mtd_info *mtd, int num);
extern int __get_mtd_device(struct mtd_info *mtd);
--- a/include/linux/mtd/partitions.h
+++ b/include/linux/mtd/partitions.h
@@ -36,12 +36,14 @@
* erasesize aligned (e.g. use MTDPART_OFS_NEXTBLK).
*/
+struct mtd_partition;
struct mtd_partition {
char *name; /* identifier string */
uint64_t size; /* partition size */
uint64_t offset; /* offset within the master MTD space */
uint32_t mask_flags; /* master MTD flags to mask out for this partition */
struct nand_ecclayout *ecclayout; /* out of band layout for this partition (NAND only) */
+ int (*refresh_partition)(struct mtd_info *);
};
#define MTDPART_OFS_RETAIN (-3)
--- a/include/mtd/mtd-abi.h
+++ b/include/mtd/mtd-abi.h
@@ -202,6 +202,7 @@ struct otp_info {
* without OOB, e.g., NOR flash.
*/
#define MEMWRITE _IOWR('M', 24, struct mtd_write_req)
+#define MTDREFRESH _IO('M', 50)
/*
* Obsolete legacy interface. Keep it in order not to break userspace

View file

@ -1,146 +0,0 @@
--- a/drivers/mtd/mtdpart.c
+++ b/drivers/mtd/mtdpart.c
@@ -35,6 +35,8 @@
#include "mtdcore.h"
+#define MTD_ERASE_PARTIAL 0x8000 /* partition only covers parts of an erase block */
+
/* Our partition linked list */
static LIST_HEAD(mtd_partitions);
static DEFINE_MUTEX(mtd_partitions_mutex);
@@ -230,13 +232,61 @@ static int part_erase(struct mtd_info *m
struct mtd_part *part = PART(mtd);
int ret;
+
+ instr->partial_start = false;
+ if (mtd->flags & MTD_ERASE_PARTIAL) {
+ size_t readlen = 0;
+ u64 mtd_ofs;
+
+ instr->erase_buf = kmalloc(part->master->erasesize, GFP_ATOMIC);
+ if (!instr->erase_buf)
+ return -ENOMEM;
+
+ mtd_ofs = part->offset + instr->addr;
+ instr->erase_buf_ofs = do_div(mtd_ofs, part->master->erasesize);
+
+ if (instr->erase_buf_ofs > 0) {
+ instr->addr -= instr->erase_buf_ofs;
+ ret = mtd_read(part->master,
+ instr->addr + part->offset,
+ part->master->erasesize,
+ &readlen, instr->erase_buf);
+
+ instr->len += instr->erase_buf_ofs;
+ instr->partial_start = true;
+ } else {
+ mtd_ofs = part->offset + part->mtd.size;
+ instr->erase_buf_ofs = part->master->erasesize -
+ do_div(mtd_ofs, part->master->erasesize);
+
+ if (instr->erase_buf_ofs > 0) {
+ instr->len += instr->erase_buf_ofs;
+ ret = mtd_read(part->master,
+ part->offset + instr->addr +
+ instr->len - part->master->erasesize,
+ part->master->erasesize, &readlen,
+ instr->erase_buf);
+ } else {
+ ret = 0;
+ }
+ }
+ if (ret < 0) {
+ kfree(instr->erase_buf);
+ return ret;
+ }
+
+ }
+
instr->addr += part->offset;
ret = part->master->_erase(part->master, instr);
if (ret) {
if (instr->fail_addr != MTD_FAIL_ADDR_UNKNOWN)
instr->fail_addr -= part->offset;
instr->addr -= part->offset;
+ if (mtd->flags & MTD_ERASE_PARTIAL)
+ kfree(instr->erase_buf);
}
+
return ret;
}
@@ -244,7 +294,25 @@ void mtd_erase_callback(struct erase_inf
{
if (instr->mtd->_erase == part_erase) {
struct mtd_part *part = PART(instr->mtd);
+ size_t wrlen = 0;
+ if (instr->mtd->flags & MTD_ERASE_PARTIAL) {
+ if (instr->partial_start) {
+ part->master->_write(part->master,
+ instr->addr, instr->erase_buf_ofs,
+ &wrlen, instr->erase_buf);
+ instr->addr += instr->erase_buf_ofs;
+ } else {
+ instr->len -= instr->erase_buf_ofs;
+ part->master->_write(part->master,
+ instr->addr + instr->len,
+ instr->erase_buf_ofs, &wrlen,
+ instr->erase_buf +
+ part->master->erasesize -
+ instr->erase_buf_ofs);
+ }
+ kfree(instr->erase_buf);
+ }
if (instr->fail_addr != MTD_FAIL_ADDR_UNKNOWN)
instr->fail_addr -= part->offset;
instr->addr -= part->offset;
@@ -504,18 +572,24 @@ static struct mtd_part *allocate_partiti
if ((slave->mtd.flags & MTD_WRITEABLE) &&
mtd_mod_by_eb(slave->offset, &slave->mtd)) {
/* Doesn't start on a boundary of major erase size */
- /* FIXME: Let it be writable if it is on a boundary of
- * _minor_ erase size though */
- slave->mtd.flags &= ~MTD_WRITEABLE;
- printk(KERN_WARNING"mtd: partition \"%s\" doesn't start on an erase block boundary -- force read-only\n",
- part->name);
+ slave->mtd.flags |= MTD_ERASE_PARTIAL;
+ if (((u32) slave->mtd.size) > master->erasesize)
+ slave->mtd.flags &= ~MTD_WRITEABLE;
+ else
+ slave->mtd.erasesize = slave->mtd.size;
}
if ((slave->mtd.flags & MTD_WRITEABLE) &&
- mtd_mod_by_eb(slave->mtd.size, &slave->mtd)) {
- slave->mtd.flags &= ~MTD_WRITEABLE;
- printk(KERN_WARNING"mtd: partition \"%s\" doesn't end on an erase block -- force read-only\n",
- part->name);
+ mtd_mod_by_eb(slave->offset + slave->mtd.size, &slave->mtd)) {
+ slave->mtd.flags |= MTD_ERASE_PARTIAL;
+
+ if ((u32) slave->mtd.size > master->erasesize)
+ slave->mtd.flags &= ~MTD_WRITEABLE;
+ else
+ slave->mtd.erasesize = slave->mtd.size;
}
+ if ((slave->mtd.flags & (MTD_ERASE_PARTIAL|MTD_WRITEABLE)) == MTD_ERASE_PARTIAL)
+ printk(KERN_WARNING"mtd: partition \"%s\" must either start or end on erase block boundary or be smaller than an erase block -- forcing read-only\n",
+ part->name);
slave->mtd.ecclayout = master->ecclayout;
slave->mtd.ecc_strength = master->ecc_strength;
--- a/include/linux/mtd/mtd.h
+++ b/include/linux/mtd/mtd.h
@@ -58,6 +58,10 @@ struct erase_info {
u_long priv;
u_char state;
struct erase_info *next;
+
+ u8 *erase_buf;
+ u32 erase_buf_ofs;
+ bool partial_start;
};
struct mtd_erase_region_info {

View file

@ -1,18 +0,0 @@
--- a/include/linux/mtd/partitions.h
+++ b/include/linux/mtd/partitions.h
@@ -35,6 +35,7 @@
* Note: writeable partitions require their size and offset be
* erasesize aligned (e.g. use MTDPART_OFS_NEXTBLK).
*/
+struct mtd_info;
struct mtd_partition;
struct mtd_partition {
@@ -52,7 +53,6 @@ struct mtd_partition {
#define MTDPART_SIZ_FULL (0)
-struct mtd_info;
struct device_node;
/**

View file

@ -1,30 +0,0 @@
--- a/drivers/mtd/redboot.c
+++ b/drivers/mtd/redboot.c
@@ -265,14 +265,21 @@ static int parse_redboot_partitions(stru
#endif
names += strlen(names)+1;
-#ifdef CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED
if(fl->next && fl->img->flash_base + fl->img->size + master->erasesize <= fl->next->img->flash_base) {
- i++;
- parts[i].offset = parts[i-1].size + parts[i-1].offset;
- parts[i].size = fl->next->img->flash_base - parts[i].offset;
- parts[i].name = nullname;
- }
+ if (!strcmp(parts[i].name, "rootfs")) {
+ parts[i].size = fl->next->img->flash_base;
+ parts[i].size &= ~(master->erasesize - 1);
+ parts[i].size -= parts[i].offset;
+#ifdef CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED
+ nrparts--;
+ } else {
+ i++;
+ parts[i].offset = parts[i-1].size + parts[i-1].offset;
+ parts[i].size = fl->next->img->flash_base - parts[i].offset;
+ parts[i].name = nullname;
#endif
+ }
+ }
tmp_fl = fl;
fl = fl->next;
kfree(tmp_fl);

View file

@ -1,35 +0,0 @@
--- a/drivers/mtd/Kconfig
+++ b/drivers/mtd/Kconfig
@@ -156,6 +156,22 @@ config MTD_BCM63XX_PARTS
This provides partions parsing for BCM63xx devices with CFE
bootloaders.
+config MTD_MYLOADER_PARTS
+ tristate "MyLoader partition parsing"
+ depends on ADM5120 || ATHEROS_AR231X || ATHEROS_AR71XX || ATH79
+ ---help---
+ MyLoader is a bootloader which allows the user to define partitions
+ in flash devices, by putting a table in the second erase block
+ on the device, similar to a partition table. This table gives the
+ offsets and lengths of the user defined partitions.
+
+ If you need code which can detect and parse these tables, and
+ register MTD 'partitions' corresponding to each image detected,
+ enable this option.
+
+ You will still need the parsing functions to be called by the driver
+ for your particular device. It won't happen automatically.
+
comment "User Modules And Translation Layers"
config MTD_CHAR
--- a/drivers/mtd/Makefile
+++ b/drivers/mtd/Makefile
@@ -12,6 +12,7 @@ obj-$(CONFIG_MTD_CMDLINE_PARTS) += cmdli
obj-$(CONFIG_MTD_AFS_PARTS) += afs.o
obj-$(CONFIG_MTD_AR7_PARTS) += ar7part.o
obj-$(CONFIG_MTD_BCM63XX_PARTS) += bcm63xxpart.o
+obj-$(CONFIG_MTD_MYLOADER_PARTS) += myloader.o
# 'Users' - code which presents functionality to userspace.
obj-$(CONFIG_MTD_CHAR) += mtdchar.o

View file

@ -1,116 +0,0 @@
--- a/drivers/mtd/devices/block2mtd.c
+++ b/drivers/mtd/devices/block2mtd.c
@@ -14,6 +14,7 @@
#include <linux/list.h>
#include <linux/init.h>
#include <linux/mtd/mtd.h>
+#include <linux/mtd/partitions.h>
#include <linux/mutex.h>
#include <linux/mount.h>
#include <linux/slab.h>
@@ -208,11 +209,12 @@ static void block2mtd_free_device(struct
/* FIXME: ensure that mtd->size % erase_size == 0 */
-static struct block2mtd_dev *add_device(char *devname, int erase_size)
+static struct block2mtd_dev *add_device(char *devname, int erase_size, const char *mtdname)
{
const fmode_t mode = FMODE_READ | FMODE_WRITE | FMODE_EXCL;
struct block_device *bdev;
struct block2mtd_dev *dev;
+ struct mtd_partition *part;
char *name;
if (!devname)
@@ -251,13 +253,16 @@ static struct block2mtd_dev *add_device(
/* Setup the MTD structure */
/* make the name contain the block device in */
- name = kasprintf(GFP_KERNEL, "block2mtd: %s", devname);
+ if (!mtdname)
+ mtdname = devname;
+ name = kmalloc(strlen(mtdname) + 1, GFP_KERNEL);
if (!name)
goto devinit_err;
+ strcpy(name, mtdname);
dev->mtd.name = name;
- dev->mtd.size = dev->blkdev->bd_inode->i_size & PAGE_MASK;
+ dev->mtd.size = dev->blkdev->bd_inode->i_size & PAGE_MASK & ~(erase_size - 1);
dev->mtd.erasesize = erase_size;
dev->mtd.writesize = 1;
dev->mtd.writebufsize = PAGE_SIZE;
@@ -270,14 +275,17 @@ static struct block2mtd_dev *add_device(
dev->mtd.priv = dev;
dev->mtd.owner = THIS_MODULE;
- if (mtd_device_register(&dev->mtd, NULL, 0)) {
+ part = kzalloc(sizeof(struct mtd_partition), GFP_KERNEL);
+ part->name = name;
+ part->offset = 0;
+ part->size = dev->mtd.size;
+ if (mtd_device_register(&dev->mtd, part, 1)) {
/* Device didn't get added, so free the entry */
goto devinit_err;
}
list_add(&dev->list, &blkmtd_device_list);
INFO("mtd%d: [%s] erase_size = %dKiB [%d]", dev->mtd.index,
- dev->mtd.name + strlen("block2mtd: "),
- dev->mtd.erasesize >> 10, dev->mtd.erasesize);
+ mtdname, dev->mtd.erasesize >> 10, dev->mtd.erasesize);
return dev;
devinit_err:
@@ -350,9 +358,9 @@ static char block2mtd_paramline[80 + 12]
static int block2mtd_setup2(const char *val)
{
- char buf[80 + 12]; /* 80 for device, 12 for erase size */
+ char buf[80 + 12 + 80]; /* 80 for device, 12 for erase size, 80 for name */
char *str = buf;
- char *token[2];
+ char *token[3];
char *name;
size_t erase_size = PAGE_SIZE;
int i, ret;
@@ -363,7 +371,7 @@ static int block2mtd_setup2(const char *
strcpy(str, val);
kill_final_newline(str);
- for (i = 0; i < 2; i++)
+ for (i = 0; i < 3; i++)
token[i] = strsep(&str, ",");
if (str)
@@ -382,8 +390,10 @@ static int block2mtd_setup2(const char *
parse_err("illegal erase size");
}
}
+ if (token[2] && (strlen(token[2]) + 1 > 80))
+ parse_err("mtd device name too long");
- add_device(name, erase_size);
+ add_device(name, erase_size, token[2]);
return 0;
}
@@ -417,7 +427,7 @@ static int block2mtd_setup(const char *v
module_param_call(block2mtd, block2mtd_setup, NULL, NULL, 0200);
-MODULE_PARM_DESC(block2mtd, "Device to use. \"block2mtd=<dev>[,<erasesize>]\"");
+MODULE_PARM_DESC(block2mtd, "Device to use. \"block2mtd=<dev>[,<erasesize>[,<name>]]\"");
static int __init block2mtd_init(void)
{
--- a/block/partition-generic.c
+++ b/block/partition-generic.c
@@ -548,6 +548,7 @@ int invalidate_partitions(struct gendisk
return 0;
}
+EXPORT_SYMBOL(rescan_partitions);
unsigned char *read_dev_sector(struct block_device *bdev, sector_t n, Sector *p)
{

View file

@ -1,269 +0,0 @@
--- a/drivers/mtd/devices/block2mtd.c
+++ b/drivers/mtd/devices/block2mtd.c
@@ -29,6 +29,8 @@ struct block2mtd_dev {
struct block_device *blkdev;
struct mtd_info mtd;
struct mutex write_mutex;
+ rwlock_t bdev_mutex;
+ char devname[0];
};
@@ -79,6 +81,12 @@ static int block2mtd_erase(struct mtd_in
size_t len = instr->len;
int err;
+ read_lock(&dev->bdev_mutex);
+ if (!dev->blkdev) {
+ err = -EINVAL;
+ goto done;
+ }
+
instr->state = MTD_ERASING;
mutex_lock(&dev->write_mutex);
err = _block2mtd_erase(dev, from, len);
@@ -90,6 +98,10 @@ static int block2mtd_erase(struct mtd_in
instr->state = MTD_ERASE_DONE;
mtd_erase_callback(instr);
+
+done:
+ read_unlock(&dev->bdev_mutex);
+
return err;
}
@@ -101,7 +113,13 @@ static int block2mtd_read(struct mtd_inf
struct page *page;
int index = from >> PAGE_SHIFT;
int offset = from & (PAGE_SIZE-1);
- int cpylen;
+ int cpylen, err = 0;
+
+ read_lock(&dev->bdev_mutex);
+ if (!dev->blkdev || (from > mtd->size)) {
+ err = -EINVAL;
+ goto done;
+ }
while (len) {
if ((offset + len) > PAGE_SIZE)
@@ -111,8 +129,10 @@ static int block2mtd_read(struct mtd_inf
len = len - cpylen;
page = page_read(dev->blkdev->bd_inode->i_mapping, index);
- if (IS_ERR(page))
- return PTR_ERR(page);
+ if (IS_ERR(page)) {
+ err = PTR_ERR(page);
+ goto done;
+ }
memcpy(buf, page_address(page) + offset, cpylen);
page_cache_release(page);
@@ -123,7 +143,10 @@ static int block2mtd_read(struct mtd_inf
offset = 0;
index++;
}
- return 0;
+
+done:
+ read_unlock(&dev->bdev_mutex);
+ return err;
}
@@ -171,13 +194,22 @@ static int block2mtd_write(struct mtd_in
size_t *retlen, const u_char *buf)
{
struct block2mtd_dev *dev = mtd->priv;
- int err;
+ int err = 0;
+
+ read_lock(&dev->bdev_mutex);
+ if (!dev->blkdev) {
+ err = -EINVAL;
+ goto done;
+ }
mutex_lock(&dev->write_mutex);
err = _block2mtd_write(dev, buf, to, len, retlen);
mutex_unlock(&dev->write_mutex);
if (err > 0)
err = 0;
+
+done:
+ read_unlock(&dev->bdev_mutex);
return err;
}
@@ -186,33 +218,110 @@ static int block2mtd_write(struct mtd_in
static void block2mtd_sync(struct mtd_info *mtd)
{
struct block2mtd_dev *dev = mtd->priv;
+ read_lock(&dev->bdev_mutex);
+ if (dev->blkdev)
sync_blockdev(dev->blkdev);
+ read_unlock(&dev->bdev_mutex);
+
return;
}
+static int _open_bdev(struct block2mtd_dev *dev)
+{
+ const fmode_t mode = FMODE_READ | FMODE_WRITE | FMODE_EXCL;
+ struct block_device *bdev;
+
+ /* Get a handle on the device */
+ bdev = blkdev_get_by_path(dev->devname, mode, dev);
+#ifndef MODULE
+ if (IS_ERR(bdev)) {
+ dev_t devt;
+
+ /* We might not have rootfs mounted at this point. Try
+ to resolve the device name by other means. */
+
+ devt = name_to_dev_t(dev->devname);
+ if (devt)
+ bdev = blkdev_get_by_dev(devt, mode, dev);
+ }
+#endif
+
+ if (IS_ERR(bdev)) {
+ ERROR("error: cannot open device %s", dev->devname);
+ return 1;
+ }
+ dev->blkdev = bdev;
+
+ if (MAJOR(bdev->bd_dev) == MTD_BLOCK_MAJOR) {
+ ERROR("attempting to use an MTD device as a block device");
+ return 1;
+ }
+
+ return 0;
+}
+
+static void _close_bdev(struct block2mtd_dev *dev)
+{
+ struct block_device *bdev;
+
+ if (!dev->blkdev)
+ return;
+
+ bdev = dev->blkdev;
+ invalidate_mapping_pages(dev->blkdev->bd_inode->i_mapping, 0, -1);
+ blkdev_put(dev->blkdev, FMODE_READ|FMODE_WRITE|FMODE_EXCL);
+ dev->blkdev = NULL;
+}
+
static void block2mtd_free_device(struct block2mtd_dev *dev)
{
if (!dev)
return;
kfree(dev->mtd.name);
-
- if (dev->blkdev) {
- invalidate_mapping_pages(dev->blkdev->bd_inode->i_mapping,
- 0, -1);
- blkdev_put(dev->blkdev, FMODE_READ|FMODE_WRITE|FMODE_EXCL);
- }
-
+ _close_bdev(dev);
kfree(dev);
}
-/* FIXME: ensure that mtd->size % erase_size == 0 */
-static struct block2mtd_dev *add_device(char *devname, int erase_size, const char *mtdname)
+static int block2mtd_refresh(struct mtd_info *mtd)
{
- const fmode_t mode = FMODE_READ | FMODE_WRITE | FMODE_EXCL;
+ struct block2mtd_dev *dev = mtd->priv;
struct block_device *bdev;
+ dev_t devt;
+ int err = 0;
+
+ /* no other mtd function can run at this point */
+ write_lock(&dev->bdev_mutex);
+
+ /* get the device number for the whole disk */
+ devt = MKDEV(MAJOR(dev->blkdev->bd_dev), 0);
+
+ /* close the old block device */
+ _close_bdev(dev);
+
+ /* open the whole disk, issue a partition rescan, then */
+ bdev = blkdev_get_by_dev(devt, FMODE_WRITE | FMODE_READ, mtd);
+ if (!bdev || !bdev->bd_disk)
+ err = -EINVAL;
+#ifndef CONFIG_MTD_BLOCK2MTD_MODULE
+ else
+ err = rescan_partitions(bdev->bd_disk, bdev);
+#endif
+ if (bdev)
+ blkdev_put(bdev, FMODE_READ|FMODE_WRITE|FMODE_EXCL);
+
+ /* try to open the partition block device again */
+ _open_bdev(dev);
+ write_unlock(&dev->bdev_mutex);
+
+ return err;
+}
+
+/* FIXME: ensure that mtd->size % erase_size == 0 */
+static struct block2mtd_dev *add_device(char *devname, int erase_size, char *mtdname)
+{
struct block2mtd_dev *dev;
struct mtd_partition *part;
char *name;
@@ -220,36 +329,17 @@ static struct block2mtd_dev *add_device(
if (!devname)
return NULL;
- dev = kzalloc(sizeof(struct block2mtd_dev), GFP_KERNEL);
+ dev = kzalloc(sizeof(struct block2mtd_dev) + strlen(devname) + 1, GFP_KERNEL);
if (!dev)
return NULL;
- /* Get a handle on the device */
- bdev = blkdev_get_by_path(devname, mode, dev);
-#ifndef MODULE
- if (IS_ERR(bdev)) {
-
- /* We might not have rootfs mounted at this point. Try
- to resolve the device name by other means. */
-
- dev_t devt = name_to_dev_t(devname);
- if (devt)
- bdev = blkdev_get_by_dev(devt, mode, dev);
- }
-#endif
-
- if (IS_ERR(bdev)) {
- ERROR("error: cannot open device %s", devname);
- goto devinit_err;
- }
- dev->blkdev = bdev;
+ strcpy(dev->devname, devname);
- if (MAJOR(bdev->bd_dev) == MTD_BLOCK_MAJOR) {
- ERROR("attempting to use an MTD device as a block device");
+ if (_open_bdev(dev))
goto devinit_err;
- }
mutex_init(&dev->write_mutex);
+ rwlock_init(&dev->bdev_mutex);
/* Setup the MTD structure */
/* make the name contain the block device in */
@@ -274,6 +364,7 @@ static struct block2mtd_dev *add_device(
dev->mtd._read = block2mtd_read;
dev->mtd.priv = dev;
dev->mtd.owner = THIS_MODULE;
+ dev->mtd.refresh_device = block2mtd_refresh;
part = kzalloc(sizeof(struct mtd_partition), GFP_KERNEL);
part->name = name;

View file

@ -1,10 +0,0 @@
--- a/drivers/mtd/devices/block2mtd.c
+++ b/drivers/mtd/devices/block2mtd.c
@@ -241,6 +241,7 @@ static int _open_bdev(struct block2mtd_d
/* We might not have rootfs mounted at this point. Try
to resolve the device name by other means. */
+ wait_for_device_probe();
devt = name_to_dev_t(dev->devname);
if (devt)
bdev = blkdev_get_by_dev(devt, mode, dev);

View file

@ -1,37 +0,0 @@
---
drivers/mtd/nand/plat_nand.c | 13 ++++++++++++-
include/linux/mtd/nand.h | 1 +
2 files changed, 13 insertions(+), 1 deletion(-)
--- a/include/linux/mtd/nand.h
+++ b/include/linux/mtd/nand.h
@@ -622,6 +622,7 @@ struct platform_nand_chip {
unsigned int options;
unsigned int bbt_options;
const char **part_probe_types;
+ int (*chip_fixup)(struct mtd_info *mtd);
};
/* Keep gcc happy */
--- a/drivers/mtd/nand/plat_nand.c
+++ b/drivers/mtd/nand/plat_nand.c
@@ -98,7 +98,18 @@ static int __devinit plat_nand_probe(str
}
/* Scan to find existence of the device */
- if (nand_scan(&data->mtd, pdata->chip.nr_chips)) {
+ if (nand_scan_ident(&data->mtd, pdata->chip.nr_chips, NULL)) {
+ err = -ENXIO;
+ goto out;
+ }
+
+ if (pdata->chip.chip_fixup) {
+ err = pdata->chip.chip_fixup(&data->mtd);
+ if (err)
+ goto out;
+ }
+
+ if (nand_scan_tail(&data->mtd)) {
err = -ENXIO;
goto out;
}

View file

@ -1,12 +0,0 @@
--- a/drivers/mtd/nand/nand_ecc.c
+++ b/drivers/mtd/nand/nand_ecc.c
@@ -507,8 +507,7 @@ int __nand_correct_data(unsigned char *b
if ((bitsperbyte[b0] + bitsperbyte[b1] + bitsperbyte[b2]) == 1)
return 1; /* error in ECC data; no action needed */
- printk(KERN_ERR "uncorrectable error : ");
- return -1;
+ return -EBADMSG;
}
EXPORT_SYMBOL(__nand_correct_data);

View file

@ -1,11 +0,0 @@
--- a/drivers/mtd/chips/cfi_cmdset_0002.c
+++ b/drivers/mtd/chips/cfi_cmdset_0002.c
@@ -700,7 +700,7 @@ static int get_chip(struct map_info *map
return 0;
case FL_ERASING:
- if (!cfip || !(cfip->EraseSuspend & (0x1|0x2)) ||
+ if (1 /* no suspend */ || !cfip || !(cfip->EraseSuspend & (0x1|0x2)) ||
!(mode == FL_READY || mode == FL_POINT ||
(mode == FL_WRITING && (cfip->EraseSuspend & 0x2))))
goto sleep;

View file

@ -1,39 +0,0 @@
--- a/drivers/mtd/devices/m25p80.c
+++ b/drivers/mtd/devices/m25p80.c
@@ -45,6 +45,7 @@
#define OPCODE_BE_4K 0x20 /* Erase 4KiB block */
#define OPCODE_BE_32K 0x52 /* Erase 32KiB block */
#define OPCODE_CHIP_ERASE 0xc7 /* Erase whole flash chip */
+#define OPCODE_BE_4K_PMC 0xd7 /* Erase 4KiB block on PMC chips*/
#define OPCODE_SE 0xd8 /* Sector erase (usually 64KiB) */
#define OPCODE_RDID 0x9f /* Read JEDEC ID */
@@ -594,6 +595,7 @@ struct flash_info {
u16 flags;
#define SECT_4K 0x01 /* OPCODE_BE_4K works uniformly */
#define M25P_NO_ERASE 0x02 /* No erase command needed */
+#define SECT_4K_PMC 0x04 /* OPCODE_BE_4K_PMC works uniformly */
};
#define INFO(_jedec_id, _ext_id, _sector_size, _n_sectors, _flags) \
@@ -663,6 +665,10 @@ static const struct spi_device_id m25p_i
{ "mx25l25635e", INFO(0xc22019, 0, 64 * 1024, 512, 0) },
{ "mx25l25655e", INFO(0xc22619, 0, 64 * 1024, 512, 0) },
+ /* 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) },
+
/* Spansion -- single (large) sector size only, at least
* for the chips listed here (without boot sectors).
*/
@@ -899,6 +905,9 @@ static int __devinit m25p_probe(struct s
if (info->flags & SECT_4K) {
flash->erase_opcode = OPCODE_BE_4K;
flash->mtd.erasesize = 4096;
+ } else if (info->flags & SECT_4K_PMC) {
+ flash->erase_opcode = OPCODE_BE_4K_PMC;
+ flash->mtd.erasesize = 4096;
} else {
flash->erase_opcode = OPCODE_SE;
flash->mtd.erasesize = info->sector_size;

View file

@ -1,10 +0,0 @@
--- a/drivers/mtd/devices/m25p80.c
+++ b/drivers/mtd/devices/m25p80.c
@@ -743,6 +743,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) },
+ { "w25q128", INFO(0xef4018, 0, 64 * 1024, 256, SECT_4K) },
/* Catalyst / On Semiconductor -- non-JEDEC */
{ "cat25c11", CAT25_INFO( 16, 8, 16, 1) },

View file

@ -1,10 +0,0 @@
--- a/drivers/mtd/devices/m25p80.c
+++ b/drivers/mtd/devices/m25p80.c
@@ -668,6 +668,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).

View file

@ -1,18 +0,0 @@
From: George Kashperko <george@znau.edu.ua>
Issue map read after Write Buffer Load command to ensure chip is ready
to receive data.
Signed-off-by: George Kashperko <george@znau.edu.ua>
---
drivers/mtd/chips/cfi_cmdset_0002.c | 1 +
1 file changed, 1 insertion(+)
--- a/drivers/mtd/chips/cfi_cmdset_0002.c
+++ b/drivers/mtd/chips/cfi_cmdset_0002.c
@@ -1413,6 +1413,7 @@ static int __xipram do_write_buffer(stru
/* Write Buffer Load */
map_write(map, CMD(0x25), cmd_adr);
+ (void) map_read(map, cmd_adr);
chip->state = FL_WRITING_TO_BUFFER;

View file

@ -1,41 +0,0 @@
--- a/drivers/mtd/devices/Kconfig
+++ b/drivers/mtd/devices/Kconfig
@@ -110,6 +110,14 @@ config MTD_SPEAR_SMI
help
This enable SNOR support on SPEAR platforms using SMI controller
+config M25PXX_PREFER_SMALL_SECTOR_ERASE
+ bool "Prefer small sector erase"
+ depends on MTD_M25P80
+ default y
+ help
+ This option enables use of the small erase sectors if that is
+ supported by the flash chip.
+
config MTD_SST25L
tristate "Support SST25L (non JEDEC) SPI Flash chips"
depends on SPI_MASTER
--- a/drivers/mtd/devices/m25p80.c
+++ b/drivers/mtd/devices/m25p80.c
@@ -84,6 +84,12 @@
#define JEDEC_MFR(_jedec_id) ((_jedec_id) >> 16)
+#ifdef CONFIG_M25PXX_PREFER_SMALL_SECTOR_ERASE
+#define PREFER_SMALL_SECTOR_ERASE 1
+#else
+#define PREFER_SMALL_SECTOR_ERASE 0
+#endif
+
/****************************************************************************/
struct m25p {
@@ -904,7 +910,7 @@ static int __devinit m25p_probe(struct s
flash->mtd._write = m25p80_write;
/* prefer "small sector" erase if possible */
- if (info->flags & SECT_4K) {
+ if (PREFER_SMALL_SECTOR_ERASE && (info->flags & SECT_4K)) {
flash->erase_opcode = OPCODE_BE_4K;
flash->mtd.erasesize = 4096;
} else if (info->flags & SECT_4K_PMC) {

View file

@ -1,10 +0,0 @@
--- a/drivers/mtd/devices/m25p80.c
+++ b/drivers/mtd/devices/m25p80.c
@@ -646,6 +646,7 @@ static const struct spi_device_id m25p_i
{ "en25p32", INFO(0x1c2016, 0, 64 * 1024, 64, 0) },
{ "en25q32b", INFO(0x1c3016, 0, 64 * 1024, 64, 0) },
{ "en25p64", INFO(0x1c2017, 0, 64 * 1024, 128, 0) },
+ { "en25q64", INFO(0x1c3017, 0, 64 * 1024, 128, SECT_4K) },
/* Everspin */
{ "mr25h256", CAT25_INFO( 32 * 1024, 1, 256, 2) },

View file

@ -1,18 +0,0 @@
--- a/drivers/mtd/mtdpart.c
+++ b/drivers/mtd/mtdpart.c
@@ -330,7 +330,14 @@ static int part_lock(struct mtd_info *mt
static int part_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len)
{
struct mtd_part *part = PART(mtd);
- return part->master->_unlock(part->master, ofs + part->offset, len);
+
+ ofs += part->offset;
+ if (mtd->flags & MTD_ERASE_PARTIAL) {
+ /* round up len to next erasesize and round down offset to prev block */
+ len = (mtd_div_by_eb(len, part->master) + 1) * part->master->erasesize;
+ ofs &= ~(part->master->erasesize - 1);
+ }
+ return part->master->_unlock(part->master, ofs, len);
}
static int part_is_locked(struct mtd_info *mtd, loff_t ofs, uint64_t len)

View file

@ -1,25 +0,0 @@
From f31b7c0efa255dd17a5f584022a319387f09b0d8 Mon Sep 17 00:00:00 2001
From: Jonas Gorski <jonas.gorski@gmail.com>
Date: Tue, 12 Apr 2011 19:55:41 +0200
Subject: [PATCH] squashfs: update xz compressor options struct.
Update the xz compressor options struct to match the squashfs userspace
one.
---
fs/squashfs/xz_wrapper.c | 4 +++-
1 files changed, 3 insertions(+), 1 deletions(-)
--- a/fs/squashfs/xz_wrapper.c
+++ b/fs/squashfs/xz_wrapper.c
@@ -39,8 +39,10 @@ struct squashfs_xz {
};
struct comp_opts {
- __le32 dictionary_size;
__le32 flags;
+ __le16 bit_opts;
+ __le16 fb;
+ __le32 dictionary_size;
};
static void *squashfs_xz_init(struct squashfs_sb_info *msblk, void *buff,

View file

@ -1,485 +0,0 @@
--- a/include/linux/lzma/LzmaDec.h
+++ b/include/linux/lzma/LzmaDec.h
@@ -31,14 +31,6 @@ typedef struct _CLzmaProps
UInt32 dicSize;
} CLzmaProps;
-/* LzmaProps_Decode - decodes properties
-Returns:
- SZ_OK
- SZ_ERROR_UNSUPPORTED - Unsupported properties
-*/
-
-SRes LzmaProps_Decode(CLzmaProps *p, const Byte *data, unsigned size);
-
/* ---------- LZMA Decoder state ---------- */
@@ -70,8 +62,6 @@ typedef struct
#define LzmaDec_Construct(p) { (p)->dic = 0; (p)->probs = 0; }
-void LzmaDec_Init(CLzmaDec *p);
-
/* There are two types of LZMA streams:
0) Stream with end mark. That end mark adds about 6 bytes to compressed size.
1) Stream without end mark. You must know exact uncompressed size to decompress such stream. */
@@ -108,97 +98,6 @@ typedef enum
/* ELzmaStatus is used only as output value for function call */
-
-/* ---------- Interfaces ---------- */
-
-/* There are 3 levels of interfaces:
- 1) Dictionary Interface
- 2) Buffer Interface
- 3) One Call Interface
- You can select any of these interfaces, but don't mix functions from different
- groups for same object. */
-
-
-/* There are two variants to allocate state for Dictionary Interface:
- 1) LzmaDec_Allocate / LzmaDec_Free
- 2) LzmaDec_AllocateProbs / LzmaDec_FreeProbs
- You can use variant 2, if you set dictionary buffer manually.
- For Buffer Interface you must always use variant 1.
-
-LzmaDec_Allocate* can return:
- SZ_OK
- SZ_ERROR_MEM - Memory allocation error
- SZ_ERROR_UNSUPPORTED - Unsupported properties
-*/
-
-SRes LzmaDec_AllocateProbs(CLzmaDec *p, const Byte *props, unsigned propsSize, ISzAlloc *alloc);
-void LzmaDec_FreeProbs(CLzmaDec *p, ISzAlloc *alloc);
-
-SRes LzmaDec_Allocate(CLzmaDec *state, const Byte *prop, unsigned propsSize, ISzAlloc *alloc);
-void LzmaDec_Free(CLzmaDec *state, ISzAlloc *alloc);
-
-/* ---------- Dictionary Interface ---------- */
-
-/* You can use it, if you want to eliminate the overhead for data copying from
- dictionary to some other external buffer.
- You must work with CLzmaDec variables directly in this interface.
-
- STEPS:
- LzmaDec_Constr()
- LzmaDec_Allocate()
- for (each new stream)
- {
- LzmaDec_Init()
- while (it needs more decompression)
- {
- LzmaDec_DecodeToDic()
- use data from CLzmaDec::dic and update CLzmaDec::dicPos
- }
- }
- LzmaDec_Free()
-*/
-
-/* LzmaDec_DecodeToDic
-
- The decoding to internal dictionary buffer (CLzmaDec::dic).
- You must manually update CLzmaDec::dicPos, if it reaches CLzmaDec::dicBufSize !!!
-
-finishMode:
- It has meaning only if the decoding reaches output limit (dicLimit).
- LZMA_FINISH_ANY - Decode just dicLimit bytes.
- LZMA_FINISH_END - Stream must be finished after dicLimit.
-
-Returns:
- SZ_OK
- status:
- LZMA_STATUS_FINISHED_WITH_MARK
- LZMA_STATUS_NOT_FINISHED
- LZMA_STATUS_NEEDS_MORE_INPUT
- LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK
- SZ_ERROR_DATA - Data error
-*/
-
-SRes LzmaDec_DecodeToDic(CLzmaDec *p, SizeT dicLimit,
- const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status);
-
-
-/* ---------- Buffer Interface ---------- */
-
-/* It's zlib-like interface.
- See LzmaDec_DecodeToDic description for information about STEPS and return results,
- but you must use LzmaDec_DecodeToBuf instead of LzmaDec_DecodeToDic and you don't need
- to work with CLzmaDec variables manually.
-
-finishMode:
- It has meaning only if the decoding reaches output limit (*destLen).
- LZMA_FINISH_ANY - Decode just destLen bytes.
- LZMA_FINISH_END - Stream must be finished after (*destLen).
-*/
-
-SRes LzmaDec_DecodeToBuf(CLzmaDec *p, Byte *dest, SizeT *destLen,
- const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status);
-
-
/* ---------- One Call Interface ---------- */
/* LzmaDecode
--- a/lib/lzma/LzmaDec.c
+++ b/lib/lzma/LzmaDec.c
@@ -682,7 +682,7 @@ static void LzmaDec_InitRc(CLzmaDec *p,
p->needFlush = 0;
}
-void LzmaDec_InitDicAndState(CLzmaDec *p, Bool initDic, Bool initState)
+static void LzmaDec_InitDicAndState(CLzmaDec *p, Bool initDic, Bool initState)
{
p->needFlush = 1;
p->remainLen = 0;
@@ -698,7 +698,7 @@ void LzmaDec_InitDicAndState(CLzmaDec *p
p->needInitState = 1;
}
-void LzmaDec_Init(CLzmaDec *p)
+static void LzmaDec_Init(CLzmaDec *p)
{
p->dicPos = 0;
LzmaDec_InitDicAndState(p, True, True);
@@ -716,7 +716,7 @@ static void LzmaDec_InitStateReal(CLzmaD
p->needInitState = 0;
}
-SRes LzmaDec_DecodeToDic(CLzmaDec *p, SizeT dicLimit, const Byte *src, SizeT *srcLen,
+static SRes LzmaDec_DecodeToDic(CLzmaDec *p, SizeT dicLimit, const Byte *src, SizeT *srcLen,
ELzmaFinishMode finishMode, ELzmaStatus *status)
{
SizeT inSize = *srcLen;
@@ -837,7 +837,7 @@ SRes LzmaDec_DecodeToDic(CLzmaDec *p, Si
return (p->code == 0) ? SZ_OK : SZ_ERROR_DATA;
}
-SRes LzmaDec_DecodeToBuf(CLzmaDec *p, Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status)
+static __maybe_unused SRes LzmaDec_DecodeToBuf(CLzmaDec *p, Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status)
{
SizeT outSize = *destLen;
SizeT inSize = *srcLen;
@@ -877,7 +877,7 @@ SRes LzmaDec_DecodeToBuf(CLzmaDec *p, By
}
}
-void LzmaDec_FreeProbs(CLzmaDec *p, ISzAlloc *alloc)
+static void LzmaDec_FreeProbs(CLzmaDec *p, ISzAlloc *alloc)
{
alloc->Free(alloc, p->probs);
p->probs = 0;
@@ -889,13 +889,13 @@ static void LzmaDec_FreeDict(CLzmaDec *p
p->dic = 0;
}
-void LzmaDec_Free(CLzmaDec *p, ISzAlloc *alloc)
+static void __maybe_unused LzmaDec_Free(CLzmaDec *p, ISzAlloc *alloc)
{
LzmaDec_FreeProbs(p, alloc);
LzmaDec_FreeDict(p, alloc);
}
-SRes LzmaProps_Decode(CLzmaProps *p, const Byte *data, unsigned size)
+static SRes LzmaProps_Decode(CLzmaProps *p, const Byte *data, unsigned size)
{
UInt32 dicSize;
Byte d;
@@ -935,7 +935,7 @@ static SRes LzmaDec_AllocateProbs2(CLzma
return SZ_OK;
}
-SRes LzmaDec_AllocateProbs(CLzmaDec *p, const Byte *props, unsigned propsSize, ISzAlloc *alloc)
+static SRes __maybe_unused LzmaDec_AllocateProbs(CLzmaDec *p, const Byte *props, unsigned propsSize, ISzAlloc *alloc)
{
CLzmaProps propNew;
RINOK(LzmaProps_Decode(&propNew, props, propsSize));
@@ -944,7 +944,7 @@ SRes LzmaDec_AllocateProbs(CLzmaDec *p,
return SZ_OK;
}
-SRes LzmaDec_Allocate(CLzmaDec *p, const Byte *props, unsigned propsSize, ISzAlloc *alloc)
+static SRes __maybe_unused LzmaDec_Allocate(CLzmaDec *p, const Byte *props, unsigned propsSize, ISzAlloc *alloc)
{
CLzmaProps propNew;
SizeT dicBufSize;
--- a/include/linux/lzma/LzmaEnc.h
+++ b/include/linux/lzma/LzmaEnc.h
@@ -31,9 +31,6 @@ typedef struct _CLzmaEncProps
} CLzmaEncProps;
void LzmaEncProps_Init(CLzmaEncProps *p);
-void LzmaEncProps_Normalize(CLzmaEncProps *p);
-UInt32 LzmaEncProps_GetDictSize(const CLzmaEncProps *props2);
-
/* ---------- CLzmaEncHandle Interface ---------- */
@@ -53,26 +50,9 @@ CLzmaEncHandle LzmaEnc_Create(ISzAlloc *
void LzmaEnc_Destroy(CLzmaEncHandle p, ISzAlloc *alloc, ISzAlloc *allocBig);
SRes LzmaEnc_SetProps(CLzmaEncHandle p, const CLzmaEncProps *props);
SRes LzmaEnc_WriteProperties(CLzmaEncHandle p, Byte *properties, SizeT *size);
-SRes LzmaEnc_Encode(CLzmaEncHandle p, ISeqOutStream *outStream, ISeqInStream *inStream,
- ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig);
SRes LzmaEnc_MemEncode(CLzmaEncHandle p, Byte *dest, SizeT *destLen, const Byte *src, SizeT srcLen,
int writeEndMark, ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig);
-/* ---------- One Call Interface ---------- */
-
-/* LzmaEncode
-Return code:
- SZ_OK - OK
- SZ_ERROR_MEM - Memory allocation error
- SZ_ERROR_PARAM - Incorrect paramater
- SZ_ERROR_OUTPUT_EOF - output buffer overflow
- SZ_ERROR_THREAD - errors in multithreading functions (only for Mt version)
-*/
-
-SRes LzmaEncode(Byte *dest, SizeT *destLen, const Byte *src, SizeT srcLen,
- const CLzmaEncProps *props, Byte *propsEncoded, SizeT *propsSize, int writeEndMark,
- ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig);
-
#ifdef __cplusplus
}
#endif
--- a/lib/lzma/LzmaEnc.c
+++ b/lib/lzma/LzmaEnc.c
@@ -53,7 +53,7 @@ void LzmaEncProps_Init(CLzmaEncProps *p)
p->writeEndMark = 0;
}
-void LzmaEncProps_Normalize(CLzmaEncProps *p)
+static void LzmaEncProps_Normalize(CLzmaEncProps *p)
{
int level = p->level;
if (level < 0) level = 5;
@@ -76,7 +76,7 @@ void LzmaEncProps_Normalize(CLzmaEncProp
#endif
}
-UInt32 LzmaEncProps_GetDictSize(const CLzmaEncProps *props2)
+static UInt32 __maybe_unused LzmaEncProps_GetDictSize(const CLzmaEncProps *props2)
{
CLzmaEncProps props = *props2;
LzmaEncProps_Normalize(&props);
@@ -93,7 +93,7 @@ UInt32 LzmaEncProps_GetDictSize(const CL
#define BSR2_RET(pos, res) { unsigned long i; _BitScanReverse(&i, (pos)); res = (i + i) + ((pos >> (i - 1)) & 1); }
-UInt32 GetPosSlot1(UInt32 pos)
+static UInt32 GetPosSlot1(UInt32 pos)
{
UInt32 res;
BSR2_RET(pos, res);
@@ -107,7 +107,7 @@ UInt32 GetPosSlot1(UInt32 pos)
#define kNumLogBits (9 + (int)sizeof(size_t) / 2)
#define kDicLogSizeMaxCompress ((kNumLogBits - 1) * 2 + 7)
-void LzmaEnc_FastPosInit(Byte *g_FastPos)
+static void LzmaEnc_FastPosInit(Byte *g_FastPos)
{
int c = 2, slotFast;
g_FastPos[0] = 0;
@@ -339,7 +339,7 @@ typedef struct
CSaveState saveState;
} CLzmaEnc;
-void LzmaEnc_SaveState(CLzmaEncHandle pp)
+static void __maybe_unused LzmaEnc_SaveState(CLzmaEncHandle pp)
{
CLzmaEnc *p = (CLzmaEnc *)pp;
CSaveState *dest = &p->saveState;
@@ -365,7 +365,7 @@ void LzmaEnc_SaveState(CLzmaEncHandle pp
memcpy(dest->litProbs, p->litProbs, (0x300 << p->lclp) * sizeof(CLzmaProb));
}
-void LzmaEnc_RestoreState(CLzmaEncHandle pp)
+static void __maybe_unused LzmaEnc_RestoreState(CLzmaEncHandle pp)
{
CLzmaEnc *dest = (CLzmaEnc *)pp;
const CSaveState *p = &dest->saveState;
@@ -600,7 +600,7 @@ static void LitEnc_EncodeMatched(CRangeE
while (symbol < 0x10000);
}
-void LzmaEnc_InitPriceTables(UInt32 *ProbPrices)
+static void LzmaEnc_InitPriceTables(UInt32 *ProbPrices)
{
UInt32 i;
for (i = (1 << kNumMoveReducingBits) / 2; i < kBitModelTotal; i += (1 << kNumMoveReducingBits))
@@ -1676,7 +1676,7 @@ static void FillDistancesPrices(CLzmaEnc
p->matchPriceCount = 0;
}
-void LzmaEnc_Construct(CLzmaEnc *p)
+static void LzmaEnc_Construct(CLzmaEnc *p)
{
RangeEnc_Construct(&p->rc);
MatchFinder_Construct(&p->matchFinderBase);
@@ -1709,7 +1709,7 @@ CLzmaEncHandle LzmaEnc_Create(ISzAlloc *
return p;
}
-void LzmaEnc_FreeLits(CLzmaEnc *p, ISzAlloc *alloc)
+static void LzmaEnc_FreeLits(CLzmaEnc *p, ISzAlloc *alloc)
{
alloc->Free(alloc, p->litProbs);
alloc->Free(alloc, p->saveState.litProbs);
@@ -2074,7 +2074,7 @@ SRes LzmaEnc_MemPrepare(CLzmaEncHandle p
return LzmaEnc_AllocAndInit(p, keepWindowSize, alloc, allocBig);
}
-void LzmaEnc_Finish(CLzmaEncHandle pp)
+static void LzmaEnc_Finish(CLzmaEncHandle pp)
{
#ifndef _7ZIP_ST
CLzmaEnc *p = (CLzmaEnc *)pp;
@@ -2108,7 +2108,7 @@ static size_t MyWrite(void *pp, const vo
}
-UInt32 LzmaEnc_GetNumAvailableBytes(CLzmaEncHandle pp)
+static UInt32 __maybe_unused LzmaEnc_GetNumAvailableBytes(CLzmaEncHandle pp)
{
const CLzmaEnc *p = (CLzmaEnc *)pp;
return p->matchFinder.GetNumAvailableBytes(p->matchFinderObj);
@@ -2120,7 +2120,7 @@ const Byte *LzmaEnc_GetCurBuf(CLzmaEncHa
return p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - p->additionalOffset;
}
-SRes LzmaEnc_CodeOneMemBlock(CLzmaEncHandle pp, Bool reInit,
+static SRes __maybe_unused LzmaEnc_CodeOneMemBlock(CLzmaEncHandle pp, Bool reInit,
Byte *dest, size_t *destLen, UInt32 desiredPackSize, UInt32 *unpackSize)
{
CLzmaEnc *p = (CLzmaEnc *)pp;
@@ -2248,7 +2248,7 @@ SRes LzmaEnc_MemEncode(CLzmaEncHandle pp
return res;
}
-SRes LzmaEncode(Byte *dest, SizeT *destLen, const Byte *src, SizeT srcLen,
+static __maybe_unused SRes LzmaEncode(Byte *dest, SizeT *destLen, const Byte *src, SizeT srcLen,
const CLzmaEncProps *props, Byte *propsEncoded, SizeT *propsSize, int writeEndMark,
ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig)
{
--- a/include/linux/lzma/LzFind.h
+++ b/include/linux/lzma/LzFind.h
@@ -55,11 +55,6 @@ typedef struct _CMatchFinder
#define Inline_MatchFinder_GetNumAvailableBytes(p) ((p)->streamPos - (p)->pos)
-int MatchFinder_NeedMove(CMatchFinder *p);
-Byte *MatchFinder_GetPointerToCurrentPos(CMatchFinder *p);
-void MatchFinder_MoveBlock(CMatchFinder *p);
-void MatchFinder_ReadIfRequired(CMatchFinder *p);
-
void MatchFinder_Construct(CMatchFinder *p);
/* Conditions:
@@ -70,12 +65,6 @@ int MatchFinder_Create(CMatchFinder *p,
UInt32 keepAddBufferBefore, UInt32 matchMaxLen, UInt32 keepAddBufferAfter,
ISzAlloc *alloc);
void MatchFinder_Free(CMatchFinder *p, ISzAlloc *alloc);
-void MatchFinder_Normalize3(UInt32 subValue, CLzRef *items, UInt32 numItems);
-void MatchFinder_ReduceOffsets(CMatchFinder *p, UInt32 subValue);
-
-UInt32 * GetMatchesSpec1(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const Byte *buffer, CLzRef *son,
- UInt32 _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 _cutValue,
- UInt32 *distances, UInt32 maxLen);
/*
Conditions:
@@ -102,12 +91,6 @@ typedef struct _IMatchFinder
void MatchFinder_CreateVTable(CMatchFinder *p, IMatchFinder *vTable);
-void MatchFinder_Init(CMatchFinder *p);
-UInt32 Bt3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances);
-UInt32 Hc3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances);
-void Bt3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num);
-void Hc3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num);
-
#ifdef __cplusplus
}
#endif
--- a/lib/lzma/LzFind.c
+++ b/lib/lzma/LzFind.c
@@ -42,12 +42,12 @@ static int LzInWindow_Create(CMatchFinde
return (p->bufferBase != 0);
}
-Byte *MatchFinder_GetPointerToCurrentPos(CMatchFinder *p) { return p->buffer; }
-Byte MatchFinder_GetIndexByte(CMatchFinder *p, Int32 index) { return p->buffer[index]; }
+static Byte *MatchFinder_GetPointerToCurrentPos(CMatchFinder *p) { return p->buffer; }
+static Byte MatchFinder_GetIndexByte(CMatchFinder *p, Int32 index) { return p->buffer[index]; }
-UInt32 MatchFinder_GetNumAvailableBytes(CMatchFinder *p) { return p->streamPos - p->pos; }
+static UInt32 MatchFinder_GetNumAvailableBytes(CMatchFinder *p) { return p->streamPos - p->pos; }
-void MatchFinder_ReduceOffsets(CMatchFinder *p, UInt32 subValue)
+static void MatchFinder_ReduceOffsets(CMatchFinder *p, UInt32 subValue)
{
p->posLimit -= subValue;
p->pos -= subValue;
@@ -268,7 +268,7 @@ static void MatchFinder_SetLimits(CMatch
p->posLimit = p->pos + limit;
}
-void MatchFinder_Init(CMatchFinder *p)
+static void MatchFinder_Init(CMatchFinder *p)
{
UInt32 i;
for (i = 0; i < p->hashSizeSum; i++)
@@ -287,7 +287,7 @@ static UInt32 MatchFinder_GetSubValue(CM
return (p->pos - p->historySize - 1) & kNormalizeMask;
}
-void MatchFinder_Normalize3(UInt32 subValue, CLzRef *items, UInt32 numItems)
+static void MatchFinder_Normalize3(UInt32 subValue, CLzRef *items, UInt32 numItems)
{
UInt32 i;
for (i = 0; i < numItems; i++)
@@ -350,7 +350,7 @@ static UInt32 * Hc_GetMatchesSpec(UInt32
}
}
-UInt32 * GetMatchesSpec1(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const Byte *cur, CLzRef *son,
+static UInt32 * GetMatchesSpec1(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const Byte *cur, CLzRef *son,
UInt32 _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 cutValue,
UInt32 *distances, UInt32 maxLen)
{
@@ -492,7 +492,7 @@ static UInt32 Bt2_MatchFinder_GetMatches
GET_MATCHES_FOOTER(offset, 1)
}
-UInt32 Bt3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
+static __maybe_unused UInt32 Bt3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
{
UInt32 offset;
GET_MATCHES_HEADER(3)
@@ -632,7 +632,7 @@ static UInt32 Hc4_MatchFinder_GetMatches
MOVE_POS_RET
}
-UInt32 Hc3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
+static __maybe_unused UInt32 Hc3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
{
UInt32 offset;
GET_MATCHES_HEADER(3)
@@ -657,7 +657,7 @@ static void Bt2_MatchFinder_Skip(CMatchF
while (--num != 0);
}
-void Bt3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num)
+static __maybe_unused void Bt3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num)
{
do
{
@@ -718,7 +718,7 @@ static void Hc4_MatchFinder_Skip(CMatchF
while (--num != 0);
}
-void Hc3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num)
+static __maybe_unused void Hc3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num)
{
do
{

View file

@ -1,53 +0,0 @@
--- a/fs/jffs2/build.c
+++ b/fs/jffs2/build.c
@@ -114,6 +114,16 @@ static int jffs2_build_filesystem(struct
dbg_fsbuild("scanned flash completely\n");
jffs2_dbg_dump_block_lists_nolock(c);
+ if (c->flags & (1 << 7)) {
+ printk("%s(): unlocking the mtd device... ", __func__);
+ mtd_unlock(c->mtd, 0, c->mtd->size);
+ printk("done.\n");
+
+ printk("%s(): erasing all blocks after the end marker... ", __func__);
+ jffs2_erase_pending_blocks(c, -1);
+ printk("done.\n");
+ }
+
dbg_fsbuild("pass 1 starting\n");
c->flags |= JFFS2_SB_FLAG_BUILDING;
/* Now scan the directory tree, increasing nlink according to every dirent found. */
--- a/fs/jffs2/scan.c
+++ b/fs/jffs2/scan.c
@@ -148,8 +148,11 @@ int jffs2_scan_medium(struct jffs2_sb_in
/* reset summary info for next eraseblock scan */
jffs2_sum_reset_collected(s);
- ret = jffs2_scan_eraseblock(c, jeb, buf_size?flashbuf:(flashbuf+jeb->offset),
- buf_size, s);
+ if (c->flags & (1 << 7))
+ ret = BLK_STATE_ALLFF;
+ else
+ ret = jffs2_scan_eraseblock(c, jeb, buf_size?flashbuf:(flashbuf+jeb->offset),
+ buf_size, s);
if (ret < 0)
goto out;
@@ -556,6 +559,17 @@ static int jffs2_scan_eraseblock (struct
return err;
}
+ if ((buf[0] == 0xde) &&
+ (buf[1] == 0xad) &&
+ (buf[2] == 0xc0) &&
+ (buf[3] == 0xde)) {
+ /* end of filesystem. erase everything after this point */
+ printk("%s(): End of filesystem marker found at 0x%x\n", __func__, jeb->offset);
+ c->flags |= (1 << 7);
+
+ return BLK_STATE_ALLFF;
+ }
+
/* We temporarily use 'ofs' as a pointer into the buffer/jeb */
ofs = 0;
max_ofs = EMPTY_SCAN_SIZE(c->sector_size);

View file

@ -1,146 +0,0 @@
--- a/crypto/Kconfig
+++ b/crypto/Kconfig
@@ -1008,6 +1008,13 @@ config CRYPTO_LZO
help
This is the LZO algorithm.
+config CRYPTO_XZ
+ tristate "XZ compression algorithm"
+ select CRYPTO_ALGAPI
+ select XZ_DEC
+ help
+ This is the XZ algorithm. Only decompression is supported for now.
+
comment "Random Number Generation"
config CRYPTO_ANSI_CPRNG
--- a/crypto/Makefile
+++ b/crypto/Makefile
@@ -82,6 +82,7 @@ obj-$(CONFIG_CRYPTO_MICHAEL_MIC) += mich
obj-$(CONFIG_CRYPTO_CRC32C) += crc32c.o
obj-$(CONFIG_CRYPTO_AUTHENC) += authenc.o authencesn.o
obj-$(CONFIG_CRYPTO_LZO) += lzo.o
+obj-$(CONFIG_CRYPTO_XZ) += xz.o
obj-$(CONFIG_CRYPTO_RNG2) += rng.o
obj-$(CONFIG_CRYPTO_RNG2) += krng.o
obj-$(CONFIG_CRYPTO_ANSI_CPRNG) += ansi_cprng.o
--- /dev/null
+++ b/crypto/xz.c
@@ -0,0 +1,117 @@
+/*
+ * Cryptographic API.
+ *
+ * XZ decompression support.
+ *
+ * Copyright (c) 2012 Gabor Juhos <juhosg@openwrt.org>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ */
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/crypto.h>
+#include <linux/xz.h>
+#include <linux/interrupt.h>
+#include <linux/mm.h>
+#include <linux/net.h>
+
+struct xz_comp_ctx {
+ struct xz_dec *decomp_state;
+ struct xz_buf decomp_buf;
+};
+
+static int crypto_xz_decomp_init(struct xz_comp_ctx *ctx)
+{
+ ctx->decomp_state = xz_dec_init(XZ_SINGLE, 0);
+ if (!ctx->decomp_state)
+ return -ENOMEM;
+
+ return 0;
+}
+
+static void crypto_xz_decomp_exit(struct xz_comp_ctx *ctx)
+{
+ xz_dec_end(ctx->decomp_state);
+}
+
+static int crypto_xz_init(struct crypto_tfm *tfm)
+{
+ struct xz_comp_ctx *ctx = crypto_tfm_ctx(tfm);
+
+ return crypto_xz_decomp_init(ctx);
+}
+
+static void crypto_xz_exit(struct crypto_tfm *tfm)
+{
+ struct xz_comp_ctx *ctx = crypto_tfm_ctx(tfm);
+
+ crypto_xz_decomp_exit(ctx);
+}
+
+static int crypto_xz_compress(struct crypto_tfm *tfm, const u8 *src,
+ unsigned int slen, u8 *dst, unsigned int *dlen)
+{
+ return -EOPNOTSUPP;
+}
+
+static int crypto_xz_decompress(struct crypto_tfm *tfm, const u8 *src,
+ unsigned int slen, u8 *dst, unsigned int *dlen)
+{
+ struct xz_comp_ctx *dctx = crypto_tfm_ctx(tfm);
+ struct xz_buf *xz_buf = &dctx->decomp_buf;
+ int ret;
+
+ memset(xz_buf, '\0', sizeof(struct xz_buf));
+
+ xz_buf->in = (u8 *) src;
+ xz_buf->in_pos = 0;
+ xz_buf->in_size = slen;
+ xz_buf->out = (u8 *) dst;
+ xz_buf->out_pos = 0;
+ xz_buf->out_size = *dlen;
+
+ ret = xz_dec_run(dctx->decomp_state, xz_buf);
+ if (ret != XZ_STREAM_END) {
+ ret = -EINVAL;
+ goto out;
+ }
+
+ *dlen = xz_buf->out_pos;
+ ret = 0;
+
+out:
+ return ret;
+}
+
+static struct crypto_alg crypto_xz_alg = {
+ .cra_name = "xz",
+ .cra_flags = CRYPTO_ALG_TYPE_COMPRESS,
+ .cra_ctxsize = sizeof(struct xz_comp_ctx),
+ .cra_module = THIS_MODULE,
+ .cra_list = LIST_HEAD_INIT(crypto_xz_alg.cra_list),
+ .cra_init = crypto_xz_init,
+ .cra_exit = crypto_xz_exit,
+ .cra_u = { .compress = {
+ .coa_compress = crypto_xz_compress,
+ .coa_decompress = crypto_xz_decompress } }
+};
+
+static int __init crypto_xz_mod_init(void)
+{
+ return crypto_register_alg(&crypto_xz_alg);
+}
+
+static void __exit crypto_xz_mod_exit(void)
+{
+ crypto_unregister_alg(&crypto_xz_alg);
+}
+
+module_init(crypto_xz_mod_init);
+module_exit(crypto_xz_mod_exit);
+
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("Crypto XZ decompression support");
+MODULE_AUTHOR("Gabor Juhos <juhosg@openwrt.org>");

View file

@ -1,92 +0,0 @@
--- a/fs/ubifs/Kconfig
+++ b/fs/ubifs/Kconfig
@@ -5,8 +5,10 @@ config UBIFS_FS
select CRYPTO if UBIFS_FS_ADVANCED_COMPR
select CRYPTO if UBIFS_FS_LZO
select CRYPTO if UBIFS_FS_ZLIB
+ select CRYPTO if UBIFS_FS_XZ
select CRYPTO_LZO if UBIFS_FS_LZO
select CRYPTO_DEFLATE if UBIFS_FS_ZLIB
+ select CRYPTO_XZ if UBIFS_FS_XZ
depends on MTD_UBI
help
UBIFS is a file system for flash devices which works on top of UBI.
@@ -35,3 +37,12 @@ config UBIFS_FS_ZLIB
default y
help
Zlib compresses better than LZO but it is slower. Say 'Y' if unsure.
+
+config UBIFS_FS_XZ
+ bool "XZ decompression support" if UBIFS_FS_ADVANCED_COMPR
+ depends on UBIFS_FS
+ default y
+ help
+ XZ compresses better the ZLIB but it is slower..
+ Say 'Y' if unsure.
+
--- a/fs/ubifs/compress.c
+++ b/fs/ubifs/compress.c
@@ -71,6 +71,24 @@ static struct ubifs_compressor zlib_comp
};
#endif
+#ifdef CONFIG_UBIFS_FS_XZ
+static DEFINE_MUTEX(xz_enc_mutex);
+static DEFINE_MUTEX(xz_dec_mutex);
+
+static struct ubifs_compressor xz_compr = {
+ .compr_type = UBIFS_COMPR_XZ,
+ .comp_mutex = &xz_enc_mutex,
+ .decomp_mutex = &xz_dec_mutex,
+ .name = "xz",
+ .capi_name = "xz",
+};
+#else
+static struct ubifs_compressor xz_compr = {
+ .compr_type = UBIFS_COMPR_XZ,
+ .name = "xz",
+};
+#endif
+
/* All UBIFS compressors */
struct ubifs_compressor *ubifs_compressors[UBIFS_COMPR_TYPES_CNT];
@@ -233,9 +251,15 @@ int __init ubifs_compressors_init(void)
if (err)
goto out_lzo;
+ err = compr_init(&xz_compr);
+ if (err)
+ goto out_zlib;
+
ubifs_compressors[UBIFS_COMPR_NONE] = &none_compr;
return 0;
+out_zlib:
+ compr_exit(&zlib_compr);
out_lzo:
compr_exit(&lzo_compr);
return err;
@@ -248,4 +272,5 @@ void ubifs_compressors_exit(void)
{
compr_exit(&lzo_compr);
compr_exit(&zlib_compr);
+ compr_exit(&xz_compr);
}
--- a/fs/ubifs/ubifs-media.h
+++ b/fs/ubifs/ubifs-media.h
@@ -332,12 +332,14 @@ enum {
* UBIFS_COMPR_NONE: no compression
* UBIFS_COMPR_LZO: LZO compression
* UBIFS_COMPR_ZLIB: ZLIB compression
+ * UBIFS_COMPR_XZ: XZ compression
* UBIFS_COMPR_TYPES_CNT: count of supported compression types
*/
enum {
UBIFS_COMPR_NONE,
UBIFS_COMPR_LZO,
UBIFS_COMPR_ZLIB,
+ UBIFS_COMPR_XZ,
UBIFS_COMPR_TYPES_CNT,
};

View file

@ -1,65 +0,0 @@
--- a/fs/ubifs/file.c
+++ b/fs/ubifs/file.c
@@ -1573,6 +1573,10 @@ const struct inode_operations ubifs_syml
.follow_link = ubifs_follow_link,
.setattr = ubifs_setattr,
.getattr = ubifs_getattr,
+ .setxattr = ubifs_setxattr,
+ .getxattr = ubifs_getxattr,
+ .listxattr = ubifs_listxattr,
+ .removexattr = ubifs_removexattr,
};
const struct file_operations ubifs_file_operations = {
--- a/fs/ubifs/journal.c
+++ b/fs/ubifs/journal.c
@@ -553,7 +553,8 @@ int ubifs_jnl_update(struct ubifs_info *
dbg_jnl("ino %lu, dent '%.*s', data len %d in dir ino %lu",
inode->i_ino, nm->len, nm->name, ui->data_len, dir->i_ino);
- ubifs_assert(dir_ui->data_len == 0);
+ if (!xent)
+ ubifs_assert(dir_ui->data_len == 0);
ubifs_assert(mutex_is_locked(&dir_ui->ui_mutex));
dlen = UBIFS_DENT_NODE_SZ + nm->len + 1;
@@ -573,6 +574,13 @@ int ubifs_jnl_update(struct ubifs_info *
aligned_dlen = ALIGN(dlen, 8);
aligned_ilen = ALIGN(ilen, 8);
len = aligned_dlen + aligned_ilen + UBIFS_INO_NODE_SZ;
+ if (xent) {
+ /*
+ * Make sure to account for dir_ui->data_len in
+ * length calculation in case there is extended attribute.
+ */
+ len += dir_ui->data_len;
+ }
dent = kmalloc(len, GFP_NOFS);
if (!dent)
return -ENOMEM;
@@ -649,7 +657,8 @@ int ubifs_jnl_update(struct ubifs_info *
ino_key_init(c, &ino_key, dir->i_ino);
ino_offs += aligned_ilen;
- err = ubifs_tnc_add(c, &ino_key, lnum, ino_offs, UBIFS_INO_NODE_SZ);
+ err = ubifs_tnc_add(c, &ino_key, lnum, ino_offs,
+ UBIFS_INO_NODE_SZ + dir_ui->data_len);
if (err)
goto out_ro;
--- a/fs/ubifs/xattr.c
+++ b/fs/ubifs/xattr.c
@@ -209,12 +209,12 @@ static int change_xattr(struct ubifs_inf
goto out_free;
}
inode->i_size = ui->ui_size = size;
- ui->data_len = size;
mutex_lock(&host_ui->ui_mutex);
host->i_ctime = ubifs_current_time(host);
host_ui->xattr_size -= CALC_XATTR_BYTES(ui->data_len);
host_ui->xattr_size += CALC_XATTR_BYTES(size);
+ ui->data_len = size;
/*
* It is important to write the host inode after the xattr inode

View file

@ -1,108 +0,0 @@
--- a/include/linux/netfilter/xt_layer7.h
+++ b/include/linux/netfilter/xt_layer7.h
@@ -8,6 +8,7 @@ struct xt_layer7_info {
char protocol[MAX_PROTOCOL_LEN];
char pattern[MAX_PATTERN_LEN];
u_int8_t invert;
+ u_int8_t pkt;
};
#endif /* _XT_LAYER7_H */
--- a/net/netfilter/xt_layer7.c
+++ b/net/netfilter/xt_layer7.c
@@ -314,33 +314,35 @@ static int match_no_append(struct nf_con
}
/* add the new app data to the conntrack. Return number of bytes added. */
-static int add_data(struct nf_conn * master_conntrack,
- char * app_data, int appdatalen)
+static int add_datastr(char *target, int offset, char *app_data, int len)
{
int length = 0, i;
- int oldlength = master_conntrack->layer7.app_data_len;
-
- /* This is a fix for a race condition by Deti Fliegl. However, I'm not
- clear on whether the race condition exists or whether this really
- fixes it. I might just be being dense... Anyway, if it's not really
- a fix, all it does is waste a very small amount of time. */
- if(!master_conntrack->layer7.app_data) return 0;
+ if (!target) return 0;
/* Strip nulls. Make everything lower case (our regex lib doesn't
do case insensitivity). Add it to the end of the current data. */
- for(i = 0; i < maxdatalen-oldlength-1 &&
- i < appdatalen; i++) {
+ for(i = 0; i < maxdatalen-offset-1 && i < len; i++) {
if(app_data[i] != '\0') {
/* the kernel version of tolower mungs 'upper ascii' */
- master_conntrack->layer7.app_data[length+oldlength] =
+ target[length+offset] =
isascii(app_data[i])?
tolower(app_data[i]) : app_data[i];
length++;
}
}
+ target[length+offset] = '\0';
+
+ return length;
+}
+
+/* add the new app data to the conntrack. Return number of bytes added. */
+static int add_data(struct nf_conn * master_conntrack,
+ char * app_data, int appdatalen)
+{
+ int length;
- master_conntrack->layer7.app_data[length+oldlength] = '\0';
- master_conntrack->layer7.app_data_len = length + oldlength;
+ length = add_datastr(master_conntrack->layer7.app_data, master_conntrack->layer7.app_data_len, app_data, appdatalen);
+ master_conntrack->layer7.app_data_len += length;
return length;
}
@@ -438,7 +440,7 @@ match(const struct sk_buff *skbin,
enum ip_conntrack_info master_ctinfo, ctinfo;
struct nf_conn *master_conntrack, *conntrack;
- unsigned char * app_data;
+ unsigned char *app_data, *tmp_data;
unsigned int pattern_result, appdatalen;
regexp * comppattern;
@@ -466,8 +468,8 @@ match(const struct sk_buff *skbin,
master_conntrack = master_ct(master_conntrack);
/* if we've classified it or seen too many packets */
- if(total_acct_packets(master_conntrack) > num_packets ||
- master_conntrack->layer7.app_proto) {
+ if(!info->pkt && (total_acct_packets(master_conntrack) > num_packets ||
+ master_conntrack->layer7.app_proto)) {
pattern_result = match_no_append(conntrack, master_conntrack,
ctinfo, master_ctinfo, info);
@@ -500,6 +502,25 @@ match(const struct sk_buff *skbin,
/* the return value gets checked later, when we're ready to use it */
comppattern = compile_and_cache(info->pattern, info->protocol);
+ if (info->pkt) {
+ tmp_data = kmalloc(maxdatalen, GFP_ATOMIC);
+ if(!tmp_data){
+ if (net_ratelimit())
+ printk(KERN_ERR "layer7: out of memory in match, bailing.\n");
+ return info->invert;
+ }
+
+ tmp_data[0] = '\0';
+ add_datastr(tmp_data, 0, app_data, appdatalen);
+ pattern_result = ((comppattern && regexec(comppattern, tmp_data)) ? 1 : 0);
+
+ kfree(tmp_data);
+ tmp_data = NULL;
+ spin_unlock_bh(&l7_lock);
+
+ return (pattern_result ^ info->invert);
+ }
+
/* On the first packet of a connection, allocate space for app data */
if(total_acct_packets(master_conntrack) == 1 && !skb->cb[0] &&
!master_conntrack->layer7.app_data){

View file

@ -1,51 +0,0 @@
--- a/net/netfilter/xt_layer7.c
+++ b/net/netfilter/xt_layer7.c
@@ -415,7 +415,9 @@ static int layer7_write_proc(struct file
}
static bool
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 28)
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 35)
+match(const struct sk_buff *skbin, struct xt_action_param *par)
+#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 28)
match(const struct sk_buff *skbin, const struct xt_match_param *par)
#else
match(const struct sk_buff *skbin,
@@ -597,14 +599,19 @@ match(const struct sk_buff *skbin,
}
// load nf_conntrack_ipv4
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 35)
+static int
+#else
+static bool
+#endif
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 28)
-static bool check(const struct xt_mtchk_param *par)
+check(const struct xt_mtchk_param *par)
{
if (nf_ct_l3proto_try_module_get(par->match->family) < 0) {
printk(KERN_WARNING "can't load conntrack support for "
"proto=%d\n", par->match->family);
#else
-static bool check(const char *tablename, const void *inf,
+check(const char *tablename, const void *inf,
const struct xt_match *match, void *matchinfo,
unsigned int hook_mask)
{
@@ -612,9 +619,15 @@ static bool check(const char *tablename,
printk(KERN_WARNING "can't load conntrack support for "
"proto=%d\n", match->family);
#endif
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 35)
+ return -EINVAL;
+ }
+ return 0;
+#else
return 0;
}
return 1;
+#endif
}

View file

@ -1,61 +0,0 @@
--- a/net/netfilter/Kconfig
+++ b/net/netfilter/Kconfig
@@ -923,6 +923,27 @@ config NETFILTER_XT_MATCH_IPVS
If unsure, say N.
+config NETFILTER_XT_MATCH_LAYER7
+ tristate '"layer7" match support'
+ depends on EXPERIMENTAL
+ depends on NETFILTER_XTABLES
+ depends on NETFILTER_ADVANCED
+ depends on NF_CONNTRACK
+ help
+ Say Y if you want to be able to classify connections (and their
+ packets) based on regular expression matching of their application
+ layer data. This is one way to classify applications such as
+ peer-to-peer filesharing systems that do not always use the same
+ port.
+
+ To compile it as a module, choose M here. If unsure, say N.
+
+config NETFILTER_XT_MATCH_LAYER7_DEBUG
+ bool 'Layer 7 debugging output'
+ depends on NETFILTER_XT_MATCH_LAYER7
+ help
+ Say Y to get lots of debugging output.
+
config NETFILTER_XT_MATCH_LENGTH
tristate '"length" match support'
depends on NETFILTER_ADVANCED
@@ -1119,26 +1140,11 @@ config NETFILTER_XT_MATCH_STATE
To compile it as a module, choose M here. If unsure, say N.
-config NETFILTER_XT_MATCH_LAYER7
- tristate '"layer7" match support'
- depends on NETFILTER_XTABLES
- depends on EXPERIMENTAL && (IP_NF_CONNTRACK || NF_CONNTRACK)
- depends on NETFILTER_ADVANCED
- help
- Say Y if you want to be able to classify connections (and their
- packets) based on regular expression matching of their application
- layer data. This is one way to classify applications such as
- peer-to-peer filesharing systems that do not always use the same
- port.
-
- To compile it as a module, choose M here. If unsure, say N.
-
config NETFILTER_XT_MATCH_LAYER7_DEBUG
- bool 'Layer 7 debugging output'
- depends on NETFILTER_XT_MATCH_LAYER7
- help
- Say Y to get lots of debugging output.
-
+ bool 'Layer 7 debugging output'
+ depends on NETFILTER_XT_MATCH_LAYER7
+ help
+ Say Y to get lots of debugging output.
config NETFILTER_XT_MATCH_STATISTIC
tristate '"statistic" match support'

View file

@ -1,46 +0,0 @@
--- 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;

View file

@ -1,93 +0,0 @@
--- a/include/linux/netfilter_ipv4/ip_tables.h
+++ b/include/linux/netfilter_ipv4/ip_tables.h
@@ -93,6 +93,7 @@ struct ipt_ip {
#define IPT_F_FRAG 0x01 /* Set if rule is a fragment rule */
#define IPT_F_GOTO 0x02 /* Set if jump is a goto */
#define IPT_F_MASK 0x03 /* All possible flag bits mask. */
+#define IPT_F_NO_DEF_MATCH 0x80 /* Internal: no default match rules present */
/* Values for "inv" field in struct ipt_ip. */
#define IPT_INV_VIA_IN 0x01 /* Invert the sense of IN IFACE. */
--- a/net/ipv4/netfilter/ip_tables.c
+++ b/net/ipv4/netfilter/ip_tables.c
@@ -81,6 +81,9 @@ ip_packet_match(const struct iphdr *ip,
#define FWINV(bool, invflg) ((bool) ^ !!(ipinfo->invflags & (invflg)))
+ if (ipinfo->flags & IPT_F_NO_DEF_MATCH)
+ return true;
+
if (FWINV((ip->saddr&ipinfo->smsk.s_addr) != ipinfo->src.s_addr,
IPT_INV_SRCIP) ||
FWINV((ip->daddr&ipinfo->dmsk.s_addr) != ipinfo->dst.s_addr,
@@ -134,6 +137,29 @@ ip_packet_match(const struct iphdr *ip,
return true;
}
+static void
+ip_checkdefault(struct ipt_ip *ip)
+{
+ static const char iface_mask[IFNAMSIZ] = {};
+
+ if (ip->invflags || ip->flags & IPT_F_FRAG)
+ return;
+
+ if (memcmp(ip->iniface_mask, iface_mask, IFNAMSIZ) != 0)
+ return;
+
+ if (memcmp(ip->outiface_mask, iface_mask, IFNAMSIZ) != 0)
+ return;
+
+ if (ip->smsk.s_addr || ip->dmsk.s_addr)
+ return;
+
+ if (ip->proto)
+ return;
+
+ ip->flags |= IPT_F_NO_DEF_MATCH;
+}
+
static bool
ip_checkentry(const struct ipt_ip *ip)
{
@@ -560,7 +586,7 @@ static void cleanup_match(struct xt_entr
}
static int
-check_entry(const struct ipt_entry *e, const char *name)
+check_entry(struct ipt_entry *e, const char *name)
{
const struct xt_entry_target *t;
@@ -569,6 +595,8 @@ check_entry(const struct ipt_entry *e, c
return -EINVAL;
}
+ ip_checkdefault(&e->ip);
+
if (e->target_offset + sizeof(struct xt_entry_target) >
e->next_offset)
return -EINVAL;
@@ -930,6 +958,7 @@ copy_entries_to_user(unsigned int total_
const struct xt_table_info *private = table->private;
int ret = 0;
const void *loc_cpu_entry;
+ u8 flags;
counters = alloc_counters(table);
if (IS_ERR(counters))
@@ -960,6 +989,14 @@ copy_entries_to_user(unsigned int total_
ret = -EFAULT;
goto free_counters;
}
+
+ flags = e->ip.flags & IPT_F_MASK;
+ if (copy_to_user(userptr + off
+ + offsetof(struct ipt_entry, ip.flags),
+ &flags, sizeof(flags)) != 0) {
+ ret = -EFAULT;
+ goto free_counters;
+ }
for (i = sizeof(struct ipt_entry);
i < e->target_offset;

View file

@ -1,81 +0,0 @@
--- a/net/ipv4/netfilter/ip_tables.c
+++ b/net/ipv4/netfilter/ip_tables.c
@@ -309,6 +309,33 @@ struct ipt_entry *ipt_next_entry(const s
return (void *)entry + entry->next_offset;
}
+static bool
+ipt_handle_default_rule(struct ipt_entry *e, unsigned int *verdict)
+{
+ struct xt_entry_target *t;
+ struct xt_standard_target *st;
+
+ if (e->target_offset != sizeof(struct ipt_entry))
+ return false;
+
+ if (!(e->ip.flags & IPT_F_NO_DEF_MATCH))
+ return false;
+
+ t = ipt_get_target(e);
+ if (t->u.kernel.target->target)
+ return false;
+
+ st = (struct xt_standard_target *) t;
+ if (st->verdict == XT_RETURN)
+ return false;
+
+ if (st->verdict >= 0)
+ return false;
+
+ *verdict = (unsigned)(-st->verdict) - 1;
+ return true;
+}
+
/* Returns one of the generic firewall policies, like NF_ACCEPT. */
unsigned int
ipt_do_table(struct sk_buff *skb,
@@ -333,6 +360,25 @@ ipt_do_table(struct sk_buff *skb,
ip = ip_hdr(skb);
indev = in ? in->name : nulldevname;
outdev = out ? out->name : nulldevname;
+
+ IP_NF_ASSERT(table->valid_hooks & (1 << hook));
+ local_bh_disable();
+ addend = xt_write_recseq_begin();
+ private = table->private;
+ cpu = smp_processor_id();
+ table_base = private->entries[cpu];
+ jumpstack = (struct ipt_entry **)private->jumpstack[cpu];
+ stackptr = per_cpu_ptr(private->stackptr, cpu);
+ origptr = *stackptr;
+
+ e = get_entry(table_base, private->hook_entry[hook]);
+ if (ipt_handle_default_rule(e, &verdict)) {
+ ADD_COUNTER(e->counters, skb->len, 1);
+ xt_write_recseq_end(addend);
+ local_bh_enable();
+ return verdict;
+ }
+
/* We handle fragments by dealing with the first fragment as
* if it was a normal packet. All other fragments are treated
* normally, except that they will NEVER match rules that ask
@@ -347,18 +393,6 @@ ipt_do_table(struct sk_buff *skb,
acpar.family = NFPROTO_IPV4;
acpar.hooknum = hook;
- IP_NF_ASSERT(table->valid_hooks & (1 << hook));
- local_bh_disable();
- addend = xt_write_recseq_begin();
- private = table->private;
- cpu = smp_processor_id();
- table_base = private->entries[cpu];
- jumpstack = (struct ipt_entry **)private->jumpstack[cpu];
- stackptr = per_cpu_ptr(private->stackptr, cpu);
- origptr = *stackptr;
-
- e = get_entry(table_base, private->hook_entry[hook]);
-
pr_debug("Entering %s(hook %u); sp at %u (UF %p)\n",
table->name, hook, origptr,
get_entry(table_base, private->underflow[hook]));

View file

@ -1,16 +0,0 @@
--- a/net/ipv4/netfilter/ip_tables.c
+++ b/net/ipv4/netfilter/ip_tables.c
@@ -84,9 +84,11 @@ ip_packet_match(const struct iphdr *ip,
if (ipinfo->flags & IPT_F_NO_DEF_MATCH)
return true;
- if (FWINV((ip->saddr&ipinfo->smsk.s_addr) != ipinfo->src.s_addr,
+ if (FWINV(ipinfo->smsk.s_addr &&
+ (ip->saddr&ipinfo->smsk.s_addr) != ipinfo->src.s_addr,
IPT_INV_SRCIP) ||
- FWINV((ip->daddr&ipinfo->dmsk.s_addr) != ipinfo->dst.s_addr,
+ FWINV(ipinfo->dmsk.s_addr &&
+ (ip->daddr&ipinfo->dmsk.s_addr) != ipinfo->dst.s_addr,
IPT_INV_DSTIP)) {
dprintf("Source or dest mismatch.\n");

Some files were not shown because too many files have changed in this diff Show more