linux/3.0: R.I.P.
It is used by the broken omap35xx/gumstix target only. git-svn-id: svn://svn.openwrt.org/openwrt/trunk@31717 3c298f89-4303-0410-b956-a3cf2f4a3e73master
parent
bd604be582
commit
9391118ede
File diff suppressed because it is too large
Load Diff
|
@ -1,31 +0,0 @@
|
||||||
checkpatch.pl warns about using __attribute__((packed)) in kernel
|
|
||||||
headers: "__packed is preferred over __attribute__((packed))". If one
|
|
||||||
follows that advice it could cause problems in the exported header
|
|
||||||
files, because the outside world doesn't know about this shortcut.
|
|
||||||
|
|
||||||
For example busybox will fail to compile:
|
|
||||||
CC miscutils/ubi_attach_detach.o
|
|
||||||
In file included from miscutils/ubi_attach_detach.c:27:0:
|
|
||||||
/usr/include/mtd/ubi-user.h:330:3: error: conflicting types for ‘__packed’
|
|
||||||
/usr/include/mtd/ubi-user.h:314:3: note: previous declaration of ‘__packed’ was here
|
|
||||||
...
|
|
||||||
|
|
||||||
Fix the problem by substituting __packed with __attribute__((packed)) in
|
|
||||||
the header_install.pl script.
|
|
||||||
|
|
||||||
Cc: Artem Bityutskiy <Artem.Bityutskiy@nokia.com>
|
|
||||||
CC: Joe Perches <joe@perches.com>
|
|
||||||
Signed-off-by: Markus Trippelsdorf <markus@trippelsdorf.de>
|
|
||||||
---
|
|
||||||
scripts/headers_install.pl | 1 +
|
|
||||||
1 files changed, 1 insertions(+), 0 deletions(-)
|
|
||||||
--- a/scripts/headers_install.pl
|
|
||||||
+++ b/scripts/headers_install.pl
|
|
||||||
@@ -35,6 +35,7 @@ foreach my $file (@files) {
|
|
||||||
$line =~ s/([\s(])__iomem\s/$1/g;
|
|
||||||
$line =~ s/\s__attribute_const__\s/ /g;
|
|
||||||
$line =~ s/\s__attribute_const__$//g;
|
|
||||||
+ $line =~ s/\b__packed\b/__attribute__((packed))/g;
|
|
||||||
$line =~ s/^#include <linux\/compiler.h>//;
|
|
||||||
$line =~ s/(^|\s)(inline)\b/$1__$2__/g;
|
|
||||||
$line =~ s/(^|\s)(asm)\b(\s|[(]|$)/$1__$2__$3/g;
|
|
|
@ -1,93 +0,0 @@
|
||||||
From 2d303b4683145f7dbc918bd14d04e1396581b2ce Mon Sep 17 00:00:00 2001
|
|
||||||
From: Imre Kaloz <kaloz@openwrt.org>
|
|
||||||
Date: Thu, 7 Jul 2011 12:05:21 +0200
|
|
||||||
Subject: [PATCH] ARM: support XZ compressed kernels
|
|
||||||
|
|
||||||
Wire up support for the XZ decompressor
|
|
||||||
|
|
||||||
Signed-off-by: Imre Kaloz <kaloz@openwrt.org>
|
|
||||||
---
|
|
||||||
arch/arm/Kconfig | 1 +
|
|
||||||
arch/arm/boot/compressed/Makefile | 11 +++++++++--
|
|
||||||
arch/arm/boot/compressed/decompress.c | 4 ++++
|
|
||||||
arch/arm/boot/compressed/piggy.xzkern.S | 6 ++++++
|
|
||||||
lib/xz/xz_dec_stream.c | 1 +
|
|
||||||
5 files changed, 21 insertions(+), 2 deletions(-)
|
|
||||||
create mode 100644 arch/arm/boot/compressed/piggy.xzkern.S
|
|
||||||
|
|
||||||
--- a/arch/arm/Kconfig
|
|
||||||
+++ b/arch/arm/Kconfig
|
|
||||||
@@ -20,6 +20,7 @@ config ARM
|
|
||||||
select HAVE_KERNEL_GZIP
|
|
||||||
select HAVE_KERNEL_LZO
|
|
||||||
select HAVE_KERNEL_LZMA
|
|
||||||
+ select HAVE_KERNEL_XZ
|
|
||||||
select HAVE_IRQ_WORK
|
|
||||||
select HAVE_PERF_EVENTS
|
|
||||||
select PERF_USE_VMALLOC
|
|
||||||
--- a/arch/arm/boot/compressed/Makefile
|
|
||||||
+++ b/arch/arm/boot/compressed/Makefile
|
|
||||||
@@ -82,13 +82,14 @@ SEDFLAGS = s/TEXT_START/$(ZTEXTADDR)/;s/
|
|
||||||
suffix_$(CONFIG_KERNEL_GZIP) = gzip
|
|
||||||
suffix_$(CONFIG_KERNEL_LZO) = lzo
|
|
||||||
suffix_$(CONFIG_KERNEL_LZMA) = lzma
|
|
||||||
+suffix_$(CONFIG_KERNEL_XZ) = xzkern
|
|
||||||
|
|
||||||
targets := vmlinux vmlinux.lds \
|
|
||||||
piggy.$(suffix_y) piggy.$(suffix_y).o \
|
|
||||||
font.o font.c head.o misc.o $(OBJS)
|
|
||||||
|
|
||||||
# Make sure files are removed during clean
|
|
||||||
-extra-y += piggy.gzip piggy.lzo piggy.lzma lib1funcs.S
|
|
||||||
+extra-y += piggy.gzip piggy.lzo piggy.lzma piggy.xzkern lib1funcs.S ashldi3.S
|
|
||||||
|
|
||||||
ifeq ($(CONFIG_FUNCTION_TRACER),y)
|
|
||||||
ORIG_CFLAGS := $(KBUILD_CFLAGS)
|
|
||||||
@@ -133,8 +134,14 @@ bad_syms=$$($(CROSS_COMPILE)nm $@ | sed
|
|
||||||
( echo "following symbols must have non local/private scope:" >&2; \
|
|
||||||
echo "$$bad_syms" >&2; rm -f $@; false )
|
|
||||||
|
|
||||||
+# For __aeabi_llsl
|
|
||||||
+ashldi3 = $(obj)/ashldi3.o
|
|
||||||
+
|
|
||||||
+$(obj)/ashldi3.S: $(srctree)/arch/$(SRCARCH)/lib/ashldi3.S FORCE
|
|
||||||
+ $(call cmd,shipped)
|
|
||||||
+
|
|
||||||
$(obj)/vmlinux: $(obj)/vmlinux.lds $(obj)/$(HEAD) $(obj)/piggy.$(suffix_y).o \
|
|
||||||
- $(addprefix $(obj)/, $(OBJS)) $(lib1funcs) FORCE
|
|
||||||
+ $(addprefix $(obj)/, $(OBJS)) $(lib1funcs) $(ashldi3) FORCE
|
|
||||||
$(call if_changed,ld)
|
|
||||||
@$(check_for_bad_syms)
|
|
||||||
|
|
||||||
--- a/arch/arm/boot/compressed/decompress.c
|
|
||||||
+++ b/arch/arm/boot/compressed/decompress.c
|
|
||||||
@@ -44,6 +44,10 @@ extern void error(char *);
|
|
||||||
#include "../../../../lib/decompress_unlzma.c"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
+#ifdef CONFIG_KERNEL_XZ
|
|
||||||
+#include "../../../../lib/decompress_unxz.c"
|
|
||||||
+#endif
|
|
||||||
+
|
|
||||||
int do_decompress(u8 *input, int len, u8 *output, void (*error)(char *x))
|
|
||||||
{
|
|
||||||
return decompress(input, len, NULL, NULL, output, NULL, error);
|
|
||||||
--- /dev/null
|
|
||||||
+++ b/arch/arm/boot/compressed/piggy.xzkern.S
|
|
||||||
@@ -0,0 +1,6 @@
|
|
||||||
+ .section .piggydata,#alloc
|
|
||||||
+ .globl input_data
|
|
||||||
+input_data:
|
|
||||||
+ .incbin "arch/arm/boot/compressed/piggy.xzkern"
|
|
||||||
+ .globl input_data_end
|
|
||||||
+input_data_end:
|
|
||||||
--- a/lib/xz/xz_dec_stream.c
|
|
||||||
+++ b/lib/xz/xz_dec_stream.c
|
|
||||||
@@ -9,6 +9,7 @@
|
|
||||||
|
|
||||||
#include "xz_private.h"
|
|
||||||
#include "xz_stream.h"
|
|
||||||
+#include <linux/kernel.h>
|
|
||||||
|
|
||||||
/* Hash used to validate the Index field */
|
|
||||||
struct xz_dec_hash {
|
|
|
@ -1,61 +0,0 @@
|
||||||
--- a/arch/mips/include/asm/unistd.h
|
|
||||||
+++ b/arch/mips/include/asm/unistd.h
|
|
||||||
@@ -363,17 +363,18 @@
|
|
||||||
#define __NR_open_by_handle_at (__NR_Linux + 340)
|
|
||||||
#define __NR_clock_adjtime (__NR_Linux + 341)
|
|
||||||
#define __NR_syncfs (__NR_Linux + 342)
|
|
||||||
-#define __NR_setns (__NR_Linux + 343)
|
|
||||||
+#define __NR_sendmmsg (__NR_Linux + 343)
|
|
||||||
+#define __NR_setns (__NR_Linux + 344)
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Offset of the last Linux o32 flavoured syscall
|
|
||||||
*/
|
|
||||||
-#define __NR_Linux_syscalls 343
|
|
||||||
+#define __NR_Linux_syscalls 344
|
|
||||||
|
|
||||||
#endif /* _MIPS_SIM == _MIPS_SIM_ABI32 */
|
|
||||||
|
|
||||||
#define __NR_O32_Linux 4000
|
|
||||||
-#define __NR_O32_Linux_syscalls 343
|
|
||||||
+#define __NR_O32_Linux_syscalls 344
|
|
||||||
|
|
||||||
#if _MIPS_SIM == _MIPS_SIM_ABI64
|
|
||||||
|
|
||||||
--- a/arch/mips/kernel/scall32-o32.S
|
|
||||||
+++ b/arch/mips/kernel/scall32-o32.S
|
|
||||||
@@ -589,6 +589,7 @@ einval: li v0, -ENOSYS
|
|
||||||
sys sys_open_by_handle_at 3 /* 4340 */
|
|
||||||
sys sys_clock_adjtime 2
|
|
||||||
sys sys_syncfs 1
|
|
||||||
+ sys sys_sendmmsg 4
|
|
||||||
sys sys_setns 2
|
|
||||||
.endm
|
|
||||||
|
|
||||||
--- a/arch/mips/kernel/scall64-64.S
|
|
||||||
+++ b/arch/mips/kernel/scall64-64.S
|
|
||||||
@@ -428,5 +428,6 @@ sys_call_table:
|
|
||||||
PTR sys_open_by_handle_at
|
|
||||||
PTR sys_clock_adjtime /* 5300 */
|
|
||||||
PTR sys_syncfs
|
|
||||||
+ PTR sys_sendmmsg
|
|
||||||
PTR sys_setns
|
|
||||||
.size sys_call_table,.-sys_call_table
|
|
||||||
--- a/arch/mips/kernel/scall64-n32.S
|
|
||||||
+++ b/arch/mips/kernel/scall64-n32.S
|
|
||||||
@@ -428,5 +428,6 @@ EXPORT(sysn32_call_table)
|
|
||||||
PTR sys_open_by_handle_at
|
|
||||||
PTR compat_sys_clock_adjtime /* 6305 */
|
|
||||||
PTR sys_syncfs
|
|
||||||
+ PTR compat_sys_sendmmsg
|
|
||||||
PTR sys_setns
|
|
||||||
.size sysn32_call_table,.-sysn32_call_table
|
|
||||||
--- a/arch/mips/kernel/scall64-o32.S
|
|
||||||
+++ b/arch/mips/kernel/scall64-o32.S
|
|
||||||
@@ -546,5 +546,6 @@ sys_call_table:
|
|
||||||
PTR compat_sys_open_by_handle_at /* 4340 */
|
|
||||||
PTR compat_sys_clock_adjtime
|
|
||||||
PTR sys_syncfs
|
|
||||||
+ PTR compat_sys_sendmmsg
|
|
||||||
PTR sys_setns
|
|
||||||
.size sys_call_table,.-sys_call_table
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,11 +0,0 @@
|
||||||
--- a/drivers/ssb/b43_pci_bridge.c
|
|
||||||
+++ b/drivers/ssb/b43_pci_bridge.c
|
|
||||||
@@ -29,6 +29,8 @@ static const struct pci_device_id b43_pc
|
|
||||||
{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4319) },
|
|
||||||
{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4320) },
|
|
||||||
{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4321) },
|
|
||||||
+ { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4322) },
|
|
||||||
+ { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 43222) },
|
|
||||||
{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4324) },
|
|
||||||
{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4325) },
|
|
||||||
{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4328) },
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,277 +0,0 @@
|
||||||
From: Nathan Williams <nathan@traverse.com.au>
|
|
||||||
To: netdev@vger.kernel.org
|
|
||||||
Date: Wed, 05 Oct 2011 15:43:30 +1100
|
|
||||||
Cc: linux-atm-general@lists.sourceforge.net,
|
|
||||||
David Woodhouse <dwmw2@infradead.org>, linux-kernel@vger.kernel.org
|
|
||||||
Subject: [Linux-ATM-General] [PATCH 1/4] atm: solos-pci: Add AnnexA/M
|
|
||||||
capability attributes
|
|
||||||
|
|
||||||
BisACapability and BisMCapability allow users to
|
|
||||||
force either Annex A or Annex M.
|
|
||||||
|
|
||||||
Signed-off-by: Nathan Williams <nathan@traverse.com.au>
|
|
||||||
---
|
|
||||||
drivers/atm/solos-attrlist.c | 2 ++
|
|
||||||
1 files changed, 2 insertions(+), 0 deletions(-)
|
|
||||||
|
|
||||||
--- a/drivers/atm/solos-attrlist.c
|
|
||||||
+++ b/drivers/atm/solos-attrlist.c
|
|
||||||
@@ -71,6 +71,8 @@ SOLOS_ATTR_RW(BisAForceSNRMarginDn)
|
|
||||||
SOLOS_ATTR_RW(BisMForceSNRMarginDn)
|
|
||||||
SOLOS_ATTR_RW(BisAMaxMargin)
|
|
||||||
SOLOS_ATTR_RW(BisMMaxMargin)
|
|
||||||
+SOLOS_ATTR_RW(BisACapability)
|
|
||||||
+SOLOS_ATTR_RW(BisMCapability)
|
|
||||||
SOLOS_ATTR_RW(AnnexAForceSNRMarginDn)
|
|
||||||
SOLOS_ATTR_RW(AnnexAMaxMargin)
|
|
||||||
SOLOS_ATTR_RW(AnnexMMaxMargin)
|
|
||||||
--- 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.0"
|
|
||||||
+#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))
|
|
||||||
@@ -127,6 +133,7 @@ struct solos_card {
|
|
||||||
int using_dma;
|
|
||||||
int fpga_version;
|
|
||||||
int buffer_size;
|
|
||||||
+ int atmel_flash;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
@@ -452,7 +459,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 +505,87 @@ static ssize_t console_store(struct devi
|
|
||||||
return err?:count;
|
|
||||||
}
|
|
||||||
|
|
||||||
+struct geos_gpio {
|
|
||||||
+ char *name;
|
|
||||||
+ int offset;
|
|
||||||
+};
|
|
||||||
+
|
|
||||||
+static struct geos_gpio geos_gpio_pins[] = {
|
|
||||||
+ {"GPIO1", 9},
|
|
||||||
+ {"GPIO2", 10},
|
|
||||||
+ {"GPIO3", 11},
|
|
||||||
+ {"GPIO4", 12},
|
|
||||||
+ {"GPIO5", 13},
|
|
||||||
+ {"PushButton", 14},
|
|
||||||
+ {NULL, 0}
|
|
||||||
+};
|
|
||||||
+
|
|
||||||
+static ssize_t geos_gpio_store(struct device *dev, struct device_attribute *attr,
|
|
||||||
+ const char *buf, size_t count)
|
|
||||||
+{
|
|
||||||
+ struct atm_dev *atmdev = container_of(dev, struct atm_dev, class_dev);
|
|
||||||
+ struct solos_card *card = atmdev->dev_data;
|
|
||||||
+ uint32_t data32;
|
|
||||||
+
|
|
||||||
+ struct geos_gpio *p = geos_gpio_pins;
|
|
||||||
+ while(p->name){
|
|
||||||
+ if(!strcmp(attr->attr.name, p->name)){
|
|
||||||
+ break;
|
|
||||||
+ }
|
|
||||||
+ p++;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ data32 = ioread32(card->config_regs + GPIO_STATUS);
|
|
||||||
+ if(buf[0] == '1'){
|
|
||||||
+ data32 |= 1 << p->offset;
|
|
||||||
+ iowrite32(data32, card->config_regs + GPIO_STATUS);
|
|
||||||
+ } else if(buf[0] == '0') {
|
|
||||||
+ data32 &= ~(1 << p->offset);
|
|
||||||
+ iowrite32(data32, card->config_regs + GPIO_STATUS);
|
|
||||||
+ }
|
|
||||||
+ return count;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static ssize_t geos_gpio_show(struct device *dev, struct device_attribute *attr,
|
|
||||||
+ char *buf)
|
|
||||||
+{
|
|
||||||
+ struct atm_dev *atmdev = container_of(dev, struct atm_dev, class_dev);
|
|
||||||
+ struct solos_card *card = atmdev->dev_data;
|
|
||||||
+ uint32_t data32;
|
|
||||||
+
|
|
||||||
+ struct geos_gpio *p = geos_gpio_pins;
|
|
||||||
+ while(p->name){
|
|
||||||
+ if(!strcmp(attr->attr.name, p->name)){
|
|
||||||
+ break;
|
|
||||||
+ }
|
|
||||||
+ p++;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ data32 = ioread32(card->config_regs + GPIO_STATUS);
|
|
||||||
+ data32 = (data32 >> p->offset) & 1;
|
|
||||||
+
|
|
||||||
+ return sprintf(buf, "%d\n", data32);
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static ssize_t hardware_show(struct device *dev, struct device_attribute *attr,
|
|
||||||
+ char *buf)
|
|
||||||
+{
|
|
||||||
+ struct atm_dev *atmdev = container_of(dev, struct atm_dev, class_dev);
|
|
||||||
+ struct solos_card *card = atmdev->dev_data;
|
|
||||||
+ uint32_t data32;
|
|
||||||
+
|
|
||||||
+ data32 = ioread32(card->config_regs + GPIO_STATUS);
|
|
||||||
+ if(!strcmp(attr->attr.name, "HardwareVersion")){
|
|
||||||
+ data32 = data32 & 0x1F;
|
|
||||||
+ return sprintf(buf, "%d\n", data32);
|
|
||||||
+ } else if(!strcmp(attr->attr.name, "HardwareVariant")){
|
|
||||||
+ data32 = (data32 >> 5) & 0x0F;
|
|
||||||
+ return sprintf(buf, "%d\n", data32);
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ return sprintf(buf, "Error\n");
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
static DEVICE_ATTR(console, 0644, console_show, console_store);
|
|
||||||
|
|
||||||
|
|
||||||
@@ -507,6 +594,14 @@ static DEVICE_ATTR(console, 0644, consol
|
|
||||||
|
|
||||||
#include "solos-attrlist.c"
|
|
||||||
|
|
||||||
+static DEVICE_ATTR(GPIO1, 0644, geos_gpio_show, geos_gpio_store);
|
|
||||||
+static DEVICE_ATTR(GPIO2, 0644, geos_gpio_show, geos_gpio_store);
|
|
||||||
+static DEVICE_ATTR(GPIO3, 0644, geos_gpio_show, geos_gpio_store);
|
|
||||||
+static DEVICE_ATTR(GPIO4, 0644, geos_gpio_show, geos_gpio_store);
|
|
||||||
+static DEVICE_ATTR(GPIO5, 0644, geos_gpio_show, geos_gpio_store);
|
|
||||||
+static DEVICE_ATTR(PushButton, 0444, geos_gpio_show, NULL);
|
|
||||||
+static DEVICE_ATTR(HardwareVersion, 0444, hardware_show, NULL);
|
|
||||||
+static DEVICE_ATTR(HardwareVariant, 0444, hardware_show, NULL);
|
|
||||||
#undef SOLOS_ATTR_RO
|
|
||||||
#undef SOLOS_ATTR_RW
|
|
||||||
|
|
||||||
@@ -515,6 +610,14 @@ static DEVICE_ATTR(console, 0644, consol
|
|
||||||
|
|
||||||
static struct attribute *solos_attrs[] = {
|
|
||||||
#include "solos-attrlist.c"
|
|
||||||
+ &dev_attr_GPIO1.attr,
|
|
||||||
+ &dev_attr_GPIO2.attr,
|
|
||||||
+ &dev_attr_GPIO3.attr,
|
|
||||||
+ &dev_attr_GPIO4.attr,
|
|
||||||
+ &dev_attr_GPIO5.attr,
|
|
||||||
+ &dev_attr_PushButton.attr,
|
|
||||||
+ &dev_attr_HardwareVersion.attr,
|
|
||||||
+ &dev_attr_HardwareVariant.attr,
|
|
||||||
NULL
|
|
||||||
};
|
|
||||||
|
|
||||||
@@ -534,16 +637,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 +665,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");
|
|
||||||
@@ -598,9 +713,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
|
|
||||||
@@ -1152,6 +1271,11 @@ 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;
|
|
||||||
if (card->fpga_version >= DMA_SUPPORTED){
|
|
||||||
card->using_dma = 1;
|
|
||||||
} else {
|
|
||||||
@@ -1159,6 +1283,8 @@ static int fpga_probe(struct pci_dev *de
|
|
||||||
/* Set RX empty flag for all ports */
|
|
||||||
iowrite32(0xF0, card->config_regs + FLAGS_ADDR);
|
|
||||||
}
|
|
||||||
+ /* New FPGAs require driver version before permitting flash upgrades */
|
|
||||||
+ iowrite32(DRIVER_VERSION, card->config_regs + DRIVER_VER);
|
|
||||||
|
|
||||||
data32 = ioread32(card->config_regs + PORTS);
|
|
||||||
card->nr_ports = (data32 & 0x000000FF);
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,13 +0,0 @@
|
||||||
--- a/tools/perf/arch/arm/util/dwarf-regs.c
|
|
||||||
+++ b/tools/perf/arch/arm/util/dwarf-regs.c
|
|
||||||
@@ -8,7 +8,10 @@
|
|
||||||
* published by the Free Software Foundation.
|
|
||||||
*/
|
|
||||||
|
|
||||||
+#include <stdlib.h>
|
|
||||||
+#ifndef __UCLIBC__
|
|
||||||
#include <libio.h>
|
|
||||||
+#endif
|
|
||||||
#include <dwarf-regs.h>
|
|
||||||
|
|
||||||
struct pt_regs_dwarfnum {
|
|
|
@ -1,41 +0,0 @@
|
||||||
--- a/drivers/usb/host/ehci-hcd.c
|
|
||||||
+++ b/drivers/usb/host/ehci-hcd.c
|
|
||||||
@@ -746,7 +746,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
|
|
||||||
@@ -655,7 +655,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;
|
|
||||||
@@ -880,7 +880,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
|
|
||||||
@@ -138,6 +138,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)
|
|
|
@ -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;
|
|
|
@ -1,11 +0,0 @@
|
||||||
--- a/scripts/setlocalversion
|
|
||||||
+++ b/scripts/setlocalversion
|
|
||||||
@@ -168,7 +168,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
|
|
|
@ -1,24 +0,0 @@
|
||||||
--- a/Makefile
|
|
||||||
+++ b/Makefile
|
|
||||||
@@ -559,9 +559,9 @@ endif # $(dot-config)
|
|
||||||
all: vmlinux
|
|
||||||
|
|
||||||
ifdef CONFIG_CC_OPTIMIZE_FOR_SIZE
|
|
||||||
-KBUILD_CFLAGS += -Os
|
|
||||||
+KBUILD_CFLAGS += -Os -fno-caller-saves
|
|
||||||
else
|
|
||||||
-KBUILD_CFLAGS += -O2
|
|
||||||
+KBUILD_CFLAGS += -O2 -fno-reorder-blocks -fno-tree-ch -fno-caller-saves
|
|
||||||
endif
|
|
||||||
|
|
||||||
include $(srctree)/arch/$(SRCARCH)/Makefile
|
|
||||||
@@ -620,6 +620,9 @@ endif
|
|
||||||
NOSTDINC_FLAGS += -nostdinc -isystem $(shell $(CC) -print-file-name=include)
|
|
||||||
CHECKFLAGS += $(NOSTDINC_FLAGS)
|
|
||||||
|
|
||||||
+# improve gcc optimization
|
|
||||||
+CFLAGS += $(call cc-option,-funit-at-a-time,)
|
|
||||||
+
|
|
||||||
# warn about C99 declaration after statement
|
|
||||||
KBUILD_CFLAGS += $(call cc-option,-Wdeclaration-after-statement,)
|
|
||||||
|
|
|
@ -1,78 +0,0 @@
|
||||||
--- a/scripts/kallsyms.c
|
|
||||||
+++ b/scripts/kallsyms.c
|
|
||||||
@@ -22,6 +22,35 @@
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <ctype.h>
|
|
||||||
+#ifdef __APPLE__
|
|
||||||
+/* Darwin has no memmem implementation, this one is ripped of the uClibc-0.9.28 source */
|
|
||||||
+void *memmem (const void *haystack, size_t haystack_len,
|
|
||||||
+ const void *needle, size_t needle_len)
|
|
||||||
+{
|
|
||||||
+ const char *begin;
|
|
||||||
+ const char *const last_possible
|
|
||||||
+ = (const char *) haystack + haystack_len - needle_len;
|
|
||||||
+
|
|
||||||
+ if (needle_len == 0)
|
|
||||||
+ /* The first occurrence of the empty string is deemed to occur at
|
|
||||||
+ the beginning of the string. */
|
|
||||||
+ return (void *) haystack;
|
|
||||||
+
|
|
||||||
+ /* Sanity check, otherwise the loop might search through the whole
|
|
||||||
+ memory. */
|
|
||||||
+ if (__builtin_expect (haystack_len < needle_len, 0))
|
|
||||||
+ return NULL;
|
|
||||||
+
|
|
||||||
+ for (begin = (const char *) haystack; begin <= last_possible; ++begin)
|
|
||||||
+ if (begin[0] == ((const char *) needle)[0] &&
|
|
||||||
+ !memcmp ((const void *) &begin[1],
|
|
||||||
+ (const void *) ((const char *) needle + 1),
|
|
||||||
+ needle_len - 1))
|
|
||||||
+ return (void *) begin;
|
|
||||||
+
|
|
||||||
+ return NULL;
|
|
||||||
+}
|
|
||||||
+#endif
|
|
||||||
|
|
||||||
#ifndef ARRAY_SIZE
|
|
||||||
#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof(arr[0]))
|
|
||||||
--- a/scripts/kconfig/Makefile
|
|
||||||
+++ b/scripts/kconfig/Makefile
|
|
||||||
@@ -148,6 +148,9 @@ check-lxdialog := $(srctree)/$(src)/lxd
|
|
||||||
# we really need to do so. (Do not call gcc as part of make mrproper)
|
|
||||||
HOST_EXTRACFLAGS += $(shell $(CONFIG_SHELL) $(check-lxdialog) -ccflags) \
|
|
||||||
-DLOCALE
|
|
||||||
+ifeq ($(shell uname -s),Darwin)
|
|
||||||
+HOST_LOADLIBES += -lncurses
|
|
||||||
+endif
|
|
||||||
|
|
||||||
# ===========================================================================
|
|
||||||
# Shared Makefile for the various kconfig executables:
|
|
||||||
--- a/scripts/mod/mk_elfconfig.c
|
|
||||||
+++ b/scripts/mod/mk_elfconfig.c
|
|
||||||
@@ -1,7 +1,11 @@
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
+#ifndef __APPLE__
|
|
||||||
#include <elf.h>
|
|
||||||
+#else
|
|
||||||
+#include "../../../../../tools/sstrip/include/elf.h"
|
|
||||||
+#endif
|
|
||||||
|
|
||||||
int
|
|
||||||
main(int argc, char **argv)
|
|
||||||
--- a/scripts/mod/modpost.h
|
|
||||||
+++ b/scripts/mod/modpost.h
|
|
||||||
@@ -7,7 +7,11 @@
|
|
||||||
#include <sys/mman.h>
|
|
||||||
#include <fcntl.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
+#if !(defined(__APPLE__) || defined(__CYGWIN__))
|
|
||||||
#include <elf.h>
|
|
||||||
+#else
|
|
||||||
+#include "../../../../../tools/sstrip/include/elf.h"
|
|
||||||
+#endif
|
|
||||||
|
|
||||||
#include "elfconfig.h"
|
|
||||||
|
|
|
@ -1,17 +0,0 @@
|
||||||
--- a/include/linux/stddef.h
|
|
||||||
+++ b/include/linux/stddef.h
|
|
||||||
@@ -16,6 +16,7 @@ enum {
|
|
||||||
false = 0,
|
|
||||||
true = 1
|
|
||||||
};
|
|
||||||
+#endif /* __KERNEL__ */
|
|
||||||
|
|
||||||
#undef offsetof
|
|
||||||
#ifdef __compiler_offsetof
|
|
||||||
@@ -23,6 +24,5 @@ enum {
|
|
||||||
#else
|
|
||||||
#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
|
|
||||||
#endif
|
|
||||||
-#endif /* __KERNEL__ */
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -1,89 +0,0 @@
|
||||||
--- a/include/asm-generic/vmlinux.lds.h
|
|
||||||
+++ b/include/asm-generic/vmlinux.lds.h
|
|
||||||
@@ -52,6 +52,27 @@
|
|
||||||
#define LOAD_OFFSET 0
|
|
||||||
#endif
|
|
||||||
|
|
||||||
+#ifndef SYMTAB_KEEP_STR
|
|
||||||
+#define SYMTAB_KEEP_STR *(__ksymtab_strings+*)
|
|
||||||
+#define SYMTAB_DISCARD_STR
|
|
||||||
+#else
|
|
||||||
+#define SYMTAB_DISCARD_STR *(__ksymtab_strings+*)
|
|
||||||
+#endif
|
|
||||||
+
|
|
||||||
+#ifndef SYMTAB_KEEP
|
|
||||||
+#define SYMTAB_KEEP *(SORT(___ksymtab+*))
|
|
||||||
+#define SYMTAB_DISCARD
|
|
||||||
+#else
|
|
||||||
+#define SYMTAB_DISCARD *(SORT(___ksymtab+*))
|
|
||||||
+#endif
|
|
||||||
+
|
|
||||||
+#ifndef SYMTAB_KEEP_GPL
|
|
||||||
+#define SYMTAB_KEEP_GPL *(SORT(___ksymtab_gpl+*))
|
|
||||||
+#define SYMTAB_DISCARD_GPL
|
|
||||||
+#else
|
|
||||||
+#define SYMTAB_DISCARD_GPL *(SORT(___ksymtab_gpl+*))
|
|
||||||
+#endif
|
|
||||||
+
|
|
||||||
#ifndef SYMBOL_PREFIX
|
|
||||||
#define VMLINUX_SYMBOL(sym) sym
|
|
||||||
#else
|
|
||||||
@@ -276,14 +297,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 +366,7 @@
|
|
||||||
\
|
|
||||||
/* Kernel symbol table: strings */ \
|
|
||||||
__ksymtab_strings : AT(ADDR(__ksymtab_strings) - LOAD_OFFSET) { \
|
|
||||||
- *(__ksymtab_strings) \
|
|
||||||
+ SYMTAB_KEEP_STR \
|
|
||||||
} \
|
|
||||||
\
|
|
||||||
/* __*init sections */ \
|
|
||||||
@@ -677,6 +698,9 @@
|
|
||||||
EXIT_TEXT \
|
|
||||||
EXIT_DATA \
|
|
||||||
EXIT_CALL \
|
|
||||||
+ SYMTAB_DISCARD \
|
|
||||||
+ SYMTAB_DISCARD_GPL \
|
|
||||||
+ SYMTAB_DISCARD_STR \
|
|
||||||
*(.discard) \
|
|
||||||
*(.discard.*) \
|
|
||||||
}
|
|
||||||
--- a/include/linux/module.h
|
|
||||||
+++ b/include/linux/module.h
|
|
||||||
@@ -230,12 +230,19 @@ struct module_use {
|
|
||||||
#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 \
|
|
|
@ -1,54 +0,0 @@
|
||||||
--- a/scripts/Makefile.lib
|
|
||||||
+++ b/scripts/Makefile.lib
|
|
||||||
@@ -254,7 +254,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 }
|
|
|
@ -1,18 +0,0 @@
|
||||||
--- a/net/netfilter/Kconfig
|
|
||||||
+++ b/net/netfilter/Kconfig
|
|
||||||
@@ -163,7 +163,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
|
|
||||||
@@ -611,7 +610,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
|
|
|
@ -1,11 +0,0 @@
|
||||||
--- a/sound/core/Kconfig
|
|
||||||
+++ b/sound/core/Kconfig
|
|
||||||
@@ -8,7 +8,7 @@ config SND_PCM
|
|
||||||
select GCD
|
|
||||||
|
|
||||||
config SND_HWDEP
|
|
||||||
- tristate
|
|
||||||
+ tristate "Sound hardware support"
|
|
||||||
|
|
||||||
config SND_RAWMIDI
|
|
||||||
tristate
|
|
|
@ -1,10 +0,0 @@
|
||||||
--- a/drivers/crypto/Kconfig
|
|
||||||
+++ b/drivers/crypto/Kconfig
|
|
||||||
@@ -172,6 +172,7 @@ config CRYPTO_DEV_MV_CESA
|
|
||||||
depends on PLAT_ORION
|
|
||||||
select CRYPTO_ALGAPI
|
|
||||||
select CRYPTO_AES
|
|
||||||
+ select CRYPTO_HASH2
|
|
||||||
select CRYPTO_BLKCIPHER2
|
|
||||||
help
|
|
||||||
This driver allows you to utilize the Cryptographic Engines and
|
|
|
@ -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
|
|
|
@ -1,23 +0,0 @@
|
||||||
--- a/lib/Kconfig
|
|
||||||
+++ b/lib/Kconfig
|
|
||||||
@@ -190,16 +190,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
|
|
|
@ -1,19 +0,0 @@
|
||||||
--- a/net/wireless/Kconfig
|
|
||||||
+++ b/net/wireless/Kconfig
|
|
||||||
@@ -142,13 +142,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"
|
|
|
@ -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
|
|
||||||
|
|
|
@ -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"
|
|
|
@ -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_QUEUE
|
|
||||||
tristate "Netfilter NFQUEUE over NFNETLINK interface"
|
|
|
@ -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
|
|
||||||
@@ -850,9 +850,6 @@ config ARC
|
|
||||||
config ARCH_MAY_HAVE_PC_FDC
|
|
||||||
bool
|
|
||||||
|
|
||||||
-config BOOT_RAW
|
|
||||||
- bool
|
|
||||||
-
|
|
||||||
config CEVT_BCM1480
|
|
||||||
bool
|
|
||||||
|
|
||||||
@@ -2300,6 +2297,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
|
|
|
@ -1,28 +0,0 @@
|
||||||
--- a/arch/mips/Kconfig
|
|
||||||
+++ b/arch/mips/Kconfig
|
|
||||||
@@ -949,6 +949,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
|
|
|
@ -1,18 +0,0 @@
|
||||||
--- a/arch/mips/include/asm/thread_info.h
|
|
||||||
+++ b/arch/mips/include/asm/thread_info.h
|
|
||||||
@@ -85,6 +85,7 @@ register struct thread_info *__current_t
|
|
||||||
|
|
||||||
#define STACK_WARN (THREAD_SIZE / 8)
|
|
||||||
|
|
||||||
+#if 0
|
|
||||||
#define __HAVE_ARCH_THREAD_INFO_ALLOCATOR
|
|
||||||
|
|
||||||
#ifdef CONFIG_DEBUG_STACK_USAGE
|
|
||||||
@@ -96,6 +97,7 @@ register struct thread_info *__current_t
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define free_thread_info(info) kfree(info)
|
|
||||||
+#endif
|
|
||||||
|
|
||||||
#endif /* !__ASSEMBLY__ */
|
|
||||||
|
|
|
@ -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);
|
|
||||||
|
|
|
@ -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
|
|
||||||
@@ -934,6 +934,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 */
|
|
||||||
@@ -1361,7 +1361,6 @@ int fpu_emulator_cop1Handler(struct pt_r
|
|
||||||
|
|
||||||
return sig;
|
|
||||||
}
|
|
||||||
-
|
|
||||||
#ifdef CONFIG_DEBUG_FS
|
|
||||||
|
|
||||||
static int fpuemu_stat_get(void *data, u64 *val)
|
|
||||||
@@ -1410,4 +1409,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
|
|
||||||
@@ -109,6 +109,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;
|
|
||||||
@@ -165,3 +166,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 */
|
|
|
@ -1,370 +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
|
|
||||||
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
|
|
||||||
@@ -9,6 +9,11 @@ struct mod_arch_specific {
|
|
||||||
struct list_head dbe_list;
|
|
||||||
const struct exception_table_entry *dbe_start;
|
|
||||||
const struct exception_table_entry *dbe_end;
|
|
||||||
+
|
|
||||||
+ 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
|
|
||||||
@@ -45,6 +45,117 @@ static struct mips_hi16 *mips_hi16_list;
|
|
||||||
static LIST_HEAD(dbe_list);
|
|
||||||
static DEFINE_SPINLOCK(dbe_lock);
|
|
||||||
|
|
||||||
+/*
|
|
||||||
+ * 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
|
|
||||||
@@ -52,21 +163,99 @@ void *module_alloc(unsigned long size)
|
|
||||||
GFP_KERNEL, PAGE_KERNEL, -1,
|
|
||||||
__builtin_return_address(0));
|
|
||||||
#else
|
|
||||||
+ void *ptr;
|
|
||||||
+
|
|
||||||
if (size == 0)
|
|
||||||
return NULL;
|
|
||||||
- return vmalloc(size);
|
|
||||||
+
|
|
||||||
+ 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)
|
|
||||||
{
|
|
||||||
- vfree(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;
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -89,28 +278,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",
|
|
||||||
@@ -119,17 +316,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;
|
|
||||||
@@ -397,11 +608,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);
|
|
|
@ -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 memcpy-inatomic.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);
|
|
||||||
+
|
|
|
@ -1,35 +0,0 @@
|
||||||
--- a/arch/mips/oprofile/op_model_mipsxx.c
|
|
||||||
+++ b/arch/mips/oprofile/op_model_mipsxx.c
|
|
||||||
@@ -298,6 +298,11 @@ static void reset_counters(void *arg)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
+static irqreturn_t mipsxx_perfcount_int(int irq, void *dev_id)
|
|
||||||
+{
|
|
||||||
+ return mipsxx_perfcount_handler();
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
static int __init mipsxx_init(void)
|
|
||||||
{
|
|
||||||
int counters;
|
|
||||||
@@ -374,6 +379,10 @@ static int __init mipsxx_init(void)
|
|
||||||
save_perf_irq = perf_irq;
|
|
||||||
perf_irq = mipsxx_perfcount_handler;
|
|
||||||
|
|
||||||
+ if (cp0_perfcount_irq >= 0)
|
|
||||||
+ return request_irq(cp0_perfcount_irq, mipsxx_perfcount_int,
|
|
||||||
+ IRQF_SHARED, "Perfcounter", save_perf_irq);
|
|
||||||
+
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -381,6 +390,9 @@ static void mipsxx_exit(void)
|
|
||||||
{
|
|
||||||
int counters = op_model_mipsxx_ops.num_counters;
|
|
||||||
|
|
||||||
+ if (cp0_perfcount_irq >= 0)
|
|
||||||
+ free_irq(cp0_perfcount_irq, save_perf_irq);
|
|
||||||
+
|
|
||||||
counters = counters_per_cpu_to_total(counters);
|
|
||||||
on_each_cpu(reset_counters, (void *)(long)counters, 1);
|
|
||||||
|
|
|
@ -1,13 +0,0 @@
|
||||||
--- a/arch/arm/kernel/module.c
|
|
||||||
+++ b/arch/arm/kernel/module.c
|
|
||||||
@@ -99,6 +99,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)) {
|
|
|
@ -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
|
|
||||||
@@ -130,7 +130,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_6xx) += -Wa,-maltivec
|
|
||||||
cpu-as-$(CONFIG_POWER4) += -Wa,-maltivec
|
|
||||||
cpu-as-$(CONFIG_E500) += -Wa,-me500
|
|
||||||
--- 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
|
|
|
@ -1,10 +0,0 @@
|
||||||
--- a/arch/powerpc/Makefile
|
|
||||||
+++ b/arch/powerpc/Makefile
|
|
||||||
@@ -94,7 +94,6 @@ else
|
|
||||||
endif
|
|
||||||
endif
|
|
||||||
|
|
||||||
-KBUILD_LDFLAGS_MODULE += arch/powerpc/lib/crtsavres.o
|
|
||||||
|
|
||||||
ifeq ($(CONFIG_TUNE_CELL),y)
|
|
||||||
KBUILD_CFLAGS += $(call cc-option,-mtune=cell)
|
|
|
@ -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
|
|
||||||
@@ -93,7 +93,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
|
|
||||||
@@ -21,6 +21,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>
|
|
||||||
@@ -488,12 +489,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;
|
|
||||||
@@ -509,6 +560,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;
|
|
||||||
@@ -544,6 +597,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
|
|
||||||
@@ -433,3 +433,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 */
|
|
|
@ -1,159 +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
|
|
||||||
@@ -13,12 +13,6 @@
|
|
||||||
#include <asm/cacheflush.h>
|
|
||||||
#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;
|
|
||||||
void (*_machine_crash_shutdown)(struct pt_regs *regs) = NULL;
|
|
||||||
@@ -61,21 +55,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 +103,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 +115,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
|
|
||||||
@@ -50,6 +50,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 */
|
|
||||||
|
|
|
@ -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>
|
|
||||||
|
|
||||||
@@ -21,9 +22,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;
|
|
|
@ -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>
|
|
||||||
|
|
||||||
int (*_machine_kexec_prepare)(struct kimage *) = NULL;
|
|
||||||
void (*_machine_kexec_shutdown)(void) = NULL;
|
|
||||||
@@ -35,6 +36,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)
|
|
||||||
{
|
|
||||||
@@ -45,6 +96,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);
|
|
|
@ -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 */
|
|
|
@ -1,186 +0,0 @@
|
||||||
--- a/arch/mips/kernel/machine_kexec.c
|
|
||||||
+++ b/arch/mips/kernel/machine_kexec.c
|
|
||||||
@@ -23,67 +23,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
|
|
||||||
@@ -95,8 +132,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);
|
|
||||||
@@ -152,11 +195,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
|
|
|
@ -1,327 +0,0 @@
|
||||||
--- a/drivers/mtd/Kconfig
|
|
||||||
+++ b/drivers/mtd/Kconfig
|
|
||||||
@@ -33,6 +33,14 @@ config MTD_TESTS
|
|
||||||
should normally be compiled as kernel modules. The modules perform
|
|
||||||
various checks and verifications when loaded.
|
|
||||||
|
|
||||||
+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
|
|
||||||
@@ -637,6 +639,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 = master->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
|
|
||||||
@@ -653,6 +804,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);
|
|
||||||
|
|
||||||
@@ -667,12 +821,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
|
|
||||||
@@ -949,6 +949,12 @@ static int mtd_ioctl(struct file *file,
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
+ case MTDREFRESH:
|
|
||||||
+ {
|
|
||||||
+ ret = mtd_device_refresh(mtd);
|
|
||||||
+ break;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
default:
|
|
||||||
ret = -ENOTTY;
|
|
||||||
}
|
|
||||||
--- a/include/linux/mtd/mtd.h
|
|
||||||
+++ b/include/linux/mtd/mtd.h
|
|
||||||
@@ -125,6 +125,7 @@ struct nand_ecclayout {
|
|
||||||
struct nand_oobfree oobfree[MTD_MAX_OOBFREE_ENTRIES_LARGE];
|
|
||||||
};
|
|
||||||
|
|
||||||
+struct mtd_info;
|
|
||||||
struct mtd_info {
|
|
||||||
u_char type;
|
|
||||||
uint32_t flags;
|
|
||||||
@@ -277,6 +278,9 @@ struct mtd_info {
|
|
||||||
struct device dev;
|
|
||||||
int usecount;
|
|
||||||
|
|
||||||
+ 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.
|
|
||||||
* The driver may register its callbacks. These callbacks are not
|
|
||||||
@@ -327,6 +331,7 @@ struct mtd_partition;
|
|
||||||
extern int mtd_device_register(struct mtd_info *master,
|
|
||||||
const struct mtd_partition *parts,
|
|
||||||
int 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
|
|
||||||
@@ -34,12 +34,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_NXTBLK (-2)
|
|
||||||
--- a/include/mtd/mtd-abi.h
|
|
||||||
+++ b/include/mtd/mtd-abi.h
|
|
||||||
@@ -127,6 +127,7 @@ struct otp_info {
|
|
||||||
#define MEMWRITEOOB64 _IOWR('M', 21, struct mtd_oob_buf64)
|
|
||||||
#define MEMREADOOB64 _IOWR('M', 22, struct mtd_oob_buf64)
|
|
||||||
#define MEMISLOCKED _IOR('M', 23, struct erase_info_user)
|
|
||||||
+#define MTDREFRESH _IO('M', 50)
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Obsolete legacy interface. Keep it in order not to break userspace
|
|
|
@ -1,145 +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);
|
|
||||||
@@ -258,13 +260,60 @@ static int part_erase(struct mtd_info *m
|
|
||||||
return -EROFS;
|
|
||||||
if (instr->addr >= mtd->size)
|
|
||||||
return -EINVAL;
|
|
||||||
+
|
|
||||||
+ 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 = part->master->read(part->master,
|
|
||||||
+ instr->addr + part->offset,
|
|
||||||
+ part->master->erasesize,
|
|
||||||
+ &readlen, instr->erase_buf);
|
|
||||||
+
|
|
||||||
+ 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 = part->master->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;
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -272,7 +321,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;
|
|
||||||
@@ -530,18 +597,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;
|
|
||||||
if (master->block_isbad) {
|
|
||||||
--- a/include/linux/mtd/mtd.h
|
|
||||||
+++ b/include/linux/mtd/mtd.h
|
|
||||||
@@ -57,6 +57,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 {
|
|
|
@ -1,18 +0,0 @@
|
||||||
--- a/include/linux/mtd/partitions.h
|
|
||||||
+++ b/include/linux/mtd/partitions.h
|
|
||||||
@@ -33,6 +33,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 {
|
|
||||||
@@ -49,7 +50,6 @@ struct mtd_partition {
|
|
||||||
#define MTDPART_SIZ_FULL (0)
|
|
||||||
|
|
||||||
|
|
||||||
-struct mtd_info;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Functions dealing with the various ways of partitioning the space
|
|
|
@ -1,30 +0,0 @@
|
||||||
--- a/drivers/mtd/redboot.c
|
|
||||||
+++ b/drivers/mtd/redboot.c
|
|
||||||
@@ -267,14 +267,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);
|
|
|
@ -1,60 +0,0 @@
|
||||||
--- a/drivers/mtd/redboot.c
|
|
||||||
+++ b/drivers/mtd/redboot.c
|
|
||||||
@@ -29,6 +29,8 @@
|
|
||||||
#include <linux/mtd/mtd.h>
|
|
||||||
#include <linux/mtd/partitions.h>
|
|
||||||
|
|
||||||
+#define BOARD_CONFIG_PART "boardconfig"
|
|
||||||
+
|
|
||||||
struct fis_image_desc {
|
|
||||||
unsigned char name[16]; // Null terminated name
|
|
||||||
uint32_t flash_base; // Address within FLASH of image
|
|
||||||
@@ -59,6 +61,7 @@ static int parse_redboot_partitions(stru
|
|
||||||
struct mtd_partition **pparts,
|
|
||||||
unsigned long fis_origin)
|
|
||||||
{
|
|
||||||
+ unsigned long max_offset = 0;
|
|
||||||
int nrparts = 0;
|
|
||||||
struct fis_image_desc *buf;
|
|
||||||
struct mtd_partition *parts;
|
|
||||||
@@ -227,14 +230,14 @@ static int parse_redboot_partitions(stru
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
- parts = kzalloc(sizeof(*parts)*nrparts + nulllen + namelen, GFP_KERNEL);
|
|
||||||
+ parts = kzalloc(sizeof(*parts) * (nrparts + 1) + nulllen + namelen + sizeof(BOARD_CONFIG_PART), GFP_KERNEL);
|
|
||||||
|
|
||||||
if (!parts) {
|
|
||||||
ret = -ENOMEM;
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
|
|
||||||
- nullname = (char *)&parts[nrparts];
|
|
||||||
+ nullname = (char *)&parts[nrparts + 1];
|
|
||||||
#ifdef CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED
|
|
||||||
if (nulllen > 0) {
|
|
||||||
strcpy(nullname, nullstring);
|
|
||||||
@@ -253,6 +256,8 @@ static int parse_redboot_partitions(stru
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
for ( ; i<nrparts; i++) {
|
|
||||||
+ if(max_offset < buf[i].flash_base + buf[i].size)
|
|
||||||
+ max_offset = buf[i].flash_base + buf[i].size;
|
|
||||||
parts[i].size = fl->img->size;
|
|
||||||
parts[i].offset = fl->img->flash_base;
|
|
||||||
parts[i].name = names;
|
|
||||||
@@ -286,6 +291,14 @@ static int parse_redboot_partitions(stru
|
|
||||||
fl = fl->next;
|
|
||||||
kfree(tmp_fl);
|
|
||||||
}
|
|
||||||
+ if(master->size - max_offset >= master->erasesize)
|
|
||||||
+ {
|
|
||||||
+ parts[nrparts].size = master->size - max_offset;
|
|
||||||
+ parts[nrparts].offset = max_offset;
|
|
||||||
+ parts[nrparts].name = names;
|
|
||||||
+ strcpy(names, BOARD_CONFIG_PART);
|
|
||||||
+ nrparts++;
|
|
||||||
+ }
|
|
||||||
ret = nrparts;
|
|
||||||
*pparts = parts;
|
|
||||||
out:
|
|
|
@ -1,35 +0,0 @@
|
||||||
--- a/drivers/mtd/Kconfig
|
|
||||||
+++ b/drivers/mtd/Kconfig
|
|
||||||
@@ -157,6 +157,22 @@ config MTD_AR7_PARTS
|
|
||||||
---help---
|
|
||||||
TI AR7 partitioning support
|
|
||||||
|
|
||||||
+config MTD_MYLOADER_PARTS
|
|
||||||
+ tristate "MyLoader partition parsing"
|
|
||||||
+ depends on ADM5120 || ATHEROS_AR231X || ATHEROS_AR71XX
|
|
||||||
+ ---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
|
|
||||||
@@ -11,6 +11,7 @@ obj-$(CONFIG_MTD_REDBOOT_PARTS) += redbo
|
|
||||||
obj-$(CONFIG_MTD_CMDLINE_PARTS) += cmdlinepart.o
|
|
||||||
obj-$(CONFIG_MTD_AFS_PARTS) += afs.o
|
|
||||||
obj-$(CONFIG_MTD_AR7_PARTS) += ar7part.o
|
|
||||||
+obj-$(CONFIG_MTD_MYLOADER_PARTS) += myloader.o
|
|
||||||
|
|
||||||
# 'Users' - code which presents functionality to userspace.
|
|
||||||
obj-$(CONFIG_MTD_CHAR) += mtdchar.o
|
|
|
@ -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/buffer_head.h>
|
|
||||||
#include <linux/mutex.h>
|
|
||||||
#include <linux/mount.h>
|
|
||||||
@@ -232,11 +233,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)
|
|
||||||
@@ -275,13 +277,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.type = MTD_RAM;
|
|
||||||
@@ -294,14 +299,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:
|
|
||||||
@@ -374,9 +382,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;
|
|
||||||
@@ -387,7 +395,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)
|
|
||||||
@@ -406,8 +414,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;
|
|
||||||
}
|
|
||||||
@@ -441,7 +451,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/fs/partitions/check.c
|
|
||||||
+++ b/fs/partitions/check.c
|
|
||||||
@@ -664,6 +664,7 @@ rescan:
|
|
||||||
kfree(state);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
+EXPORT_SYMBOL(rescan_partitions);
|
|
||||||
|
|
||||||
unsigned char *read_dev_sector(struct block_device *bdev, sector_t n, Sector *p)
|
|
||||||
{
|
|
|
@ -1,291 +0,0 @@
|
||||||
--- a/drivers/mtd/devices/block2mtd.c
|
|
||||||
+++ b/drivers/mtd/devices/block2mtd.c
|
|
||||||
@@ -30,6 +30,8 @@ struct block2mtd_dev {
|
|
||||||
struct block_device *blkdev;
|
|
||||||
struct mtd_info mtd;
|
|
||||||
struct mutex write_mutex;
|
|
||||||
+ rwlock_t bdev_mutex;
|
|
||||||
+ char devname[0];
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
@@ -82,6 +84,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);
|
|
||||||
@@ -93,6 +101,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;
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -104,10 +116,14 @@ 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;
|
|
||||||
+ }
|
|
||||||
|
|
||||||
- if (from > mtd->size)
|
|
||||||
- return -EINVAL;
|
|
||||||
if (from + len > mtd->size)
|
|
||||||
len = mtd->size - from;
|
|
||||||
|
|
||||||
@@ -122,10 +138,14 @@ static int block2mtd_read(struct mtd_inf
|
|
||||||
len = len - cpylen;
|
|
||||||
|
|
||||||
page = page_read(dev->blkdev->bd_inode->i_mapping, index);
|
|
||||||
- if (!page)
|
|
||||||
- return -ENOMEM;
|
|
||||||
- if (IS_ERR(page))
|
|
||||||
- return PTR_ERR(page);
|
|
||||||
+ if (!page) {
|
|
||||||
+ err = -ENOMEM;
|
|
||||||
+ goto done;
|
|
||||||
+ }
|
|
||||||
+ if (IS_ERR(page)) {
|
|
||||||
+ err = PTR_ERR(page);
|
|
||||||
+ goto done;
|
|
||||||
+ }
|
|
||||||
|
|
||||||
memcpy(buf, page_address(page) + offset, cpylen);
|
|
||||||
page_cache_release(page);
|
|
||||||
@@ -136,7 +156,10 @@ static int block2mtd_read(struct mtd_inf
|
|
||||||
offset = 0;
|
|
||||||
index++;
|
|
||||||
}
|
|
||||||
- return 0;
|
|
||||||
+
|
|
||||||
+done:
|
|
||||||
+ read_unlock(&dev->bdev_mutex);
|
|
||||||
+ return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@@ -188,12 +211,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;
|
|
||||||
+ }
|
|
||||||
|
|
||||||
if (!len)
|
|
||||||
- return 0;
|
|
||||||
- if (to >= mtd->size)
|
|
||||||
- return -ENOSPC;
|
|
||||||
+ goto done;
|
|
||||||
+
|
|
||||||
+ if (to >= mtd->size) {
|
|
||||||
+ err = -ENOSPC;
|
|
||||||
+ goto done;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
if (to + len > mtd->size)
|
|
||||||
len = mtd->size - to;
|
|
||||||
|
|
||||||
@@ -202,6 +235,9 @@ static int block2mtd_write(struct mtd_in
|
|
||||||
mutex_unlock(&dev->write_mutex);
|
|
||||||
if (err > 0)
|
|
||||||
err = 0;
|
|
||||||
+
|
|
||||||
+done:
|
|
||||||
+ read_unlock(&dev->bdev_mutex);
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -210,33 +246,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;
|
|
||||||
@@ -244,36 +357,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. */
|
|
||||||
+ strcpy(dev->devname, devname);
|
|
||||||
|
|
||||||
- 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);
|
|
||||||
+ if (_open_bdev(dev))
|
|
||||||
goto devinit_err;
|
|
||||||
- }
|
|
||||||
- dev->blkdev = bdev;
|
|
||||||
-
|
|
||||||
- if (MAJOR(bdev->bd_dev) == MTD_BLOCK_MAJOR) {
|
|
||||||
- ERROR("attempting to use an MTD device as a block device");
|
|
||||||
- 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 */
|
|
||||||
@@ -298,6 +392,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;
|
|
|
@ -1,10 +0,0 @@
|
||||||
--- a/drivers/mtd/devices/block2mtd.c
|
|
||||||
+++ b/drivers/mtd/devices/block2mtd.c
|
|
||||||
@@ -269,6 +269,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);
|
|
|
@ -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
|
|
||||||
@@ -625,6 +625,7 @@ struct platform_nand_chip {
|
|
||||||
int chip_delay;
|
|
||||||
unsigned int options;
|
|
||||||
const char **part_probe_types;
|
|
||||||
+ int (*chip_fixup)(struct mtd_info *mtd);
|
|
||||||
void (*set_parts)(uint64_t size, struct platform_nand_chip *chip);
|
|
||||||
void *priv;
|
|
||||||
};
|
|
||||||
--- a/drivers/mtd/nand/plat_nand.c
|
|
||||||
+++ b/drivers/mtd/nand/plat_nand.c
|
|
||||||
@@ -94,7 +94,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)) {
|
|
||||||
+ res = -ENXIO;
|
|
||||||
+ goto out;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ if (pdata->chip.chip_fixup) {
|
|
||||||
+ res = pdata->chip.chip_fixup(&data->mtd);
|
|
||||||
+ if (res)
|
|
||||||
+ goto out;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ if (nand_scan_tail(&data->mtd)) {
|
|
||||||
err = -ENXIO;
|
|
||||||
goto out;
|
|
||||||
}
|
|
|
@ -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);
|
|
||||||
|
|
|
@ -1,11 +0,0 @@
|
||||||
--- a/drivers/mtd/chips/cfi_cmdset_0002.c
|
|
||||||
+++ b/drivers/mtd/chips/cfi_cmdset_0002.c
|
|
||||||
@@ -685,7 +685,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;
|
|
|
@ -1,39 +0,0 @@
|
||||||
--- a/drivers/mtd/devices/m25p80.c
|
|
||||||
+++ b/drivers/mtd/devices/m25p80.c
|
|
||||||
@@ -44,6 +44,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 */
|
|
||||||
|
|
||||||
@@ -630,6 +631,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) \
|
|
||||||
@@ -689,6 +691,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).
|
|
||||||
*/
|
|
||||||
@@ -920,6 +926,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;
|
|
|
@ -1,10 +0,0 @@
|
||||||
--- a/drivers/mtd/devices/m25p80.c
|
|
||||||
+++ b/drivers/mtd/devices/m25p80.c
|
|
||||||
@@ -768,6 +768,7 @@ static const struct spi_device_id m25p_i
|
|
||||||
{ "w25q32", INFO(0xef4016, 0, 64 * 1024, 64, SECT_4K) },
|
|
||||||
{ "w25x64", INFO(0xef3017, 0, 64 * 1024, 128, SECT_4K) },
|
|
||||||
{ "w25q64", INFO(0xef4017, 0, 64 * 1024, 128, SECT_4K) },
|
|
||||||
+ { "w25q128", INFO(0xef4018, 0, 64 * 1024, 256, SECT_4K) },
|
|
||||||
|
|
||||||
/* Catalyst / On Semiconductor -- non-JEDEC */
|
|
||||||
{ "cat25c11", CAT25_INFO( 16, 8, 16, 1) },
|
|
|
@ -1,12 +0,0 @@
|
||||||
--- a/drivers/mtd/mtdconcat.c
|
|
||||||
+++ b/drivers/mtd/mtdconcat.c
|
|
||||||
@@ -619,7 +619,8 @@ static void concat_sync(struct mtd_info
|
|
||||||
|
|
||||||
for (i = 0; i < concat->num_subdev; i++) {
|
|
||||||
struct mtd_info *subdev = concat->subdev[i];
|
|
||||||
- subdev->sync(subdev);
|
|
||||||
+ if (subdev->sync)
|
|
||||||
+ subdev->sync(subdev);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -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
|
|
||||||
@@ -1412,6 +1412,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;
|
|
||||||
|
|
|
@ -1,41 +0,0 @@
|
||||||
--- a/drivers/mtd/devices/Kconfig
|
|
||||||
+++ b/drivers/mtd/devices/Kconfig
|
|
||||||
@@ -102,6 +102,14 @@ config M25PXX_USE_FAST_READ
|
|
||||||
help
|
|
||||||
This option enables FAST_READ access supported by ST M25Pxx.
|
|
||||||
|
|
||||||
+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
|
|
||||||
@@ -83,6 +83,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 {
|
|
||||||
@@ -924,7 +930,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) {
|
|
|
@ -1,18 +0,0 @@
|
||||||
--- a/fs/Kconfig
|
|
||||||
+++ b/fs/Kconfig
|
|
||||||
@@ -35,6 +35,7 @@ source "fs/gfs2/Kconfig"
|
|
||||||
source "fs/ocfs2/Kconfig"
|
|
||||||
source "fs/btrfs/Kconfig"
|
|
||||||
source "fs/nilfs2/Kconfig"
|
|
||||||
+source "fs/yaffs2/Kconfig"
|
|
||||||
|
|
||||||
endif # BLOCK
|
|
||||||
|
|
||||||
--- a/fs/Makefile
|
|
||||||
+++ b/fs/Makefile
|
|
||||||
@@ -125,3 +125,5 @@ obj-$(CONFIG_GFS2_FS) += gfs2/
|
|
||||||
obj-$(CONFIG_EXOFS_FS) += exofs/
|
|
||||||
obj-$(CONFIG_CEPH_FS) += ceph/
|
|
||||||
obj-$(CONFIG_PSTORE) += pstore/
|
|
||||||
+obj-$(CONFIG_YAFFS_FS) += yaffs2/
|
|
||||||
+
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -1,17 +0,0 @@
|
||||||
--- a/fs/yaffs2/yaffs_guts.c
|
|
||||||
+++ b/fs/yaffs2/yaffs_guts.c
|
|
||||||
@@ -1709,11 +1709,11 @@ static int yaffs_change_obj_name(yaffs_o
|
|
||||||
}
|
|
||||||
|
|
||||||
/* TODO: Do we need this different handling for YAFFS2 and YAFFS1?? */
|
|
||||||
- if (obj->my_dev->param.is_yaffs2)
|
|
||||||
+ // if (obj->my_dev->param.is_yaffs2)
|
|
||||||
unlinkOp = (new_dir == obj->my_dev->unlinked_dir);
|
|
||||||
- else
|
|
||||||
+ /* else
|
|
||||||
unlinkOp = (new_dir == obj->my_dev->unlinked_dir
|
|
||||||
- && obj->variant_type == YAFFS_OBJECT_TYPE_FILE);
|
|
||||||
+ && obj->variant_type == YAFFS_OBJECT_TYPE_FILE); */
|
|
||||||
|
|
||||||
deleteOp = (new_dir == obj->my_dev->del_dir);
|
|
||||||
|
|
|
@ -1,20 +0,0 @@
|
||||||
--- a/fs/yaffs2/yaffs_vfs_glue.c
|
|
||||||
+++ b/fs/yaffs2/yaffs_vfs_glue.c
|
|
||||||
@@ -3036,7 +3036,7 @@ static struct super_block *yaffs_interna
|
|
||||||
YINIT_LIST_HEAD(&(yaffs_dev_to_lc(dev)->searchContexts));
|
|
||||||
param->remove_obj_fn = yaffs_remove_obj_callback;
|
|
||||||
|
|
||||||
- init_MUTEX(&(yaffs_dev_to_lc(dev)->grossLock));
|
|
||||||
+ sema_init(&(yaffs_dev_to_lc(dev)->grossLock), 1);
|
|
||||||
|
|
||||||
yaffs_gross_lock(dev);
|
|
||||||
|
|
||||||
@@ -3494,7 +3494,7 @@ static int __init init_yaffs_fs(void)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
- init_MUTEX(&yaffs_context_lock);
|
|
||||||
+ sema_init((&yaffs_context_lock), 1);
|
|
||||||
|
|
||||||
/* Install the proc_fs entries */
|
|
||||||
my_proc_entry = create_proc_entry("yaffs",
|
|
|
@ -1,147 +0,0 @@
|
||||||
--- a/fs/yaffs2/yaffs_vfs_glue.c
|
|
||||||
+++ b/fs/yaffs2/yaffs_vfs_glue.c
|
|
||||||
@@ -72,7 +72,7 @@
|
|
||||||
#include <linux/init.h>
|
|
||||||
#include <linux/fs.h>
|
|
||||||
#include <linux/proc_fs.h>
|
|
||||||
-#include <linux/smp_lock.h>
|
|
||||||
+#include <linux/mutex.h>
|
|
||||||
#include <linux/pagemap.h>
|
|
||||||
#include <linux/mtd/mtd.h>
|
|
||||||
#include <linux/interrupt.h>
|
|
||||||
@@ -97,6 +97,8 @@
|
|
||||||
|
|
||||||
#include <asm/div64.h>
|
|
||||||
|
|
||||||
+static DEFINE_MUTEX(yaffs_mutex);
|
|
||||||
+
|
|
||||||
#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0))
|
|
||||||
|
|
||||||
#include <linux/statfs.h>
|
|
||||||
@@ -1538,7 +1540,7 @@ static loff_t yaffs_dir_llseek(struct fi
|
|
||||||
{
|
|
||||||
long long retval;
|
|
||||||
|
|
||||||
- lock_kernel();
|
|
||||||
+ mutex_lock(&yaffs_mutex);
|
|
||||||
|
|
||||||
switch (origin){
|
|
||||||
case 2:
|
|
||||||
@@ -1555,7 +1557,7 @@ static loff_t yaffs_dir_llseek(struct fi
|
|
||||||
|
|
||||||
retval = offset;
|
|
||||||
}
|
|
||||||
- unlock_kernel();
|
|
||||||
+ mutex_unlock(&yaffs_mutex);
|
|
||||||
return retval;
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -3087,98 +3089,52 @@ static struct super_block *yaffs_interna
|
|
||||||
return sb;
|
|
||||||
}
|
|
||||||
|
|
||||||
-
|
|
||||||
-#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0))
|
|
||||||
static int yaffs_internal_read_super_mtd(struct super_block *sb, void *data,
|
|
||||||
int silent)
|
|
||||||
{
|
|
||||||
return yaffs_internal_read_super(1, sb, data, silent) ? 0 : -EINVAL;
|
|
||||||
}
|
|
||||||
|
|
||||||
-#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 17))
|
|
||||||
-static int yaffs_read_super(struct file_system_type *fs,
|
|
||||||
+static struct dentry *yaffs_read_super(struct file_system_type *fs,
|
|
||||||
int flags, const char *dev_name,
|
|
||||||
- void *data, struct vfsmount *mnt)
|
|
||||||
-{
|
|
||||||
-
|
|
||||||
- return get_sb_bdev(fs, flags, dev_name, data,
|
|
||||||
- yaffs_internal_read_super_mtd, mnt);
|
|
||||||
-}
|
|
||||||
-#else
|
|
||||||
-static struct super_block *yaffs_read_super(struct file_system_type *fs,
|
|
||||||
- int flags, const char *dev_name,
|
|
||||||
- void *data)
|
|
||||||
+ void *data)
|
|
||||||
{
|
|
||||||
|
|
||||||
- return get_sb_bdev(fs, flags, dev_name, data,
|
|
||||||
+ return mount_bdev(fs, flags, dev_name, data,
|
|
||||||
yaffs_internal_read_super_mtd);
|
|
||||||
}
|
|
||||||
-#endif
|
|
||||||
|
|
||||||
static struct file_system_type yaffs_fs_type = {
|
|
||||||
.owner = THIS_MODULE,
|
|
||||||
.name = "yaffs",
|
|
||||||
- .get_sb = yaffs_read_super,
|
|
||||||
+ .mount = yaffs_read_super,
|
|
||||||
.kill_sb = kill_block_super,
|
|
||||||
.fs_flags = FS_REQUIRES_DEV,
|
|
||||||
};
|
|
||||||
-#else
|
|
||||||
-static struct super_block *yaffs_read_super(struct super_block *sb, void *data,
|
|
||||||
- int silent)
|
|
||||||
-{
|
|
||||||
- return yaffs_internal_read_super(1, sb, data, silent);
|
|
||||||
-}
|
|
||||||
-
|
|
||||||
-static DECLARE_FSTYPE(yaffs_fs_type, "yaffs", yaffs_read_super,
|
|
||||||
- FS_REQUIRES_DEV);
|
|
||||||
-#endif
|
|
||||||
-
|
|
||||||
|
|
||||||
#ifdef CONFIG_YAFFS_YAFFS2
|
|
||||||
|
|
||||||
-#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0))
|
|
||||||
static int yaffs2_internal_read_super_mtd(struct super_block *sb, void *data,
|
|
||||||
int silent)
|
|
||||||
{
|
|
||||||
return yaffs_internal_read_super(2, sb, data, silent) ? 0 : -EINVAL;
|
|
||||||
}
|
|
||||||
|
|
||||||
-#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 17))
|
|
||||||
-static int yaffs2_read_super(struct file_system_type *fs,
|
|
||||||
- int flags, const char *dev_name, void *data,
|
|
||||||
- struct vfsmount *mnt)
|
|
||||||
+static struct dentry *yaffs2_read_super(struct file_system_type *fs,
|
|
||||||
+ int flags, const char *dev_name,
|
|
||||||
+ void *data)
|
|
||||||
{
|
|
||||||
- return get_sb_bdev(fs, flags, dev_name, data,
|
|
||||||
- yaffs2_internal_read_super_mtd, mnt);
|
|
||||||
+ return mount_bdev(fs, flags, dev_name, data,
|
|
||||||
+ yaffs_internal_read_super_mtd);
|
|
||||||
}
|
|
||||||
-#else
|
|
||||||
-static struct super_block *yaffs2_read_super(struct file_system_type *fs,
|
|
||||||
- int flags, const char *dev_name,
|
|
||||||
- void *data)
|
|
||||||
-{
|
|
||||||
-
|
|
||||||
- return get_sb_bdev(fs, flags, dev_name, data,
|
|
||||||
- yaffs2_internal_read_super_mtd);
|
|
||||||
-}
|
|
||||||
-#endif
|
|
||||||
|
|
||||||
static struct file_system_type yaffs2_fs_type = {
|
|
||||||
.owner = THIS_MODULE,
|
|
||||||
.name = "yaffs2",
|
|
||||||
- .get_sb = yaffs2_read_super,
|
|
||||||
+ .mount = yaffs2_read_super,
|
|
||||||
.kill_sb = kill_block_super,
|
|
||||||
.fs_flags = FS_REQUIRES_DEV,
|
|
||||||
};
|
|
||||||
-#else
|
|
||||||
-static struct super_block *yaffs2_read_super(struct super_block *sb,
|
|
||||||
- void *data, int silent)
|
|
||||||
-{
|
|
||||||
- return yaffs_internal_read_super(2, sb, data, silent);
|
|
||||||
-}
|
|
||||||
-
|
|
||||||
-static DECLARE_FSTYPE(yaffs2_fs_type, "yaffs2", yaffs2_read_super,
|
|
||||||
- FS_REQUIRES_DEV);
|
|
||||||
-#endif
|
|
||||||
|
|
||||||
#endif /* CONFIG_YAFFS_YAFFS2 */
|
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -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
|
|
||||||
{
|
|
|
@ -1,132 +0,0 @@
|
||||||
--- a/fs/jffs2/build.c
|
|
||||||
+++ b/fs/jffs2/build.c
|
|
||||||
@@ -112,6 +112,17 @@ 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__);
|
|
||||||
+ if (c->mtd->unlock)
|
|
||||||
+ c->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
|
|
||||||
@@ -72,7 +72,7 @@ static int file_dirty(struct jffs2_sb_in
|
|
||||||
return ret;
|
|
||||||
if ((ret = jffs2_scan_dirty_space(c, jeb, jeb->free_size)))
|
|
||||||
return ret;
|
|
||||||
- /* Turned wasted size into dirty, since we apparently
|
|
||||||
+ /* Turned wasted size into dirty, since we apparently
|
|
||||||
think it's recoverable now. */
|
|
||||||
jeb->dirty_size += jeb->wasted_size;
|
|
||||||
c->dirty_size += jeb->wasted_size;
|
|
||||||
@@ -147,8 +147,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;
|
|
||||||
@@ -405,7 +408,7 @@ static int jffs2_scan_xref_node(struct j
|
|
||||||
if (!ref)
|
|
||||||
return -ENOMEM;
|
|
||||||
|
|
||||||
- /* BEFORE jffs2_build_xattr_subsystem() called,
|
|
||||||
+ /* BEFORE jffs2_build_xattr_subsystem() called,
|
|
||||||
* and AFTER xattr_ref is marked as a dead xref,
|
|
||||||
* ref->xid is used to store 32bit xid, xd is not used
|
|
||||||
* ref->ino is used to store 32bit inode-number, ic is not used
|
|
||||||
@@ -478,7 +481,7 @@ static int jffs2_scan_eraseblock (struct
|
|
||||||
struct jffs2_sum_marker *sm;
|
|
||||||
void *sumptr = NULL;
|
|
||||||
uint32_t sumlen;
|
|
||||||
-
|
|
||||||
+
|
|
||||||
if (!buf_size) {
|
|
||||||
/* XIP case. Just look, point at the summary if it's there */
|
|
||||||
sm = (void *)buf + c->sector_size - sizeof(*sm);
|
|
||||||
@@ -494,9 +497,9 @@ static int jffs2_scan_eraseblock (struct
|
|
||||||
buf_len = sizeof(*sm);
|
|
||||||
|
|
||||||
/* Read as much as we want into the _end_ of the preallocated buffer */
|
|
||||||
- err = jffs2_fill_scan_buf(c, buf + buf_size - buf_len,
|
|
||||||
+ err = jffs2_fill_scan_buf(c, buf + buf_size - buf_len,
|
|
||||||
jeb->offset + c->sector_size - buf_len,
|
|
||||||
- buf_len);
|
|
||||||
+ buf_len);
|
|
||||||
if (err)
|
|
||||||
return err;
|
|
||||||
|
|
||||||
@@ -515,9 +518,9 @@ static int jffs2_scan_eraseblock (struct
|
|
||||||
}
|
|
||||||
if (buf_len < sumlen) {
|
|
||||||
/* Need to read more so that the entire summary node is present */
|
|
||||||
- err = jffs2_fill_scan_buf(c, sumptr,
|
|
||||||
+ err = jffs2_fill_scan_buf(c, sumptr,
|
|
||||||
jeb->offset + c->sector_size - sumlen,
|
|
||||||
- sumlen - buf_len);
|
|
||||||
+ sumlen - buf_len);
|
|
||||||
if (err)
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
@@ -530,7 +533,7 @@ static int jffs2_scan_eraseblock (struct
|
|
||||||
|
|
||||||
if (buf_size && sumlen > buf_size)
|
|
||||||
kfree(sumptr);
|
|
||||||
- /* If it returns with a real error, bail.
|
|
||||||
+ /* If it returns with a real error, bail.
|
|
||||||
If it returns positive, that's a block classification
|
|
||||||
(i.e. BLK_STATE_xxx) so return that too.
|
|
||||||
If it returns zero, fall through to full scan. */
|
|
||||||
@@ -551,6 +554,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);
|
|
||||||
@@ -676,7 +690,7 @@ scan_more:
|
|
||||||
scan_end = buf_len;
|
|
||||||
goto more_empty;
|
|
||||||
}
|
|
||||||
-
|
|
||||||
+
|
|
||||||
/* See how much more there is to read in this eraseblock... */
|
|
||||||
buf_len = min_t(uint32_t, buf_size, jeb->offset + c->sector_size - ofs);
|
|
||||||
if (!buf_len) {
|
|
||||||
@@ -912,7 +926,7 @@ scan_more:
|
|
||||||
|
|
||||||
D1(printk(KERN_DEBUG "Block at 0x%08x: free 0x%08x, dirty 0x%08x, unchecked 0x%08x, used 0x%08x, wasted 0x%08x\n",
|
|
||||||
jeb->offset,jeb->free_size, jeb->dirty_size, jeb->unchecked_size, jeb->used_size, jeb->wasted_size));
|
|
||||||
-
|
|
||||||
+
|
|
||||||
/* mark_node_obsolete can add to wasted !! */
|
|
||||||
if (jeb->wasted_size) {
|
|
||||||
jeb->dirty_size += jeb->wasted_size;
|
|
|
@ -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,
|
|
File diff suppressed because it is too large
Load Diff
|
@ -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){
|
|
|
@ -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
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
|
@ -1,61 +0,0 @@
|
||||||
--- a/net/netfilter/Kconfig
|
|
||||||
+++ b/net/netfilter/Kconfig
|
|
||||||
@@ -832,6 +832,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
|
|
||||||
@@ -1018,26 +1039,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'
|
|
|
@ -1,118 +0,0 @@
|
||||||
--- a/include/linux/netfilter/nf_conntrack_sip.h
|
|
||||||
+++ b/include/linux/netfilter/nf_conntrack_sip.h
|
|
||||||
@@ -2,12 +2,15 @@
|
|
||||||
#define __NF_CONNTRACK_SIP_H__
|
|
||||||
#ifdef __KERNEL__
|
|
||||||
|
|
||||||
+#include <linux/types.h>
|
|
||||||
+
|
|
||||||
#define SIP_PORT 5060
|
|
||||||
#define SIP_TIMEOUT 3600
|
|
||||||
|
|
||||||
struct nf_ct_sip_master {
|
|
||||||
unsigned int register_cseq;
|
|
||||||
unsigned int invite_cseq;
|
|
||||||
+ __be16 forced_dport;
|
|
||||||
};
|
|
||||||
|
|
||||||
enum sip_expectation_classes {
|
|
||||||
--- a/net/ipv4/netfilter/nf_nat_sip.c
|
|
||||||
+++ b/net/ipv4/netfilter/nf_nat_sip.c
|
|
||||||
@@ -73,6 +73,7 @@ static int map_addr(struct sk_buff *skb,
|
|
||||||
enum ip_conntrack_info ctinfo;
|
|
||||||
struct nf_conn *ct = nf_ct_get(skb, &ctinfo);
|
|
||||||
enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo);
|
|
||||||
+ struct nf_conn_help *help = nfct_help(ct);
|
|
||||||
char buffer[sizeof("nnn.nnn.nnn.nnn:nnnnn")];
|
|
||||||
unsigned int buflen;
|
|
||||||
__be32 newaddr;
|
|
||||||
@@ -85,7 +86,8 @@ static int map_addr(struct sk_buff *skb,
|
|
||||||
} else if (ct->tuplehash[dir].tuple.dst.u3.ip == addr->ip &&
|
|
||||||
ct->tuplehash[dir].tuple.dst.u.udp.port == port) {
|
|
||||||
newaddr = ct->tuplehash[!dir].tuple.src.u3.ip;
|
|
||||||
- newport = ct->tuplehash[!dir].tuple.src.u.udp.port;
|
|
||||||
+ newport = help->help.ct_sip_info.forced_dport ? :
|
|
||||||
+ ct->tuplehash[!dir].tuple.src.u.udp.port;
|
|
||||||
} else
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
@@ -121,6 +123,7 @@ static unsigned int ip_nat_sip(struct sk
|
|
||||||
enum ip_conntrack_info ctinfo;
|
|
||||||
struct nf_conn *ct = nf_ct_get(skb, &ctinfo);
|
|
||||||
enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo);
|
|
||||||
+ struct nf_conn_help *help = nfct_help(ct);
|
|
||||||
unsigned int coff, matchoff, matchlen;
|
|
||||||
enum sip_header_types hdr;
|
|
||||||
union nf_inet_addr addr;
|
|
||||||
@@ -229,6 +232,20 @@ next:
|
|
||||||
!map_sip_addr(skb, dataoff, dptr, datalen, SIP_HDR_TO))
|
|
||||||
return NF_DROP;
|
|
||||||
|
|
||||||
+ /* Mangle destination port for Cisco phones, then fix up checksums */
|
|
||||||
+ if (dir == IP_CT_DIR_REPLY && help->help.ct_sip_info.forced_dport) {
|
|
||||||
+ struct udphdr *uh;
|
|
||||||
+
|
|
||||||
+ if (!skb_make_writable(skb, skb->len))
|
|
||||||
+ return NF_DROP;
|
|
||||||
+
|
|
||||||
+ uh = (struct udphdr *)(skb->data + ip_hdrlen(skb));
|
|
||||||
+ uh->dest = help->help.ct_sip_info.forced_dport;
|
|
||||||
+
|
|
||||||
+ if (!nf_nat_mangle_udp_packet(skb, ct, ctinfo, 0, 0, NULL, 0))
|
|
||||||
+ return NF_DROP;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
return NF_ACCEPT;
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -280,8 +297,10 @@ static unsigned int ip_nat_sip_expect(st
|
|
||||||
enum ip_conntrack_info ctinfo;
|
|
||||||
struct nf_conn *ct = nf_ct_get(skb, &ctinfo);
|
|
||||||
enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo);
|
|
||||||
+ struct nf_conn_help *help = nfct_help(ct);
|
|
||||||
__be32 newip;
|
|
||||||
u_int16_t port;
|
|
||||||
+ __be16 srcport;
|
|
||||||
char buffer[sizeof("nnn.nnn.nnn.nnn:nnnnn")];
|
|
||||||
unsigned buflen;
|
|
||||||
|
|
||||||
@@ -294,8 +313,9 @@ static unsigned int ip_nat_sip_expect(st
|
|
||||||
/* If the signalling port matches the connection's source port in the
|
|
||||||
* original direction, try to use the destination port in the opposite
|
|
||||||
* direction. */
|
|
||||||
- if (exp->tuple.dst.u.udp.port ==
|
|
||||||
- ct->tuplehash[dir].tuple.src.u.udp.port)
|
|
||||||
+ srcport = help->help.ct_sip_info.forced_dport ? :
|
|
||||||
+ ct->tuplehash[dir].tuple.src.u.udp.port;
|
|
||||||
+ if (exp->tuple.dst.u.udp.port == srcport)
|
|
||||||
port = ntohs(ct->tuplehash[!dir].tuple.dst.u.udp.port);
|
|
||||||
else
|
|
||||||
port = ntohs(exp->tuple.dst.u.udp.port);
|
|
||||||
--- a/net/netfilter/nf_conntrack_sip.c
|
|
||||||
+++ b/net/netfilter/nf_conntrack_sip.c
|
|
||||||
@@ -1363,8 +1363,25 @@ static int process_sip_request(struct sk
|
|
||||||
{
|
|
||||||
enum ip_conntrack_info ctinfo;
|
|
||||||
struct nf_conn *ct = nf_ct_get(skb, &ctinfo);
|
|
||||||
+ struct nf_conn_help *help = nfct_help(ct);
|
|
||||||
+ enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo);
|
|
||||||
unsigned int matchoff, matchlen;
|
|
||||||
unsigned int cseq, i;
|
|
||||||
+ union nf_inet_addr addr;
|
|
||||||
+ __be16 port;
|
|
||||||
+
|
|
||||||
+ /* Many Cisco IP phones use a high source port for SIP requests, but
|
|
||||||
+ * listen for the response on port 5060. If we are the local
|
|
||||||
+ * router for one of these phones, save the port number from the
|
|
||||||
+ * Via: header so that nf_nat_sip can redirect the responses to
|
|
||||||
+ * the correct port.
|
|
||||||
+ */
|
|
||||||
+ if (ct_sip_parse_header_uri(ct, *dptr, NULL, *datalen,
|
|
||||||
+ SIP_HDR_VIA_UDP, NULL, &matchoff,
|
|
||||||
+ &matchlen, &addr, &port) > 0 &&
|
|
||||||
+ port != ct->tuplehash[dir].tuple.src.u.udp.port &&
|
|
||||||
+ nf_inet_addr_cmp(&addr, &ct->tuplehash[dir].tuple.src.u3))
|
|
||||||
+ help->help.ct_sip_info.forced_dport = port;
|
|
||||||
|
|
||||||
for (i = 0; i < ARRAY_SIZE(sip_handlers); i++) {
|
|
||||||
const struct sip_handler *handler;
|
|
|
@ -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)
|
|
||||||
{
|
|
||||||
@@ -561,7 +587,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;
|
|
||||||
|
|
||||||
@@ -570,6 +596,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;
|
|
||||||
@@ -931,6 +959,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))
|
|
||||||
@@ -961,6 +990,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;
|
|
|
@ -1,81 +0,0 @@
|
||||||
--- a/net/ipv4/netfilter/ip_tables.c
|
|
||||||
+++ b/net/ipv4/netfilter/ip_tables.c
|
|
||||||
@@ -310,6 +310,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,
|
|
||||||
@@ -334,6 +361,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
|
|
||||||
@@ -348,18 +394,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]));
|
|
|
@ -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");
|
|
||||||
|
|
|
@ -1,36 +0,0 @@
|
||||||
--- a/net/netfilter/nf_conntrack_proto_tcp.c
|
|
||||||
+++ b/net/netfilter/nf_conntrack_proto_tcp.c
|
|
||||||
@@ -29,6 +29,9 @@
|
|
||||||
#include <net/netfilter/ipv4/nf_conntrack_ipv4.h>
|
|
||||||
#include <net/netfilter/ipv6/nf_conntrack_ipv6.h>
|
|
||||||
|
|
||||||
+/* Do not check the TCP window for incoming packets */
|
|
||||||
+static int nf_ct_tcp_no_window_check __read_mostly = 1;
|
|
||||||
+
|
|
||||||
/* "Be conservative in what you do,
|
|
||||||
be liberal in what you accept from others."
|
|
||||||
If it's non-zero, we mark only out of window RST segments as INVALID. */
|
|
||||||
@@ -524,6 +527,9 @@ static bool tcp_in_window(const struct n
|
|
||||||
s16 receiver_offset;
|
|
||||||
bool res;
|
|
||||||
|
|
||||||
+ if (nf_ct_tcp_no_window_check)
|
|
||||||
+ return true;
|
|
||||||
+
|
|
||||||
/*
|
|
||||||
* Get the required data from the packet.
|
|
||||||
*/
|
|
||||||
@@ -1321,6 +1327,13 @@ static struct ctl_table tcp_sysctl_table
|
|
||||||
.proc_handler = proc_dointvec,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
+ .procname = "nf_conntrack_tcp_no_window_check",
|
|
||||||
+ .data = &nf_ct_tcp_no_window_check,
|
|
||||||
+ .maxlen = sizeof(unsigned int),
|
|
||||||
+ .mode = 0644,
|
|
||||||
+ .proc_handler = proc_dointvec,
|
|
||||||
+ },
|
|
||||||
+ {
|
|
||||||
.procname = "nf_conntrack_tcp_be_liberal",
|
|
||||||
.data = &nf_ct_tcp_be_liberal,
|
|
||||||
.maxlen = sizeof(unsigned int),
|
|
|
@ -1,795 +0,0 @@
|
||||||
--- a/include/linux/pkt_sched.h
|
|
||||||
+++ b/include/linux/pkt_sched.h
|
|
||||||
@@ -173,8 +173,37 @@ struct tc_sfq_xstats {
|
|
||||||
*
|
|
||||||
* The only reason for this is efficiency, it is possible
|
|
||||||
* to change these parameters in compile time.
|
|
||||||
+ *
|
|
||||||
+ * If you need to play with these values, use esfq instead.
|
|
||||||
*/
|
|
||||||
|
|
||||||
+/* ESFQ section */
|
|
||||||
+
|
|
||||||
+enum
|
|
||||||
+{
|
|
||||||
+ /* traditional */
|
|
||||||
+ TCA_SFQ_HASH_CLASSIC,
|
|
||||||
+ TCA_SFQ_HASH_DST,
|
|
||||||
+ TCA_SFQ_HASH_SRC,
|
|
||||||
+ TCA_SFQ_HASH_FWMARK,
|
|
||||||
+ /* conntrack */
|
|
||||||
+ TCA_SFQ_HASH_CTORIGDST,
|
|
||||||
+ TCA_SFQ_HASH_CTORIGSRC,
|
|
||||||
+ TCA_SFQ_HASH_CTREPLDST,
|
|
||||||
+ TCA_SFQ_HASH_CTREPLSRC,
|
|
||||||
+ TCA_SFQ_HASH_CTNATCHG,
|
|
||||||
+};
|
|
||||||
+
|
|
||||||
+struct tc_esfq_qopt
|
|
||||||
+{
|
|
||||||
+ unsigned quantum; /* Bytes per round allocated to flow */
|
|
||||||
+ int perturb_period; /* Period of hash perturbation */
|
|
||||||
+ __u32 limit; /* Maximal packets in queue */
|
|
||||||
+ unsigned divisor; /* Hash divisor */
|
|
||||||
+ unsigned flows; /* Maximal number of flows */
|
|
||||||
+ unsigned hash_kind; /* Hash function to use for flow identification */
|
|
||||||
+};
|
|
||||||
+
|
|
||||||
/* RED section */
|
|
||||||
|
|
||||||
enum {
|
|
||||||
--- a/net/sched/Kconfig
|
|
||||||
+++ b/net/sched/Kconfig
|
|
||||||
@@ -148,6 +148,37 @@ config NET_SCH_SFQ
|
|
||||||
To compile this code as a module, choose M here: the
|
|
||||||
module will be called sch_sfq.
|
|
||||||
|
|
||||||
+config NET_SCH_ESFQ
|
|
||||||
+ tristate "Enhanced Stochastic Fairness Queueing (ESFQ)"
|
|
||||||
+ ---help---
|
|
||||||
+ Say Y here if you want to use the Enhanced Stochastic Fairness
|
|
||||||
+ Queueing (ESFQ) packet scheduling algorithm for some of your network
|
|
||||||
+ devices or as a leaf discipline for a classful qdisc such as HTB or
|
|
||||||
+ CBQ (see the top of <file:net/sched/sch_esfq.c> for details and
|
|
||||||
+ references to the SFQ algorithm).
|
|
||||||
+
|
|
||||||
+ This is an enchanced SFQ version which allows you to control some
|
|
||||||
+ hardcoded values in the SFQ scheduler.
|
|
||||||
+
|
|
||||||
+ ESFQ also adds control of the hash function used to identify packet
|
|
||||||
+ flows. The original SFQ discipline hashes by connection; ESFQ add
|
|
||||||
+ several other hashing methods, such as by src IP or by dst IP, which
|
|
||||||
+ can be more fair to users in some networking situations.
|
|
||||||
+
|
|
||||||
+ To compile this code as a module, choose M here: the
|
|
||||||
+ module will be called sch_esfq.
|
|
||||||
+
|
|
||||||
+config NET_SCH_ESFQ_NFCT
|
|
||||||
+ bool "Connection Tracking Hash Types"
|
|
||||||
+ depends on NET_SCH_ESFQ && NF_CONNTRACK
|
|
||||||
+ ---help---
|
|
||||||
+ Say Y here to enable support for hashing based on netfilter connection
|
|
||||||
+ tracking information. This is useful for a router that is also using
|
|
||||||
+ NAT to connect privately-addressed hosts to the Internet. If you want
|
|
||||||
+ to provide fair distribution of upstream bandwidth, ESFQ must use
|
|
||||||
+ connection tracking information, since all outgoing packets will share
|
|
||||||
+ the same source address.
|
|
||||||
+
|
|
||||||
config NET_SCH_TEQL
|
|
||||||
tristate "True Link Equalizer (TEQL)"
|
|
||||||
---help---
|
|
||||||
--- a/net/sched/Makefile
|
|
||||||
+++ b/net/sched/Makefile
|
|
||||||
@@ -26,6 +26,7 @@ obj-$(CONFIG_NET_SCH_INGRESS) += sch_ing
|
|
||||||
obj-$(CONFIG_NET_SCH_DSMARK) += sch_dsmark.o
|
|
||||||
obj-$(CONFIG_NET_SCH_SFB) += sch_sfb.o
|
|
||||||
obj-$(CONFIG_NET_SCH_SFQ) += sch_sfq.o
|
|
||||||
+obj-$(CONFIG_NET_SCH_ESFQ) += sch_esfq.o
|
|
||||||
obj-$(CONFIG_NET_SCH_TBF) += sch_tbf.o
|
|
||||||
obj-$(CONFIG_NET_SCH_TEQL) += sch_teql.o
|
|
||||||
obj-$(CONFIG_NET_SCH_PRIO) += sch_prio.o
|
|
||||||
--- /dev/null
|
|
||||||
+++ b/net/sched/sch_esfq.c
|
|
||||||
@@ -0,0 +1,702 @@
|
|
||||||
+/*
|
|
||||||
+ * net/sched/sch_esfq.c Extended Stochastic Fairness Queueing discipline.
|
|
||||||
+ *
|
|
||||||
+ * This program is free software; you can redistribute it and/or
|
|
||||||
+ * modify it under the terms of the GNU General Public License
|
|
||||||
+ * as published by the Free Software Foundation; either version
|
|
||||||
+ * 2 of the License, or (at your option) any later version.
|
|
||||||
+ *
|
|
||||||
+ * Authors: Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru>
|
|
||||||
+ *
|
|
||||||
+ * Changes: Alexander Atanasov, <alex@ssi.bg>
|
|
||||||
+ * Added dynamic depth,limit,divisor,hash_kind options.
|
|
||||||
+ * Added dst and src hashes.
|
|
||||||
+ *
|
|
||||||
+ * Alexander Clouter, <alex@digriz.org.uk>
|
|
||||||
+ * Ported ESFQ to Linux 2.6.
|
|
||||||
+ *
|
|
||||||
+ * Corey Hickey, <bugfood-c@fatooh.org>
|
|
||||||
+ * Maintenance of the Linux 2.6 port.
|
|
||||||
+ * Added fwmark hash (thanks to Robert Kurjata).
|
|
||||||
+ * Added usage of jhash.
|
|
||||||
+ * Added conntrack support.
|
|
||||||
+ * Added ctnatchg hash (thanks to Ben Pfountz).
|
|
||||||
+ */
|
|
||||||
+
|
|
||||||
+#include <linux/module.h>
|
|
||||||
+#include <asm/uaccess.h>
|
|
||||||
+#include <asm/system.h>
|
|
||||||
+#include <linux/bitops.h>
|
|
||||||
+#include <linux/types.h>
|
|
||||||
+#include <linux/kernel.h>
|
|
||||||
+#include <linux/jiffies.h>
|
|
||||||
+#include <linux/string.h>
|
|
||||||
+#include <linux/mm.h>
|
|
||||||
+#include <linux/socket.h>
|
|
||||||
+#include <linux/sockios.h>
|
|
||||||
+#include <linux/in.h>
|
|
||||||
+#include <linux/errno.h>
|
|
||||||
+#include <linux/interrupt.h>
|
|
||||||
+#include <linux/if_ether.h>
|
|
||||||
+#include <linux/inet.h>
|
|
||||||
+#include <linux/netdevice.h>
|
|
||||||
+#include <linux/etherdevice.h>
|
|
||||||
+#include <linux/notifier.h>
|
|
||||||
+#include <linux/init.h>
|
|
||||||
+#include <net/ip.h>
|
|
||||||
+#include <net/netlink.h>
|
|
||||||
+#include <linux/ipv6.h>
|
|
||||||
+#include <net/route.h>
|
|
||||||
+#include <linux/skbuff.h>
|
|
||||||
+#include <net/sock.h>
|
|
||||||
+#include <net/pkt_sched.h>
|
|
||||||
+#include <linux/jhash.h>
|
|
||||||
+#ifdef CONFIG_NET_SCH_ESFQ_NFCT
|
|
||||||
+#include <net/netfilter/nf_conntrack.h>
|
|
||||||
+#endif
|
|
||||||
+
|
|
||||||
+/* Stochastic Fairness Queuing algorithm.
|
|
||||||
+ For more comments look at sch_sfq.c.
|
|
||||||
+ The difference is that you can change limit, depth,
|
|
||||||
+ hash table size and choose alternate hash types.
|
|
||||||
+
|
|
||||||
+ classic: same as in sch_sfq.c
|
|
||||||
+ dst: destination IP address
|
|
||||||
+ src: source IP address
|
|
||||||
+ fwmark: netfilter mark value
|
|
||||||
+ ctorigdst: original destination IP address
|
|
||||||
+ ctorigsrc: original source IP address
|
|
||||||
+ ctrepldst: reply destination IP address
|
|
||||||
+ ctreplsrc: reply source IP
|
|
||||||
+
|
|
||||||
+*/
|
|
||||||
+
|
|
||||||
+#define ESFQ_HEAD 0
|
|
||||||
+#define ESFQ_TAIL 1
|
|
||||||
+
|
|
||||||
+/* This type should contain at least SFQ_DEPTH*2 values */
|
|
||||||
+typedef unsigned int esfq_index;
|
|
||||||
+
|
|
||||||
+struct esfq_head
|
|
||||||
+{
|
|
||||||
+ esfq_index next;
|
|
||||||
+ esfq_index prev;
|
|
||||||
+};
|
|
||||||
+
|
|
||||||
+struct esfq_sched_data
|
|
||||||
+{
|
|
||||||
+/* Parameters */
|
|
||||||
+ int perturb_period;
|
|
||||||
+ unsigned quantum; /* Allotment per round: MUST BE >= MTU */
|
|
||||||
+ int limit;
|
|
||||||
+ unsigned depth;
|
|
||||||
+ unsigned hash_divisor;
|
|
||||||
+ unsigned hash_kind;
|
|
||||||
+/* Variables */
|
|
||||||
+ struct timer_list perturb_timer;
|
|
||||||
+ int perturbation;
|
|
||||||
+ esfq_index tail; /* Index of current slot in round */
|
|
||||||
+ esfq_index max_depth; /* Maximal depth */
|
|
||||||
+
|
|
||||||
+ esfq_index *ht; /* Hash table */
|
|
||||||
+ esfq_index *next; /* Active slots link */
|
|
||||||
+ short *allot; /* Current allotment per slot */
|
|
||||||
+ unsigned short *hash; /* Hash value indexed by slots */
|
|
||||||
+ struct sk_buff_head *qs; /* Slot queue */
|
|
||||||
+ struct esfq_head *dep; /* Linked list of slots, indexed by depth */
|
|
||||||
+};
|
|
||||||
+
|
|
||||||
+/* This contains the info we will hash. */
|
|
||||||
+struct esfq_packet_info
|
|
||||||
+{
|
|
||||||
+ u32 proto; /* protocol or port */
|
|
||||||
+ u32 src; /* source from packet header */
|
|
||||||
+ u32 dst; /* destination from packet header */
|
|
||||||
+ u32 ctorigsrc; /* original source from conntrack */
|
|
||||||
+ u32 ctorigdst; /* original destination from conntrack */
|
|
||||||
+ u32 ctreplsrc; /* reply source from conntrack */
|
|
||||||
+ u32 ctrepldst; /* reply destination from conntrack */
|
|
||||||
+ u32 mark; /* netfilter mark (fwmark) */
|
|
||||||
+};
|
|
||||||
+
|
|
||||||
+static __inline__ unsigned esfq_jhash_1word(struct esfq_sched_data *q,u32 a)
|
|
||||||
+{
|
|
||||||
+ return jhash_1word(a, q->perturbation) & (q->hash_divisor-1);
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static __inline__ unsigned esfq_jhash_2words(struct esfq_sched_data *q, u32 a, u32 b)
|
|
||||||
+{
|
|
||||||
+ return jhash_2words(a, b, q->perturbation) & (q->hash_divisor-1);
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static __inline__ unsigned esfq_jhash_3words(struct esfq_sched_data *q, u32 a, u32 b, u32 c)
|
|
||||||
+{
|
|
||||||
+ return jhash_3words(a, b, c, q->perturbation) & (q->hash_divisor-1);
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static unsigned esfq_hash(struct esfq_sched_data *q, struct sk_buff *skb)
|
|
||||||
+{
|
|
||||||
+ struct esfq_packet_info info;
|
|
||||||
+#ifdef CONFIG_NET_SCH_ESFQ_NFCT
|
|
||||||
+ enum ip_conntrack_info ctinfo;
|
|
||||||
+ struct nf_conn *ct = nf_ct_get(skb, &ctinfo);
|
|
||||||
+#endif
|
|
||||||
+
|
|
||||||
+ switch (skb->protocol) {
|
|
||||||
+ case __constant_htons(ETH_P_IP):
|
|
||||||
+ {
|
|
||||||
+ struct iphdr *iph = ip_hdr(skb);
|
|
||||||
+ info.dst = iph->daddr;
|
|
||||||
+ info.src = iph->saddr;
|
|
||||||
+ if (!(iph->frag_off&htons(IP_MF|IP_OFFSET)) &&
|
|
||||||
+ (iph->protocol == IPPROTO_TCP ||
|
|
||||||
+ iph->protocol == IPPROTO_UDP ||
|
|
||||||
+ iph->protocol == IPPROTO_SCTP ||
|
|
||||||
+ iph->protocol == IPPROTO_DCCP ||
|
|
||||||
+ iph->protocol == IPPROTO_ESP))
|
|
||||||
+ info.proto = *(((u32*)iph) + iph->ihl);
|
|
||||||
+ else
|
|
||||||
+ info.proto = iph->protocol;
|
|
||||||
+ break;
|
|
||||||
+ }
|
|
||||||
+ case __constant_htons(ETH_P_IPV6):
|
|
||||||
+ {
|
|
||||||
+ struct ipv6hdr *iph = ipv6_hdr(skb);
|
|
||||||
+ /* Hash ipv6 addresses into a u32. This isn't ideal,
|
|
||||||
+ * but the code is simple. */
|
|
||||||
+ info.dst = jhash2(iph->daddr.s6_addr32, 4, q->perturbation);
|
|
||||||
+ info.src = jhash2(iph->saddr.s6_addr32, 4, q->perturbation);
|
|
||||||
+ if (iph->nexthdr == IPPROTO_TCP ||
|
|
||||||
+ iph->nexthdr == IPPROTO_UDP ||
|
|
||||||
+ iph->nexthdr == IPPROTO_SCTP ||
|
|
||||||
+ iph->nexthdr == IPPROTO_DCCP ||
|
|
||||||
+ iph->nexthdr == IPPROTO_ESP)
|
|
||||||
+ info.proto = *(u32*)&iph[1];
|
|
||||||
+ else
|
|
||||||
+ info.proto = iph->nexthdr;
|
|
||||||
+ break;
|
|
||||||
+ }
|
|
||||||
+ default:
|
|
||||||
+ info.dst = (u32)(unsigned long)skb_dst(skb);
|
|
||||||
+ info.src = (u32)(unsigned long)skb->sk;
|
|
||||||
+ info.proto = skb->protocol;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ info.mark = skb->mark;
|
|
||||||
+
|
|
||||||
+#ifdef CONFIG_NET_SCH_ESFQ_NFCT
|
|
||||||
+ /* defaults if there is no conntrack info */
|
|
||||||
+ info.ctorigsrc = info.src;
|
|
||||||
+ info.ctorigdst = info.dst;
|
|
||||||
+ info.ctreplsrc = info.dst;
|
|
||||||
+ info.ctrepldst = info.src;
|
|
||||||
+ /* collect conntrack info */
|
|
||||||
+ if (ct && ct != &nf_conntrack_untracked) {
|
|
||||||
+ if (skb->protocol == __constant_htons(ETH_P_IP)) {
|
|
||||||
+ info.ctorigsrc = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u3.ip;
|
|
||||||
+ info.ctorigdst = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.u3.ip;
|
|
||||||
+ info.ctreplsrc = ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.u3.ip;
|
|
||||||
+ info.ctrepldst = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u3.ip;
|
|
||||||
+ }
|
|
||||||
+ else if (skb->protocol == __constant_htons(ETH_P_IPV6)) {
|
|
||||||
+ /* Again, hash ipv6 addresses into a single u32. */
|
|
||||||
+ info.ctorigsrc = jhash2(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u3.ip6, 4, q->perturbation);
|
|
||||||
+ info.ctorigdst = jhash2(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.u3.ip6, 4, q->perturbation);
|
|
||||||
+ info.ctreplsrc = jhash2(ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.u3.ip6, 4, q->perturbation);
|
|
||||||
+ info.ctrepldst = jhash2(ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u3.ip6, 4, q->perturbation);
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ }
|
|
||||||
+#endif
|
|
||||||
+
|
|
||||||
+ switch(q->hash_kind) {
|
|
||||||
+ case TCA_SFQ_HASH_CLASSIC:
|
|
||||||
+ return esfq_jhash_3words(q, info.dst, info.src, info.proto);
|
|
||||||
+ case TCA_SFQ_HASH_DST:
|
|
||||||
+ return esfq_jhash_1word(q, info.dst);
|
|
||||||
+ case TCA_SFQ_HASH_SRC:
|
|
||||||
+ return esfq_jhash_1word(q, info.src);
|
|
||||||
+ case TCA_SFQ_HASH_FWMARK:
|
|
||||||
+ return esfq_jhash_1word(q, info.mark);
|
|
||||||
+#ifdef CONFIG_NET_SCH_ESFQ_NFCT
|
|
||||||
+ case TCA_SFQ_HASH_CTORIGDST:
|
|
||||||
+ return esfq_jhash_1word(q, info.ctorigdst);
|
|
||||||
+ case TCA_SFQ_HASH_CTORIGSRC:
|
|
||||||
+ return esfq_jhash_1word(q, info.ctorigsrc);
|
|
||||||
+ case TCA_SFQ_HASH_CTREPLDST:
|
|
||||||
+ return esfq_jhash_1word(q, info.ctrepldst);
|
|
||||||
+ case TCA_SFQ_HASH_CTREPLSRC:
|
|
||||||
+ return esfq_jhash_1word(q, info.ctreplsrc);
|
|
||||||
+ case TCA_SFQ_HASH_CTNATCHG:
|
|
||||||
+ {
|
|
||||||
+ if (info.ctorigdst == info.ctreplsrc)
|
|
||||||
+ return esfq_jhash_1word(q, info.ctorigsrc);
|
|
||||||
+ return esfq_jhash_1word(q, info.ctreplsrc);
|
|
||||||
+ }
|
|
||||||
+#endif
|
|
||||||
+ default:
|
|
||||||
+ if (net_ratelimit())
|
|
||||||
+ printk(KERN_WARNING "ESFQ: Unknown hash method. Falling back to classic.\n");
|
|
||||||
+ }
|
|
||||||
+ return esfq_jhash_3words(q, info.dst, info.src, info.proto);
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static inline void esfq_link(struct esfq_sched_data *q, esfq_index x)
|
|
||||||
+{
|
|
||||||
+ esfq_index p, n;
|
|
||||||
+ int d = q->qs[x].qlen + q->depth;
|
|
||||||
+
|
|
||||||
+ p = d;
|
|
||||||
+ n = q->dep[d].next;
|
|
||||||
+ q->dep[x].next = n;
|
|
||||||
+ q->dep[x].prev = p;
|
|
||||||
+ q->dep[p].next = q->dep[n].prev = x;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static inline void esfq_dec(struct esfq_sched_data *q, esfq_index x)
|
|
||||||
+{
|
|
||||||
+ esfq_index p, n;
|
|
||||||
+
|
|
||||||
+ n = q->dep[x].next;
|
|
||||||
+ p = q->dep[x].prev;
|
|
||||||
+ q->dep[p].next = n;
|
|
||||||
+ q->dep[n].prev = p;
|
|
||||||
+
|
|
||||||
+ if (n == p && q->max_depth == q->qs[x].qlen + 1)
|
|
||||||
+ q->max_depth--;
|
|
||||||
+
|
|
||||||
+ esfq_link(q, x);
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static inline void esfq_inc(struct esfq_sched_data *q, esfq_index x)
|
|
||||||
+{
|
|
||||||
+ esfq_index p, n;
|
|
||||||
+ int d;
|
|
||||||
+
|
|
||||||
+ n = q->dep[x].next;
|
|
||||||
+ p = q->dep[x].prev;
|
|
||||||
+ q->dep[p].next = n;
|
|
||||||
+ q->dep[n].prev = p;
|
|
||||||
+ d = q->qs[x].qlen;
|
|
||||||
+ if (q->max_depth < d)
|
|
||||||
+ q->max_depth = d;
|
|
||||||
+
|
|
||||||
+ esfq_link(q, x);
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static unsigned int esfq_drop(struct Qdisc *sch)
|
|
||||||
+{
|
|
||||||
+ struct esfq_sched_data *q = qdisc_priv(sch);
|
|
||||||
+ esfq_index d = q->max_depth;
|
|
||||||
+ struct sk_buff *skb;
|
|
||||||
+ unsigned int len;
|
|
||||||
+
|
|
||||||
+ /* Queue is full! Find the longest slot and
|
|
||||||
+ drop a packet from it */
|
|
||||||
+
|
|
||||||
+ if (d > 1) {
|
|
||||||
+ esfq_index x = q->dep[d+q->depth].next;
|
|
||||||
+ skb = q->qs[x].prev;
|
|
||||||
+ len = skb->len;
|
|
||||||
+ __skb_unlink(skb, &q->qs[x]);
|
|
||||||
+ kfree_skb(skb);
|
|
||||||
+ esfq_dec(q, x);
|
|
||||||
+ sch->q.qlen--;
|
|
||||||
+ sch->qstats.drops++;
|
|
||||||
+ sch->qstats.backlog -= len;
|
|
||||||
+ return len;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ if (d == 1) {
|
|
||||||
+ /* It is difficult to believe, but ALL THE SLOTS HAVE LENGTH 1. */
|
|
||||||
+ d = q->next[q->tail];
|
|
||||||
+ q->next[q->tail] = q->next[d];
|
|
||||||
+ q->allot[q->next[d]] += q->quantum;
|
|
||||||
+ skb = q->qs[d].prev;
|
|
||||||
+ len = skb->len;
|
|
||||||
+ __skb_unlink(skb, &q->qs[d]);
|
|
||||||
+ kfree_skb(skb);
|
|
||||||
+ esfq_dec(q, d);
|
|
||||||
+ sch->q.qlen--;
|
|
||||||
+ q->ht[q->hash[d]] = q->depth;
|
|
||||||
+ sch->qstats.drops++;
|
|
||||||
+ sch->qstats.backlog -= len;
|
|
||||||
+ return len;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ return 0;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static void esfq_q_enqueue(struct sk_buff *skb, struct esfq_sched_data *q, unsigned int end)
|
|
||||||
+{
|
|
||||||
+ unsigned hash = esfq_hash(q, skb);
|
|
||||||
+ unsigned depth = q->depth;
|
|
||||||
+ esfq_index x;
|
|
||||||
+
|
|
||||||
+ x = q->ht[hash];
|
|
||||||
+ if (x == depth) {
|
|
||||||
+ q->ht[hash] = x = q->dep[depth].next;
|
|
||||||
+ q->hash[x] = hash;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ if (end == ESFQ_TAIL)
|
|
||||||
+ __skb_queue_tail(&q->qs[x], skb);
|
|
||||||
+ else
|
|
||||||
+ __skb_queue_head(&q->qs[x], skb);
|
|
||||||
+
|
|
||||||
+ esfq_inc(q, x);
|
|
||||||
+ if (q->qs[x].qlen == 1) { /* The flow is new */
|
|
||||||
+ if (q->tail == depth) { /* It is the first flow */
|
|
||||||
+ q->tail = x;
|
|
||||||
+ q->next[x] = x;
|
|
||||||
+ q->allot[x] = q->quantum;
|
|
||||||
+ } else {
|
|
||||||
+ q->next[x] = q->next[q->tail];
|
|
||||||
+ q->next[q->tail] = x;
|
|
||||||
+ q->tail = x;
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static int esfq_enqueue(struct sk_buff *skb, struct Qdisc* sch)
|
|
||||||
+{
|
|
||||||
+ struct esfq_sched_data *q = qdisc_priv(sch);
|
|
||||||
+ esfq_q_enqueue(skb, q, ESFQ_TAIL);
|
|
||||||
+ sch->qstats.backlog += skb->len;
|
|
||||||
+ if (++sch->q.qlen < q->limit-1) {
|
|
||||||
+ sch->bstats.bytes += skb->len;
|
|
||||||
+ sch->bstats.packets++;
|
|
||||||
+ return 0;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ sch->qstats.drops++;
|
|
||||||
+ esfq_drop(sch);
|
|
||||||
+ return NET_XMIT_CN;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static struct sk_buff *esfq_peek(struct Qdisc* sch)
|
|
||||||
+{
|
|
||||||
+ struct esfq_sched_data *q = qdisc_priv(sch);
|
|
||||||
+ esfq_index a;
|
|
||||||
+
|
|
||||||
+ /* No active slots */
|
|
||||||
+ if (q->tail == q->depth)
|
|
||||||
+ return NULL;
|
|
||||||
+
|
|
||||||
+ a = q->next[q->tail];
|
|
||||||
+ return skb_peek(&q->qs[a]);
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static struct sk_buff *esfq_q_dequeue(struct esfq_sched_data *q)
|
|
||||||
+{
|
|
||||||
+ struct sk_buff *skb;
|
|
||||||
+ unsigned depth = q->depth;
|
|
||||||
+ esfq_index a, old_a;
|
|
||||||
+
|
|
||||||
+ /* No active slots */
|
|
||||||
+ if (q->tail == depth)
|
|
||||||
+ return NULL;
|
|
||||||
+
|
|
||||||
+ a = old_a = q->next[q->tail];
|
|
||||||
+
|
|
||||||
+ /* Grab packet */
|
|
||||||
+ skb = __skb_dequeue(&q->qs[a]);
|
|
||||||
+ esfq_dec(q, a);
|
|
||||||
+
|
|
||||||
+ /* Is the slot empty? */
|
|
||||||
+ if (q->qs[a].qlen == 0) {
|
|
||||||
+ q->ht[q->hash[a]] = depth;
|
|
||||||
+ a = q->next[a];
|
|
||||||
+ if (a == old_a) {
|
|
||||||
+ q->tail = depth;
|
|
||||||
+ return skb;
|
|
||||||
+ }
|
|
||||||
+ q->next[q->tail] = a;
|
|
||||||
+ q->allot[a] += q->quantum;
|
|
||||||
+ } else if ((q->allot[a] -= skb->len) <= 0) {
|
|
||||||
+ q->tail = a;
|
|
||||||
+ a = q->next[a];
|
|
||||||
+ q->allot[a] += q->quantum;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ return skb;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static struct sk_buff *esfq_dequeue(struct Qdisc* sch)
|
|
||||||
+{
|
|
||||||
+ struct esfq_sched_data *q = qdisc_priv(sch);
|
|
||||||
+ struct sk_buff *skb;
|
|
||||||
+
|
|
||||||
+ skb = esfq_q_dequeue(q);
|
|
||||||
+ if (skb == NULL)
|
|
||||||
+ return NULL;
|
|
||||||
+ sch->q.qlen--;
|
|
||||||
+ sch->qstats.backlog -= skb->len;
|
|
||||||
+ return skb;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static void esfq_q_destroy(struct esfq_sched_data *q)
|
|
||||||
+{
|
|
||||||
+ del_timer(&q->perturb_timer);
|
|
||||||
+ if(q->ht)
|
|
||||||
+ kfree(q->ht);
|
|
||||||
+ if(q->dep)
|
|
||||||
+ kfree(q->dep);
|
|
||||||
+ if(q->next)
|
|
||||||
+ kfree(q->next);
|
|
||||||
+ if(q->allot)
|
|
||||||
+ kfree(q->allot);
|
|
||||||
+ if(q->hash)
|
|
||||||
+ kfree(q->hash);
|
|
||||||
+ if(q->qs)
|
|
||||||
+ kfree(q->qs);
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static void esfq_destroy(struct Qdisc *sch)
|
|
||||||
+{
|
|
||||||
+ struct esfq_sched_data *q = qdisc_priv(sch);
|
|
||||||
+ esfq_q_destroy(q);
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+
|
|
||||||
+static void esfq_reset(struct Qdisc* sch)
|
|
||||||
+{
|
|
||||||
+ struct sk_buff *skb;
|
|
||||||
+
|
|
||||||
+ while ((skb = esfq_dequeue(sch)) != NULL)
|
|
||||||
+ kfree_skb(skb);
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static void esfq_perturbation(unsigned long arg)
|
|
||||||
+{
|
|
||||||
+ struct Qdisc *sch = (struct Qdisc*)arg;
|
|
||||||
+ struct esfq_sched_data *q = qdisc_priv(sch);
|
|
||||||
+
|
|
||||||
+ q->perturbation = net_random()&0x1F;
|
|
||||||
+
|
|
||||||
+ if (q->perturb_period) {
|
|
||||||
+ q->perturb_timer.expires = jiffies + q->perturb_period;
|
|
||||||
+ add_timer(&q->perturb_timer);
|
|
||||||
+ }
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static unsigned int esfq_check_hash(unsigned int kind)
|
|
||||||
+{
|
|
||||||
+ switch (kind) {
|
|
||||||
+ case TCA_SFQ_HASH_CTORIGDST:
|
|
||||||
+ case TCA_SFQ_HASH_CTORIGSRC:
|
|
||||||
+ case TCA_SFQ_HASH_CTREPLDST:
|
|
||||||
+ case TCA_SFQ_HASH_CTREPLSRC:
|
|
||||||
+ case TCA_SFQ_HASH_CTNATCHG:
|
|
||||||
+#ifndef CONFIG_NET_SCH_ESFQ_NFCT
|
|
||||||
+ {
|
|
||||||
+ if (net_ratelimit())
|
|
||||||
+ printk(KERN_WARNING "ESFQ: Conntrack hash types disabled in kernel config. Falling back to classic.\n");
|
|
||||||
+ return TCA_SFQ_HASH_CLASSIC;
|
|
||||||
+ }
|
|
||||||
+#endif
|
|
||||||
+ case TCA_SFQ_HASH_CLASSIC:
|
|
||||||
+ case TCA_SFQ_HASH_DST:
|
|
||||||
+ case TCA_SFQ_HASH_SRC:
|
|
||||||
+ case TCA_SFQ_HASH_FWMARK:
|
|
||||||
+ return kind;
|
|
||||||
+ default:
|
|
||||||
+ {
|
|
||||||
+ if (net_ratelimit())
|
|
||||||
+ printk(KERN_WARNING "ESFQ: Unknown hash type. Falling back to classic.\n");
|
|
||||||
+ return TCA_SFQ_HASH_CLASSIC;
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static int esfq_q_init(struct esfq_sched_data *q, struct nlattr *opt)
|
|
||||||
+{
|
|
||||||
+ struct tc_esfq_qopt *ctl = nla_data(opt);
|
|
||||||
+ esfq_index p = ~0U/2;
|
|
||||||
+ int i;
|
|
||||||
+
|
|
||||||
+ if (opt && opt->nla_len < nla_attr_size(sizeof(*ctl)))
|
|
||||||
+ return -EINVAL;
|
|
||||||
+
|
|
||||||
+ q->perturbation = 0;
|
|
||||||
+ q->hash_kind = TCA_SFQ_HASH_CLASSIC;
|
|
||||||
+ q->max_depth = 0;
|
|
||||||
+ if (opt == NULL) {
|
|
||||||
+ q->perturb_period = 0;
|
|
||||||
+ q->hash_divisor = 1024;
|
|
||||||
+ q->tail = q->limit = q->depth = 128;
|
|
||||||
+
|
|
||||||
+ } else {
|
|
||||||
+ struct tc_esfq_qopt *ctl = nla_data(opt);
|
|
||||||
+ if (ctl->quantum)
|
|
||||||
+ q->quantum = ctl->quantum;
|
|
||||||
+ q->perturb_period = ctl->perturb_period*HZ;
|
|
||||||
+ q->hash_divisor = ctl->divisor ? : 1024;
|
|
||||||
+ q->tail = q->limit = q->depth = ctl->flows ? : 128;
|
|
||||||
+
|
|
||||||
+ if ( q->depth > p - 1 )
|
|
||||||
+ return -EINVAL;
|
|
||||||
+
|
|
||||||
+ if (ctl->limit)
|
|
||||||
+ q->limit = min_t(u32, ctl->limit, q->depth);
|
|
||||||
+
|
|
||||||
+ if (ctl->hash_kind) {
|
|
||||||
+ q->hash_kind = esfq_check_hash(ctl->hash_kind);
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ q->ht = kmalloc(q->hash_divisor*sizeof(esfq_index), GFP_KERNEL);
|
|
||||||
+ if (!q->ht)
|
|
||||||
+ goto err_case;
|
|
||||||
+ q->dep = kmalloc((1+q->depth*2)*sizeof(struct esfq_head), GFP_KERNEL);
|
|
||||||
+ if (!q->dep)
|
|
||||||
+ goto err_case;
|
|
||||||
+ q->next = kmalloc(q->depth*sizeof(esfq_index), GFP_KERNEL);
|
|
||||||
+ if (!q->next)
|
|
||||||
+ goto err_case;
|
|
||||||
+ q->allot = kmalloc(q->depth*sizeof(short), GFP_KERNEL);
|
|
||||||
+ if (!q->allot)
|
|
||||||
+ goto err_case;
|
|
||||||
+ q->hash = kmalloc(q->depth*sizeof(unsigned short), GFP_KERNEL);
|
|
||||||
+ if (!q->hash)
|
|
||||||
+ goto err_case;
|
|
||||||
+ q->qs = kmalloc(q->depth*sizeof(struct sk_buff_head), GFP_KERNEL);
|
|
||||||
+ if (!q->qs)
|
|
||||||
+ goto err_case;
|
|
||||||
+
|
|
||||||
+ for (i=0; i< q->hash_divisor; i++)
|
|
||||||
+ q->ht[i] = q->depth;
|
|
||||||
+ for (i=0; i<q->depth; i++) {
|
|
||||||
+ skb_queue_head_init(&q->qs[i]);
|
|
||||||
+ q->dep[i+q->depth].next = i+q->depth;
|
|
||||||
+ q->dep[i+q->depth].prev = i+q->depth;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ for (i=0; i<q->depth; i++)
|
|
||||||
+ esfq_link(q, i);
|
|
||||||
+ return 0;
|
|
||||||
+err_case:
|
|
||||||
+ esfq_q_destroy(q);
|
|
||||||
+ return -ENOBUFS;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static int esfq_init(struct Qdisc *sch, struct nlattr *opt)
|
|
||||||
+{
|
|
||||||
+ struct esfq_sched_data *q = qdisc_priv(sch);
|
|
||||||
+ int err;
|
|
||||||
+
|
|
||||||
+ q->quantum = psched_mtu(qdisc_dev(sch)); /* default */
|
|
||||||
+ if ((err = esfq_q_init(q, opt)))
|
|
||||||
+ return err;
|
|
||||||
+
|
|
||||||
+ init_timer(&q->perturb_timer);
|
|
||||||
+ q->perturb_timer.data = (unsigned long)sch;
|
|
||||||
+ q->perturb_timer.function = esfq_perturbation;
|
|
||||||
+ if (q->perturb_period) {
|
|
||||||
+ q->perturb_timer.expires = jiffies + q->perturb_period;
|
|
||||||
+ add_timer(&q->perturb_timer);
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ return 0;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static int esfq_change(struct Qdisc *sch, struct nlattr *opt)
|
|
||||||
+{
|
|
||||||
+ struct esfq_sched_data *q = qdisc_priv(sch);
|
|
||||||
+ struct esfq_sched_data new;
|
|
||||||
+ struct sk_buff *skb;
|
|
||||||
+ int err;
|
|
||||||
+
|
|
||||||
+ /* set up new queue */
|
|
||||||
+ memset(&new, 0, sizeof(struct esfq_sched_data));
|
|
||||||
+ new.quantum = psched_mtu(qdisc_dev(sch)); /* default */
|
|
||||||
+ if ((err = esfq_q_init(&new, opt)))
|
|
||||||
+ return err;
|
|
||||||
+
|
|
||||||
+ /* copy all packets from the old queue to the new queue */
|
|
||||||
+ sch_tree_lock(sch);
|
|
||||||
+ while ((skb = esfq_q_dequeue(q)) != NULL)
|
|
||||||
+ esfq_q_enqueue(skb, &new, ESFQ_TAIL);
|
|
||||||
+
|
|
||||||
+ /* clean up the old queue */
|
|
||||||
+ esfq_q_destroy(q);
|
|
||||||
+
|
|
||||||
+ /* copy elements of the new queue into the old queue */
|
|
||||||
+ q->perturb_period = new.perturb_period;
|
|
||||||
+ q->quantum = new.quantum;
|
|
||||||
+ q->limit = new.limit;
|
|
||||||
+ q->depth = new.depth;
|
|
||||||
+ q->hash_divisor = new.hash_divisor;
|
|
||||||
+ q->hash_kind = new.hash_kind;
|
|
||||||
+ q->tail = new.tail;
|
|
||||||
+ q->max_depth = new.max_depth;
|
|
||||||
+ q->ht = new.ht;
|
|
||||||
+ q->dep = new.dep;
|
|
||||||
+ q->next = new.next;
|
|
||||||
+ q->allot = new.allot;
|
|
||||||
+ q->hash = new.hash;
|
|
||||||
+ q->qs = new.qs;
|
|
||||||
+
|
|
||||||
+ /* finish up */
|
|
||||||
+ if (q->perturb_period) {
|
|
||||||
+ q->perturb_timer.expires = jiffies + q->perturb_period;
|
|
||||||
+ add_timer(&q->perturb_timer);
|
|
||||||
+ } else {
|
|
||||||
+ q->perturbation = 0;
|
|
||||||
+ }
|
|
||||||
+ sch_tree_unlock(sch);
|
|
||||||
+ return 0;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static int esfq_dump(struct Qdisc *sch, struct sk_buff *skb)
|
|
||||||
+{
|
|
||||||
+ struct esfq_sched_data *q = qdisc_priv(sch);
|
|
||||||
+ unsigned char *b = skb_tail_pointer(skb);
|
|
||||||
+ struct tc_esfq_qopt opt;
|
|
||||||
+
|
|
||||||
+ opt.quantum = q->quantum;
|
|
||||||
+ opt.perturb_period = q->perturb_period/HZ;
|
|
||||||
+
|
|
||||||
+ opt.limit = q->limit;
|
|
||||||
+ opt.divisor = q->hash_divisor;
|
|
||||||
+ opt.flows = q->depth;
|
|
||||||
+ opt.hash_kind = q->hash_kind;
|
|
||||||
+
|
|
||||||
+ NLA_PUT(skb, TCA_OPTIONS, sizeof(opt), &opt);
|
|
||||||
+
|
|
||||||
+ return skb->len;
|
|
||||||
+
|
|
||||||
+nla_put_failure:
|
|
||||||
+ nlmsg_trim(skb, b);
|
|
||||||
+ return -1;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static struct Qdisc_ops esfq_qdisc_ops =
|
|
||||||
+{
|
|
||||||
+ .next = NULL,
|
|
||||||
+ .cl_ops = NULL,
|
|
||||||
+ .id = "esfq",
|
|
||||||
+ .priv_size = sizeof(struct esfq_sched_data),
|
|
||||||
+ .enqueue = esfq_enqueue,
|
|
||||||
+ .dequeue = esfq_dequeue,
|
|
||||||
+ .peek = esfq_peek,
|
|
||||||
+ .drop = esfq_drop,
|
|
||||||
+ .init = esfq_init,
|
|
||||||
+ .reset = esfq_reset,
|
|
||||||
+ .destroy = esfq_destroy,
|
|
||||||
+ .change = esfq_change,
|
|
||||||
+ .dump = esfq_dump,
|
|
||||||
+ .owner = THIS_MODULE,
|
|
||||||
+};
|
|
||||||
+
|
|
||||||
+static int __init esfq_module_init(void)
|
|
||||||
+{
|
|
||||||
+ return register_qdisc(&esfq_qdisc_ops);
|
|
||||||
+}
|
|
||||||
+static void __exit esfq_module_exit(void)
|
|
||||||
+{
|
|
||||||
+ unregister_qdisc(&esfq_qdisc_ops);
|
|
||||||
+}
|
|
||||||
+module_init(esfq_module_init)
|
|
||||||
+module_exit(esfq_module_exit)
|
|
||||||
+MODULE_LICENSE("GPL");
|
|
|
@ -1,172 +0,0 @@
|
||||||
--- /dev/null
|
|
||||||
+++ b/net/sched/act_connmark.c
|
|
||||||
@@ -0,0 +1,137 @@
|
|
||||||
+/*
|
|
||||||
+ * Copyright (c) 2011 Felix Fietkau <nbd@openwrt.org>
|
|
||||||
+ *
|
|
||||||
+ * This program is free software; you can redistribute it and/or modify it
|
|
||||||
+ * under the terms and conditions of the GNU General Public License,
|
|
||||||
+ * version 2, as published by the Free Software Foundation.
|
|
||||||
+ *
|
|
||||||
+ * This program is distributed in the hope it will be useful, but WITHOUT
|
|
||||||
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
||||||
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
|
||||||
+ * more details.
|
|
||||||
+ *
|
|
||||||
+ * You should have received a copy of the GNU General Public License along with
|
|
||||||
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
|
|
||||||
+ * Place - Suite 330, Boston, MA 02111-1307 USA.
|
|
||||||
+ */
|
|
||||||
+
|
|
||||||
+#include <linux/module.h>
|
|
||||||
+#include <linux/init.h>
|
|
||||||
+#include <linux/kernel.h>
|
|
||||||
+#include <linux/skbuff.h>
|
|
||||||
+#include <linux/rtnetlink.h>
|
|
||||||
+#include <linux/pkt_cls.h>
|
|
||||||
+#include <linux/ip.h>
|
|
||||||
+#include <linux/ipv6.h>
|
|
||||||
+#include <net/netlink.h>
|
|
||||||
+#include <net/pkt_sched.h>
|
|
||||||
+#include <net/act_api.h>
|
|
||||||
+
|
|
||||||
+#include <net/netfilter/nf_conntrack.h>
|
|
||||||
+#include <net/netfilter/nf_conntrack_core.h>
|
|
||||||
+
|
|
||||||
+#define TCA_ACT_CONNMARK 20
|
|
||||||
+
|
|
||||||
+#define CONNMARK_TAB_MASK 3
|
|
||||||
+static struct tcf_common *tcf_connmark_ht[CONNMARK_TAB_MASK + 1];
|
|
||||||
+static u32 connmark_idx_gen;
|
|
||||||
+static DEFINE_RWLOCK(connmark_lock);
|
|
||||||
+
|
|
||||||
+static struct tcf_hashinfo connmark_hash_info = {
|
|
||||||
+ .htab = tcf_connmark_ht,
|
|
||||||
+ .hmask = CONNMARK_TAB_MASK,
|
|
||||||
+ .lock = &connmark_lock,
|
|
||||||
+};
|
|
||||||
+
|
|
||||||
+static int tcf_connmark(struct sk_buff *skb, struct tc_action *a,
|
|
||||||
+ struct tcf_result *res)
|
|
||||||
+{
|
|
||||||
+ struct nf_conn *c;
|
|
||||||
+ enum ip_conntrack_info ctinfo;
|
|
||||||
+ int proto;
|
|
||||||
+ int r;
|
|
||||||
+
|
|
||||||
+ if (skb->protocol == htons(ETH_P_IP)) {
|
|
||||||
+ if (skb->len < sizeof(struct iphdr))
|
|
||||||
+ goto out;
|
|
||||||
+ proto = PF_INET;
|
|
||||||
+ } else if (skb->protocol == htons(ETH_P_IPV6)) {
|
|
||||||
+ if (skb->len < sizeof(struct ipv6hdr))
|
|
||||||
+ goto out;
|
|
||||||
+ proto = PF_INET6;
|
|
||||||
+ } else
|
|
||||||
+ goto out;
|
|
||||||
+
|
|
||||||
+ r = nf_conntrack_in(dev_net(skb->dev), proto, NF_INET_PRE_ROUTING, skb);
|
|
||||||
+ if (r != NF_ACCEPT)
|
|
||||||
+ goto out;
|
|
||||||
+
|
|
||||||
+ c = nf_ct_get(skb, &ctinfo);
|
|
||||||
+ if (!c)
|
|
||||||
+ goto out;
|
|
||||||
+
|
|
||||||
+ skb->mark = c->mark;
|
|
||||||
+ nf_conntrack_put(skb->nfct);
|
|
||||||
+ skb->nfct = NULL;
|
|
||||||
+
|
|
||||||
+out:
|
|
||||||
+ return TC_ACT_PIPE;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static int tcf_connmark_init(struct nlattr *nla, struct nlattr *est,
|
|
||||||
+ struct tc_action *a, int ovr, int bind)
|
|
||||||
+{
|
|
||||||
+ struct tcf_common *pc;
|
|
||||||
+
|
|
||||||
+ pc = tcf_hash_create(0, est, a, sizeof(*pc), bind,
|
|
||||||
+ &connmark_idx_gen, &connmark_hash_info);
|
|
||||||
+ if (IS_ERR(pc))
|
|
||||||
+ return PTR_ERR(pc);
|
|
||||||
+
|
|
||||||
+ tcf_hash_insert(pc, &connmark_hash_info);
|
|
||||||
+
|
|
||||||
+ return ACT_P_CREATED;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static inline int tcf_connmark_cleanup(struct tc_action *a, int bind)
|
|
||||||
+{
|
|
||||||
+ if (a->priv)
|
|
||||||
+ return tcf_hash_release(a->priv, bind, &connmark_hash_info);
|
|
||||||
+ return 0;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static inline int tcf_connmark_dump(struct sk_buff *skb, struct tc_action *a,
|
|
||||||
+ int bind, int ref)
|
|
||||||
+{
|
|
||||||
+ return skb->len;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static struct tc_action_ops act_connmark_ops = {
|
|
||||||
+ .kind = "connmark",
|
|
||||||
+ .hinfo = &connmark_hash_info,
|
|
||||||
+ .type = TCA_ACT_CONNMARK,
|
|
||||||
+ .capab = TCA_CAP_NONE,
|
|
||||||
+ .owner = THIS_MODULE,
|
|
||||||
+ .act = tcf_connmark,
|
|
||||||
+ .dump = tcf_connmark_dump,
|
|
||||||
+ .cleanup = tcf_connmark_cleanup,
|
|
||||||
+ .init = tcf_connmark_init,
|
|
||||||
+ .walk = tcf_generic_walker,
|
|
||||||
+};
|
|
||||||
+
|
|
||||||
+MODULE_AUTHOR("Felix Fietkau <nbd@openwrt.org>");
|
|
||||||
+MODULE_DESCRIPTION("Connection tracking mark restoring");
|
|
||||||
+MODULE_LICENSE("GPL");
|
|
||||||
+
|
|
||||||
+static int __init connmark_init_module(void)
|
|
||||||
+{
|
|
||||||
+ return tcf_register_action(&act_connmark_ops);
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static void __exit connmark_cleanup_module(void)
|
|
||||||
+{
|
|
||||||
+ tcf_unregister_action(&act_connmark_ops);
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+module_init(connmark_init_module);
|
|
||||||
+module_exit(connmark_cleanup_module);
|
|
||||||
--- a/net/sched/Kconfig
|
|
||||||
+++ b/net/sched/Kconfig
|
|
||||||
@@ -602,6 +602,19 @@ config NET_ACT_CSUM
|
|
||||||
To compile this code as a module, choose M here: the
|
|
||||||
module will be called act_csum.
|
|
||||||
|
|
||||||
+config NET_ACT_CONNMARK
|
|
||||||
+ tristate "Connection Tracking Marking"
|
|
||||||
+ depends on NET_CLS_ACT
|
|
||||||
+ depends on NF_CONNTRACK
|
|
||||||
+ depends on NF_CONNTRACK_MARK
|
|
||||||
+ ---help---
|
|
||||||
+ Say Y here to restore the connmark from a scheduler action
|
|
||||||
+
|
|
||||||
+ If unsure, say N.
|
|
||||||
+
|
|
||||||
+ To compile this code as a module, choose M here: the
|
|
||||||
+ module will be called act_connmark.
|
|
||||||
+
|
|
||||||
config NET_CLS_IND
|
|
||||||
bool "Incoming device classification"
|
|
||||||
depends on NET_CLS_U32 || NET_CLS_FW
|
|
||||||
--- a/net/sched/Makefile
|
|
||||||
+++ b/net/sched/Makefile
|
|
||||||
@@ -16,6 +16,7 @@ obj-$(CONFIG_NET_ACT_PEDIT) += act_pedit
|
|
||||||
obj-$(CONFIG_NET_ACT_SIMP) += act_simple.o
|
|
||||||
obj-$(CONFIG_NET_ACT_SKBEDIT) += act_skbedit.o
|
|
||||||
obj-$(CONFIG_NET_ACT_CSUM) += act_csum.o
|
|
||||||
+obj-$(CONFIG_NET_ACT_CONNMARK) += act_connmark.o
|
|
||||||
obj-$(CONFIG_NET_SCH_FIFO) += sch_fifo.o
|
|
||||||
obj-$(CONFIG_NET_SCH_CBQ) += sch_cbq.o
|
|
||||||
obj-$(CONFIG_NET_SCH_HTB) += sch_htb.o
|
|
|
@ -1,132 +0,0 @@
|
||||||
This patch allows the user to specify desired packet types (outgoing,
|
|
||||||
broadcast, unicast, etc.) on packet sockets via setsockopt.
|
|
||||||
This can reduce the load in situations where only a limited number
|
|
||||||
of packet types are necessary
|
|
||||||
|
|
||||||
Signed-off-by: Felix Fietkau <nbd@openwrt.org>
|
|
||||||
|
|
||||||
--- a/include/linux/if_packet.h
|
|
||||||
+++ b/include/linux/if_packet.h
|
|
||||||
@@ -29,6 +29,8 @@ struct sockaddr_ll {
|
|
||||||
/* These ones are invisible by user level */
|
|
||||||
#define PACKET_LOOPBACK 5 /* MC/BRD frame looped back */
|
|
||||||
#define PACKET_FASTROUTE 6 /* Fastrouted frame */
|
|
||||||
+#define PACKET_MASK_ANY 0xffffffff /* mask for packet type bits */
|
|
||||||
+
|
|
||||||
|
|
||||||
/* Packet socket options */
|
|
||||||
|
|
||||||
@@ -49,6 +51,7 @@ struct sockaddr_ll {
|
|
||||||
#define PACKET_VNET_HDR 15
|
|
||||||
#define PACKET_TX_TIMESTAMP 16
|
|
||||||
#define PACKET_TIMESTAMP 17
|
|
||||||
+#define PACKET_RECV_TYPE 18
|
|
||||||
|
|
||||||
struct tpacket_stats {
|
|
||||||
unsigned int tp_packets;
|
|
||||||
--- a/net/packet/af_packet.c
|
|
||||||
+++ b/net/packet/af_packet.c
|
|
||||||
@@ -210,6 +210,7 @@ struct packet_sock {
|
|
||||||
unsigned int tp_loss:1;
|
|
||||||
unsigned int tp_tstamp;
|
|
||||||
struct packet_type prot_hook ____cacheline_aligned_in_smp;
|
|
||||||
+ unsigned int pkt_type;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct packet_skb_cb {
|
|
||||||
@@ -354,6 +355,7 @@ static int packet_rcv_spkt(struct sk_buf
|
|
||||||
{
|
|
||||||
struct sock *sk;
|
|
||||||
struct sockaddr_pkt *spkt;
|
|
||||||
+ struct packet_sock *po;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* When we registered the protocol we saved the socket in the data
|
|
||||||
@@ -361,6 +363,7 @@ static int packet_rcv_spkt(struct sk_buf
|
|
||||||
*/
|
|
||||||
|
|
||||||
sk = pt->af_packet_priv;
|
|
||||||
+ po = pkt_sk(sk);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Yank back the headers [hope the device set this
|
|
||||||
@@ -373,7 +376,7 @@ static int packet_rcv_spkt(struct sk_buf
|
|
||||||
* so that this procedure is noop.
|
|
||||||
*/
|
|
||||||
|
|
||||||
- if (skb->pkt_type == PACKET_LOOPBACK)
|
|
||||||
+ if (!(po->pkt_type & (1 << skb->pkt_type)))
|
|
||||||
goto out;
|
|
||||||
|
|
||||||
if (!net_eq(dev_net(dev), sock_net(sk)))
|
|
||||||
@@ -566,12 +569,12 @@ static int packet_rcv(struct sk_buff *sk
|
|
||||||
int skb_len = skb->len;
|
|
||||||
unsigned int snaplen, res;
|
|
||||||
|
|
||||||
- if (skb->pkt_type == PACKET_LOOPBACK)
|
|
||||||
- goto drop;
|
|
||||||
-
|
|
||||||
sk = pt->af_packet_priv;
|
|
||||||
po = pkt_sk(sk);
|
|
||||||
|
|
||||||
+ if (!(po->pkt_type & (1 << skb->pkt_type)))
|
|
||||||
+ goto drop;
|
|
||||||
+
|
|
||||||
if (!net_eq(dev_net(dev), sock_net(sk)))
|
|
||||||
goto drop;
|
|
||||||
|
|
||||||
@@ -690,12 +693,12 @@ static int tpacket_rcv(struct sk_buff *s
|
|
||||||
struct timespec ts;
|
|
||||||
struct skb_shared_hwtstamps *shhwtstamps = skb_hwtstamps(skb);
|
|
||||||
|
|
||||||
- if (skb->pkt_type == PACKET_LOOPBACK)
|
|
||||||
- goto drop;
|
|
||||||
-
|
|
||||||
sk = pt->af_packet_priv;
|
|
||||||
po = pkt_sk(sk);
|
|
||||||
|
|
||||||
+ if (!(po->pkt_type & (1 << skb->pkt_type)))
|
|
||||||
+ goto drop;
|
|
||||||
+
|
|
||||||
if (!net_eq(dev_net(dev), sock_net(sk)))
|
|
||||||
goto drop;
|
|
||||||
|
|
||||||
@@ -1532,6 +1535,7 @@ static int packet_create(struct net *net
|
|
||||||
spin_lock_init(&po->bind_lock);
|
|
||||||
mutex_init(&po->pg_vec_lock);
|
|
||||||
po->prot_hook.func = packet_rcv;
|
|
||||||
+ po->pkt_type = PACKET_MASK_ANY & ~(1 << PACKET_LOOPBACK);
|
|
||||||
|
|
||||||
if (sock->type == SOCK_PACKET)
|
|
||||||
po->prot_hook.func = packet_rcv_spkt;
|
|
||||||
@@ -2105,6 +2109,16 @@ packet_setsockopt(struct socket *sock, i
|
|
||||||
po->tp_tstamp = val;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
+ case PACKET_RECV_TYPE:
|
|
||||||
+ {
|
|
||||||
+ unsigned int val;
|
|
||||||
+ if (optlen != sizeof(val))
|
|
||||||
+ return -EINVAL;
|
|
||||||
+ if (copy_from_user(&val, optval, sizeof(val)))
|
|
||||||
+ return -EFAULT;
|
|
||||||
+ po->pkt_type = val & ~PACKET_LOOPBACK;
|
|
||||||
+ return 0;
|
|
||||||
+ }
|
|
||||||
default:
|
|
||||||
return -ENOPROTOOPT;
|
|
||||||
}
|
|
||||||
@@ -2162,6 +2176,13 @@ static int packet_getsockopt(struct sock
|
|
||||||
|
|
||||||
data = &val;
|
|
||||||
break;
|
|
||||||
+ case PACKET_RECV_TYPE:
|
|
||||||
+ if (len > sizeof(unsigned int))
|
|
||||||
+ len = sizeof(unsigned int);
|
|
||||||
+ val = po->pkt_type;
|
|
||||||
+
|
|
||||||
+ data = &val;
|
|
||||||
+ break;
|
|
||||||
case PACKET_VERSION:
|
|
||||||
if (len > sizeof(int))
|
|
||||||
len = sizeof(int);
|
|
|
@ -1,15 +0,0 @@
|
||||||
--- a/net/bridge/br_input.c
|
|
||||||
+++ b/net/bridge/br_input.c
|
|
||||||
@@ -77,7 +77,11 @@ int br_handle_frame_finish(struct sk_buf
|
|
||||||
|
|
||||||
dst = NULL;
|
|
||||||
|
|
||||||
- if (is_broadcast_ether_addr(dest))
|
|
||||||
+ if (skb->protocol == htons(ETH_P_PAE)) {
|
|
||||||
+ skb2 = skb;
|
|
||||||
+ /* Do not forward 802.1x/EAP frames */
|
|
||||||
+ skb = NULL;
|
|
||||||
+ } else if (is_broadcast_ether_addr(dest))
|
|
||||||
skb2 = skb;
|
|
||||||
else if (is_multicast_ether_addr(dest)) {
|
|
||||||
mdst = br_mdb_get(br, skb);
|
|
|
@ -1,11 +0,0 @@
|
||||||
--- a/net/bridge/br_input.c
|
|
||||||
+++ b/net/bridge/br_input.c
|
|
||||||
@@ -64,7 +64,7 @@ int br_handle_frame_finish(struct sk_buf
|
|
||||||
br_multicast_rcv(br, p, skb))
|
|
||||||
goto drop;
|
|
||||||
|
|
||||||
- if (p->state == BR_STATE_LEARNING)
|
|
||||||
+ if ((p->state == BR_STATE_LEARNING) && skb->protocol != htons(ETH_P_PAE))
|
|
||||||
goto drop;
|
|
||||||
|
|
||||||
BR_INPUT_SKB_CB(skb)->brdev = br->dev;
|
|
|
@ -1,103 +0,0 @@
|
||||||
--- a/net/bridge/br_private.h
|
|
||||||
+++ b/net/bridge/br_private.h
|
|
||||||
@@ -134,6 +134,7 @@ struct net_bridge_port
|
|
||||||
|
|
||||||
unsigned long flags;
|
|
||||||
#define BR_HAIRPIN_MODE 0x00000001
|
|
||||||
+#define BR_ISOLATE_MODE 0x00000002
|
|
||||||
|
|
||||||
#ifdef CONFIG_BRIDGE_IGMP_SNOOPING
|
|
||||||
u32 multicast_startup_queries_sent;
|
|
||||||
--- a/net/bridge/br_sysfs_if.c
|
|
||||||
+++ b/net/bridge/br_sysfs_if.c
|
|
||||||
@@ -149,6 +149,22 @@ static int store_hairpin_mode(struct net
|
|
||||||
static BRPORT_ATTR(hairpin_mode, S_IRUGO | S_IWUSR,
|
|
||||||
show_hairpin_mode, store_hairpin_mode);
|
|
||||||
|
|
||||||
+static ssize_t show_isolate_mode(struct net_bridge_port *p, char *buf)
|
|
||||||
+{
|
|
||||||
+ int isolate_mode = (p->flags & BR_ISOLATE_MODE) ? 1 : 0;
|
|
||||||
+ return sprintf(buf, "%d\n", isolate_mode);
|
|
||||||
+}
|
|
||||||
+static ssize_t store_isolate_mode(struct net_bridge_port *p, unsigned long v)
|
|
||||||
+{
|
|
||||||
+ if (v)
|
|
||||||
+ p->flags |= BR_ISOLATE_MODE;
|
|
||||||
+ else
|
|
||||||
+ p->flags &= ~BR_ISOLATE_MODE;
|
|
||||||
+ return 0;
|
|
||||||
+}
|
|
||||||
+static BRPORT_ATTR(isolate_mode, S_IRUGO | S_IWUSR,
|
|
||||||
+ show_isolate_mode, store_isolate_mode);
|
|
||||||
+
|
|
||||||
#ifdef CONFIG_BRIDGE_IGMP_SNOOPING
|
|
||||||
static ssize_t show_multicast_router(struct net_bridge_port *p, char *buf)
|
|
||||||
{
|
|
||||||
@@ -181,6 +197,7 @@ static struct brport_attribute *brport_a
|
|
||||||
&brport_attr_hold_timer,
|
|
||||||
&brport_attr_flush,
|
|
||||||
&brport_attr_hairpin_mode,
|
|
||||||
+ &brport_attr_isolate_mode,
|
|
||||||
#ifdef CONFIG_BRIDGE_IGMP_SNOOPING
|
|
||||||
&brport_attr_multicast_router,
|
|
||||||
#endif
|
|
||||||
--- a/net/bridge/br_input.c
|
|
||||||
+++ b/net/bridge/br_input.c
|
|
||||||
@@ -97,7 +97,8 @@ int br_handle_frame_finish(struct sk_buf
|
|
||||||
skb2 = skb;
|
|
||||||
|
|
||||||
br->dev->stats.multicast++;
|
|
||||||
- } else if ((dst = __br_fdb_get(br, dest)) && dst->is_local) {
|
|
||||||
+ } else if ((p->flags & BR_ISOLATE_MODE) ||
|
|
||||||
+ ((dst = __br_fdb_get(br, dest)) && dst->is_local)) {
|
|
||||||
skb2 = skb;
|
|
||||||
/* Do not forward the packet since it's local. */
|
|
||||||
skb = NULL;
|
|
||||||
--- a/net/bridge/br_forward.c
|
|
||||||
+++ b/net/bridge/br_forward.c
|
|
||||||
@@ -109,7 +109,7 @@ void br_deliver(const struct net_bridge_
|
|
||||||
/* called with rcu_read_lock */
|
|
||||||
void br_forward(const struct net_bridge_port *to, struct sk_buff *skb, struct sk_buff *skb0)
|
|
||||||
{
|
|
||||||
- if (should_deliver(to, skb)) {
|
|
||||||
+ if (should_deliver(to, skb) && !(to->flags & BR_ISOLATE_MODE)) {
|
|
||||||
if (skb0)
|
|
||||||
deliver_clone(to, skb, __br_forward);
|
|
||||||
else
|
|
||||||
@@ -164,7 +164,8 @@ out:
|
|
||||||
static void br_flood(struct net_bridge *br, struct sk_buff *skb,
|
|
||||||
struct sk_buff *skb0,
|
|
||||||
void (*__packet_hook)(const struct net_bridge_port *p,
|
|
||||||
- struct sk_buff *skb))
|
|
||||||
+ struct sk_buff *skb),
|
|
||||||
+ bool forward)
|
|
||||||
{
|
|
||||||
struct net_bridge_port *p;
|
|
||||||
struct net_bridge_port *prev;
|
|
||||||
@@ -172,6 +173,9 @@ static void br_flood(struct net_bridge *
|
|
||||||
prev = NULL;
|
|
||||||
|
|
||||||
list_for_each_entry_rcu(p, &br->port_list, list) {
|
|
||||||
+ if (forward && (p->flags & BR_ISOLATE_MODE))
|
|
||||||
+ continue;
|
|
||||||
+
|
|
||||||
prev = maybe_deliver(prev, p, skb, __packet_hook);
|
|
||||||
if (IS_ERR(prev))
|
|
||||||
goto out;
|
|
||||||
@@ -195,14 +199,14 @@ out:
|
|
||||||
/* called with rcu_read_lock */
|
|
||||||
void br_flood_deliver(struct net_bridge *br, struct sk_buff *skb)
|
|
||||||
{
|
|
||||||
- br_flood(br, skb, NULL, __br_deliver);
|
|
||||||
+ br_flood(br, skb, NULL, __br_deliver, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* called under bridge lock */
|
|
||||||
void br_flood_forward(struct net_bridge *br, struct sk_buff *skb,
|
|
||||||
struct sk_buff *skb2)
|
|
||||||
{
|
|
||||||
- br_flood(br, skb, skb2, __br_forward);
|
|
||||||
+ br_flood(br, skb, skb2, __br_forward, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef CONFIG_BRIDGE_IGMP_SNOOPING
|
|
|
@ -1,101 +0,0 @@
|
||||||
--- a/include/net/addrconf.h
|
|
||||||
+++ b/include/net/addrconf.h
|
|
||||||
@@ -91,6 +91,12 @@ extern void addrconf_join_solict(struc
|
|
||||||
extern void addrconf_leave_solict(struct inet6_dev *idev,
|
|
||||||
const struct in6_addr *addr);
|
|
||||||
|
|
||||||
+extern int (*ipv6_dev_get_saddr_hook)(struct net *net,
|
|
||||||
+ struct net_device *dev,
|
|
||||||
+ const struct in6_addr *daddr,
|
|
||||||
+ unsigned int srcprefs,
|
|
||||||
+ struct in6_addr *saddr);
|
|
||||||
+
|
|
||||||
static inline unsigned long addrconf_timeout_fixup(u32 timeout,
|
|
||||||
unsigned unit)
|
|
||||||
{
|
|
||||||
--- a/net/bridge/Kconfig
|
|
||||||
+++ b/net/bridge/Kconfig
|
|
||||||
@@ -6,7 +6,6 @@ config BRIDGE
|
|
||||||
tristate "802.1d Ethernet Bridging"
|
|
||||||
select LLC
|
|
||||||
select STP
|
|
||||||
- depends on IPV6 || IPV6=n
|
|
||||||
---help---
|
|
||||||
If you say Y here, then your Linux box will be able to act as an
|
|
||||||
Ethernet bridge, which means that the different Ethernet segments it
|
|
||||||
--- a/net/ipv6/Makefile
|
|
||||||
+++ b/net/ipv6/Makefile
|
|
||||||
@@ -40,3 +40,4 @@ obj-$(CONFIG_IPV6_TUNNEL) += ip6_tunnel.
|
|
||||||
obj-y += addrconf_core.o exthdrs_core.o
|
|
||||||
|
|
||||||
obj-$(subst m,y,$(CONFIG_IPV6)) += inet6_hashtables.o
|
|
||||||
+obj-$(subst m,y,$(CONFIG_IPV6)) += inet6_stubs.o
|
|
||||||
--- a/net/ipv6/addrconf.c
|
|
||||||
+++ b/net/ipv6/addrconf.c
|
|
||||||
@@ -1106,7 +1106,7 @@ out:
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
-int ipv6_dev_get_saddr(struct net *net, struct net_device *dst_dev,
|
|
||||||
+static int __ipv6_dev_get_saddr(struct net *net, struct net_device *dst_dev,
|
|
||||||
const struct in6_addr *daddr, unsigned int prefs,
|
|
||||||
struct in6_addr *saddr)
|
|
||||||
{
|
|
||||||
@@ -1231,7 +1231,6 @@ try_nextdev:
|
|
||||||
in6_ifa_put(hiscore->ifa);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
-EXPORT_SYMBOL(ipv6_dev_get_saddr);
|
|
||||||
|
|
||||||
int ipv6_get_lladdr(struct net_device *dev, struct in6_addr *addr,
|
|
||||||
unsigned char banned_flags)
|
|
||||||
@@ -4705,6 +4704,9 @@ int __init addrconf_init(void)
|
|
||||||
|
|
||||||
ipv6_addr_label_rtnl_register();
|
|
||||||
|
|
||||||
+ BUG_ON(ipv6_dev_get_saddr_hook != NULL);
|
|
||||||
+ rcu_assign_pointer(ipv6_dev_get_saddr_hook, __ipv6_dev_get_saddr);
|
|
||||||
+
|
|
||||||
return 0;
|
|
||||||
errout:
|
|
||||||
rtnl_af_unregister(&inet6_ops);
|
|
||||||
@@ -4723,6 +4725,9 @@ void addrconf_cleanup(void)
|
|
||||||
struct net_device *dev;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
+ rcu_assign_pointer(ipv6_dev_get_saddr_hook, NULL);
|
|
||||||
+ synchronize_rcu();
|
|
||||||
+
|
|
||||||
unregister_netdevice_notifier(&ipv6_dev_notf);
|
|
||||||
unregister_pernet_subsys(&addrconf_ops);
|
|
||||||
ipv6_addr_label_cleanup();
|
|
||||||
--- /dev/null
|
|
||||||
+++ b/net/ipv6/inet6_stubs.c
|
|
||||||
@@ -0,0 +1,27 @@
|
|
||||||
+/*
|
|
||||||
+ * This program is free software; you can redistribute it and/or
|
|
||||||
+ * modify it under the terms of the GNU General Public License
|
|
||||||
+ * as published by the Free Software Foundation; either version
|
|
||||||
+ * 2 of the License, or (at your option) any later version.
|
|
||||||
+ */
|
|
||||||
+#include <net/ipv6.h>
|
|
||||||
+
|
|
||||||
+int (*ipv6_dev_get_saddr_hook)(struct net *net, struct net_device *dev,
|
|
||||||
+ const struct in6_addr *daddr, unsigned int srcprefs,
|
|
||||||
+ struct in6_addr *saddr);
|
|
||||||
+
|
|
||||||
+EXPORT_SYMBOL(ipv6_dev_get_saddr_hook);
|
|
||||||
+
|
|
||||||
+int ipv6_dev_get_saddr(struct net *net, struct net_device *dst_dev,
|
|
||||||
+ const struct in6_addr *daddr, unsigned int prefs,
|
|
||||||
+ struct in6_addr *saddr)
|
|
||||||
+{
|
|
||||||
+ typeof(ipv6_dev_get_saddr_hook) dev_get_saddr = rcu_dereference(ipv6_dev_get_saddr_hook);
|
|
||||||
+
|
|
||||||
+ if (dev_get_saddr)
|
|
||||||
+ return dev_get_saddr(net, dst_dev, daddr, prefs, saddr);
|
|
||||||
+
|
|
||||||
+ return -EADDRNOTAVAIL;
|
|
||||||
+}
|
|
||||||
+EXPORT_SYMBOL(ipv6_dev_get_saddr);
|
|
||||||
+
|
|
|
@ -1,20 +0,0 @@
|
||||||
--- a/drivers/net/pppoe.c
|
|
||||||
+++ b/drivers/net/pppoe.c
|
|
||||||
@@ -856,7 +856,7 @@ static int pppoe_sendmsg(struct kiocb *i
|
|
||||||
goto end;
|
|
||||||
|
|
||||||
|
|
||||||
- skb = sock_wmalloc(sk, total_len + dev->hard_header_len + 32,
|
|
||||||
+ skb = sock_wmalloc(sk, total_len + dev->hard_header_len + 32 + NET_SKB_PAD,
|
|
||||||
0, GFP_KERNEL);
|
|
||||||
if (!skb) {
|
|
||||||
error = -ENOMEM;
|
|
||||||
@@ -864,7 +864,7 @@ static int pppoe_sendmsg(struct kiocb *i
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Reserve space for headers. */
|
|
||||||
- skb_reserve(skb, dev->hard_header_len);
|
|
||||||
+ skb_reserve(skb, dev->hard_header_len + NET_SKB_PAD);
|
|
||||||
skb_reset_network_header(skb);
|
|
||||||
|
|
||||||
skb->dev = dev;
|
|
|
@ -1,11 +0,0 @@
|
||||||
--- a/include/linux/netdevice.h
|
|
||||||
+++ b/include/linux/netdevice.h
|
|
||||||
@@ -148,7 +148,7 @@ static inline bool dev_xmit_complete(int
|
|
||||||
*/
|
|
||||||
|
|
||||||
#if defined(CONFIG_WLAN) || defined(CONFIG_AX25) || defined(CONFIG_AX25_MODULE)
|
|
||||||
-# if defined(CONFIG_MAC80211_MESH)
|
|
||||||
+# if 1 || defined(CONFIG_MAC80211_MESH)
|
|
||||||
# define LL_MAX_HEADER 128
|
|
||||||
# else
|
|
||||||
# define LL_MAX_HEADER 96
|
|
|
@ -1,12 +0,0 @@
|
||||||
--- a/include/linux/atm.h
|
|
||||||
+++ b/include/linux/atm.h
|
|
||||||
@@ -139,6 +139,9 @@ struct atm_trafprm {
|
|
||||||
int min_pcr; /* minimum PCR in cells per second */
|
|
||||||
int max_cdv; /* maximum CDV in microseconds */
|
|
||||||
int max_sdu; /* maximum SDU in bytes */
|
|
||||||
+ int scr; /* sustained rate in cells per second */
|
|
||||||
+ int mbs; /* maximum burst size (MBS) in cells */
|
|
||||||
+ int cdv; /* Cell delay varition */
|
|
||||||
/* extra params for ABR */
|
|
||||||
unsigned int icr; /* Initial Cell Rate (24-bit) */
|
|
||||||
unsigned int tbe; /* Transient Buffer Exposure (24-bit) */
|
|
|
@ -1,29 +0,0 @@
|
||||||
--- a/drivers/net/phy/Kconfig
|
|
||||||
+++ b/drivers/net/phy/Kconfig
|
|
||||||
@@ -13,6 +13,16 @@ menuconfig PHYLIB
|
|
||||||
|
|
||||||
if PHYLIB
|
|
||||||
|
|
||||||
+config SWCONFIG
|
|
||||||
+ tristate "Switch configuration API"
|
|
||||||
+ ---help---
|
|
||||||
+ Switch configuration API using netlink. This allows
|
|
||||||
+ you to configure the VLAN features of certain switches.
|
|
||||||
+
|
|
||||||
+config SWCONFIG_LEDS
|
|
||||||
+ bool "Switch LED trigger support"
|
|
||||||
+ depends on (SWCONFIG && LEDS_TRIGGERS)
|
|
||||||
+
|
|
||||||
comment "MII PHY device drivers"
|
|
||||||
|
|
||||||
config MARVELL_PHY
|
|
||||||
--- a/drivers/net/phy/Makefile
|
|
||||||
+++ b/drivers/net/phy/Makefile
|
|
||||||
@@ -3,6 +3,7 @@
|
|
||||||
libphy-objs := phy.o phy_device.o mdio_bus.o
|
|
||||||
|
|
||||||
obj-$(CONFIG_PHYLIB) += libphy.o
|
|
||||||
+obj-$(CONFIG_SWCONFIG) += swconfig.o
|
|
||||||
obj-$(CONFIG_MARVELL_PHY) += marvell.o
|
|
||||||
obj-$(CONFIG_DAVICOM_PHY) += davicom.o
|
|
||||||
obj-$(CONFIG_CICADA_PHY) += cicada.o
|
|
|
@ -1,72 +0,0 @@
|
||||||
--- a/drivers/net/phy/phy.c
|
|
||||||
+++ b/drivers/net/phy/phy.c
|
|
||||||
@@ -299,6 +299,50 @@ int phy_ethtool_gset(struct phy_device *
|
|
||||||
}
|
|
||||||
EXPORT_SYMBOL(phy_ethtool_gset);
|
|
||||||
|
|
||||||
+int phy_ethtool_ioctl(struct phy_device *phydev, void *useraddr)
|
|
||||||
+{
|
|
||||||
+ u32 cmd;
|
|
||||||
+ int tmp;
|
|
||||||
+ struct ethtool_cmd ecmd = { ETHTOOL_GSET };
|
|
||||||
+ struct ethtool_value edata = { ETHTOOL_GLINK };
|
|
||||||
+
|
|
||||||
+ if (get_user(cmd, (u32 *) useraddr))
|
|
||||||
+ return -EFAULT;
|
|
||||||
+
|
|
||||||
+ switch (cmd) {
|
|
||||||
+ case ETHTOOL_GSET:
|
|
||||||
+ phy_ethtool_gset(phydev, &ecmd);
|
|
||||||
+ if (copy_to_user(useraddr, &ecmd, sizeof(ecmd)))
|
|
||||||
+ return -EFAULT;
|
|
||||||
+ return 0;
|
|
||||||
+
|
|
||||||
+ case ETHTOOL_SSET:
|
|
||||||
+ if (copy_from_user(&ecmd, useraddr, sizeof(ecmd)))
|
|
||||||
+ return -EFAULT;
|
|
||||||
+ return phy_ethtool_sset(phydev, &ecmd);
|
|
||||||
+
|
|
||||||
+ case ETHTOOL_NWAY_RST:
|
|
||||||
+ /* if autoneg is off, it's an error */
|
|
||||||
+ tmp = phy_read(phydev, MII_BMCR);
|
|
||||||
+ if (tmp & BMCR_ANENABLE) {
|
|
||||||
+ tmp |= (BMCR_ANRESTART);
|
|
||||||
+ phy_write(phydev, MII_BMCR, tmp);
|
|
||||||
+ return 0;
|
|
||||||
+ }
|
|
||||||
+ return -EINVAL;
|
|
||||||
+
|
|
||||||
+ case ETHTOOL_GLINK:
|
|
||||||
+ edata.data = (phy_read(phydev,
|
|
||||||
+ MII_BMSR) & BMSR_LSTATUS) ? 1 : 0;
|
|
||||||
+ if (copy_to_user(useraddr, &edata, sizeof(edata)))
|
|
||||||
+ return -EFAULT;
|
|
||||||
+ return 0;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ return -EOPNOTSUPP;
|
|
||||||
+}
|
|
||||||
+EXPORT_SYMBOL(phy_ethtool_ioctl);
|
|
||||||
+
|
|
||||||
/**
|
|
||||||
* phy_mii_ioctl - generic PHY MII ioctl interface
|
|
||||||
* @phydev: the phy_device struct
|
|
||||||
@@ -474,7 +518,7 @@ static void phy_force_reduction(struct p
|
|
||||||
int idx;
|
|
||||||
|
|
||||||
idx = phy_find_setting(phydev->speed, phydev->duplex);
|
|
||||||
-
|
|
||||||
+
|
|
||||||
idx++;
|
|
||||||
|
|
||||||
idx = phy_find_valid(idx, phydev->supported);
|
|
||||||
--- a/include/linux/phy.h
|
|
||||||
+++ b/include/linux/phy.h
|
|
||||||
@@ -508,6 +508,7 @@ void phy_start_machine(struct phy_device
|
|
||||||
void phy_stop_machine(struct phy_device *phydev);
|
|
||||||
int phy_ethtool_sset(struct phy_device *phydev, struct ethtool_cmd *cmd);
|
|
||||||
int phy_ethtool_gset(struct phy_device *phydev, struct ethtool_cmd *cmd);
|
|
||||||
+int phy_ethtool_ioctl(struct phy_device *phydev, void *useraddr);
|
|
||||||
int phy_mii_ioctl(struct phy_device *phydev,
|
|
||||||
struct ifreq *ifr, int cmd);
|
|
||||||
int phy_start_interrupts(struct phy_device *phydev);
|
|
|
@ -1,45 +0,0 @@
|
||||||
--- a/include/linux/phy.h
|
|
||||||
+++ b/include/linux/phy.h
|
|
||||||
@@ -386,9 +386,18 @@ struct phy_driver {
|
|
||||||
*/
|
|
||||||
int (*config_aneg)(struct phy_device *phydev);
|
|
||||||
|
|
||||||
+ /* Determine if autonegotiation is done */
|
|
||||||
+ int (*aneg_done)(struct phy_device *phydev);
|
|
||||||
+
|
|
||||||
/* Determines the negotiated speed and duplex */
|
|
||||||
int (*read_status)(struct phy_device *phydev);
|
|
||||||
|
|
||||||
+ /*
|
|
||||||
+ * Update the value in phydev->link to reflect the
|
|
||||||
+ * current link value
|
|
||||||
+ */
|
|
||||||
+ int (*update_link)(struct phy_device *phydev);
|
|
||||||
+
|
|
||||||
/* Clears any pending interrupts */
|
|
||||||
int (*ack_interrupt)(struct phy_device *phydev);
|
|
||||||
|
|
||||||
--- a/drivers/net/phy/phy_device.c
|
|
||||||
+++ b/drivers/net/phy/phy_device.c
|
|
||||||
@@ -719,6 +719,9 @@ int genphy_update_link(struct phy_device
|
|
||||||
{
|
|
||||||
int status;
|
|
||||||
|
|
||||||
+ if (phydev->drv->update_link)
|
|
||||||
+ return phydev->drv->update_link(phydev);
|
|
||||||
+
|
|
||||||
/* Do a fake read */
|
|
||||||
status = phy_read(phydev, MII_BMSR);
|
|
||||||
|
|
||||||
--- a/drivers/net/phy/phy.c
|
|
||||||
+++ b/drivers/net/phy/phy.c
|
|
||||||
@@ -106,6 +106,9 @@ static inline int phy_aneg_done(struct p
|
|
||||||
{
|
|
||||||
int retval;
|
|
||||||
|
|
||||||
+ if (phydev->drv->aneg_done)
|
|
||||||
+ return phydev->drv->aneg_done(phydev);
|
|
||||||
+
|
|
||||||
retval = phy_read(phydev, MII_BMSR);
|
|
||||||
|
|
||||||
return (retval < 0) ? retval : (retval & BMSR_ANEGCOMPLETE);
|
|
|
@ -1,26 +0,0 @@
|
||||||
--- a/drivers/net/phy/Kconfig
|
|
||||||
+++ b/drivers/net/phy/Kconfig
|
|
||||||
@@ -102,6 +102,13 @@ config MICREL_PHY
|
|
||||||
---help---
|
|
||||||
Supports the KSZ9021, VSC8201, KS8001 PHYs.
|
|
||||||
|
|
||||||
+config ADM6996_PHY
|
|
||||||
+ tristate "Driver for ADM6996 switches"
|
|
||||||
+ select SWCONFIG
|
|
||||||
+ ---help---
|
|
||||||
+ Currently supports the ADM6996FC and ADM6996M switches.
|
|
||||||
+ Support for FC is very limited.
|
|
||||||
+
|
|
||||||
config FIXED_PHY
|
|
||||||
bool "Driver for MDIO Bus/PHY emulation with fixed speed/link PHYs"
|
|
||||||
depends on PHYLIB=y
|
|
||||||
--- a/drivers/net/phy/Makefile
|
|
||||||
+++ b/drivers/net/phy/Makefile
|
|
||||||
@@ -14,6 +14,7 @@ obj-$(CONFIG_VITESSE_PHY) += vitesse.o
|
|
||||||
obj-$(CONFIG_BROADCOM_PHY) += broadcom.o
|
|
||||||
obj-$(CONFIG_BCM63XX_PHY) += bcm63xx.o
|
|
||||||
obj-$(CONFIG_ICPLUS_PHY) += icplus.o
|
|
||||||
+obj-$(CONFIG_ADM6996_PHY) += adm6996.o
|
|
||||||
obj-$(CONFIG_REALTEK_PHY) += realtek.o
|
|
||||||
obj-$(CONFIG_LSI_ET1011C_PHY) += et1011c.o
|
|
||||||
obj-$(CONFIG_FIXED_PHY) += fixed.o
|
|
|
@ -1,63 +0,0 @@
|
||||||
--- a/drivers/net/phy/phy_device.c
|
|
||||||
+++ b/drivers/net/phy/phy_device.c
|
|
||||||
@@ -149,6 +149,18 @@ int phy_scan_fixups(struct phy_device *p
|
|
||||||
}
|
|
||||||
EXPORT_SYMBOL(phy_scan_fixups);
|
|
||||||
|
|
||||||
+static int generic_receive_skb(struct sk_buff *skb)
|
|
||||||
+{
|
|
||||||
+ skb->protocol = eth_type_trans(skb, skb->dev);
|
|
||||||
+ return netif_receive_skb(skb);
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static int generic_rx(struct sk_buff *skb)
|
|
||||||
+{
|
|
||||||
+ skb->protocol = eth_type_trans(skb, skb->dev);
|
|
||||||
+ return netif_rx(skb);
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
static struct phy_device* phy_device_create(struct mii_bus *bus,
|
|
||||||
int addr, int phy_id)
|
|
||||||
{
|
|
||||||
@@ -180,6 +192,8 @@ static struct phy_device* phy_device_cre
|
|
||||||
dev_set_name(&dev->dev, PHY_ID_FMT, bus->id, addr);
|
|
||||||
|
|
||||||
dev->state = PHY_DOWN;
|
|
||||||
+ dev->netif_receive_skb = &generic_receive_skb;
|
|
||||||
+ dev->netif_rx = &generic_rx;
|
|
||||||
|
|
||||||
mutex_init(&dev->lock);
|
|
||||||
INIT_DELAYED_WORK(&dev->state_queue, phy_state_machine);
|
|
||||||
--- a/include/linux/phy.h
|
|
||||||
+++ b/include/linux/phy.h
|
|
||||||
@@ -332,6 +332,20 @@ struct phy_device {
|
|
||||||
void (*adjust_link)(struct net_device *dev);
|
|
||||||
|
|
||||||
void (*adjust_state)(struct net_device *dev);
|
|
||||||
+
|
|
||||||
+ /*
|
|
||||||
+ * By default these point to the original functions
|
|
||||||
+ * with the same name. adding them to the phy_device
|
|
||||||
+ * allows the phy driver to override them for packet
|
|
||||||
+ * mangling if the ethernet driver supports it
|
|
||||||
+ * This is required to support some really horrible
|
|
||||||
+ * switches such as the Marvell 88E6060
|
|
||||||
+ */
|
|
||||||
+ int (*netif_receive_skb)(struct sk_buff *skb);
|
|
||||||
+ int (*netif_rx)(struct sk_buff *skb);
|
|
||||||
+
|
|
||||||
+ /* alignment offset for packets */
|
|
||||||
+ int pkt_align;
|
|
||||||
};
|
|
||||||
#define to_phy_device(d) container_of(d, struct phy_device, dev)
|
|
||||||
|
|
||||||
--- a/include/linux/netdevice.h
|
|
||||||
+++ b/include/linux/netdevice.h
|
|
||||||
@@ -1188,6 +1188,7 @@ struct net_device {
|
|
||||||
void *ax25_ptr; /* AX.25 specific data */
|
|
||||||
struct wireless_dev *ieee80211_ptr; /* IEEE 802.11 specific data,
|
|
||||||
assign before registering */
|
|
||||||
+ void *phy_ptr; /* PHY device specific data */
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Cache lines mostly used on receive path (including eth_type_trans())
|
|
|
@ -1,22 +0,0 @@
|
||||||
--- a/drivers/net/phy/Kconfig
|
|
||||||
+++ b/drivers/net/phy/Kconfig
|
|
||||||
@@ -109,6 +109,9 @@ config ADM6996_PHY
|
|
||||||
Currently supports the ADM6996FC and ADM6996M switches.
|
|
||||||
Support for FC is very limited.
|
|
||||||
|
|
||||||
+config MVSWITCH_PHY
|
|
||||||
+ tristate "Driver for Marvell 88E6060 switches"
|
|
||||||
+
|
|
||||||
config FIXED_PHY
|
|
||||||
bool "Driver for MDIO Bus/PHY emulation with fixed speed/link PHYs"
|
|
||||||
depends on PHYLIB=y
|
|
||||||
--- a/drivers/net/phy/Makefile
|
|
||||||
+++ b/drivers/net/phy/Makefile
|
|
||||||
@@ -15,6 +15,7 @@ obj-$(CONFIG_BROADCOM_PHY) += broadcom.o
|
|
||||||
obj-$(CONFIG_BCM63XX_PHY) += bcm63xx.o
|
|
||||||
obj-$(CONFIG_ICPLUS_PHY) += icplus.o
|
|
||||||
obj-$(CONFIG_ADM6996_PHY) += adm6996.o
|
|
||||||
+obj-$(CONFIG_MVSWITCH_PHY) += mvswitch.o
|
|
||||||
obj-$(CONFIG_REALTEK_PHY) += realtek.o
|
|
||||||
obj-$(CONFIG_LSI_ET1011C_PHY) += et1011c.o
|
|
||||||
obj-$(CONFIG_FIXED_PHY) += fixed.o
|
|
|
@ -1,23 +0,0 @@
|
||||||
--- a/drivers/net/phy/Kconfig
|
|
||||||
+++ b/drivers/net/phy/Kconfig
|
|
||||||
@@ -112,6 +112,10 @@ config ADM6996_PHY
|
|
||||||
config MVSWITCH_PHY
|
|
||||||
tristate "Driver for Marvell 88E6060 switches"
|
|
||||||
|
|
||||||
+config IP17XX_PHY
|
|
||||||
+ tristate "Driver for IC+ IP17xx switches"
|
|
||||||
+ select SWCONFIG
|
|
||||||
+
|
|
||||||
config FIXED_PHY
|
|
||||||
bool "Driver for MDIO Bus/PHY emulation with fixed speed/link PHYs"
|
|
||||||
depends on PHYLIB=y
|
|
||||||
--- a/drivers/net/phy/Makefile
|
|
||||||
+++ b/drivers/net/phy/Makefile
|
|
||||||
@@ -16,6 +16,7 @@ obj-$(CONFIG_BCM63XX_PHY) += bcm63xx.o
|
|
||||||
obj-$(CONFIG_ICPLUS_PHY) += icplus.o
|
|
||||||
obj-$(CONFIG_ADM6996_PHY) += adm6996.o
|
|
||||||
obj-$(CONFIG_MVSWITCH_PHY) += mvswitch.o
|
|
||||||
+obj-$(CONFIG_IP17XX_PHY) += ip17xx.o
|
|
||||||
obj-$(CONFIG_REALTEK_PHY) += realtek.o
|
|
||||||
obj-$(CONFIG_LSI_ET1011C_PHY) += et1011c.o
|
|
||||||
obj-$(CONFIG_FIXED_PHY) += fixed.o
|
|
|
@ -1,23 +0,0 @@
|
||||||
--- a/drivers/net/phy/Kconfig
|
|
||||||
+++ b/drivers/net/phy/Kconfig
|
|
||||||
@@ -116,6 +116,10 @@ config IP17XX_PHY
|
|
||||||
tristate "Driver for IC+ IP17xx switches"
|
|
||||||
select SWCONFIG
|
|
||||||
|
|
||||||
+config AR8216_PHY
|
|
||||||
+ tristate "Driver for Atheros AR8216 switches"
|
|
||||||
+ select SWCONFIG
|
|
||||||
+
|
|
||||||
config FIXED_PHY
|
|
||||||
bool "Driver for MDIO Bus/PHY emulation with fixed speed/link PHYs"
|
|
||||||
depends on PHYLIB=y
|
|
||||||
--- a/drivers/net/phy/Makefile
|
|
||||||
+++ b/drivers/net/phy/Makefile
|
|
||||||
@@ -18,6 +18,7 @@ obj-$(CONFIG_ADM6996_PHY) += adm6996.o
|
|
||||||
obj-$(CONFIG_MVSWITCH_PHY) += mvswitch.o
|
|
||||||
obj-$(CONFIG_IP17XX_PHY) += ip17xx.o
|
|
||||||
obj-$(CONFIG_REALTEK_PHY) += realtek.o
|
|
||||||
+obj-$(CONFIG_AR8216_PHY) += ar8216.o
|
|
||||||
obj-$(CONFIG_LSI_ET1011C_PHY) += et1011c.o
|
|
||||||
obj-$(CONFIG_FIXED_PHY) += fixed.o
|
|
||||||
obj-$(CONFIG_MDIO_BITBANG) += mdio-bitbang.o
|
|
|
@ -1,23 +0,0 @@
|
||||||
--- a/drivers/net/phy/Kconfig
|
|
||||||
+++ b/drivers/net/phy/Kconfig
|
|
||||||
@@ -120,6 +120,10 @@ config AR8216_PHY
|
|
||||||
tristate "Driver for Atheros AR8216 switches"
|
|
||||||
select SWCONFIG
|
|
||||||
|
|
||||||
+config RTL8306_PHY
|
|
||||||
+ tristate "Driver for Realtek RTL8306S switches"
|
|
||||||
+ select SWCONFIG
|
|
||||||
+
|
|
||||||
config FIXED_PHY
|
|
||||||
bool "Driver for MDIO Bus/PHY emulation with fixed speed/link PHYs"
|
|
||||||
depends on PHYLIB=y
|
|
||||||
--- a/drivers/net/phy/Makefile
|
|
||||||
+++ b/drivers/net/phy/Makefile
|
|
||||||
@@ -19,6 +19,7 @@ obj-$(CONFIG_MVSWITCH_PHY) += mvswitch.o
|
|
||||||
obj-$(CONFIG_IP17XX_PHY) += ip17xx.o
|
|
||||||
obj-$(CONFIG_REALTEK_PHY) += realtek.o
|
|
||||||
obj-$(CONFIG_AR8216_PHY) += ar8216.o
|
|
||||||
+obj-$(CONFIG_RTL8306_PHY) += rtl8306.o
|
|
||||||
obj-$(CONFIG_LSI_ET1011C_PHY) += et1011c.o
|
|
||||||
obj-$(CONFIG_FIXED_PHY) += fixed.o
|
|
||||||
obj-$(CONFIG_MDIO_BITBANG) += mdio-bitbang.o
|
|
|
@ -1,44 +0,0 @@
|
||||||
--- a/drivers/net/phy/Kconfig
|
|
||||||
+++ b/drivers/net/phy/Kconfig
|
|
||||||
@@ -162,4 +162,29 @@ config MDIO_OCTEON
|
|
||||||
|
|
||||||
If in doubt, say Y.
|
|
||||||
|
|
||||||
+config RTL8366_SMI
|
|
||||||
+ tristate "Driver for the RTL8366 SMI interface"
|
|
||||||
+ depends on GENERIC_GPIO
|
|
||||||
+ ---help---
|
|
||||||
+ This module implements the SMI interface protocol which is used
|
|
||||||
+ by some RTL8366 ethernet switch devices via the generic GPIO API.
|
|
||||||
+
|
|
||||||
+if RTL8366_SMI
|
|
||||||
+
|
|
||||||
+config RTL8366S_PHY
|
|
||||||
+ tristate "Driver for the Realtek RTL8366S switch"
|
|
||||||
+ select SWCONFIG
|
|
||||||
+
|
|
||||||
+config RTL8366RB_PHY
|
|
||||||
+ tristate "Driver for the Realtek RTL8366RB switch"
|
|
||||||
+ select SWCONFIG
|
|
||||||
+
|
|
||||||
+config RTL8366S_PHY_DEBUG_FS
|
|
||||||
+ bool "RTL8366 switch driver DEBUG_FS support"
|
|
||||||
+ depends on RTL8366S_PHY || RTL8366RB_PHY
|
|
||||||
+ depends on DEBUG_FS
|
|
||||||
+ default n
|
|
||||||
+
|
|
||||||
+endif # RTL8366_SMI
|
|
||||||
+
|
|
||||||
endif # PHYLIB
|
|
||||||
--- a/drivers/net/phy/Makefile
|
|
||||||
+++ b/drivers/net/phy/Makefile
|
|
||||||
@@ -20,6 +20,9 @@ obj-$(CONFIG_IP17XX_PHY) += ip17xx.o
|
|
||||||
obj-$(CONFIG_REALTEK_PHY) += realtek.o
|
|
||||||
obj-$(CONFIG_AR8216_PHY) += ar8216.o
|
|
||||||
obj-$(CONFIG_RTL8306_PHY) += rtl8306.o
|
|
||||||
+obj-$(CONFIG_RTL8366_SMI) += rtl8366_smi.o
|
|
||||||
+obj-$(CONFIG_RTL8366S_PHY) += rtl8366s.o
|
|
||||||
+obj-$(CONFIG_RTL8366RB_PHY) += rtl8366rb.o
|
|
||||||
obj-$(CONFIG_LSI_ET1011C_PHY) += et1011c.o
|
|
||||||
obj-$(CONFIG_FIXED_PHY) += fixed.o
|
|
||||||
obj-$(CONFIG_MDIO_BITBANG) += mdio-bitbang.o
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue