kernel: remove linux 3.8 support
Signed-off-by: Felix Fietkau <nbd@openwrt.org> git-svn-id: svn://svn.openwrt.org/openwrt/trunk@44890 3c298f89-4303-0410-b956-a3cf2f4a3e73master
parent
d121ed26a1
commit
3ab6563711
File diff suppressed because it is too large
Load Diff
|
@ -1,250 +0,0 @@
|
||||||
From 455bd4c430b0c0a361f38e8658a0d6cb469942b5 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Ivan Djelic <ivan.djelic@parrot.com>
|
|
||||||
Date: Wed, 6 Mar 2013 20:09:27 +0100
|
|
||||||
Subject: [PATCH] ARM: 7668/1: fix memset-related crashes caused by recent GCC
|
|
||||||
(4.7.2) optimizations
|
|
||||||
|
|
||||||
Recent GCC versions (e.g. GCC-4.7.2) perform optimizations based on
|
|
||||||
assumptions about the implementation of memset and similar functions.
|
|
||||||
The current ARM optimized memset code does not return the value of
|
|
||||||
its first argument, as is usually expected from standard implementations.
|
|
||||||
|
|
||||||
For instance in the following function:
|
|
||||||
|
|
||||||
void debug_mutex_lock_common(struct mutex *lock, struct mutex_waiter *waiter)
|
|
||||||
{
|
|
||||||
memset(waiter, MUTEX_DEBUG_INIT, sizeof(*waiter));
|
|
||||||
waiter->magic = waiter;
|
|
||||||
INIT_LIST_HEAD(&waiter->list);
|
|
||||||
}
|
|
||||||
|
|
||||||
compiled as:
|
|
||||||
|
|
||||||
800554d0 <debug_mutex_lock_common>:
|
|
||||||
800554d0: e92d4008 push {r3, lr}
|
|
||||||
800554d4: e1a00001 mov r0, r1
|
|
||||||
800554d8: e3a02010 mov r2, #16 ; 0x10
|
|
||||||
800554dc: e3a01011 mov r1, #17 ; 0x11
|
|
||||||
800554e0: eb04426e bl 80165ea0 <memset>
|
|
||||||
800554e4: e1a03000 mov r3, r0
|
|
||||||
800554e8: e583000c str r0, [r3, #12]
|
|
||||||
800554ec: e5830000 str r0, [r3]
|
|
||||||
800554f0: e5830004 str r0, [r3, #4]
|
|
||||||
800554f4: e8bd8008 pop {r3, pc}
|
|
||||||
|
|
||||||
GCC assumes memset returns the value of pointer 'waiter' in register r0; causing
|
|
||||||
register/memory corruptions.
|
|
||||||
|
|
||||||
This patch fixes the return value of the assembly version of memset.
|
|
||||||
It adds a 'mov' instruction and merges an additional load+store into
|
|
||||||
existing load/store instructions.
|
|
||||||
For ease of review, here is a breakdown of the patch into 4 simple steps:
|
|
||||||
|
|
||||||
Step 1
|
|
||||||
======
|
|
||||||
Perform the following substitutions:
|
|
||||||
ip -> r8, then
|
|
||||||
r0 -> ip,
|
|
||||||
and insert 'mov ip, r0' as the first statement of the function.
|
|
||||||
At this point, we have a memset() implementation returning the proper result,
|
|
||||||
but corrupting r8 on some paths (the ones that were using ip).
|
|
||||||
|
|
||||||
Step 2
|
|
||||||
======
|
|
||||||
Make sure r8 is saved and restored when (! CALGN(1)+0) == 1:
|
|
||||||
|
|
||||||
save r8:
|
|
||||||
- str lr, [sp, #-4]!
|
|
||||||
+ stmfd sp!, {r8, lr}
|
|
||||||
|
|
||||||
and restore r8 on both exit paths:
|
|
||||||
- ldmeqfd sp!, {pc} @ Now <64 bytes to go.
|
|
||||||
+ ldmeqfd sp!, {r8, pc} @ Now <64 bytes to go.
|
|
||||||
(...)
|
|
||||||
tst r2, #16
|
|
||||||
stmneia ip!, {r1, r3, r8, lr}
|
|
||||||
- ldr lr, [sp], #4
|
|
||||||
+ ldmfd sp!, {r8, lr}
|
|
||||||
|
|
||||||
Step 3
|
|
||||||
======
|
|
||||||
Make sure r8 is saved and restored when (! CALGN(1)+0) == 0:
|
|
||||||
|
|
||||||
save r8:
|
|
||||||
- stmfd sp!, {r4-r7, lr}
|
|
||||||
+ stmfd sp!, {r4-r8, lr}
|
|
||||||
|
|
||||||
and restore r8 on both exit paths:
|
|
||||||
bgt 3b
|
|
||||||
- ldmeqfd sp!, {r4-r7, pc}
|
|
||||||
+ ldmeqfd sp!, {r4-r8, pc}
|
|
||||||
(...)
|
|
||||||
tst r2, #16
|
|
||||||
stmneia ip!, {r4-r7}
|
|
||||||
- ldmfd sp!, {r4-r7, lr}
|
|
||||||
+ ldmfd sp!, {r4-r8, lr}
|
|
||||||
|
|
||||||
Step 4
|
|
||||||
======
|
|
||||||
Rewrite register list "r4-r7, r8" as "r4-r8".
|
|
||||||
|
|
||||||
Signed-off-by: Ivan Djelic <ivan.djelic@parrot.com>
|
|
||||||
Reviewed-by: Nicolas Pitre <nico@linaro.org>
|
|
||||||
Signed-off-by: Dirk Behme <dirk.behme@gmail.com>
|
|
||||||
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
|
|
||||||
---
|
|
||||||
arch/arm/lib/memset.S | 85 ++++++++++++++++++++++++++-------------------------
|
|
||||||
1 file changed, 44 insertions(+), 41 deletions(-)
|
|
||||||
|
|
||||||
--- a/arch/arm/lib/memset.S
|
|
||||||
+++ b/arch/arm/lib/memset.S
|
|
||||||
@@ -19,9 +19,9 @@
|
|
||||||
1: subs r2, r2, #4 @ 1 do we have enough
|
|
||||||
blt 5f @ 1 bytes to align with?
|
|
||||||
cmp r3, #2 @ 1
|
|
||||||
- strltb r1, [r0], #1 @ 1
|
|
||||||
- strleb r1, [r0], #1 @ 1
|
|
||||||
- strb r1, [r0], #1 @ 1
|
|
||||||
+ strltb r1, [ip], #1 @ 1
|
|
||||||
+ strleb r1, [ip], #1 @ 1
|
|
||||||
+ strb r1, [ip], #1 @ 1
|
|
||||||
add r2, r2, r3 @ 1 (r2 = r2 - (4 - r3))
|
|
||||||
/*
|
|
||||||
* The pointer is now aligned and the length is adjusted. Try doing the
|
|
||||||
@@ -29,10 +29,14 @@
|
|
||||||
*/
|
|
||||||
|
|
||||||
ENTRY(memset)
|
|
||||||
- ands r3, r0, #3 @ 1 unaligned?
|
|
||||||
+/*
|
|
||||||
+ * Preserve the contents of r0 for the return value.
|
|
||||||
+ */
|
|
||||||
+ mov ip, r0
|
|
||||||
+ ands r3, ip, #3 @ 1 unaligned?
|
|
||||||
bne 1b @ 1
|
|
||||||
/*
|
|
||||||
- * we know that the pointer in r0 is aligned to a word boundary.
|
|
||||||
+ * we know that the pointer in ip is aligned to a word boundary.
|
|
||||||
*/
|
|
||||||
orr r1, r1, r1, lsl #8
|
|
||||||
orr r1, r1, r1, lsl #16
|
|
||||||
@@ -43,29 +47,28 @@ ENTRY(memset)
|
|
||||||
#if ! CALGN(1)+0
|
|
||||||
|
|
||||||
/*
|
|
||||||
- * We need an extra register for this loop - save the return address and
|
|
||||||
- * use the LR
|
|
||||||
+ * We need 2 extra registers for this loop - use r8 and the LR
|
|
||||||
*/
|
|
||||||
- str lr, [sp, #-4]!
|
|
||||||
- mov ip, r1
|
|
||||||
+ stmfd sp!, {r8, lr}
|
|
||||||
+ mov r8, r1
|
|
||||||
mov lr, r1
|
|
||||||
|
|
||||||
2: subs r2, r2, #64
|
|
||||||
- stmgeia r0!, {r1, r3, ip, lr} @ 64 bytes at a time.
|
|
||||||
- stmgeia r0!, {r1, r3, ip, lr}
|
|
||||||
- stmgeia r0!, {r1, r3, ip, lr}
|
|
||||||
- stmgeia r0!, {r1, r3, ip, lr}
|
|
||||||
+ stmgeia ip!, {r1, r3, r8, lr} @ 64 bytes at a time.
|
|
||||||
+ stmgeia ip!, {r1, r3, r8, lr}
|
|
||||||
+ stmgeia ip!, {r1, r3, r8, lr}
|
|
||||||
+ stmgeia ip!, {r1, r3, r8, lr}
|
|
||||||
bgt 2b
|
|
||||||
- ldmeqfd sp!, {pc} @ Now <64 bytes to go.
|
|
||||||
+ ldmeqfd sp!, {r8, pc} @ Now <64 bytes to go.
|
|
||||||
/*
|
|
||||||
* No need to correct the count; we're only testing bits from now on
|
|
||||||
*/
|
|
||||||
tst r2, #32
|
|
||||||
- stmneia r0!, {r1, r3, ip, lr}
|
|
||||||
- stmneia r0!, {r1, r3, ip, lr}
|
|
||||||
+ stmneia ip!, {r1, r3, r8, lr}
|
|
||||||
+ stmneia ip!, {r1, r3, r8, lr}
|
|
||||||
tst r2, #16
|
|
||||||
- stmneia r0!, {r1, r3, ip, lr}
|
|
||||||
- ldr lr, [sp], #4
|
|
||||||
+ stmneia ip!, {r1, r3, r8, lr}
|
|
||||||
+ ldmfd sp!, {r8, lr}
|
|
||||||
|
|
||||||
#else
|
|
||||||
|
|
||||||
@@ -74,54 +77,54 @@ ENTRY(memset)
|
|
||||||
* whole cache lines at once.
|
|
||||||
*/
|
|
||||||
|
|
||||||
- stmfd sp!, {r4-r7, lr}
|
|
||||||
+ stmfd sp!, {r4-r8, lr}
|
|
||||||
mov r4, r1
|
|
||||||
mov r5, r1
|
|
||||||
mov r6, r1
|
|
||||||
mov r7, r1
|
|
||||||
- mov ip, r1
|
|
||||||
+ mov r8, r1
|
|
||||||
mov lr, r1
|
|
||||||
|
|
||||||
cmp r2, #96
|
|
||||||
- tstgt r0, #31
|
|
||||||
+ tstgt ip, #31
|
|
||||||
ble 3f
|
|
||||||
|
|
||||||
- and ip, r0, #31
|
|
||||||
- rsb ip, ip, #32
|
|
||||||
- sub r2, r2, ip
|
|
||||||
- movs ip, ip, lsl #(32 - 4)
|
|
||||||
- stmcsia r0!, {r4, r5, r6, r7}
|
|
||||||
- stmmiia r0!, {r4, r5}
|
|
||||||
- tst ip, #(1 << 30)
|
|
||||||
- mov ip, r1
|
|
||||||
- strne r1, [r0], #4
|
|
||||||
+ and r8, ip, #31
|
|
||||||
+ rsb r8, r8, #32
|
|
||||||
+ sub r2, r2, r8
|
|
||||||
+ movs r8, r8, lsl #(32 - 4)
|
|
||||||
+ stmcsia ip!, {r4, r5, r6, r7}
|
|
||||||
+ stmmiia ip!, {r4, r5}
|
|
||||||
+ tst r8, #(1 << 30)
|
|
||||||
+ mov r8, r1
|
|
||||||
+ strne r1, [ip], #4
|
|
||||||
|
|
||||||
3: subs r2, r2, #64
|
|
||||||
- stmgeia r0!, {r1, r3-r7, ip, lr}
|
|
||||||
- stmgeia r0!, {r1, r3-r7, ip, lr}
|
|
||||||
+ stmgeia ip!, {r1, r3-r8, lr}
|
|
||||||
+ stmgeia ip!, {r1, r3-r8, lr}
|
|
||||||
bgt 3b
|
|
||||||
- ldmeqfd sp!, {r4-r7, pc}
|
|
||||||
+ ldmeqfd sp!, {r4-r8, pc}
|
|
||||||
|
|
||||||
tst r2, #32
|
|
||||||
- stmneia r0!, {r1, r3-r7, ip, lr}
|
|
||||||
+ stmneia ip!, {r1, r3-r8, lr}
|
|
||||||
tst r2, #16
|
|
||||||
- stmneia r0!, {r4-r7}
|
|
||||||
- ldmfd sp!, {r4-r7, lr}
|
|
||||||
+ stmneia ip!, {r4-r7}
|
|
||||||
+ ldmfd sp!, {r4-r8, lr}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
4: tst r2, #8
|
|
||||||
- stmneia r0!, {r1, r3}
|
|
||||||
+ stmneia ip!, {r1, r3}
|
|
||||||
tst r2, #4
|
|
||||||
- strne r1, [r0], #4
|
|
||||||
+ strne r1, [ip], #4
|
|
||||||
/*
|
|
||||||
* When we get here, we've got less than 4 bytes to zero. We
|
|
||||||
* may have an unaligned pointer as well.
|
|
||||||
*/
|
|
||||||
5: tst r2, #2
|
|
||||||
- strneb r1, [r0], #1
|
|
||||||
- strneb r1, [r0], #1
|
|
||||||
+ strneb r1, [ip], #1
|
|
||||||
+ strneb r1, [ip], #1
|
|
||||||
tst r2, #1
|
|
||||||
- strneb r1, [r0], #1
|
|
||||||
+ strneb r1, [ip], #1
|
|
||||||
mov pc, lr
|
|
||||||
ENDPROC(memset)
|
|
|
@ -1,78 +0,0 @@
|
||||||
From 418df63adac56841ef6b0f1fcf435bc64d4ed177 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Nicolas Pitre <nicolas.pitre@linaro.org>
|
|
||||||
Date: Tue, 12 Mar 2013 13:00:42 +0100
|
|
||||||
Subject: [PATCH] ARM: 7670/1: fix the memset fix
|
|
||||||
|
|
||||||
Commit 455bd4c430b0 ("ARM: 7668/1: fix memset-related crashes caused by
|
|
||||||
recent GCC (4.7.2) optimizations") attempted to fix a compliance issue
|
|
||||||
with the memset return value. However the memset itself became broken
|
|
||||||
by that patch for misaligned pointers.
|
|
||||||
|
|
||||||
This fixes the above by branching over the entry code from the
|
|
||||||
misaligned fixup code to avoid reloading the original pointer.
|
|
||||||
|
|
||||||
Also, because the function entry alignment is wrong in the Thumb mode
|
|
||||||
compilation, that fixup code is moved to the end.
|
|
||||||
|
|
||||||
While at it, the entry instructions are slightly reworked to help dual
|
|
||||||
issue pipelines.
|
|
||||||
|
|
||||||
Signed-off-by: Nicolas Pitre <nico@linaro.org>
|
|
||||||
Tested-by: Alexander Holler <holler@ahsoftware.de>
|
|
||||||
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
|
|
||||||
---
|
|
||||||
arch/arm/lib/memset.S | 33 +++++++++++++--------------------
|
|
||||||
1 file changed, 13 insertions(+), 20 deletions(-)
|
|
||||||
|
|
||||||
--- a/arch/arm/lib/memset.S
|
|
||||||
+++ b/arch/arm/lib/memset.S
|
|
||||||
@@ -14,31 +14,15 @@
|
|
||||||
|
|
||||||
.text
|
|
||||||
.align 5
|
|
||||||
- .word 0
|
|
||||||
-
|
|
||||||
-1: subs r2, r2, #4 @ 1 do we have enough
|
|
||||||
- blt 5f @ 1 bytes to align with?
|
|
||||||
- cmp r3, #2 @ 1
|
|
||||||
- strltb r1, [ip], #1 @ 1
|
|
||||||
- strleb r1, [ip], #1 @ 1
|
|
||||||
- strb r1, [ip], #1 @ 1
|
|
||||||
- add r2, r2, r3 @ 1 (r2 = r2 - (4 - r3))
|
|
||||||
-/*
|
|
||||||
- * The pointer is now aligned and the length is adjusted. Try doing the
|
|
||||||
- * memset again.
|
|
||||||
- */
|
|
||||||
|
|
||||||
ENTRY(memset)
|
|
||||||
-/*
|
|
||||||
- * Preserve the contents of r0 for the return value.
|
|
||||||
- */
|
|
||||||
- mov ip, r0
|
|
||||||
- ands r3, ip, #3 @ 1 unaligned?
|
|
||||||
- bne 1b @ 1
|
|
||||||
+ ands r3, r0, #3 @ 1 unaligned?
|
|
||||||
+ mov ip, r0 @ preserve r0 as return value
|
|
||||||
+ bne 6f @ 1
|
|
||||||
/*
|
|
||||||
* we know that the pointer in ip is aligned to a word boundary.
|
|
||||||
*/
|
|
||||||
- orr r1, r1, r1, lsl #8
|
|
||||||
+1: orr r1, r1, r1, lsl #8
|
|
||||||
orr r1, r1, r1, lsl #16
|
|
||||||
mov r3, r1
|
|
||||||
cmp r2, #16
|
|
||||||
@@ -127,4 +111,13 @@ ENTRY(memset)
|
|
||||||
tst r2, #1
|
|
||||||
strneb r1, [ip], #1
|
|
||||||
mov pc, lr
|
|
||||||
+
|
|
||||||
+6: subs r2, r2, #4 @ 1 do we have enough
|
|
||||||
+ blt 5b @ 1 bytes to align with?
|
|
||||||
+ cmp r3, #2 @ 1
|
|
||||||
+ strltb r1, [ip], #1 @ 1
|
|
||||||
+ strleb r1, [ip], #1 @ 1
|
|
||||||
+ strb r1, [ip], #1 @ 1
|
|
||||||
+ add r2, r2, r3 @ 1 (r2 = r2 - (4 - r3))
|
|
||||||
+ b 1b
|
|
||||||
ENDPROC(memset)
|
|
|
@ -1,40 +0,0 @@
|
||||||
From 35e57e1b49a351aa804dab6010cd46ae6112a541 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Daniel Gimpelevich <daniel@gimpelevich.san-francisco.ca.us>
|
|
||||||
Date: Wed, 21 Aug 2013 01:43:07 -0700
|
|
||||||
Subject: [PATCH 1/2] hso: Earlier catch of error condition
|
|
||||||
|
|
||||||
There is no need to get an interface specification if we know it's the
|
|
||||||
wrong one.
|
|
||||||
|
|
||||||
Signed-off-by: Daniel Gimpelevich <daniel@gimpelevich.san-francisco.ca.us>
|
|
||||||
Acked-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
|
|
||||||
Signed-off-by: David S. Miller <davem@davemloft.net>
|
|
||||||
---
|
|
||||||
drivers/net/usb/hso.c | 9 +++++----
|
|
||||||
1 file changed, 5 insertions(+), 4 deletions(-)
|
|
||||||
|
|
||||||
--- a/drivers/net/usb/hso.c
|
|
||||||
+++ b/drivers/net/usb/hso.c
|
|
||||||
@@ -2908,6 +2908,11 @@ static int hso_probe(struct usb_interfac
|
|
||||||
struct hso_shared_int *shared_int;
|
|
||||||
struct hso_device *tmp_dev = NULL;
|
|
||||||
|
|
||||||
+ if (interface->cur_altsetting->desc.bInterfaceClass != 0xFF) {
|
|
||||||
+ dev_err(&interface->dev, "Not our interface\n");
|
|
||||||
+ return -ENODEV;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
if_num = interface->altsetting->desc.bInterfaceNumber;
|
|
||||||
|
|
||||||
/* Get the interface/port specification from either driver_info or from
|
|
||||||
@@ -2917,10 +2922,6 @@ static int hso_probe(struct usb_interfac
|
|
||||||
else
|
|
||||||
port_spec = hso_get_config_data(interface);
|
|
||||||
|
|
||||||
- if (interface->cur_altsetting->desc.bInterfaceClass != 0xFF) {
|
|
||||||
- dev_err(&interface->dev, "Not our interface\n");
|
|
||||||
- return -ENODEV;
|
|
||||||
- }
|
|
||||||
/* Check if we need to switch to alt interfaces prior to port
|
|
||||||
* configuration */
|
|
||||||
if (interface->num_altsetting > 1)
|
|
|
@ -1,48 +0,0 @@
|
||||||
From e75dc677ff8d06ffa61bef6fee436227ae5440c6 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Daniel Gimpelevich <daniel@gimpelevich.san-francisco.ca.us>
|
|
||||||
Date: Wed, 21 Aug 2013 01:43:19 -0700
|
|
||||||
Subject: [PATCH 2/2] hso: Fix stack corruption on some architectures
|
|
||||||
|
|
||||||
As Sergei Shtylyov explained in the #mipslinux IRC channel:
|
|
||||||
[Mon 2013-08-19 12:28:21 PM PDT] <headless> guys, are you sure it's not "DMA off stack" case?
|
|
||||||
[Mon 2013-08-19 12:28:35 PM PDT] <headless> it's a known stack corruptor on non-coherent arches
|
|
||||||
[Mon 2013-08-19 12:31:48 PM PDT] <DonkeyHotei> headless: for usb/ehci?
|
|
||||||
[Mon 2013-08-19 12:34:11 PM PDT] <DonkeyHotei> headless: explain
|
|
||||||
[Mon 2013-08-19 12:35:38 PM PDT] <headless> usb_control_msg() (or other such func) should not use buffer on stack. DMA from/to stack is prohibited
|
|
||||||
[Mon 2013-08-19 12:35:58 PM PDT] <headless> and EHCI uses DMA on control xfers (as well as all the others)
|
|
||||||
|
|
||||||
Signed-off-by: Daniel Gimpelevich <daniel@gimpelevich.san-francisco.ca.us>
|
|
||||||
Acked-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
|
|
||||||
Signed-off-by: David S. Miller <davem@davemloft.net>
|
|
||||||
---
|
|
||||||
drivers/net/usb/hso.c | 6 +++++-
|
|
||||||
1 file changed, 5 insertions(+), 1 deletion(-)
|
|
||||||
|
|
||||||
--- a/drivers/net/usb/hso.c
|
|
||||||
+++ b/drivers/net/usb/hso.c
|
|
||||||
@@ -2838,13 +2838,16 @@ exit:
|
|
||||||
static int hso_get_config_data(struct usb_interface *interface)
|
|
||||||
{
|
|
||||||
struct usb_device *usbdev = interface_to_usbdev(interface);
|
|
||||||
- u8 config_data[17];
|
|
||||||
+ u8 *config_data = kmalloc(17, GFP_KERNEL);
|
|
||||||
u32 if_num = interface->altsetting->desc.bInterfaceNumber;
|
|
||||||
s32 result;
|
|
||||||
|
|
||||||
+ if (!config_data)
|
|
||||||
+ return -ENOMEM;
|
|
||||||
if (usb_control_msg(usbdev, usb_rcvctrlpipe(usbdev, 0),
|
|
||||||
0x86, 0xC0, 0, 0, config_data, 17,
|
|
||||||
USB_CTRL_SET_TIMEOUT) != 0x11) {
|
|
||||||
+ kfree(config_data);
|
|
||||||
return -EIO;
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -2895,6 +2898,7 @@ static int hso_get_config_data(struct us
|
|
||||||
if (config_data[16] & 0x1)
|
|
||||||
result |= HSO_INFO_CRC_BUG;
|
|
||||||
|
|
||||||
+ kfree(config_data);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,13 +0,0 @@
|
||||||
--- a/drivers/mtd/devices/m25p80.c
|
|
||||||
+++ b/drivers/mtd/devices/m25p80.c
|
|
||||||
@@ -642,6 +642,10 @@ static const struct spi_device_id m25p_i
|
|
||||||
/* Everspin */
|
|
||||||
{ "mr25h256", CAT25_INFO( 32 * 1024, 1, 256, 2) },
|
|
||||||
|
|
||||||
+ /* GigaDevice */
|
|
||||||
+ { "gd25q32", INFO(0xc84016, 0, 64 * 1024, 64, SECT_4K) },
|
|
||||||
+ { "gd25q64", INFO(0xc84017, 0, 64 * 1024, 128, SECT_4K) },
|
|
||||||
+
|
|
||||||
/* Intel/Numonyx -- xxxs33b */
|
|
||||||
{ "160s33b", INFO(0x898911, 0, 64 * 1024, 32, 0) },
|
|
||||||
{ "320s33b", INFO(0x898912, 0, 64 * 1024, 64, 0) },
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -1,251 +0,0 @@
|
||||||
From 75096579c3ac39ddc2f8b0d9a8924eba31f4d920 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Thierry Reding <thierry.reding@avionic-design.de>
|
|
||||||
Date: Mon, 21 Jan 2013 11:08:54 +0100
|
|
||||||
Subject: [PATCH] lib: devres: Introduce devm_ioremap_resource()
|
|
||||||
|
|
||||||
The devm_request_and_ioremap() function is very useful and helps avoid a
|
|
||||||
whole lot of boilerplate. However, one issue that keeps popping up is
|
|
||||||
its lack of a specific error code to determine which of the steps that
|
|
||||||
it performs failed. Furthermore, while the function gives an example and
|
|
||||||
suggests what error code to return on failure, a wide variety of error
|
|
||||||
codes are used throughout the tree.
|
|
||||||
|
|
||||||
In an attempt to fix these problems, this patch adds a new function that
|
|
||||||
drivers can transition to. The devm_ioremap_resource() returns a pointer
|
|
||||||
to the remapped I/O memory on success or an ERR_PTR() encoded error code
|
|
||||||
on failure. Callers can check for failure using IS_ERR() and determine
|
|
||||||
its cause by extracting the error code using PTR_ERR().
|
|
||||||
|
|
||||||
devm_request_and_ioremap() is implemented as a wrapper around the new
|
|
||||||
API and return NULL on failure as before. This ensures that backwards
|
|
||||||
compatibility is maintained until all users have been converted to the
|
|
||||||
new API, at which point the old devm_request_and_ioremap() function
|
|
||||||
should be removed.
|
|
||||||
|
|
||||||
A semantic patch is included which can be used to convert from the old
|
|
||||||
devm_request_and_ioremap() API to the new devm_ioremap_resource() API.
|
|
||||||
Some non-trivial cases may require manual intervention, though.
|
|
||||||
|
|
||||||
Signed-off-by: Thierry Reding <thierry.reding@avionic-design.de>
|
|
||||||
Cc: Arnd Bergmann <arnd@arndb.de>
|
|
||||||
Acked-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
|
|
||||||
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
|
|
||||||
---
|
|
||||||
Documentation/driver-model/devres.txt | 3 +-
|
|
||||||
include/linux/device.h | 1 +
|
|
||||||
lib/devres.c | 57 ++++++++++---
|
|
||||||
scripts/coccinelle/api/devm_ioremap_resource.cocci | 90 ++++++++++++++++++++
|
|
||||||
4 files changed, 137 insertions(+), 14 deletions(-)
|
|
||||||
create mode 100644 scripts/coccinelle/api/devm_ioremap_resource.cocci
|
|
||||||
|
|
||||||
--- a/Documentation/driver-model/devres.txt
|
|
||||||
+++ b/Documentation/driver-model/devres.txt
|
|
||||||
@@ -266,7 +266,8 @@ IOMAP
|
|
||||||
devm_ioremap()
|
|
||||||
devm_ioremap_nocache()
|
|
||||||
devm_iounmap()
|
|
||||||
- devm_request_and_ioremap() : checks resource, requests region, ioremaps
|
|
||||||
+ devm_ioremap_resource() : checks resource, requests memory region, ioremaps
|
|
||||||
+ devm_request_and_ioremap() : obsoleted by devm_ioremap_resource()
|
|
||||||
pcim_iomap()
|
|
||||||
pcim_iounmap()
|
|
||||||
pcim_iomap_table() : array of mapped addresses indexed by BAR
|
|
||||||
--- a/include/linux/device.h
|
|
||||||
+++ b/include/linux/device.h
|
|
||||||
@@ -573,6 +573,7 @@ extern int devres_release_group(struct d
|
|
||||||
extern void *devm_kzalloc(struct device *dev, size_t size, gfp_t gfp);
|
|
||||||
extern void devm_kfree(struct device *dev, void *p);
|
|
||||||
|
|
||||||
+void __iomem *devm_ioremap_resource(struct device *dev, struct resource *res);
|
|
||||||
void __iomem *devm_request_and_ioremap(struct device *dev,
|
|
||||||
struct resource *res);
|
|
||||||
|
|
||||||
--- a/lib/devres.c
|
|
||||||
+++ b/lib/devres.c
|
|
||||||
@@ -86,22 +86,24 @@ void devm_iounmap(struct device *dev, vo
|
|
||||||
EXPORT_SYMBOL(devm_iounmap);
|
|
||||||
|
|
||||||
/**
|
|
||||||
- * devm_request_and_ioremap() - Check, request region, and ioremap resource
|
|
||||||
- * @dev: Generic device to handle the resource for
|
|
||||||
+ * devm_ioremap_resource() - check, request region, and ioremap resource
|
|
||||||
+ * @dev: generic device to handle the resource for
|
|
||||||
* @res: resource to be handled
|
|
||||||
*
|
|
||||||
- * Takes all necessary steps to ioremap a mem resource. Uses managed device, so
|
|
||||||
- * everything is undone on driver detach. Checks arguments, so you can feed
|
|
||||||
- * it the result from e.g. platform_get_resource() directly. Returns the
|
|
||||||
- * remapped pointer or NULL on error. Usage example:
|
|
||||||
+ * Checks that a resource is a valid memory region, requests the memory region
|
|
||||||
+ * and ioremaps it either as cacheable or as non-cacheable memory depending on
|
|
||||||
+ * the resource's flags. All operations are managed and will be undone on
|
|
||||||
+ * driver detach.
|
|
||||||
+ *
|
|
||||||
+ * Returns a pointer to the remapped memory or an ERR_PTR() encoded error code
|
|
||||||
+ * on failure. Usage example:
|
|
||||||
*
|
|
||||||
* res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
|
||||||
- * base = devm_request_and_ioremap(&pdev->dev, res);
|
|
||||||
- * if (!base)
|
|
||||||
- * return -EADDRNOTAVAIL;
|
|
||||||
+ * base = devm_ioremap_resource(&pdev->dev, res);
|
|
||||||
+ * if (IS_ERR(base))
|
|
||||||
+ * return PTR_ERR(base);
|
|
||||||
*/
|
|
||||||
-void __iomem *devm_request_and_ioremap(struct device *dev,
|
|
||||||
- struct resource *res)
|
|
||||||
+void __iomem *devm_ioremap_resource(struct device *dev, struct resource *res)
|
|
||||||
{
|
|
||||||
resource_size_t size;
|
|
||||||
const char *name;
|
|
||||||
@@ -111,7 +113,7 @@ void __iomem *devm_request_and_ioremap(s
|
|
||||||
|
|
||||||
if (!res || resource_type(res) != IORESOURCE_MEM) {
|
|
||||||
dev_err(dev, "invalid resource\n");
|
|
||||||
- return NULL;
|
|
||||||
+ return ERR_PTR(-EINVAL);
|
|
||||||
}
|
|
||||||
|
|
||||||
size = resource_size(res);
|
|
||||||
@@ -119,7 +121,7 @@ void __iomem *devm_request_and_ioremap(s
|
|
||||||
|
|
||||||
if (!devm_request_mem_region(dev, res->start, size, name)) {
|
|
||||||
dev_err(dev, "can't request region for resource %pR\n", res);
|
|
||||||
- return NULL;
|
|
||||||
+ return ERR_PTR(-EBUSY);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (res->flags & IORESOURCE_CACHEABLE)
|
|
||||||
@@ -130,10 +132,39 @@ void __iomem *devm_request_and_ioremap(s
|
|
||||||
if (!dest_ptr) {
|
|
||||||
dev_err(dev, "ioremap failed for resource %pR\n", res);
|
|
||||||
devm_release_mem_region(dev, res->start, size);
|
|
||||||
+ dest_ptr = ERR_PTR(-ENOMEM);
|
|
||||||
}
|
|
||||||
|
|
||||||
return dest_ptr;
|
|
||||||
}
|
|
||||||
+EXPORT_SYMBOL(devm_ioremap_resource);
|
|
||||||
+
|
|
||||||
+/**
|
|
||||||
+ * devm_request_and_ioremap() - Check, request region, and ioremap resource
|
|
||||||
+ * @dev: Generic device to handle the resource for
|
|
||||||
+ * @res: resource to be handled
|
|
||||||
+ *
|
|
||||||
+ * Takes all necessary steps to ioremap a mem resource. Uses managed device, so
|
|
||||||
+ * everything is undone on driver detach. Checks arguments, so you can feed
|
|
||||||
+ * it the result from e.g. platform_get_resource() directly. Returns the
|
|
||||||
+ * remapped pointer or NULL on error. Usage example:
|
|
||||||
+ *
|
|
||||||
+ * res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
|
||||||
+ * base = devm_request_and_ioremap(&pdev->dev, res);
|
|
||||||
+ * if (!base)
|
|
||||||
+ * return -EADDRNOTAVAIL;
|
|
||||||
+ */
|
|
||||||
+void __iomem *devm_request_and_ioremap(struct device *device,
|
|
||||||
+ struct resource *res)
|
|
||||||
+{
|
|
||||||
+ void __iomem *dest_ptr;
|
|
||||||
+
|
|
||||||
+ dest_ptr = devm_ioremap_resource(device, res);
|
|
||||||
+ if (IS_ERR(dest_ptr))
|
|
||||||
+ return NULL;
|
|
||||||
+
|
|
||||||
+ return dest_ptr;
|
|
||||||
+}
|
|
||||||
EXPORT_SYMBOL(devm_request_and_ioremap);
|
|
||||||
|
|
||||||
#ifdef CONFIG_HAS_IOPORT
|
|
||||||
--- /dev/null
|
|
||||||
+++ b/scripts/coccinelle/api/devm_ioremap_resource.cocci
|
|
||||||
@@ -0,0 +1,90 @@
|
|
||||||
+virtual patch
|
|
||||||
+virtual report
|
|
||||||
+
|
|
||||||
+@depends on patch@
|
|
||||||
+expression base, dev, res;
|
|
||||||
+@@
|
|
||||||
+
|
|
||||||
+-base = devm_request_and_ioremap(dev, res);
|
|
||||||
++base = devm_ioremap_resource(dev, res);
|
|
||||||
+ ...
|
|
||||||
+ if (
|
|
||||||
+-base == NULL
|
|
||||||
++IS_ERR(base)
|
|
||||||
+ || ...) {
|
|
||||||
+<...
|
|
||||||
+- return ...;
|
|
||||||
++ return PTR_ERR(base);
|
|
||||||
+...>
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+@depends on patch@
|
|
||||||
+expression e, E, ret;
|
|
||||||
+identifier l;
|
|
||||||
+@@
|
|
||||||
+
|
|
||||||
+ e = devm_ioremap_resource(...);
|
|
||||||
+ ...
|
|
||||||
+ if (IS_ERR(e) || ...) {
|
|
||||||
+ ... when any
|
|
||||||
+- ret = E;
|
|
||||||
++ ret = PTR_ERR(e);
|
|
||||||
+ ...
|
|
||||||
+(
|
|
||||||
+ return ret;
|
|
||||||
+|
|
|
||||||
+ goto l;
|
|
||||||
+)
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+@depends on patch@
|
|
||||||
+expression e;
|
|
||||||
+@@
|
|
||||||
+
|
|
||||||
+ e = devm_ioremap_resource(...);
|
|
||||||
+ ...
|
|
||||||
+ if (IS_ERR(e) || ...) {
|
|
||||||
+ ...
|
|
||||||
+- \(dev_dbg\|dev_err\|pr_debug\|pr_err\|DRM_ERROR\)(...);
|
|
||||||
+ ...
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+@depends on patch@
|
|
||||||
+expression e;
|
|
||||||
+identifier l;
|
|
||||||
+@@
|
|
||||||
+
|
|
||||||
+ e = devm_ioremap_resource(...);
|
|
||||||
+ ...
|
|
||||||
+ if (IS_ERR(e) || ...)
|
|
||||||
+-{
|
|
||||||
+(
|
|
||||||
+ return ...;
|
|
||||||
+|
|
|
||||||
+ goto l;
|
|
||||||
+)
|
|
||||||
+-}
|
|
||||||
+
|
|
||||||
+@r depends on report@
|
|
||||||
+expression e;
|
|
||||||
+identifier l;
|
|
||||||
+position p1;
|
|
||||||
+@@
|
|
||||||
+
|
|
||||||
+*e = devm_request_and_ioremap@p1(...);
|
|
||||||
+ ...
|
|
||||||
+ if (e == NULL || ...) {
|
|
||||||
+ ...
|
|
||||||
+(
|
|
||||||
+ return ...;
|
|
||||||
+|
|
|
||||||
+ goto l;
|
|
||||||
+)
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+@script:python depends on r@
|
|
||||||
+p1 << r.p1;
|
|
||||||
+@@
|
|
||||||
+
|
|
||||||
+msg = "ERROR: deprecated devm_request_and_ioremap() API used on line %s" % (p1[0].line)
|
|
||||||
+coccilib.report.print_report(p1[0], msg)
|
|
|
@ -1,40 +0,0 @@
|
||||||
From 10629d711ed780470937ecda50d9ffa0e925a4ee Mon Sep 17 00:00:00 2001
|
|
||||||
From: Bjorn Helgaas <bhelgaas@google.com>
|
|
||||||
Date: Wed, 10 Apr 2013 09:56:54 -0600
|
|
||||||
Subject: [PATCH 1/2] PCI: Remove __weak annotation from
|
|
||||||
pcibios_get_phb_of_node decl
|
|
||||||
|
|
||||||
The __weak annotation on the pcibios_get_phb_of_node() declaration
|
|
||||||
causes *every* definition to be marked "weak." The linker then
|
|
||||||
selects one based on link order, which may be the wrong one.
|
|
||||||
|
|
||||||
Gabor found that on MIPS, the linker selected the generic implementation
|
|
||||||
from drivers/pci even though arch/mips supplied a definition without the
|
|
||||||
__weak annotation:
|
|
||||||
|
|
||||||
$ mipsel-openwrt-linux-readelf -s arch/mips/pci/built-in.o \
|
|
||||||
drivers/pci/built-in.o vmlinux.o | grep pcibios_get_phb_of_node
|
|
||||||
86: 0000046c 12 FUNC WEAK DEFAULT 2 pcibios_get_phb_of_node
|
|
||||||
1430: 00012e2c 104 FUNC WEAK DEFAULT 2 pcibios_get_phb_of_node
|
|
||||||
31898: 0017e4ec 104 FUNC WEAK DEFAULT 2 pcibios_get_phb_of_node
|
|
||||||
|
|
||||||
This removes the __weak annotation from the pcibios_get_phb_of_node()
|
|
||||||
declaration so arch-specific non-weak implementations work reliably.
|
|
||||||
|
|
||||||
Suggested-by: Gabor Juhos <juhosg@openwrt.org>
|
|
||||||
Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
|
|
||||||
---
|
|
||||||
include/linux/pci.h | 2 +-
|
|
||||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
|
||||||
|
|
||||||
--- a/include/linux/pci.h
|
|
||||||
+++ b/include/linux/pci.h
|
|
||||||
@@ -1803,7 +1803,7 @@ extern void pci_set_bus_of_node(struct p
|
|
||||||
extern void pci_release_bus_of_node(struct pci_bus *bus);
|
|
||||||
|
|
||||||
/* Arch may override this (weak) */
|
|
||||||
-extern struct device_node * __weak pcibios_get_phb_of_node(struct pci_bus *bus);
|
|
||||||
+extern struct device_node *pcibios_get_phb_of_node(struct pci_bus *bus);
|
|
||||||
|
|
||||||
static inline struct device_node *
|
|
||||||
pci_device_to_OF_node(const struct pci_dev *pdev)
|
|
|
@ -1,48 +0,0 @@
|
||||||
From 9a97cd43f4ef62520a852b5a2348233b0f37455b Mon Sep 17 00:00:00 2001
|
|
||||||
From: Gabor Juhos <juhosg@openwrt.org>
|
|
||||||
Date: Thu, 4 Apr 2013 20:01:23 +0200
|
|
||||||
Subject: [PATCH 2/2] MIPS/PCI: Implement pcibios_get_phb_of_node
|
|
||||||
|
|
||||||
The of_node field of the device assigned to a
|
|
||||||
PCI bus is used during scanning of the PCI bus.
|
|
||||||
However on MIPS, the of_node field is assigned
|
|
||||||
only after the bus has been scanned.
|
|
||||||
|
|
||||||
Implement the architecture specific version of
|
|
||||||
'pcibios_get_phb_of_node'. Which ensures that the
|
|
||||||
PCI driver core will initialize the of_node field
|
|
||||||
before starting the scan.
|
|
||||||
|
|
||||||
Also remove the local assignment of bus->dev.of_node,
|
|
||||||
it is not needed after the patch.
|
|
||||||
|
|
||||||
Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
|
|
||||||
Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
|
|
||||||
---
|
|
||||||
arch/mips/pci/pci.c | 8 +++++++-
|
|
||||||
1 file changed, 7 insertions(+), 1 deletion(-)
|
|
||||||
|
|
||||||
--- a/arch/mips/pci/pci.c
|
|
||||||
+++ b/arch/mips/pci/pci.c
|
|
||||||
@@ -115,7 +115,6 @@ static void pcibios_scanbus(struct pci_c
|
|
||||||
pci_bus_assign_resources(bus);
|
|
||||||
pci_enable_bridges(bus);
|
|
||||||
}
|
|
||||||
- bus->dev.of_node = hose->of_node;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -169,6 +168,13 @@ void pci_load_of_ranges(struct pci_contr
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
+
|
|
||||||
+struct device_node *pcibios_get_phb_of_node(struct pci_bus *bus)
|
|
||||||
+{
|
|
||||||
+ struct pci_controller *hose = bus->sysdata;
|
|
||||||
+
|
|
||||||
+ return of_node_get(hose->of_node);
|
|
||||||
+}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static DEFINE_MUTEX(pci_scan_mutex);
|
|
|
@ -1,37 +0,0 @@
|
||||||
From bb29785e0d6d150181704be2efcc3141044625e2 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Grant Likely <grant.likely@secretlab.ca>
|
|
||||||
Date: Fri, 21 Dec 2012 19:32:09 +0000
|
|
||||||
Subject: [PATCH] spi/of: Use DT aliases for assigning bus number
|
|
||||||
|
|
||||||
Linux assigns a number to each spi_master in the system, but when the
|
|
||||||
platform used the device tree, the numbers are dynamically assigned and
|
|
||||||
are not predictable. In general this shouldn't matter since the kernel
|
|
||||||
doesn't use the bus number for anything other than matching a bus to
|
|
||||||
spi_boardinfo (not used for DT). However, sometimes userspace needs to
|
|
||||||
figure out which bus is which, so it makes sense to use the global
|
|
||||||
/aliases namespace to choose a specific bus number.
|
|
||||||
|
|
||||||
It is safe to derive the bus number from an alias because aliases will
|
|
||||||
never cause two buses to try and use the same bus number. (At one time
|
|
||||||
the cell-index property was used for this purpose, but cell-index has
|
|
||||||
the risk of an id collision).
|
|
||||||
|
|
||||||
Signed-off-by: Grant Likely <grant.likely@secretlab.ca>
|
|
||||||
Cc: Anatolij Gustschin <agust@denx.de>
|
|
||||||
Cc: Mark Brown <broonie@opensource.wolfsonmicro.com>
|
|
||||||
---
|
|
||||||
drivers/spi/spi.c | 3 +++
|
|
||||||
1 file changed, 3 insertions(+)
|
|
||||||
|
|
||||||
--- a/drivers/spi/spi.c
|
|
||||||
+++ b/drivers/spi/spi.c
|
|
||||||
@@ -1135,6 +1135,9 @@ int spi_register_master(struct spi_maste
|
|
||||||
if (master->num_chipselect == 0)
|
|
||||||
return -EINVAL;
|
|
||||||
|
|
||||||
+ if ((master->bus_num < 0) && master->dev.of_node)
|
|
||||||
+ master->bus_num = of_alias_get_id(master->dev.of_node, "spi");
|
|
||||||
+
|
|
||||||
/* convention: dynamically assigned bus IDs count down from the max */
|
|
||||||
if (master->bus_num < 0) {
|
|
||||||
/* FIXME switch to an IDR based scheme, something like
|
|
|
@ -1,25 +0,0 @@
|
||||||
--- a/drivers/leds/leds-gpio.c
|
|
||||||
+++ b/drivers/leds/leds-gpio.c
|
|
||||||
@@ -107,6 +107,10 @@ static int create_gpio_led(const struct
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
+ ret = devm_gpio_request(parent, template->gpio, template->name);
|
|
||||||
+ if (ret < 0)
|
|
||||||
+ return ret;
|
|
||||||
+
|
|
||||||
led_dat->cdev.name = template->name;
|
|
||||||
led_dat->cdev.default_trigger = template->default_trigger;
|
|
||||||
led_dat->gpio = template->gpio;
|
|
||||||
@@ -126,10 +130,7 @@ static int create_gpio_led(const struct
|
|
||||||
if (!template->retain_state_suspended)
|
|
||||||
led_dat->cdev.flags |= LED_CORE_SUSPENDRESUME;
|
|
||||||
|
|
||||||
- ret = devm_gpio_request_one(parent, template->gpio,
|
|
||||||
- (led_dat->active_low ^ state) ?
|
|
||||||
- GPIOF_OUT_INIT_HIGH : GPIOF_OUT_INIT_LOW,
|
|
||||||
- template->name);
|
|
||||||
+ ret = gpio_direction_output(led_dat->gpio, led_dat->active_low ^ state);
|
|
||||||
if (ret < 0)
|
|
||||||
return ret;
|
|
||||||
|
|
|
@ -1,36 +0,0 @@
|
||||||
--- a/drivers/net/usb/hso.c
|
|
||||||
+++ b/drivers/net/usb/hso.c
|
|
||||||
@@ -468,8 +468,10 @@ static const struct usb_device_id hso_id
|
|
||||||
{USB_DEVICE(0x0af0, 0x8400)},
|
|
||||||
{USB_DEVICE(0x0af0, 0x8600)},
|
|
||||||
{USB_DEVICE(0x0af0, 0x8800)},
|
|
||||||
- {USB_DEVICE(0x0af0, 0x8900)},
|
|
||||||
- {USB_DEVICE(0x0af0, 0x9000)},
|
|
||||||
+ {USB_DEVICE(0x0af0, 0x8900)}, /* GTM 67xx */
|
|
||||||
+ {USB_DEVICE(0x0af0, 0x9000)}, /* GTM 66xx */
|
|
||||||
+ {USB_DEVICE(0x0af0, 0x9200)}, /* GTM 67xxWFS */
|
|
||||||
+ {USB_DEVICE(0x0af0, 0x9300)}, /* GTM 66xxWFS */
|
|
||||||
{USB_DEVICE(0x0af0, 0xd035)},
|
|
||||||
{USB_DEVICE(0x0af0, 0xd055)},
|
|
||||||
{USB_DEVICE(0x0af0, 0xd155)},
|
|
||||||
--- a/drivers/usb/storage/unusual_devs.h
|
|
||||||
+++ b/drivers/usb/storage/unusual_devs.h
|
|
||||||
@@ -1244,6 +1244,18 @@ UNUSUAL_DEV( 0x0af0, 0x8304, 0x0000, 0x0
|
|
||||||
USB_SC_DEVICE, USB_PR_DEVICE, NULL,
|
|
||||||
0 ),
|
|
||||||
|
|
||||||
+UNUSUAL_DEV( 0x0af0, 0x9200, 0x0000, 0x0000,
|
|
||||||
+ "Option",
|
|
||||||
+ "Globetrotter 67xxWFS SD-Card",
|
|
||||||
+ USB_SC_DEVICE, USB_PR_DEVICE, NULL,
|
|
||||||
+ 0 ),
|
|
||||||
+
|
|
||||||
+UNUSUAL_DEV( 0x0af0, 0x9300, 0x0000, 0x0000,
|
|
||||||
+ "Option",
|
|
||||||
+ "Globetrotter 66xxWFS SD-Card",
|
|
||||||
+ USB_SC_DEVICE, USB_PR_DEVICE, NULL,
|
|
||||||
+ 0 ),
|
|
||||||
+
|
|
||||||
UNUSUAL_DEV( 0x0af0, 0xc100, 0x0000, 0x0000,
|
|
||||||
"Option",
|
|
||||||
"GI 070x SD-Card",
|
|
|
@ -1,10 +0,0 @@
|
||||||
--- a/arch/arm/boot/compressed/decompress.c
|
|
||||||
+++ b/arch/arm/boot/compressed/decompress.c
|
|
||||||
@@ -50,6 +50,7 @@ extern char * strstr(const char * s1, co
|
|
||||||
#ifdef CONFIG_KERNEL_XZ
|
|
||||||
#define memmove memmove
|
|
||||||
#define memcpy memcpy
|
|
||||||
+extern char * strstr(const char *, const char *);
|
|
||||||
#include "../../../../lib/decompress_unxz.c"
|
|
||||||
#endif
|
|
||||||
|
|
|
@ -1,66 +0,0 @@
|
||||||
From 0db3db45f5bd6df4bdc03bbd5dec672e16164c4e Mon Sep 17 00:00:00 2001
|
|
||||||
From: Florian Fainelli <florian@openwrt.org>
|
|
||||||
Date: Mon, 12 Nov 2012 12:31:55 +0100
|
|
||||||
Subject: [PATCH] MIPS: decompressor: fix build failure on memcpy() in
|
|
||||||
decompress.c
|
|
||||||
|
|
||||||
The decompress.c file includes linux/kernel.h which causes the following
|
|
||||||
inclusion chain to be pulled:
|
|
||||||
linux/kernel.h ->
|
|
||||||
linux/dynamic_debug.h ->
|
|
||||||
linux/string.h ->
|
|
||||||
asm/string.h
|
|
||||||
|
|
||||||
We end up having a the GCC builtin + architecture specific memcpy() expanding
|
|
||||||
into this:
|
|
||||||
|
|
||||||
void *({ size_t __len = (size_t n); void *__ret; if
|
|
||||||
(__builtin_constant_p(size_t n) && __len >= 64) __ret = memcpy((void *dest),
|
|
||||||
(const void *src), __len); else __ret = __builtin_memcpy((void *dest), (const
|
|
||||||
void *src), __len); __ret; })
|
|
||||||
{
|
|
||||||
[memcpy implementation in decompress.c starts here]
|
|
||||||
int i;
|
|
||||||
const char *s = src;
|
|
||||||
char *d = dest;
|
|
||||||
|
|
||||||
for (i = 0; i < n; i++)
|
|
||||||
d[i] = s[i];
|
|
||||||
return dest;
|
|
||||||
}
|
|
||||||
|
|
||||||
raising the following compilation error:
|
|
||||||
arch/mips/boot/compressed/decompress.c:46:8: error: expected identifier or '('
|
|
||||||
before '{' token
|
|
||||||
|
|
||||||
There are at least three possibilities to fix this issue:
|
|
||||||
|
|
||||||
1) define _LINUX_STRING_H_ at the beginning of decompress.c to prevent
|
|
||||||
further linux/string.h definitions and declarations from being used, and add
|
|
||||||
an explicit strstr() declaration for linux/dynamic_debug.h
|
|
||||||
|
|
||||||
2) remove the inclusion of linux/kernel.h because we actually use no definition
|
|
||||||
or declaration from this header file
|
|
||||||
|
|
||||||
3) undefine memcpy or re-define memcpy to memcpy thus resulting in picking up
|
|
||||||
the local memcpy() implementation to this compilation unit
|
|
||||||
|
|
||||||
This patch uses the second option which is the less intrusive one.
|
|
||||||
|
|
||||||
Signed-off-by: Florian Fainelli <florian@openwrt.org>
|
|
||||||
---
|
|
||||||
arch/mips/boot/compressed/decompress.c | 2 --
|
|
||||||
1 file changed, 2 deletions(-)
|
|
||||||
|
|
||||||
--- a/arch/mips/boot/compressed/decompress.c
|
|
||||||
+++ b/arch/mips/boot/compressed/decompress.c
|
|
||||||
@@ -10,9 +10,7 @@
|
|
||||||
* Free Software Foundation; either version 2 of the License, or (at your
|
|
||||||
* option) any later version.
|
|
||||||
*/
|
|
||||||
-
|
|
||||||
#include <linux/types.h>
|
|
||||||
-#include <linux/kernel.h>
|
|
||||||
|
|
||||||
#include <asm/addrspace.h>
|
|
||||||
|
|
|
@ -1,27 +0,0 @@
|
||||||
From 031d8ad2c3cee85c515e551fc8c0054bdedb7b8b Mon Sep 17 00:00:00 2001
|
|
||||||
From: Florian Fainelli <florian@openwrt.org>
|
|
||||||
Date: Thu, 13 Dec 2012 18:02:11 +0100
|
|
||||||
Subject: [PATCH] x86: fix perf build with uclibc toolchains
|
|
||||||
|
|
||||||
libio.h is not provided by uClibc, in order to be able to test the
|
|
||||||
definition of __UCLIBC__ we need to include stdlib.h, which also
|
|
||||||
includes stddef.h, providing the definition of 'NULL'
|
|
||||||
|
|
||||||
Signed-off-by: Florian Fainelli <florian@openwrt.org>
|
|
||||||
---
|
|
||||||
tools/perf/arch/x86/util/dwarf-regs.c | 3 +++
|
|
||||||
1 file changed, 3 insertions(+)
|
|
||||||
|
|
||||||
--- a/tools/perf/arch/x86/util/dwarf-regs.c
|
|
||||||
+++ b/tools/perf/arch/x86/util/dwarf-regs.c
|
|
||||||
@@ -20,7 +20,10 @@
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
+#include <stdlib.h>
|
|
||||||
+#ifndef __UCLIBC__
|
|
||||||
#include <libio.h>
|
|
||||||
+#endif
|
|
||||||
#include <dwarf-regs.h>
|
|
||||||
|
|
||||||
/*
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,10 +0,0 @@
|
||||||
--- a/fs/overlayfs/super.c
|
|
||||||
+++ b/fs/overlayfs/super.c
|
|
||||||
@@ -385,7 +385,6 @@ struct dentry *ovl_lookup(struct inode *
|
|
||||||
|
|
||||||
struct file *ovl_path_open(struct path *path, int flags)
|
|
||||||
{
|
|
||||||
- path_get(path);
|
|
||||||
return dentry_open(path, flags, current_cred());
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,81 +0,0 @@
|
||||||
From 1e311820ec3055e3f08e687de6564692a7cec675 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Florian Fainelli <florian@openwrt.org>
|
|
||||||
Date: Mon, 28 Jan 2013 20:06:29 +0100
|
|
||||||
Subject: [PATCH 11/12] USB: EHCI: add ignore_oc flag to disable overcurrent
|
|
||||||
checking
|
|
||||||
|
|
||||||
This patch adds an ignore_oc flag which can be set by EHCI controller
|
|
||||||
not supporting or wanting to disable overcurrent checking. The EHCI
|
|
||||||
platform data in include/linux/usb/ehci_pdriver.h is also augmented to
|
|
||||||
take advantage of this new flag.
|
|
||||||
|
|
||||||
Signed-off-by: Florian Fainelli <florian@openwrt.org>
|
|
||||||
---
|
|
||||||
drivers/usb/host/ehci-hcd.c | 2 +-
|
|
||||||
drivers/usb/host/ehci-hub.c | 4 ++--
|
|
||||||
drivers/usb/host/ehci-platform.c | 1 +
|
|
||||||
drivers/usb/host/ehci.h | 1 +
|
|
||||||
include/linux/usb/ehci_pdriver.h | 1 +
|
|
||||||
5 files changed, 6 insertions(+), 3 deletions(-)
|
|
||||||
|
|
||||||
--- a/drivers/usb/host/ehci-hcd.c
|
|
||||||
+++ b/drivers/usb/host/ehci-hcd.c
|
|
||||||
@@ -631,7 +631,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
|
|
||||||
@@ -611,7 +611,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;
|
|
||||||
@@ -829,7 +829,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-platform.c
|
|
||||||
+++ b/drivers/usb/host/ehci-platform.c
|
|
||||||
@@ -44,6 +44,7 @@ static int ehci_platform_reset(struct us
|
|
||||||
ehci->has_synopsys_hc_bug = pdata->has_synopsys_hc_bug;
|
|
||||||
ehci->big_endian_desc = pdata->big_endian_desc;
|
|
||||||
ehci->big_endian_mmio = pdata->big_endian_mmio;
|
|
||||||
+ ehci->ignore_oc = pdata->ignore_oc;
|
|
||||||
|
|
||||||
ehci->caps = hcd->regs + pdata->caps_offset;
|
|
||||||
retval = ehci_setup(hcd);
|
|
||||||
--- a/drivers/usb/host/ehci.h
|
|
||||||
+++ b/drivers/usb/host/ehci.h
|
|
||||||
@@ -200,6 +200,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)
|
|
||||||
--- a/include/linux/usb/ehci_pdriver.h
|
|
||||||
+++ b/include/linux/usb/ehci_pdriver.h
|
|
||||||
@@ -42,6 +42,7 @@ struct usb_ehci_pdata {
|
|
||||||
unsigned big_endian_desc:1;
|
|
||||||
unsigned big_endian_mmio:1;
|
|
||||||
unsigned no_io_watchdog:1;
|
|
||||||
+ unsigned ignore_oc:1;
|
|
||||||
|
|
||||||
/* Turn on all power and clocks */
|
|
||||||
int (*power_on)(struct platform_device *pdev);
|
|
|
@ -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
|
|
||||||
@@ -167,7 +167,7 @@ else
|
|
||||||
# annotated or signed tagged state (as git describe only
|
|
||||||
# looks at signed or annotated tags - git tag -a/-s) and
|
|
||||||
# LOCALVERSION= is not specified
|
|
||||||
- if test "${LOCALVERSION+set}" != "set"; then
|
|
||||||
+ if test "${CONFIG_LOCALVERSION+set}" != "set"; then
|
|
||||||
scm=$(scm_version --short)
|
|
||||||
res="$res${scm:++}"
|
|
||||||
fi
|
|
|
@ -1,14 +0,0 @@
|
||||||
--- a/Makefile
|
|
||||||
+++ b/Makefile
|
|
||||||
@@ -570,9 +570,9 @@ endif # $(dot-config)
|
|
||||||
all: vmlinux
|
|
||||||
|
|
||||||
ifdef CONFIG_CC_OPTIMIZE_FOR_SIZE
|
|
||||||
-KBUILD_CFLAGS += -Os
|
|
||||||
+KBUILD_CFLAGS += -Os $(EXTRA_OPTIMIZATION)
|
|
||||||
else
|
|
||||||
-KBUILD_CFLAGS += -O2
|
|
||||||
+KBUILD_CFLAGS += -O2 -fno-reorder-blocks -fno-tree-ch $(EXTRA_OPTIMIZATION)
|
|
||||||
endif
|
|
||||||
|
|
||||||
include $(srctree)/arch/$(SRCARCH)/Makefile
|
|
|
@ -1,11 +0,0 @@
|
||||||
--- a/Makefile
|
|
||||||
+++ b/Makefile
|
|
||||||
@@ -379,7 +379,7 @@ KBUILD_CFLAGS_KERNEL :=
|
|
||||||
KBUILD_AFLAGS := -D__ASSEMBLY__
|
|
||||||
KBUILD_AFLAGS_MODULE := -DMODULE
|
|
||||||
KBUILD_CFLAGS_MODULE := -DMODULE
|
|
||||||
-KBUILD_LDFLAGS_MODULE := -T $(srctree)/scripts/module-common.lds
|
|
||||||
+KBUILD_LDFLAGS_MODULE = -T $(srctree)/scripts/module-common.lds $(if $(CONFIG_PROFILING),,-s)
|
|
||||||
|
|
||||||
# Read KERNELRELEASE from include/config/kernel.release (if it exists)
|
|
||||||
KERNELRELEASE = $(shell cat include/config/kernel.release 2> /dev/null)
|
|
|
@ -1,108 +0,0 @@
|
||||||
--- a/scripts/kallsyms.c
|
|
||||||
+++ b/scripts/kallsyms.c
|
|
||||||
@@ -54,6 +54,7 @@ static struct text_range text_ranges[] =
|
|
||||||
static struct sym_entry *table;
|
|
||||||
static unsigned int table_size, table_cnt;
|
|
||||||
static int all_symbols = 0;
|
|
||||||
+static int uncompressed = 0;
|
|
||||||
static char symbol_prefix_char = '\0';
|
|
||||||
|
|
||||||
int token_profit[0x10000];
|
|
||||||
@@ -360,6 +361,9 @@ static void write_src(void)
|
|
||||||
|
|
||||||
free(markers);
|
|
||||||
|
|
||||||
+ if (uncompressed)
|
|
||||||
+ return;
|
|
||||||
+
|
|
||||||
output_label("kallsyms_token_table");
|
|
||||||
off = 0;
|
|
||||||
for (i = 0; i < 256; i++) {
|
|
||||||
@@ -418,6 +422,9 @@ static void *find_token(unsigned char *s
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
|
|
||||||
+ if (uncompressed)
|
|
||||||
+ return NULL;
|
|
||||||
+
|
|
||||||
for (i = 0; i < len - 1; i++) {
|
|
||||||
if (str[i] == token[0] && str[i+1] == token[1])
|
|
||||||
return &str[i];
|
|
||||||
@@ -490,6 +497,9 @@ static void optimize_result(void)
|
|
||||||
{
|
|
||||||
int i, best;
|
|
||||||
|
|
||||||
+ if (uncompressed)
|
|
||||||
+ return;
|
|
||||||
+
|
|
||||||
/* using the '\0' symbol last allows compress_symbols to use standard
|
|
||||||
* fast string functions */
|
|
||||||
for (i = 255; i >= 0; i--) {
|
|
||||||
@@ -646,7 +656,9 @@ int main(int argc, char **argv)
|
|
||||||
if ((*p == '"' && *(p+2) == '"') || (*p == '\'' && *(p+2) == '\''))
|
|
||||||
p++;
|
|
||||||
symbol_prefix_char = *p;
|
|
||||||
- } else
|
|
||||||
+ } else if (strcmp(argv[i], "--uncompressed") == 0)
|
|
||||||
+ uncompressed = 1;
|
|
||||||
+ else
|
|
||||||
usage();
|
|
||||||
}
|
|
||||||
} else if (argc != 1)
|
|
||||||
--- a/init/Kconfig
|
|
||||||
+++ b/init/Kconfig
|
|
||||||
@@ -1257,6 +1257,17 @@ config KALLSYMS_ALL
|
|
||||||
|
|
||||||
Say N unless you really need all symbols.
|
|
||||||
|
|
||||||
+config KALLSYMS_UNCOMPRESSED
|
|
||||||
+ bool "Keep kallsyms uncompressed"
|
|
||||||
+ depends on KALLSYMS
|
|
||||||
+ help
|
|
||||||
+ Normally kallsyms contains compressed symbols (using a token table),
|
|
||||||
+ reducing the uncompressed kernel image size. Keeping the symbol table
|
|
||||||
+ uncompressed significantly improves the size of this part in compressed
|
|
||||||
+ kernel images.
|
|
||||||
+
|
|
||||||
+ Say N unless you need compressed kernel images to be small.
|
|
||||||
+
|
|
||||||
config HOTPLUG
|
|
||||||
def_bool y
|
|
||||||
|
|
||||||
--- a/scripts/link-vmlinux.sh
|
|
||||||
+++ b/scripts/link-vmlinux.sh
|
|
||||||
@@ -83,6 +83,10 @@ kallsyms()
|
|
||||||
kallsymopt="${kallsymopt} --all-symbols"
|
|
||||||
fi
|
|
||||||
|
|
||||||
+ if [ -n "${CONFIG_KALLSYMS_UNCOMPRESSED}" ]; then
|
|
||||||
+ kallsymopt="${kallsymopt} --uncompressed"
|
|
||||||
+ fi
|
|
||||||
+
|
|
||||||
local aflags="${KBUILD_AFLAGS} ${KBUILD_AFLAGS_KERNEL} \
|
|
||||||
${NOSTDINC_FLAGS} ${LINUXINCLUDE} ${KBUILD_CPPFLAGS}"
|
|
||||||
|
|
||||||
--- a/kernel/kallsyms.c
|
|
||||||
+++ b/kernel/kallsyms.c
|
|
||||||
@@ -106,6 +106,11 @@ static unsigned int kallsyms_expand_symb
|
|
||||||
* For every byte on the compressed symbol data, copy the table
|
|
||||||
* entry for that byte.
|
|
||||||
*/
|
|
||||||
+#ifdef CONFIG_KALLSYMS_UNCOMPRESSED
|
|
||||||
+ memcpy(result, data + 1, len - 1);
|
|
||||||
+ result += len - 1;
|
|
||||||
+ len = 0;
|
|
||||||
+#endif
|
|
||||||
while (len) {
|
|
||||||
tptr = &kallsyms_token_table[kallsyms_token_index[*data]];
|
|
||||||
data++;
|
|
||||||
@@ -133,6 +138,9 @@ static unsigned int kallsyms_expand_symb
|
|
||||||
*/
|
|
||||||
static char kallsyms_get_symbol_type(unsigned int off)
|
|
||||||
{
|
|
||||||
+#ifdef CONFIG_KALLSYMS_UNCOMPRESSED
|
|
||||||
+ return kallsyms_names[off + 1];
|
|
||||||
+#endif
|
|
||||||
/*
|
|
||||||
* Get just the first code, look it up in the token table,
|
|
||||||
* and return the first char from this token.
|
|
|
@ -1,200 +0,0 @@
|
||||||
From: Felix Fietkau <nbd@openwrt.org>
|
|
||||||
Subject: [PATCH] build: add a hack for removing non-essential module info
|
|
||||||
|
|
||||||
Signed-off-by: Felix Fietkau <nbd@openwrt.org>
|
|
||||||
---
|
|
||||||
--- a/include/linux/module.h
|
|
||||||
+++ b/include/linux/module.h
|
|
||||||
@@ -82,7 +82,7 @@ void sort_extable(struct exception_table
|
|
||||||
void sort_main_extable(void);
|
|
||||||
void trim_init_extable(struct module *m);
|
|
||||||
|
|
||||||
-#ifdef MODULE
|
|
||||||
+#if defined(MODULE) && !defined(CONFIG_MODULE_STRIPPED)
|
|
||||||
#define MODULE_GENERIC_TABLE(gtype,name) \
|
|
||||||
extern const struct gtype##_id __mod_##gtype##_table \
|
|
||||||
__attribute__ ((unused, alias(__stringify(name))))
|
|
||||||
@@ -93,9 +93,10 @@ extern const struct gtype##_id __mod_##g
|
|
||||||
|
|
||||||
/* Generic info of form tag = "info" */
|
|
||||||
#define MODULE_INFO(tag, info) __MODULE_INFO(tag, tag, info)
|
|
||||||
+#define MODULE_INFO_STRIP(tag, info) __MODULE_INFO_STRIP(tag, tag, info)
|
|
||||||
|
|
||||||
/* For userspace: you can also call me... */
|
|
||||||
-#define MODULE_ALIAS(_alias) MODULE_INFO(alias, _alias)
|
|
||||||
+#define MODULE_ALIAS(_alias) MODULE_INFO_STRIP(alias, _alias)
|
|
||||||
|
|
||||||
/*
|
|
||||||
* The following license idents are currently accepted as indicating free
|
|
||||||
@@ -131,10 +132,10 @@ extern const struct gtype##_id __mod_##g
|
|
||||||
* Author(s), use "Name <email>" or just "Name", for multiple
|
|
||||||
* authors use multiple MODULE_AUTHOR() statements/lines.
|
|
||||||
*/
|
|
||||||
-#define MODULE_AUTHOR(_author) MODULE_INFO(author, _author)
|
|
||||||
+#define MODULE_AUTHOR(_author) MODULE_INFO_STRIP(author, _author)
|
|
||||||
|
|
||||||
/* What your module does. */
|
|
||||||
-#define MODULE_DESCRIPTION(_description) MODULE_INFO(description, _description)
|
|
||||||
+#define MODULE_DESCRIPTION(_description) MODULE_INFO_STRIP(description, _description)
|
|
||||||
|
|
||||||
#define MODULE_DEVICE_TABLE(type,name) \
|
|
||||||
MODULE_GENERIC_TABLE(type##_device,name)
|
|
||||||
@@ -155,7 +156,9 @@ extern const struct gtype##_id __mod_##g
|
|
||||||
*/
|
|
||||||
|
|
||||||
#if defined(MODULE) || !defined(CONFIG_SYSFS)
|
|
||||||
-#define MODULE_VERSION(_version) MODULE_INFO(version, _version)
|
|
||||||
+#define MODULE_VERSION(_version) MODULE_INFO_STRIP(version, _version)
|
|
||||||
+#elif defined(CONFIG_MODULE_STRIPPED)
|
|
||||||
+#define MODULE_VERSION(_version) __MODULE_INFO_DISABLED(version)
|
|
||||||
#else
|
|
||||||
#define MODULE_VERSION(_version) \
|
|
||||||
static struct module_version_attribute ___modver_attr = { \
|
|
||||||
@@ -177,7 +180,7 @@ extern const struct gtype##_id __mod_##g
|
|
||||||
/* Optional firmware file (or files) needed by the module
|
|
||||||
* format is simply firmware file name. Multiple firmware
|
|
||||||
* files require multiple MODULE_FIRMWARE() specifiers */
|
|
||||||
-#define MODULE_FIRMWARE(_firmware) MODULE_INFO(firmware, _firmware)
|
|
||||||
+#define MODULE_FIRMWARE(_firmware) MODULE_INFO_STRIP(firmware, _firmware)
|
|
||||||
|
|
||||||
/* Given an address, look for it in the exception tables */
|
|
||||||
const struct exception_table_entry *search_exception_tables(unsigned long add);
|
|
||||||
--- a/include/linux/moduleparam.h
|
|
||||||
+++ b/include/linux/moduleparam.h
|
|
||||||
@@ -16,6 +16,16 @@
|
|
||||||
/* Chosen so that structs with an unsigned long line up. */
|
|
||||||
#define MAX_PARAM_PREFIX_LEN (64 - sizeof(unsigned long))
|
|
||||||
|
|
||||||
+/* This struct is here for syntactic coherency, it is not used */
|
|
||||||
+#define __MODULE_INFO_DISABLED(name) \
|
|
||||||
+ struct __UNIQUE_ID(name) {}
|
|
||||||
+
|
|
||||||
+#ifdef CONFIG_MODULE_STRIPPED
|
|
||||||
+#define __MODULE_INFO_STRIP(tag, name, info) __MODULE_INFO_DISABLED(name)
|
|
||||||
+#else
|
|
||||||
+#define __MODULE_INFO_STRIP(tag, name, info) __MODULE_INFO(tag, name, info)
|
|
||||||
+#endif
|
|
||||||
+
|
|
||||||
#ifdef MODULE
|
|
||||||
#define __MODULE_INFO(tag, name, info) \
|
|
||||||
static const char __UNIQUE_ID(name)[] \
|
|
||||||
@@ -23,8 +33,7 @@ static const char __UNIQUE_ID(name)[]
|
|
||||||
= __stringify(tag) "=" info
|
|
||||||
#else /* !MODULE */
|
|
||||||
/* This struct is here for syntactic coherency, it is not used */
|
|
||||||
-#define __MODULE_INFO(tag, name, info) \
|
|
||||||
- struct __UNIQUE_ID(name) {}
|
|
||||||
+#define __MODULE_INFO(tag, name, info) __MODULE_INFO_DISABLED(name)
|
|
||||||
#endif
|
|
||||||
#define __MODULE_PARM_TYPE(name, _type) \
|
|
||||||
__MODULE_INFO(parmtype, name##type, #name ":" _type)
|
|
||||||
@@ -32,7 +41,7 @@ static const char __UNIQUE_ID(name)[]
|
|
||||||
/* One for each parameter, describing how to use it. Some files do
|
|
||||||
multiple of these per line, so can't just use MODULE_INFO. */
|
|
||||||
#define MODULE_PARM_DESC(_parm, desc) \
|
|
||||||
- __MODULE_INFO(parm, _parm, #_parm ":" desc)
|
|
||||||
+ __MODULE_INFO_STRIP(parm, _parm, #_parm ":" desc)
|
|
||||||
|
|
||||||
struct kernel_param;
|
|
||||||
|
|
||||||
--- a/init/Kconfig
|
|
||||||
+++ b/init/Kconfig
|
|
||||||
@@ -1708,6 +1708,13 @@ config MODULE_SIG_SHA512
|
|
||||||
|
|
||||||
endchoice
|
|
||||||
|
|
||||||
+config MODULE_STRIPPED
|
|
||||||
+ bool "Reduce module size"
|
|
||||||
+ depends on MODULES
|
|
||||||
+ help
|
|
||||||
+ Remove module parameter descriptions, author info, version, aliases,
|
|
||||||
+ device tables, etc.
|
|
||||||
+
|
|
||||||
endif # MODULES
|
|
||||||
|
|
||||||
config INIT_ALL_POSSIBLE
|
|
||||||
--- a/kernel/module.c
|
|
||||||
+++ b/kernel/module.c
|
|
||||||
@@ -2682,6 +2682,7 @@ static struct module *setup_load_info(st
|
|
||||||
|
|
||||||
static int check_modinfo(struct module *mod, struct load_info *info, int flags)
|
|
||||||
{
|
|
||||||
+#ifndef CONFIG_MODULE_STRIPPED
|
|
||||||
const char *modmagic = get_modinfo(info, "vermagic");
|
|
||||||
int err;
|
|
||||||
|
|
||||||
@@ -2708,6 +2709,7 @@ static int check_modinfo(struct module *
|
|
||||||
" the quality is unknown, you have been warned.\n",
|
|
||||||
mod->name);
|
|
||||||
}
|
|
||||||
+#endif
|
|
||||||
|
|
||||||
/* Set up license info based on the info section */
|
|
||||||
set_license(mod, get_modinfo(info, "license"));
|
|
||||||
--- a/scripts/mod/modpost.c
|
|
||||||
+++ b/scripts/mod/modpost.c
|
|
||||||
@@ -1736,7 +1736,9 @@ static void read_symbols(char *modname)
|
|
||||||
symname = info.strtab + sym->st_name;
|
|
||||||
|
|
||||||
handle_modversions(mod, &info, sym, symname);
|
|
||||||
+#ifndef CONFIG_MODULE_STRIPPED
|
|
||||||
handle_moddevtable(mod, &info, sym, symname);
|
|
||||||
+#endif
|
|
||||||
}
|
|
||||||
if (!is_vmlinux(modname) ||
|
|
||||||
(is_vmlinux(modname) && vmlinux_section_warnings))
|
|
||||||
@@ -1859,7 +1861,9 @@ static void add_header(struct buffer *b,
|
|
||||||
buf_printf(b, "#include <linux/vermagic.h>\n");
|
|
||||||
buf_printf(b, "#include <linux/compiler.h>\n");
|
|
||||||
buf_printf(b, "\n");
|
|
||||||
+#ifndef CONFIG_MODULE_STRIPPED
|
|
||||||
buf_printf(b, "MODULE_INFO(vermagic, VERMAGIC_STRING);\n");
|
|
||||||
+#endif
|
|
||||||
buf_printf(b, "\n");
|
|
||||||
buf_printf(b, "struct module __this_module\n");
|
|
||||||
buf_printf(b, "__attribute__((section(\".gnu.linkonce.this_module\"))) = {\n");
|
|
||||||
@@ -1876,16 +1880,20 @@ static void add_header(struct buffer *b,
|
|
||||||
|
|
||||||
static void add_intree_flag(struct buffer *b, int is_intree)
|
|
||||||
{
|
|
||||||
+#ifndef CONFIG_MODULE_STRIPPED
|
|
||||||
if (is_intree)
|
|
||||||
buf_printf(b, "\nMODULE_INFO(intree, \"Y\");\n");
|
|
||||||
+#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
static void add_staging_flag(struct buffer *b, const char *name)
|
|
||||||
{
|
|
||||||
+#ifndef CONFIG_MODULE_STRIPPED
|
|
||||||
static const char *staging_dir = "drivers/staging";
|
|
||||||
|
|
||||||
if (strncmp(staging_dir, name, strlen(staging_dir)) == 0)
|
|
||||||
buf_printf(b, "\nMODULE_INFO(staging, \"Y\");\n");
|
|
||||||
+#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
@@ -1977,11 +1985,13 @@ static void add_depends(struct buffer *b
|
|
||||||
|
|
||||||
static void add_srcversion(struct buffer *b, struct module *mod)
|
|
||||||
{
|
|
||||||
+#ifndef CONFIG_MODULE_STRIPPED
|
|
||||||
if (mod->srcversion[0]) {
|
|
||||||
buf_printf(b, "\n");
|
|
||||||
buf_printf(b, "MODULE_INFO(srcversion, \"%s\");\n",
|
|
||||||
mod->srcversion);
|
|
||||||
}
|
|
||||||
+#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
static void write_if_changed(struct buffer *b, const char *fname)
|
|
||||||
@@ -2204,7 +2214,9 @@ int main(int argc, char **argv)
|
|
||||||
add_staging_flag(&buf, mod->name);
|
|
||||||
err |= add_versions(&buf, mod);
|
|
||||||
add_depends(&buf, mod, modules);
|
|
||||||
+#ifndef CONFIG_MODULE_STRIPPED
|
|
||||||
add_moddevtable(&buf, mod);
|
|
||||||
+#endif
|
|
||||||
add_srcversion(&buf, mod);
|
|
||||||
|
|
||||||
sprintf(fname, "%s.mod.c", mod->name);
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,53 +0,0 @@
|
||||||
--- a/tools/include/tools/be_byteshift.h
|
|
||||||
+++ b/tools/include/tools/be_byteshift.h
|
|
||||||
@@ -1,7 +1,11 @@
|
|
||||||
#ifndef _TOOLS_BE_BYTESHIFT_H
|
|
||||||
#define _TOOLS_BE_BYTESHIFT_H
|
|
||||||
|
|
||||||
+#ifdef __linux__
|
|
||||||
#include <linux/types.h>
|
|
||||||
+#else
|
|
||||||
+#include "linux_types.h"
|
|
||||||
+#endif
|
|
||||||
|
|
||||||
static inline __u16 __get_unaligned_be16(const __u8 *p)
|
|
||||||
{
|
|
||||||
--- a/tools/include/tools/le_byteshift.h
|
|
||||||
+++ b/tools/include/tools/le_byteshift.h
|
|
||||||
@@ -1,7 +1,11 @@
|
|
||||||
#ifndef _TOOLS_LE_BYTESHIFT_H
|
|
||||||
#define _TOOLS_LE_BYTESHIFT_H
|
|
||||||
|
|
||||||
+#ifdef __linux__
|
|
||||||
#include <linux/types.h>
|
|
||||||
+#else
|
|
||||||
+#include "linux_types.h"
|
|
||||||
+#endif
|
|
||||||
|
|
||||||
static inline __u16 __get_unaligned_le16(const __u8 *p)
|
|
||||||
{
|
|
||||||
--- /dev/null
|
|
||||||
+++ b/tools/include/tools/linux_types.h
|
|
||||||
@@ -0,0 +1,22 @@
|
|
||||||
+#ifndef __LINUX_TYPES_H
|
|
||||||
+#define __LINUX_TYPES_H
|
|
||||||
+
|
|
||||||
+#include <stdint.h>
|
|
||||||
+
|
|
||||||
+typedef uint8_t __u8;
|
|
||||||
+typedef uint8_t __be8;
|
|
||||||
+typedef uint8_t __le8;
|
|
||||||
+
|
|
||||||
+typedef uint16_t __u16;
|
|
||||||
+typedef uint16_t __be16;
|
|
||||||
+typedef uint16_t __le16;
|
|
||||||
+
|
|
||||||
+typedef uint32_t __u32;
|
|
||||||
+typedef uint32_t __be32;
|
|
||||||
+typedef uint32_t __le32;
|
|
||||||
+
|
|
||||||
+typedef uint64_t __u64;
|
|
||||||
+typedef uint64_t __be64;
|
|
||||||
+typedef uint64_t __le64;
|
|
||||||
+
|
|
||||||
+#endif
|
|
|
@ -1,483 +0,0 @@
|
||||||
--- a/arch/mips/Makefile
|
|
||||||
+++ b/arch/mips/Makefile
|
|
||||||
@@ -89,10 +89,14 @@ all-$(CONFIG_SYS_SUPPORTS_ZBOOT)+= vmlin
|
|
||||||
#
|
|
||||||
cflags-y += -G 0 -mno-abicalls -fno-pic -pipe
|
|
||||||
cflags-y += -msoft-float
|
|
||||||
-LDFLAGS_vmlinux += -G 0 -static -n -nostdlib
|
|
||||||
+LDFLAGS_vmlinux += -G 0 -static -n -nostdlib --gc-sections --sort-section=name
|
|
||||||
KBUILD_AFLAGS_MODULE += -mlong-calls
|
|
||||||
KBUILD_CFLAGS_MODULE += -mlong-calls
|
|
||||||
|
|
||||||
+ifndef CONFIG_FUNCTION_TRACER
|
|
||||||
+KBUILD_CFLAGS_KERNEL += -ffunction-sections -fdata-sections
|
|
||||||
+endif
|
|
||||||
+
|
|
||||||
cflags-y += -ffreestanding
|
|
||||||
|
|
||||||
#
|
|
||||||
--- a/arch/mips/kernel/vmlinux.lds.S
|
|
||||||
+++ b/arch/mips/kernel/vmlinux.lds.S
|
|
||||||
@@ -67,7 +67,7 @@ SECTIONS
|
|
||||||
/* Exception table for data bus errors */
|
|
||||||
__dbe_table : {
|
|
||||||
__start___dbe_table = .;
|
|
||||||
- *(__dbe_table)
|
|
||||||
+ KEEP(*(__dbe_table))
|
|
||||||
__stop___dbe_table = .;
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -112,7 +112,7 @@ SECTIONS
|
|
||||||
. = ALIGN(4);
|
|
||||||
.mips.machines.init : AT(ADDR(.mips.machines.init) - LOAD_OFFSET) {
|
|
||||||
__mips_machines_start = .;
|
|
||||||
- *(.mips.machines.init)
|
|
||||||
+ KEEP(*(.mips.machines.init))
|
|
||||||
__mips_machines_end = .;
|
|
||||||
}
|
|
||||||
|
|
||||||
--- a/include/asm-generic/vmlinux.lds.h
|
|
||||||
+++ b/include/asm-generic/vmlinux.lds.h
|
|
||||||
@@ -101,7 +101,7 @@
|
|
||||||
#ifdef CONFIG_FTRACE_MCOUNT_RECORD
|
|
||||||
#define MCOUNT_REC() . = ALIGN(8); \
|
|
||||||
VMLINUX_SYMBOL(__start_mcount_loc) = .; \
|
|
||||||
- *(__mcount_loc) \
|
|
||||||
+ KEEP(*(__mcount_loc)) \
|
|
||||||
VMLINUX_SYMBOL(__stop_mcount_loc) = .;
|
|
||||||
#else
|
|
||||||
#define MCOUNT_REC()
|
|
||||||
@@ -109,7 +109,7 @@
|
|
||||||
|
|
||||||
#ifdef CONFIG_TRACE_BRANCH_PROFILING
|
|
||||||
#define LIKELY_PROFILE() VMLINUX_SYMBOL(__start_annotated_branch_profile) = .; \
|
|
||||||
- *(_ftrace_annotated_branch) \
|
|
||||||
+ KEEP(*(_ftrace_annotated_branch)) \
|
|
||||||
VMLINUX_SYMBOL(__stop_annotated_branch_profile) = .;
|
|
||||||
#else
|
|
||||||
#define LIKELY_PROFILE()
|
|
||||||
@@ -117,7 +117,7 @@
|
|
||||||
|
|
||||||
#ifdef CONFIG_PROFILE_ALL_BRANCHES
|
|
||||||
#define BRANCH_PROFILE() VMLINUX_SYMBOL(__start_branch_profile) = .; \
|
|
||||||
- *(_ftrace_branch) \
|
|
||||||
+ KEEP(*(_ftrace_branch)) \
|
|
||||||
VMLINUX_SYMBOL(__stop_branch_profile) = .;
|
|
||||||
#else
|
|
||||||
#define BRANCH_PROFILE()
|
|
||||||
@@ -126,7 +126,7 @@
|
|
||||||
#ifdef CONFIG_EVENT_TRACING
|
|
||||||
#define FTRACE_EVENTS() . = ALIGN(8); \
|
|
||||||
VMLINUX_SYMBOL(__start_ftrace_events) = .; \
|
|
||||||
- *(_ftrace_events) \
|
|
||||||
+ KEEP(*(_ftrace_events)) \
|
|
||||||
VMLINUX_SYMBOL(__stop_ftrace_events) = .;
|
|
||||||
#else
|
|
||||||
#define FTRACE_EVENTS()
|
|
||||||
@@ -134,7 +134,7 @@
|
|
||||||
|
|
||||||
#ifdef CONFIG_TRACING
|
|
||||||
#define TRACE_PRINTKS() VMLINUX_SYMBOL(__start___trace_bprintk_fmt) = .; \
|
|
||||||
- *(__trace_printk_fmt) /* Trace_printk fmt' pointer */ \
|
|
||||||
+ KEEP(*(__trace_printk_fmt)) /* Trace_printk fmt' pointer */ \
|
|
||||||
VMLINUX_SYMBOL(__stop___trace_bprintk_fmt) = .;
|
|
||||||
#else
|
|
||||||
#define TRACE_PRINTKS()
|
|
||||||
@@ -143,7 +143,7 @@
|
|
||||||
#ifdef CONFIG_FTRACE_SYSCALLS
|
|
||||||
#define TRACE_SYSCALLS() . = ALIGN(8); \
|
|
||||||
VMLINUX_SYMBOL(__start_syscalls_metadata) = .; \
|
|
||||||
- *(__syscalls_metadata) \
|
|
||||||
+ KEEP(*(__syscalls_metadata)) \
|
|
||||||
VMLINUX_SYMBOL(__stop_syscalls_metadata) = .;
|
|
||||||
#else
|
|
||||||
#define TRACE_SYSCALLS()
|
|
||||||
@@ -153,7 +153,7 @@
|
|
||||||
#define KERNEL_DTB() \
|
|
||||||
STRUCT_ALIGN(); \
|
|
||||||
VMLINUX_SYMBOL(__dtb_start) = .; \
|
|
||||||
- *(.dtb.init.rodata) \
|
|
||||||
+ KEEP(*(.dtb.init.rodata)) \
|
|
||||||
VMLINUX_SYMBOL(__dtb_end) = .;
|
|
||||||
|
|
||||||
/* .data section */
|
|
||||||
@@ -173,15 +173,16 @@
|
|
||||||
/* implement dynamic printk debug */ \
|
|
||||||
. = ALIGN(8); \
|
|
||||||
VMLINUX_SYMBOL(__start___jump_table) = .; \
|
|
||||||
- *(__jump_table) \
|
|
||||||
+ KEEP(*(__jump_table)) \
|
|
||||||
VMLINUX_SYMBOL(__stop___jump_table) = .; \
|
|
||||||
. = ALIGN(8); \
|
|
||||||
VMLINUX_SYMBOL(__start___verbose) = .; \
|
|
||||||
- *(__verbose) \
|
|
||||||
+ KEEP(*(__verbose)) \
|
|
||||||
VMLINUX_SYMBOL(__stop___verbose) = .; \
|
|
||||||
LIKELY_PROFILE() \
|
|
||||||
BRANCH_PROFILE() \
|
|
||||||
- TRACE_PRINTKS()
|
|
||||||
+ TRACE_PRINTKS() \
|
|
||||||
+ *(.data.[a-zA-Z_]*)
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Data section helpers
|
|
||||||
@@ -235,39 +236,39 @@
|
|
||||||
/* PCI quirks */ \
|
|
||||||
.pci_fixup : AT(ADDR(.pci_fixup) - LOAD_OFFSET) { \
|
|
||||||
VMLINUX_SYMBOL(__start_pci_fixups_early) = .; \
|
|
||||||
- *(.pci_fixup_early) \
|
|
||||||
+ KEEP(*(.pci_fixup_early)) \
|
|
||||||
VMLINUX_SYMBOL(__end_pci_fixups_early) = .; \
|
|
||||||
VMLINUX_SYMBOL(__start_pci_fixups_header) = .; \
|
|
||||||
- *(.pci_fixup_header) \
|
|
||||||
+ KEEP(*(.pci_fixup_header)) \
|
|
||||||
VMLINUX_SYMBOL(__end_pci_fixups_header) = .; \
|
|
||||||
VMLINUX_SYMBOL(__start_pci_fixups_final) = .; \
|
|
||||||
- *(.pci_fixup_final) \
|
|
||||||
+ KEEP(*(.pci_fixup_final)) \
|
|
||||||
VMLINUX_SYMBOL(__end_pci_fixups_final) = .; \
|
|
||||||
VMLINUX_SYMBOL(__start_pci_fixups_enable) = .; \
|
|
||||||
- *(.pci_fixup_enable) \
|
|
||||||
+ KEEP(*(.pci_fixup_enable)) \
|
|
||||||
VMLINUX_SYMBOL(__end_pci_fixups_enable) = .; \
|
|
||||||
VMLINUX_SYMBOL(__start_pci_fixups_resume) = .; \
|
|
||||||
- *(.pci_fixup_resume) \
|
|
||||||
+ KEEP(*(.pci_fixup_resume)) \
|
|
||||||
VMLINUX_SYMBOL(__end_pci_fixups_resume) = .; \
|
|
||||||
VMLINUX_SYMBOL(__start_pci_fixups_resume_early) = .; \
|
|
||||||
- *(.pci_fixup_resume_early) \
|
|
||||||
+ KEEP(*(.pci_fixup_resume_early)) \
|
|
||||||
VMLINUX_SYMBOL(__end_pci_fixups_resume_early) = .; \
|
|
||||||
VMLINUX_SYMBOL(__start_pci_fixups_suspend) = .; \
|
|
||||||
- *(.pci_fixup_suspend) \
|
|
||||||
+ KEEP(*(.pci_fixup_suspend)) \
|
|
||||||
VMLINUX_SYMBOL(__end_pci_fixups_suspend) = .; \
|
|
||||||
} \
|
|
||||||
\
|
|
||||||
/* Built-in firmware blobs */ \
|
|
||||||
.builtin_fw : AT(ADDR(.builtin_fw) - LOAD_OFFSET) { \
|
|
||||||
VMLINUX_SYMBOL(__start_builtin_fw) = .; \
|
|
||||||
- *(.builtin_fw) \
|
|
||||||
+ KEEP(*(.builtin_fw)) \
|
|
||||||
VMLINUX_SYMBOL(__end_builtin_fw) = .; \
|
|
||||||
} \
|
|
||||||
\
|
|
||||||
/* RapidIO route ops */ \
|
|
||||||
.rio_ops : AT(ADDR(.rio_ops) - LOAD_OFFSET) { \
|
|
||||||
VMLINUX_SYMBOL(__start_rio_switch_ops) = .; \
|
|
||||||
- *(.rio_switch_ops) \
|
|
||||||
+ KEEP(*(.rio_switch_ops)) \
|
|
||||||
VMLINUX_SYMBOL(__end_rio_switch_ops) = .; \
|
|
||||||
} \
|
|
||||||
\
|
|
||||||
@@ -276,49 +277,49 @@
|
|
||||||
/* Kernel symbol table: Normal symbols */ \
|
|
||||||
__ksymtab : AT(ADDR(__ksymtab) - LOAD_OFFSET) { \
|
|
||||||
VMLINUX_SYMBOL(__start___ksymtab) = .; \
|
|
||||||
- *(SORT(___ksymtab+*)) \
|
|
||||||
+ KEEP(*(SORT(___ksymtab+*))) \
|
|
||||||
VMLINUX_SYMBOL(__stop___ksymtab) = .; \
|
|
||||||
} \
|
|
||||||
\
|
|
||||||
/* Kernel symbol table: GPL-only symbols */ \
|
|
||||||
__ksymtab_gpl : AT(ADDR(__ksymtab_gpl) - LOAD_OFFSET) { \
|
|
||||||
VMLINUX_SYMBOL(__start___ksymtab_gpl) = .; \
|
|
||||||
- *(SORT(___ksymtab_gpl+*)) \
|
|
||||||
+ KEEP(*(SORT(___ksymtab_gpl+*))) \
|
|
||||||
VMLINUX_SYMBOL(__stop___ksymtab_gpl) = .; \
|
|
||||||
} \
|
|
||||||
\
|
|
||||||
/* Kernel symbol table: Normal unused symbols */ \
|
|
||||||
__ksymtab_unused : AT(ADDR(__ksymtab_unused) - LOAD_OFFSET) { \
|
|
||||||
VMLINUX_SYMBOL(__start___ksymtab_unused) = .; \
|
|
||||||
- *(SORT(___ksymtab_unused+*)) \
|
|
||||||
+ KEEP(*(SORT(___ksymtab_unused+*))) \
|
|
||||||
VMLINUX_SYMBOL(__stop___ksymtab_unused) = .; \
|
|
||||||
} \
|
|
||||||
\
|
|
||||||
/* Kernel symbol table: GPL-only unused symbols */ \
|
|
||||||
__ksymtab_unused_gpl : AT(ADDR(__ksymtab_unused_gpl) - LOAD_OFFSET) { \
|
|
||||||
VMLINUX_SYMBOL(__start___ksymtab_unused_gpl) = .; \
|
|
||||||
- *(SORT(___ksymtab_unused_gpl+*)) \
|
|
||||||
+ KEEP(*(SORT(___ksymtab_unused_gpl+*))) \
|
|
||||||
VMLINUX_SYMBOL(__stop___ksymtab_unused_gpl) = .; \
|
|
||||||
} \
|
|
||||||
\
|
|
||||||
/* Kernel symbol table: GPL-future-only symbols */ \
|
|
||||||
__ksymtab_gpl_future : AT(ADDR(__ksymtab_gpl_future) - LOAD_OFFSET) { \
|
|
||||||
VMLINUX_SYMBOL(__start___ksymtab_gpl_future) = .; \
|
|
||||||
- *(SORT(___ksymtab_gpl_future+*)) \
|
|
||||||
+ KEEP(*(SORT(___ksymtab_gpl_future+*))) \
|
|
||||||
VMLINUX_SYMBOL(__stop___ksymtab_gpl_future) = .; \
|
|
||||||
} \
|
|
||||||
\
|
|
||||||
/* Kernel symbol table: Normal symbols */ \
|
|
||||||
__kcrctab : AT(ADDR(__kcrctab) - LOAD_OFFSET) { \
|
|
||||||
VMLINUX_SYMBOL(__start___kcrctab) = .; \
|
|
||||||
- *(SORT(___kcrctab+*)) \
|
|
||||||
+ KEEP(*(SORT(___kcrctab+*))) \
|
|
||||||
VMLINUX_SYMBOL(__stop___kcrctab) = .; \
|
|
||||||
} \
|
|
||||||
\
|
|
||||||
/* Kernel symbol table: GPL-only symbols */ \
|
|
||||||
__kcrctab_gpl : AT(ADDR(__kcrctab_gpl) - LOAD_OFFSET) { \
|
|
||||||
VMLINUX_SYMBOL(__start___kcrctab_gpl) = .; \
|
|
||||||
- *(SORT(___kcrctab_gpl+*)) \
|
|
||||||
+ KEEP(*(SORT(___kcrctab_gpl+*))) \
|
|
||||||
VMLINUX_SYMBOL(__stop___kcrctab_gpl) = .; \
|
|
||||||
} \
|
|
||||||
\
|
|
||||||
@@ -332,14 +333,14 @@
|
|
||||||
/* Kernel symbol table: GPL-only unused symbols */ \
|
|
||||||
__kcrctab_unused_gpl : AT(ADDR(__kcrctab_unused_gpl) - LOAD_OFFSET) { \
|
|
||||||
VMLINUX_SYMBOL(__start___kcrctab_unused_gpl) = .; \
|
|
||||||
- *(SORT(___kcrctab_unused_gpl+*)) \
|
|
||||||
+ KEEP(*(SORT(___kcrctab_unused_gpl+*))) \
|
|
||||||
VMLINUX_SYMBOL(__stop___kcrctab_unused_gpl) = .; \
|
|
||||||
} \
|
|
||||||
\
|
|
||||||
/* Kernel symbol table: GPL-future-only symbols */ \
|
|
||||||
__kcrctab_gpl_future : AT(ADDR(__kcrctab_gpl_future) - LOAD_OFFSET) { \
|
|
||||||
VMLINUX_SYMBOL(__start___kcrctab_gpl_future) = .; \
|
|
||||||
- *(SORT(___kcrctab_gpl_future+*)) \
|
|
||||||
+ KEEP(*(SORT(___kcrctab_gpl_future+*))) \
|
|
||||||
VMLINUX_SYMBOL(__stop___kcrctab_gpl_future) = .; \
|
|
||||||
} \
|
|
||||||
\
|
|
||||||
@@ -362,14 +363,14 @@
|
|
||||||
/* Built-in module parameters. */ \
|
|
||||||
__param : AT(ADDR(__param) - LOAD_OFFSET) { \
|
|
||||||
VMLINUX_SYMBOL(__start___param) = .; \
|
|
||||||
- *(__param) \
|
|
||||||
+ KEEP(*(__param)) \
|
|
||||||
VMLINUX_SYMBOL(__stop___param) = .; \
|
|
||||||
} \
|
|
||||||
\
|
|
||||||
/* Built-in module versions. */ \
|
|
||||||
__modver : AT(ADDR(__modver) - LOAD_OFFSET) { \
|
|
||||||
VMLINUX_SYMBOL(__start___modver) = .; \
|
|
||||||
- *(__modver) \
|
|
||||||
+ KEEP(*(__modver)) \
|
|
||||||
VMLINUX_SYMBOL(__stop___modver) = .; \
|
|
||||||
. = ALIGN((align)); \
|
|
||||||
VMLINUX_SYMBOL(__end_rodata) = .; \
|
|
||||||
@@ -429,7 +430,7 @@
|
|
||||||
#define ENTRY_TEXT \
|
|
||||||
ALIGN_FUNCTION(); \
|
|
||||||
VMLINUX_SYMBOL(__entry_text_start) = .; \
|
|
||||||
- *(.entry.text) \
|
|
||||||
+ KEEP(*(.entry.text)) \
|
|
||||||
VMLINUX_SYMBOL(__entry_text_end) = .;
|
|
||||||
|
|
||||||
#ifdef CONFIG_FUNCTION_GRAPH_TRACER
|
|
||||||
@@ -457,7 +458,7 @@
|
|
||||||
. = ALIGN(align); \
|
|
||||||
__ex_table : AT(ADDR(__ex_table) - LOAD_OFFSET) { \
|
|
||||||
VMLINUX_SYMBOL(__start___ex_table) = .; \
|
|
||||||
- *(__ex_table) \
|
|
||||||
+ KEEP(*(__ex_table)) \
|
|
||||||
VMLINUX_SYMBOL(__stop___ex_table) = .; \
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -473,7 +474,7 @@
|
|
||||||
#ifdef CONFIG_CONSTRUCTORS
|
|
||||||
#define KERNEL_CTORS() . = ALIGN(8); \
|
|
||||||
VMLINUX_SYMBOL(__ctors_start) = .; \
|
|
||||||
- *(.ctors) \
|
|
||||||
+ KEEP(*(.ctors)) \
|
|
||||||
VMLINUX_SYMBOL(__ctors_end) = .;
|
|
||||||
#else
|
|
||||||
#define KERNEL_CTORS()
|
|
||||||
@@ -526,7 +527,7 @@
|
|
||||||
#define SBSS(sbss_align) \
|
|
||||||
. = ALIGN(sbss_align); \
|
|
||||||
.sbss : AT(ADDR(.sbss) - LOAD_OFFSET) { \
|
|
||||||
- *(.sbss) \
|
|
||||||
+ *(.sbss .sbss.*) \
|
|
||||||
*(.scommon) \
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -544,7 +545,7 @@
|
|
||||||
BSS_FIRST_SECTIONS \
|
|
||||||
*(.bss..page_aligned) \
|
|
||||||
*(.dynbss) \
|
|
||||||
- *(.bss) \
|
|
||||||
+ *(.bss .bss.*) \
|
|
||||||
*(COMMON) \
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -593,7 +594,7 @@
|
|
||||||
. = ALIGN(8); \
|
|
||||||
__bug_table : AT(ADDR(__bug_table) - LOAD_OFFSET) { \
|
|
||||||
VMLINUX_SYMBOL(__start___bug_table) = .; \
|
|
||||||
- *(__bug_table) \
|
|
||||||
+ KEEP(*(__bug_table)) \
|
|
||||||
VMLINUX_SYMBOL(__stop___bug_table) = .; \
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
@@ -605,7 +606,7 @@
|
|
||||||
. = ALIGN(4); \
|
|
||||||
.tracedata : AT(ADDR(.tracedata) - LOAD_OFFSET) { \
|
|
||||||
VMLINUX_SYMBOL(__tracedata_start) = .; \
|
|
||||||
- *(.tracedata) \
|
|
||||||
+ KEEP(*(.tracedata)) \
|
|
||||||
VMLINUX_SYMBOL(__tracedata_end) = .; \
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
@@ -622,17 +623,17 @@
|
|
||||||
#define INIT_SETUP(initsetup_align) \
|
|
||||||
. = ALIGN(initsetup_align); \
|
|
||||||
VMLINUX_SYMBOL(__setup_start) = .; \
|
|
||||||
- *(.init.setup) \
|
|
||||||
+ KEEP(*(.init.setup)) \
|
|
||||||
VMLINUX_SYMBOL(__setup_end) = .;
|
|
||||||
|
|
||||||
#define INIT_CALLS_LEVEL(level) \
|
|
||||||
VMLINUX_SYMBOL(__initcall##level##_start) = .; \
|
|
||||||
- *(.initcall##level##.init) \
|
|
||||||
- *(.initcall##level##s.init) \
|
|
||||||
+ KEEP(*(.initcall##level##.init)) \
|
|
||||||
+ KEEP(*(.initcall##level##s.init)) \
|
|
||||||
|
|
||||||
#define INIT_CALLS \
|
|
||||||
VMLINUX_SYMBOL(__initcall_start) = .; \
|
|
||||||
- *(.initcallearly.init) \
|
|
||||||
+ KEEP(*(.initcallearly.init)) \
|
|
||||||
INIT_CALLS_LEVEL(0) \
|
|
||||||
INIT_CALLS_LEVEL(1) \
|
|
||||||
INIT_CALLS_LEVEL(2) \
|
|
||||||
@@ -646,21 +647,21 @@
|
|
||||||
|
|
||||||
#define CON_INITCALL \
|
|
||||||
VMLINUX_SYMBOL(__con_initcall_start) = .; \
|
|
||||||
- *(.con_initcall.init) \
|
|
||||||
+ KEEP(*(.con_initcall.init)) \
|
|
||||||
VMLINUX_SYMBOL(__con_initcall_end) = .;
|
|
||||||
|
|
||||||
#define SECURITY_INITCALL \
|
|
||||||
VMLINUX_SYMBOL(__security_initcall_start) = .; \
|
|
||||||
- *(.security_initcall.init) \
|
|
||||||
+ KEEP(*(.security_initcall.init)) \
|
|
||||||
VMLINUX_SYMBOL(__security_initcall_end) = .;
|
|
||||||
|
|
||||||
#ifdef CONFIG_BLK_DEV_INITRD
|
|
||||||
#define INIT_RAM_FS \
|
|
||||||
. = ALIGN(4); \
|
|
||||||
VMLINUX_SYMBOL(__initramfs_start) = .; \
|
|
||||||
- *(.init.ramfs) \
|
|
||||||
+ KEEP(*(.init.ramfs)) \
|
|
||||||
. = ALIGN(8); \
|
|
||||||
- *(.init.ramfs.info)
|
|
||||||
+ KEEP(*(.init.ramfs.info))
|
|
||||||
#else
|
|
||||||
#define INIT_RAM_FS
|
|
||||||
#endif
|
|
||||||
--- a/arch/arm/Makefile
|
|
||||||
+++ b/arch/arm/Makefile
|
|
||||||
@@ -17,11 +17,16 @@ LDFLAGS_vmlinux :=-p --no-undefined -X
|
|
||||||
ifeq ($(CONFIG_CPU_ENDIAN_BE8),y)
|
|
||||||
LDFLAGS_vmlinux += --be8
|
|
||||||
endif
|
|
||||||
+LDFLAGS_vmlinux += --gc-sections --sort-section=name
|
|
||||||
|
|
||||||
OBJCOPYFLAGS :=-O binary -R .comment -S
|
|
||||||
GZFLAGS :=-9
|
|
||||||
#KBUILD_CFLAGS +=-pipe
|
|
||||||
|
|
||||||
+ifndef CONFIG_FUNCTION_TRACER
|
|
||||||
+KBUILD_CFLAGS_KERNEL += -ffunction-sections -fdata-sections
|
|
||||||
+endif
|
|
||||||
+
|
|
||||||
# Never generate .eh_frame
|
|
||||||
KBUILD_CFLAGS += $(call cc-option,-fno-dwarf2-cfi-asm)
|
|
||||||
|
|
||||||
--- a/arch/arm/kernel/vmlinux.lds.S
|
|
||||||
+++ b/arch/arm/kernel/vmlinux.lds.S
|
|
||||||
@@ -12,13 +12,13 @@
|
|
||||||
#define PROC_INFO \
|
|
||||||
. = ALIGN(4); \
|
|
||||||
VMLINUX_SYMBOL(__proc_info_begin) = .; \
|
|
||||||
- *(.proc.info.init) \
|
|
||||||
+ KEEP(*(.proc.info.init)) \
|
|
||||||
VMLINUX_SYMBOL(__proc_info_end) = .;
|
|
||||||
|
|
||||||
#define IDMAP_TEXT \
|
|
||||||
ALIGN_FUNCTION(); \
|
|
||||||
VMLINUX_SYMBOL(__idmap_text_start) = .; \
|
|
||||||
- *(.idmap.text) \
|
|
||||||
+ KEEP(*(.idmap.text)) \
|
|
||||||
VMLINUX_SYMBOL(__idmap_text_end) = .;
|
|
||||||
|
|
||||||
#ifdef CONFIG_HOTPLUG_CPU
|
|
||||||
@@ -93,7 +93,7 @@ SECTIONS
|
|
||||||
.text : { /* Real text segment */
|
|
||||||
_stext = .; /* Text and read-only data */
|
|
||||||
__exception_text_start = .;
|
|
||||||
- *(.exception.text)
|
|
||||||
+ KEEP(*(.exception.text))
|
|
||||||
__exception_text_end = .;
|
|
||||||
IRQENTRY_TEXT
|
|
||||||
TEXT_TEXT
|
|
||||||
@@ -118,7 +118,7 @@ SECTIONS
|
|
||||||
__ex_table : AT(ADDR(__ex_table) - LOAD_OFFSET) {
|
|
||||||
__start___ex_table = .;
|
|
||||||
#ifdef CONFIG_MMU
|
|
||||||
- *(__ex_table)
|
|
||||||
+ KEEP(*(__ex_table))
|
|
||||||
#endif
|
|
||||||
__stop___ex_table = .;
|
|
||||||
}
|
|
||||||
@@ -130,12 +130,12 @@ SECTIONS
|
|
||||||
. = ALIGN(8);
|
|
||||||
.ARM.unwind_idx : {
|
|
||||||
__start_unwind_idx = .;
|
|
||||||
- *(.ARM.exidx*)
|
|
||||||
+ KEEP(*(.ARM.exidx*))
|
|
||||||
__stop_unwind_idx = .;
|
|
||||||
}
|
|
||||||
.ARM.unwind_tab : {
|
|
||||||
__start_unwind_tab = .;
|
|
||||||
- *(.ARM.extab*)
|
|
||||||
+ KEEP(*(.ARM.extab*))
|
|
||||||
__stop_unwind_tab = .;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
@@ -158,24 +158,24 @@ SECTIONS
|
|
||||||
}
|
|
||||||
.init.arch.info : {
|
|
||||||
__arch_info_begin = .;
|
|
||||||
- *(.arch.info.init)
|
|
||||||
+ KEEP(*(.arch.info.init))
|
|
||||||
__arch_info_end = .;
|
|
||||||
}
|
|
||||||
.init.tagtable : {
|
|
||||||
__tagtable_begin = .;
|
|
||||||
- *(.taglist.init)
|
|
||||||
+ KEEP(*(.taglist.init))
|
|
||||||
__tagtable_end = .;
|
|
||||||
}
|
|
||||||
#ifdef CONFIG_SMP_ON_UP
|
|
||||||
.init.smpalt : {
|
|
||||||
__smpalt_begin = .;
|
|
||||||
- *(.alt.smp.init)
|
|
||||||
+ KEEP(*(.alt.smp.init))
|
|
||||||
__smpalt_end = .;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
.init.pv_table : {
|
|
||||||
__pv_table_begin = .;
|
|
||||||
- *(.pv_table)
|
|
||||||
+ KEEP(*(.pv_table))
|
|
||||||
__pv_table_end = .;
|
|
||||||
}
|
|
||||||
.init.data : {
|
|
||||||
--- a/arch/arm/boot/compressed/Makefile
|
|
||||||
+++ b/arch/arm/boot/compressed/Makefile
|
|
||||||
@@ -119,6 +119,7 @@ ifeq ($(CONFIG_FUNCTION_TRACER),y)
|
|
||||||
ORIG_CFLAGS := $(KBUILD_CFLAGS)
|
|
||||||
KBUILD_CFLAGS = $(subst -pg, , $(ORIG_CFLAGS))
|
|
||||||
endif
|
|
||||||
+KBUILD_CFLAGS_KERNEL := $(patsubst -f%-sections,,$(KBUILD_CFLAGS_KERNEL))
|
|
||||||
|
|
||||||
ccflags-y := -fpic -fno-builtin -I$(obj)
|
|
||||||
asflags-y := -Wa,-march=all -DZIMAGE
|
|
|
@ -1,88 +0,0 @@
|
||||||
--- a/include/asm-generic/vmlinux.lds.h
|
|
||||||
+++ b/include/asm-generic/vmlinux.lds.h
|
|
||||||
@@ -52,6 +52,16 @@
|
|
||||||
#define LOAD_OFFSET 0
|
|
||||||
#endif
|
|
||||||
|
|
||||||
+#ifndef SYMTAB_KEEP
|
|
||||||
+#define SYMTAB_KEEP KEEP(*(SORT(___ksymtab+*)))
|
|
||||||
+#define SYMTAB_KEEP_GPL KEEP(*(SORT(___ksymtab_gpl+*)))
|
|
||||||
+#endif
|
|
||||||
+
|
|
||||||
+#ifndef SYMTAB_DISCARD
|
|
||||||
+#define SYMTAB_DISCARD
|
|
||||||
+#define SYMTAB_DISCARD_GPL
|
|
||||||
+#endif
|
|
||||||
+
|
|
||||||
#ifndef SYMBOL_PREFIX
|
|
||||||
#define VMLINUX_SYMBOL(sym) sym
|
|
||||||
#else
|
|
||||||
@@ -277,14 +287,14 @@
|
|
||||||
/* Kernel symbol table: Normal symbols */ \
|
|
||||||
__ksymtab : AT(ADDR(__ksymtab) - LOAD_OFFSET) { \
|
|
||||||
VMLINUX_SYMBOL(__start___ksymtab) = .; \
|
|
||||||
- KEEP(*(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) = .; \
|
|
||||||
- KEEP(*(SORT(___ksymtab_gpl+*))) \
|
|
||||||
+ SYMTAB_KEEP_GPL \
|
|
||||||
VMLINUX_SYMBOL(__stop___ksymtab_gpl) = .; \
|
|
||||||
} \
|
|
||||||
\
|
|
||||||
@@ -346,7 +356,7 @@
|
|
||||||
\
|
|
||||||
/* Kernel symbol table: strings */ \
|
|
||||||
__ksymtab_strings : AT(ADDR(__ksymtab_strings) - LOAD_OFFSET) { \
|
|
||||||
- *(__ksymtab_strings) \
|
|
||||||
+ *(__ksymtab_strings+*) \
|
|
||||||
} \
|
|
||||||
\
|
|
||||||
/* __*init sections */ \
|
|
||||||
@@ -680,6 +690,8 @@
|
|
||||||
EXIT_TEXT \
|
|
||||||
EXIT_DATA \
|
|
||||||
EXIT_CALL \
|
|
||||||
+ SYMTAB_DISCARD \
|
|
||||||
+ SYMTAB_DISCARD_GPL \
|
|
||||||
*(.discard) \
|
|
||||||
*(.discard.*) \
|
|
||||||
}
|
|
||||||
--- a/scripts/Makefile.build
|
|
||||||
+++ b/scripts/Makefile.build
|
|
||||||
@@ -348,7 +348,7 @@ targets += $(extra-y) $(MAKECMDGOALS) $(
|
|
||||||
# Linker scripts preprocessor (.lds.S -> .lds)
|
|
||||||
# ---------------------------------------------------------------------------
|
|
||||||
quiet_cmd_cpp_lds_S = LDS $@
|
|
||||||
- cmd_cpp_lds_S = $(CPP) $(cpp_flags) -P -C -U$(ARCH) \
|
|
||||||
+ cmd_cpp_lds_S = $(CPP) $(EXTRA_LDSFLAGS) $(cpp_flags) -P -C -U$(ARCH) \
|
|
||||||
-D__ASSEMBLY__ -DLINKER_SCRIPT -o $@ $<
|
|
||||||
|
|
||||||
$(obj)/%.lds: $(src)/%.lds.S FORCE
|
|
||||||
--- a/include/linux/export.h
|
|
||||||
+++ b/include/linux/export.h
|
|
||||||
@@ -45,12 +45,19 @@ extern struct module __this_module;
|
|
||||||
#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
|
|
||||||
@@ -299,7 +299,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
|
|
||||||
@@ -43,6 +43,7 @@ static const struct compress_format comp
|
|
||||||
{ {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
|
|
||||||
@@ -191,7 +191,6 @@ config NF_CONNTRACK_FTP
|
|
||||||
|
|
||||||
config NF_CONNTRACK_H323
|
|
||||||
tristate "H.323 protocol support"
|
|
||||||
- depends on (IPV6 || IPV6=n)
|
|
||||||
depends on NETFILTER_ADVANCED
|
|
||||||
help
|
|
||||||
H.323 is a VoIP signalling protocol from ITU-T. As one of the most
|
|
||||||
@@ -757,7 +756,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,18 +0,0 @@
|
||||||
--- a/sound/core/Kconfig
|
|
||||||
+++ b/sound/core/Kconfig
|
|
||||||
@@ -7,13 +7,13 @@ config SND_PCM
|
|
||||||
select SND_TIMER
|
|
||||||
|
|
||||||
config SND_HWDEP
|
|
||||||
- tristate
|
|
||||||
+ tristate "Sound hardware support"
|
|
||||||
|
|
||||||
config SND_RAWMIDI
|
|
||||||
tristate
|
|
||||||
|
|
||||||
config SND_COMPRESS_OFFLOAD
|
|
||||||
- tristate
|
|
||||||
+ tristate "Compression offloading support"
|
|
||||||
|
|
||||||
# To be effective this also requires INPUT - users should say:
|
|
||||||
# select SND_JACK if INPUT=y || INPUT=SND
|
|
|
@ -1,10 +0,0 @@
|
||||||
--- a/drivers/crypto/Kconfig
|
|
||||||
+++ b/drivers/crypto/Kconfig
|
|
||||||
@@ -164,6 +164,7 @@ config CRYPTO_DEV_MV_CESA
|
|
||||||
depends on PLAT_ORION
|
|
||||||
select CRYPTO_ALGAPI
|
|
||||||
select CRYPTO_AES
|
|
||||||
+ select CRYPTO_HASH2
|
|
||||||
select CRYPTO_BLKCIPHER2
|
|
||||||
select CRYPTO_HASH
|
|
||||||
help
|
|
|
@ -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
|
|
||||||
@@ -280,16 +280,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
|
|
||||||
@@ -149,13 +149,13 @@ config LIB80211
|
|
||||||
Drivers should select this themselves if needed.
|
|
||||||
|
|
||||||
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_ACCT
|
|
||||||
tristate "Netfilter NFACCT over NFNETLINK interface"
|
|
|
@ -1,72 +0,0 @@
|
||||||
--- a/drivers/base/regmap/Kconfig
|
|
||||||
+++ b/drivers/base/regmap/Kconfig
|
|
||||||
@@ -3,20 +3,24 @@
|
|
||||||
# subsystems should select the appropriate symbols.
|
|
||||||
|
|
||||||
config REGMAP
|
|
||||||
- default y if (REGMAP_I2C || REGMAP_SPI || REGMAP_MMIO || REGMAP_IRQ)
|
|
||||||
select LZO_COMPRESS
|
|
||||||
select LZO_DECOMPRESS
|
|
||||||
select IRQ_DOMAIN if REGMAP_IRQ
|
|
||||||
- bool
|
|
||||||
+ tristate "Regmap"
|
|
||||||
|
|
||||||
config REGMAP_I2C
|
|
||||||
- tristate
|
|
||||||
+ select REGMAP
|
|
||||||
+ tristate "Regmap I2C"
|
|
||||||
|
|
||||||
config REGMAP_SPI
|
|
||||||
- tristate
|
|
||||||
+ select REGMAP
|
|
||||||
+ depends on SPI_MASTER
|
|
||||||
+ tristate "Regmap SPI"
|
|
||||||
|
|
||||||
config REGMAP_MMIO
|
|
||||||
+ select REGMAP
|
|
||||||
tristate
|
|
||||||
|
|
||||||
config REGMAP_IRQ
|
|
||||||
+ select REGMAP
|
|
||||||
bool
|
|
||||||
--- a/include/linux/regmap.h
|
|
||||||
+++ b/include/linux/regmap.h
|
|
||||||
@@ -44,7 +44,7 @@ struct reg_default {
|
|
||||||
unsigned int def;
|
|
||||||
};
|
|
||||||
|
|
||||||
-#ifdef CONFIG_REGMAP
|
|
||||||
+#if IS_ENABLED(CONFIG_REGMAP)
|
|
||||||
|
|
||||||
enum regmap_endian {
|
|
||||||
/* Unspecified -> 0 -> Backwards compatible default */
|
|
||||||
--- a/drivers/base/regmap/Makefile
|
|
||||||
+++ b/drivers/base/regmap/Makefile
|
|
||||||
@@ -1,6 +1,8 @@
|
|
||||||
-obj-$(CONFIG_REGMAP) += regmap.o regcache.o
|
|
||||||
-obj-$(CONFIG_REGMAP) += regcache-rbtree.o regcache-lzo.o
|
|
||||||
-obj-$(CONFIG_DEBUG_FS) += regmap-debugfs.o
|
|
||||||
+regmap-core-objs = regmap.o regcache.o regcache-rbtree.o regcache-lzo.o
|
|
||||||
+ifdef CONFIG_DEBUG_FS
|
|
||||||
+regmap-core-objs += regmap-debugfs.o
|
|
||||||
+endif
|
|
||||||
+obj-$(CONFIG_REGMAP) += regmap-core.o
|
|
||||||
obj-$(CONFIG_REGMAP_I2C) += regmap-i2c.o
|
|
||||||
obj-$(CONFIG_REGMAP_SPI) += regmap-spi.o
|
|
||||||
obj-$(CONFIG_REGMAP_MMIO) += regmap-mmio.o
|
|
||||||
--- a/drivers/base/regmap/regmap.c
|
|
||||||
+++ b/drivers/base/regmap/regmap.c
|
|
||||||
@@ -13,6 +13,7 @@
|
|
||||||
#include <linux/device.h>
|
|
||||||
#include <linux/slab.h>
|
|
||||||
#include <linux/export.h>
|
|
||||||
+#include <linux/module.h>
|
|
||||||
#include <linux/mutex.h>
|
|
||||||
#include <linux/err.h>
|
|
||||||
#include <linux/rbtree.h>
|
|
||||||
@@ -1530,3 +1531,5 @@ static int __init regmap_initcall(void)
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
postcore_initcall(regmap_initcall);
|
|
||||||
+
|
|
||||||
+MODULE_LICENSE("GPL");
|
|
|
@ -1,37 +0,0 @@
|
||||||
--- a/crypto/Kconfig
|
|
||||||
+++ b/crypto/Kconfig
|
|
||||||
@@ -95,10 +95,10 @@ config CRYPTO_MANAGER
|
|
||||||
|
|
||||||
config CRYPTO_MANAGER2
|
|
||||||
def_tristate CRYPTO_MANAGER || (CRYPTO_MANAGER!=n && CRYPTO_ALGAPI=y)
|
|
||||||
- select CRYPTO_AEAD2
|
|
||||||
- select CRYPTO_HASH2
|
|
||||||
- select CRYPTO_BLKCIPHER2
|
|
||||||
- select CRYPTO_PCOMP2
|
|
||||||
+ select CRYPTO_AEAD2 if !CRYPTO_MANAGER_DISABLE_TESTS
|
|
||||||
+ select CRYPTO_HASH2 if !CRYPTO_MANAGER_DISABLE_TESTS
|
|
||||||
+ select CRYPTO_BLKCIPHER2 if !CRYPTO_MANAGER_DISABLE_TESTS
|
|
||||||
+ select CRYPTO_PCOMP2 if !CRYPTO_MANAGER_DISABLE_TESTS
|
|
||||||
|
|
||||||
config CRYPTO_USER
|
|
||||||
tristate "Userspace cryptographic algorithm configuration"
|
|
||||||
--- a/crypto/algboss.c
|
|
||||||
+++ b/crypto/algboss.c
|
|
||||||
@@ -247,6 +247,9 @@ static int cryptomgr_schedule_test(struc
|
|
||||||
type = alg->cra_flags;
|
|
||||||
|
|
||||||
/* This piece of crap needs to disappear into per-type test hooks. */
|
|
||||||
+#ifdef CONFIG_CRYPTO_MANAGER_DISABLE_TESTS
|
|
||||||
+ type |= CRYPTO_ALG_TESTED;
|
|
||||||
+#else
|
|
||||||
if ((!((type ^ CRYPTO_ALG_TYPE_BLKCIPHER) &
|
|
||||||
CRYPTO_ALG_TYPE_BLKCIPHER_MASK) && !(type & CRYPTO_ALG_GENIV) &&
|
|
||||||
((alg->cra_flags & CRYPTO_ALG_TYPE_MASK) ==
|
|
||||||
@@ -255,6 +258,7 @@ static int cryptomgr_schedule_test(struc
|
|
||||||
(!((type ^ CRYPTO_ALG_TYPE_AEAD) & CRYPTO_ALG_TYPE_MASK) &&
|
|
||||||
alg->cra_type == &crypto_nivaead_type && alg->cra_aead.ivsize))
|
|
||||||
type |= CRYPTO_ALG_TESTED;
|
|
||||||
+#endif
|
|
||||||
|
|
||||||
param->type = type;
|
|
||||||
|
|
|
@ -1,23 +0,0 @@
|
||||||
--- a/lib/Kconfig
|
|
||||||
+++ b/lib/Kconfig
|
|
||||||
@@ -178,16 +178,16 @@ config AUDIT_GENERIC
|
|
||||||
# compression support is select'ed if needed
|
|
||||||
#
|
|
||||||
config ZLIB_INFLATE
|
|
||||||
- tristate
|
|
||||||
+ tristate "ZLIB inflate support"
|
|
||||||
|
|
||||||
config ZLIB_DEFLATE
|
|
||||||
- tristate
|
|
||||||
+ tristate "ZLIB deflate support"
|
|
||||||
|
|
||||||
config LZO_COMPRESS
|
|
||||||
- tristate
|
|
||||||
+ tristate "LZO compress support"
|
|
||||||
|
|
||||||
config LZO_DECOMPRESS
|
|
||||||
- tristate
|
|
||||||
+ tristate "LZO decompress support"
|
|
||||||
|
|
||||||
source "lib/xz/Kconfig"
|
|
||||||
|
|
|
@ -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
|
|
||||||
@@ -893,9 +893,6 @@ config FW_ARC
|
|
||||||
config ARCH_MAY_HAVE_PC_FDC
|
|
||||||
bool
|
|
||||||
|
|
||||||
-config BOOT_RAW
|
|
||||||
- bool
|
|
||||||
-
|
|
||||||
config CEVT_BCM1480
|
|
||||||
bool
|
|
||||||
|
|
||||||
@@ -2374,6 +2371,18 @@ config USE_OF
|
|
||||||
select OF_EARLY_FLATTREE
|
|
||||||
select IRQ_DOMAIN
|
|
||||||
|
|
||||||
+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
|
|
||||||
@@ -984,6 +984,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
|
|
||||||
@@ -140,6 +140,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,11 +0,0 @@
|
||||||
--- a/arch/mips/Makefile
|
|
||||||
+++ b/arch/mips/Makefile
|
|
||||||
@@ -87,7 +87,7 @@ all-$(CONFIG_SYS_SUPPORTS_ZBOOT)+= vmlin
|
|
||||||
# machines may also. Since BFD is incredibly buggy with respect to
|
|
||||||
# crossformat linking we rely on the elf2ecoff tool for format conversion.
|
|
||||||
#
|
|
||||||
-cflags-y += -G 0 -mno-abicalls -fno-pic -pipe
|
|
||||||
+cflags-y += -G 0 -mno-abicalls -fno-pic -pipe -mno-branch-likely
|
|
||||||
cflags-y += -msoft-float
|
|
||||||
LDFLAGS_vmlinux += -G 0 -static -n -nostdlib --gc-sections --sort-section=name
|
|
||||||
KBUILD_AFLAGS_MODULE += -mlong-calls
|
|
|
@ -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
|
|
||||||
@@ -969,6 +969,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
|
|
||||||
@@ -108,6 +108,7 @@ int mips_dsemul(struct pt_regs *regs, mi
|
|
||||||
return SIGILL; /* force out of emulation loop */
|
|
||||||
}
|
|
||||||
|
|
||||||
+#ifdef CONFIG_MIPS_FPU_EMU
|
|
||||||
int do_dsemulret(struct pt_regs *xcp)
|
|
||||||
{
|
|
||||||
struct emuframe __user *fr;
|
|
||||||
@@ -164,3 +165,9 @@ int do_dsemulret(struct pt_regs *xcp)
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
+#else
|
|
||||||
+int do_dsemulret(struct pt_regs *xcp)
|
|
||||||
+{
|
|
||||||
+ return 0;
|
|
||||||
+}
|
|
||||||
+#endif /* CONFIG_MIPS_FPU_EMU */
|
|
||||||
--- a/arch/mips/math-emu/kernel_linkage.c
|
|
||||||
+++ b/arch/mips/math-emu/kernel_linkage.c
|
|
||||||
@@ -29,6 +29,7 @@
|
|
||||||
|
|
||||||
#define SIGNALLING_NAN 0x7ff800007ff80000LL
|
|
||||||
|
|
||||||
+#ifdef CONFIG_MIPS_FPU_EMU
|
|
||||||
void fpu_emulator_init_fpu(void)
|
|
||||||
{
|
|
||||||
static int first = 1;
|
|
||||||
@@ -112,4 +113,36 @@ int fpu_emulator_restore_context32(struc
|
|
||||||
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
-#endif
|
|
||||||
+#endif /* CONFIG_64BIT */
|
|
||||||
+#else
|
|
||||||
+
|
|
||||||
+void fpu_emulator_init_fpu(void)
|
|
||||||
+{
|
|
||||||
+ printk(KERN_INFO "FPU emulator disabled, make sure your toolchain"
|
|
||||||
+ "was compiled with software floating point support (soft-float)\n");
|
|
||||||
+ return;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+int fpu_emulator_save_context(struct sigcontext __user *sc)
|
|
||||||
+{
|
|
||||||
+ return 0;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+int fpu_emulator_restore_context(struct sigcontext __user *sc)
|
|
||||||
+{
|
|
||||||
+ return 0;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+int fpu_emulator_save_context32(struct sigcontext32 __user *sc)
|
|
||||||
+{
|
|
||||||
+ return 0;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+int fpu_emulator_restore_context32(struct sigcontext32 __user *sc)
|
|
||||||
+{
|
|
||||||
+ return 0;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+#ifdef CONFIG_64BIT
|
|
||||||
+#endif /* CONFIG_64BIT */
|
|
||||||
+#endif /* CONFIG_MIPS_FPU_EMU */
|
|
|
@ -1,350 +0,0 @@
|
||||||
--- a/arch/mips/Makefile
|
|
||||||
+++ b/arch/mips/Makefile
|
|
||||||
@@ -90,8 +90,13 @@ all-$(CONFIG_SYS_SUPPORTS_ZBOOT)+= vmlin
|
|
||||||
cflags-y += -G 0 -mno-abicalls -fno-pic -pipe -mno-branch-likely
|
|
||||||
cflags-y += -msoft-float
|
|
||||||
LDFLAGS_vmlinux += -G 0 -static -n -nostdlib --gc-sections --sort-section=name
|
|
||||||
+ifdef CONFIG_64BIT
|
|
||||||
KBUILD_AFLAGS_MODULE += -mlong-calls
|
|
||||||
KBUILD_CFLAGS_MODULE += -mlong-calls
|
|
||||||
+else
|
|
||||||
+KBUILD_AFLAGS_MODULE += -mno-long-calls
|
|
||||||
+KBUILD_CFLAGS_MODULE += -mno-long-calls
|
|
||||||
+endif
|
|
||||||
|
|
||||||
ifndef CONFIG_FUNCTION_TRACER
|
|
||||||
KBUILD_CFLAGS_KERNEL += -ffunction-sections -fdata-sections
|
|
||||||
--- a/arch/mips/include/asm/module.h
|
|
||||||
+++ b/arch/mips/include/asm/module.h
|
|
||||||
@@ -11,6 +11,11 @@ struct mod_arch_specific {
|
|
||||||
const struct exception_table_entry *dbe_start;
|
|
||||||
const struct exception_table_entry *dbe_end;
|
|
||||||
struct mips_hi16 *r_mips_hi16_list;
|
|
||||||
+
|
|
||||||
+ void *phys_plt_tbl;
|
|
||||||
+ void *virt_plt_tbl;
|
|
||||||
+ unsigned int phys_plt_offset;
|
|
||||||
+ unsigned int virt_plt_offset;
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef uint8_t Elf64_Byte; /* Type for a 8-bit quantity. */
|
|
||||||
--- a/arch/mips/kernel/module.c
|
|
||||||
+++ b/arch/mips/kernel/module.c
|
|
||||||
@@ -42,14 +42,219 @@ struct mips_hi16 {
|
|
||||||
static LIST_HEAD(dbe_list);
|
|
||||||
static DEFINE_SPINLOCK(dbe_lock);
|
|
||||||
|
|
||||||
-#ifdef MODULE_START
|
|
||||||
+/*
|
|
||||||
+ * Get the potential max trampolines size required of the init and
|
|
||||||
+ * non-init sections. Only used if we cannot find enough contiguous
|
|
||||||
+ * physically mapped memory to put the module into.
|
|
||||||
+ */
|
|
||||||
+static unsigned int
|
|
||||||
+get_plt_size(const Elf_Ehdr *hdr, const Elf_Shdr *sechdrs,
|
|
||||||
+ const char *secstrings, unsigned int symindex, bool is_init)
|
|
||||||
+{
|
|
||||||
+ unsigned long ret = 0;
|
|
||||||
+ unsigned int i, j;
|
|
||||||
+ Elf_Sym *syms;
|
|
||||||
+
|
|
||||||
+ /* Everything marked ALLOC (this includes the exported symbols) */
|
|
||||||
+ for (i = 1; i < hdr->e_shnum; ++i) {
|
|
||||||
+ unsigned int info = sechdrs[i].sh_info;
|
|
||||||
+
|
|
||||||
+ if (sechdrs[i].sh_type != SHT_REL
|
|
||||||
+ && sechdrs[i].sh_type != SHT_RELA)
|
|
||||||
+ continue;
|
|
||||||
+
|
|
||||||
+ /* Not a valid relocation section? */
|
|
||||||
+ if (info >= hdr->e_shnum)
|
|
||||||
+ continue;
|
|
||||||
+
|
|
||||||
+ /* Don't bother with non-allocated sections */
|
|
||||||
+ if (!(sechdrs[info].sh_flags & SHF_ALLOC))
|
|
||||||
+ continue;
|
|
||||||
+
|
|
||||||
+ /* If it's called *.init*, and we're not init, we're
|
|
||||||
+ not interested */
|
|
||||||
+ if ((strstr(secstrings + sechdrs[i].sh_name, ".init") != 0)
|
|
||||||
+ != is_init)
|
|
||||||
+ continue;
|
|
||||||
+
|
|
||||||
+ syms = (Elf_Sym *) sechdrs[symindex].sh_addr;
|
|
||||||
+ if (sechdrs[i].sh_type == SHT_REL) {
|
|
||||||
+ Elf_Mips_Rel *rel = (void *) sechdrs[i].sh_addr;
|
|
||||||
+ unsigned int size = sechdrs[i].sh_size / sizeof(*rel);
|
|
||||||
+
|
|
||||||
+ for (j = 0; j < size; ++j) {
|
|
||||||
+ Elf_Sym *sym;
|
|
||||||
+
|
|
||||||
+ if (ELF_MIPS_R_TYPE(rel[j]) != R_MIPS_26)
|
|
||||||
+ continue;
|
|
||||||
+
|
|
||||||
+ sym = syms + ELF_MIPS_R_SYM(rel[j]);
|
|
||||||
+ if (!is_init && sym->st_shndx != SHN_UNDEF)
|
|
||||||
+ continue;
|
|
||||||
+
|
|
||||||
+ ret += 4 * sizeof(int);
|
|
||||||
+ }
|
|
||||||
+ } else {
|
|
||||||
+ Elf_Mips_Rela *rela = (void *) sechdrs[i].sh_addr;
|
|
||||||
+ unsigned int size = sechdrs[i].sh_size / sizeof(*rela);
|
|
||||||
+
|
|
||||||
+ for (j = 0; j < size; ++j) {
|
|
||||||
+ Elf_Sym *sym;
|
|
||||||
+
|
|
||||||
+ if (ELF_MIPS_R_TYPE(rela[j]) != R_MIPS_26)
|
|
||||||
+ continue;
|
|
||||||
+
|
|
||||||
+ sym = syms + ELF_MIPS_R_SYM(rela[j]);
|
|
||||||
+ if (!is_init && sym->st_shndx != SHN_UNDEF)
|
|
||||||
+ continue;
|
|
||||||
+
|
|
||||||
+ ret += 4 * sizeof(int);
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ return ret;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+#ifndef MODULE_START
|
|
||||||
+static void *alloc_phys(unsigned long size)
|
|
||||||
+{
|
|
||||||
+ unsigned order;
|
|
||||||
+ struct page *page;
|
|
||||||
+ struct page *p;
|
|
||||||
+
|
|
||||||
+ size = PAGE_ALIGN(size);
|
|
||||||
+ order = get_order(size);
|
|
||||||
+
|
|
||||||
+ page = alloc_pages(GFP_KERNEL | __GFP_NORETRY | __GFP_NOWARN |
|
|
||||||
+ __GFP_THISNODE, order);
|
|
||||||
+ if (!page)
|
|
||||||
+ return NULL;
|
|
||||||
+
|
|
||||||
+ split_page(page, order);
|
|
||||||
+
|
|
||||||
+ for (p = page + (size >> PAGE_SHIFT); p < page + (1 << order); ++p)
|
|
||||||
+ __free_page(p);
|
|
||||||
+
|
|
||||||
+ return page_address(page);
|
|
||||||
+}
|
|
||||||
+#endif
|
|
||||||
+
|
|
||||||
+static void free_phys(void *ptr, unsigned long size)
|
|
||||||
+{
|
|
||||||
+ struct page *page;
|
|
||||||
+ struct page *end;
|
|
||||||
+
|
|
||||||
+ page = virt_to_page(ptr);
|
|
||||||
+ end = page + (PAGE_ALIGN(size) >> PAGE_SHIFT);
|
|
||||||
+
|
|
||||||
+ for (; page < end; ++page)
|
|
||||||
+ __free_page(page);
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+
|
|
||||||
void *module_alloc(unsigned long size)
|
|
||||||
{
|
|
||||||
+#ifdef MODULE_START
|
|
||||||
return __vmalloc_node_range(size, 1, MODULE_START, MODULE_END,
|
|
||||||
GFP_KERNEL, PAGE_KERNEL, -1,
|
|
||||||
__builtin_return_address(0));
|
|
||||||
+#else
|
|
||||||
+ void *ptr;
|
|
||||||
+
|
|
||||||
+ if (size == 0)
|
|
||||||
+ return NULL;
|
|
||||||
+
|
|
||||||
+ ptr = alloc_phys(size);
|
|
||||||
+
|
|
||||||
+ /* If we failed to allocate physically contiguous memory,
|
|
||||||
+ * fall back to regular vmalloc. The module loader code will
|
|
||||||
+ * create jump tables to handle long jumps */
|
|
||||||
+ if (!ptr)
|
|
||||||
+ return vmalloc(size);
|
|
||||||
+
|
|
||||||
+ return ptr;
|
|
||||||
+#endif
|
|
||||||
}
|
|
||||||
+
|
|
||||||
+static inline bool is_phys_addr(void *ptr)
|
|
||||||
+{
|
|
||||||
+#ifdef CONFIG_64BIT
|
|
||||||
+ return (KSEGX((unsigned long)ptr) == CKSEG0);
|
|
||||||
+#else
|
|
||||||
+ return (KSEGX(ptr) == KSEG0);
|
|
||||||
#endif
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+/* Free memory returned from module_alloc */
|
|
||||||
+void module_free(struct module *mod, void *module_region)
|
|
||||||
+{
|
|
||||||
+ if (is_phys_addr(module_region)) {
|
|
||||||
+ if (mod->module_init == module_region)
|
|
||||||
+ free_phys(module_region, mod->init_size);
|
|
||||||
+ else if (mod->module_core == module_region)
|
|
||||||
+ free_phys(module_region, mod->core_size);
|
|
||||||
+ else
|
|
||||||
+ BUG();
|
|
||||||
+ } else {
|
|
||||||
+ vfree(module_region);
|
|
||||||
+ }
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static void *__module_alloc(int size, bool phys)
|
|
||||||
+{
|
|
||||||
+ void *ptr;
|
|
||||||
+
|
|
||||||
+ if (phys)
|
|
||||||
+ ptr = kmalloc(size, GFP_KERNEL);
|
|
||||||
+ else
|
|
||||||
+ ptr = vmalloc(size);
|
|
||||||
+ return ptr;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static void __module_free(void *ptr)
|
|
||||||
+{
|
|
||||||
+ if (is_phys_addr(ptr))
|
|
||||||
+ kfree(ptr);
|
|
||||||
+ else
|
|
||||||
+ vfree(ptr);
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+int module_frob_arch_sections(Elf_Ehdr *hdr, Elf_Shdr *sechdrs,
|
|
||||||
+ char *secstrings, struct module *mod)
|
|
||||||
+{
|
|
||||||
+ unsigned int symindex = 0;
|
|
||||||
+ unsigned int core_size, init_size;
|
|
||||||
+ int i;
|
|
||||||
+
|
|
||||||
+ for (i = 1; i < hdr->e_shnum; i++)
|
|
||||||
+ if (sechdrs[i].sh_type == SHT_SYMTAB)
|
|
||||||
+ symindex = i;
|
|
||||||
+
|
|
||||||
+ core_size = get_plt_size(hdr, sechdrs, secstrings, symindex, false);
|
|
||||||
+ init_size = get_plt_size(hdr, sechdrs, secstrings, symindex, true);
|
|
||||||
+
|
|
||||||
+ mod->arch.phys_plt_offset = 0;
|
|
||||||
+ mod->arch.virt_plt_offset = 0;
|
|
||||||
+ mod->arch.phys_plt_tbl = NULL;
|
|
||||||
+ mod->arch.virt_plt_tbl = NULL;
|
|
||||||
+
|
|
||||||
+ if ((core_size + init_size) == 0)
|
|
||||||
+ return 0;
|
|
||||||
+
|
|
||||||
+ mod->arch.phys_plt_tbl = __module_alloc(core_size + init_size, 1);
|
|
||||||
+ if (!mod->arch.phys_plt_tbl)
|
|
||||||
+ return -ENOMEM;
|
|
||||||
+
|
|
||||||
+ mod->arch.virt_plt_tbl = __module_alloc(core_size + init_size, 0);
|
|
||||||
+ if (!mod->arch.virt_plt_tbl) {
|
|
||||||
+ __module_free(mod->arch.phys_plt_tbl);
|
|
||||||
+ mod->arch.phys_plt_tbl = NULL;
|
|
||||||
+ return -ENOMEM;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ return 0;
|
|
||||||
+}
|
|
||||||
|
|
||||||
int apply_r_mips_none(struct module *me, u32 *location, Elf_Addr v)
|
|
||||||
{
|
|
||||||
@@ -63,8 +268,39 @@ static int apply_r_mips_32_rel(struct mo
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
+static Elf_Addr add_plt_entry_to(unsigned *plt_offset,
|
|
||||||
+ void *start, Elf_Addr v)
|
|
||||||
+{
|
|
||||||
+ unsigned *tramp = start + *plt_offset;
|
|
||||||
+ *plt_offset += 4 * sizeof(int);
|
|
||||||
+
|
|
||||||
+ /* adjust carry for addiu */
|
|
||||||
+ if (v & 0x00008000)
|
|
||||||
+ v += 0x10000;
|
|
||||||
+
|
|
||||||
+ tramp[0] = 0x3c190000 | (v >> 16); /* lui t9, hi16 */
|
|
||||||
+ tramp[1] = 0x27390000 | (v & 0xffff); /* addiu t9, t9, lo16 */
|
|
||||||
+ tramp[2] = 0x03200008; /* jr t9 */
|
|
||||||
+ tramp[3] = 0x00000000; /* nop */
|
|
||||||
+
|
|
||||||
+ return (Elf_Addr) tramp;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static Elf_Addr add_plt_entry(struct module *me, void *location, Elf_Addr v)
|
|
||||||
+{
|
|
||||||
+ if (is_phys_addr(location))
|
|
||||||
+ return add_plt_entry_to(&me->arch.phys_plt_offset,
|
|
||||||
+ me->arch.phys_plt_tbl, v);
|
|
||||||
+ else
|
|
||||||
+ return add_plt_entry_to(&me->arch.virt_plt_offset,
|
|
||||||
+ me->arch.virt_plt_tbl, v);
|
|
||||||
+
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
static int apply_r_mips_26_rel(struct module *me, u32 *location, Elf_Addr v)
|
|
||||||
{
|
|
||||||
+ u32 ofs = *location & 0x03ffffff;
|
|
||||||
+
|
|
||||||
if (v % 4) {
|
|
||||||
pr_err("module %s: dangerous R_MIPS_26 REL relocation\n",
|
|
||||||
me->name);
|
|
||||||
@@ -72,14 +308,17 @@ static int apply_r_mips_26_rel(struct mo
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((v & 0xf0000000) != (((unsigned long)location + 4) & 0xf0000000)) {
|
|
||||||
- printk(KERN_ERR
|
|
||||||
- "module %s: relocation overflow\n",
|
|
||||||
- me->name);
|
|
||||||
- return -ENOEXEC;
|
|
||||||
+ v = add_plt_entry(me, location, v + (ofs << 2));
|
|
||||||
+ if (!v) {
|
|
||||||
+ printk(KERN_ERR
|
|
||||||
+ "module %s: relocation overflow\n",
|
|
||||||
+ me->name);
|
|
||||||
+ return -ENOEXEC;
|
|
||||||
+ }
|
|
||||||
+ ofs = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
- *location = (*location & ~0x03ffffff) |
|
|
||||||
- ((*location + (v >> 2)) & 0x03ffffff);
|
|
||||||
+ *location = (*location & ~0x03ffffff) | ((ofs + (v >> 2)) & 0x03ffffff);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
@@ -286,11 +525,32 @@ int module_finalize(const Elf_Ehdr *hdr,
|
|
||||||
list_add(&me->arch.dbe_list, &dbe_list);
|
|
||||||
spin_unlock_irq(&dbe_lock);
|
|
||||||
}
|
|
||||||
+
|
|
||||||
+ /* Get rid of the fixup trampoline if we're running the module
|
|
||||||
+ * from physically mapped address space */
|
|
||||||
+ if (me->arch.phys_plt_offset == 0) {
|
|
||||||
+ __module_free(me->arch.phys_plt_tbl);
|
|
||||||
+ me->arch.phys_plt_tbl = NULL;
|
|
||||||
+ }
|
|
||||||
+ if (me->arch.virt_plt_offset == 0) {
|
|
||||||
+ __module_free(me->arch.virt_plt_tbl);
|
|
||||||
+ me->arch.virt_plt_tbl = NULL;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void module_arch_cleanup(struct module *mod)
|
|
||||||
{
|
|
||||||
+ if (mod->arch.phys_plt_tbl) {
|
|
||||||
+ __module_free(mod->arch.phys_plt_tbl);
|
|
||||||
+ mod->arch.phys_plt_tbl = NULL;
|
|
||||||
+ }
|
|
||||||
+ if (mod->arch.virt_plt_tbl) {
|
|
||||||
+ __module_free(mod->arch.virt_plt_tbl);
|
|
||||||
+ mod->arch.virt_plt_tbl = NULL;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
spin_lock_irq(&dbe_lock);
|
|
||||||
list_del(&mod->arch.dbe_list);
|
|
||||||
spin_unlock_irq(&dbe_lock);
|
|
|
@ -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
|
|
||||||
@@ -4,7 +4,7 @@
|
|
||||||
|
|
||||||
lib-y += bitops.o csum_partial.o delay.o memcpy.o memset.o \
|
|
||||||
mips-atomic.o strlen_user.o strncpy_user.o \
|
|
||||||
- strnlen_user.o uncached.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,17 +0,0 @@
|
||||||
--- a/arch/mips/kernel/cpu-probe.c
|
|
||||||
+++ b/arch/mips/kernel/cpu-probe.c
|
|
||||||
@@ -838,10 +838,13 @@ static inline void cpu_probe_mips(struct
|
|
||||||
__cpu_name[cpu] = "MIPS 20Kc";
|
|
||||||
break;
|
|
||||||
case PRID_IMP_24K:
|
|
||||||
- case PRID_IMP_24KE:
|
|
||||||
c->cputype = CPU_24K;
|
|
||||||
__cpu_name[cpu] = "MIPS 24Kc";
|
|
||||||
break;
|
|
||||||
+ case PRID_IMP_24KE:
|
|
||||||
+ c->cputype = CPU_24K;
|
|
||||||
+ __cpu_name[cpu] = "MIPS 24KEc";
|
|
||||||
+ break;
|
|
||||||
case PRID_IMP_25KF:
|
|
||||||
c->cputype = CPU_25KF;
|
|
||||||
__cpu_name[cpu] = "MIPS 25Kc";
|
|
|
@ -1,32 +0,0 @@
|
||||||
--- a/arch/mips/mm/cache.c
|
|
||||||
+++ b/arch/mips/mm/cache.c
|
|
||||||
@@ -39,6 +39,7 @@ void (*__flush_kernel_vmap_range)(unsign
|
|
||||||
void (*__invalidate_kernel_vmap_range)(unsigned long vaddr, int size);
|
|
||||||
|
|
||||||
EXPORT_SYMBOL_GPL(__flush_kernel_vmap_range);
|
|
||||||
+EXPORT_SYMBOL(__flush_cache_all);
|
|
||||||
|
|
||||||
/* MIPS specific cache operations */
|
|
||||||
void (*flush_cache_sigtramp)(unsigned long addr);
|
|
||||||
--- a/fs/fuse/dev.c
|
|
||||||
+++ b/fs/fuse/dev.c
|
|
||||||
@@ -19,6 +19,9 @@
|
|
||||||
#include <linux/pipe_fs_i.h>
|
|
||||||
#include <linux/swap.h>
|
|
||||||
#include <linux/splice.h>
|
|
||||||
+#ifdef CONFIG_MIPS
|
|
||||||
+#include <asm/cacheflush.h>
|
|
||||||
+#endif
|
|
||||||
|
|
||||||
MODULE_ALIAS_MISCDEV(FUSE_MINOR);
|
|
||||||
MODULE_ALIAS("devname:fuse");
|
|
||||||
@@ -654,6 +657,9 @@ static int fuse_copy_fill(struct fuse_co
|
|
||||||
static int fuse_copy_do(struct fuse_copy_state *cs, void **val, unsigned *size)
|
|
||||||
{
|
|
||||||
unsigned ncpy = min(*size, cs->len);
|
|
||||||
+#ifdef CONFIG_MIPS
|
|
||||||
+ __flush_cache_all();
|
|
||||||
+#endif
|
|
||||||
if (val) {
|
|
||||||
if (cs->write)
|
|
||||||
memcpy(cs->buf, *val, ncpy);
|
|
|
@ -1,13 +0,0 @@
|
||||||
--- a/arch/arm/kernel/module.c
|
|
||||||
+++ b/arch/arm/kernel/module.c
|
|
||||||
@@ -81,6 +81,10 @@ apply_relocate(Elf32_Shdr *sechdrs, cons
|
|
||||||
return -ENOEXEC;
|
|
||||||
}
|
|
||||||
|
|
||||||
+ if ((IS_ERR_VALUE(sym->st_value) || !sym->st_value) &&
|
|
||||||
+ ELF_ST_BIND(sym->st_info) == STB_WEAK)
|
|
||||||
+ continue;
|
|
||||||
+
|
|
||||||
loc = dstsec->sh_addr + rel->r_offset;
|
|
||||||
|
|
||||||
switch (ELF32_R_TYPE(rel->r_info)) {
|
|
|
@ -1,31 +0,0 @@
|
||||||
Upstream doesn't optimize the kernel and bootwrappers for ppc44x because
|
|
||||||
they still want to support gcc 3.3 -- well, we don't.
|
|
||||||
|
|
||||||
--- a/arch/powerpc/Makefile
|
|
||||||
+++ b/arch/powerpc/Makefile
|
|
||||||
@@ -119,7 +119,8 @@ ifeq ($(CONFIG_FUNCTION_TRACER),y)
|
|
||||||
KBUILD_CFLAGS += -mno-sched-epilog
|
|
||||||
endif
|
|
||||||
|
|
||||||
-cpu-as-$(CONFIG_4xx) += -Wa,-m405
|
|
||||||
+cpu-as-$(CONFIG_40x) += -Wa,-m405
|
|
||||||
+cpu-as-$(CONFIG_44x) += -Wa,-m440
|
|
||||||
cpu-as-$(CONFIG_ALTIVEC) += -Wa,-maltivec
|
|
||||||
cpu-as-$(CONFIG_E500) += -Wa,-me500
|
|
||||||
cpu-as-$(CONFIG_E200) += -Wa,-me200
|
|
||||||
--- a/arch/powerpc/boot/Makefile
|
|
||||||
+++ b/arch/powerpc/boot/Makefile
|
|
||||||
@@ -38,10 +38,10 @@ BOOTCFLAGS += -I$(obj) -I$(srctree)/$(ob
|
|
||||||
DTC_FLAGS ?= -p 1024
|
|
||||||
|
|
||||||
$(obj)/4xx.o: BOOTCFLAGS += -mcpu=405
|
|
||||||
-$(obj)/ebony.o: BOOTCFLAGS += -mcpu=405
|
|
||||||
+$(obj)/ebony.o: BOOTCFLAGS += -mcpu=440
|
|
||||||
$(obj)/cuboot-hotfoot.o: BOOTCFLAGS += -mcpu=405
|
|
||||||
-$(obj)/cuboot-taishan.o: BOOTCFLAGS += -mcpu=405
|
|
||||||
-$(obj)/cuboot-katmai.o: BOOTCFLAGS += -mcpu=405
|
|
||||||
+$(obj)/cuboot-taishan.o: BOOTCFLAGS += -mcpu=440
|
|
||||||
+$(obj)/cuboot-katmai.o: BOOTCFLAGS += -mcpu=440
|
|
||||||
$(obj)/cuboot-acadia.o: BOOTCFLAGS += -mcpu=405
|
|
||||||
$(obj)/treeboot-walnut.o: BOOTCFLAGS += -mcpu=405
|
|
||||||
$(obj)/treeboot-iss4xx.o: BOOTCFLAGS += -mcpu=405
|
|
|
@ -1,10 +0,0 @@
|
||||||
--- a/arch/powerpc/Makefile
|
|
||||||
+++ b/arch/powerpc/Makefile
|
|
||||||
@@ -86,7 +86,6 @@ CPP = $(CC) -E $(KBUILD_CFLAGS)
|
|
||||||
|
|
||||||
CHECKFLAGS += -m$(CONFIG_WORD_SIZE) -D__powerpc__ -D__powerpc$(CONFIG_WORD_SIZE)__
|
|
||||||
|
|
||||||
-KBUILD_LDFLAGS_MODULE += arch/powerpc/lib/crtsavres.o
|
|
||||||
|
|
||||||
# No AltiVec or VSX instructions when building kernel
|
|
||||||
KBUILD_CFLAGS += $(call cc-option,-mno-altivec)
|
|
|
@ -1,10 +0,0 @@
|
||||||
--- a/drivers/crypto/amcc/crypto4xx_core.c
|
|
||||||
+++ b/drivers/crypto/amcc/crypto4xx_core.c
|
|
||||||
@@ -19,6 +19,7 @@
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <linux/kernel.h>
|
|
||||||
+#include <linux/module.h>
|
|
||||||
#include <linux/interrupt.h>
|
|
||||||
#include <linux/spinlock_types.h>
|
|
||||||
#include <linux/random.h>
|
|
|
@ -1,316 +0,0 @@
|
||||||
--- a/drivers/mtd/Kconfig
|
|
||||||
+++ b/drivers/mtd/Kconfig
|
|
||||||
@@ -23,6 +23,14 @@ config MTD_TESTS
|
|
||||||
WARNING: some of the tests will ERASE entire MTD device which they
|
|
||||||
test. Do not use these tests unless you really know what you do.
|
|
||||||
|
|
||||||
+config MTD_ROOTFS_ROOT_DEV
|
|
||||||
+ bool "Automatically set 'rootfs' partition to be root filesystem"
|
|
||||||
+ default y
|
|
||||||
+
|
|
||||||
+config MTD_ROOTFS_SPLIT
|
|
||||||
+ bool "Automatically split 'rootfs' partition for squashfs"
|
|
||||||
+ default y
|
|
||||||
+
|
|
||||||
config MTD_REDBOOT_PARTS
|
|
||||||
tristate "RedBoot partition table parsing"
|
|
||||||
---help---
|
|
||||||
--- a/drivers/mtd/mtdpart.c
|
|
||||||
+++ b/drivers/mtd/mtdpart.c
|
|
||||||
@@ -29,6 +29,8 @@
|
|
||||||
#include <linux/kmod.h>
|
|
||||||
#include <linux/mtd/mtd.h>
|
|
||||||
#include <linux/mtd/partitions.h>
|
|
||||||
+#include <linux/root_dev.h>
|
|
||||||
+#include <linux/magic.h>
|
|
||||||
#include <linux/err.h>
|
|
||||||
|
|
||||||
#include "mtdcore.h"
|
|
||||||
@@ -50,7 +52,7 @@ struct mtd_part {
|
|
||||||
* the pointer to that structure with this macro.
|
|
||||||
*/
|
|
||||||
#define PART(x) ((struct mtd_part *)(x))
|
|
||||||
-
|
|
||||||
+#define IS_PART(mtd) (mtd->_read == part_read)
|
|
||||||
|
|
||||||
/*
|
|
||||||
* MTD methods which simply translate the effective address and pass through
|
|
||||||
@@ -613,6 +615,144 @@ int mtd_del_partition(struct mtd_info *m
|
|
||||||
}
|
|
||||||
EXPORT_SYMBOL_GPL(mtd_del_partition);
|
|
||||||
|
|
||||||
+#ifdef CONFIG_MTD_ROOTFS_SPLIT
|
|
||||||
+#define ROOTFS_SPLIT_NAME "rootfs_data"
|
|
||||||
+#define ROOTFS_REMOVED_NAME "<removed>"
|
|
||||||
+
|
|
||||||
+struct squashfs_super_block {
|
|
||||||
+ __le32 s_magic;
|
|
||||||
+ __le32 pad0[9];
|
|
||||||
+ __le64 bytes_used;
|
|
||||||
+};
|
|
||||||
+
|
|
||||||
+
|
|
||||||
+static int split_squashfs(struct mtd_info *master, int offset, int *split_offset)
|
|
||||||
+{
|
|
||||||
+ struct squashfs_super_block sb;
|
|
||||||
+ int len, ret;
|
|
||||||
+
|
|
||||||
+ ret = mtd_read(master, offset, sizeof(sb), &len, (void *) &sb);
|
|
||||||
+ if (ret || (len != sizeof(sb))) {
|
|
||||||
+ printk(KERN_ALERT "split_squashfs: error occured while reading "
|
|
||||||
+ "from \"%s\"\n", master->name);
|
|
||||||
+ return -EINVAL;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ if (SQUASHFS_MAGIC != le32_to_cpu(sb.s_magic) ) {
|
|
||||||
+ printk(KERN_ALERT "split_squashfs: no squashfs found in \"%s\"\n",
|
|
||||||
+ master->name);
|
|
||||||
+ *split_offset = 0;
|
|
||||||
+ return 0;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ if (le64_to_cpu((sb.bytes_used)) <= 0) {
|
|
||||||
+ printk(KERN_ALERT "split_squashfs: squashfs is empty in \"%s\"\n",
|
|
||||||
+ master->name);
|
|
||||||
+ *split_offset = 0;
|
|
||||||
+ return 0;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ len = (u32) le64_to_cpu(sb.bytes_used);
|
|
||||||
+ len += (offset & 0x000fffff);
|
|
||||||
+ len += (master->erasesize - 1);
|
|
||||||
+ len &= ~(master->erasesize - 1);
|
|
||||||
+ len -= (offset & 0x000fffff);
|
|
||||||
+ *split_offset = offset + len;
|
|
||||||
+
|
|
||||||
+ return 0;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static int split_rootfs_data(struct mtd_info *master, struct mtd_info *rpart, const struct mtd_partition *part)
|
|
||||||
+{
|
|
||||||
+ struct mtd_partition dpart;
|
|
||||||
+ struct mtd_part *slave = NULL;
|
|
||||||
+ struct mtd_part *spart;
|
|
||||||
+ int ret, split_offset = 0;
|
|
||||||
+
|
|
||||||
+ spart = PART(rpart);
|
|
||||||
+ ret = split_squashfs(master, spart->offset, &split_offset);
|
|
||||||
+ if (ret)
|
|
||||||
+ return ret;
|
|
||||||
+
|
|
||||||
+ if (split_offset <= 0)
|
|
||||||
+ return 0;
|
|
||||||
+
|
|
||||||
+ memcpy(&dpart, part, sizeof(dpart));
|
|
||||||
+ dpart.name = ROOTFS_SPLIT_NAME;
|
|
||||||
+
|
|
||||||
+ dpart.size = rpart->size - (split_offset - spart->offset);
|
|
||||||
+ dpart.offset = split_offset;
|
|
||||||
+
|
|
||||||
+ printk(KERN_INFO "mtd: partition \"%s\" created automatically, ofs=%llX, len=%llX \n",
|
|
||||||
+ ROOTFS_SPLIT_NAME, dpart.offset, dpart.size);
|
|
||||||
+
|
|
||||||
+ slave = allocate_partition(master, &dpart, 0, split_offset);
|
|
||||||
+ if (IS_ERR(slave))
|
|
||||||
+ return PTR_ERR(slave);
|
|
||||||
+ mutex_lock(&mtd_partitions_mutex);
|
|
||||||
+ list_add(&slave->list, &mtd_partitions);
|
|
||||||
+ mutex_unlock(&mtd_partitions_mutex);
|
|
||||||
+
|
|
||||||
+ add_mtd_device(&slave->mtd);
|
|
||||||
+
|
|
||||||
+ rpart->split = &slave->mtd;
|
|
||||||
+
|
|
||||||
+ return 0;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static int refresh_rootfs_split(struct mtd_info *mtd)
|
|
||||||
+{
|
|
||||||
+ struct mtd_partition tpart;
|
|
||||||
+ struct mtd_part *part;
|
|
||||||
+ char *name;
|
|
||||||
+ //int index = 0;
|
|
||||||
+ int offset, size;
|
|
||||||
+ int ret;
|
|
||||||
+
|
|
||||||
+ part = PART(mtd);
|
|
||||||
+
|
|
||||||
+ /* check for the new squashfs offset first */
|
|
||||||
+ ret = split_squashfs(part->master, part->offset, &offset);
|
|
||||||
+ if (ret)
|
|
||||||
+ return ret;
|
|
||||||
+
|
|
||||||
+ if ((offset > 0) && !mtd->split) {
|
|
||||||
+ printk(KERN_INFO "%s: creating new split partition for \"%s\"\n", __func__, mtd->name);
|
|
||||||
+ /* if we don't have a rootfs split partition, create a new one */
|
|
||||||
+ tpart.name = (char *) mtd->name;
|
|
||||||
+ tpart.size = mtd->size;
|
|
||||||
+ tpart.offset = part->offset;
|
|
||||||
+
|
|
||||||
+ return split_rootfs_data(part->master, &part->mtd, &tpart);
|
|
||||||
+ } else if ((offset > 0) && mtd->split) {
|
|
||||||
+ /* update the offsets of the existing partition */
|
|
||||||
+ size = mtd->size + part->offset - offset;
|
|
||||||
+
|
|
||||||
+ part = PART(mtd->split);
|
|
||||||
+ part->offset = offset;
|
|
||||||
+ part->mtd.size = size;
|
|
||||||
+ printk(KERN_INFO "%s: %s partition \"" ROOTFS_SPLIT_NAME "\", offset: 0x%06x (0x%06x)\n",
|
|
||||||
+ __func__, (!strcmp(part->mtd.name, ROOTFS_SPLIT_NAME) ? "updating" : "creating"),
|
|
||||||
+ (u32) part->offset, (u32) part->mtd.size);
|
|
||||||
+ name = kmalloc(sizeof(ROOTFS_SPLIT_NAME) + 1, GFP_KERNEL);
|
|
||||||
+ strcpy(name, ROOTFS_SPLIT_NAME);
|
|
||||||
+ part->mtd.name = name;
|
|
||||||
+ } else if ((offset <= 0) && mtd->split) {
|
|
||||||
+ printk(KERN_INFO "%s: removing partition \"%s\"\n", __func__, mtd->split->name);
|
|
||||||
+
|
|
||||||
+ /* mark existing partition as removed */
|
|
||||||
+ part = PART(mtd->split);
|
|
||||||
+ name = kmalloc(sizeof(ROOTFS_SPLIT_NAME) + 1, GFP_KERNEL);
|
|
||||||
+ strcpy(name, ROOTFS_REMOVED_NAME);
|
|
||||||
+ part->mtd.name = name;
|
|
||||||
+ part->offset = 0;
|
|
||||||
+ part->mtd.size = 0;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ return 0;
|
|
||||||
+}
|
|
||||||
+#endif /* CONFIG_MTD_ROOTFS_SPLIT */
|
|
||||||
+
|
|
||||||
/*
|
|
||||||
* This function, given a master MTD object and a partition table, creates
|
|
||||||
* and registers slave MTD objects which are bound to the master according to
|
|
||||||
@@ -629,6 +769,9 @@ int add_mtd_partitions(struct mtd_info *
|
|
||||||
struct mtd_part *slave;
|
|
||||||
uint64_t cur_offset = 0;
|
|
||||||
int i;
|
|
||||||
+#ifdef CONFIG_MTD_ROOTFS_SPLIT
|
|
||||||
+ int ret;
|
|
||||||
+#endif
|
|
||||||
|
|
||||||
printk(KERN_NOTICE "Creating %d MTD partitions on \"%s\":\n", nbparts, master->name);
|
|
||||||
|
|
||||||
@@ -643,12 +786,53 @@ int add_mtd_partitions(struct mtd_info *
|
|
||||||
|
|
||||||
add_mtd_device(&slave->mtd);
|
|
||||||
|
|
||||||
+ if (!strcmp(parts[i].name, "rootfs")) {
|
|
||||||
+#ifdef CONFIG_MTD_ROOTFS_ROOT_DEV
|
|
||||||
+ if (ROOT_DEV == 0) {
|
|
||||||
+ printk(KERN_NOTICE "mtd: partition \"rootfs\" "
|
|
||||||
+ "set to be root filesystem\n");
|
|
||||||
+ ROOT_DEV = MKDEV(MTD_BLOCK_MAJOR, slave->mtd.index);
|
|
||||||
+ }
|
|
||||||
+#endif
|
|
||||||
+#ifdef CONFIG_MTD_ROOTFS_SPLIT
|
|
||||||
+ ret = split_rootfs_data(master, &slave->mtd, &parts[i]);
|
|
||||||
+ /* if (ret == 0)
|
|
||||||
+ * j++; */
|
|
||||||
+#endif
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
cur_offset = slave->offset + slave->mtd.size;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
+int mtd_device_refresh(struct mtd_info *mtd)
|
|
||||||
+{
|
|
||||||
+ int ret = 0;
|
|
||||||
+
|
|
||||||
+ if (IS_PART(mtd)) {
|
|
||||||
+ struct mtd_part *part;
|
|
||||||
+ struct mtd_info *master;
|
|
||||||
+
|
|
||||||
+ part = PART(mtd);
|
|
||||||
+ master = part->master;
|
|
||||||
+ if (master->refresh_device)
|
|
||||||
+ ret = master->refresh_device(master);
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ if (!ret && mtd->refresh_device)
|
|
||||||
+ ret = mtd->refresh_device(mtd);
|
|
||||||
+
|
|
||||||
+#ifdef CONFIG_MTD_ROOTFS_SPLIT
|
|
||||||
+ if (!ret && IS_PART(mtd) && !strcmp(mtd->name, "rootfs"))
|
|
||||||
+ refresh_rootfs_split(mtd);
|
|
||||||
+#endif
|
|
||||||
+
|
|
||||||
+ return 0;
|
|
||||||
+}
|
|
||||||
+EXPORT_SYMBOL_GPL(mtd_device_refresh);
|
|
||||||
+
|
|
||||||
static DEFINE_SPINLOCK(part_parser_lock);
|
|
||||||
static LIST_HEAD(part_parsers);
|
|
||||||
|
|
||||||
--- a/drivers/mtd/mtdchar.c
|
|
||||||
+++ b/drivers/mtd/mtdchar.c
|
|
||||||
@@ -1012,6 +1012,12 @@ static int mtdchar_ioctl(struct file *fi
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
+ case MTDREFRESH:
|
|
||||||
+ {
|
|
||||||
+ ret = mtd_device_refresh(mtd);
|
|
||||||
+ break;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
default:
|
|
||||||
ret = -ENOTTY;
|
|
||||||
}
|
|
||||||
--- a/include/linux/mtd/mtd.h
|
|
||||||
+++ b/include/linux/mtd/mtd.h
|
|
||||||
@@ -114,6 +114,7 @@ struct nand_ecclayout {
|
|
||||||
|
|
||||||
struct module; /* only needed for owner field in mtd_info */
|
|
||||||
|
|
||||||
+struct mtd_info;
|
|
||||||
struct mtd_info {
|
|
||||||
u_char type;
|
|
||||||
uint32_t flags;
|
|
||||||
@@ -226,6 +227,9 @@ struct mtd_info {
|
|
||||||
int (*_block_markbad) (struct mtd_info *mtd, loff_t ofs);
|
|
||||||
int (*_suspend) (struct mtd_info *mtd);
|
|
||||||
void (*_resume) (struct mtd_info *mtd);
|
|
||||||
+ int (*refresh_device)(struct mtd_info *mtd);
|
|
||||||
+ struct mtd_info *split;
|
|
||||||
+
|
|
||||||
/*
|
|
||||||
* If the driver is something smart, like UBI, it may need to maintain
|
|
||||||
* its own reference counting. The below functions are only for driver.
|
|
||||||
@@ -368,6 +372,7 @@ extern int mtd_device_parse_register(str
|
|
||||||
int defnr_parts);
|
|
||||||
#define mtd_device_register(master, parts, nr_parts) \
|
|
||||||
mtd_device_parse_register(master, NULL, NULL, parts, nr_parts)
|
|
||||||
+extern int mtd_device_refresh(struct mtd_info *master);
|
|
||||||
extern int mtd_device_unregister(struct mtd_info *master);
|
|
||||||
extern struct mtd_info *get_mtd_device(struct mtd_info *mtd, int num);
|
|
||||||
extern int __get_mtd_device(struct mtd_info *mtd);
|
|
||||||
--- a/include/linux/mtd/partitions.h
|
|
||||||
+++ b/include/linux/mtd/partitions.h
|
|
||||||
@@ -36,12 +36,14 @@
|
|
||||||
* erasesize aligned (e.g. use MTDPART_OFS_NEXTBLK).
|
|
||||||
*/
|
|
||||||
|
|
||||||
+struct mtd_partition;
|
|
||||||
struct mtd_partition {
|
|
||||||
char *name; /* identifier string */
|
|
||||||
uint64_t size; /* partition size */
|
|
||||||
uint64_t offset; /* offset within the master MTD space */
|
|
||||||
uint32_t mask_flags; /* master MTD flags to mask out for this partition */
|
|
||||||
struct nand_ecclayout *ecclayout; /* out of band layout for this partition (NAND only) */
|
|
||||||
+ int (*refresh_partition)(struct mtd_info *);
|
|
||||||
};
|
|
||||||
|
|
||||||
#define MTDPART_OFS_RETAIN (-3)
|
|
||||||
--- a/include/uapi/mtd/mtd-abi.h
|
|
||||||
+++ b/include/uapi/mtd/mtd-abi.h
|
|
||||||
@@ -202,6 +202,7 @@ struct otp_info {
|
|
||||||
* without OOB, e.g., NOR flash.
|
|
||||||
*/
|
|
||||||
#define MEMWRITE _IOWR('M', 24, struct mtd_write_req)
|
|
||||||
+#define MTDREFRESH _IO('M', 50)
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Obsolete legacy interface. Keep it in order not to break userspace
|
|
|
@ -1,146 +0,0 @@
|
||||||
--- a/drivers/mtd/mtdpart.c
|
|
||||||
+++ b/drivers/mtd/mtdpart.c
|
|
||||||
@@ -35,6 +35,8 @@
|
|
||||||
|
|
||||||
#include "mtdcore.h"
|
|
||||||
|
|
||||||
+#define MTD_ERASE_PARTIAL 0x8000 /* partition only covers parts of an erase block */
|
|
||||||
+
|
|
||||||
/* Our partition linked list */
|
|
||||||
static LIST_HEAD(mtd_partitions);
|
|
||||||
static DEFINE_MUTEX(mtd_partitions_mutex);
|
|
||||||
@@ -230,13 +232,61 @@ static int part_erase(struct mtd_info *m
|
|
||||||
struct mtd_part *part = PART(mtd);
|
|
||||||
int ret;
|
|
||||||
|
|
||||||
+
|
|
||||||
+ instr->partial_start = false;
|
|
||||||
+ if (mtd->flags & MTD_ERASE_PARTIAL) {
|
|
||||||
+ size_t readlen = 0;
|
|
||||||
+ u64 mtd_ofs;
|
|
||||||
+
|
|
||||||
+ instr->erase_buf = kmalloc(part->master->erasesize, GFP_ATOMIC);
|
|
||||||
+ if (!instr->erase_buf)
|
|
||||||
+ return -ENOMEM;
|
|
||||||
+
|
|
||||||
+ mtd_ofs = part->offset + instr->addr;
|
|
||||||
+ instr->erase_buf_ofs = do_div(mtd_ofs, part->master->erasesize);
|
|
||||||
+
|
|
||||||
+ if (instr->erase_buf_ofs > 0) {
|
|
||||||
+ instr->addr -= instr->erase_buf_ofs;
|
|
||||||
+ ret = mtd_read(part->master,
|
|
||||||
+ instr->addr + part->offset,
|
|
||||||
+ part->master->erasesize,
|
|
||||||
+ &readlen, instr->erase_buf);
|
|
||||||
+
|
|
||||||
+ instr->len += instr->erase_buf_ofs;
|
|
||||||
+ instr->partial_start = true;
|
|
||||||
+ } else {
|
|
||||||
+ mtd_ofs = part->offset + part->mtd.size;
|
|
||||||
+ instr->erase_buf_ofs = part->master->erasesize -
|
|
||||||
+ do_div(mtd_ofs, part->master->erasesize);
|
|
||||||
+
|
|
||||||
+ if (instr->erase_buf_ofs > 0) {
|
|
||||||
+ instr->len += instr->erase_buf_ofs;
|
|
||||||
+ ret = mtd_read(part->master,
|
|
||||||
+ part->offset + instr->addr +
|
|
||||||
+ instr->len - part->master->erasesize,
|
|
||||||
+ part->master->erasesize, &readlen,
|
|
||||||
+ instr->erase_buf);
|
|
||||||
+ } else {
|
|
||||||
+ ret = 0;
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
+ if (ret < 0) {
|
|
||||||
+ kfree(instr->erase_buf);
|
|
||||||
+ return ret;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
instr->addr += part->offset;
|
|
||||||
ret = part->master->_erase(part->master, instr);
|
|
||||||
if (ret) {
|
|
||||||
if (instr->fail_addr != MTD_FAIL_ADDR_UNKNOWN)
|
|
||||||
instr->fail_addr -= part->offset;
|
|
||||||
instr->addr -= part->offset;
|
|
||||||
+ if (mtd->flags & MTD_ERASE_PARTIAL)
|
|
||||||
+ kfree(instr->erase_buf);
|
|
||||||
}
|
|
||||||
+
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -244,7 +294,25 @@ void mtd_erase_callback(struct erase_inf
|
|
||||||
{
|
|
||||||
if (instr->mtd->_erase == part_erase) {
|
|
||||||
struct mtd_part *part = PART(instr->mtd);
|
|
||||||
+ size_t wrlen = 0;
|
|
||||||
|
|
||||||
+ if (instr->mtd->flags & MTD_ERASE_PARTIAL) {
|
|
||||||
+ if (instr->partial_start) {
|
|
||||||
+ part->master->_write(part->master,
|
|
||||||
+ instr->addr, instr->erase_buf_ofs,
|
|
||||||
+ &wrlen, instr->erase_buf);
|
|
||||||
+ instr->addr += instr->erase_buf_ofs;
|
|
||||||
+ } else {
|
|
||||||
+ instr->len -= instr->erase_buf_ofs;
|
|
||||||
+ part->master->_write(part->master,
|
|
||||||
+ instr->addr + instr->len,
|
|
||||||
+ instr->erase_buf_ofs, &wrlen,
|
|
||||||
+ instr->erase_buf +
|
|
||||||
+ part->master->erasesize -
|
|
||||||
+ instr->erase_buf_ofs);
|
|
||||||
+ }
|
|
||||||
+ kfree(instr->erase_buf);
|
|
||||||
+ }
|
|
||||||
if (instr->fail_addr != MTD_FAIL_ADDR_UNKNOWN)
|
|
||||||
instr->fail_addr -= part->offset;
|
|
||||||
instr->addr -= part->offset;
|
|
||||||
@@ -504,18 +572,24 @@ static struct mtd_part *allocate_partiti
|
|
||||||
if ((slave->mtd.flags & MTD_WRITEABLE) &&
|
|
||||||
mtd_mod_by_eb(slave->offset, &slave->mtd)) {
|
|
||||||
/* Doesn't start on a boundary of major erase size */
|
|
||||||
- /* FIXME: Let it be writable if it is on a boundary of
|
|
||||||
- * _minor_ erase size though */
|
|
||||||
- slave->mtd.flags &= ~MTD_WRITEABLE;
|
|
||||||
- printk(KERN_WARNING"mtd: partition \"%s\" doesn't start on an erase block boundary -- force read-only\n",
|
|
||||||
- part->name);
|
|
||||||
+ slave->mtd.flags |= MTD_ERASE_PARTIAL;
|
|
||||||
+ if (((u32) slave->mtd.size) > master->erasesize)
|
|
||||||
+ slave->mtd.flags &= ~MTD_WRITEABLE;
|
|
||||||
+ else
|
|
||||||
+ slave->mtd.erasesize = slave->mtd.size;
|
|
||||||
}
|
|
||||||
if ((slave->mtd.flags & MTD_WRITEABLE) &&
|
|
||||||
- mtd_mod_by_eb(slave->mtd.size, &slave->mtd)) {
|
|
||||||
- slave->mtd.flags &= ~MTD_WRITEABLE;
|
|
||||||
- printk(KERN_WARNING"mtd: partition \"%s\" doesn't end on an erase block -- force read-only\n",
|
|
||||||
- part->name);
|
|
||||||
+ mtd_mod_by_eb(slave->offset + slave->mtd.size, &slave->mtd)) {
|
|
||||||
+ slave->mtd.flags |= MTD_ERASE_PARTIAL;
|
|
||||||
+
|
|
||||||
+ if ((u32) slave->mtd.size > master->erasesize)
|
|
||||||
+ slave->mtd.flags &= ~MTD_WRITEABLE;
|
|
||||||
+ else
|
|
||||||
+ slave->mtd.erasesize = slave->mtd.size;
|
|
||||||
}
|
|
||||||
+ if ((slave->mtd.flags & (MTD_ERASE_PARTIAL|MTD_WRITEABLE)) == MTD_ERASE_PARTIAL)
|
|
||||||
+ printk(KERN_WARNING"mtd: partition \"%s\" must either start or end on erase block boundary or be smaller than an erase block -- forcing read-only\n",
|
|
||||||
+ part->name);
|
|
||||||
|
|
||||||
slave->mtd.ecclayout = master->ecclayout;
|
|
||||||
slave->mtd.ecc_strength = master->ecc_strength;
|
|
||||||
--- a/include/linux/mtd/mtd.h
|
|
||||||
+++ b/include/linux/mtd/mtd.h
|
|
||||||
@@ -58,6 +58,10 @@ struct erase_info {
|
|
||||||
u_long priv;
|
|
||||||
u_char state;
|
|
||||||
struct erase_info *next;
|
|
||||||
+
|
|
||||||
+ u8 *erase_buf;
|
|
||||||
+ u32 erase_buf_ofs;
|
|
||||||
+ bool partial_start;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct mtd_erase_region_info {
|
|
|
@ -1,18 +0,0 @@
|
||||||
--- a/include/linux/mtd/partitions.h
|
|
||||||
+++ b/include/linux/mtd/partitions.h
|
|
||||||
@@ -35,6 +35,7 @@
|
|
||||||
* Note: writeable partitions require their size and offset be
|
|
||||||
* erasesize aligned (e.g. use MTDPART_OFS_NEXTBLK).
|
|
||||||
*/
|
|
||||||
+struct mtd_info;
|
|
||||||
|
|
||||||
struct mtd_partition;
|
|
||||||
struct mtd_partition {
|
|
||||||
@@ -52,7 +53,6 @@ struct mtd_partition {
|
|
||||||
#define MTDPART_SIZ_FULL (0)
|
|
||||||
|
|
||||||
|
|
||||||
-struct mtd_info;
|
|
||||||
struct device_node;
|
|
||||||
|
|
||||||
/**
|
|
|
@ -1,30 +0,0 @@
|
||||||
--- a/drivers/mtd/redboot.c
|
|
||||||
+++ b/drivers/mtd/redboot.c
|
|
||||||
@@ -265,14 +265,21 @@ static int parse_redboot_partitions(stru
|
|
||||||
#endif
|
|
||||||
names += strlen(names)+1;
|
|
||||||
|
|
||||||
-#ifdef CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED
|
|
||||||
if(fl->next && fl->img->flash_base + fl->img->size + master->erasesize <= fl->next->img->flash_base) {
|
|
||||||
- i++;
|
|
||||||
- parts[i].offset = parts[i-1].size + parts[i-1].offset;
|
|
||||||
- parts[i].size = fl->next->img->flash_base - parts[i].offset;
|
|
||||||
- parts[i].name = nullname;
|
|
||||||
- }
|
|
||||||
+ if (!strcmp(parts[i].name, "rootfs")) {
|
|
||||||
+ parts[i].size = fl->next->img->flash_base;
|
|
||||||
+ parts[i].size &= ~(master->erasesize - 1);
|
|
||||||
+ parts[i].size -= parts[i].offset;
|
|
||||||
+#ifdef CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED
|
|
||||||
+ nrparts--;
|
|
||||||
+ } else {
|
|
||||||
+ i++;
|
|
||||||
+ parts[i].offset = parts[i-1].size + parts[i-1].offset;
|
|
||||||
+ parts[i].size = fl->next->img->flash_base - parts[i].offset;
|
|
||||||
+ parts[i].name = nullname;
|
|
||||||
#endif
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
tmp_fl = fl;
|
|
||||||
fl = fl->next;
|
|
||||||
kfree(tmp_fl);
|
|
|
@ -1,35 +0,0 @@
|
||||||
--- a/drivers/mtd/Kconfig
|
|
||||||
+++ b/drivers/mtd/Kconfig
|
|
||||||
@@ -163,6 +163,22 @@ config MTD_BCM47XX_PARTS
|
|
||||||
This provides partitions parser for devices based on BCM47xx
|
|
||||||
boards.
|
|
||||||
|
|
||||||
+config MTD_MYLOADER_PARTS
|
|
||||||
+ tristate "MyLoader partition parsing"
|
|
||||||
+ depends on ADM5120 || ATHEROS_AR231X || ATHEROS_AR71XX || ATH79
|
|
||||||
+ ---help---
|
|
||||||
+ MyLoader is a bootloader which allows the user to define partitions
|
|
||||||
+ in flash devices, by putting a table in the second erase block
|
|
||||||
+ on the device, similar to a partition table. This table gives the
|
|
||||||
+ offsets and lengths of the user defined partitions.
|
|
||||||
+
|
|
||||||
+ If you need code which can detect and parse these tables, and
|
|
||||||
+ register MTD 'partitions' corresponding to each image detected,
|
|
||||||
+ enable this option.
|
|
||||||
+
|
|
||||||
+ You will still need the parsing functions to be called by the driver
|
|
||||||
+ for your particular device. It won't happen automatically.
|
|
||||||
+
|
|
||||||
comment "User Modules And Translation Layers"
|
|
||||||
|
|
||||||
config MTD_CHAR
|
|
||||||
--- a/drivers/mtd/Makefile
|
|
||||||
+++ b/drivers/mtd/Makefile
|
|
||||||
@@ -13,6 +13,7 @@ obj-$(CONFIG_MTD_AFS_PARTS) += afs.o
|
|
||||||
obj-$(CONFIG_MTD_AR7_PARTS) += ar7part.o
|
|
||||||
obj-$(CONFIG_MTD_BCM63XX_PARTS) += bcm63xxpart.o
|
|
||||||
obj-$(CONFIG_MTD_BCM47XX_PARTS) += bcm47xxpart.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/mutex.h>
|
|
||||||
#include <linux/mount.h>
|
|
||||||
#include <linux/slab.h>
|
|
||||||
@@ -210,11 +211,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)
|
|
||||||
@@ -253,13 +255,16 @@ static struct block2mtd_dev *add_device(
|
|
||||||
|
|
||||||
/* Setup the MTD structure */
|
|
||||||
/* make the name contain the block device in */
|
|
||||||
- name = kasprintf(GFP_KERNEL, "block2mtd: %s", devname);
|
|
||||||
+ if (!mtdname)
|
|
||||||
+ mtdname = devname;
|
|
||||||
+ name = kmalloc(strlen(mtdname) + 1, GFP_KERNEL);
|
|
||||||
if (!name)
|
|
||||||
goto devinit_err;
|
|
||||||
|
|
||||||
+ strcpy(name, mtdname);
|
|
||||||
dev->mtd.name = name;
|
|
||||||
|
|
||||||
- dev->mtd.size = dev->blkdev->bd_inode->i_size & PAGE_MASK;
|
|
||||||
+ dev->mtd.size = dev->blkdev->bd_inode->i_size & PAGE_MASK & ~(erase_size - 1);
|
|
||||||
dev->mtd.erasesize = erase_size;
|
|
||||||
dev->mtd.writesize = 1;
|
|
||||||
dev->mtd.writebufsize = PAGE_SIZE;
|
|
||||||
@@ -272,14 +277,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:
|
|
||||||
@@ -352,9 +360,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;
|
|
||||||
@@ -365,7 +373,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)
|
|
||||||
@@ -384,8 +392,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;
|
|
||||||
}
|
|
||||||
@@ -419,7 +429,7 @@ static int block2mtd_setup(const char *v
|
|
||||||
|
|
||||||
|
|
||||||
module_param_call(block2mtd, block2mtd_setup, NULL, NULL, 0200);
|
|
||||||
-MODULE_PARM_DESC(block2mtd, "Device to use. \"block2mtd=<dev>[,<erasesize>]\"");
|
|
||||||
+MODULE_PARM_DESC(block2mtd, "Device to use. \"block2mtd=<dev>[,<erasesize>[,<name>]]\"");
|
|
||||||
|
|
||||||
static int __init block2mtd_init(void)
|
|
||||||
{
|
|
||||||
--- a/block/partition-generic.c
|
|
||||||
+++ b/block/partition-generic.c
|
|
||||||
@@ -548,6 +548,7 @@ int invalidate_partitions(struct gendisk
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
+EXPORT_SYMBOL(rescan_partitions);
|
|
||||||
|
|
||||||
unsigned char *read_dev_sector(struct block_device *bdev, sector_t n, Sector *p)
|
|
||||||
{
|
|
|
@ -1,269 +0,0 @@
|
||||||
--- a/drivers/mtd/devices/block2mtd.c
|
|
||||||
+++ b/drivers/mtd/devices/block2mtd.c
|
|
||||||
@@ -29,6 +29,8 @@ struct block2mtd_dev {
|
|
||||||
struct block_device *blkdev;
|
|
||||||
struct mtd_info mtd;
|
|
||||||
struct mutex write_mutex;
|
|
||||||
+ rwlock_t bdev_mutex;
|
|
||||||
+ char devname[0];
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
@@ -80,6 +82,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);
|
|
||||||
@@ -91,6 +99,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;
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -102,7 +114,13 @@ static int block2mtd_read(struct mtd_inf
|
|
||||||
struct page *page;
|
|
||||||
int index = from >> PAGE_SHIFT;
|
|
||||||
int offset = from & (PAGE_SIZE-1);
|
|
||||||
- int cpylen;
|
|
||||||
+ int cpylen, err = 0;
|
|
||||||
+
|
|
||||||
+ read_lock(&dev->bdev_mutex);
|
|
||||||
+ if (!dev->blkdev || (from > mtd->size)) {
|
|
||||||
+ err = -EINVAL;
|
|
||||||
+ goto done;
|
|
||||||
+ }
|
|
||||||
|
|
||||||
while (len) {
|
|
||||||
if ((offset + len) > PAGE_SIZE)
|
|
||||||
@@ -112,8 +130,10 @@ static int block2mtd_read(struct mtd_inf
|
|
||||||
len = len - cpylen;
|
|
||||||
|
|
||||||
page = page_read(dev->blkdev->bd_inode->i_mapping, index);
|
|
||||||
- if (IS_ERR(page))
|
|
||||||
- return PTR_ERR(page);
|
|
||||||
+ if (IS_ERR(page)) {
|
|
||||||
+ err = PTR_ERR(page);
|
|
||||||
+ goto done;
|
|
||||||
+ }
|
|
||||||
|
|
||||||
memcpy(buf, page_address(page) + offset, cpylen);
|
|
||||||
page_cache_release(page);
|
|
||||||
@@ -124,7 +144,10 @@ static int block2mtd_read(struct mtd_inf
|
|
||||||
offset = 0;
|
|
||||||
index++;
|
|
||||||
}
|
|
||||||
- return 0;
|
|
||||||
+
|
|
||||||
+done:
|
|
||||||
+ read_unlock(&dev->bdev_mutex);
|
|
||||||
+ return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@@ -173,13 +196,22 @@ static int block2mtd_write(struct mtd_in
|
|
||||||
size_t *retlen, const u_char *buf)
|
|
||||||
{
|
|
||||||
struct block2mtd_dev *dev = mtd->priv;
|
|
||||||
- int err;
|
|
||||||
+ int err = 0;
|
|
||||||
+
|
|
||||||
+ read_lock(&dev->bdev_mutex);
|
|
||||||
+ if (!dev->blkdev) {
|
|
||||||
+ err = -EINVAL;
|
|
||||||
+ goto done;
|
|
||||||
+ }
|
|
||||||
|
|
||||||
mutex_lock(&dev->write_mutex);
|
|
||||||
err = _block2mtd_write(dev, buf, to, len, retlen);
|
|
||||||
mutex_unlock(&dev->write_mutex);
|
|
||||||
if (err > 0)
|
|
||||||
err = 0;
|
|
||||||
+
|
|
||||||
+done:
|
|
||||||
+ read_unlock(&dev->bdev_mutex);
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -188,33 +220,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;
|
|
||||||
@@ -222,36 +331,17 @@ static struct block2mtd_dev *add_device(
|
|
||||||
if (!devname)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
- dev = kzalloc(sizeof(struct block2mtd_dev), GFP_KERNEL);
|
|
||||||
+ dev = kzalloc(sizeof(struct block2mtd_dev) + strlen(devname) + 1, GFP_KERNEL);
|
|
||||||
if (!dev)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
- /* Get a handle on the device */
|
|
||||||
- bdev = blkdev_get_by_path(devname, mode, dev);
|
|
||||||
-#ifndef MODULE
|
|
||||||
- if (IS_ERR(bdev)) {
|
|
||||||
-
|
|
||||||
- /* We might not have rootfs mounted at this point. Try
|
|
||||||
- to resolve the device name by other means. */
|
|
||||||
-
|
|
||||||
- dev_t devt = name_to_dev_t(devname);
|
|
||||||
- if (devt)
|
|
||||||
- bdev = blkdev_get_by_dev(devt, mode, dev);
|
|
||||||
- }
|
|
||||||
-#endif
|
|
||||||
-
|
|
||||||
- if (IS_ERR(bdev)) {
|
|
||||||
- ERROR("error: cannot open device %s", devname);
|
|
||||||
- goto devinit_err;
|
|
||||||
- }
|
|
||||||
- dev->blkdev = bdev;
|
|
||||||
+ strcpy(dev->devname, devname);
|
|
||||||
|
|
||||||
- if (MAJOR(bdev->bd_dev) == MTD_BLOCK_MAJOR) {
|
|
||||||
- ERROR("attempting to use an MTD device as a block device");
|
|
||||||
+ if (_open_bdev(dev))
|
|
||||||
goto devinit_err;
|
|
||||||
- }
|
|
||||||
|
|
||||||
mutex_init(&dev->write_mutex);
|
|
||||||
+ rwlock_init(&dev->bdev_mutex);
|
|
||||||
|
|
||||||
/* Setup the MTD structure */
|
|
||||||
/* make the name contain the block device in */
|
|
||||||
@@ -276,6 +366,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
|
|
||||||
@@ -243,6 +243,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
|
|
||||||
@@ -654,6 +654,7 @@ struct platform_nand_chip {
|
|
||||||
unsigned int options;
|
|
||||||
unsigned int bbt_options;
|
|
||||||
const char **part_probe_types;
|
|
||||||
+ int (*chip_fixup)(struct mtd_info *mtd);
|
|
||||||
};
|
|
||||||
|
|
||||||
/* Keep gcc happy */
|
|
||||||
--- a/drivers/mtd/nand/plat_nand.c
|
|
||||||
+++ b/drivers/mtd/nand/plat_nand.c
|
|
||||||
@@ -103,7 +103,18 @@ static int plat_nand_probe(struct platfo
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Scan to find existence of the device */
|
|
||||||
- if (nand_scan(&data->mtd, pdata->chip.nr_chips)) {
|
|
||||||
+ if (nand_scan_ident(&data->mtd, pdata->chip.nr_chips, NULL)) {
|
|
||||||
+ err = -ENXIO;
|
|
||||||
+ goto out;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ if (pdata->chip.chip_fixup) {
|
|
||||||
+ err = pdata->chip.chip_fixup(&data->mtd);
|
|
||||||
+ if (err)
|
|
||||||
+ goto out;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ if (nand_scan_tail(&data->mtd)) {
|
|
||||||
err = -ENXIO;
|
|
||||||
goto out;
|
|
||||||
}
|
|
|
@ -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
|
|
||||||
@@ -762,7 +762,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
|
|
||||||
@@ -45,6 +45,7 @@
|
|
||||||
#define OPCODE_BE_4K 0x20 /* Erase 4KiB block */
|
|
||||||
#define OPCODE_BE_32K 0x52 /* Erase 32KiB block */
|
|
||||||
#define OPCODE_CHIP_ERASE 0xc7 /* Erase whole flash chip */
|
|
||||||
+#define OPCODE_BE_4K_PMC 0xd7 /* Erase 4KiB block on PMC chips*/
|
|
||||||
#define OPCODE_SE 0xd8 /* Sector erase (usually 64KiB) */
|
|
||||||
#define OPCODE_RDID 0x9f /* Read JEDEC ID */
|
|
||||||
|
|
||||||
@@ -591,6 +592,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) \
|
|
||||||
@@ -669,6 +671,10 @@ static const struct spi_device_id m25p_i
|
|
||||||
{ "n25q128a13", INFO(0x20ba18, 0, 64 * 1024, 256, 0) },
|
|
||||||
{ "n25q256a", INFO(0x20ba19, 0, 64 * 1024, 512, SECT_4K) },
|
|
||||||
|
|
||||||
+ /* 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).
|
|
||||||
*/
|
|
||||||
@@ -913,6 +919,9 @@ static int m25p_probe(struct spi_device
|
|
||||||
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
|
|
||||||
@@ -754,6 +754,7 @@ static const struct spi_device_id m25p_i
|
|
||||||
{ "w25q64", INFO(0xef4017, 0, 64 * 1024, 128, SECT_4K) },
|
|
||||||
{ "w25q80", INFO(0xef5014, 0, 64 * 1024, 16, SECT_4K) },
|
|
||||||
{ "w25q80bl", INFO(0xef4014, 0, 64 * 1024, 16, SECT_4K) },
|
|
||||||
+ { "w25q128", INFO(0xef4018, 0, 64 * 1024, 256, SECT_4K) },
|
|
||||||
{ "w25q256", INFO(0xef4019, 0, 64 * 1024, 512, SECT_4K) },
|
|
||||||
|
|
||||||
/* Catalyst / On Semiconductor -- non-JEDEC */
|
|
|
@ -1,10 +0,0 @@
|
||||||
--- a/drivers/mtd/devices/m25p80.c
|
|
||||||
+++ b/drivers/mtd/devices/m25p80.c
|
|
||||||
@@ -674,6 +674,7 @@ static const struct spi_device_id m25p_i
|
|
||||||
/* PMC -- pm25x "blocks" are 32K, sectors are 4K */
|
|
||||||
{ "pm25lv512", INFO(0, 0, 32 * 1024, 2, SECT_4K_PMC) },
|
|
||||||
{ "pm25lv010", INFO(0, 0, 32 * 1024, 4, SECT_4K_PMC) },
|
|
||||||
+ { "pm25lq032", INFO(0x7F9D46, 0, 64 * 1024, 64, SECT_4K) },
|
|
||||||
|
|
||||||
/* Spansion -- single (large) sector size only, at least
|
|
||||||
* for the chips listed here (without boot sectors).
|
|
|
@ -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
|
|
||||||
@@ -1480,6 +1480,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
|
|
||||||
@@ -110,6 +110,14 @@ config MTD_SPEAR_SMI
|
|
||||||
help
|
|
||||||
This enable SNOR support on SPEAR platforms using SMI controller
|
|
||||||
|
|
||||||
+config M25PXX_PREFER_SMALL_SECTOR_ERASE
|
|
||||||
+ bool "Prefer small sector erase"
|
|
||||||
+ depends on MTD_M25P80
|
|
||||||
+ default y
|
|
||||||
+ help
|
|
||||||
+ This option enables use of the small erase sectors if that is
|
|
||||||
+ supported by the flash chip.
|
|
||||||
+
|
|
||||||
config MTD_SST25L
|
|
||||||
tristate "Support SST25L (non JEDEC) SPI Flash chips"
|
|
||||||
depends on SPI_MASTER
|
|
||||||
--- a/drivers/mtd/devices/m25p80.c
|
|
||||||
+++ b/drivers/mtd/devices/m25p80.c
|
|
||||||
@@ -76,6 +76,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 {
|
|
||||||
@@ -918,7 +924,7 @@ static int m25p_probe(struct spi_device
|
|
||||||
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/drivers/mtd/mtdpart.c
|
|
||||||
+++ b/drivers/mtd/mtdpart.c
|
|
||||||
@@ -331,7 +331,14 @@ static int part_lock(struct mtd_info *mt
|
|
||||||
static int part_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len)
|
|
||||||
{
|
|
||||||
struct mtd_part *part = PART(mtd);
|
|
||||||
- return part->master->_unlock(part->master, ofs + part->offset, len);
|
|
||||||
+
|
|
||||||
+ ofs += part->offset;
|
|
||||||
+ if (mtd->flags & MTD_ERASE_PARTIAL) {
|
|
||||||
+ /* round up len to next erasesize and round down offset to prev block */
|
|
||||||
+ len = (mtd_div_by_eb(len, part->master) + 1) * part->master->erasesize;
|
|
||||||
+ ofs &= ~(part->master->erasesize - 1);
|
|
||||||
+ }
|
|
||||||
+ return part->master->_unlock(part->master, ofs, len);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int part_is_locked(struct mtd_info *mtd, loff_t ofs, uint64_t len)
|
|
|
@ -1,18 +0,0 @@
|
||||||
--- a/fs/Kconfig
|
|
||||||
+++ b/fs/Kconfig
|
|
||||||
@@ -39,6 +39,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
|
|
||||||
@@ -128,3 +128,5 @@ obj-$(CONFIG_F2FS_FS) += f2fs/
|
|
||||||
obj-y += exofs/ # Multiple modules
|
|
||||||
obj-$(CONFIG_CEPH_FS) += ceph/
|
|
||||||
obj-$(CONFIG_PSTORE) += pstore/
|
|
||||||
+obj-$(CONFIG_YAFFS_FS) += yaffs2/
|
|
||||||
+
|
|
|
@ -1,155 +0,0 @@
|
||||||
--- a/fs/yaffs2/yaffs_vfs.c
|
|
||||||
+++ b/fs/yaffs2/yaffs_vfs.c
|
|
||||||
@@ -329,6 +329,33 @@ static int yaffs_readpage(struct file *f
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0))
|
|
||||||
+#define YCRED_FSUID() from_kuid(&init_user_ns, current_fsuid())
|
|
||||||
+#define YCRED_FSGID() from_kgid(&init_user_ns, current_fsgid())
|
|
||||||
+#else
|
|
||||||
+#define YCRED_FSUID() YCRED(current)->fsuid
|
|
||||||
+#define YCRED_FSGID() YCRED(current)->fsgid
|
|
||||||
+
|
|
||||||
+static inline uid_t i_uid_read(const struct inode *inode)
|
|
||||||
+{
|
|
||||||
+ return inode->i_uid;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static inline gid_t i_gid_read(const struct inode *inode)
|
|
||||||
+{
|
|
||||||
+ return inode->i_gid;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static inline void i_uid_write(struct inode *inode, uid_t uid)
|
|
||||||
+{
|
|
||||||
+ inode->i_uid = uid;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static inline void i_gid_write(struct inode *inode, gid_t gid)
|
|
||||||
+{
|
|
||||||
+ inode->i_gid = gid;
|
|
||||||
+}
|
|
||||||
+#endif
|
|
||||||
|
|
||||||
static void yaffs_set_super_dirty_val(struct yaffs_dev *dev, int val)
|
|
||||||
{
|
|
||||||
@@ -1225,9 +1252,9 @@ static int yaffs_mknod(struct inode *dir
|
|
||||||
struct yaffs_obj *parent = yaffs_inode_to_obj(dir);
|
|
||||||
|
|
||||||
int error = -ENOSPC;
|
|
||||||
- uid_t uid = YCRED(current)->fsuid;
|
|
||||||
+ uid_t uid = YCRED_FSUID();
|
|
||||||
gid_t gid =
|
|
||||||
- (dir->i_mode & S_ISGID) ? dir->i_gid : YCRED(current)->fsgid;
|
|
||||||
+ (dir->i_mode & S_ISGID) ? i_gid_read(dir) : YCRED_FSGID();
|
|
||||||
|
|
||||||
if ((dir->i_mode & S_ISGID) && S_ISDIR(mode))
|
|
||||||
mode |= S_ISGID;
|
|
||||||
@@ -1424,9 +1451,9 @@ static int yaffs_symlink(struct inode *d
|
|
||||||
{
|
|
||||||
struct yaffs_obj *obj;
|
|
||||||
struct yaffs_dev *dev;
|
|
||||||
- uid_t uid = YCRED(current)->fsuid;
|
|
||||||
+ uid_t uid = YCRED_FSUID();
|
|
||||||
gid_t gid =
|
|
||||||
- (dir->i_mode & S_ISGID) ? dir->i_gid : YCRED(current)->fsgid;
|
|
||||||
+ (dir->i_mode & S_ISGID) ? i_gid_read(dir) : YCRED_FSGID();
|
|
||||||
|
|
||||||
yaffs_trace(YAFFS_TRACE_OS, "yaffs_symlink");
|
|
||||||
|
|
||||||
@@ -1829,8 +1856,8 @@ static void yaffs_fill_inode_from_obj(st
|
|
||||||
|
|
||||||
inode->i_ino = obj->obj_id;
|
|
||||||
inode->i_mode = obj->yst_mode;
|
|
||||||
- inode->i_uid = obj->yst_uid;
|
|
||||||
- inode->i_gid = obj->yst_gid;
|
|
||||||
+ i_uid_write(inode, obj->yst_uid);
|
|
||||||
+ i_gid_write(inode, obj->yst_gid);
|
|
||||||
#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19))
|
|
||||||
inode->i_blksize = inode->i_sb->s_blocksize;
|
|
||||||
#endif
|
|
||||||
@@ -1856,7 +1883,7 @@ static void yaffs_fill_inode_from_obj(st
|
|
||||||
|
|
||||||
yaffs_trace(YAFFS_TRACE_OS,
|
|
||||||
"yaffs_fill_inode mode %x uid %d gid %d size %lld count %d",
|
|
||||||
- inode->i_mode, inode->i_uid, inode->i_gid,
|
|
||||||
+ inode->i_mode, i_uid_read(inode), i_gid_read(inode),
|
|
||||||
inode->i_size, atomic_read(&inode->i_count));
|
|
||||||
|
|
||||||
switch (obj->yst_mode & S_IFMT) {
|
|
||||||
--- a/fs/yaffs2/yaffs_attribs.c
|
|
||||||
+++ b/fs/yaffs2/yaffs_attribs.c
|
|
||||||
@@ -14,6 +14,48 @@
|
|
||||||
#include "yaffs_guts.h"
|
|
||||||
#include "yaffs_attribs.h"
|
|
||||||
|
|
||||||
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0))
|
|
||||||
+static inline uid_t ia_uid_read(const struct iattr *iattr)
|
|
||||||
+{
|
|
||||||
+ return from_kuid(&init_user_ns, iattr->ia_uid);
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static inline gid_t ia_gid_read(const struct iattr *iattr)
|
|
||||||
+{
|
|
||||||
+ return from_kgid(&init_user_ns, iattr->ia_gid);
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static inline void ia_uid_write(struct iattr *iattr, uid_t uid)
|
|
||||||
+{
|
|
||||||
+ iattr->ia_uid = make_kuid(&init_user_ns, uid);
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static inline void ia_gid_write(struct iattr *iattr, gid_t gid)
|
|
||||||
+{
|
|
||||||
+ iattr->ia_gid = make_kgid(&init_user_ns, gid);
|
|
||||||
+}
|
|
||||||
+#else
|
|
||||||
+static inline uid_t ia_uid_read(const struct iattr *iattr)
|
|
||||||
+{
|
|
||||||
+ return iattr->ia_uid;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static inline gid_t ia_gid_read(const struct iattr *inode)
|
|
||||||
+{
|
|
||||||
+ return iattr->ia_gid;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static inline void ia_uid_write(struct iattr *iattr, uid_t uid)
|
|
||||||
+{
|
|
||||||
+ iattr->ia_uid = uid;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static inline void ia_gid_write(struct iattr *iattr, gid_t gid)
|
|
||||||
+{
|
|
||||||
+ iattr->ia_gid = gid;
|
|
||||||
+}
|
|
||||||
+#endif
|
|
||||||
+
|
|
||||||
void yaffs_load_attribs(struct yaffs_obj *obj, struct yaffs_obj_hdr *oh)
|
|
||||||
{
|
|
||||||
obj->yst_uid = oh->yst_uid;
|
|
||||||
@@ -77,9 +119,9 @@ int yaffs_set_attribs(struct yaffs_obj *
|
|
||||||
if (valid & ATTR_MODE)
|
|
||||||
obj->yst_mode = attr->ia_mode;
|
|
||||||
if (valid & ATTR_UID)
|
|
||||||
- obj->yst_uid = attr->ia_uid;
|
|
||||||
+ obj->yst_uid = ia_uid_read(attr);
|
|
||||||
if (valid & ATTR_GID)
|
|
||||||
- obj->yst_gid = attr->ia_gid;
|
|
||||||
+ obj->yst_gid = ia_gid_read(attr);
|
|
||||||
|
|
||||||
if (valid & ATTR_ATIME)
|
|
||||||
obj->yst_atime = Y_TIME_CONVERT(attr->ia_atime);
|
|
||||||
@@ -103,9 +145,9 @@ int yaffs_get_attribs(struct yaffs_obj *
|
|
||||||
|
|
||||||
attr->ia_mode = obj->yst_mode;
|
|
||||||
valid |= ATTR_MODE;
|
|
||||||
- attr->ia_uid = obj->yst_uid;
|
|
||||||
+ ia_uid_write(attr, obj->yst_uid);
|
|
||||||
valid |= ATTR_UID;
|
|
||||||
- attr->ia_gid = obj->yst_gid;
|
|
||||||
+ ia_gid_write(attr, obj->yst_gid);
|
|
||||||
valid |= ATTR_GID;
|
|
||||||
|
|
||||||
Y_TIME_CONVERT(attr->ia_atime) = obj->yst_atime;
|
|
|
@ -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
File diff suppressed because it is too large
Load Diff
|
@ -1,53 +0,0 @@
|
||||||
--- a/fs/jffs2/build.c
|
|
||||||
+++ b/fs/jffs2/build.c
|
|
||||||
@@ -114,6 +114,16 @@ static int jffs2_build_filesystem(struct
|
|
||||||
dbg_fsbuild("scanned flash completely\n");
|
|
||||||
jffs2_dbg_dump_block_lists_nolock(c);
|
|
||||||
|
|
||||||
+ if (c->flags & (1 << 7)) {
|
|
||||||
+ printk("%s(): unlocking the mtd device... ", __func__);
|
|
||||||
+ mtd_unlock(c->mtd, 0, c->mtd->size);
|
|
||||||
+ printk("done.\n");
|
|
||||||
+
|
|
||||||
+ printk("%s(): erasing all blocks after the end marker... ", __func__);
|
|
||||||
+ jffs2_erase_pending_blocks(c, -1);
|
|
||||||
+ printk("done.\n");
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
dbg_fsbuild("pass 1 starting\n");
|
|
||||||
c->flags |= JFFS2_SB_FLAG_BUILDING;
|
|
||||||
/* Now scan the directory tree, increasing nlink according to every dirent found. */
|
|
||||||
--- a/fs/jffs2/scan.c
|
|
||||||
+++ b/fs/jffs2/scan.c
|
|
||||||
@@ -148,8 +148,11 @@ int jffs2_scan_medium(struct jffs2_sb_in
|
|
||||||
/* reset summary info for next eraseblock scan */
|
|
||||||
jffs2_sum_reset_collected(s);
|
|
||||||
|
|
||||||
- ret = jffs2_scan_eraseblock(c, jeb, buf_size?flashbuf:(flashbuf+jeb->offset),
|
|
||||||
- buf_size, s);
|
|
||||||
+ if (c->flags & (1 << 7))
|
|
||||||
+ ret = BLK_STATE_ALLFF;
|
|
||||||
+ else
|
|
||||||
+ ret = jffs2_scan_eraseblock(c, jeb, buf_size?flashbuf:(flashbuf+jeb->offset),
|
|
||||||
+ buf_size, s);
|
|
||||||
|
|
||||||
if (ret < 0)
|
|
||||||
goto out;
|
|
||||||
@@ -556,6 +559,17 @@ static int jffs2_scan_eraseblock (struct
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
+ if ((buf[0] == 0xde) &&
|
|
||||||
+ (buf[1] == 0xad) &&
|
|
||||||
+ (buf[2] == 0xc0) &&
|
|
||||||
+ (buf[3] == 0xde)) {
|
|
||||||
+ /* end of filesystem. erase everything after this point */
|
|
||||||
+ printk("%s(): End of filesystem marker found at 0x%x\n", __func__, jeb->offset);
|
|
||||||
+ c->flags |= (1 << 7);
|
|
||||||
+
|
|
||||||
+ return BLK_STATE_ALLFF;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
/* We temporarily use 'ofs' as a pointer into the buffer/jeb */
|
|
||||||
ofs = 0;
|
|
||||||
max_ofs = EMPTY_SCAN_SIZE(c->sector_size);
|
|
|
@ -1,146 +0,0 @@
|
||||||
--- a/crypto/Kconfig
|
|
||||||
+++ b/crypto/Kconfig
|
|
||||||
@@ -1223,6 +1223,13 @@ config CRYPTO_842
|
|
||||||
help
|
|
||||||
This is the 842 algorithm.
|
|
||||||
|
|
||||||
+config CRYPTO_XZ
|
|
||||||
+ tristate "XZ compression algorithm"
|
|
||||||
+ select CRYPTO_ALGAPI
|
|
||||||
+ select XZ_DEC
|
|
||||||
+ help
|
|
||||||
+ This is the XZ algorithm. Only decompression is supported for now.
|
|
||||||
+
|
|
||||||
comment "Random Number Generation"
|
|
||||||
|
|
||||||
config CRYPTO_ANSI_CPRNG
|
|
||||||
--- a/crypto/Makefile
|
|
||||||
+++ b/crypto/Makefile
|
|
||||||
@@ -83,6 +83,7 @@ obj-$(CONFIG_CRYPTO_MICHAEL_MIC) += mich
|
|
||||||
obj-$(CONFIG_CRYPTO_CRC32C) += crc32c.o
|
|
||||||
obj-$(CONFIG_CRYPTO_AUTHENC) += authenc.o authencesn.o
|
|
||||||
obj-$(CONFIG_CRYPTO_LZO) += lzo.o
|
|
||||||
+obj-$(CONFIG_CRYPTO_XZ) += xz.o
|
|
||||||
obj-$(CONFIG_CRYPTO_842) += 842.o
|
|
||||||
obj-$(CONFIG_CRYPTO_RNG2) += rng.o
|
|
||||||
obj-$(CONFIG_CRYPTO_RNG2) += krng.o
|
|
||||||
--- /dev/null
|
|
||||||
+++ b/crypto/xz.c
|
|
||||||
@@ -0,0 +1,117 @@
|
|
||||||
+/*
|
|
||||||
+ * Cryptographic API.
|
|
||||||
+ *
|
|
||||||
+ * XZ decompression support.
|
|
||||||
+ *
|
|
||||||
+ * Copyright (c) 2012 Gabor Juhos <juhosg@openwrt.org>
|
|
||||||
+ *
|
|
||||||
+ * This program is free software; you can redistribute it and/or modify it
|
|
||||||
+ * under the terms of the GNU General Public License version 2 as published by
|
|
||||||
+ * the Free Software Foundation.
|
|
||||||
+ *
|
|
||||||
+ */
|
|
||||||
+#include <linux/init.h>
|
|
||||||
+#include <linux/module.h>
|
|
||||||
+#include <linux/crypto.h>
|
|
||||||
+#include <linux/xz.h>
|
|
||||||
+#include <linux/interrupt.h>
|
|
||||||
+#include <linux/mm.h>
|
|
||||||
+#include <linux/net.h>
|
|
||||||
+
|
|
||||||
+struct xz_comp_ctx {
|
|
||||||
+ struct xz_dec *decomp_state;
|
|
||||||
+ struct xz_buf decomp_buf;
|
|
||||||
+};
|
|
||||||
+
|
|
||||||
+static int crypto_xz_decomp_init(struct xz_comp_ctx *ctx)
|
|
||||||
+{
|
|
||||||
+ ctx->decomp_state = xz_dec_init(XZ_SINGLE, 0);
|
|
||||||
+ if (!ctx->decomp_state)
|
|
||||||
+ return -ENOMEM;
|
|
||||||
+
|
|
||||||
+ return 0;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static void crypto_xz_decomp_exit(struct xz_comp_ctx *ctx)
|
|
||||||
+{
|
|
||||||
+ xz_dec_end(ctx->decomp_state);
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static int crypto_xz_init(struct crypto_tfm *tfm)
|
|
||||||
+{
|
|
||||||
+ struct xz_comp_ctx *ctx = crypto_tfm_ctx(tfm);
|
|
||||||
+
|
|
||||||
+ return crypto_xz_decomp_init(ctx);
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static void crypto_xz_exit(struct crypto_tfm *tfm)
|
|
||||||
+{
|
|
||||||
+ struct xz_comp_ctx *ctx = crypto_tfm_ctx(tfm);
|
|
||||||
+
|
|
||||||
+ crypto_xz_decomp_exit(ctx);
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static int crypto_xz_compress(struct crypto_tfm *tfm, const u8 *src,
|
|
||||||
+ unsigned int slen, u8 *dst, unsigned int *dlen)
|
|
||||||
+{
|
|
||||||
+ return -EOPNOTSUPP;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static int crypto_xz_decompress(struct crypto_tfm *tfm, const u8 *src,
|
|
||||||
+ unsigned int slen, u8 *dst, unsigned int *dlen)
|
|
||||||
+{
|
|
||||||
+ struct xz_comp_ctx *dctx = crypto_tfm_ctx(tfm);
|
|
||||||
+ struct xz_buf *xz_buf = &dctx->decomp_buf;
|
|
||||||
+ int ret;
|
|
||||||
+
|
|
||||||
+ memset(xz_buf, '\0', sizeof(struct xz_buf));
|
|
||||||
+
|
|
||||||
+ xz_buf->in = (u8 *) src;
|
|
||||||
+ xz_buf->in_pos = 0;
|
|
||||||
+ xz_buf->in_size = slen;
|
|
||||||
+ xz_buf->out = (u8 *) dst;
|
|
||||||
+ xz_buf->out_pos = 0;
|
|
||||||
+ xz_buf->out_size = *dlen;
|
|
||||||
+
|
|
||||||
+ ret = xz_dec_run(dctx->decomp_state, xz_buf);
|
|
||||||
+ if (ret != XZ_STREAM_END) {
|
|
||||||
+ ret = -EINVAL;
|
|
||||||
+ goto out;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ *dlen = xz_buf->out_pos;
|
|
||||||
+ ret = 0;
|
|
||||||
+
|
|
||||||
+out:
|
|
||||||
+ return ret;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static struct crypto_alg crypto_xz_alg = {
|
|
||||||
+ .cra_name = "xz",
|
|
||||||
+ .cra_flags = CRYPTO_ALG_TYPE_COMPRESS,
|
|
||||||
+ .cra_ctxsize = sizeof(struct xz_comp_ctx),
|
|
||||||
+ .cra_module = THIS_MODULE,
|
|
||||||
+ .cra_list = LIST_HEAD_INIT(crypto_xz_alg.cra_list),
|
|
||||||
+ .cra_init = crypto_xz_init,
|
|
||||||
+ .cra_exit = crypto_xz_exit,
|
|
||||||
+ .cra_u = { .compress = {
|
|
||||||
+ .coa_compress = crypto_xz_compress,
|
|
||||||
+ .coa_decompress = crypto_xz_decompress } }
|
|
||||||
+};
|
|
||||||
+
|
|
||||||
+static int __init crypto_xz_mod_init(void)
|
|
||||||
+{
|
|
||||||
+ return crypto_register_alg(&crypto_xz_alg);
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static void __exit crypto_xz_mod_exit(void)
|
|
||||||
+{
|
|
||||||
+ crypto_unregister_alg(&crypto_xz_alg);
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+module_init(crypto_xz_mod_init);
|
|
||||||
+module_exit(crypto_xz_mod_exit);
|
|
||||||
+
|
|
||||||
+MODULE_LICENSE("GPL v2");
|
|
||||||
+MODULE_DESCRIPTION("Crypto XZ decompression support");
|
|
||||||
+MODULE_AUTHOR("Gabor Juhos <juhosg@openwrt.org>");
|
|
|
@ -1,92 +0,0 @@
|
||||||
--- a/fs/ubifs/Kconfig
|
|
||||||
+++ b/fs/ubifs/Kconfig
|
|
||||||
@@ -5,8 +5,10 @@ config UBIFS_FS
|
|
||||||
select CRYPTO if UBIFS_FS_ADVANCED_COMPR
|
|
||||||
select CRYPTO if UBIFS_FS_LZO
|
|
||||||
select CRYPTO if UBIFS_FS_ZLIB
|
|
||||||
+ select CRYPTO if UBIFS_FS_XZ
|
|
||||||
select CRYPTO_LZO if UBIFS_FS_LZO
|
|
||||||
select CRYPTO_DEFLATE if UBIFS_FS_ZLIB
|
|
||||||
+ select CRYPTO_XZ if UBIFS_FS_XZ
|
|
||||||
depends on MTD_UBI
|
|
||||||
help
|
|
||||||
UBIFS is a file system for flash devices which works on top of UBI.
|
|
||||||
@@ -35,3 +37,12 @@ config UBIFS_FS_ZLIB
|
|
||||||
default y
|
|
||||||
help
|
|
||||||
Zlib compresses better than LZO but it is slower. Say 'Y' if unsure.
|
|
||||||
+
|
|
||||||
+config UBIFS_FS_XZ
|
|
||||||
+ bool "XZ decompression support" if UBIFS_FS_ADVANCED_COMPR
|
|
||||||
+ depends on UBIFS_FS
|
|
||||||
+ default y
|
|
||||||
+ help
|
|
||||||
+ XZ compresses better the ZLIB but it is slower..
|
|
||||||
+ Say 'Y' if unsure.
|
|
||||||
+
|
|
||||||
--- a/fs/ubifs/compress.c
|
|
||||||
+++ b/fs/ubifs/compress.c
|
|
||||||
@@ -71,6 +71,24 @@ static struct ubifs_compressor zlib_comp
|
|
||||||
};
|
|
||||||
#endif
|
|
||||||
|
|
||||||
+#ifdef CONFIG_UBIFS_FS_XZ
|
|
||||||
+static DEFINE_MUTEX(xz_enc_mutex);
|
|
||||||
+static DEFINE_MUTEX(xz_dec_mutex);
|
|
||||||
+
|
|
||||||
+static struct ubifs_compressor xz_compr = {
|
|
||||||
+ .compr_type = UBIFS_COMPR_XZ,
|
|
||||||
+ .comp_mutex = &xz_enc_mutex,
|
|
||||||
+ .decomp_mutex = &xz_dec_mutex,
|
|
||||||
+ .name = "xz",
|
|
||||||
+ .capi_name = "xz",
|
|
||||||
+};
|
|
||||||
+#else
|
|
||||||
+static struct ubifs_compressor xz_compr = {
|
|
||||||
+ .compr_type = UBIFS_COMPR_XZ,
|
|
||||||
+ .name = "xz",
|
|
||||||
+};
|
|
||||||
+#endif
|
|
||||||
+
|
|
||||||
/* All UBIFS compressors */
|
|
||||||
struct ubifs_compressor *ubifs_compressors[UBIFS_COMPR_TYPES_CNT];
|
|
||||||
|
|
||||||
@@ -232,9 +250,15 @@ int __init ubifs_compressors_init(void)
|
|
||||||
if (err)
|
|
||||||
goto out_lzo;
|
|
||||||
|
|
||||||
+ err = compr_init(&xz_compr);
|
|
||||||
+ if (err)
|
|
||||||
+ goto out_zlib;
|
|
||||||
+
|
|
||||||
ubifs_compressors[UBIFS_COMPR_NONE] = &none_compr;
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
+out_zlib:
|
|
||||||
+ compr_exit(&zlib_compr);
|
|
||||||
out_lzo:
|
|
||||||
compr_exit(&lzo_compr);
|
|
||||||
return err;
|
|
||||||
@@ -247,4 +271,5 @@ void ubifs_compressors_exit(void)
|
|
||||||
{
|
|
||||||
compr_exit(&lzo_compr);
|
|
||||||
compr_exit(&zlib_compr);
|
|
||||||
+ compr_exit(&xz_compr);
|
|
||||||
}
|
|
||||||
--- a/fs/ubifs/ubifs-media.h
|
|
||||||
+++ b/fs/ubifs/ubifs-media.h
|
|
||||||
@@ -332,12 +332,14 @@ enum {
|
|
||||||
* UBIFS_COMPR_NONE: no compression
|
|
||||||
* UBIFS_COMPR_LZO: LZO compression
|
|
||||||
* UBIFS_COMPR_ZLIB: ZLIB compression
|
|
||||||
+ * UBIFS_COMPR_XZ: XZ compression
|
|
||||||
* UBIFS_COMPR_TYPES_CNT: count of supported compression types
|
|
||||||
*/
|
|
||||||
enum {
|
|
||||||
UBIFS_COMPR_NONE,
|
|
||||||
UBIFS_COMPR_LZO,
|
|
||||||
UBIFS_COMPR_ZLIB,
|
|
||||||
+ UBIFS_COMPR_XZ,
|
|
||||||
UBIFS_COMPR_TYPES_CNT,
|
|
||||||
};
|
|
||||||
|
|
|
@ -1,65 +0,0 @@
|
||||||
--- a/fs/ubifs/file.c
|
|
||||||
+++ b/fs/ubifs/file.c
|
|
||||||
@@ -1574,6 +1574,10 @@ const struct inode_operations ubifs_syml
|
|
||||||
.follow_link = ubifs_follow_link,
|
|
||||||
.setattr = ubifs_setattr,
|
|
||||||
.getattr = ubifs_getattr,
|
|
||||||
+ .setxattr = ubifs_setxattr,
|
|
||||||
+ .getxattr = ubifs_getxattr,
|
|
||||||
+ .listxattr = ubifs_listxattr,
|
|
||||||
+ .removexattr = ubifs_removexattr,
|
|
||||||
};
|
|
||||||
|
|
||||||
const struct file_operations ubifs_file_operations = {
|
|
||||||
--- a/fs/ubifs/journal.c
|
|
||||||
+++ b/fs/ubifs/journal.c
|
|
||||||
@@ -553,7 +553,8 @@ int ubifs_jnl_update(struct ubifs_info *
|
|
||||||
|
|
||||||
dbg_jnl("ino %lu, dent '%.*s', data len %d in dir ino %lu",
|
|
||||||
inode->i_ino, nm->len, nm->name, ui->data_len, dir->i_ino);
|
|
||||||
- ubifs_assert(dir_ui->data_len == 0);
|
|
||||||
+ if (!xent)
|
|
||||||
+ ubifs_assert(dir_ui->data_len == 0);
|
|
||||||
ubifs_assert(mutex_is_locked(&dir_ui->ui_mutex));
|
|
||||||
|
|
||||||
dlen = UBIFS_DENT_NODE_SZ + nm->len + 1;
|
|
||||||
@@ -573,6 +574,13 @@ int ubifs_jnl_update(struct ubifs_info *
|
|
||||||
aligned_dlen = ALIGN(dlen, 8);
|
|
||||||
aligned_ilen = ALIGN(ilen, 8);
|
|
||||||
len = aligned_dlen + aligned_ilen + UBIFS_INO_NODE_SZ;
|
|
||||||
+ if (xent) {
|
|
||||||
+ /*
|
|
||||||
+ * Make sure to account for dir_ui->data_len in
|
|
||||||
+ * length calculation in case there is extended attribute.
|
|
||||||
+ */
|
|
||||||
+ len += dir_ui->data_len;
|
|
||||||
+ }
|
|
||||||
dent = kmalloc(len, GFP_NOFS);
|
|
||||||
if (!dent)
|
|
||||||
return -ENOMEM;
|
|
||||||
@@ -649,7 +657,8 @@ int ubifs_jnl_update(struct ubifs_info *
|
|
||||||
|
|
||||||
ino_key_init(c, &ino_key, dir->i_ino);
|
|
||||||
ino_offs += aligned_ilen;
|
|
||||||
- err = ubifs_tnc_add(c, &ino_key, lnum, ino_offs, UBIFS_INO_NODE_SZ);
|
|
||||||
+ err = ubifs_tnc_add(c, &ino_key, lnum, ino_offs,
|
|
||||||
+ UBIFS_INO_NODE_SZ + dir_ui->data_len);
|
|
||||||
if (err)
|
|
||||||
goto out_ro;
|
|
||||||
|
|
||||||
--- a/fs/ubifs/xattr.c
|
|
||||||
+++ b/fs/ubifs/xattr.c
|
|
||||||
@@ -209,12 +209,12 @@ static int change_xattr(struct ubifs_inf
|
|
||||||
goto out_free;
|
|
||||||
}
|
|
||||||
inode->i_size = ui->ui_size = size;
|
|
||||||
- ui->data_len = size;
|
|
||||||
|
|
||||||
mutex_lock(&host_ui->ui_mutex);
|
|
||||||
host->i_ctime = ubifs_current_time(host);
|
|
||||||
host_ui->xattr_size -= CALC_XATTR_BYTES(ui->data_len);
|
|
||||||
host_ui->xattr_size += CALC_XATTR_BYTES(size);
|
|
||||||
+ ui->data_len = size;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* It is important to write the host inode after the xattr inode
|
|
|
@ -1,29 +0,0 @@
|
||||||
--- a/fs/ubifs/sb.c
|
|
||||||
+++ b/fs/ubifs/sb.c
|
|
||||||
@@ -63,6 +63,17 @@
|
|
||||||
/* Default time granularity in nanoseconds */
|
|
||||||
#define DEFAULT_TIME_GRAN 1000000000
|
|
||||||
|
|
||||||
+static int get_default_compressor(void)
|
|
||||||
+{
|
|
||||||
+ if (ubifs_compr_present(UBIFS_COMPR_LZO))
|
|
||||||
+ return UBIFS_COMPR_LZO;
|
|
||||||
+
|
|
||||||
+ if (ubifs_compr_present(UBIFS_COMPR_ZLIB))
|
|
||||||
+ return UBIFS_COMPR_ZLIB;
|
|
||||||
+
|
|
||||||
+ return UBIFS_COMPR_NONE;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
/**
|
|
||||||
* create_default_filesystem - format empty UBI volume.
|
|
||||||
* @c: UBIFS file-system description object
|
|
||||||
@@ -183,7 +194,7 @@ static int create_default_filesystem(str
|
|
||||||
if (c->mount_opts.override_compr)
|
|
||||||
sup->default_compr = cpu_to_le16(c->mount_opts.compr_type);
|
|
||||||
else
|
|
||||||
- sup->default_compr = cpu_to_le16(UBIFS_COMPR_LZO);
|
|
||||||
+ sup->default_compr = cpu_to_le16(get_default_compressor());
|
|
||||||
|
|
||||||
generate_random_uuid(sup->uuid);
|
|
||||||
|
|
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
|
|
||||||
@@ -987,6 +987,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
|
|
||||||
@@ -1183,26 +1204,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,86 +0,0 @@
|
||||||
--- a/net/netfilter/nf_conntrack_standalone.c
|
|
||||||
+++ b/net/netfilter/nf_conntrack_standalone.c
|
|
||||||
@@ -16,6 +16,7 @@
|
|
||||||
#include <linux/percpu.h>
|
|
||||||
#include <linux/netdevice.h>
|
|
||||||
#include <linux/security.h>
|
|
||||||
+#include <linux/inet.h>
|
|
||||||
#include <net/net_namespace.h>
|
|
||||||
#ifdef CONFIG_SYSCTL
|
|
||||||
#include <linux/sysctl.h>
|
|
||||||
@@ -267,10 +268,66 @@ static int ct_open(struct inode *inode,
|
|
||||||
sizeof(struct ct_iter_state));
|
|
||||||
}
|
|
||||||
|
|
||||||
+struct kill_request {
|
|
||||||
+ u16 family;
|
|
||||||
+ union nf_inet_addr addr;
|
|
||||||
+};
|
|
||||||
+
|
|
||||||
+static int kill_matching(struct nf_conn *i, void *data)
|
|
||||||
+{
|
|
||||||
+ struct kill_request *kr = data;
|
|
||||||
+ struct nf_conntrack_tuple *t1 = &i->tuplehash[IP_CT_DIR_ORIGINAL].tuple;
|
|
||||||
+ struct nf_conntrack_tuple *t2 = &i->tuplehash[IP_CT_DIR_REPLY].tuple;
|
|
||||||
+
|
|
||||||
+ if (!kr->family)
|
|
||||||
+ return 1;
|
|
||||||
+
|
|
||||||
+ if (t1->src.l3num != kr->family)
|
|
||||||
+ return 0;
|
|
||||||
+
|
|
||||||
+ return (nf_inet_addr_cmp(&kr->addr, &t1->src.u3) ||
|
|
||||||
+ nf_inet_addr_cmp(&kr->addr, &t1->dst.u3) ||
|
|
||||||
+ nf_inet_addr_cmp(&kr->addr, &t2->src.u3) ||
|
|
||||||
+ nf_inet_addr_cmp(&kr->addr, &t2->dst.u3));
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static ssize_t ct_file_write(struct file *file, const char __user *buf,
|
|
||||||
+ size_t count, loff_t *ppos)
|
|
||||||
+{
|
|
||||||
+ struct seq_file *seq = file->private_data;
|
|
||||||
+ struct net *net = seq_file_net(seq);
|
|
||||||
+ struct kill_request kr = { };
|
|
||||||
+ char req[INET6_ADDRSTRLEN] = { };
|
|
||||||
+
|
|
||||||
+ if (count == 0)
|
|
||||||
+ return 0;
|
|
||||||
+
|
|
||||||
+ if (count >= INET6_ADDRSTRLEN)
|
|
||||||
+ count = INET6_ADDRSTRLEN - 1;
|
|
||||||
+
|
|
||||||
+ if (copy_from_user(req, buf, count))
|
|
||||||
+ return -EFAULT;
|
|
||||||
+
|
|
||||||
+ if (strnchr(req, count, ':')) {
|
|
||||||
+ kr.family = AF_INET6;
|
|
||||||
+ if (!in6_pton(req, count, (void *)&kr.addr, '\n', NULL))
|
|
||||||
+ return -EINVAL;
|
|
||||||
+ } else if (strnchr(req, count, '.')) {
|
|
||||||
+ kr.family = AF_INET;
|
|
||||||
+ if (!in4_pton(req, count, (void *)&kr.addr, '\n', NULL))
|
|
||||||
+ return -EINVAL;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ nf_ct_iterate_cleanup(net, kill_matching, &kr);
|
|
||||||
+
|
|
||||||
+ return count;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
static const struct file_operations ct_file_ops = {
|
|
||||||
.owner = THIS_MODULE,
|
|
||||||
.open = ct_open,
|
|
||||||
.read = seq_read,
|
|
||||||
+ .write = ct_file_write,
|
|
||||||
.llseek = seq_lseek,
|
|
||||||
.release = seq_release_net,
|
|
||||||
};
|
|
||||||
@@ -372,7 +429,7 @@ static int nf_conntrack_standalone_init_
|
|
||||||
{
|
|
||||||
struct proc_dir_entry *pde;
|
|
||||||
|
|
||||||
- pde = proc_net_fops_create(net, "nf_conntrack", 0440, &ct_file_ops);
|
|
||||||
+ pde = proc_net_fops_create(net, "nf_conntrack", 0660, &ct_file_ops);
|
|
||||||
if (!pde)
|
|
||||||
goto out_nf_conntrack;
|
|
||||||
|
|
|
@ -1,93 +0,0 @@
|
||||||
--- a/include/uapi/linux/netfilter_ipv4/ip_tables.h
|
|
||||||
+++ b/include/uapi/linux/netfilter_ipv4/ip_tables.h
|
|
||||||
@@ -87,6 +87,7 @@ struct ipt_ip {
|
|
||||||
#define IPT_F_FRAG 0x01 /* Set if rule is a fragment rule */
|
|
||||||
#define IPT_F_GOTO 0x02 /* Set if jump is a goto */
|
|
||||||
#define IPT_F_MASK 0x03 /* All possible flag bits mask. */
|
|
||||||
+#define IPT_F_NO_DEF_MATCH 0x80 /* Internal: no default match rules present */
|
|
||||||
|
|
||||||
/* Values for "inv" field in struct ipt_ip. */
|
|
||||||
#define IPT_INV_VIA_IN 0x01 /* Invert the sense of IN IFACE. */
|
|
||||||
--- a/net/ipv4/netfilter/ip_tables.c
|
|
||||||
+++ b/net/ipv4/netfilter/ip_tables.c
|
|
||||||
@@ -81,6 +81,9 @@ ip_packet_match(const struct iphdr *ip,
|
|
||||||
|
|
||||||
#define FWINV(bool, invflg) ((bool) ^ !!(ipinfo->invflags & (invflg)))
|
|
||||||
|
|
||||||
+ if (ipinfo->flags & IPT_F_NO_DEF_MATCH)
|
|
||||||
+ return true;
|
|
||||||
+
|
|
||||||
if (FWINV((ip->saddr&ipinfo->smsk.s_addr) != ipinfo->src.s_addr,
|
|
||||||
IPT_INV_SRCIP) ||
|
|
||||||
FWINV((ip->daddr&ipinfo->dmsk.s_addr) != ipinfo->dst.s_addr,
|
|
||||||
@@ -134,6 +137,29 @@ ip_packet_match(const struct iphdr *ip,
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
+static void
|
|
||||||
+ip_checkdefault(struct ipt_ip *ip)
|
|
||||||
+{
|
|
||||||
+ static const char iface_mask[IFNAMSIZ] = {};
|
|
||||||
+
|
|
||||||
+ if (ip->invflags || ip->flags & IPT_F_FRAG)
|
|
||||||
+ return;
|
|
||||||
+
|
|
||||||
+ if (memcmp(ip->iniface_mask, iface_mask, IFNAMSIZ) != 0)
|
|
||||||
+ return;
|
|
||||||
+
|
|
||||||
+ if (memcmp(ip->outiface_mask, iface_mask, IFNAMSIZ) != 0)
|
|
||||||
+ return;
|
|
||||||
+
|
|
||||||
+ if (ip->smsk.s_addr || ip->dmsk.s_addr)
|
|
||||||
+ return;
|
|
||||||
+
|
|
||||||
+ if (ip->proto)
|
|
||||||
+ return;
|
|
||||||
+
|
|
||||||
+ ip->flags |= IPT_F_NO_DEF_MATCH;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
static bool
|
|
||||||
ip_checkentry(const struct ipt_ip *ip)
|
|
||||||
{
|
|
||||||
@@ -560,7 +586,7 @@ static void cleanup_match(struct xt_entr
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
-check_entry(const struct ipt_entry *e, const char *name)
|
|
||||||
+check_entry(struct ipt_entry *e, const char *name)
|
|
||||||
{
|
|
||||||
const struct xt_entry_target *t;
|
|
||||||
|
|
||||||
@@ -569,6 +595,8 @@ check_entry(const struct ipt_entry *e, c
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
|
||||||
|
|
||||||
+ ip_checkdefault(&e->ip);
|
|
||||||
+
|
|
||||||
if (e->target_offset + sizeof(struct xt_entry_target) >
|
|
||||||
e->next_offset)
|
|
||||||
return -EINVAL;
|
|
||||||
@@ -930,6 +958,7 @@ copy_entries_to_user(unsigned int total_
|
|
||||||
const struct xt_table_info *private = table->private;
|
|
||||||
int ret = 0;
|
|
||||||
const void *loc_cpu_entry;
|
|
||||||
+ u8 flags;
|
|
||||||
|
|
||||||
counters = alloc_counters(table);
|
|
||||||
if (IS_ERR(counters))
|
|
||||||
@@ -960,6 +989,14 @@ copy_entries_to_user(unsigned int total_
|
|
||||||
ret = -EFAULT;
|
|
||||||
goto free_counters;
|
|
||||||
}
|
|
||||||
+
|
|
||||||
+ flags = e->ip.flags & IPT_F_MASK;
|
|
||||||
+ if (copy_to_user(userptr + off
|
|
||||||
+ + offsetof(struct ipt_entry, ip.flags),
|
|
||||||
+ &flags, sizeof(flags)) != 0) {
|
|
||||||
+ ret = -EFAULT;
|
|
||||||
+ goto free_counters;
|
|
||||||
+ }
|
|
||||||
|
|
||||||
for (i = sizeof(struct ipt_entry);
|
|
||||||
i < e->target_offset;
|
|
|
@ -1,81 +0,0 @@
|
||||||
--- a/net/ipv4/netfilter/ip_tables.c
|
|
||||||
+++ b/net/ipv4/netfilter/ip_tables.c
|
|
||||||
@@ -309,6 +309,33 @@ struct ipt_entry *ipt_next_entry(const s
|
|
||||||
return (void *)entry + entry->next_offset;
|
|
||||||
}
|
|
||||||
|
|
||||||
+static bool
|
|
||||||
+ipt_handle_default_rule(struct ipt_entry *e, unsigned int *verdict)
|
|
||||||
+{
|
|
||||||
+ struct xt_entry_target *t;
|
|
||||||
+ struct xt_standard_target *st;
|
|
||||||
+
|
|
||||||
+ if (e->target_offset != sizeof(struct ipt_entry))
|
|
||||||
+ return false;
|
|
||||||
+
|
|
||||||
+ if (!(e->ip.flags & IPT_F_NO_DEF_MATCH))
|
|
||||||
+ return false;
|
|
||||||
+
|
|
||||||
+ t = ipt_get_target(e);
|
|
||||||
+ if (t->u.kernel.target->target)
|
|
||||||
+ return false;
|
|
||||||
+
|
|
||||||
+ st = (struct xt_standard_target *) t;
|
|
||||||
+ if (st->verdict == XT_RETURN)
|
|
||||||
+ return false;
|
|
||||||
+
|
|
||||||
+ if (st->verdict >= 0)
|
|
||||||
+ return false;
|
|
||||||
+
|
|
||||||
+ *verdict = (unsigned)(-st->verdict) - 1;
|
|
||||||
+ return true;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
/* Returns one of the generic firewall policies, like NF_ACCEPT. */
|
|
||||||
unsigned int
|
|
||||||
ipt_do_table(struct sk_buff *skb,
|
|
||||||
@@ -333,6 +360,25 @@ ipt_do_table(struct sk_buff *skb,
|
|
||||||
ip = ip_hdr(skb);
|
|
||||||
indev = in ? in->name : nulldevname;
|
|
||||||
outdev = out ? out->name : nulldevname;
|
|
||||||
+
|
|
||||||
+ IP_NF_ASSERT(table->valid_hooks & (1 << hook));
|
|
||||||
+ local_bh_disable();
|
|
||||||
+ addend = xt_write_recseq_begin();
|
|
||||||
+ private = table->private;
|
|
||||||
+ cpu = smp_processor_id();
|
|
||||||
+ table_base = private->entries[cpu];
|
|
||||||
+ jumpstack = (struct ipt_entry **)private->jumpstack[cpu];
|
|
||||||
+ stackptr = per_cpu_ptr(private->stackptr, cpu);
|
|
||||||
+ origptr = *stackptr;
|
|
||||||
+
|
|
||||||
+ e = get_entry(table_base, private->hook_entry[hook]);
|
|
||||||
+ if (ipt_handle_default_rule(e, &verdict)) {
|
|
||||||
+ ADD_COUNTER(e->counters, skb->len, 1);
|
|
||||||
+ xt_write_recseq_end(addend);
|
|
||||||
+ local_bh_enable();
|
|
||||||
+ return verdict;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
/* We handle fragments by dealing with the first fragment as
|
|
||||||
* if it was a normal packet. All other fragments are treated
|
|
||||||
* normally, except that they will NEVER match rules that ask
|
|
||||||
@@ -347,18 +393,6 @@ ipt_do_table(struct sk_buff *skb,
|
|
||||||
acpar.family = NFPROTO_IPV4;
|
|
||||||
acpar.hooknum = hook;
|
|
||||||
|
|
||||||
- IP_NF_ASSERT(table->valid_hooks & (1 << hook));
|
|
||||||
- local_bh_disable();
|
|
||||||
- addend = xt_write_recseq_begin();
|
|
||||||
- private = table->private;
|
|
||||||
- cpu = smp_processor_id();
|
|
||||||
- table_base = private->entries[cpu];
|
|
||||||
- jumpstack = (struct ipt_entry **)private->jumpstack[cpu];
|
|
||||||
- stackptr = per_cpu_ptr(private->stackptr, cpu);
|
|
||||||
- origptr = *stackptr;
|
|
||||||
-
|
|
||||||
- e = get_entry(table_base, private->hook_entry[hook]);
|
|
||||||
-
|
|
||||||
pr_debug("Entering %s(hook %u); sp at %u (UF %p)\n",
|
|
||||||
table->name, hook, origptr,
|
|
||||||
get_entry(table_base, private->underflow[hook]));
|
|
|
@ -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. */
|
|
||||||
@@ -526,6 +529,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.
|
|
||||||
*/
|
|
||||||
@@ -1438,6 +1444,13 @@ static struct ctl_table tcp_sysctl_table
|
|
||||||
.mode = 0644,
|
|
||||||
.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,
|
|
||||||
+ },
|
|
||||||
{ }
|
|
||||||
};
|
|
||||||
|
|
|
@ -1,95 +0,0 @@
|
||||||
--- a/include/uapi/linux/netfilter/Kbuild
|
|
||||||
+++ b/include/uapi/linux/netfilter/Kbuild
|
|
||||||
@@ -49,6 +49,7 @@ header-y += xt_ecn.h
|
|
||||||
header-y += xt_esp.h
|
|
||||||
header-y += xt_hashlimit.h
|
|
||||||
header-y += xt_helper.h
|
|
||||||
+header-y += xt_id.h
|
|
||||||
header-y += xt_iprange.h
|
|
||||||
header-y += xt_ipvs.h
|
|
||||||
header-y += xt_layer7.h
|
|
||||||
--- /dev/null
|
|
||||||
+++ b/include/uapi/linux/netfilter/xt_id.h
|
|
||||||
@@ -0,0 +1,8 @@
|
|
||||||
+#ifndef _XT_ID_H
|
|
||||||
+#define _XT_ID_H
|
|
||||||
+
|
|
||||||
+struct xt_id_info {
|
|
||||||
+ u32 id;
|
|
||||||
+};
|
|
||||||
+
|
|
||||||
+#endif /* XT_ID_H */
|
|
||||||
--- a/net/netfilter/Kconfig
|
|
||||||
+++ b/net/netfilter/Kconfig
|
|
||||||
@@ -967,6 +967,13 @@ config NETFILTER_XT_MATCH_HL
|
|
||||||
in the IPv6 header, or the time-to-live field in the IPv4
|
|
||||||
header of the packet.
|
|
||||||
|
|
||||||
+config NETFILTER_XT_MATCH_ID
|
|
||||||
+ tristate '"id" match support'
|
|
||||||
+ depends on NETFILTER_ADVANCED
|
|
||||||
+ ---help---
|
|
||||||
+ This option adds a `id' dummy-match, which allows you to put
|
|
||||||
+ numeric IDs into your iptables ruleset.
|
|
||||||
+
|
|
||||||
config NETFILTER_XT_MATCH_IPRANGE
|
|
||||||
tristate '"iprange" address range match support'
|
|
||||||
depends on NETFILTER_ADVANCED
|
|
||||||
--- a/net/netfilter/Makefile
|
|
||||||
+++ b/net/netfilter/Makefile
|
|
||||||
@@ -112,6 +112,7 @@ obj-$(CONFIG_NETFILTER_XT_MATCH_ESP) +=
|
|
||||||
obj-$(CONFIG_NETFILTER_XT_MATCH_HASHLIMIT) += xt_hashlimit.o
|
|
||||||
obj-$(CONFIG_NETFILTER_XT_MATCH_HELPER) += xt_helper.o
|
|
||||||
obj-$(CONFIG_NETFILTER_XT_MATCH_HL) += xt_hl.o
|
|
||||||
+obj-$(CONFIG_NETFILTER_XT_MATCH_ID) += xt_id.o
|
|
||||||
obj-$(CONFIG_NETFILTER_XT_MATCH_IPRANGE) += xt_iprange.o
|
|
||||||
obj-$(CONFIG_NETFILTER_XT_MATCH_IPVS) += xt_ipvs.o
|
|
||||||
obj-$(CONFIG_NETFILTER_XT_MATCH_LENGTH) += xt_length.o
|
|
||||||
--- /dev/null
|
|
||||||
+++ b/net/netfilter/xt_id.c
|
|
||||||
@@ -0,0 +1,45 @@
|
|
||||||
+/*
|
|
||||||
+ * Implements a dummy match to allow attaching IDs to rules
|
|
||||||
+ *
|
|
||||||
+ * 2014-08-01 Jo-Philipp Wich <jow@openwrt.org>
|
|
||||||
+ */
|
|
||||||
+
|
|
||||||
+#include <linux/module.h>
|
|
||||||
+#include <linux/skbuff.h>
|
|
||||||
+#include <linux/netfilter/x_tables.h>
|
|
||||||
+#include <linux/netfilter/xt_id.h>
|
|
||||||
+
|
|
||||||
+MODULE_AUTHOR("Jo-Philipp Wich <jow@openwrt.org>");
|
|
||||||
+MODULE_DESCRIPTION("Xtables: No-op match which can be tagged with a 32bit ID");
|
|
||||||
+MODULE_LICENSE("GPL");
|
|
||||||
+MODULE_ALIAS("ipt_id");
|
|
||||||
+MODULE_ALIAS("ip6t_id");
|
|
||||||
+
|
|
||||||
+static bool
|
|
||||||
+id_mt(const struct sk_buff *skb, struct xt_action_param *par)
|
|
||||||
+{
|
|
||||||
+ /* We always match */
|
|
||||||
+ return true;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static struct xt_match id_mt_reg __read_mostly = {
|
|
||||||
+ .name = "id",
|
|
||||||
+ .revision = 0,
|
|
||||||
+ .family = NFPROTO_UNSPEC,
|
|
||||||
+ .match = id_mt,
|
|
||||||
+ .matchsize = sizeof(struct xt_id_info),
|
|
||||||
+ .me = THIS_MODULE,
|
|
||||||
+};
|
|
||||||
+
|
|
||||||
+static int __init id_mt_init(void)
|
|
||||||
+{
|
|
||||||
+ return xt_register_match(&id_mt_reg);
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static void __exit id_mt_exit(void)
|
|
||||||
+{
|
|
||||||
+ xt_unregister_match(&id_mt_reg);
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+module_init(id_mt_init);
|
|
||||||
+module_exit(id_mt_exit);
|
|
|
@ -1,791 +0,0 @@
|
||||||
--- a/include/uapi/linux/pkt_sched.h
|
|
||||||
+++ b/include/uapi/linux/pkt_sched.h
|
|
||||||
@@ -214,6 +214,33 @@ struct tc_sfq_xstats {
|
|
||||||
__s32 allot;
|
|
||||||
};
|
|
||||||
|
|
||||||
+/* 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 <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;
|
|
||||||
+
|
|
||||||
+ if (nla_put(skb, TCA_OPTIONS, sizeof(opt), &opt))
|
|
||||||
+ goto nla_put_failure;
|
|
||||||
+
|
|
||||||
+ 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, const 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
|
|
||||||
@@ -670,6 +670,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,134 +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/uapi/linux/if_packet.h
|
|
||||||
+++ b/include/uapi/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 */
|
|
||||||
|
|
||||||
@@ -51,6 +53,7 @@ struct sockaddr_ll {
|
|
||||||
#define PACKET_TIMESTAMP 17
|
|
||||||
#define PACKET_FANOUT 18
|
|
||||||
#define PACKET_TX_HAS_OFF 19
|
|
||||||
+#define PACKET_RECV_TYPE 20
|
|
||||||
|
|
||||||
#define PACKET_FANOUT_HASH 0
|
|
||||||
#define PACKET_FANOUT_LB 1
|
|
||||||
--- a/net/packet/af_packet.c
|
|
||||||
+++ b/net/packet/af_packet.c
|
|
||||||
@@ -1273,6 +1273,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
|
|
||||||
@@ -1280,6 +1281,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
|
|
||||||
@@ -1292,7 +1294,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)))
|
|
||||||
@@ -1498,12 +1500,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;
|
|
||||||
|
|
||||||
@@ -1622,12 +1624,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;
|
|
||||||
|
|
||||||
@@ -2539,6 +2541,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;
|
|
||||||
@@ -3152,6 +3155,16 @@ packet_setsockopt(struct socket *sock, i
|
|
||||||
po->tp_tx_has_off = !!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 & ~BIT(PACKET_LOOPBACK);
|
|
||||||
+ return 0;
|
|
||||||
+ }
|
|
||||||
default:
|
|
||||||
return -ENOPROTOOPT;
|
|
||||||
}
|
|
||||||
@@ -3206,6 +3219,13 @@ static int packet_getsockopt(struct sock
|
|
||||||
case PACKET_VNET_HDR:
|
|
||||||
val = po->has_vnet_hdr;
|
|
||||||
break;
|
|
||||||
+ case PACKET_RECV_TYPE:
|
|
||||||
+ if (len > sizeof(unsigned int))
|
|
||||||
+ len = sizeof(unsigned int);
|
|
||||||
+ val = po->pkt_type;
|
|
||||||
+
|
|
||||||
+ data = &val;
|
|
||||||
+ break;
|
|
||||||
case PACKET_VERSION:
|
|
||||||
val = po->tp_version;
|
|
||||||
break;
|
|
||||||
--- a/net/packet/internal.h
|
|
||||||
+++ b/net/packet/internal.h
|
|
||||||
@@ -112,6 +112,7 @@ struct packet_sock {
|
|
||||||
unsigned int tp_tx_has_off:1;
|
|
||||||
unsigned int tp_tstamp;
|
|
||||||
struct packet_type prot_hook ____cacheline_aligned_in_smp;
|
|
||||||
+ unsigned int pkt_type;
|
|
||||||
};
|
|
||||||
|
|
||||||
static struct packet_sock *pkt_sk(struct sock *sk)
|
|
|
@ -1,15 +0,0 @@
|
||||||
--- a/net/bridge/br_input.c
|
|
||||||
+++ b/net/bridge/br_input.c
|
|
||||||
@@ -75,7 +75,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
|
|
||||||
@@ -62,7 +62,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
|
|
||||||
@@ -139,6 +139,7 @@ struct net_bridge_port
|
|
||||||
#define BR_BPDU_GUARD 0x00000002
|
|
||||||
#define BR_ROOT_BLOCK 0x00000004
|
|
||||||
#define BR_MULTICAST_FAST_LEAVE 0x00000008
|
|
||||||
+#define BR_ISOLATE_MODE 0x00000010
|
|
||||||
|
|
||||||
#ifdef CONFIG_BRIDGE_IGMP_SNOOPING
|
|
||||||
u32 multicast_startup_queries_sent;
|
|
||||||
--- a/net/bridge/br_sysfs_if.c
|
|
||||||
+++ b/net/bridge/br_sysfs_if.c
|
|
||||||
@@ -159,6 +159,22 @@ BRPORT_ATTR_FLAG(hairpin_mode, BR_HAIRPI
|
|
||||||
BRPORT_ATTR_FLAG(bpdu_guard, BR_BPDU_GUARD);
|
|
||||||
BRPORT_ATTR_FLAG(root_block, BR_ROOT_BLOCK);
|
|
||||||
|
|
||||||
+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)
|
|
||||||
{
|
|
||||||
@@ -199,6 +215,7 @@ static const struct brport_attribute *br
|
|
||||||
&brport_attr_multicast_router,
|
|
||||||
&brport_attr_multicast_fast_leave,
|
|
||||||
#endif
|
|
||||||
+ &brport_attr_isolate_mode,
|
|
||||||
NULL
|
|
||||||
};
|
|
||||||
|
|
||||||
--- a/net/bridge/br_input.c
|
|
||||||
+++ b/net/bridge/br_input.c
|
|
||||||
@@ -95,7 +95,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
|
|
||||||
@@ -110,7 +110,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
|
|
||||||
@@ -165,7 +165,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;
|
|
||||||
@@ -173,6 +174,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;
|
|
||||||
@@ -196,14 +200,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,107 +0,0 @@
|
||||||
--- a/include/net/addrconf.h
|
|
||||||
+++ b/include/net/addrconf.h
|
|
||||||
@@ -92,6 +92,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,
|
|
||||||
+ const struct net_device *dev,
|
|
||||||
+ const struct in6_addr *daddr,
|
|
||||||
+ unsigned int prefs,
|
|
||||||
+ struct in6_addr *saddr);
|
|
||||||
+
|
|
||||||
static inline unsigned long addrconf_timeout_fixup(u32 timeout,
|
|
||||||
unsigned int 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
|
|
||||||
@@ -44,3 +44,4 @@ obj-y += addrconf_core.o exthdrs_core.o
|
|
||||||
obj-$(CONFIG_INET) += output_core.o protocol.o $(ipv6-offload)
|
|
||||||
|
|
||||||
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
|
|
||||||
@@ -1243,7 +1243,7 @@ out:
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
-int ipv6_dev_get_saddr(struct net *net, const struct net_device *dst_dev,
|
|
||||||
+static int __ipv6_dev_get_saddr(struct net *net, const struct net_device *dst_dev,
|
|
||||||
const struct in6_addr *daddr, unsigned int prefs,
|
|
||||||
struct in6_addr *saddr)
|
|
||||||
{
|
|
||||||
@@ -1368,7 +1368,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)
|
|
||||||
@@ -4968,6 +4967,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);
|
|
||||||
@@ -4986,6 +4988,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,33 @@
|
|
||||||
+/*
|
|
||||||
+ * 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 <linux/export.h>
|
|
||||||
+#include <net/ipv6.h>
|
|
||||||
+
|
|
||||||
+int (*ipv6_dev_get_saddr_hook)(struct net *net, const struct net_device *dev,
|
|
||||||
+ const struct in6_addr *daddr, unsigned int prefs,
|
|
||||||
+ struct in6_addr *saddr);
|
|
||||||
+
|
|
||||||
+EXPORT_SYMBOL(ipv6_dev_get_saddr_hook);
|
|
||||||
+
|
|
||||||
+int ipv6_dev_get_saddr(struct net *net, const struct net_device *dst_dev,
|
|
||||||
+ const struct in6_addr *daddr, unsigned int prefs,
|
|
||||||
+ struct in6_addr *saddr)
|
|
||||||
+{
|
|
||||||
+ int ret = -EADDRNOTAVAIL;
|
|
||||||
+ typeof(ipv6_dev_get_saddr_hook) dev_get_saddr;
|
|
||||||
+
|
|
||||||
+ rcu_read_lock();
|
|
||||||
+ dev_get_saddr = rcu_dereference(ipv6_dev_get_saddr_hook);
|
|
||||||
+
|
|
||||||
+ if (dev_get_saddr)
|
|
||||||
+ ret = dev_get_saddr(net, dst_dev, daddr, prefs, saddr);
|
|
||||||
+
|
|
||||||
+ rcu_read_unlock();
|
|
||||||
+ return ret;
|
|
||||||
+}
|
|
||||||
+EXPORT_SYMBOL(ipv6_dev_get_saddr);
|
|
||||||
+
|
|
|
@ -1,146 +0,0 @@
|
||||||
--- a/net/bridge/br_forward.c
|
|
||||||
+++ b/net/bridge/br_forward.c
|
|
||||||
@@ -56,7 +56,7 @@ int br_dev_queue_push_xmit(struct sk_buf
|
|
||||||
|
|
||||||
int br_forward_finish(struct sk_buff *skb)
|
|
||||||
{
|
|
||||||
- return NF_HOOK(NFPROTO_BRIDGE, NF_BR_POST_ROUTING, skb, NULL, skb->dev,
|
|
||||||
+ return BR_HOOK(NFPROTO_BRIDGE, NF_BR_POST_ROUTING, skb, NULL, skb->dev,
|
|
||||||
br_dev_queue_push_xmit);
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -75,7 +75,7 @@ static void __br_deliver(const struct ne
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
- NF_HOOK(NFPROTO_BRIDGE, NF_BR_LOCAL_OUT, skb, NULL, skb->dev,
|
|
||||||
+ BR_HOOK(NFPROTO_BRIDGE, NF_BR_LOCAL_OUT, skb, NULL, skb->dev,
|
|
||||||
br_forward_finish);
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -92,7 +92,7 @@ static void __br_forward(const struct ne
|
|
||||||
skb->dev = to->dev;
|
|
||||||
skb_forward_csum(skb);
|
|
||||||
|
|
||||||
- NF_HOOK(NFPROTO_BRIDGE, NF_BR_FORWARD, skb, indev, skb->dev,
|
|
||||||
+ BR_HOOK(NFPROTO_BRIDGE, NF_BR_FORWARD, skb, indev, skb->dev,
|
|
||||||
br_forward_finish);
|
|
||||||
}
|
|
||||||
|
|
||||||
--- a/net/bridge/br_input.c
|
|
||||||
+++ b/net/bridge/br_input.c
|
|
||||||
@@ -37,7 +37,7 @@ static int br_pass_frame_up(struct sk_bu
|
|
||||||
indev = skb->dev;
|
|
||||||
skb->dev = brdev;
|
|
||||||
|
|
||||||
- return NF_HOOK(NFPROTO_BRIDGE, NF_BR_LOCAL_IN, skb, indev, NULL,
|
|
||||||
+ return BR_HOOK(NFPROTO_BRIDGE, NF_BR_LOCAL_IN, skb, indev, NULL,
|
|
||||||
netif_receive_skb);
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -184,7 +184,7 @@ rx_handler_result_t br_handle_frame(stru
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Deliver packet to local host only */
|
|
||||||
- if (NF_HOOK(NFPROTO_BRIDGE, NF_BR_LOCAL_IN, skb, skb->dev,
|
|
||||||
+ if (BR_HOOK(NFPROTO_BRIDGE, NF_BR_LOCAL_IN, skb, skb->dev,
|
|
||||||
NULL, br_handle_local_finish)) {
|
|
||||||
return RX_HANDLER_CONSUMED; /* consumed by filter */
|
|
||||||
} else {
|
|
||||||
@@ -209,7 +209,7 @@ forward:
|
|
||||||
if (ether_addr_equal(p->br->dev->dev_addr, dest))
|
|
||||||
skb->pkt_type = PACKET_HOST;
|
|
||||||
|
|
||||||
- NF_HOOK(NFPROTO_BRIDGE, NF_BR_PRE_ROUTING, skb, skb->dev, NULL,
|
|
||||||
+ BR_HOOK(NFPROTO_BRIDGE, NF_BR_PRE_ROUTING, skb, skb->dev, NULL,
|
|
||||||
br_handle_frame_finish);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
--- a/net/bridge/br_multicast.c
|
|
||||||
+++ b/net/bridge/br_multicast.c
|
|
||||||
@@ -772,7 +772,7 @@ static void __br_multicast_send_query(st
|
|
||||||
if (port) {
|
|
||||||
__skb_push(skb, sizeof(struct ethhdr));
|
|
||||||
skb->dev = port->dev;
|
|
||||||
- NF_HOOK(NFPROTO_BRIDGE, NF_BR_LOCAL_OUT, skb, NULL, skb->dev,
|
|
||||||
+ BR_HOOK(NFPROTO_BRIDGE, NF_BR_LOCAL_OUT, skb, NULL, skb->dev,
|
|
||||||
dev_queue_xmit);
|
|
||||||
} else
|
|
||||||
netif_rx(skb);
|
|
||||||
--- a/net/bridge/br_netfilter.c
|
|
||||||
+++ b/net/bridge/br_netfilter.c
|
|
||||||
@@ -73,6 +73,15 @@ static int brnf_pass_vlan_indev __read_m
|
|
||||||
#define IS_ARP(skb) \
|
|
||||||
(!vlan_tx_tag_present(skb) && skb->protocol == htons(ETH_P_ARP))
|
|
||||||
|
|
||||||
+int brnf_call_ebtables __read_mostly = 0;
|
|
||||||
+EXPORT_SYMBOL_GPL(brnf_call_ebtables);
|
|
||||||
+
|
|
||||||
+bool br_netfilter_run_hooks(void)
|
|
||||||
+{
|
|
||||||
+ return brnf_call_iptables | brnf_call_ip6tables | brnf_call_arptables |
|
|
||||||
+ brnf_call_ebtables;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
static inline __be16 vlan_proto(const struct sk_buff *skb)
|
|
||||||
{
|
|
||||||
if (vlan_tx_tag_present(skb))
|
|
||||||
--- a/net/bridge/br_private.h
|
|
||||||
+++ b/net/bridge/br_private.h
|
|
||||||
@@ -537,15 +537,29 @@ static inline void br_mdb_uninit(void)
|
|
||||||
|
|
||||||
/* br_netfilter.c */
|
|
||||||
#ifdef CONFIG_BRIDGE_NETFILTER
|
|
||||||
+extern int brnf_call_ebtables;
|
|
||||||
extern int br_netfilter_init(void);
|
|
||||||
extern void br_netfilter_fini(void);
|
|
||||||
extern void br_netfilter_rtable_init(struct net_bridge *);
|
|
||||||
+extern bool br_netfilter_run_hooks(void);
|
|
||||||
#else
|
|
||||||
#define br_netfilter_init() (0)
|
|
||||||
#define br_netfilter_fini() do { } while(0)
|
|
||||||
#define br_netfilter_rtable_init(x)
|
|
||||||
+#define br_netfilter_run_hooks() false
|
|
||||||
#endif
|
|
||||||
|
|
||||||
+static inline int
|
|
||||||
+BR_HOOK(uint8_t pf, unsigned int hook, struct sk_buff *skb,
|
|
||||||
+ struct net_device *in, struct net_device *out,
|
|
||||||
+ int (*okfn)(struct sk_buff *))
|
|
||||||
+{
|
|
||||||
+ if (!br_netfilter_run_hooks())
|
|
||||||
+ return okfn(skb);
|
|
||||||
+
|
|
||||||
+ return NF_HOOK(pf, hook, skb, in, out, okfn);
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
/* br_stp.c */
|
|
||||||
extern void br_log_state(const struct net_bridge_port *p);
|
|
||||||
extern struct net_bridge_port *br_get_port(struct net_bridge *br,
|
|
||||||
--- a/net/bridge/br_stp_bpdu.c
|
|
||||||
+++ b/net/bridge/br_stp_bpdu.c
|
|
||||||
@@ -54,7 +54,7 @@ static void br_send_bpdu(struct net_brid
|
|
||||||
|
|
||||||
skb_reset_mac_header(skb);
|
|
||||||
|
|
||||||
- NF_HOOK(NFPROTO_BRIDGE, NF_BR_LOCAL_OUT, skb, NULL, skb->dev,
|
|
||||||
+ BR_HOOK(NFPROTO_BRIDGE, NF_BR_LOCAL_OUT, skb, NULL, skb->dev,
|
|
||||||
dev_queue_xmit);
|
|
||||||
}
|
|
||||||
|
|
||||||
--- a/net/bridge/netfilter/ebtables.c
|
|
||||||
+++ b/net/bridge/netfilter/ebtables.c
|
|
||||||
@@ -2403,11 +2403,13 @@ static int __init ebtables_init(void)
|
|
||||||
}
|
|
||||||
|
|
||||||
printk(KERN_INFO "Ebtables v2.0 registered\n");
|
|
||||||
+ brnf_call_ebtables = 1;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void __exit ebtables_fini(void)
|
|
||||||
{
|
|
||||||
+ brnf_call_ebtables = 0;
|
|
||||||
nf_unregister_sockopt(&ebt_sockopts);
|
|
||||||
xt_unregister_target(&ebt_standard_target);
|
|
||||||
printk(KERN_INFO "Ebtables v2.0 unregistered\n");
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue