linux: generic: add support for 3.1-rc1
SVN-Revision: 27940
This commit is contained in:
		
							
								
								
									
										3138
									
								
								target/linux/generic/config-3.1
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3138
									
								
								target/linux/generic/config-3.1
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							@@ -0,0 +1,93 @@
 | 
				
			|||||||
 | 
					From 2d303b4683145f7dbc918bd14d04e1396581b2ce Mon Sep 17 00:00:00 2001
 | 
				
			||||||
 | 
					From: Imre Kaloz <kaloz@openwrt.org>
 | 
				
			||||||
 | 
					Date: Thu, 7 Jul 2011 12:05:21 +0200
 | 
				
			||||||
 | 
					Subject: [PATCH] ARM: support XZ compressed kernels
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Wire up support for the XZ decompressor
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Signed-off-by: Imre Kaloz <kaloz@openwrt.org>
 | 
				
			||||||
 | 
					---
 | 
				
			||||||
 | 
					 arch/arm/Kconfig                        |    1 +
 | 
				
			||||||
 | 
					 arch/arm/boot/compressed/Makefile       |   11 +++++++++--
 | 
				
			||||||
 | 
					 arch/arm/boot/compressed/decompress.c   |    4 ++++
 | 
				
			||||||
 | 
					 arch/arm/boot/compressed/piggy.xzkern.S |    6 ++++++
 | 
				
			||||||
 | 
					 lib/xz/xz_dec_stream.c                  |    1 +
 | 
				
			||||||
 | 
					 5 files changed, 21 insertions(+), 2 deletions(-)
 | 
				
			||||||
 | 
					 create mode 100644 arch/arm/boot/compressed/piggy.xzkern.S
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					--- a/arch/arm/Kconfig
 | 
				
			||||||
 | 
					+++ b/arch/arm/Kconfig
 | 
				
			||||||
 | 
					@@ -20,6 +20,7 @@ config ARM
 | 
				
			||||||
 | 
					 	select HAVE_KERNEL_GZIP
 | 
				
			||||||
 | 
					 	select HAVE_KERNEL_LZO
 | 
				
			||||||
 | 
					 	select HAVE_KERNEL_LZMA
 | 
				
			||||||
 | 
					+	select HAVE_KERNEL_XZ
 | 
				
			||||||
 | 
					 	select HAVE_IRQ_WORK
 | 
				
			||||||
 | 
					 	select HAVE_PERF_EVENTS
 | 
				
			||||||
 | 
					 	select PERF_USE_VMALLOC
 | 
				
			||||||
 | 
					--- a/arch/arm/boot/compressed/Makefile
 | 
				
			||||||
 | 
					+++ b/arch/arm/boot/compressed/Makefile
 | 
				
			||||||
 | 
					@@ -88,13 +88,14 @@ SEDFLAGS	= s/TEXT_START/$(ZTEXTADDR)/;s/
 | 
				
			||||||
 | 
					 suffix_$(CONFIG_KERNEL_GZIP) = gzip
 | 
				
			||||||
 | 
					 suffix_$(CONFIG_KERNEL_LZO)  = lzo
 | 
				
			||||||
 | 
					 suffix_$(CONFIG_KERNEL_LZMA) = lzma
 | 
				
			||||||
 | 
					+suffix_$(CONFIG_KERNEL_XZ)   = xzkern
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 targets       := vmlinux vmlinux.lds \
 | 
				
			||||||
 | 
					 		 piggy.$(suffix_y) piggy.$(suffix_y).o \
 | 
				
			||||||
 | 
					 		 font.o font.c head.o misc.o $(OBJS)
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 # Make sure files are removed during clean
 | 
				
			||||||
 | 
					-extra-y       += piggy.gzip piggy.lzo piggy.lzma lib1funcs.S
 | 
				
			||||||
 | 
					+extra-y       += piggy.gzip piggy.lzo piggy.lzma piggy.xzkern lib1funcs.S ashldi3.S
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 ifeq ($(CONFIG_FUNCTION_TRACER),y)
 | 
				
			||||||
 | 
					 ORIG_CFLAGS := $(KBUILD_CFLAGS)
 | 
				
			||||||
 | 
					@@ -139,8 +140,14 @@ bad_syms=$$($(CROSS_COMPILE)nm $@ | sed
 | 
				
			||||||
 | 
					   ( echo "following symbols must have non local/private scope:" >&2; \
 | 
				
			||||||
 | 
					     echo "$$bad_syms" >&2; rm -f $@; false )
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					+# For __aeabi_llsl
 | 
				
			||||||
 | 
					+ashldi3 = $(obj)/ashldi3.o
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+$(obj)/ashldi3.S: $(srctree)/arch/$(SRCARCH)/lib/ashldi3.S FORCE
 | 
				
			||||||
 | 
					+	$(call cmd,shipped)
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					 $(obj)/vmlinux: $(obj)/vmlinux.lds $(obj)/$(HEAD) $(obj)/piggy.$(suffix_y).o \
 | 
				
			||||||
 | 
					-	 	$(addprefix $(obj)/, $(OBJS)) $(lib1funcs) FORCE
 | 
				
			||||||
 | 
					+	 	$(addprefix $(obj)/, $(OBJS)) $(lib1funcs) $(ashldi3) FORCE
 | 
				
			||||||
 | 
					 	$(call if_changed,ld)
 | 
				
			||||||
 | 
					 	@$(check_for_bad_syms)
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					--- a/arch/arm/boot/compressed/decompress.c
 | 
				
			||||||
 | 
					+++ b/arch/arm/boot/compressed/decompress.c
 | 
				
			||||||
 | 
					@@ -44,6 +44,10 @@ extern void error(char *);
 | 
				
			||||||
 | 
					 #include "../../../../lib/decompress_unlzma.c"
 | 
				
			||||||
 | 
					 #endif
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					+#ifdef CONFIG_KERNEL_XZ
 | 
				
			||||||
 | 
					+#include "../../../../lib/decompress_unxz.c"
 | 
				
			||||||
 | 
					+#endif
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					 int do_decompress(u8 *input, int len, u8 *output, void (*error)(char *x))
 | 
				
			||||||
 | 
					 {
 | 
				
			||||||
 | 
					 	return decompress(input, len, NULL, NULL, output, NULL, error);
 | 
				
			||||||
 | 
					--- /dev/null
 | 
				
			||||||
 | 
					+++ b/arch/arm/boot/compressed/piggy.xzkern.S
 | 
				
			||||||
 | 
					@@ -0,0 +1,6 @@
 | 
				
			||||||
 | 
					+	.section .piggydata,#alloc
 | 
				
			||||||
 | 
					+	.globl	input_data
 | 
				
			||||||
 | 
					+input_data:
 | 
				
			||||||
 | 
					+	.incbin	"arch/arm/boot/compressed/piggy.xzkern"
 | 
				
			||||||
 | 
					+	.globl	input_data_end
 | 
				
			||||||
 | 
					+input_data_end:
 | 
				
			||||||
 | 
					--- a/lib/xz/xz_dec_stream.c
 | 
				
			||||||
 | 
					+++ b/lib/xz/xz_dec_stream.c
 | 
				
			||||||
 | 
					@@ -9,6 +9,7 @@
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 #include "xz_private.h"
 | 
				
			||||||
 | 
					 #include "xz_stream.h"
 | 
				
			||||||
 | 
					+#include <linux/kernel.h>
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 /* Hash used to validate the Index field */
 | 
				
			||||||
 | 
					 struct xz_dec_hash {
 | 
				
			||||||
							
								
								
									
										3176
									
								
								target/linux/generic/patches-3.1/100-overlayfs_v11.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3176
									
								
								target/linux/generic/patches-3.1/100-overlayfs_v11.patch
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										10
									
								
								target/linux/generic/patches-3.1/110-fix_mtd_include.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								target/linux/generic/patches-3.1/110-fix_mtd_include.patch
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,10 @@
 | 
				
			|||||||
 | 
					--- 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;
 | 
				
			||||||
							
								
								
									
										11
									
								
								target/linux/generic/patches-3.1/200-fix_localversion.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								target/linux/generic/patches-3.1/200-fix_localversion.patch
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,11 @@
 | 
				
			|||||||
 | 
					--- a/scripts/setlocalversion
 | 
				
			||||||
 | 
					+++ b/scripts/setlocalversion
 | 
				
			||||||
 | 
					@@ -168,7 +168,7 @@ else
 | 
				
			||||||
 | 
					 	# annotated or signed tagged state (as git describe only
 | 
				
			||||||
 | 
					 	# looks at signed or annotated tags - git tag -a/-s) and
 | 
				
			||||||
 | 
					 	# LOCALVERSION= is not specified
 | 
				
			||||||
 | 
					-	if test "${LOCALVERSION+set}" != "set"; then
 | 
				
			||||||
 | 
					+	if test "${CONFIG_LOCALVERSION+set}" != "set"; then
 | 
				
			||||||
 | 
					 		scm=$(scm_version --short)
 | 
				
			||||||
 | 
					 		res="$res${scm:++}"
 | 
				
			||||||
 | 
					 	fi
 | 
				
			||||||
@@ -0,0 +1,24 @@
 | 
				
			|||||||
 | 
					--- a/Makefile
 | 
				
			||||||
 | 
					+++ b/Makefile
 | 
				
			||||||
 | 
					@@ -559,9 +559,9 @@ endif # $(dot-config)
 | 
				
			||||||
 | 
					 all: vmlinux
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 ifdef CONFIG_CC_OPTIMIZE_FOR_SIZE
 | 
				
			||||||
 | 
					-KBUILD_CFLAGS	+= -Os
 | 
				
			||||||
 | 
					+KBUILD_CFLAGS	+= -Os -fno-caller-saves
 | 
				
			||||||
 | 
					 else
 | 
				
			||||||
 | 
					-KBUILD_CFLAGS	+= -O2
 | 
				
			||||||
 | 
					+KBUILD_CFLAGS	+= -O2 -fno-reorder-blocks -fno-tree-ch -fno-caller-saves
 | 
				
			||||||
 | 
					 endif
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 include $(srctree)/arch/$(SRCARCH)/Makefile
 | 
				
			||||||
 | 
					@@ -620,6 +620,9 @@ endif
 | 
				
			||||||
 | 
					 NOSTDINC_FLAGS += -nostdinc -isystem $(shell $(CC) -print-file-name=include)
 | 
				
			||||||
 | 
					 CHECKFLAGS     += $(NOSTDINC_FLAGS)
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					+# improve gcc optimization
 | 
				
			||||||
 | 
					+CFLAGS += $(call cc-option,-funit-at-a-time,)
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					 # warn about C99 declaration after statement
 | 
				
			||||||
 | 
					 KBUILD_CFLAGS += $(call cc-option,-Wdeclaration-after-statement,)
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
@@ -0,0 +1,78 @@
 | 
				
			|||||||
 | 
					--- a/scripts/kallsyms.c
 | 
				
			||||||
 | 
					+++ b/scripts/kallsyms.c
 | 
				
			||||||
 | 
					@@ -22,6 +22,35 @@
 | 
				
			||||||
 | 
					 #include <stdlib.h>
 | 
				
			||||||
 | 
					 #include <string.h>
 | 
				
			||||||
 | 
					 #include <ctype.h>
 | 
				
			||||||
 | 
					+#ifdef __APPLE__
 | 
				
			||||||
 | 
					+/* Darwin has no memmem implementation, this one is ripped of the uClibc-0.9.28 source */
 | 
				
			||||||
 | 
					+void *memmem (const void *haystack, size_t haystack_len,
 | 
				
			||||||
 | 
					+                          const void *needle,  size_t needle_len)
 | 
				
			||||||
 | 
					+{
 | 
				
			||||||
 | 
					+  const char *begin;
 | 
				
			||||||
 | 
					+  const char *const last_possible
 | 
				
			||||||
 | 
					+    = (const char *) haystack + haystack_len - needle_len;
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+  if (needle_len == 0)
 | 
				
			||||||
 | 
					+    /* The first occurrence of the empty string is deemed to occur at
 | 
				
			||||||
 | 
					+       the beginning of the string.  */
 | 
				
			||||||
 | 
					+    return (void *) haystack;
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+  /* Sanity check, otherwise the loop might search through the whole
 | 
				
			||||||
 | 
					+     memory.  */
 | 
				
			||||||
 | 
					+  if (__builtin_expect (haystack_len < needle_len, 0))
 | 
				
			||||||
 | 
					+    return NULL;
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+  for (begin = (const char *) haystack; begin <= last_possible; ++begin)
 | 
				
			||||||
 | 
					+    if (begin[0] == ((const char *) needle)[0] &&
 | 
				
			||||||
 | 
					+        !memcmp ((const void *) &begin[1],
 | 
				
			||||||
 | 
					+                 (const void *) ((const char *) needle + 1),
 | 
				
			||||||
 | 
					+                 needle_len - 1))
 | 
				
			||||||
 | 
					+      return (void *) begin;
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+  return NULL;
 | 
				
			||||||
 | 
					+}
 | 
				
			||||||
 | 
					+#endif
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 #ifndef ARRAY_SIZE
 | 
				
			||||||
 | 
					 #define ARRAY_SIZE(arr) (sizeof(arr) / sizeof(arr[0]))
 | 
				
			||||||
 | 
					--- a/scripts/kconfig/Makefile
 | 
				
			||||||
 | 
					+++ b/scripts/kconfig/Makefile
 | 
				
			||||||
 | 
					@@ -148,6 +148,9 @@ check-lxdialog  := $(srctree)/$(src)/lxd
 | 
				
			||||||
 | 
					 # we really need to do so. (Do not call gcc as part of make mrproper)
 | 
				
			||||||
 | 
					 HOST_EXTRACFLAGS += $(shell $(CONFIG_SHELL) $(check-lxdialog) -ccflags) \
 | 
				
			||||||
 | 
					                     -DLOCALE
 | 
				
			||||||
 | 
					+ifeq ($(shell uname -s),Darwin)
 | 
				
			||||||
 | 
					+HOST_LOADLIBES  += -lncurses
 | 
				
			||||||
 | 
					+endif
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 # ===========================================================================
 | 
				
			||||||
 | 
					 # Shared Makefile for the various kconfig executables:
 | 
				
			||||||
 | 
					--- a/scripts/mod/mk_elfconfig.c
 | 
				
			||||||
 | 
					+++ b/scripts/mod/mk_elfconfig.c
 | 
				
			||||||
 | 
					@@ -1,7 +1,11 @@
 | 
				
			||||||
 | 
					 #include <stdio.h>
 | 
				
			||||||
 | 
					 #include <stdlib.h>
 | 
				
			||||||
 | 
					 #include <string.h>
 | 
				
			||||||
 | 
					+#ifndef __APPLE__
 | 
				
			||||||
 | 
					 #include <elf.h>
 | 
				
			||||||
 | 
					+#else
 | 
				
			||||||
 | 
					+#include "../../../../../tools/sstrip/include/elf.h"
 | 
				
			||||||
 | 
					+#endif
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 int
 | 
				
			||||||
 | 
					 main(int argc, char **argv)
 | 
				
			||||||
 | 
					--- a/scripts/mod/modpost.h
 | 
				
			||||||
 | 
					+++ b/scripts/mod/modpost.h
 | 
				
			||||||
 | 
					@@ -7,7 +7,11 @@
 | 
				
			||||||
 | 
					 #include <sys/mman.h>
 | 
				
			||||||
 | 
					 #include <fcntl.h>
 | 
				
			||||||
 | 
					 #include <unistd.h>
 | 
				
			||||||
 | 
					+#if !(defined(__APPLE__) || defined(__CYGWIN__))
 | 
				
			||||||
 | 
					 #include <elf.h>
 | 
				
			||||||
 | 
					+#else
 | 
				
			||||||
 | 
					+#include "../../../../../tools/sstrip/include/elf.h"
 | 
				
			||||||
 | 
					+#endif
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 #include "elfconfig.h"
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
							
								
								
									
										17
									
								
								target/linux/generic/patches-3.1/211-stddef_include.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								target/linux/generic/patches-3.1/211-stddef_include.patch
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,17 @@
 | 
				
			|||||||
 | 
					--- a/include/linux/stddef.h
 | 
				
			||||||
 | 
					+++ b/include/linux/stddef.h
 | 
				
			||||||
 | 
					@@ -16,6 +16,7 @@ enum {
 | 
				
			||||||
 | 
					 	false	= 0,
 | 
				
			||||||
 | 
					 	true	= 1
 | 
				
			||||||
 | 
					 };
 | 
				
			||||||
 | 
					+#endif /* __KERNEL__ */
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 #undef offsetof
 | 
				
			||||||
 | 
					 #ifdef __compiler_offsetof
 | 
				
			||||||
 | 
					@@ -23,6 +24,5 @@ enum {
 | 
				
			||||||
 | 
					 #else
 | 
				
			||||||
 | 
					 #define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
 | 
				
			||||||
 | 
					 #endif
 | 
				
			||||||
 | 
					-#endif /* __KERNEL__ */
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 #endif
 | 
				
			||||||
							
								
								
									
										89
									
								
								target/linux/generic/patches-3.1/220-module_exports.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										89
									
								
								target/linux/generic/patches-3.1/220-module_exports.patch
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,89 @@
 | 
				
			|||||||
 | 
					--- a/include/asm-generic/vmlinux.lds.h
 | 
				
			||||||
 | 
					+++ b/include/asm-generic/vmlinux.lds.h
 | 
				
			||||||
 | 
					@@ -52,6 +52,27 @@
 | 
				
			||||||
 | 
					 #define LOAD_OFFSET 0
 | 
				
			||||||
 | 
					 #endif
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					+#ifndef SYMTAB_KEEP_STR
 | 
				
			||||||
 | 
					+#define SYMTAB_KEEP_STR *(__ksymtab_strings+*)
 | 
				
			||||||
 | 
					+#define SYMTAB_DISCARD_STR
 | 
				
			||||||
 | 
					+#else
 | 
				
			||||||
 | 
					+#define SYMTAB_DISCARD_STR *(__ksymtab_strings+*)
 | 
				
			||||||
 | 
					+#endif
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+#ifndef SYMTAB_KEEP
 | 
				
			||||||
 | 
					+#define SYMTAB_KEEP *(SORT(___ksymtab+*))
 | 
				
			||||||
 | 
					+#define SYMTAB_DISCARD
 | 
				
			||||||
 | 
					+#else
 | 
				
			||||||
 | 
					+#define SYMTAB_DISCARD *(SORT(___ksymtab+*))
 | 
				
			||||||
 | 
					+#endif
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+#ifndef SYMTAB_KEEP_GPL
 | 
				
			||||||
 | 
					+#define SYMTAB_KEEP_GPL *(SORT(___ksymtab_gpl+*))
 | 
				
			||||||
 | 
					+#define SYMTAB_DISCARD_GPL
 | 
				
			||||||
 | 
					+#else
 | 
				
			||||||
 | 
					+#define SYMTAB_DISCARD_GPL *(SORT(___ksymtab_gpl+*))
 | 
				
			||||||
 | 
					+#endif
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					 #ifndef SYMBOL_PREFIX
 | 
				
			||||||
 | 
					 #define VMLINUX_SYMBOL(sym) sym
 | 
				
			||||||
 | 
					 #else
 | 
				
			||||||
 | 
					@@ -276,14 +297,14 @@
 | 
				
			||||||
 | 
					 	/* Kernel symbol table: Normal symbols */			\
 | 
				
			||||||
 | 
					 	__ksymtab         : AT(ADDR(__ksymtab) - LOAD_OFFSET) {		\
 | 
				
			||||||
 | 
					 		VMLINUX_SYMBOL(__start___ksymtab) = .;			\
 | 
				
			||||||
 | 
					-		*(SORT(___ksymtab+*))					\
 | 
				
			||||||
 | 
					+		SYMTAB_KEEP						\
 | 
				
			||||||
 | 
					 		VMLINUX_SYMBOL(__stop___ksymtab) = .;			\
 | 
				
			||||||
 | 
					 	}								\
 | 
				
			||||||
 | 
					 									\
 | 
				
			||||||
 | 
					 	/* Kernel symbol table: GPL-only symbols */			\
 | 
				
			||||||
 | 
					 	__ksymtab_gpl     : AT(ADDR(__ksymtab_gpl) - LOAD_OFFSET) {	\
 | 
				
			||||||
 | 
					 		VMLINUX_SYMBOL(__start___ksymtab_gpl) = .;		\
 | 
				
			||||||
 | 
					-		*(SORT(___ksymtab_gpl+*))				\
 | 
				
			||||||
 | 
					+		SYMTAB_KEEP_GPL						\
 | 
				
			||||||
 | 
					 		VMLINUX_SYMBOL(__stop___ksymtab_gpl) = .;		\
 | 
				
			||||||
 | 
					 	}								\
 | 
				
			||||||
 | 
					 									\
 | 
				
			||||||
 | 
					@@ -345,7 +366,7 @@
 | 
				
			||||||
 | 
					 									\
 | 
				
			||||||
 | 
					 	/* Kernel symbol table: strings */				\
 | 
				
			||||||
 | 
					         __ksymtab_strings : AT(ADDR(__ksymtab_strings) - LOAD_OFFSET) {	\
 | 
				
			||||||
 | 
					-		*(__ksymtab_strings)					\
 | 
				
			||||||
 | 
					+		SYMTAB_KEEP_STR						\
 | 
				
			||||||
 | 
					 	}								\
 | 
				
			||||||
 | 
					 									\
 | 
				
			||||||
 | 
					 	/* __*init sections */						\
 | 
				
			||||||
 | 
					@@ -677,6 +698,9 @@
 | 
				
			||||||
 | 
					 	EXIT_TEXT							\
 | 
				
			||||||
 | 
					 	EXIT_DATA							\
 | 
				
			||||||
 | 
					 	EXIT_CALL							\
 | 
				
			||||||
 | 
					+	SYMTAB_DISCARD							\
 | 
				
			||||||
 | 
					+	SYMTAB_DISCARD_GPL						\
 | 
				
			||||||
 | 
					+	SYMTAB_DISCARD_STR						\
 | 
				
			||||||
 | 
					 	*(.discard)							\
 | 
				
			||||||
 | 
					 	*(.discard.*)							\
 | 
				
			||||||
 | 
					 	}
 | 
				
			||||||
 | 
					--- a/include/linux/module.h
 | 
				
			||||||
 | 
					+++ b/include/linux/module.h
 | 
				
			||||||
 | 
					@@ -232,12 +232,19 @@ struct module_use {
 | 
				
			||||||
 | 
					 #define __CRC_SYMBOL(sym, sec)
 | 
				
			||||||
 | 
					 #endif
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					+#ifdef MODULE
 | 
				
			||||||
 | 
					+#define __EXPORT_SUFFIX(sym)
 | 
				
			||||||
 | 
					+#else
 | 
				
			||||||
 | 
					+#define __EXPORT_SUFFIX(sym) "+" #sym
 | 
				
			||||||
 | 
					+#endif
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					 /* For every exported symbol, place a struct in the __ksymtab section */
 | 
				
			||||||
 | 
					 #define __EXPORT_SYMBOL(sym, sec)				\
 | 
				
			||||||
 | 
					 	extern typeof(sym) sym;					\
 | 
				
			||||||
 | 
					 	__CRC_SYMBOL(sym, sec)					\
 | 
				
			||||||
 | 
					 	static const char __kstrtab_##sym[]			\
 | 
				
			||||||
 | 
					-	__attribute__((section("__ksymtab_strings"), aligned(1))) \
 | 
				
			||||||
 | 
					+	__attribute__((section("__ksymtab_strings"		\
 | 
				
			||||||
 | 
					+	  __EXPORT_SUFFIX(sym)), aligned(1)))			\
 | 
				
			||||||
 | 
					 	= MODULE_SYMBOL_PREFIX #sym;                    	\
 | 
				
			||||||
 | 
					 	static const struct kernel_symbol __ksymtab_##sym	\
 | 
				
			||||||
 | 
					 	__used							\
 | 
				
			||||||
@@ -0,0 +1,54 @@
 | 
				
			|||||||
 | 
					--- a/scripts/Makefile.lib
 | 
				
			||||||
 | 
					+++ b/scripts/Makefile.lib
 | 
				
			||||||
 | 
					@@ -292,7 +292,7 @@ cmd_bzip2 = (cat $(filter-out FORCE,$^)
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 quiet_cmd_lzma = LZMA    $@
 | 
				
			||||||
 | 
					 cmd_lzma = (cat $(filter-out FORCE,$^) | \
 | 
				
			||||||
 | 
					-	lzma -9 && $(call size_append, $(filter-out FORCE,$^))) > $@ || \
 | 
				
			||||||
 | 
					+	lzma e -d20 -lc1 -lp2 -pb2 -eos -si -so && $(call size_append, $(filter-out FORCE,$^))) > $@ || \
 | 
				
			||||||
 | 
					 	(rm -f $@ ; false)
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 quiet_cmd_lzo = LZO     $@
 | 
				
			||||||
 | 
					--- a/scripts/gen_initramfs_list.sh
 | 
				
			||||||
 | 
					+++ b/scripts/gen_initramfs_list.sh
 | 
				
			||||||
 | 
					@@ -226,7 +226,7 @@ cpio_list=
 | 
				
			||||||
 | 
					 output="/dev/stdout"
 | 
				
			||||||
 | 
					 output_file=""
 | 
				
			||||||
 | 
					 is_cpio_compressed=
 | 
				
			||||||
 | 
					-compr="gzip -n -9 -f"
 | 
				
			||||||
 | 
					+compr="gzip -n -9 -f -"
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 arg="$1"
 | 
				
			||||||
 | 
					 case "$arg" in
 | 
				
			||||||
 | 
					@@ -240,9 +240,9 @@ case "$arg" in
 | 
				
			||||||
 | 
					 		output_file="$1"
 | 
				
			||||||
 | 
					 		cpio_list="$(mktemp ${TMPDIR:-/tmp}/cpiolist.XXXXXX)"
 | 
				
			||||||
 | 
					 		output=${cpio_list}
 | 
				
			||||||
 | 
					-		echo "$output_file" | grep -q "\.gz$" && compr="gzip -n -9 -f"
 | 
				
			||||||
 | 
					-		echo "$output_file" | grep -q "\.bz2$" && compr="bzip2 -9 -f"
 | 
				
			||||||
 | 
					-		echo "$output_file" | grep -q "\.lzma$" && compr="lzma -9 -f"
 | 
				
			||||||
 | 
					+		echo "$output_file" | grep -q "\.gz$" && compr="gzip -n -9 -f -"
 | 
				
			||||||
 | 
					+		echo "$output_file" | grep -q "\.bz2$" && compr="bzip2 -9 -f -"
 | 
				
			||||||
 | 
					+		echo "$output_file" | grep -q "\.lzma$" && compr="lzma e -d20 -lc1 -lp2 -pb2 -eos -si -so"
 | 
				
			||||||
 | 
					 		echo "$output_file" | grep -q "\.xz$" && \
 | 
				
			||||||
 | 
					 				compr="xz --check=crc32 --lzma2=dict=1MiB"
 | 
				
			||||||
 | 
					 		echo "$output_file" | grep -q "\.lzo$" && compr="lzop -9 -f"
 | 
				
			||||||
 | 
					@@ -303,7 +303,7 @@ if [ ! -z ${output_file} ]; then
 | 
				
			||||||
 | 
					 	if [ "${is_cpio_compressed}" = "compressed" ]; then
 | 
				
			||||||
 | 
					 		cat ${cpio_tfile} > ${output_file}
 | 
				
			||||||
 | 
					 	else
 | 
				
			||||||
 | 
					-		(cat ${cpio_tfile} | ${compr}  - > ${output_file}) \
 | 
				
			||||||
 | 
					+		(cat ${cpio_tfile} | ${compr} > ${output_file}) \
 | 
				
			||||||
 | 
					 		|| (rm -f ${output_file} ; false)
 | 
				
			||||||
 | 
					 	fi
 | 
				
			||||||
 | 
					 	[ -z ${cpio_file} ] && rm ${cpio_tfile}
 | 
				
			||||||
 | 
					--- a/lib/decompress.c
 | 
				
			||||||
 | 
					+++ b/lib/decompress.c
 | 
				
			||||||
 | 
					@@ -40,6 +40,7 @@ static const struct compress_format {
 | 
				
			||||||
 | 
					 	{ {037, 0236}, "gzip", gunzip },
 | 
				
			||||||
 | 
					 	{ {0x42, 0x5a}, "bzip2", bunzip2 },
 | 
				
			||||||
 | 
					 	{ {0x5d, 0x00}, "lzma", unlzma },
 | 
				
			||||||
 | 
					+	{ {0x6d, 0x00}, "lzma-openwrt", unlzma },
 | 
				
			||||||
 | 
					 	{ {0xfd, 0x37}, "xz", unxz },
 | 
				
			||||||
 | 
					 	{ {0x89, 0x4c}, "lzo", unlzo },
 | 
				
			||||||
 | 
					 	{ {0, 0}, NULL, NULL }
 | 
				
			||||||
							
								
								
									
										18
									
								
								target/linux/generic/patches-3.1/250-netfilter_depends.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								target/linux/generic/patches-3.1/250-netfilter_depends.patch
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,18 @@
 | 
				
			|||||||
 | 
					--- a/net/netfilter/Kconfig
 | 
				
			||||||
 | 
					+++ b/net/netfilter/Kconfig
 | 
				
			||||||
 | 
					@@ -163,7 +163,6 @@ config NF_CONNTRACK_FTP
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 config NF_CONNTRACK_H323
 | 
				
			||||||
 | 
					 	tristate "H.323 protocol support"
 | 
				
			||||||
 | 
					-	depends on (IPV6 || IPV6=n)
 | 
				
			||||||
 | 
					 	depends on NETFILTER_ADVANCED
 | 
				
			||||||
 | 
					 	help
 | 
				
			||||||
 | 
					 	  H.323 is a VoIP signalling protocol from ITU-T. As one of the most
 | 
				
			||||||
 | 
					@@ -611,7 +610,6 @@ config NETFILTER_XT_TARGET_SECMARK
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 config NETFILTER_XT_TARGET_TCPMSS
 | 
				
			||||||
 | 
					 	tristate '"TCPMSS" target support'
 | 
				
			||||||
 | 
					-	depends on (IPV6 || IPV6=n)
 | 
				
			||||||
 | 
					 	default m if NETFILTER_ADVANCED=n
 | 
				
			||||||
 | 
					 	---help---
 | 
				
			||||||
 | 
					 	  This option adds a `TCPMSS' target, which allows you to alter the
 | 
				
			||||||
							
								
								
									
										11
									
								
								target/linux/generic/patches-3.1/251-sound_kconfig.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								target/linux/generic/patches-3.1/251-sound_kconfig.patch
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,11 @@
 | 
				
			|||||||
 | 
					--- a/sound/core/Kconfig
 | 
				
			||||||
 | 
					+++ b/sound/core/Kconfig
 | 
				
			||||||
 | 
					@@ -8,7 +8,7 @@ config SND_PCM
 | 
				
			||||||
 | 
					 	select GCD
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 config SND_HWDEP
 | 
				
			||||||
 | 
					-	tristate
 | 
				
			||||||
 | 
					+	tristate "Sound hardware support"
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 config SND_RAWMIDI
 | 
				
			||||||
 | 
					 	tristate
 | 
				
			||||||
							
								
								
									
										10
									
								
								target/linux/generic/patches-3.1/252-mv_cesa_depends.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								target/linux/generic/patches-3.1/252-mv_cesa_depends.patch
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,10 @@
 | 
				
			|||||||
 | 
					--- a/drivers/crypto/Kconfig
 | 
				
			||||||
 | 
					+++ b/drivers/crypto/Kconfig
 | 
				
			||||||
 | 
					@@ -172,6 +172,7 @@ config CRYPTO_DEV_MV_CESA
 | 
				
			||||||
 | 
					 	depends on PLAT_ORION
 | 
				
			||||||
 | 
					 	select CRYPTO_ALGAPI
 | 
				
			||||||
 | 
					 	select CRYPTO_AES
 | 
				
			||||||
 | 
					+	select CRYPTO_HASH2
 | 
				
			||||||
 | 
					 	select CRYPTO_BLKCIPHER2
 | 
				
			||||||
 | 
					 	help
 | 
				
			||||||
 | 
					 	  This driver allows you to utilize the Cryptographic Engines and
 | 
				
			||||||
@@ -0,0 +1,29 @@
 | 
				
			|||||||
 | 
					--- 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
 | 
				
			||||||
@@ -0,0 +1,23 @@
 | 
				
			|||||||
 | 
					--- a/lib/Kconfig
 | 
				
			||||||
 | 
					+++ b/lib/Kconfig
 | 
				
			||||||
 | 
					@@ -197,16 +197,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
 | 
				
			||||||
@@ -0,0 +1,19 @@
 | 
				
			|||||||
 | 
					--- a/net/wireless/Kconfig
 | 
				
			||||||
 | 
					+++ b/net/wireless/Kconfig
 | 
				
			||||||
 | 
					@@ -142,13 +142,13 @@ config LIB80211
 | 
				
			||||||
 | 
					 	  you want this built into your kernel.
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 config LIB80211_CRYPT_WEP
 | 
				
			||||||
 | 
					-	tristate
 | 
				
			||||||
 | 
					+	tristate "LIB80211_CRYPT_WEP"
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 config LIB80211_CRYPT_CCMP
 | 
				
			||||||
 | 
					-	tristate
 | 
				
			||||||
 | 
					+	tristate "LIB80211_CRYPT_CCMP"
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 config LIB80211_CRYPT_TKIP
 | 
				
			||||||
 | 
					-	tristate
 | 
				
			||||||
 | 
					+	tristate "LIB80211_CRYPT_TKIP"
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 config LIB80211_DEBUG
 | 
				
			||||||
 | 
					 	bool "lib80211 debugging messages"
 | 
				
			||||||
@@ -0,0 +1,47 @@
 | 
				
			|||||||
 | 
					--- 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
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
@@ -0,0 +1,22 @@
 | 
				
			|||||||
 | 
					--- 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"
 | 
				
			||||||
@@ -0,0 +1,39 @@
 | 
				
			|||||||
 | 
					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
 | 
				
			||||||
 | 
					@@ -853,9 +853,6 @@ config ARC
 | 
				
			||||||
 | 
					 config ARCH_MAY_HAVE_PC_FDC
 | 
				
			||||||
 | 
					 	bool
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					-config BOOT_RAW
 | 
				
			||||||
 | 
					-	bool
 | 
				
			||||||
 | 
					-
 | 
				
			||||||
 | 
					 config CEVT_BCM1480
 | 
				
			||||||
 | 
					 	bool
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					@@ -2303,6 +2300,18 @@ config USE_OF
 | 
				
			||||||
 | 
					 	help
 | 
				
			||||||
 | 
					 	  Include support for flattened device tree machine descriptions.
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					+config BOOT_RAW
 | 
				
			||||||
 | 
					+	bool "Enable the kernel to be executed from the load address"
 | 
				
			||||||
 | 
					+	default n
 | 
				
			||||||
 | 
					+	help
 | 
				
			||||||
 | 
					+	 Allow the kernel to be executed from the load address for
 | 
				
			||||||
 | 
					+	 bootloaders which cannot read the ELF format. This places
 | 
				
			||||||
 | 
					+	 a jump to start_kernel at the load address.
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	 If unsure, say N.
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					 endmenu
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 config LOCKDEP_SUPPORT
 | 
				
			||||||
@@ -0,0 +1,28 @@
 | 
				
			|||||||
 | 
					--- a/arch/mips/Kconfig
 | 
				
			||||||
 | 
					+++ b/arch/mips/Kconfig
 | 
				
			||||||
 | 
					@@ -952,6 +952,10 @@ config SYNC_R4K
 | 
				
			||||||
 | 
					 config MIPS_MACHINE
 | 
				
			||||||
 | 
					 	def_bool n
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					+config IMAGE_CMDLINE_HACK
 | 
				
			||||||
 | 
					+	bool "OpenWrt specific image command line hack"
 | 
				
			||||||
 | 
					+	default n
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					 config NO_IOPORT
 | 
				
			||||||
 | 
					 	def_bool n
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					--- a/arch/mips/kernel/head.S
 | 
				
			||||||
 | 
					+++ b/arch/mips/kernel/head.S
 | 
				
			||||||
 | 
					@@ -141,6 +141,12 @@ FEXPORT(__kernel_entry)
 | 
				
			||||||
 | 
					 	j	kernel_entry
 | 
				
			||||||
 | 
					 #endif
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					+#ifdef CONFIG_IMAGE_CMDLINE_HACK
 | 
				
			||||||
 | 
					+	.ascii	"CMDLINE:"
 | 
				
			||||||
 | 
					+EXPORT(__image_cmdline)
 | 
				
			||||||
 | 
					+	.fill	0x400
 | 
				
			||||||
 | 
					+#endif /* CONFIG_IMAGE_CMDLINE_HACK */
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					 	__REF
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 NESTED(kernel_entry, 16, sp)			# kernel entry point
 | 
				
			||||||
@@ -0,0 +1,18 @@
 | 
				
			|||||||
 | 
					--- a/arch/mips/include/asm/thread_info.h
 | 
				
			||||||
 | 
					+++ b/arch/mips/include/asm/thread_info.h
 | 
				
			||||||
 | 
					@@ -85,6 +85,7 @@ register struct thread_info *__current_t
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 #define STACK_WARN	(THREAD_SIZE / 8)
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					+#if 0
 | 
				
			||||||
 | 
					 #define __HAVE_ARCH_THREAD_INFO_ALLOCATOR
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 #ifdef CONFIG_DEBUG_STACK_USAGE
 | 
				
			||||||
 | 
					@@ -96,6 +97,7 @@ register struct thread_info *__current_t
 | 
				
			||||||
 | 
					 #endif
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 #define free_thread_info(info) kfree(info)
 | 
				
			||||||
 | 
					+#endif
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 #endif /* !__ASSEMBLY__ */
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
							
								
								
									
										11
									
								
								target/linux/generic/patches-3.1/303-mips_fix_kexec.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								target/linux/generic/patches-3.1/303-mips_fix_kexec.patch
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,11 @@
 | 
				
			|||||||
 | 
					--- a/arch/mips/kernel/machine_kexec.c
 | 
				
			||||||
 | 
					+++ b/arch/mips/kernel/machine_kexec.c
 | 
				
			||||||
 | 
					@@ -52,7 +52,7 @@ machine_kexec(struct kimage *image)
 | 
				
			||||||
 | 
					 	reboot_code_buffer =
 | 
				
			||||||
 | 
					 	  (unsigned long)page_address(image->control_code_page);
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					-	kexec_start_address = image->start;
 | 
				
			||||||
 | 
					+	kexec_start_address = (unsigned long) phys_to_virt(image->start);
 | 
				
			||||||
 | 
					 	kexec_indirection_page =
 | 
				
			||||||
 | 
					 		(unsigned long) phys_to_virt(image->head & PAGE_MASK);
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
							
								
								
									
										160
									
								
								target/linux/generic/patches-3.1/304-mips_disable_fpu.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										160
									
								
								target/linux/generic/patches-3.1/304-mips_disable_fpu.patch
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,160 @@
 | 
				
			|||||||
 | 
					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
 | 
				
			||||||
 | 
					@@ -937,6 +937,17 @@ config I8259
 | 
				
			||||||
 | 
					 config MIPS_BONITO64
 | 
				
			||||||
 | 
					 	bool
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					+config MIPS_FPU_EMU
 | 
				
			||||||
 | 
					+	bool "Enable FPU emulation"
 | 
				
			||||||
 | 
					+	default y
 | 
				
			||||||
 | 
					+	help
 | 
				
			||||||
 | 
					+	   This option allows building a kernel with or without the Algorithmics
 | 
				
			||||||
 | 
					+	   FPU emulator enabled. Turning off this option results in a kernel which
 | 
				
			||||||
 | 
					+	   does not catch floating operations exceptions. Make sure that your toolchain
 | 
				
			||||||
 | 
					+	   is configured to enable software floating point emulation in that case.
 | 
				
			||||||
 | 
					+		
 | 
				
			||||||
 | 
					+	   If unsure say Y here.
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					 config MIPS_MSC
 | 
				
			||||||
 | 
					 	bool
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					--- a/arch/mips/math-emu/Makefile
 | 
				
			||||||
 | 
					+++ b/arch/mips/math-emu/Makefile
 | 
				
			||||||
 | 
					@@ -2,11 +2,13 @@
 | 
				
			||||||
 | 
					 # Makefile for the Linux/MIPS kernel FPU emulation.
 | 
				
			||||||
 | 
					 #
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					-obj-y	:= cp1emu.o ieee754m.o ieee754d.o ieee754dp.o ieee754sp.o ieee754.o \
 | 
				
			||||||
 | 
					+obj-y	:=	kernel_linkage.o dsemul.o cp1emu.o
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+obj-$(CONFIG_MIPS_FPU_EMU)	+= ieee754m.o ieee754d.o ieee754dp.o ieee754sp.o ieee754.o \
 | 
				
			||||||
 | 
					 	   ieee754xcpt.o dp_frexp.o dp_modf.o dp_div.o dp_mul.o dp_sub.o \
 | 
				
			||||||
 | 
					 	   dp_add.o dp_fsp.o dp_cmp.o dp_logb.o dp_scalb.o dp_simple.o \
 | 
				
			||||||
 | 
					 	   dp_tint.o dp_fint.o dp_tlong.o dp_flong.o sp_frexp.o sp_modf.o \
 | 
				
			||||||
 | 
					 	   sp_div.o sp_mul.o sp_sub.o sp_add.o sp_fdp.o sp_cmp.o sp_logb.o \
 | 
				
			||||||
 | 
					 	   sp_scalb.o sp_simple.o sp_tint.o sp_fint.o sp_tlong.o sp_flong.o \
 | 
				
			||||||
 | 
					-	   dp_sqrt.o sp_sqrt.o kernel_linkage.o dsemul.o
 | 
				
			||||||
 | 
					+	   dp_sqrt.o sp_sqrt.o
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					--- a/arch/mips/math-emu/cp1emu.c
 | 
				
			||||||
 | 
					+++ b/arch/mips/math-emu/cp1emu.c
 | 
				
			||||||
 | 
					@@ -58,7 +58,11 @@
 | 
				
			||||||
 | 
					 #define __mips 4
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 /* Function which emulates a floating point instruction. */
 | 
				
			||||||
 | 
					+#ifdef CONFIG_DEBUG_FS
 | 
				
			||||||
 | 
					+DEFINE_PER_CPU(struct mips_fpu_emulator_stats, fpuemustats);
 | 
				
			||||||
 | 
					+#endif
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					+#ifdef CONFIG_MIPS_FPU_EMU
 | 
				
			||||||
 | 
					 static int fpu_emu(struct pt_regs *, struct mips_fpu_struct *,
 | 
				
			||||||
 | 
					 	mips_instruction);
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					@@ -69,10 +73,6 @@ static int fpux_emu(struct pt_regs *,
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 /* Further private data for which no space exists in mips_fpu_struct */
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					-#ifdef CONFIG_DEBUG_FS
 | 
				
			||||||
 | 
					-DEFINE_PER_CPU(struct mips_fpu_emulator_stats, fpuemustats);
 | 
				
			||||||
 | 
					-#endif
 | 
				
			||||||
 | 
					-
 | 
				
			||||||
 | 
					 /* Control registers */
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 #define FPCREG_RID	0	/* $0  = revision id */
 | 
				
			||||||
 | 
					@@ -1360,7 +1360,6 @@ int fpu_emulator_cop1Handler(struct pt_r
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 	return sig;
 | 
				
			||||||
 | 
					 }
 | 
				
			||||||
 | 
					-
 | 
				
			||||||
 | 
					 #ifdef CONFIG_DEBUG_FS
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 static int fpuemu_stat_get(void *data, u64 *val)
 | 
				
			||||||
 | 
					@@ -1409,4 +1408,11 @@ static int __init debugfs_fpuemu(void)
 | 
				
			||||||
 | 
					 	return 0;
 | 
				
			||||||
 | 
					 }
 | 
				
			||||||
 | 
					 __initcall(debugfs_fpuemu);
 | 
				
			||||||
 | 
					-#endif
 | 
				
			||||||
 | 
					+#endif /* CONFIG_DEBUGFS */
 | 
				
			||||||
 | 
					+#else
 | 
				
			||||||
 | 
					+int fpu_emulator_cop1Handler(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
 | 
				
			||||||
 | 
					+        int has_fpu)
 | 
				
			||||||
 | 
					+{
 | 
				
			||||||
 | 
					+	return 0;
 | 
				
			||||||
 | 
					+}
 | 
				
			||||||
 | 
					+#endif /* CONFIG_MIPS_FPU_EMU */
 | 
				
			||||||
 | 
					--- a/arch/mips/math-emu/dsemul.c
 | 
				
			||||||
 | 
					+++ b/arch/mips/math-emu/dsemul.c
 | 
				
			||||||
 | 
					@@ -109,6 +109,7 @@ int mips_dsemul(struct pt_regs *regs, mi
 | 
				
			||||||
 | 
					 	return SIGILL;		/* force out of emulation loop */
 | 
				
			||||||
 | 
					 }
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					+#ifdef CONFIG_MIPS_FPU_EMU
 | 
				
			||||||
 | 
					 int do_dsemulret(struct pt_regs *xcp)
 | 
				
			||||||
 | 
					 {
 | 
				
			||||||
 | 
					 	struct emuframe __user *fr;
 | 
				
			||||||
 | 
					@@ -165,3 +166,9 @@ int do_dsemulret(struct pt_regs *xcp)
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 	return 1;
 | 
				
			||||||
 | 
					 }
 | 
				
			||||||
 | 
					+#else
 | 
				
			||||||
 | 
					+int do_dsemulret(struct pt_regs *xcp)
 | 
				
			||||||
 | 
					+{
 | 
				
			||||||
 | 
					+	return 0;
 | 
				
			||||||
 | 
					+}
 | 
				
			||||||
 | 
					+#endif /* CONFIG_MIPS_FPU_EMU */
 | 
				
			||||||
 | 
					--- a/arch/mips/math-emu/kernel_linkage.c
 | 
				
			||||||
 | 
					+++ b/arch/mips/math-emu/kernel_linkage.c
 | 
				
			||||||
 | 
					@@ -29,6 +29,7 @@
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 #define SIGNALLING_NAN 0x7ff800007ff80000LL
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					+#ifdef CONFIG_MIPS_FPU_EMU
 | 
				
			||||||
 | 
					 void fpu_emulator_init_fpu(void)
 | 
				
			||||||
 | 
					 {
 | 
				
			||||||
 | 
					 	static int first = 1;
 | 
				
			||||||
 | 
					@@ -112,4 +113,36 @@ int fpu_emulator_restore_context32(struc
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 	return err;
 | 
				
			||||||
 | 
					 }
 | 
				
			||||||
 | 
					-#endif
 | 
				
			||||||
 | 
					+#endif	/* CONFIG_64BIT */
 | 
				
			||||||
 | 
					+#else
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+void fpu_emulator_init_fpu(void)
 | 
				
			||||||
 | 
					+{
 | 
				
			||||||
 | 
					+	printk(KERN_INFO "FPU emulator disabled, make sure your toolchain"
 | 
				
			||||||
 | 
					+		"was compiled with software floating point support (soft-float)\n");
 | 
				
			||||||
 | 
					+	return;
 | 
				
			||||||
 | 
					+}
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+int fpu_emulator_save_context(struct sigcontext __user *sc)
 | 
				
			||||||
 | 
					+{
 | 
				
			||||||
 | 
					+	return 0;
 | 
				
			||||||
 | 
					+}
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+int fpu_emulator_restore_context(struct sigcontext __user *sc)
 | 
				
			||||||
 | 
					+{
 | 
				
			||||||
 | 
					+	return 0;
 | 
				
			||||||
 | 
					+}
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+int fpu_emulator_save_context32(struct sigcontext32 __user *sc)
 | 
				
			||||||
 | 
					+{
 | 
				
			||||||
 | 
					+	return 0;
 | 
				
			||||||
 | 
					+}
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+int fpu_emulator_restore_context32(struct sigcontext32 __user *sc)
 | 
				
			||||||
 | 
					+{
 | 
				
			||||||
 | 
					+	return 0;
 | 
				
			||||||
 | 
					+}
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+#ifdef CONFIG_64BIT
 | 
				
			||||||
 | 
					+#endif	/* CONFIG_64BIT */
 | 
				
			||||||
 | 
					+#endif /* CONFIG_MIPS_FPU_EMU */
 | 
				
			||||||
							
								
								
									
										371
									
								
								target/linux/generic/patches-3.1/305-mips_module_reloc.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										371
									
								
								target/linux/generic/patches-3.1/305-mips_module_reloc.patch
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,371 @@
 | 
				
			|||||||
 | 
					--- a/arch/mips/Makefile
 | 
				
			||||||
 | 
					+++ b/arch/mips/Makefile
 | 
				
			||||||
 | 
					@@ -90,8 +90,8 @@ all-$(CONFIG_SYS_SUPPORTS_ZBOOT)+= vmlin
 | 
				
			||||||
 | 
					 cflags-y			+= -G 0 -mno-abicalls -fno-pic -pipe
 | 
				
			||||||
 | 
					 cflags-y			+= -msoft-float
 | 
				
			||||||
 | 
					 LDFLAGS_vmlinux			+= -G 0 -static -n -nostdlib
 | 
				
			||||||
 | 
					-KBUILD_AFLAGS_MODULE		+= -mlong-calls
 | 
				
			||||||
 | 
					-KBUILD_CFLAGS_MODULE		+= -mlong-calls
 | 
				
			||||||
 | 
					+KBUILD_AFLAGS_MODULE		+= -mno-long-calls
 | 
				
			||||||
 | 
					+KBUILD_CFLAGS_MODULE		+= -mno-long-calls
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 cflags-y += -ffreestanding
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					--- a/arch/mips/include/asm/module.h
 | 
				
			||||||
 | 
					+++ b/arch/mips/include/asm/module.h
 | 
				
			||||||
 | 
					@@ -9,6 +9,11 @@ struct mod_arch_specific {
 | 
				
			||||||
 | 
					 	struct list_head dbe_list;
 | 
				
			||||||
 | 
					 	const struct exception_table_entry *dbe_start;
 | 
				
			||||||
 | 
					 	const struct exception_table_entry *dbe_end;
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	void *phys_plt_tbl;
 | 
				
			||||||
 | 
					+	void *virt_plt_tbl;
 | 
				
			||||||
 | 
					+	unsigned int phys_plt_offset;
 | 
				
			||||||
 | 
					+	unsigned int virt_plt_offset;
 | 
				
			||||||
 | 
					 };
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 typedef uint8_t Elf64_Byte;		/* Type for a 8-bit quantity.  */
 | 
				
			||||||
 | 
					--- a/arch/mips/kernel/module.c
 | 
				
			||||||
 | 
					+++ b/arch/mips/kernel/module.c
 | 
				
			||||||
 | 
					@@ -45,14 +45,219 @@ static struct mips_hi16 *mips_hi16_list;
 | 
				
			||||||
 | 
					 static LIST_HEAD(dbe_list);
 | 
				
			||||||
 | 
					 static DEFINE_SPINLOCK(dbe_lock);
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					-#ifdef MODULE_START
 | 
				
			||||||
 | 
					+/*
 | 
				
			||||||
 | 
					+ * Get the potential max trampolines size required of the init and
 | 
				
			||||||
 | 
					+ * non-init sections. Only used if we cannot find enough contiguous
 | 
				
			||||||
 | 
					+ * physically mapped memory to put the module into.
 | 
				
			||||||
 | 
					+ */
 | 
				
			||||||
 | 
					+static unsigned int
 | 
				
			||||||
 | 
					+get_plt_size(const Elf_Ehdr *hdr, const Elf_Shdr *sechdrs,
 | 
				
			||||||
 | 
					+             const char *secstrings, unsigned int symindex, bool is_init)
 | 
				
			||||||
 | 
					+{
 | 
				
			||||||
 | 
					+	unsigned long ret = 0;
 | 
				
			||||||
 | 
					+	unsigned int i, j;
 | 
				
			||||||
 | 
					+	Elf_Sym *syms;
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	/* Everything marked ALLOC (this includes the exported symbols) */
 | 
				
			||||||
 | 
					+	for (i = 1; i < hdr->e_shnum; ++i) {
 | 
				
			||||||
 | 
					+		unsigned int info = sechdrs[i].sh_info;
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+		if (sechdrs[i].sh_type != SHT_REL
 | 
				
			||||||
 | 
					+		    && sechdrs[i].sh_type != SHT_RELA)
 | 
				
			||||||
 | 
					+			continue;
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+		/* Not a valid relocation section? */
 | 
				
			||||||
 | 
					+		if (info >= hdr->e_shnum)
 | 
				
			||||||
 | 
					+			continue;
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+		/* Don't bother with non-allocated sections */
 | 
				
			||||||
 | 
					+		if (!(sechdrs[info].sh_flags & SHF_ALLOC))
 | 
				
			||||||
 | 
					+			continue;
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+		/* If it's called *.init*, and we're not init, we're
 | 
				
			||||||
 | 
					+                   not interested */
 | 
				
			||||||
 | 
					+		if ((strstr(secstrings + sechdrs[i].sh_name, ".init") != 0)
 | 
				
			||||||
 | 
					+		    != is_init)
 | 
				
			||||||
 | 
					+			continue;
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+		syms = (Elf_Sym *) sechdrs[symindex].sh_addr;
 | 
				
			||||||
 | 
					+		if (sechdrs[i].sh_type == SHT_REL) {
 | 
				
			||||||
 | 
					+			Elf_Mips_Rel *rel = (void *) sechdrs[i].sh_addr;
 | 
				
			||||||
 | 
					+			unsigned int size = sechdrs[i].sh_size / sizeof(*rel);
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+			for (j = 0; j < size; ++j) {
 | 
				
			||||||
 | 
					+				Elf_Sym *sym;
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+				if (ELF_MIPS_R_TYPE(rel[j]) != R_MIPS_26)
 | 
				
			||||||
 | 
					+					continue;
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+				sym = syms + ELF_MIPS_R_SYM(rel[j]);
 | 
				
			||||||
 | 
					+				if (!is_init && sym->st_shndx != SHN_UNDEF)
 | 
				
			||||||
 | 
					+					continue;
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+				ret += 4 * sizeof(int);
 | 
				
			||||||
 | 
					+			}
 | 
				
			||||||
 | 
					+		} else {
 | 
				
			||||||
 | 
					+			Elf_Mips_Rela *rela = (void *) sechdrs[i].sh_addr;
 | 
				
			||||||
 | 
					+			unsigned int size = sechdrs[i].sh_size / sizeof(*rela);
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+			for (j = 0; j < size; ++j) {
 | 
				
			||||||
 | 
					+				Elf_Sym *sym;
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+				if (ELF_MIPS_R_TYPE(rela[j]) != R_MIPS_26)
 | 
				
			||||||
 | 
					+					continue;
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+				sym = syms + ELF_MIPS_R_SYM(rela[j]);
 | 
				
			||||||
 | 
					+				if (!is_init && sym->st_shndx != SHN_UNDEF)
 | 
				
			||||||
 | 
					+					continue;
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+				ret += 4 * sizeof(int);
 | 
				
			||||||
 | 
					+			}
 | 
				
			||||||
 | 
					+		}
 | 
				
			||||||
 | 
					+	}
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	return ret;
 | 
				
			||||||
 | 
					+}
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+#ifndef MODULE_START
 | 
				
			||||||
 | 
					+static void *alloc_phys(unsigned long size)
 | 
				
			||||||
 | 
					+{
 | 
				
			||||||
 | 
					+	unsigned order;
 | 
				
			||||||
 | 
					+	struct page *page;
 | 
				
			||||||
 | 
					+	struct page *p;
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	size = PAGE_ALIGN(size);
 | 
				
			||||||
 | 
					+	order = get_order(size);
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	page = alloc_pages(GFP_KERNEL | __GFP_NORETRY | __GFP_NOWARN |
 | 
				
			||||||
 | 
					+			__GFP_THISNODE, order);
 | 
				
			||||||
 | 
					+	if (!page)
 | 
				
			||||||
 | 
					+		return NULL;
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	split_page(page, order);
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	for (p = page + (size >> PAGE_SHIFT); p < page + (1 << order); ++p)
 | 
				
			||||||
 | 
					+		__free_page(p);
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	return page_address(page);
 | 
				
			||||||
 | 
					+}
 | 
				
			||||||
 | 
					+#endif
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+static void free_phys(void *ptr, unsigned long size)
 | 
				
			||||||
 | 
					+{
 | 
				
			||||||
 | 
					+	struct page *page;
 | 
				
			||||||
 | 
					+	struct page *end;
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	page = virt_to_page(ptr);
 | 
				
			||||||
 | 
					+	end = page + (PAGE_ALIGN(size) >> PAGE_SHIFT);
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	for (; page < end; ++page)
 | 
				
			||||||
 | 
					+		__free_page(page);
 | 
				
			||||||
 | 
					+}
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					 void *module_alloc(unsigned long size)
 | 
				
			||||||
 | 
					 {
 | 
				
			||||||
 | 
					+#ifdef MODULE_START
 | 
				
			||||||
 | 
					 	return __vmalloc_node_range(size, 1, MODULE_START, MODULE_END,
 | 
				
			||||||
 | 
					 				GFP_KERNEL, PAGE_KERNEL, -1,
 | 
				
			||||||
 | 
					 				__builtin_return_address(0));
 | 
				
			||||||
 | 
					+#else
 | 
				
			||||||
 | 
					+	void *ptr;
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	if (size == 0)
 | 
				
			||||||
 | 
					+		return NULL;
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	ptr = alloc_phys(size);
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	/* If we failed to allocate physically contiguous memory,
 | 
				
			||||||
 | 
					+	 * fall back to regular vmalloc. The module loader code will
 | 
				
			||||||
 | 
					+	 * create jump tables to handle long jumps */
 | 
				
			||||||
 | 
					+	if (!ptr)
 | 
				
			||||||
 | 
					+		return vmalloc(size);
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	return ptr;
 | 
				
			||||||
 | 
					+#endif
 | 
				
			||||||
 | 
					 }
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+static inline bool is_phys_addr(void *ptr)
 | 
				
			||||||
 | 
					+{
 | 
				
			||||||
 | 
					+#ifdef CONFIG_64BIT
 | 
				
			||||||
 | 
					+	return (KSEGX((unsigned long)ptr) == CKSEG0);
 | 
				
			||||||
 | 
					+#else
 | 
				
			||||||
 | 
					+	return (KSEGX(ptr) == KSEG0);
 | 
				
			||||||
 | 
					 #endif
 | 
				
			||||||
 | 
					+}
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+/* Free memory returned from module_alloc */
 | 
				
			||||||
 | 
					+void module_free(struct module *mod, void *module_region)
 | 
				
			||||||
 | 
					+{
 | 
				
			||||||
 | 
					+	if (is_phys_addr(module_region)) {
 | 
				
			||||||
 | 
					+		if (mod->module_init == module_region)
 | 
				
			||||||
 | 
					+			free_phys(module_region, mod->init_size);
 | 
				
			||||||
 | 
					+		else if (mod->module_core == module_region)
 | 
				
			||||||
 | 
					+			free_phys(module_region, mod->core_size);
 | 
				
			||||||
 | 
					+		else
 | 
				
			||||||
 | 
					+			BUG();
 | 
				
			||||||
 | 
					+	} else {
 | 
				
			||||||
 | 
					+		vfree(module_region);
 | 
				
			||||||
 | 
					+	}
 | 
				
			||||||
 | 
					+}
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+static void *__module_alloc(int size, bool phys)
 | 
				
			||||||
 | 
					+{
 | 
				
			||||||
 | 
					+	void *ptr;
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	if (phys)
 | 
				
			||||||
 | 
					+		ptr = kmalloc(size, GFP_KERNEL);
 | 
				
			||||||
 | 
					+	else
 | 
				
			||||||
 | 
					+		ptr = vmalloc(size);
 | 
				
			||||||
 | 
					+	return ptr;
 | 
				
			||||||
 | 
					+}
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+static void __module_free(void *ptr)
 | 
				
			||||||
 | 
					+{
 | 
				
			||||||
 | 
					+	if (is_phys_addr(ptr))
 | 
				
			||||||
 | 
					+		kfree(ptr);
 | 
				
			||||||
 | 
					+	else
 | 
				
			||||||
 | 
					+		vfree(ptr);
 | 
				
			||||||
 | 
					+}
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+int module_frob_arch_sections(Elf_Ehdr *hdr, Elf_Shdr *sechdrs,
 | 
				
			||||||
 | 
					+			      char *secstrings, struct module *mod)
 | 
				
			||||||
 | 
					+{
 | 
				
			||||||
 | 
					+	unsigned int symindex = 0;
 | 
				
			||||||
 | 
					+	unsigned int core_size, init_size;
 | 
				
			||||||
 | 
					+	int i;
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	for (i = 1; i < hdr->e_shnum; i++)
 | 
				
			||||||
 | 
					+		if (sechdrs[i].sh_type == SHT_SYMTAB)
 | 
				
			||||||
 | 
					+			symindex = i;
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	core_size = get_plt_size(hdr, sechdrs, secstrings, symindex, false);
 | 
				
			||||||
 | 
					+	init_size = get_plt_size(hdr, sechdrs, secstrings, symindex, true);
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	mod->arch.phys_plt_offset = 0;
 | 
				
			||||||
 | 
					+	mod->arch.virt_plt_offset = 0;
 | 
				
			||||||
 | 
					+	mod->arch.phys_plt_tbl = NULL;
 | 
				
			||||||
 | 
					+	mod->arch.virt_plt_tbl = NULL;
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	if ((core_size + init_size) == 0)
 | 
				
			||||||
 | 
					+		return 0;
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	mod->arch.phys_plt_tbl = __module_alloc(core_size + init_size, 1);
 | 
				
			||||||
 | 
					+	if (!mod->arch.phys_plt_tbl)
 | 
				
			||||||
 | 
					+		return -ENOMEM;
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	mod->arch.virt_plt_tbl = __module_alloc(core_size + init_size, 0);
 | 
				
			||||||
 | 
					+	if (!mod->arch.virt_plt_tbl) {
 | 
				
			||||||
 | 
					+		__module_free(mod->arch.phys_plt_tbl);
 | 
				
			||||||
 | 
					+		mod->arch.phys_plt_tbl = NULL;
 | 
				
			||||||
 | 
					+		return -ENOMEM;
 | 
				
			||||||
 | 
					+	}
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	return 0;
 | 
				
			||||||
 | 
					+}
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 static int apply_r_mips_none(struct module *me, u32 *location, Elf_Addr v)
 | 
				
			||||||
 | 
					 {
 | 
				
			||||||
 | 
					@@ -73,28 +278,36 @@ static int apply_r_mips_32_rela(struct m
 | 
				
			||||||
 | 
					 	return 0;
 | 
				
			||||||
 | 
					 }
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					-static int apply_r_mips_26_rel(struct module *me, u32 *location, Elf_Addr v)
 | 
				
			||||||
 | 
					+static Elf_Addr add_plt_entry_to(unsigned *plt_offset,
 | 
				
			||||||
 | 
					+				 void *start, Elf_Addr v)
 | 
				
			||||||
 | 
					 {
 | 
				
			||||||
 | 
					-	if (v % 4) {
 | 
				
			||||||
 | 
					-		pr_err("module %s: dangerous R_MIPS_26 REL relocation\n",
 | 
				
			||||||
 | 
					-		       me->name);
 | 
				
			||||||
 | 
					-		return -ENOEXEC;
 | 
				
			||||||
 | 
					-	}
 | 
				
			||||||
 | 
					+	unsigned *tramp = start + *plt_offset;
 | 
				
			||||||
 | 
					+	*plt_offset += 4 * sizeof(int);
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					-	if ((v & 0xf0000000) != (((unsigned long)location + 4) & 0xf0000000)) {
 | 
				
			||||||
 | 
					-		printk(KERN_ERR
 | 
				
			||||||
 | 
					-		       "module %s: relocation overflow\n",
 | 
				
			||||||
 | 
					-		       me->name);
 | 
				
			||||||
 | 
					-		return -ENOEXEC;
 | 
				
			||||||
 | 
					-	}
 | 
				
			||||||
 | 
					+	/* adjust carry for addiu */
 | 
				
			||||||
 | 
					+	if (v & 0x00008000)
 | 
				
			||||||
 | 
					+		v += 0x10000;
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					-	*location = (*location & ~0x03ffffff) |
 | 
				
			||||||
 | 
					-	            ((*location + (v >> 2)) & 0x03ffffff);
 | 
				
			||||||
 | 
					+	tramp[0] = 0x3c190000 | (v >> 16);      /* lui t9, hi16 */
 | 
				
			||||||
 | 
					+	tramp[1] = 0x27390000 | (v & 0xffff);   /* addiu t9, t9, lo16 */
 | 
				
			||||||
 | 
					+	tramp[2] = 0x03200008;                  /* jr t9 */
 | 
				
			||||||
 | 
					+	tramp[3] = 0x00000000;                  /* nop */
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					-	return 0;
 | 
				
			||||||
 | 
					+	return (Elf_Addr) tramp;
 | 
				
			||||||
 | 
					 }
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					-static int apply_r_mips_26_rela(struct module *me, u32 *location, Elf_Addr v)
 | 
				
			||||||
 | 
					+static Elf_Addr add_plt_entry(struct module *me, void *location, Elf_Addr v)
 | 
				
			||||||
 | 
					+{
 | 
				
			||||||
 | 
					+	if (is_phys_addr(location))
 | 
				
			||||||
 | 
					+		return add_plt_entry_to(&me->arch.phys_plt_offset,
 | 
				
			||||||
 | 
					+				me->arch.phys_plt_tbl, v);
 | 
				
			||||||
 | 
					+	else
 | 
				
			||||||
 | 
					+		return add_plt_entry_to(&me->arch.virt_plt_offset,
 | 
				
			||||||
 | 
					+				me->arch.virt_plt_tbl, v);
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+}
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+static int set_r_mips_26(struct module *me, u32 *location, u32 ofs, Elf_Addr v)
 | 
				
			||||||
 | 
					 {
 | 
				
			||||||
 | 
					 	if (v % 4) {
 | 
				
			||||||
 | 
					 		pr_err("module %s: dangerous R_MIPS_26 RELArelocation\n",
 | 
				
			||||||
 | 
					@@ -103,17 +316,31 @@ static int apply_r_mips_26_rela(struct m
 | 
				
			||||||
 | 
					 	}
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 	if ((v & 0xf0000000) != (((unsigned long)location + 4) & 0xf0000000)) {
 | 
				
			||||||
 | 
					-		printk(KERN_ERR
 | 
				
			||||||
 | 
					+	    v = add_plt_entry(me, location, v + (ofs << 2));
 | 
				
			||||||
 | 
					+		if (!v) {
 | 
				
			||||||
 | 
					+			printk(KERN_ERR
 | 
				
			||||||
 | 
					 		       "module %s: relocation overflow\n",
 | 
				
			||||||
 | 
					 		       me->name);
 | 
				
			||||||
 | 
					-		return -ENOEXEC;
 | 
				
			||||||
 | 
					+			return -ENOEXEC;
 | 
				
			||||||
 | 
					+		}
 | 
				
			||||||
 | 
					+		ofs = 0;
 | 
				
			||||||
 | 
					 	}
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					-	*location = (*location & ~0x03ffffff) | ((v >> 2) & 0x03ffffff);
 | 
				
			||||||
 | 
					+	*location = (*location & ~0x03ffffff) | ((ofs + (v >> 2)) & 0x03ffffff);
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 	return 0;
 | 
				
			||||||
 | 
					 }
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					+static int apply_r_mips_26_rel(struct module *me, u32 *location, Elf_Addr v)
 | 
				
			||||||
 | 
					+{
 | 
				
			||||||
 | 
					+	return set_r_mips_26(me, location, *location & 0x03ffffff, v);
 | 
				
			||||||
 | 
					+}
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+static int apply_r_mips_26_rela(struct module *me, u32 *location, Elf_Addr v)
 | 
				
			||||||
 | 
					+{
 | 
				
			||||||
 | 
					+	return set_r_mips_26(me, location, 0, v);
 | 
				
			||||||
 | 
					+}
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					 static int apply_r_mips_hi16_rel(struct module *me, u32 *location, Elf_Addr v)
 | 
				
			||||||
 | 
					 {
 | 
				
			||||||
 | 
					 	struct mips_hi16 *n;
 | 
				
			||||||
 | 
					@@ -381,11 +608,32 @@ int module_finalize(const Elf_Ehdr *hdr,
 | 
				
			||||||
 | 
					 		list_add(&me->arch.dbe_list, &dbe_list);
 | 
				
			||||||
 | 
					 		spin_unlock_irq(&dbe_lock);
 | 
				
			||||||
 | 
					 	}
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	/* Get rid of the fixup trampoline if we're running the module
 | 
				
			||||||
 | 
					+	 * from physically mapped address space */
 | 
				
			||||||
 | 
					+	if (me->arch.phys_plt_offset == 0) {
 | 
				
			||||||
 | 
					+		__module_free(me->arch.phys_plt_tbl);
 | 
				
			||||||
 | 
					+		me->arch.phys_plt_tbl = NULL;
 | 
				
			||||||
 | 
					+	}
 | 
				
			||||||
 | 
					+	if (me->arch.virt_plt_offset == 0) {
 | 
				
			||||||
 | 
					+		__module_free(me->arch.virt_plt_tbl);
 | 
				
			||||||
 | 
					+		me->arch.virt_plt_tbl = NULL;
 | 
				
			||||||
 | 
					+	}
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					 	return 0;
 | 
				
			||||||
 | 
					 }
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 void module_arch_cleanup(struct module *mod)
 | 
				
			||||||
 | 
					 {
 | 
				
			||||||
 | 
					+	if (mod->arch.phys_plt_tbl) {
 | 
				
			||||||
 | 
					+		__module_free(mod->arch.phys_plt_tbl);
 | 
				
			||||||
 | 
					+		mod->arch.phys_plt_tbl = NULL;
 | 
				
			||||||
 | 
					+	}
 | 
				
			||||||
 | 
					+	if (mod->arch.virt_plt_tbl) {
 | 
				
			||||||
 | 
					+		__module_free(mod->arch.virt_plt_tbl);
 | 
				
			||||||
 | 
					+		mod->arch.virt_plt_tbl = NULL;
 | 
				
			||||||
 | 
					+	}
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					 	spin_lock_irq(&dbe_lock);
 | 
				
			||||||
 | 
					 	list_del(&mod->arch.dbe_list);
 | 
				
			||||||
 | 
					 	spin_unlock_irq(&dbe_lock);
 | 
				
			||||||
@@ -0,0 +1,83 @@
 | 
				
			|||||||
 | 
					--- a/arch/mips/include/asm/string.h
 | 
				
			||||||
 | 
					+++ b/arch/mips/include/asm/string.h
 | 
				
			||||||
 | 
					@@ -133,11 +133,44 @@ strncmp(__const__ char *__cs, __const__
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 #define __HAVE_ARCH_MEMSET
 | 
				
			||||||
 | 
					 extern void *memset(void *__s, int __c, size_t __count);
 | 
				
			||||||
 | 
					+#define memset(__s, __c, len)					\
 | 
				
			||||||
 | 
					+({								\
 | 
				
			||||||
 | 
					+	size_t __len = (len);					\
 | 
				
			||||||
 | 
					+	void *__ret;						\
 | 
				
			||||||
 | 
					+	if (__builtin_constant_p(len) && __len >= 64)		\
 | 
				
			||||||
 | 
					+		__ret = memset((__s), (__c), __len);		\
 | 
				
			||||||
 | 
					+	else							\
 | 
				
			||||||
 | 
					+		__ret = __builtin_memset((__s), (__c), __len);	\
 | 
				
			||||||
 | 
					+	__ret;							\
 | 
				
			||||||
 | 
					+})
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 #define __HAVE_ARCH_MEMCPY
 | 
				
			||||||
 | 
					 extern void *memcpy(void *__to, __const__ void *__from, size_t __n);
 | 
				
			||||||
 | 
					+#define memcpy(dst, src, len)					\
 | 
				
			||||||
 | 
					+({								\
 | 
				
			||||||
 | 
					+	size_t __len = (len);					\
 | 
				
			||||||
 | 
					+	void *__ret;						\
 | 
				
			||||||
 | 
					+	if (__builtin_constant_p(len) && __len >= 64)		\
 | 
				
			||||||
 | 
					+		__ret = memcpy((dst), (src), __len);		\
 | 
				
			||||||
 | 
					+	else							\
 | 
				
			||||||
 | 
					+		__ret = __builtin_memcpy((dst), (src), __len);	\
 | 
				
			||||||
 | 
					+	__ret;							\
 | 
				
			||||||
 | 
					+})
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 #define __HAVE_ARCH_MEMMOVE
 | 
				
			||||||
 | 
					 extern void *memmove(void *__dest, __const__ void *__src, size_t __n);
 | 
				
			||||||
 | 
					+#define memmove(dst, src, len)					\
 | 
				
			||||||
 | 
					+({								\
 | 
				
			||||||
 | 
					+	size_t __len = (len);					\
 | 
				
			||||||
 | 
					+	void *__ret;						\
 | 
				
			||||||
 | 
					+	if (__builtin_constant_p(len) && __len >= 64)		\
 | 
				
			||||||
 | 
					+		__ret = memmove((dst), (src), __len);		\
 | 
				
			||||||
 | 
					+	else							\
 | 
				
			||||||
 | 
					+		__ret = __builtin_memmove((dst), (src), __len);	\
 | 
				
			||||||
 | 
					+	__ret;							\
 | 
				
			||||||
 | 
					+})
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+#define __HAVE_ARCH_MEMCMP
 | 
				
			||||||
 | 
					+#define memcmp(src1, src2, len) __builtin_memcmp((src1), (src2), (len))
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 #endif /* _ASM_STRING_H */
 | 
				
			||||||
 | 
					--- a/arch/mips/lib/Makefile
 | 
				
			||||||
 | 
					+++ b/arch/mips/lib/Makefile
 | 
				
			||||||
 | 
					@@ -3,7 +3,7 @@
 | 
				
			||||||
 | 
					 #
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 lib-y	+= csum_partial.o delay.o memcpy.o memcpy-inatomic.o memset.o \
 | 
				
			||||||
 | 
					-	   strlen_user.o strncpy_user.o strnlen_user.o uncached.o
 | 
				
			||||||
 | 
					+	   strlen_user.o strncpy_user.o strnlen_user.o uncached.o memcmp.o
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 obj-y			+= iomap.o
 | 
				
			||||||
 | 
					 obj-$(CONFIG_PCI)	+= iomap-pci.o
 | 
				
			||||||
 | 
					--- /dev/null
 | 
				
			||||||
 | 
					+++ b/arch/mips/lib/memcmp.c
 | 
				
			||||||
 | 
					@@ -0,0 +1,22 @@
 | 
				
			||||||
 | 
					+/*
 | 
				
			||||||
 | 
					+ *  copied from linux/lib/string.c
 | 
				
			||||||
 | 
					+ *
 | 
				
			||||||
 | 
					+ *  Copyright (C) 1991, 1992  Linus Torvalds
 | 
				
			||||||
 | 
					+ */
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+#include <linux/module.h>
 | 
				
			||||||
 | 
					+#include <linux/string.h>
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+#undef memcmp
 | 
				
			||||||
 | 
					+int memcmp(const void *cs, const void *ct, size_t count)
 | 
				
			||||||
 | 
					+{
 | 
				
			||||||
 | 
					+	const unsigned char *su1, *su2;
 | 
				
			||||||
 | 
					+	int res = 0;
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	for (su1 = cs, su2 = ct; 0 < count; ++su1, ++su2, count--)
 | 
				
			||||||
 | 
					+		if ((res = *su1 - *su2) != 0)
 | 
				
			||||||
 | 
					+			break;
 | 
				
			||||||
 | 
					+	return res;
 | 
				
			||||||
 | 
					+}
 | 
				
			||||||
 | 
					+EXPORT_SYMBOL(memcmp);
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
							
								
								
									
										35
									
								
								target/linux/generic/patches-3.1/307-mips_oprofile_fix.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										35
									
								
								target/linux/generic/patches-3.1/307-mips_oprofile_fix.patch
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,35 @@
 | 
				
			|||||||
 | 
					--- a/arch/mips/oprofile/op_model_mipsxx.c
 | 
				
			||||||
 | 
					+++ b/arch/mips/oprofile/op_model_mipsxx.c
 | 
				
			||||||
 | 
					@@ -298,6 +298,11 @@ static void reset_counters(void *arg)
 | 
				
			||||||
 | 
					 	}
 | 
				
			||||||
 | 
					 }
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					+static irqreturn_t mipsxx_perfcount_int(int irq, void *dev_id)
 | 
				
			||||||
 | 
					+{
 | 
				
			||||||
 | 
					+	return mipsxx_perfcount_handler();
 | 
				
			||||||
 | 
					+}
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					 static int __init mipsxx_init(void)
 | 
				
			||||||
 | 
					 {
 | 
				
			||||||
 | 
					 	int counters;
 | 
				
			||||||
 | 
					@@ -374,6 +379,10 @@ static int __init mipsxx_init(void)
 | 
				
			||||||
 | 
					 	save_perf_irq = perf_irq;
 | 
				
			||||||
 | 
					 	perf_irq = mipsxx_perfcount_handler;
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					+	if (cp0_perfcount_irq >= 0)
 | 
				
			||||||
 | 
					+		return request_irq(cp0_perfcount_irq, mipsxx_perfcount_int,
 | 
				
			||||||
 | 
					+			IRQF_SHARED, "Perfcounter", save_perf_irq);
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					 	return 0;
 | 
				
			||||||
 | 
					 }
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					@@ -381,6 +390,9 @@ static void mipsxx_exit(void)
 | 
				
			||||||
 | 
					 {
 | 
				
			||||||
 | 
					 	int counters = op_model_mipsxx_ops.num_counters;
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					+	if (cp0_perfcount_irq >= 0)
 | 
				
			||||||
 | 
					+		free_irq(cp0_perfcount_irq, save_perf_irq);
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					 	counters = counters_per_cpu_to_total(counters);
 | 
				
			||||||
 | 
					 	on_each_cpu(reset_counters, (void *)(long)counters, 1);
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
@@ -0,0 +1,13 @@
 | 
				
			|||||||
 | 
					--- 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)) {
 | 
				
			||||||
@@ -0,0 +1,31 @@
 | 
				
			|||||||
 | 
					Upstream doesn't optimize the kernel and bootwrappers for ppc44x because
 | 
				
			||||||
 | 
					they still want to support gcc 3.3 -- well, we don't.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					--- a/arch/powerpc/Makefile
 | 
				
			||||||
 | 
					+++ b/arch/powerpc/Makefile
 | 
				
			||||||
 | 
					@@ -130,7 +130,8 @@ ifeq ($(CONFIG_FUNCTION_TRACER),y)
 | 
				
			||||||
 | 
					 KBUILD_CFLAGS		+= -mno-sched-epilog
 | 
				
			||||||
 | 
					 endif
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					-cpu-as-$(CONFIG_4xx)		+= -Wa,-m405
 | 
				
			||||||
 | 
					+cpu-as-$(CONFIG_40x)		+= -Wa,-m405
 | 
				
			||||||
 | 
					+cpu-as-$(CONFIG_44x)		+= -Wa,-m440
 | 
				
			||||||
 | 
					 cpu-as-$(CONFIG_6xx)		+= -Wa,-maltivec
 | 
				
			||||||
 | 
					 cpu-as-$(CONFIG_POWER4)		+= -Wa,-maltivec
 | 
				
			||||||
 | 
					 cpu-as-$(CONFIG_E500)		+= -Wa,-me500
 | 
				
			||||||
 | 
					--- a/arch/powerpc/boot/Makefile
 | 
				
			||||||
 | 
					+++ b/arch/powerpc/boot/Makefile
 | 
				
			||||||
 | 
					@@ -38,10 +38,10 @@ BOOTCFLAGS	+= -I$(obj) -I$(srctree)/$(ob
 | 
				
			||||||
 | 
					 DTC_FLAGS	?= -p 1024
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 $(obj)/4xx.o: BOOTCFLAGS += -mcpu=405
 | 
				
			||||||
 | 
					-$(obj)/ebony.o: BOOTCFLAGS += -mcpu=405
 | 
				
			||||||
 | 
					+$(obj)/ebony.o: BOOTCFLAGS += -mcpu=440
 | 
				
			||||||
 | 
					 $(obj)/cuboot-hotfoot.o: BOOTCFLAGS += -mcpu=405
 | 
				
			||||||
 | 
					-$(obj)/cuboot-taishan.o: BOOTCFLAGS += -mcpu=405
 | 
				
			||||||
 | 
					-$(obj)/cuboot-katmai.o: BOOTCFLAGS += -mcpu=405
 | 
				
			||||||
 | 
					+$(obj)/cuboot-taishan.o: BOOTCFLAGS += -mcpu=440
 | 
				
			||||||
 | 
					+$(obj)/cuboot-katmai.o: BOOTCFLAGS += -mcpu=440
 | 
				
			||||||
 | 
					 $(obj)/cuboot-acadia.o: BOOTCFLAGS += -mcpu=405
 | 
				
			||||||
 | 
					 $(obj)/treeboot-walnut.o: BOOTCFLAGS += -mcpu=405
 | 
				
			||||||
 | 
					 $(obj)/treeboot-iss4xx.o: BOOTCFLAGS += -mcpu=405
 | 
				
			||||||
@@ -0,0 +1,56 @@
 | 
				
			|||||||
 | 
					--- a/Makefile
 | 
				
			||||||
 | 
					+++ b/Makefile
 | 
				
			||||||
 | 
					@@ -375,6 +375,7 @@ KBUILD_AFLAGS   := -D__ASSEMBLY__
 | 
				
			||||||
 | 
					 KBUILD_AFLAGS_MODULE  := -DMODULE
 | 
				
			||||||
 | 
					 KBUILD_CFLAGS_MODULE  := -DMODULE
 | 
				
			||||||
 | 
					 KBUILD_LDFLAGS_MODULE := -T $(srctree)/scripts/module-common.lds
 | 
				
			||||||
 | 
					+KBUILD_LDFLAGS_MODULE_PREREQ	:= 
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 # Read KERNELRELEASE from include/config/kernel.release (if it exists)
 | 
				
			||||||
 | 
					 KERNELRELEASE = $(shell cat include/config/kernel.release 2> /dev/null)
 | 
				
			||||||
 | 
					@@ -384,7 +385,7 @@ export VERSION PATCHLEVEL SUBLEVEL KERNE
 | 
				
			||||||
 | 
					 export ARCH SRCARCH CONFIG_SHELL HOSTCC HOSTCFLAGS CROSS_COMPILE AS LD CC
 | 
				
			||||||
 | 
					 export CPP AR NM STRIP OBJCOPY OBJDUMP
 | 
				
			||||||
 | 
					 export MAKE AWK GENKSYMS INSTALLKERNEL PERL UTS_MACHINE
 | 
				
			||||||
 | 
					-export HOSTCXX HOSTCXXFLAGS LDFLAGS_MODULE CHECK CHECKFLAGS
 | 
				
			||||||
 | 
					+export HOSTCXX HOSTCXXFLAGS LDFLAGS_MODULE KBUILD_LDFLAGS_MODULE_PREREQ CHECK CHECKFLAGS
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 export KBUILD_CPPFLAGS NOSTDINC_FLAGS LINUXINCLUDE OBJCOPYFLAGS LDFLAGS
 | 
				
			||||||
 | 
					 export KBUILD_CFLAGS CFLAGS_KERNEL CFLAGS_MODULE CFLAGS_GCOV
 | 
				
			||||||
 | 
					--- a/arch/powerpc/Makefile
 | 
				
			||||||
 | 
					+++ b/arch/powerpc/Makefile
 | 
				
			||||||
 | 
					@@ -94,7 +94,7 @@ else
 | 
				
			||||||
 | 
					 endif
 | 
				
			||||||
 | 
					 endif
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					-KBUILD_LDFLAGS_MODULE += arch/powerpc/lib/crtsavres.o
 | 
				
			||||||
 | 
					+KBUILD_LDFLAGS_MODULE_PREREQ += arch/powerpc/lib/crtsavres.o
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 ifeq ($(CONFIG_TUNE_CELL),y)
 | 
				
			||||||
 | 
					 	KBUILD_CFLAGS += $(call cc-option,-mtune=cell)
 | 
				
			||||||
 | 
					--- a/scripts/Makefile.modpost
 | 
				
			||||||
 | 
					+++ b/scripts/Makefile.modpost
 | 
				
			||||||
 | 
					@@ -110,7 +110,14 @@ quiet_cmd_cc_o_c = CC      $@
 | 
				
			||||||
 | 
					       cmd_cc_o_c = $(CC) $(c_flags) $(KBUILD_CFLAGS_MODULE) $(CFLAGS_MODULE) \
 | 
				
			||||||
 | 
					 		   -c -o $@ $<
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					-$(modules:.ko=.mod.o): %.mod.o: %.mod.c FORCE
 | 
				
			||||||
 | 
					+quiet_cmd_as_o_S	= AS $(quiet_modtag)  $@
 | 
				
			||||||
 | 
					+cmd_as_o_S		= $(CC) $(a_flags) $(AFLAGS_MODULE) -c -o $@ $<
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+$(KBUILD_LDFLAGS_MODULE_PREREQ): %.o: %.S FORCE
 | 
				
			||||||
 | 
					+	$(Q)mkdir -p $(dir $@)
 | 
				
			||||||
 | 
					+	$(call if_changed_dep,as_o_S)
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+$(modules:.ko=.mod.o): %.mod.o: %.mod.c $(KBUILD_LDFLAGS_MODULE_PREREQ) FORCE
 | 
				
			||||||
 | 
					 	$(call if_changed_dep,cc_o_c)
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 targets += $(modules:.ko=.mod.o)
 | 
				
			||||||
 | 
					@@ -119,6 +126,7 @@ targets += $(modules:.ko=.mod.o)
 | 
				
			||||||
 | 
					 quiet_cmd_ld_ko_o = LD [M]  $@
 | 
				
			||||||
 | 
					       cmd_ld_ko_o = $(LD) -r $(LDFLAGS)                                 \
 | 
				
			||||||
 | 
					                              $(KBUILD_LDFLAGS_MODULE) $(LDFLAGS_MODULE) \
 | 
				
			||||||
 | 
					+			     $(KBUILD_LDFLAGS_MODULE_PREREQ)		\
 | 
				
			||||||
 | 
					                              -o $@ $(filter-out FORCE,$^)
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 $(modules): %.ko :%.o %.mod.o FORCE
 | 
				
			||||||
							
								
								
									
										327
									
								
								target/linux/generic/patches-3.1/400-rootfs_split.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										327
									
								
								target/linux/generic/patches-3.1/400-rootfs_split.patch
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,327 @@
 | 
				
			|||||||
 | 
					--- a/drivers/mtd/Kconfig
 | 
				
			||||||
 | 
					+++ b/drivers/mtd/Kconfig
 | 
				
			||||||
 | 
					@@ -33,6 +33,14 @@ config MTD_TESTS
 | 
				
			||||||
 | 
					 	  should normally be compiled as kernel modules. The modules perform
 | 
				
			||||||
 | 
					 	  various checks and verifications when loaded.
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					+config MTD_ROOTFS_ROOT_DEV
 | 
				
			||||||
 | 
					+	bool "Automatically set 'rootfs' partition to be root filesystem"
 | 
				
			||||||
 | 
					+	default y
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+config MTD_ROOTFS_SPLIT
 | 
				
			||||||
 | 
					+	bool "Automatically split 'rootfs' partition for squashfs"
 | 
				
			||||||
 | 
					+	default y
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					 config MTD_REDBOOT_PARTS
 | 
				
			||||||
 | 
					 	tristate "RedBoot partition table parsing"
 | 
				
			||||||
 | 
					 	---help---
 | 
				
			||||||
 | 
					--- a/drivers/mtd/mtdpart.c
 | 
				
			||||||
 | 
					+++ b/drivers/mtd/mtdpart.c
 | 
				
			||||||
 | 
					@@ -29,6 +29,8 @@
 | 
				
			||||||
 | 
					 #include <linux/kmod.h>
 | 
				
			||||||
 | 
					 #include <linux/mtd/mtd.h>
 | 
				
			||||||
 | 
					 #include <linux/mtd/partitions.h>
 | 
				
			||||||
 | 
					+#include <linux/root_dev.h>
 | 
				
			||||||
 | 
					+#include <linux/magic.h>
 | 
				
			||||||
 | 
					 #include <linux/err.h>
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 #include "mtdcore.h"
 | 
				
			||||||
 | 
					@@ -50,7 +52,7 @@ struct mtd_part {
 | 
				
			||||||
 | 
					  * the pointer to that structure with this macro.
 | 
				
			||||||
 | 
					  */
 | 
				
			||||||
 | 
					 #define PART(x)  ((struct mtd_part *)(x))
 | 
				
			||||||
 | 
					-
 | 
				
			||||||
 | 
					+#define IS_PART(mtd) (mtd->read == part_read)
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 /*
 | 
				
			||||||
 | 
					  * MTD methods which simply translate the effective address and pass through
 | 
				
			||||||
 | 
					@@ -637,6 +639,155 @@ int mtd_del_partition(struct mtd_info *m
 | 
				
			||||||
 | 
					 }
 | 
				
			||||||
 | 
					 EXPORT_SYMBOL_GPL(mtd_del_partition);
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					+#ifdef CONFIG_MTD_ROOTFS_SPLIT
 | 
				
			||||||
 | 
					+#define ROOTFS_SPLIT_NAME "rootfs_data"
 | 
				
			||||||
 | 
					+#define ROOTFS_REMOVED_NAME "<removed>"
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+struct squashfs_super_block {
 | 
				
			||||||
 | 
					+	__le32 s_magic;
 | 
				
			||||||
 | 
					+	__le32 pad0[9];
 | 
				
			||||||
 | 
					+	__le64 bytes_used;
 | 
				
			||||||
 | 
					+};
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+static int split_squashfs(struct mtd_info *master, int offset, int *split_offset)
 | 
				
			||||||
 | 
					+{
 | 
				
			||||||
 | 
					+	struct squashfs_super_block sb;
 | 
				
			||||||
 | 
					+	int len, ret;
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	ret = master->read(master, offset, sizeof(sb), &len, (void *) &sb);
 | 
				
			||||||
 | 
					+	if (ret || (len != sizeof(sb))) {
 | 
				
			||||||
 | 
					+		printk(KERN_ALERT "split_squashfs: error occured while reading "
 | 
				
			||||||
 | 
					+			"from \"%s\"\n", master->name);
 | 
				
			||||||
 | 
					+		return -EINVAL;
 | 
				
			||||||
 | 
					+	}
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	if (SQUASHFS_MAGIC != le32_to_cpu(sb.s_magic) ) {
 | 
				
			||||||
 | 
					+		printk(KERN_ALERT "split_squashfs: no squashfs found in \"%s\"\n",
 | 
				
			||||||
 | 
					+			master->name);
 | 
				
			||||||
 | 
					+		*split_offset = 0;
 | 
				
			||||||
 | 
					+		return 0;
 | 
				
			||||||
 | 
					+	}
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	if (le64_to_cpu((sb.bytes_used)) <= 0) {
 | 
				
			||||||
 | 
					+		printk(KERN_ALERT "split_squashfs: squashfs is empty in \"%s\"\n",
 | 
				
			||||||
 | 
					+			master->name);
 | 
				
			||||||
 | 
					+		*split_offset = 0;
 | 
				
			||||||
 | 
					+		return 0;
 | 
				
			||||||
 | 
					+	}
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	len = (u32) le64_to_cpu(sb.bytes_used);
 | 
				
			||||||
 | 
					+	len += (offset & 0x000fffff);
 | 
				
			||||||
 | 
					+	len +=  (master->erasesize - 1);
 | 
				
			||||||
 | 
					+	len &= ~(master->erasesize - 1);
 | 
				
			||||||
 | 
					+	len -= (offset & 0x000fffff);
 | 
				
			||||||
 | 
					+	*split_offset = offset + len;
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	return 0;
 | 
				
			||||||
 | 
					+}
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+static int split_rootfs_data(struct mtd_info *master, struct mtd_info *rpart, const struct mtd_partition *part)
 | 
				
			||||||
 | 
					+{
 | 
				
			||||||
 | 
					+	struct mtd_partition *dpart;
 | 
				
			||||||
 | 
					+	struct mtd_part *slave = NULL;
 | 
				
			||||||
 | 
					+	struct mtd_part *spart;
 | 
				
			||||||
 | 
					+	int ret, split_offset = 0;
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	spart = PART(rpart);
 | 
				
			||||||
 | 
					+	ret = split_squashfs(master, spart->offset, &split_offset);
 | 
				
			||||||
 | 
					+	if (ret)
 | 
				
			||||||
 | 
					+		return ret;
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	if (split_offset <= 0)
 | 
				
			||||||
 | 
					+		return 0;
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	dpart = kmalloc(sizeof(*part)+sizeof(ROOTFS_SPLIT_NAME)+1, GFP_KERNEL);
 | 
				
			||||||
 | 
					+	if (dpart == NULL) {
 | 
				
			||||||
 | 
					+		printk(KERN_INFO "split_squashfs: no memory for partition \"%s\"\n",
 | 
				
			||||||
 | 
					+			ROOTFS_SPLIT_NAME);
 | 
				
			||||||
 | 
					+		return -ENOMEM;
 | 
				
			||||||
 | 
					+	}
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	memcpy(dpart, part, sizeof(*part));
 | 
				
			||||||
 | 
					+	dpart->name = (unsigned char *)&dpart[1];
 | 
				
			||||||
 | 
					+	strcpy(dpart->name, ROOTFS_SPLIT_NAME);
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	dpart->size = rpart->size - (split_offset - spart->offset);
 | 
				
			||||||
 | 
					+	dpart->offset = split_offset;
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	if (dpart == NULL)
 | 
				
			||||||
 | 
					+		return 1;
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	printk(KERN_INFO "mtd: partition \"%s\" created automatically, ofs=%llX, len=%llX \n",
 | 
				
			||||||
 | 
					+		ROOTFS_SPLIT_NAME, dpart->offset, dpart->size);
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	slave = allocate_partition(master, dpart, 0, split_offset);
 | 
				
			||||||
 | 
					+	if (IS_ERR(slave))
 | 
				
			||||||
 | 
					+		return PTR_ERR(slave);
 | 
				
			||||||
 | 
					+	mutex_lock(&mtd_partitions_mutex);
 | 
				
			||||||
 | 
					+	list_add(&slave->list, &mtd_partitions);
 | 
				
			||||||
 | 
					+	mutex_unlock(&mtd_partitions_mutex);
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	add_mtd_device(&slave->mtd);
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	rpart->split = &slave->mtd;
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	return 0;
 | 
				
			||||||
 | 
					+}
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+static int refresh_rootfs_split(struct mtd_info *mtd)
 | 
				
			||||||
 | 
					+{
 | 
				
			||||||
 | 
					+	struct mtd_partition tpart;
 | 
				
			||||||
 | 
					+	struct mtd_part *part;
 | 
				
			||||||
 | 
					+	char *name;
 | 
				
			||||||
 | 
					+	//int index = 0;
 | 
				
			||||||
 | 
					+	int offset, size;
 | 
				
			||||||
 | 
					+	int ret;
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	part = PART(mtd);
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	/* check for the new squashfs offset first */
 | 
				
			||||||
 | 
					+	ret = split_squashfs(part->master, part->offset, &offset);
 | 
				
			||||||
 | 
					+	if (ret)
 | 
				
			||||||
 | 
					+		return ret;
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	if ((offset > 0) && !mtd->split) {
 | 
				
			||||||
 | 
					+		printk(KERN_INFO "%s: creating new split partition for \"%s\"\n", __func__, mtd->name);
 | 
				
			||||||
 | 
					+		/* if we don't have a rootfs split partition, create a new one */
 | 
				
			||||||
 | 
					+		tpart.name = (char *) mtd->name;
 | 
				
			||||||
 | 
					+		tpart.size = mtd->size;
 | 
				
			||||||
 | 
					+		tpart.offset = part->offset;
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+		return split_rootfs_data(part->master, &part->mtd, &tpart);
 | 
				
			||||||
 | 
					+	} else if ((offset > 0) && mtd->split) {
 | 
				
			||||||
 | 
					+		/* update the offsets of the existing partition */
 | 
				
			||||||
 | 
					+		size = mtd->size + part->offset - offset;
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+		part = PART(mtd->split);
 | 
				
			||||||
 | 
					+		part->offset = offset;
 | 
				
			||||||
 | 
					+		part->mtd.size = size;
 | 
				
			||||||
 | 
					+		printk(KERN_INFO "%s: %s partition \"" ROOTFS_SPLIT_NAME "\", offset: 0x%06x (0x%06x)\n",
 | 
				
			||||||
 | 
					+			__func__, (!strcmp(part->mtd.name, ROOTFS_SPLIT_NAME) ? "updating" : "creating"),
 | 
				
			||||||
 | 
					+			(u32) part->offset, (u32) part->mtd.size);
 | 
				
			||||||
 | 
					+		name = kmalloc(sizeof(ROOTFS_SPLIT_NAME) + 1, GFP_KERNEL);
 | 
				
			||||||
 | 
					+		strcpy(name, ROOTFS_SPLIT_NAME);
 | 
				
			||||||
 | 
					+		part->mtd.name = name;
 | 
				
			||||||
 | 
					+	} else if ((offset <= 0) && mtd->split) {
 | 
				
			||||||
 | 
					+		printk(KERN_INFO "%s: removing partition \"%s\"\n", __func__, mtd->split->name);
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+		/* mark existing partition as removed */
 | 
				
			||||||
 | 
					+		part = PART(mtd->split);
 | 
				
			||||||
 | 
					+		name = kmalloc(sizeof(ROOTFS_SPLIT_NAME) + 1, GFP_KERNEL);
 | 
				
			||||||
 | 
					+		strcpy(name, ROOTFS_REMOVED_NAME);
 | 
				
			||||||
 | 
					+		part->mtd.name = name;
 | 
				
			||||||
 | 
					+		part->offset = 0;
 | 
				
			||||||
 | 
					+		part->mtd.size = 0;
 | 
				
			||||||
 | 
					+	}
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	return 0;
 | 
				
			||||||
 | 
					+}
 | 
				
			||||||
 | 
					+#endif /* CONFIG_MTD_ROOTFS_SPLIT */
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					 /*
 | 
				
			||||||
 | 
					  * This function, given a master MTD object and a partition table, creates
 | 
				
			||||||
 | 
					  * and registers slave MTD objects which are bound to the master according to
 | 
				
			||||||
 | 
					@@ -653,6 +804,9 @@ int add_mtd_partitions(struct mtd_info *
 | 
				
			||||||
 | 
					 	struct mtd_part *slave;
 | 
				
			||||||
 | 
					 	uint64_t cur_offset = 0;
 | 
				
			||||||
 | 
					 	int i;
 | 
				
			||||||
 | 
					+#ifdef CONFIG_MTD_ROOTFS_SPLIT
 | 
				
			||||||
 | 
					+	int ret;
 | 
				
			||||||
 | 
					+#endif
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 	printk(KERN_NOTICE "Creating %d MTD partitions on \"%s\":\n", nbparts, master->name);
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					@@ -667,12 +821,53 @@ int add_mtd_partitions(struct mtd_info *
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 		add_mtd_device(&slave->mtd);
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					+		if (!strcmp(parts[i].name, "rootfs")) {
 | 
				
			||||||
 | 
					+#ifdef CONFIG_MTD_ROOTFS_ROOT_DEV
 | 
				
			||||||
 | 
					+			if (ROOT_DEV == 0) {
 | 
				
			||||||
 | 
					+				printk(KERN_NOTICE "mtd: partition \"rootfs\" "
 | 
				
			||||||
 | 
					+					"set to be root filesystem\n");
 | 
				
			||||||
 | 
					+				ROOT_DEV = MKDEV(MTD_BLOCK_MAJOR, slave->mtd.index);
 | 
				
			||||||
 | 
					+			}
 | 
				
			||||||
 | 
					+#endif
 | 
				
			||||||
 | 
					+#ifdef CONFIG_MTD_ROOTFS_SPLIT
 | 
				
			||||||
 | 
					+			ret = split_rootfs_data(master, &slave->mtd, &parts[i]);
 | 
				
			||||||
 | 
					+			/* if (ret == 0)
 | 
				
			||||||
 | 
					+			 * 	j++; */
 | 
				
			||||||
 | 
					+#endif
 | 
				
			||||||
 | 
					+		}
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					 		cur_offset = slave->offset + slave->mtd.size;
 | 
				
			||||||
 | 
					 	}
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 	return 0;
 | 
				
			||||||
 | 
					 }
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					+int mtd_device_refresh(struct mtd_info *mtd)
 | 
				
			||||||
 | 
					+{
 | 
				
			||||||
 | 
					+	int ret = 0;
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	if (IS_PART(mtd)) {
 | 
				
			||||||
 | 
					+		struct mtd_part *part;
 | 
				
			||||||
 | 
					+		struct mtd_info *master;
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+		part = PART(mtd);
 | 
				
			||||||
 | 
					+		master = part->master;
 | 
				
			||||||
 | 
					+		if (master->refresh_device)
 | 
				
			||||||
 | 
					+			ret = master->refresh_device(master);
 | 
				
			||||||
 | 
					+	}
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	if (!ret && mtd->refresh_device)
 | 
				
			||||||
 | 
					+		ret = mtd->refresh_device(mtd);
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+#ifdef CONFIG_MTD_ROOTFS_SPLIT
 | 
				
			||||||
 | 
					+	if (!ret && IS_PART(mtd) && !strcmp(mtd->name, "rootfs"))
 | 
				
			||||||
 | 
					+		refresh_rootfs_split(mtd);
 | 
				
			||||||
 | 
					+#endif
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	return 0;
 | 
				
			||||||
 | 
					+}
 | 
				
			||||||
 | 
					+EXPORT_SYMBOL_GPL(mtd_device_refresh);
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					 static DEFINE_SPINLOCK(part_parser_lock);
 | 
				
			||||||
 | 
					 static LIST_HEAD(part_parsers);
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					--- a/drivers/mtd/mtdchar.c
 | 
				
			||||||
 | 
					+++ b/drivers/mtd/mtdchar.c
 | 
				
			||||||
 | 
					@@ -948,6 +948,12 @@ static int mtd_ioctl(struct file *file,
 | 
				
			||||||
 | 
					 		break;
 | 
				
			||||||
 | 
					 	}
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					+	case MTDREFRESH:
 | 
				
			||||||
 | 
					+	{
 | 
				
			||||||
 | 
					+		ret = mtd_device_refresh(mtd);
 | 
				
			||||||
 | 
					+		break;
 | 
				
			||||||
 | 
					+	}
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					 	default:
 | 
				
			||||||
 | 
					 		ret = -ENOTTY;
 | 
				
			||||||
 | 
					 	}
 | 
				
			||||||
 | 
					--- a/include/linux/mtd/mtd.h
 | 
				
			||||||
 | 
					+++ b/include/linux/mtd/mtd.h
 | 
				
			||||||
 | 
					@@ -125,6 +125,7 @@ struct nand_ecclayout {
 | 
				
			||||||
 | 
					 	struct nand_oobfree oobfree[MTD_MAX_OOBFREE_ENTRIES_LARGE];
 | 
				
			||||||
 | 
					 };
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					+struct mtd_info;
 | 
				
			||||||
 | 
					 struct mtd_info {
 | 
				
			||||||
 | 
					 	u_char type;
 | 
				
			||||||
 | 
					 	uint32_t flags;
 | 
				
			||||||
 | 
					@@ -277,6 +278,9 @@ struct mtd_info {
 | 
				
			||||||
 | 
					 	struct device dev;
 | 
				
			||||||
 | 
					 	int usecount;
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					+	int (*refresh_device)(struct mtd_info *mtd);
 | 
				
			||||||
 | 
					+	struct mtd_info *split;
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					 	/* If the driver is something smart, like UBI, it may need to maintain
 | 
				
			||||||
 | 
					 	 * its own reference counting. The below functions are only for driver.
 | 
				
			||||||
 | 
					 	 * The driver may register its callbacks. These callbacks are not
 | 
				
			||||||
 | 
					@@ -327,6 +331,7 @@ struct mtd_partition;
 | 
				
			||||||
 | 
					 extern int mtd_device_register(struct mtd_info *master,
 | 
				
			||||||
 | 
					 			       const struct mtd_partition *parts,
 | 
				
			||||||
 | 
					 			       int nr_parts);
 | 
				
			||||||
 | 
					+extern int mtd_device_refresh(struct mtd_info *master);
 | 
				
			||||||
 | 
					 extern int mtd_device_unregister(struct mtd_info *master);
 | 
				
			||||||
 | 
					 extern struct mtd_info *get_mtd_device(struct mtd_info *mtd, int num);
 | 
				
			||||||
 | 
					 extern int __get_mtd_device(struct mtd_info *mtd);
 | 
				
			||||||
 | 
					--- a/include/linux/mtd/partitions.h
 | 
				
			||||||
 | 
					+++ b/include/linux/mtd/partitions.h
 | 
				
			||||||
 | 
					@@ -34,12 +34,14 @@
 | 
				
			||||||
 | 
					  * erasesize aligned (e.g. use MTDPART_OFS_NEXTBLK).
 | 
				
			||||||
 | 
					  */
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					+struct mtd_partition;
 | 
				
			||||||
 | 
					 struct mtd_partition {
 | 
				
			||||||
 | 
					 	char *name;			/* identifier string */
 | 
				
			||||||
 | 
					 	uint64_t size;			/* partition size */
 | 
				
			||||||
 | 
					 	uint64_t offset;		/* offset within the master MTD space */
 | 
				
			||||||
 | 
					 	uint32_t mask_flags;		/* master MTD flags to mask out for this partition */
 | 
				
			||||||
 | 
					 	struct nand_ecclayout *ecclayout;	/* out of band layout for this partition (NAND only) */
 | 
				
			||||||
 | 
					+	int (*refresh_partition)(struct mtd_info *);
 | 
				
			||||||
 | 
					 };
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 #define MTDPART_OFS_NXTBLK	(-2)
 | 
				
			||||||
 | 
					--- a/include/mtd/mtd-abi.h
 | 
				
			||||||
 | 
					+++ b/include/mtd/mtd-abi.h
 | 
				
			||||||
 | 
					@@ -127,6 +127,7 @@ struct otp_info {
 | 
				
			||||||
 | 
					 #define MEMWRITEOOB64		_IOWR('M', 21, struct mtd_oob_buf64)
 | 
				
			||||||
 | 
					 #define MEMREADOOB64		_IOWR('M', 22, struct mtd_oob_buf64)
 | 
				
			||||||
 | 
					 #define MEMISLOCKED		_IOR('M', 23, struct erase_info_user)
 | 
				
			||||||
 | 
					+#define MTDREFRESH		_IO('M', 24)
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 /*
 | 
				
			||||||
 | 
					  * Obsolete legacy interface. Keep it in order not to break userspace
 | 
				
			||||||
@@ -0,0 +1,145 @@
 | 
				
			|||||||
 | 
					--- a/drivers/mtd/mtdpart.c
 | 
				
			||||||
 | 
					+++ b/drivers/mtd/mtdpart.c
 | 
				
			||||||
 | 
					@@ -35,6 +35,8 @@
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 #include "mtdcore.h"
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					+#define MTD_ERASE_PARTIAL	0x8000 /* partition only covers parts of an erase block */
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					 /* Our partition linked list */
 | 
				
			||||||
 | 
					 static LIST_HEAD(mtd_partitions);
 | 
				
			||||||
 | 
					 static DEFINE_MUTEX(mtd_partitions_mutex);
 | 
				
			||||||
 | 
					@@ -258,13 +260,60 @@ static int part_erase(struct mtd_info *m
 | 
				
			||||||
 | 
					 		return -EROFS;
 | 
				
			||||||
 | 
					 	if (instr->addr >= mtd->size)
 | 
				
			||||||
 | 
					 		return -EINVAL;
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	instr->partial_start = false;
 | 
				
			||||||
 | 
					+	if (mtd->flags & MTD_ERASE_PARTIAL) {
 | 
				
			||||||
 | 
					+		size_t readlen = 0;
 | 
				
			||||||
 | 
					+		u64 mtd_ofs;
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+		instr->erase_buf = kmalloc(part->master->erasesize, GFP_ATOMIC);
 | 
				
			||||||
 | 
					+		if (!instr->erase_buf)
 | 
				
			||||||
 | 
					+			return -ENOMEM;
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+		mtd_ofs = part->offset + instr->addr;
 | 
				
			||||||
 | 
					+		instr->erase_buf_ofs = do_div(mtd_ofs, part->master->erasesize);
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+		if (instr->erase_buf_ofs > 0) {
 | 
				
			||||||
 | 
					+			instr->addr -= instr->erase_buf_ofs;
 | 
				
			||||||
 | 
					+			ret = part->master->read(part->master,
 | 
				
			||||||
 | 
					+				instr->addr + part->offset,
 | 
				
			||||||
 | 
					+				part->master->erasesize,
 | 
				
			||||||
 | 
					+				&readlen, instr->erase_buf);
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+			instr->partial_start = true;
 | 
				
			||||||
 | 
					+		} else {
 | 
				
			||||||
 | 
					+			mtd_ofs = part->offset + part->mtd.size;
 | 
				
			||||||
 | 
					+			instr->erase_buf_ofs = part->master->erasesize -
 | 
				
			||||||
 | 
					+				do_div(mtd_ofs, part->master->erasesize);
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+			if (instr->erase_buf_ofs > 0) {
 | 
				
			||||||
 | 
					+				instr->len += instr->erase_buf_ofs;
 | 
				
			||||||
 | 
					+				ret = part->master->read(part->master,
 | 
				
			||||||
 | 
					+					part->offset + instr->addr +
 | 
				
			||||||
 | 
					+					instr->len - part->master->erasesize,
 | 
				
			||||||
 | 
					+					part->master->erasesize, &readlen,
 | 
				
			||||||
 | 
					+					instr->erase_buf);
 | 
				
			||||||
 | 
					+			} else {
 | 
				
			||||||
 | 
					+				ret = 0;
 | 
				
			||||||
 | 
					+			}
 | 
				
			||||||
 | 
					+		}
 | 
				
			||||||
 | 
					+		if (ret < 0) {
 | 
				
			||||||
 | 
					+			kfree(instr->erase_buf);
 | 
				
			||||||
 | 
					+			return ret;
 | 
				
			||||||
 | 
					+		}
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	}
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					 	instr->addr += part->offset;
 | 
				
			||||||
 | 
					 	ret = part->master->erase(part->master, instr);
 | 
				
			||||||
 | 
					 	if (ret) {
 | 
				
			||||||
 | 
					 		if (instr->fail_addr != MTD_FAIL_ADDR_UNKNOWN)
 | 
				
			||||||
 | 
					 			instr->fail_addr -= part->offset;
 | 
				
			||||||
 | 
					 		instr->addr -= part->offset;
 | 
				
			||||||
 | 
					+		if (mtd->flags & MTD_ERASE_PARTIAL)
 | 
				
			||||||
 | 
					+			kfree(instr->erase_buf);
 | 
				
			||||||
 | 
					 	}
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					 	return ret;
 | 
				
			||||||
 | 
					 }
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					@@ -272,7 +321,25 @@ void mtd_erase_callback(struct erase_inf
 | 
				
			||||||
 | 
					 {
 | 
				
			||||||
 | 
					 	if (instr->mtd->erase == part_erase) {
 | 
				
			||||||
 | 
					 		struct mtd_part *part = PART(instr->mtd);
 | 
				
			||||||
 | 
					+		size_t wrlen = 0;
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					+		if (instr->mtd->flags & MTD_ERASE_PARTIAL) {
 | 
				
			||||||
 | 
					+			if (instr->partial_start) {
 | 
				
			||||||
 | 
					+				part->master->write(part->master,
 | 
				
			||||||
 | 
					+					instr->addr, instr->erase_buf_ofs,
 | 
				
			||||||
 | 
					+					&wrlen, instr->erase_buf);
 | 
				
			||||||
 | 
					+				instr->addr += instr->erase_buf_ofs;
 | 
				
			||||||
 | 
					+			} else {
 | 
				
			||||||
 | 
					+				instr->len -= instr->erase_buf_ofs;
 | 
				
			||||||
 | 
					+				part->master->write(part->master,
 | 
				
			||||||
 | 
					+					instr->addr + instr->len,
 | 
				
			||||||
 | 
					+					instr->erase_buf_ofs, &wrlen,
 | 
				
			||||||
 | 
					+					instr->erase_buf +
 | 
				
			||||||
 | 
					+					part->master->erasesize -
 | 
				
			||||||
 | 
					+					instr->erase_buf_ofs);
 | 
				
			||||||
 | 
					+			}
 | 
				
			||||||
 | 
					+			kfree(instr->erase_buf);
 | 
				
			||||||
 | 
					+		}
 | 
				
			||||||
 | 
					 		if (instr->fail_addr != MTD_FAIL_ADDR_UNKNOWN)
 | 
				
			||||||
 | 
					 			instr->fail_addr -= part->offset;
 | 
				
			||||||
 | 
					 		instr->addr -= part->offset;
 | 
				
			||||||
 | 
					@@ -530,18 +597,24 @@ static struct mtd_part *allocate_partiti
 | 
				
			||||||
 | 
					 	if ((slave->mtd.flags & MTD_WRITEABLE) &&
 | 
				
			||||||
 | 
					 	    mtd_mod_by_eb(slave->offset, &slave->mtd)) {
 | 
				
			||||||
 | 
					 		/* Doesn't start on a boundary of major erase size */
 | 
				
			||||||
 | 
					-		/* FIXME: Let it be writable if it is on a boundary of
 | 
				
			||||||
 | 
					-		 * _minor_ erase size though */
 | 
				
			||||||
 | 
					-		slave->mtd.flags &= ~MTD_WRITEABLE;
 | 
				
			||||||
 | 
					-		printk(KERN_WARNING"mtd: partition \"%s\" doesn't start on an erase block boundary -- force read-only\n",
 | 
				
			||||||
 | 
					-			part->name);
 | 
				
			||||||
 | 
					+		slave->mtd.flags |= MTD_ERASE_PARTIAL;
 | 
				
			||||||
 | 
					+		if (((u32) slave->mtd.size) > master->erasesize)
 | 
				
			||||||
 | 
					+			slave->mtd.flags &= ~MTD_WRITEABLE;
 | 
				
			||||||
 | 
					+		else
 | 
				
			||||||
 | 
					+			slave->mtd.erasesize = slave->mtd.size;
 | 
				
			||||||
 | 
					 	}
 | 
				
			||||||
 | 
					 	if ((slave->mtd.flags & MTD_WRITEABLE) &&
 | 
				
			||||||
 | 
					-	    mtd_mod_by_eb(slave->mtd.size, &slave->mtd)) {
 | 
				
			||||||
 | 
					-		slave->mtd.flags &= ~MTD_WRITEABLE;
 | 
				
			||||||
 | 
					-		printk(KERN_WARNING"mtd: partition \"%s\" doesn't end on an erase block -- force read-only\n",
 | 
				
			||||||
 | 
					-			part->name);
 | 
				
			||||||
 | 
					+	    mtd_mod_by_eb(slave->offset + slave->mtd.size, &slave->mtd)) {
 | 
				
			||||||
 | 
					+		slave->mtd.flags |= MTD_ERASE_PARTIAL;
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+		if ((u32) slave->mtd.size > master->erasesize)
 | 
				
			||||||
 | 
					+			slave->mtd.flags &= ~MTD_WRITEABLE;
 | 
				
			||||||
 | 
					+		else
 | 
				
			||||||
 | 
					+			slave->mtd.erasesize = slave->mtd.size;
 | 
				
			||||||
 | 
					 	}
 | 
				
			||||||
 | 
					+	if ((slave->mtd.flags & (MTD_ERASE_PARTIAL|MTD_WRITEABLE)) == MTD_ERASE_PARTIAL)
 | 
				
			||||||
 | 
					+		printk(KERN_WARNING"mtd: partition \"%s\" must either start or end on erase block boundary or be smaller than an erase block -- forcing read-only\n",
 | 
				
			||||||
 | 
					+				part->name);
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 	slave->mtd.ecclayout = master->ecclayout;
 | 
				
			||||||
 | 
					 	if (master->block_isbad) {
 | 
				
			||||||
 | 
					--- a/include/linux/mtd/mtd.h
 | 
				
			||||||
 | 
					+++ b/include/linux/mtd/mtd.h
 | 
				
			||||||
 | 
					@@ -57,6 +57,10 @@ struct erase_info {
 | 
				
			||||||
 | 
					 	u_long priv;
 | 
				
			||||||
 | 
					 	u_char state;
 | 
				
			||||||
 | 
					 	struct erase_info *next;
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	u8 *erase_buf;
 | 
				
			||||||
 | 
					+	u32 erase_buf_ofs;
 | 
				
			||||||
 | 
					+	bool partial_start;
 | 
				
			||||||
 | 
					 };
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 struct mtd_erase_region_info {
 | 
				
			||||||
@@ -0,0 +1,18 @@
 | 
				
			|||||||
 | 
					--- a/include/linux/mtd/partitions.h
 | 
				
			||||||
 | 
					+++ b/include/linux/mtd/partitions.h
 | 
				
			||||||
 | 
					@@ -33,6 +33,7 @@
 | 
				
			||||||
 | 
					  * Note: writeable partitions require their size and offset be
 | 
				
			||||||
 | 
					  * erasesize aligned (e.g. use MTDPART_OFS_NEXTBLK).
 | 
				
			||||||
 | 
					  */
 | 
				
			||||||
 | 
					+struct mtd_info;
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 struct mtd_partition;
 | 
				
			||||||
 | 
					 struct mtd_partition {
 | 
				
			||||||
 | 
					@@ -49,7 +50,6 @@ struct mtd_partition {
 | 
				
			||||||
 | 
					 #define MTDPART_SIZ_FULL	(0)
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					-struct mtd_info;
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 /*
 | 
				
			||||||
 | 
					  * Functions dealing with the various ways of partitioning the space
 | 
				
			||||||
							
								
								
									
										30
									
								
								target/linux/generic/patches-3.1/420-redboot_space.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										30
									
								
								target/linux/generic/patches-3.1/420-redboot_space.patch
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,30 @@
 | 
				
			|||||||
 | 
					--- a/drivers/mtd/redboot.c
 | 
				
			||||||
 | 
					+++ b/drivers/mtd/redboot.c
 | 
				
			||||||
 | 
					@@ -267,14 +267,21 @@ static int parse_redboot_partitions(stru
 | 
				
			||||||
 | 
					 #endif
 | 
				
			||||||
 | 
					 		names += strlen(names)+1;
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					-#ifdef CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED
 | 
				
			||||||
 | 
					 		if(fl->next && fl->img->flash_base + fl->img->size + master->erasesize <= fl->next->img->flash_base) {
 | 
				
			||||||
 | 
					-			i++;
 | 
				
			||||||
 | 
					-			parts[i].offset = parts[i-1].size + parts[i-1].offset;
 | 
				
			||||||
 | 
					-			parts[i].size = fl->next->img->flash_base - parts[i].offset;
 | 
				
			||||||
 | 
					-			parts[i].name = nullname;
 | 
				
			||||||
 | 
					-		}
 | 
				
			||||||
 | 
					+			if (!strcmp(parts[i].name, "rootfs")) {
 | 
				
			||||||
 | 
					+				parts[i].size = fl->next->img->flash_base;
 | 
				
			||||||
 | 
					+				parts[i].size &= ~(master->erasesize - 1);
 | 
				
			||||||
 | 
					+				parts[i].size -= parts[i].offset;
 | 
				
			||||||
 | 
					+#ifdef CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED
 | 
				
			||||||
 | 
					+				nrparts--;
 | 
				
			||||||
 | 
					+			} else {
 | 
				
			||||||
 | 
					+				i++;
 | 
				
			||||||
 | 
					+				parts[i].offset = parts[i-1].size + parts[i-1].offset;
 | 
				
			||||||
 | 
					+				parts[i].size = fl->next->img->flash_base - parts[i].offset;
 | 
				
			||||||
 | 
					+				parts[i].name = nullname;
 | 
				
			||||||
 | 
					 #endif
 | 
				
			||||||
 | 
					+			}
 | 
				
			||||||
 | 
					+		}
 | 
				
			||||||
 | 
					 		tmp_fl = fl;
 | 
				
			||||||
 | 
					 		fl = fl->next;
 | 
				
			||||||
 | 
					 		kfree(tmp_fl);
 | 
				
			||||||
@@ -0,0 +1,60 @@
 | 
				
			|||||||
 | 
					--- a/drivers/mtd/redboot.c
 | 
				
			||||||
 | 
					+++ b/drivers/mtd/redboot.c
 | 
				
			||||||
 | 
					@@ -29,6 +29,8 @@
 | 
				
			||||||
 | 
					 #include <linux/mtd/mtd.h>
 | 
				
			||||||
 | 
					 #include <linux/mtd/partitions.h>
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					+#define BOARD_CONFIG_PART		"boardconfig"
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					 struct fis_image_desc {
 | 
				
			||||||
 | 
					     unsigned char name[16];      // Null terminated name
 | 
				
			||||||
 | 
					     uint32_t	  flash_base;    // Address within FLASH of image
 | 
				
			||||||
 | 
					@@ -59,6 +61,7 @@ static int parse_redboot_partitions(stru
 | 
				
			||||||
 | 
					                              struct mtd_partition **pparts,
 | 
				
			||||||
 | 
					                              unsigned long fis_origin)
 | 
				
			||||||
 | 
					 {
 | 
				
			||||||
 | 
					+	unsigned long max_offset = 0;
 | 
				
			||||||
 | 
					 	int nrparts = 0;
 | 
				
			||||||
 | 
					 	struct fis_image_desc *buf;
 | 
				
			||||||
 | 
					 	struct mtd_partition *parts;
 | 
				
			||||||
 | 
					@@ -227,14 +230,14 @@ static int parse_redboot_partitions(stru
 | 
				
			||||||
 | 
					 		}
 | 
				
			||||||
 | 
					 	}
 | 
				
			||||||
 | 
					 #endif
 | 
				
			||||||
 | 
					-	parts = kzalloc(sizeof(*parts)*nrparts + nulllen + namelen, GFP_KERNEL);
 | 
				
			||||||
 | 
					+	parts = kzalloc(sizeof(*parts) * (nrparts + 1) + nulllen + namelen + sizeof(BOARD_CONFIG_PART), GFP_KERNEL);
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 	if (!parts) {
 | 
				
			||||||
 | 
					 		ret = -ENOMEM;
 | 
				
			||||||
 | 
					 		goto out;
 | 
				
			||||||
 | 
					 	}
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					-	nullname = (char *)&parts[nrparts];
 | 
				
			||||||
 | 
					+	nullname = (char *)&parts[nrparts + 1];
 | 
				
			||||||
 | 
					 #ifdef CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED
 | 
				
			||||||
 | 
					 	if (nulllen > 0) {
 | 
				
			||||||
 | 
					 		strcpy(nullname, nullstring);
 | 
				
			||||||
 | 
					@@ -253,6 +256,8 @@ static int parse_redboot_partitions(stru
 | 
				
			||||||
 | 
					 	}
 | 
				
			||||||
 | 
					 #endif
 | 
				
			||||||
 | 
					 	for ( ; i<nrparts; i++) {
 | 
				
			||||||
 | 
					+		if(max_offset < buf[i].flash_base + buf[i].size)
 | 
				
			||||||
 | 
					+			max_offset = buf[i].flash_base + buf[i].size;
 | 
				
			||||||
 | 
					 		parts[i].size = fl->img->size;
 | 
				
			||||||
 | 
					 		parts[i].offset = fl->img->flash_base;
 | 
				
			||||||
 | 
					 		parts[i].name = names;
 | 
				
			||||||
 | 
					@@ -286,6 +291,14 @@ static int parse_redboot_partitions(stru
 | 
				
			||||||
 | 
					 		fl = fl->next;
 | 
				
			||||||
 | 
					 		kfree(tmp_fl);
 | 
				
			||||||
 | 
					 	}
 | 
				
			||||||
 | 
					+	if(master->size - max_offset >= master->erasesize)
 | 
				
			||||||
 | 
					+	{
 | 
				
			||||||
 | 
					+		parts[nrparts].size = master->size - max_offset;
 | 
				
			||||||
 | 
					+		parts[nrparts].offset = max_offset;
 | 
				
			||||||
 | 
					+		parts[nrparts].name = names;
 | 
				
			||||||
 | 
					+		strcpy(names, BOARD_CONFIG_PART);
 | 
				
			||||||
 | 
					+		nrparts++;
 | 
				
			||||||
 | 
					+	}
 | 
				
			||||||
 | 
					 	ret = nrparts;
 | 
				
			||||||
 | 
					 	*pparts = parts;
 | 
				
			||||||
 | 
					  out:
 | 
				
			||||||
@@ -0,0 +1,35 @@
 | 
				
			|||||||
 | 
					--- a/drivers/mtd/Kconfig
 | 
				
			||||||
 | 
					+++ b/drivers/mtd/Kconfig
 | 
				
			||||||
 | 
					@@ -157,6 +157,22 @@ config MTD_AR7_PARTS
 | 
				
			||||||
 | 
					 	---help---
 | 
				
			||||||
 | 
					 	  TI AR7 partitioning support
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					+config MTD_MYLOADER_PARTS
 | 
				
			||||||
 | 
					+	tristate "MyLoader partition parsing"
 | 
				
			||||||
 | 
					+	depends on ADM5120 || ATHEROS_AR231X || ATHEROS_AR71XX
 | 
				
			||||||
 | 
					+	---help---
 | 
				
			||||||
 | 
					+	  MyLoader is a bootloader which allows the user to define partitions
 | 
				
			||||||
 | 
					+	  in flash devices, by putting a table in the second erase block
 | 
				
			||||||
 | 
					+	  on the device, similar to a partition table. This table gives the 
 | 
				
			||||||
 | 
					+	  offsets and lengths of the user defined partitions.
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	  If you need code which can detect and parse these tables, and
 | 
				
			||||||
 | 
					+	  register MTD 'partitions' corresponding to each image detected,
 | 
				
			||||||
 | 
					+	  enable this option.
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	  You will still need the parsing functions to be called by the driver
 | 
				
			||||||
 | 
					+	  for your particular device. It won't happen automatically.
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					 comment "User Modules And Translation Layers"
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 config MTD_CHAR
 | 
				
			||||||
 | 
					--- a/drivers/mtd/Makefile
 | 
				
			||||||
 | 
					+++ b/drivers/mtd/Makefile
 | 
				
			||||||
 | 
					@@ -11,6 +11,7 @@ obj-$(CONFIG_MTD_REDBOOT_PARTS) += redbo
 | 
				
			||||||
 | 
					 obj-$(CONFIG_MTD_CMDLINE_PARTS) += cmdlinepart.o
 | 
				
			||||||
 | 
					 obj-$(CONFIG_MTD_AFS_PARTS)	+= afs.o
 | 
				
			||||||
 | 
					 obj-$(CONFIG_MTD_AR7_PARTS)	+= ar7part.o
 | 
				
			||||||
 | 
					+obj-$(CONFIG_MTD_MYLOADER_PARTS) += myloader.o
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 # 'Users' - code which presents functionality to userspace.
 | 
				
			||||||
 | 
					 obj-$(CONFIG_MTD_CHAR)		+= mtdchar.o
 | 
				
			||||||
							
								
								
									
										116
									
								
								target/linux/generic/patches-3.1/440-block2mtd_init.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										116
									
								
								target/linux/generic/patches-3.1/440-block2mtd_init.patch
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,116 @@
 | 
				
			|||||||
 | 
					--- a/drivers/mtd/devices/block2mtd.c
 | 
				
			||||||
 | 
					+++ b/drivers/mtd/devices/block2mtd.c
 | 
				
			||||||
 | 
					@@ -14,6 +14,7 @@
 | 
				
			||||||
 | 
					 #include <linux/list.h>
 | 
				
			||||||
 | 
					 #include <linux/init.h>
 | 
				
			||||||
 | 
					 #include <linux/mtd/mtd.h>
 | 
				
			||||||
 | 
					+#include <linux/mtd/partitions.h>
 | 
				
			||||||
 | 
					 #include <linux/buffer_head.h>
 | 
				
			||||||
 | 
					 #include <linux/mutex.h>
 | 
				
			||||||
 | 
					 #include <linux/mount.h>
 | 
				
			||||||
 | 
					@@ -232,11 +233,12 @@ static void block2mtd_free_device(struct
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 /* FIXME: ensure that mtd->size % erase_size == 0 */
 | 
				
			||||||
 | 
					-static struct block2mtd_dev *add_device(char *devname, int erase_size)
 | 
				
			||||||
 | 
					+static struct block2mtd_dev *add_device(char *devname, int erase_size, const char *mtdname)
 | 
				
			||||||
 | 
					 {
 | 
				
			||||||
 | 
					 	const fmode_t mode = FMODE_READ | FMODE_WRITE | FMODE_EXCL;
 | 
				
			||||||
 | 
					 	struct block_device *bdev;
 | 
				
			||||||
 | 
					 	struct block2mtd_dev *dev;
 | 
				
			||||||
 | 
					+	struct mtd_partition *part;
 | 
				
			||||||
 | 
					 	char *name;
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 	if (!devname)
 | 
				
			||||||
 | 
					@@ -275,13 +277,16 @@ static struct block2mtd_dev *add_device(
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 	/* Setup the MTD structure */
 | 
				
			||||||
 | 
					 	/* make the name contain the block device in */
 | 
				
			||||||
 | 
					-	name = kasprintf(GFP_KERNEL, "block2mtd: %s", devname);
 | 
				
			||||||
 | 
					+	if (!mtdname)
 | 
				
			||||||
 | 
					+		mtdname = devname;
 | 
				
			||||||
 | 
					+	name = kmalloc(strlen(mtdname) + 1, GFP_KERNEL);
 | 
				
			||||||
 | 
					 	if (!name)
 | 
				
			||||||
 | 
					 		goto devinit_err;
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					+	strcpy(name, mtdname);
 | 
				
			||||||
 | 
					 	dev->mtd.name = name;
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					-	dev->mtd.size = dev->blkdev->bd_inode->i_size & PAGE_MASK;
 | 
				
			||||||
 | 
					+	dev->mtd.size = dev->blkdev->bd_inode->i_size & PAGE_MASK & ~(erase_size - 1);
 | 
				
			||||||
 | 
					 	dev->mtd.erasesize = erase_size;
 | 
				
			||||||
 | 
					 	dev->mtd.writesize = 1;
 | 
				
			||||||
 | 
					 	dev->mtd.type = MTD_RAM;
 | 
				
			||||||
 | 
					@@ -294,14 +299,17 @@ static struct block2mtd_dev *add_device(
 | 
				
			||||||
 | 
					 	dev->mtd.priv = dev;
 | 
				
			||||||
 | 
					 	dev->mtd.owner = THIS_MODULE;
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					-	if (mtd_device_register(&dev->mtd, NULL, 0)) {
 | 
				
			||||||
 | 
					+	part = kzalloc(sizeof(struct mtd_partition), GFP_KERNEL);
 | 
				
			||||||
 | 
					+	part->name = name;
 | 
				
			||||||
 | 
					+	part->offset = 0;
 | 
				
			||||||
 | 
					+	part->size = dev->mtd.size;
 | 
				
			||||||
 | 
					+	if (mtd_device_register(&dev->mtd, part, 1)) {
 | 
				
			||||||
 | 
					 		/* Device didn't get added, so free the entry */
 | 
				
			||||||
 | 
					 		goto devinit_err;
 | 
				
			||||||
 | 
					 	}
 | 
				
			||||||
 | 
					 	list_add(&dev->list, &blkmtd_device_list);
 | 
				
			||||||
 | 
					 	INFO("mtd%d: [%s] erase_size = %dKiB [%d]", dev->mtd.index,
 | 
				
			||||||
 | 
					-			dev->mtd.name + strlen("block2mtd: "),
 | 
				
			||||||
 | 
					-			dev->mtd.erasesize >> 10, dev->mtd.erasesize);
 | 
				
			||||||
 | 
					+			mtdname, dev->mtd.erasesize >> 10, dev->mtd.erasesize);
 | 
				
			||||||
 | 
					 	return dev;
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 devinit_err:
 | 
				
			||||||
 | 
					@@ -374,9 +382,9 @@ static char block2mtd_paramline[80 + 12]
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 static int block2mtd_setup2(const char *val)
 | 
				
			||||||
 | 
					 {
 | 
				
			||||||
 | 
					-	char buf[80 + 12]; /* 80 for device, 12 for erase size */
 | 
				
			||||||
 | 
					+	char buf[80 + 12 + 80]; /* 80 for device, 12 for erase size, 80 for name */
 | 
				
			||||||
 | 
					 	char *str = buf;
 | 
				
			||||||
 | 
					-	char *token[2];
 | 
				
			||||||
 | 
					+	char *token[3];
 | 
				
			||||||
 | 
					 	char *name;
 | 
				
			||||||
 | 
					 	size_t erase_size = PAGE_SIZE;
 | 
				
			||||||
 | 
					 	int i, ret;
 | 
				
			||||||
 | 
					@@ -387,7 +395,7 @@ static int block2mtd_setup2(const char *
 | 
				
			||||||
 | 
					 	strcpy(str, val);
 | 
				
			||||||
 | 
					 	kill_final_newline(str);
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					-	for (i = 0; i < 2; i++)
 | 
				
			||||||
 | 
					+	for (i = 0; i < 3; i++)
 | 
				
			||||||
 | 
					 		token[i] = strsep(&str, ",");
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 	if (str)
 | 
				
			||||||
 | 
					@@ -406,8 +414,10 @@ static int block2mtd_setup2(const char *
 | 
				
			||||||
 | 
					 			parse_err("illegal erase size");
 | 
				
			||||||
 | 
					 		}
 | 
				
			||||||
 | 
					 	}
 | 
				
			||||||
 | 
					+	if (token[2] && (strlen(token[2]) + 1 > 80))
 | 
				
			||||||
 | 
					+		parse_err("mtd device name too long");
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					-	add_device(name, erase_size);
 | 
				
			||||||
 | 
					+	add_device(name, erase_size, token[2]);
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 	return 0;
 | 
				
			||||||
 | 
					 }
 | 
				
			||||||
 | 
					@@ -441,7 +451,7 @@ static int block2mtd_setup(const char *v
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 module_param_call(block2mtd, block2mtd_setup, NULL, NULL, 0200);
 | 
				
			||||||
 | 
					-MODULE_PARM_DESC(block2mtd, "Device to use. \"block2mtd=<dev>[,<erasesize>]\"");
 | 
				
			||||||
 | 
					+MODULE_PARM_DESC(block2mtd, "Device to use. \"block2mtd=<dev>[,<erasesize>[,<name>]]\"");
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 static int __init block2mtd_init(void)
 | 
				
			||||||
 | 
					 {
 | 
				
			||||||
 | 
					--- a/fs/partitions/check.c
 | 
				
			||||||
 | 
					+++ b/fs/partitions/check.c
 | 
				
			||||||
 | 
					@@ -664,6 +664,7 @@ rescan:
 | 
				
			||||||
 | 
					 	kfree(state);
 | 
				
			||||||
 | 
					 	return 0;
 | 
				
			||||||
 | 
					 }
 | 
				
			||||||
 | 
					+EXPORT_SYMBOL(rescan_partitions);
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 unsigned char *read_dev_sector(struct block_device *bdev, sector_t n, Sector *p)
 | 
				
			||||||
 | 
					 {
 | 
				
			||||||
							
								
								
									
										291
									
								
								target/linux/generic/patches-3.1/441-block2mtd_refresh.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										291
									
								
								target/linux/generic/patches-3.1/441-block2mtd_refresh.patch
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,291 @@
 | 
				
			|||||||
 | 
					--- a/drivers/mtd/devices/block2mtd.c
 | 
				
			||||||
 | 
					+++ b/drivers/mtd/devices/block2mtd.c
 | 
				
			||||||
 | 
					@@ -30,6 +30,8 @@ struct block2mtd_dev {
 | 
				
			||||||
 | 
					 	struct block_device *blkdev;
 | 
				
			||||||
 | 
					 	struct mtd_info mtd;
 | 
				
			||||||
 | 
					 	struct mutex write_mutex;
 | 
				
			||||||
 | 
					+	rwlock_t bdev_mutex;
 | 
				
			||||||
 | 
					+	char devname[0];
 | 
				
			||||||
 | 
					 };
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					@@ -82,6 +84,12 @@ static int block2mtd_erase(struct mtd_in
 | 
				
			||||||
 | 
					 	size_t len = instr->len;
 | 
				
			||||||
 | 
					 	int err;
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					+	read_lock(&dev->bdev_mutex);
 | 
				
			||||||
 | 
					+	if (!dev->blkdev) {
 | 
				
			||||||
 | 
					+		err = -EINVAL;
 | 
				
			||||||
 | 
					+		goto done;
 | 
				
			||||||
 | 
					+	}
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					 	instr->state = MTD_ERASING;
 | 
				
			||||||
 | 
					 	mutex_lock(&dev->write_mutex);
 | 
				
			||||||
 | 
					 	err = _block2mtd_erase(dev, from, len);
 | 
				
			||||||
 | 
					@@ -93,6 +101,10 @@ static int block2mtd_erase(struct mtd_in
 | 
				
			||||||
 | 
					 		instr->state = MTD_ERASE_DONE;
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 	mtd_erase_callback(instr);
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+done:
 | 
				
			||||||
 | 
					+	read_unlock(&dev->bdev_mutex);
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					 	return err;
 | 
				
			||||||
 | 
					 }
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					@@ -104,10 +116,14 @@ static int block2mtd_read(struct mtd_inf
 | 
				
			||||||
 | 
					 	struct page *page;
 | 
				
			||||||
 | 
					 	int index = from >> PAGE_SHIFT;
 | 
				
			||||||
 | 
					 	int offset = from & (PAGE_SIZE-1);
 | 
				
			||||||
 | 
					-	int cpylen;
 | 
				
			||||||
 | 
					+	int cpylen, err = 0;
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	read_lock(&dev->bdev_mutex);
 | 
				
			||||||
 | 
					+	if (!dev->blkdev || (from > mtd->size)) {
 | 
				
			||||||
 | 
					+		err = -EINVAL;
 | 
				
			||||||
 | 
					+		goto done;
 | 
				
			||||||
 | 
					+	}
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					-	if (from > mtd->size)
 | 
				
			||||||
 | 
					-		return -EINVAL;
 | 
				
			||||||
 | 
					 	if (from + len > mtd->size)
 | 
				
			||||||
 | 
					 		len = mtd->size - from;
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					@@ -122,10 +138,14 @@ static int block2mtd_read(struct mtd_inf
 | 
				
			||||||
 | 
					 		len = len - cpylen;
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 		page = page_read(dev->blkdev->bd_inode->i_mapping, index);
 | 
				
			||||||
 | 
					-		if (!page)
 | 
				
			||||||
 | 
					-			return -ENOMEM;
 | 
				
			||||||
 | 
					-		if (IS_ERR(page))
 | 
				
			||||||
 | 
					-			return PTR_ERR(page);
 | 
				
			||||||
 | 
					+		if (!page) {
 | 
				
			||||||
 | 
					+			err = -ENOMEM;
 | 
				
			||||||
 | 
					+			goto done;
 | 
				
			||||||
 | 
					+		}
 | 
				
			||||||
 | 
					+		if (IS_ERR(page)) {
 | 
				
			||||||
 | 
					+			err = PTR_ERR(page);
 | 
				
			||||||
 | 
					+			goto done;
 | 
				
			||||||
 | 
					+		}
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 		memcpy(buf, page_address(page) + offset, cpylen);
 | 
				
			||||||
 | 
					 		page_cache_release(page);
 | 
				
			||||||
 | 
					@@ -136,7 +156,10 @@ static int block2mtd_read(struct mtd_inf
 | 
				
			||||||
 | 
					 		offset = 0;
 | 
				
			||||||
 | 
					 		index++;
 | 
				
			||||||
 | 
					 	}
 | 
				
			||||||
 | 
					-	return 0;
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+done:
 | 
				
			||||||
 | 
					+	read_unlock(&dev->bdev_mutex);
 | 
				
			||||||
 | 
					+	return err;
 | 
				
			||||||
 | 
					 }
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					@@ -188,12 +211,22 @@ static int block2mtd_write(struct mtd_in
 | 
				
			||||||
 | 
					 		size_t *retlen, const u_char *buf)
 | 
				
			||||||
 | 
					 {
 | 
				
			||||||
 | 
					 	struct block2mtd_dev *dev = mtd->priv;
 | 
				
			||||||
 | 
					-	int err;
 | 
				
			||||||
 | 
					+	int err = 0;
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	read_lock(&dev->bdev_mutex);
 | 
				
			||||||
 | 
					+	if (!dev->blkdev) {
 | 
				
			||||||
 | 
					+		err = -EINVAL;
 | 
				
			||||||
 | 
					+		goto done;
 | 
				
			||||||
 | 
					+	}
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 	if (!len)
 | 
				
			||||||
 | 
					-		return 0;
 | 
				
			||||||
 | 
					-	if (to >= mtd->size)
 | 
				
			||||||
 | 
					-		return -ENOSPC;
 | 
				
			||||||
 | 
					+		goto done;
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	if (to >= mtd->size) {
 | 
				
			||||||
 | 
					+		err = -ENOSPC;
 | 
				
			||||||
 | 
					+		goto done;
 | 
				
			||||||
 | 
					+	}
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					 	if (to + len > mtd->size)
 | 
				
			||||||
 | 
					 		len = mtd->size - to;
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					@@ -202,6 +235,9 @@ static int block2mtd_write(struct mtd_in
 | 
				
			||||||
 | 
					 	mutex_unlock(&dev->write_mutex);
 | 
				
			||||||
 | 
					 	if (err > 0)
 | 
				
			||||||
 | 
					 		err = 0;
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+done:
 | 
				
			||||||
 | 
					+	read_unlock(&dev->bdev_mutex);
 | 
				
			||||||
 | 
					 	return err;
 | 
				
			||||||
 | 
					 }
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					@@ -210,33 +246,110 @@ static int block2mtd_write(struct mtd_in
 | 
				
			||||||
 | 
					 static void block2mtd_sync(struct mtd_info *mtd)
 | 
				
			||||||
 | 
					 {
 | 
				
			||||||
 | 
					 	struct block2mtd_dev *dev = mtd->priv;
 | 
				
			||||||
 | 
					+	read_lock(&dev->bdev_mutex);
 | 
				
			||||||
 | 
					+	if (dev->blkdev)
 | 
				
			||||||
 | 
					 	sync_blockdev(dev->blkdev);
 | 
				
			||||||
 | 
					+	read_unlock(&dev->bdev_mutex);
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					 	return;
 | 
				
			||||||
 | 
					 }
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					+static int _open_bdev(struct block2mtd_dev *dev)
 | 
				
			||||||
 | 
					+{
 | 
				
			||||||
 | 
					+	const fmode_t mode = FMODE_READ | FMODE_WRITE | FMODE_EXCL;
 | 
				
			||||||
 | 
					+	struct block_device *bdev;
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	/* Get a handle on the device */
 | 
				
			||||||
 | 
					+	bdev = blkdev_get_by_path(dev->devname, mode, dev);
 | 
				
			||||||
 | 
					+#ifndef MODULE
 | 
				
			||||||
 | 
					+	if (IS_ERR(bdev)) {
 | 
				
			||||||
 | 
					+		dev_t devt;
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+		/* We might not have rootfs mounted at this point. Try
 | 
				
			||||||
 | 
					+		   to resolve the device name by other means. */
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+		devt = name_to_dev_t(dev->devname);
 | 
				
			||||||
 | 
					+		if (devt)
 | 
				
			||||||
 | 
					+			bdev = blkdev_get_by_dev(devt, mode, dev);
 | 
				
			||||||
 | 
					+	}
 | 
				
			||||||
 | 
					+#endif
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	if (IS_ERR(bdev)) {
 | 
				
			||||||
 | 
					+		ERROR("error: cannot open device %s", dev->devname);
 | 
				
			||||||
 | 
					+		return 1;
 | 
				
			||||||
 | 
					+	}
 | 
				
			||||||
 | 
					+	dev->blkdev = bdev;
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	if (MAJOR(bdev->bd_dev) == MTD_BLOCK_MAJOR) {
 | 
				
			||||||
 | 
					+		ERROR("attempting to use an MTD device as a block device");
 | 
				
			||||||
 | 
					+		return 1;
 | 
				
			||||||
 | 
					+	}
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	return 0;
 | 
				
			||||||
 | 
					+}
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+static void _close_bdev(struct block2mtd_dev *dev)
 | 
				
			||||||
 | 
					+{
 | 
				
			||||||
 | 
					+	struct block_device *bdev;
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	if (!dev->blkdev)
 | 
				
			||||||
 | 
					+		return;
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	bdev = dev->blkdev;
 | 
				
			||||||
 | 
					+	invalidate_mapping_pages(dev->blkdev->bd_inode->i_mapping, 0, -1);
 | 
				
			||||||
 | 
					+	blkdev_put(dev->blkdev, FMODE_READ|FMODE_WRITE|FMODE_EXCL);
 | 
				
			||||||
 | 
					+	dev->blkdev = NULL;
 | 
				
			||||||
 | 
					+}
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					 static void block2mtd_free_device(struct block2mtd_dev *dev)
 | 
				
			||||||
 | 
					 {
 | 
				
			||||||
 | 
					 	if (!dev)
 | 
				
			||||||
 | 
					 		return;
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 	kfree(dev->mtd.name);
 | 
				
			||||||
 | 
					-
 | 
				
			||||||
 | 
					-	if (dev->blkdev) {
 | 
				
			||||||
 | 
					-		invalidate_mapping_pages(dev->blkdev->bd_inode->i_mapping,
 | 
				
			||||||
 | 
					-					0, -1);
 | 
				
			||||||
 | 
					-		blkdev_put(dev->blkdev, FMODE_READ|FMODE_WRITE|FMODE_EXCL);
 | 
				
			||||||
 | 
					-	}
 | 
				
			||||||
 | 
					-
 | 
				
			||||||
 | 
					+	_close_bdev(dev);
 | 
				
			||||||
 | 
					 	kfree(dev);
 | 
				
			||||||
 | 
					 }
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					-/* FIXME: ensure that mtd->size % erase_size == 0 */
 | 
				
			||||||
 | 
					-static struct block2mtd_dev *add_device(char *devname, int erase_size, const char *mtdname)
 | 
				
			||||||
 | 
					+static int block2mtd_refresh(struct mtd_info *mtd)
 | 
				
			||||||
 | 
					 {
 | 
				
			||||||
 | 
					-	const fmode_t mode = FMODE_READ | FMODE_WRITE | FMODE_EXCL;
 | 
				
			||||||
 | 
					+	struct block2mtd_dev *dev = mtd->priv;
 | 
				
			||||||
 | 
					 	struct block_device *bdev;
 | 
				
			||||||
 | 
					+	dev_t devt;
 | 
				
			||||||
 | 
					+	int err = 0;
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	/* no other mtd function can run at this point */
 | 
				
			||||||
 | 
					+	write_lock(&dev->bdev_mutex);
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	/* get the device number for the whole disk */
 | 
				
			||||||
 | 
					+	devt = MKDEV(MAJOR(dev->blkdev->bd_dev), 0);
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	/* close the old block device */
 | 
				
			||||||
 | 
					+	_close_bdev(dev);
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	/* open the whole disk, issue a partition rescan, then */
 | 
				
			||||||
 | 
					+	bdev = blkdev_get_by_dev(devt, FMODE_WRITE | FMODE_READ, mtd);
 | 
				
			||||||
 | 
					+	if (!bdev || !bdev->bd_disk)
 | 
				
			||||||
 | 
					+		err = -EINVAL;
 | 
				
			||||||
 | 
					+#ifndef CONFIG_MTD_BLOCK2MTD_MODULE
 | 
				
			||||||
 | 
					+	else
 | 
				
			||||||
 | 
					+		err = rescan_partitions(bdev->bd_disk, bdev);
 | 
				
			||||||
 | 
					+#endif
 | 
				
			||||||
 | 
					+	if (bdev)
 | 
				
			||||||
 | 
					+		blkdev_put(bdev, FMODE_READ|FMODE_WRITE|FMODE_EXCL);
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	/* try to open the partition block device again */
 | 
				
			||||||
 | 
					+	_open_bdev(dev);
 | 
				
			||||||
 | 
					+	write_unlock(&dev->bdev_mutex);
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	return err;
 | 
				
			||||||
 | 
					+}
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+/* FIXME: ensure that mtd->size % erase_size == 0 */
 | 
				
			||||||
 | 
					+static struct block2mtd_dev *add_device(char *devname, int erase_size, char *mtdname)
 | 
				
			||||||
 | 
					+{
 | 
				
			||||||
 | 
					 	struct block2mtd_dev *dev;
 | 
				
			||||||
 | 
					 	struct mtd_partition *part;
 | 
				
			||||||
 | 
					 	char *name;
 | 
				
			||||||
 | 
					@@ -244,36 +357,17 @@ static struct block2mtd_dev *add_device(
 | 
				
			||||||
 | 
					 	if (!devname)
 | 
				
			||||||
 | 
					 		return NULL;
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					-	dev = kzalloc(sizeof(struct block2mtd_dev), GFP_KERNEL);
 | 
				
			||||||
 | 
					+	dev = kzalloc(sizeof(struct block2mtd_dev) + strlen(devname) + 1, GFP_KERNEL);
 | 
				
			||||||
 | 
					 	if (!dev)
 | 
				
			||||||
 | 
					 		return NULL;
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					-	/* Get a handle on the device */
 | 
				
			||||||
 | 
					-	bdev = blkdev_get_by_path(devname, mode, dev);
 | 
				
			||||||
 | 
					-#ifndef MODULE
 | 
				
			||||||
 | 
					-	if (IS_ERR(bdev)) {
 | 
				
			||||||
 | 
					-
 | 
				
			||||||
 | 
					-		/* We might not have rootfs mounted at this point. Try
 | 
				
			||||||
 | 
					-		   to resolve the device name by other means. */
 | 
				
			||||||
 | 
					+	strcpy(dev->devname, devname);
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					-		dev_t devt = name_to_dev_t(devname);
 | 
				
			||||||
 | 
					-		if (devt)
 | 
				
			||||||
 | 
					-			bdev = blkdev_get_by_dev(devt, mode, dev);
 | 
				
			||||||
 | 
					-	}
 | 
				
			||||||
 | 
					-#endif
 | 
				
			||||||
 | 
					-
 | 
				
			||||||
 | 
					-	if (IS_ERR(bdev)) {
 | 
				
			||||||
 | 
					-		ERROR("error: cannot open device %s", devname);
 | 
				
			||||||
 | 
					+	if (_open_bdev(dev))
 | 
				
			||||||
 | 
					 		goto devinit_err;
 | 
				
			||||||
 | 
					-	}
 | 
				
			||||||
 | 
					-	dev->blkdev = bdev;
 | 
				
			||||||
 | 
					-
 | 
				
			||||||
 | 
					-	if (MAJOR(bdev->bd_dev) == MTD_BLOCK_MAJOR) {
 | 
				
			||||||
 | 
					-		ERROR("attempting to use an MTD device as a block device");
 | 
				
			||||||
 | 
					-		goto devinit_err;
 | 
				
			||||||
 | 
					-	}
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 	mutex_init(&dev->write_mutex);
 | 
				
			||||||
 | 
					+	rwlock_init(&dev->bdev_mutex);
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 	/* Setup the MTD structure */
 | 
				
			||||||
 | 
					 	/* make the name contain the block device in */
 | 
				
			||||||
 | 
					@@ -298,6 +392,7 @@ static struct block2mtd_dev *add_device(
 | 
				
			||||||
 | 
					 	dev->mtd.read = block2mtd_read;
 | 
				
			||||||
 | 
					 	dev->mtd.priv = dev;
 | 
				
			||||||
 | 
					 	dev->mtd.owner = THIS_MODULE;
 | 
				
			||||||
 | 
					+	dev->mtd.refresh_device = block2mtd_refresh;
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 	part = kzalloc(sizeof(struct mtd_partition), GFP_KERNEL);
 | 
				
			||||||
 | 
					 	part->name = name;
 | 
				
			||||||
							
								
								
									
										10
									
								
								target/linux/generic/patches-3.1/442-block2mtd_probe.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								target/linux/generic/patches-3.1/442-block2mtd_probe.patch
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,10 @@
 | 
				
			|||||||
 | 
					--- a/drivers/mtd/devices/block2mtd.c
 | 
				
			||||||
 | 
					+++ b/drivers/mtd/devices/block2mtd.c
 | 
				
			||||||
 | 
					@@ -269,6 +269,7 @@ static int _open_bdev(struct block2mtd_d
 | 
				
			||||||
 | 
					 		/* We might not have rootfs mounted at this point. Try
 | 
				
			||||||
 | 
					 		   to resolve the device name by other means. */
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					+		wait_for_device_probe();
 | 
				
			||||||
 | 
					 		devt = name_to_dev_t(dev->devname);
 | 
				
			||||||
 | 
					 		if (devt)
 | 
				
			||||||
 | 
					 			bdev = blkdev_get_by_dev(devt, mode, dev);
 | 
				
			||||||
@@ -0,0 +1,37 @@
 | 
				
			|||||||
 | 
					---
 | 
				
			||||||
 | 
					 drivers/mtd/nand/plat_nand.c |   13 ++++++++++++-
 | 
				
			||||||
 | 
					 include/linux/mtd/nand.h     |    1 +
 | 
				
			||||||
 | 
					 2 files changed, 13 insertions(+), 1 deletion(-)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					--- a/include/linux/mtd/nand.h
 | 
				
			||||||
 | 
					+++ b/include/linux/mtd/nand.h
 | 
				
			||||||
 | 
					@@ -625,6 +625,7 @@ struct platform_nand_chip {
 | 
				
			||||||
 | 
					 	int chip_delay;
 | 
				
			||||||
 | 
					 	unsigned int options;
 | 
				
			||||||
 | 
					 	const char **part_probe_types;
 | 
				
			||||||
 | 
					+	int (*chip_fixup)(struct mtd_info *mtd);
 | 
				
			||||||
 | 
					 	void (*set_parts)(uint64_t size, struct platform_nand_chip *chip);
 | 
				
			||||||
 | 
					 	void *priv;
 | 
				
			||||||
 | 
					 };
 | 
				
			||||||
 | 
					--- a/drivers/mtd/nand/plat_nand.c
 | 
				
			||||||
 | 
					+++ b/drivers/mtd/nand/plat_nand.c
 | 
				
			||||||
 | 
					@@ -94,7 +94,18 @@ static int __devinit plat_nand_probe(str
 | 
				
			||||||
 | 
					 	}
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 	/* Scan to find existence of the device */
 | 
				
			||||||
 | 
					-	if (nand_scan(&data->mtd, pdata->chip.nr_chips)) {
 | 
				
			||||||
 | 
					+	if (nand_scan_ident(&data->mtd, pdata->chip.nr_chips, NULL)) {
 | 
				
			||||||
 | 
					+		res = -ENXIO;
 | 
				
			||||||
 | 
					+		goto out;
 | 
				
			||||||
 | 
					+	}
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	if (pdata->chip.chip_fixup) {
 | 
				
			||||||
 | 
					+		res = pdata->chip.chip_fixup(&data->mtd);
 | 
				
			||||||
 | 
					+		if (res)
 | 
				
			||||||
 | 
					+			goto out;
 | 
				
			||||||
 | 
					+	}
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	if (nand_scan_tail(&data->mtd)) {
 | 
				
			||||||
 | 
					 		err = -ENXIO;
 | 
				
			||||||
 | 
					 		goto out;
 | 
				
			||||||
 | 
					 	}
 | 
				
			||||||
@@ -0,0 +1,12 @@
 | 
				
			|||||||
 | 
					--- 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);
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
@@ -0,0 +1,39 @@
 | 
				
			|||||||
 | 
					--- a/drivers/mtd/devices/m25p80.c
 | 
				
			||||||
 | 
					+++ b/drivers/mtd/devices/m25p80.c
 | 
				
			||||||
 | 
					@@ -44,6 +44,7 @@
 | 
				
			||||||
 | 
					 #define	OPCODE_BE_4K		0x20	/* Erase 4KiB block */
 | 
				
			||||||
 | 
					 #define	OPCODE_BE_32K		0x52	/* Erase 32KiB block */
 | 
				
			||||||
 | 
					 #define	OPCODE_CHIP_ERASE	0xc7	/* Erase whole flash chip */
 | 
				
			||||||
 | 
					+#define	OPCODE_BE_4K_PMC	0xd7	/* Erase 4KiB block on PMC chips*/
 | 
				
			||||||
 | 
					 #define	OPCODE_SE		0xd8	/* Sector erase (usually 64KiB) */
 | 
				
			||||||
 | 
					 #define	OPCODE_RDID		0x9f	/* Read JEDEC ID */
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					@@ -630,6 +631,7 @@ struct flash_info {
 | 
				
			||||||
 | 
					 	u16		flags;
 | 
				
			||||||
 | 
					 #define	SECT_4K		0x01		/* OPCODE_BE_4K works uniformly */
 | 
				
			||||||
 | 
					 #define	M25P_NO_ERASE	0x02		/* No erase command needed */
 | 
				
			||||||
 | 
					+#define	SECT_4K_PMC	0x04		/* OPCODE_BE_4K_PMC works uniformly */
 | 
				
			||||||
 | 
					 };
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 #define INFO(_jedec_id, _ext_id, _sector_size, _n_sectors, _flags)	\
 | 
				
			||||||
 | 
					@@ -689,6 +691,10 @@ static const struct spi_device_id m25p_i
 | 
				
			||||||
 | 
					 	{ "mx25l25635e", INFO(0xc22019, 0, 64 * 1024, 512, 0) },
 | 
				
			||||||
 | 
					 	{ "mx25l25655e", INFO(0xc22619, 0, 64 * 1024, 512, 0) },
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					+	/* PMC -- pm25x "blocks" are 32K, sectors are 4K */
 | 
				
			||||||
 | 
					+	{ "pm25lv512", INFO(0, 0, 32 * 1024, 2, SECT_4K_PMC) },
 | 
				
			||||||
 | 
					+	{ "pm25lv010", INFO(0, 0, 32 * 1024, 4, SECT_4K_PMC) },
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					 	/* Spansion -- single (large) sector size only, at least
 | 
				
			||||||
 | 
					 	 * for the chips listed here (without boot sectors).
 | 
				
			||||||
 | 
					 	 */
 | 
				
			||||||
 | 
					@@ -920,6 +926,9 @@ static int __devinit m25p_probe(struct s
 | 
				
			||||||
 | 
					 	if (info->flags & SECT_4K) {
 | 
				
			||||||
 | 
					 		flash->erase_opcode = OPCODE_BE_4K;
 | 
				
			||||||
 | 
					 		flash->mtd.erasesize = 4096;
 | 
				
			||||||
 | 
					+	} else if (info->flags & SECT_4K_PMC) {
 | 
				
			||||||
 | 
					+		flash->erase_opcode = OPCODE_BE_4K_PMC;
 | 
				
			||||||
 | 
					+		flash->mtd.erasesize = 4096;
 | 
				
			||||||
 | 
					 	} else {
 | 
				
			||||||
 | 
					 		flash->erase_opcode = OPCODE_SE;
 | 
				
			||||||
 | 
					 		flash->mtd.erasesize = info->sector_size;
 | 
				
			||||||
@@ -0,0 +1,10 @@
 | 
				
			|||||||
 | 
					--- a/drivers/mtd/devices/m25p80.c
 | 
				
			||||||
 | 
					+++ b/drivers/mtd/devices/m25p80.c
 | 
				
			||||||
 | 
					@@ -768,6 +768,7 @@ static const struct spi_device_id m25p_i
 | 
				
			||||||
 | 
					 	{ "w25q32", INFO(0xef4016, 0, 64 * 1024,  64, SECT_4K) },
 | 
				
			||||||
 | 
					 	{ "w25x64", INFO(0xef3017, 0, 64 * 1024, 128, SECT_4K) },
 | 
				
			||||||
 | 
					 	{ "w25q64", INFO(0xef4017, 0, 64 * 1024, 128, SECT_4K) },
 | 
				
			||||||
 | 
					+	{ "w25q128", INFO(0xef4018, 0, 64 * 1024, 256, SECT_4K) },
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 	/* Catalyst / On Semiconductor -- non-JEDEC */
 | 
				
			||||||
 | 
					 	{ "cat25c11", CAT25_INFO(  16, 8, 16, 1) },
 | 
				
			||||||
@@ -0,0 +1,12 @@
 | 
				
			|||||||
 | 
					--- a/drivers/mtd/mtdconcat.c
 | 
				
			||||||
 | 
					+++ b/drivers/mtd/mtdconcat.c
 | 
				
			||||||
 | 
					@@ -619,7 +619,8 @@ static void concat_sync(struct mtd_info
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 	for (i = 0; i < concat->num_subdev; i++) {
 | 
				
			||||||
 | 
					 		struct mtd_info *subdev = concat->subdev[i];
 | 
				
			||||||
 | 
					-		subdev->sync(subdev);
 | 
				
			||||||
 | 
					+		if (subdev->sync)
 | 
				
			||||||
 | 
					+			subdev->sync(subdev);
 | 
				
			||||||
 | 
					 	}
 | 
				
			||||||
 | 
					 }
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
@@ -0,0 +1,18 @@
 | 
				
			|||||||
 | 
					From: George Kashperko <george@znau.edu.ua>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Issue map read after Write Buffer Load command to ensure chip is ready
 | 
				
			||||||
 | 
					to receive data.
 | 
				
			||||||
 | 
					Signed-off-by: George Kashperko <george@znau.edu.ua>
 | 
				
			||||||
 | 
					---
 | 
				
			||||||
 | 
					 drivers/mtd/chips/cfi_cmdset_0002.c |    1 +
 | 
				
			||||||
 | 
					 1 file changed, 1 insertion(+)
 | 
				
			||||||
 | 
					--- a/drivers/mtd/chips/cfi_cmdset_0002.c
 | 
				
			||||||
 | 
					+++ b/drivers/mtd/chips/cfi_cmdset_0002.c
 | 
				
			||||||
 | 
					@@ -1412,6 +1412,7 @@ static int __xipram do_write_buffer(stru
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 	/* Write Buffer Load */
 | 
				
			||||||
 | 
					 	map_write(map, CMD(0x25), cmd_adr);
 | 
				
			||||||
 | 
					+	(void) map_read(map, cmd_adr);
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 	chip->state = FL_WRITING_TO_BUFFER;
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
							
								
								
									
										18
									
								
								target/linux/generic/patches-3.1/500-yaffs_support.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								target/linux/generic/patches-3.1/500-yaffs_support.patch
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,18 @@
 | 
				
			|||||||
 | 
					--- a/fs/Kconfig
 | 
				
			||||||
 | 
					+++ b/fs/Kconfig
 | 
				
			||||||
 | 
					@@ -35,6 +35,7 @@ source "fs/gfs2/Kconfig"
 | 
				
			||||||
 | 
					 source "fs/ocfs2/Kconfig"
 | 
				
			||||||
 | 
					 source "fs/btrfs/Kconfig"
 | 
				
			||||||
 | 
					 source "fs/nilfs2/Kconfig"
 | 
				
			||||||
 | 
					+source "fs/yaffs2/Kconfig"
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 endif # BLOCK
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					--- a/fs/Makefile
 | 
				
			||||||
 | 
					+++ b/fs/Makefile
 | 
				
			||||||
 | 
					@@ -124,3 +124,5 @@ obj-$(CONFIG_GFS2_FS)           += gfs2/
 | 
				
			||||||
 | 
					 obj-$(CONFIG_EXOFS_FS)          += exofs/
 | 
				
			||||||
 | 
					 obj-$(CONFIG_CEPH_FS)		+= ceph/
 | 
				
			||||||
 | 
					 obj-$(CONFIG_PSTORE)		+= pstore/
 | 
				
			||||||
 | 
					+obj-$(CONFIG_YAFFS_FS)		+= yaffs2/
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
							
								
								
									
										12344
									
								
								target/linux/generic/patches-3.1/501-yaffs_cvs_2009_04_24.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										12344
									
								
								target/linux/generic/patches-3.1/501-yaffs_cvs_2009_04_24.patch
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										27068
									
								
								target/linux/generic/patches-3.1/502-yaffs_git_2010_10_20.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										27068
									
								
								target/linux/generic/patches-3.1/502-yaffs_git_2010_10_20.patch
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										17
									
								
								target/linux/generic/patches-3.1/503-yaffs_symlink_bug.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								target/linux/generic/patches-3.1/503-yaffs_symlink_bug.patch
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,17 @@
 | 
				
			|||||||
 | 
					--- a/fs/yaffs2/yaffs_guts.c
 | 
				
			||||||
 | 
					+++ b/fs/yaffs2/yaffs_guts.c
 | 
				
			||||||
 | 
					@@ -1709,11 +1709,11 @@ static int yaffs_change_obj_name(yaffs_o
 | 
				
			||||||
 | 
					 	}
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 	/* TODO: Do we need this different handling for YAFFS2 and YAFFS1?? */
 | 
				
			||||||
 | 
					-	if (obj->my_dev->param.is_yaffs2)
 | 
				
			||||||
 | 
					+	// if (obj->my_dev->param.is_yaffs2) 
 | 
				
			||||||
 | 
					 		unlinkOp = (new_dir == obj->my_dev->unlinked_dir);
 | 
				
			||||||
 | 
					-	else
 | 
				
			||||||
 | 
					+	/* else
 | 
				
			||||||
 | 
					 		unlinkOp = (new_dir == obj->my_dev->unlinked_dir
 | 
				
			||||||
 | 
					-			    && obj->variant_type == YAFFS_OBJECT_TYPE_FILE);
 | 
				
			||||||
 | 
					+			    && obj->variant_type == YAFFS_OBJECT_TYPE_FILE); */
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 	deleteOp = (new_dir == obj->my_dev->del_dir);
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
							
								
								
									
										20
									
								
								target/linux/generic/patches-3.1/504-yaffs_mutex_fix.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								target/linux/generic/patches-3.1/504-yaffs_mutex_fix.patch
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,20 @@
 | 
				
			|||||||
 | 
					--- a/fs/yaffs2/yaffs_vfs_glue.c
 | 
				
			||||||
 | 
					+++ b/fs/yaffs2/yaffs_vfs_glue.c
 | 
				
			||||||
 | 
					@@ -3036,7 +3036,7 @@ static struct super_block *yaffs_interna
 | 
				
			||||||
 | 
					         YINIT_LIST_HEAD(&(yaffs_dev_to_lc(dev)->searchContexts));
 | 
				
			||||||
 | 
					         param->remove_obj_fn = yaffs_remove_obj_callback;
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					-	init_MUTEX(&(yaffs_dev_to_lc(dev)->grossLock));
 | 
				
			||||||
 | 
					+	sema_init(&(yaffs_dev_to_lc(dev)->grossLock), 1);
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 	yaffs_gross_lock(dev);
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					@@ -3494,7 +3494,7 @@ static int __init init_yaffs_fs(void)
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					-	init_MUTEX(&yaffs_context_lock);
 | 
				
			||||||
 | 
					+	sema_init((&yaffs_context_lock), 1);
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 	/* Install the proc_fs entries */
 | 
				
			||||||
 | 
					 	my_proc_entry = create_proc_entry("yaffs",
 | 
				
			||||||
							
								
								
									
										147
									
								
								target/linux/generic/patches-3.1/505-2.6.39_fix.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										147
									
								
								target/linux/generic/patches-3.1/505-2.6.39_fix.patch
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,147 @@
 | 
				
			|||||||
 | 
					--- a/fs/yaffs2/yaffs_vfs_glue.c
 | 
				
			||||||
 | 
					+++ b/fs/yaffs2/yaffs_vfs_glue.c
 | 
				
			||||||
 | 
					@@ -72,7 +72,7 @@
 | 
				
			||||||
 | 
					 #include <linux/init.h>
 | 
				
			||||||
 | 
					 #include <linux/fs.h>
 | 
				
			||||||
 | 
					 #include <linux/proc_fs.h>
 | 
				
			||||||
 | 
					-#include <linux/smp_lock.h>
 | 
				
			||||||
 | 
					+#include <linux/mutex.h>
 | 
				
			||||||
 | 
					 #include <linux/pagemap.h>
 | 
				
			||||||
 | 
					 #include <linux/mtd/mtd.h>
 | 
				
			||||||
 | 
					 #include <linux/interrupt.h>
 | 
				
			||||||
 | 
					@@ -97,6 +97,8 @@
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 #include <asm/div64.h>
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					+static DEFINE_MUTEX(yaffs_mutex);
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0))
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 #include <linux/statfs.h>
 | 
				
			||||||
 | 
					@@ -1538,7 +1540,7 @@ static loff_t yaffs_dir_llseek(struct fi
 | 
				
			||||||
 | 
					 {
 | 
				
			||||||
 | 
					 	long long retval;
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					-	lock_kernel();
 | 
				
			||||||
 | 
					+	mutex_lock(&yaffs_mutex);
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 	switch (origin){
 | 
				
			||||||
 | 
					 	case 2:
 | 
				
			||||||
 | 
					@@ -1555,7 +1557,7 @@ static loff_t yaffs_dir_llseek(struct fi
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 		retval = offset;
 | 
				
			||||||
 | 
					 	}
 | 
				
			||||||
 | 
					-	unlock_kernel();
 | 
				
			||||||
 | 
					+	mutex_unlock(&yaffs_mutex);
 | 
				
			||||||
 | 
					 	return retval;
 | 
				
			||||||
 | 
					 }
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					@@ -3087,98 +3089,52 @@ static struct super_block *yaffs_interna
 | 
				
			||||||
 | 
					 	return sb;
 | 
				
			||||||
 | 
					 }
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					-
 | 
				
			||||||
 | 
					-#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0))
 | 
				
			||||||
 | 
					 static int yaffs_internal_read_super_mtd(struct super_block *sb, void *data,
 | 
				
			||||||
 | 
					 					 int silent)
 | 
				
			||||||
 | 
					 {
 | 
				
			||||||
 | 
					 	return yaffs_internal_read_super(1, sb, data, silent) ? 0 : -EINVAL;
 | 
				
			||||||
 | 
					 }
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					-#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 17))
 | 
				
			||||||
 | 
					-static int yaffs_read_super(struct file_system_type *fs,
 | 
				
			||||||
 | 
					+static struct dentry *yaffs_read_super(struct file_system_type *fs,
 | 
				
			||||||
 | 
					 			    int flags, const char *dev_name,
 | 
				
			||||||
 | 
					-			    void *data, struct vfsmount *mnt)
 | 
				
			||||||
 | 
					-{
 | 
				
			||||||
 | 
					-
 | 
				
			||||||
 | 
					-	return get_sb_bdev(fs, flags, dev_name, data,
 | 
				
			||||||
 | 
					-			   yaffs_internal_read_super_mtd, mnt);
 | 
				
			||||||
 | 
					-}
 | 
				
			||||||
 | 
					-#else
 | 
				
			||||||
 | 
					-static struct super_block *yaffs_read_super(struct file_system_type *fs,
 | 
				
			||||||
 | 
					-					    int flags, const char *dev_name,
 | 
				
			||||||
 | 
					-					    void *data)
 | 
				
			||||||
 | 
					+			    void *data)
 | 
				
			||||||
 | 
					 {
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					-	return get_sb_bdev(fs, flags, dev_name, data,
 | 
				
			||||||
 | 
					+	return mount_bdev(fs, flags, dev_name, data,
 | 
				
			||||||
 | 
					 			   yaffs_internal_read_super_mtd);
 | 
				
			||||||
 | 
					 }
 | 
				
			||||||
 | 
					-#endif
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 static struct file_system_type yaffs_fs_type = {
 | 
				
			||||||
 | 
					 	.owner = THIS_MODULE,
 | 
				
			||||||
 | 
					 	.name = "yaffs",
 | 
				
			||||||
 | 
					-	.get_sb = yaffs_read_super,
 | 
				
			||||||
 | 
					+	.mount = yaffs_read_super,
 | 
				
			||||||
 | 
					 	.kill_sb = kill_block_super,
 | 
				
			||||||
 | 
					 	.fs_flags = FS_REQUIRES_DEV,
 | 
				
			||||||
 | 
					 };
 | 
				
			||||||
 | 
					-#else
 | 
				
			||||||
 | 
					-static struct super_block *yaffs_read_super(struct super_block *sb, void *data,
 | 
				
			||||||
 | 
					-					    int silent)
 | 
				
			||||||
 | 
					-{
 | 
				
			||||||
 | 
					-	return yaffs_internal_read_super(1, sb, data, silent);
 | 
				
			||||||
 | 
					-}
 | 
				
			||||||
 | 
					-
 | 
				
			||||||
 | 
					-static DECLARE_FSTYPE(yaffs_fs_type, "yaffs", yaffs_read_super,
 | 
				
			||||||
 | 
					-		      FS_REQUIRES_DEV);
 | 
				
			||||||
 | 
					-#endif
 | 
				
			||||||
 | 
					-
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 #ifdef CONFIG_YAFFS_YAFFS2
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					-#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0))
 | 
				
			||||||
 | 
					 static int yaffs2_internal_read_super_mtd(struct super_block *sb, void *data,
 | 
				
			||||||
 | 
					 					  int silent)
 | 
				
			||||||
 | 
					 {
 | 
				
			||||||
 | 
					 	return yaffs_internal_read_super(2, sb, data, silent) ? 0 : -EINVAL;
 | 
				
			||||||
 | 
					 }
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					-#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 17))
 | 
				
			||||||
 | 
					-static int yaffs2_read_super(struct file_system_type *fs,
 | 
				
			||||||
 | 
					-			int flags, const char *dev_name, void *data,
 | 
				
			||||||
 | 
					-			struct vfsmount *mnt)
 | 
				
			||||||
 | 
					+static struct dentry *yaffs2_read_super(struct file_system_type *fs,
 | 
				
			||||||
 | 
					+			int flags, const char *dev_name,
 | 
				
			||||||
 | 
					+			void *data)
 | 
				
			||||||
 | 
					 {
 | 
				
			||||||
 | 
					-	return get_sb_bdev(fs, flags, dev_name, data,
 | 
				
			||||||
 | 
					-			yaffs2_internal_read_super_mtd, mnt);
 | 
				
			||||||
 | 
					+	return mount_bdev(fs, flags, dev_name, data,
 | 
				
			||||||
 | 
					+		yaffs_internal_read_super_mtd);
 | 
				
			||||||
 | 
					 }
 | 
				
			||||||
 | 
					-#else
 | 
				
			||||||
 | 
					-static struct super_block *yaffs2_read_super(struct file_system_type *fs,
 | 
				
			||||||
 | 
					-					     int flags, const char *dev_name,
 | 
				
			||||||
 | 
					-					     void *data)
 | 
				
			||||||
 | 
					-{
 | 
				
			||||||
 | 
					-
 | 
				
			||||||
 | 
					-	return get_sb_bdev(fs, flags, dev_name, data,
 | 
				
			||||||
 | 
					-			   yaffs2_internal_read_super_mtd);
 | 
				
			||||||
 | 
					-}
 | 
				
			||||||
 | 
					-#endif
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 static struct file_system_type yaffs2_fs_type = {
 | 
				
			||||||
 | 
					 	.owner = THIS_MODULE,
 | 
				
			||||||
 | 
					 	.name = "yaffs2",
 | 
				
			||||||
 | 
					-	.get_sb = yaffs2_read_super,
 | 
				
			||||||
 | 
					+	.mount = yaffs2_read_super,
 | 
				
			||||||
 | 
					 	.kill_sb = kill_block_super,
 | 
				
			||||||
 | 
					 	.fs_flags = FS_REQUIRES_DEV,
 | 
				
			||||||
 | 
					 };
 | 
				
			||||||
 | 
					-#else
 | 
				
			||||||
 | 
					-static struct super_block *yaffs2_read_super(struct super_block *sb,
 | 
				
			||||||
 | 
					-					     void *data, int silent)
 | 
				
			||||||
 | 
					-{
 | 
				
			||||||
 | 
					-	return yaffs_internal_read_super(2, sb, data, silent);
 | 
				
			||||||
 | 
					-}
 | 
				
			||||||
 | 
					-
 | 
				
			||||||
 | 
					-static DECLARE_FSTYPE(yaffs2_fs_type, "yaffs2", yaffs2_read_super,
 | 
				
			||||||
 | 
					-		      FS_REQUIRES_DEV);
 | 
				
			||||||
 | 
					-#endif
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 #endif				/* CONFIG_YAFFS_YAFFS2 */
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
							
								
								
									
										5142
									
								
								target/linux/generic/patches-3.1/510-jffs2_make_lzma_available.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5142
									
								
								target/linux/generic/patches-3.1/510-jffs2_make_lzma_available.patch
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										485
									
								
								target/linux/generic/patches-3.1/511-debloat_lzma.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										485
									
								
								target/linux/generic/patches-3.1/511-debloat_lzma.patch
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,485 @@
 | 
				
			|||||||
 | 
					--- a/include/linux/lzma/LzmaDec.h
 | 
				
			||||||
 | 
					+++ b/include/linux/lzma/LzmaDec.h
 | 
				
			||||||
 | 
					@@ -31,14 +31,6 @@ typedef struct _CLzmaProps
 | 
				
			||||||
 | 
					   UInt32 dicSize;
 | 
				
			||||||
 | 
					 } CLzmaProps;
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					-/* LzmaProps_Decode - decodes properties
 | 
				
			||||||
 | 
					-Returns:
 | 
				
			||||||
 | 
					-  SZ_OK
 | 
				
			||||||
 | 
					-  SZ_ERROR_UNSUPPORTED - Unsupported properties
 | 
				
			||||||
 | 
					-*/
 | 
				
			||||||
 | 
					-
 | 
				
			||||||
 | 
					-SRes LzmaProps_Decode(CLzmaProps *p, const Byte *data, unsigned size);
 | 
				
			||||||
 | 
					-
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 /* ---------- LZMA Decoder state ---------- */
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					@@ -70,8 +62,6 @@ typedef struct
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 #define LzmaDec_Construct(p) { (p)->dic = 0; (p)->probs = 0; }
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					-void LzmaDec_Init(CLzmaDec *p);
 | 
				
			||||||
 | 
					-
 | 
				
			||||||
 | 
					 /* There are two types of LZMA streams:
 | 
				
			||||||
 | 
					      0) Stream with end mark. That end mark adds about 6 bytes to compressed size.
 | 
				
			||||||
 | 
					      1) Stream without end mark. You must know exact uncompressed size to decompress such stream. */
 | 
				
			||||||
 | 
					@@ -108,97 +98,6 @@ typedef enum
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 /* ELzmaStatus is used only as output value for function call */
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					-
 | 
				
			||||||
 | 
					-/* ---------- Interfaces ---------- */
 | 
				
			||||||
 | 
					-
 | 
				
			||||||
 | 
					-/* There are 3 levels of interfaces:
 | 
				
			||||||
 | 
					-     1) Dictionary Interface
 | 
				
			||||||
 | 
					-     2) Buffer Interface
 | 
				
			||||||
 | 
					-     3) One Call Interface
 | 
				
			||||||
 | 
					-   You can select any of these interfaces, but don't mix functions from different
 | 
				
			||||||
 | 
					-   groups for same object. */
 | 
				
			||||||
 | 
					-
 | 
				
			||||||
 | 
					-
 | 
				
			||||||
 | 
					-/* There are two variants to allocate state for Dictionary Interface:
 | 
				
			||||||
 | 
					-     1) LzmaDec_Allocate / LzmaDec_Free
 | 
				
			||||||
 | 
					-     2) LzmaDec_AllocateProbs / LzmaDec_FreeProbs
 | 
				
			||||||
 | 
					-   You can use variant 2, if you set dictionary buffer manually.
 | 
				
			||||||
 | 
					-   For Buffer Interface you must always use variant 1.
 | 
				
			||||||
 | 
					-
 | 
				
			||||||
 | 
					-LzmaDec_Allocate* can return:
 | 
				
			||||||
 | 
					-  SZ_OK
 | 
				
			||||||
 | 
					-  SZ_ERROR_MEM         - Memory allocation error
 | 
				
			||||||
 | 
					-  SZ_ERROR_UNSUPPORTED - Unsupported properties
 | 
				
			||||||
 | 
					-*/
 | 
				
			||||||
 | 
					-   
 | 
				
			||||||
 | 
					-SRes LzmaDec_AllocateProbs(CLzmaDec *p, const Byte *props, unsigned propsSize, ISzAlloc *alloc);
 | 
				
			||||||
 | 
					-void LzmaDec_FreeProbs(CLzmaDec *p, ISzAlloc *alloc);
 | 
				
			||||||
 | 
					-
 | 
				
			||||||
 | 
					-SRes LzmaDec_Allocate(CLzmaDec *state, const Byte *prop, unsigned propsSize, ISzAlloc *alloc);
 | 
				
			||||||
 | 
					-void LzmaDec_Free(CLzmaDec *state, ISzAlloc *alloc);
 | 
				
			||||||
 | 
					-
 | 
				
			||||||
 | 
					-/* ---------- Dictionary Interface ---------- */
 | 
				
			||||||
 | 
					-
 | 
				
			||||||
 | 
					-/* You can use it, if you want to eliminate the overhead for data copying from
 | 
				
			||||||
 | 
					-   dictionary to some other external buffer.
 | 
				
			||||||
 | 
					-   You must work with CLzmaDec variables directly in this interface.
 | 
				
			||||||
 | 
					-
 | 
				
			||||||
 | 
					-   STEPS:
 | 
				
			||||||
 | 
					-     LzmaDec_Constr()
 | 
				
			||||||
 | 
					-     LzmaDec_Allocate()
 | 
				
			||||||
 | 
					-     for (each new stream)
 | 
				
			||||||
 | 
					-     {
 | 
				
			||||||
 | 
					-       LzmaDec_Init()
 | 
				
			||||||
 | 
					-       while (it needs more decompression)
 | 
				
			||||||
 | 
					-       {
 | 
				
			||||||
 | 
					-         LzmaDec_DecodeToDic()
 | 
				
			||||||
 | 
					-         use data from CLzmaDec::dic and update CLzmaDec::dicPos
 | 
				
			||||||
 | 
					-       }
 | 
				
			||||||
 | 
					-     }
 | 
				
			||||||
 | 
					-     LzmaDec_Free()
 | 
				
			||||||
 | 
					-*/
 | 
				
			||||||
 | 
					-
 | 
				
			||||||
 | 
					-/* LzmaDec_DecodeToDic
 | 
				
			||||||
 | 
					-   
 | 
				
			||||||
 | 
					-   The decoding to internal dictionary buffer (CLzmaDec::dic).
 | 
				
			||||||
 | 
					-   You must manually update CLzmaDec::dicPos, if it reaches CLzmaDec::dicBufSize !!!
 | 
				
			||||||
 | 
					-
 | 
				
			||||||
 | 
					-finishMode:
 | 
				
			||||||
 | 
					-  It has meaning only if the decoding reaches output limit (dicLimit).
 | 
				
			||||||
 | 
					-  LZMA_FINISH_ANY - Decode just dicLimit bytes.
 | 
				
			||||||
 | 
					-  LZMA_FINISH_END - Stream must be finished after dicLimit.
 | 
				
			||||||
 | 
					-
 | 
				
			||||||
 | 
					-Returns:
 | 
				
			||||||
 | 
					-  SZ_OK
 | 
				
			||||||
 | 
					-    status:
 | 
				
			||||||
 | 
					-      LZMA_STATUS_FINISHED_WITH_MARK
 | 
				
			||||||
 | 
					-      LZMA_STATUS_NOT_FINISHED
 | 
				
			||||||
 | 
					-      LZMA_STATUS_NEEDS_MORE_INPUT
 | 
				
			||||||
 | 
					-      LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK
 | 
				
			||||||
 | 
					-  SZ_ERROR_DATA - Data error
 | 
				
			||||||
 | 
					-*/
 | 
				
			||||||
 | 
					-
 | 
				
			||||||
 | 
					-SRes LzmaDec_DecodeToDic(CLzmaDec *p, SizeT dicLimit,
 | 
				
			||||||
 | 
					-    const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status);
 | 
				
			||||||
 | 
					-
 | 
				
			||||||
 | 
					-
 | 
				
			||||||
 | 
					-/* ---------- Buffer Interface ---------- */
 | 
				
			||||||
 | 
					-
 | 
				
			||||||
 | 
					-/* It's zlib-like interface.
 | 
				
			||||||
 | 
					-   See LzmaDec_DecodeToDic description for information about STEPS and return results,
 | 
				
			||||||
 | 
					-   but you must use LzmaDec_DecodeToBuf instead of LzmaDec_DecodeToDic and you don't need
 | 
				
			||||||
 | 
					-   to work with CLzmaDec variables manually.
 | 
				
			||||||
 | 
					-
 | 
				
			||||||
 | 
					-finishMode:
 | 
				
			||||||
 | 
					-  It has meaning only if the decoding reaches output limit (*destLen).
 | 
				
			||||||
 | 
					-  LZMA_FINISH_ANY - Decode just destLen bytes.
 | 
				
			||||||
 | 
					-  LZMA_FINISH_END - Stream must be finished after (*destLen).
 | 
				
			||||||
 | 
					-*/
 | 
				
			||||||
 | 
					-
 | 
				
			||||||
 | 
					-SRes LzmaDec_DecodeToBuf(CLzmaDec *p, Byte *dest, SizeT *destLen,
 | 
				
			||||||
 | 
					-    const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status);
 | 
				
			||||||
 | 
					-
 | 
				
			||||||
 | 
					-
 | 
				
			||||||
 | 
					 /* ---------- One Call Interface ---------- */
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 /* LzmaDecode
 | 
				
			||||||
 | 
					--- a/lib/lzma/LzmaDec.c
 | 
				
			||||||
 | 
					+++ b/lib/lzma/LzmaDec.c
 | 
				
			||||||
 | 
					@@ -682,7 +682,7 @@ static void LzmaDec_InitRc(CLzmaDec *p,
 | 
				
			||||||
 | 
					   p->needFlush = 0;
 | 
				
			||||||
 | 
					 }
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					-void LzmaDec_InitDicAndState(CLzmaDec *p, Bool initDic, Bool initState)
 | 
				
			||||||
 | 
					+static void LzmaDec_InitDicAndState(CLzmaDec *p, Bool initDic, Bool initState)
 | 
				
			||||||
 | 
					 {
 | 
				
			||||||
 | 
					   p->needFlush = 1;
 | 
				
			||||||
 | 
					   p->remainLen = 0;
 | 
				
			||||||
 | 
					@@ -698,7 +698,7 @@ void LzmaDec_InitDicAndState(CLzmaDec *p
 | 
				
			||||||
 | 
					     p->needInitState = 1;
 | 
				
			||||||
 | 
					 }
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					-void LzmaDec_Init(CLzmaDec *p)
 | 
				
			||||||
 | 
					+static void LzmaDec_Init(CLzmaDec *p)
 | 
				
			||||||
 | 
					 {
 | 
				
			||||||
 | 
					   p->dicPos = 0;
 | 
				
			||||||
 | 
					   LzmaDec_InitDicAndState(p, True, True);
 | 
				
			||||||
 | 
					@@ -716,7 +716,7 @@ static void LzmaDec_InitStateReal(CLzmaD
 | 
				
			||||||
 | 
					   p->needInitState = 0;
 | 
				
			||||||
 | 
					 }
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					-SRes LzmaDec_DecodeToDic(CLzmaDec *p, SizeT dicLimit, const Byte *src, SizeT *srcLen,
 | 
				
			||||||
 | 
					+static SRes LzmaDec_DecodeToDic(CLzmaDec *p, SizeT dicLimit, const Byte *src, SizeT *srcLen,
 | 
				
			||||||
 | 
					     ELzmaFinishMode finishMode, ELzmaStatus *status)
 | 
				
			||||||
 | 
					 {
 | 
				
			||||||
 | 
					   SizeT inSize = *srcLen;
 | 
				
			||||||
 | 
					@@ -837,7 +837,7 @@ SRes LzmaDec_DecodeToDic(CLzmaDec *p, Si
 | 
				
			||||||
 | 
					   return (p->code == 0) ? SZ_OK : SZ_ERROR_DATA;
 | 
				
			||||||
 | 
					 }
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					-SRes LzmaDec_DecodeToBuf(CLzmaDec *p, Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status)
 | 
				
			||||||
 | 
					+static __maybe_unused SRes LzmaDec_DecodeToBuf(CLzmaDec *p, Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status)
 | 
				
			||||||
 | 
					 {
 | 
				
			||||||
 | 
					   SizeT outSize = *destLen;
 | 
				
			||||||
 | 
					   SizeT inSize = *srcLen;
 | 
				
			||||||
 | 
					@@ -877,7 +877,7 @@ SRes LzmaDec_DecodeToBuf(CLzmaDec *p, By
 | 
				
			||||||
 | 
					   }
 | 
				
			||||||
 | 
					 }
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					-void LzmaDec_FreeProbs(CLzmaDec *p, ISzAlloc *alloc)
 | 
				
			||||||
 | 
					+static void LzmaDec_FreeProbs(CLzmaDec *p, ISzAlloc *alloc)
 | 
				
			||||||
 | 
					 {
 | 
				
			||||||
 | 
					   alloc->Free(alloc, p->probs);
 | 
				
			||||||
 | 
					   p->probs = 0;
 | 
				
			||||||
 | 
					@@ -889,13 +889,13 @@ static void LzmaDec_FreeDict(CLzmaDec *p
 | 
				
			||||||
 | 
					   p->dic = 0;
 | 
				
			||||||
 | 
					 }
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					-void LzmaDec_Free(CLzmaDec *p, ISzAlloc *alloc)
 | 
				
			||||||
 | 
					+static void __maybe_unused LzmaDec_Free(CLzmaDec *p, ISzAlloc *alloc)
 | 
				
			||||||
 | 
					 {
 | 
				
			||||||
 | 
					   LzmaDec_FreeProbs(p, alloc);
 | 
				
			||||||
 | 
					   LzmaDec_FreeDict(p, alloc);
 | 
				
			||||||
 | 
					 }
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					-SRes LzmaProps_Decode(CLzmaProps *p, const Byte *data, unsigned size)
 | 
				
			||||||
 | 
					+static SRes LzmaProps_Decode(CLzmaProps *p, const Byte *data, unsigned size)
 | 
				
			||||||
 | 
					 {
 | 
				
			||||||
 | 
					   UInt32 dicSize;
 | 
				
			||||||
 | 
					   Byte d;
 | 
				
			||||||
 | 
					@@ -935,7 +935,7 @@ static SRes LzmaDec_AllocateProbs2(CLzma
 | 
				
			||||||
 | 
					   return SZ_OK;
 | 
				
			||||||
 | 
					 }
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					-SRes LzmaDec_AllocateProbs(CLzmaDec *p, const Byte *props, unsigned propsSize, ISzAlloc *alloc)
 | 
				
			||||||
 | 
					+static SRes __maybe_unused LzmaDec_AllocateProbs(CLzmaDec *p, const Byte *props, unsigned propsSize, ISzAlloc *alloc)
 | 
				
			||||||
 | 
					 {
 | 
				
			||||||
 | 
					   CLzmaProps propNew;
 | 
				
			||||||
 | 
					   RINOK(LzmaProps_Decode(&propNew, props, propsSize));
 | 
				
			||||||
 | 
					@@ -944,7 +944,7 @@ SRes LzmaDec_AllocateProbs(CLzmaDec *p,
 | 
				
			||||||
 | 
					   return SZ_OK;
 | 
				
			||||||
 | 
					 }
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					-SRes LzmaDec_Allocate(CLzmaDec *p, const Byte *props, unsigned propsSize, ISzAlloc *alloc)
 | 
				
			||||||
 | 
					+static SRes __maybe_unused LzmaDec_Allocate(CLzmaDec *p, const Byte *props, unsigned propsSize, ISzAlloc *alloc)
 | 
				
			||||||
 | 
					 {
 | 
				
			||||||
 | 
					   CLzmaProps propNew;
 | 
				
			||||||
 | 
					   SizeT dicBufSize;
 | 
				
			||||||
 | 
					--- a/include/linux/lzma/LzmaEnc.h
 | 
				
			||||||
 | 
					+++ b/include/linux/lzma/LzmaEnc.h
 | 
				
			||||||
 | 
					@@ -31,9 +31,6 @@ typedef struct _CLzmaEncProps
 | 
				
			||||||
 | 
					 } CLzmaEncProps;
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 void LzmaEncProps_Init(CLzmaEncProps *p);
 | 
				
			||||||
 | 
					-void LzmaEncProps_Normalize(CLzmaEncProps *p);
 | 
				
			||||||
 | 
					-UInt32 LzmaEncProps_GetDictSize(const CLzmaEncProps *props2);
 | 
				
			||||||
 | 
					-
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 /* ---------- CLzmaEncHandle Interface ---------- */
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					@@ -53,26 +50,9 @@ CLzmaEncHandle LzmaEnc_Create(ISzAlloc *
 | 
				
			||||||
 | 
					 void LzmaEnc_Destroy(CLzmaEncHandle p, ISzAlloc *alloc, ISzAlloc *allocBig);
 | 
				
			||||||
 | 
					 SRes LzmaEnc_SetProps(CLzmaEncHandle p, const CLzmaEncProps *props);
 | 
				
			||||||
 | 
					 SRes LzmaEnc_WriteProperties(CLzmaEncHandle p, Byte *properties, SizeT *size);
 | 
				
			||||||
 | 
					-SRes LzmaEnc_Encode(CLzmaEncHandle p, ISeqOutStream *outStream, ISeqInStream *inStream,
 | 
				
			||||||
 | 
					-    ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig);
 | 
				
			||||||
 | 
					 SRes LzmaEnc_MemEncode(CLzmaEncHandle p, Byte *dest, SizeT *destLen, const Byte *src, SizeT srcLen,
 | 
				
			||||||
 | 
					     int writeEndMark, ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig);
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					-/* ---------- One Call Interface ---------- */
 | 
				
			||||||
 | 
					-
 | 
				
			||||||
 | 
					-/* LzmaEncode
 | 
				
			||||||
 | 
					-Return code:
 | 
				
			||||||
 | 
					-  SZ_OK               - OK
 | 
				
			||||||
 | 
					-  SZ_ERROR_MEM        - Memory allocation error
 | 
				
			||||||
 | 
					-  SZ_ERROR_PARAM      - Incorrect paramater
 | 
				
			||||||
 | 
					-  SZ_ERROR_OUTPUT_EOF - output buffer overflow
 | 
				
			||||||
 | 
					-  SZ_ERROR_THREAD     - errors in multithreading functions (only for Mt version)
 | 
				
			||||||
 | 
					-*/
 | 
				
			||||||
 | 
					-
 | 
				
			||||||
 | 
					-SRes LzmaEncode(Byte *dest, SizeT *destLen, const Byte *src, SizeT srcLen,
 | 
				
			||||||
 | 
					-    const CLzmaEncProps *props, Byte *propsEncoded, SizeT *propsSize, int writeEndMark,
 | 
				
			||||||
 | 
					-    ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig);
 | 
				
			||||||
 | 
					-
 | 
				
			||||||
 | 
					 #ifdef __cplusplus
 | 
				
			||||||
 | 
					 }
 | 
				
			||||||
 | 
					 #endif
 | 
				
			||||||
 | 
					--- a/lib/lzma/LzmaEnc.c
 | 
				
			||||||
 | 
					+++ b/lib/lzma/LzmaEnc.c
 | 
				
			||||||
 | 
					@@ -53,7 +53,7 @@ void LzmaEncProps_Init(CLzmaEncProps *p)
 | 
				
			||||||
 | 
					   p->writeEndMark = 0;
 | 
				
			||||||
 | 
					 }
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					-void LzmaEncProps_Normalize(CLzmaEncProps *p)
 | 
				
			||||||
 | 
					+static void LzmaEncProps_Normalize(CLzmaEncProps *p)
 | 
				
			||||||
 | 
					 {
 | 
				
			||||||
 | 
					   int level = p->level;
 | 
				
			||||||
 | 
					   if (level < 0) level = 5;
 | 
				
			||||||
 | 
					@@ -76,7 +76,7 @@ void LzmaEncProps_Normalize(CLzmaEncProp
 | 
				
			||||||
 | 
					       #endif
 | 
				
			||||||
 | 
					 }
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					-UInt32 LzmaEncProps_GetDictSize(const CLzmaEncProps *props2)
 | 
				
			||||||
 | 
					+static UInt32 __maybe_unused LzmaEncProps_GetDictSize(const CLzmaEncProps *props2)
 | 
				
			||||||
 | 
					 {
 | 
				
			||||||
 | 
					   CLzmaEncProps props = *props2;
 | 
				
			||||||
 | 
					   LzmaEncProps_Normalize(&props);
 | 
				
			||||||
 | 
					@@ -93,7 +93,7 @@ UInt32 LzmaEncProps_GetDictSize(const CL
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 #define BSR2_RET(pos, res) { unsigned long i; _BitScanReverse(&i, (pos)); res = (i + i) + ((pos >> (i - 1)) & 1); }
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					-UInt32 GetPosSlot1(UInt32 pos)
 | 
				
			||||||
 | 
					+static UInt32 GetPosSlot1(UInt32 pos)
 | 
				
			||||||
 | 
					 {
 | 
				
			||||||
 | 
					   UInt32 res;
 | 
				
			||||||
 | 
					   BSR2_RET(pos, res);
 | 
				
			||||||
 | 
					@@ -107,7 +107,7 @@ UInt32 GetPosSlot1(UInt32 pos)
 | 
				
			||||||
 | 
					 #define kNumLogBits (9 + (int)sizeof(size_t) / 2)
 | 
				
			||||||
 | 
					 #define kDicLogSizeMaxCompress ((kNumLogBits - 1) * 2 + 7)
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					-void LzmaEnc_FastPosInit(Byte *g_FastPos)
 | 
				
			||||||
 | 
					+static void LzmaEnc_FastPosInit(Byte *g_FastPos)
 | 
				
			||||||
 | 
					 {
 | 
				
			||||||
 | 
					   int c = 2, slotFast;
 | 
				
			||||||
 | 
					   g_FastPos[0] = 0;
 | 
				
			||||||
 | 
					@@ -339,7 +339,7 @@ typedef struct
 | 
				
			||||||
 | 
					   CSaveState saveState;
 | 
				
			||||||
 | 
					 } CLzmaEnc;
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					-void LzmaEnc_SaveState(CLzmaEncHandle pp)
 | 
				
			||||||
 | 
					+static void __maybe_unused LzmaEnc_SaveState(CLzmaEncHandle pp)
 | 
				
			||||||
 | 
					 {
 | 
				
			||||||
 | 
					   CLzmaEnc *p = (CLzmaEnc *)pp;
 | 
				
			||||||
 | 
					   CSaveState *dest = &p->saveState;
 | 
				
			||||||
 | 
					@@ -365,7 +365,7 @@ void LzmaEnc_SaveState(CLzmaEncHandle pp
 | 
				
			||||||
 | 
					   memcpy(dest->litProbs, p->litProbs, (0x300 << p->lclp) * sizeof(CLzmaProb));
 | 
				
			||||||
 | 
					 }
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					-void LzmaEnc_RestoreState(CLzmaEncHandle pp)
 | 
				
			||||||
 | 
					+static void __maybe_unused LzmaEnc_RestoreState(CLzmaEncHandle pp)
 | 
				
			||||||
 | 
					 {
 | 
				
			||||||
 | 
					   CLzmaEnc *dest = (CLzmaEnc *)pp;
 | 
				
			||||||
 | 
					   const CSaveState *p = &dest->saveState;
 | 
				
			||||||
 | 
					@@ -600,7 +600,7 @@ static void LitEnc_EncodeMatched(CRangeE
 | 
				
			||||||
 | 
					   while (symbol < 0x10000);
 | 
				
			||||||
 | 
					 }
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					-void LzmaEnc_InitPriceTables(UInt32 *ProbPrices)
 | 
				
			||||||
 | 
					+static void LzmaEnc_InitPriceTables(UInt32 *ProbPrices)
 | 
				
			||||||
 | 
					 {
 | 
				
			||||||
 | 
					   UInt32 i;
 | 
				
			||||||
 | 
					   for (i = (1 << kNumMoveReducingBits) / 2; i < kBitModelTotal; i += (1 << kNumMoveReducingBits))
 | 
				
			||||||
 | 
					@@ -1676,7 +1676,7 @@ static void FillDistancesPrices(CLzmaEnc
 | 
				
			||||||
 | 
					   p->matchPriceCount = 0;
 | 
				
			||||||
 | 
					 }
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					-void LzmaEnc_Construct(CLzmaEnc *p)
 | 
				
			||||||
 | 
					+static void LzmaEnc_Construct(CLzmaEnc *p)
 | 
				
			||||||
 | 
					 {
 | 
				
			||||||
 | 
					   RangeEnc_Construct(&p->rc);
 | 
				
			||||||
 | 
					   MatchFinder_Construct(&p->matchFinderBase);
 | 
				
			||||||
 | 
					@@ -1709,7 +1709,7 @@ CLzmaEncHandle LzmaEnc_Create(ISzAlloc *
 | 
				
			||||||
 | 
					   return p;
 | 
				
			||||||
 | 
					 }
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					-void LzmaEnc_FreeLits(CLzmaEnc *p, ISzAlloc *alloc)
 | 
				
			||||||
 | 
					+static void LzmaEnc_FreeLits(CLzmaEnc *p, ISzAlloc *alloc)
 | 
				
			||||||
 | 
					 {
 | 
				
			||||||
 | 
					   alloc->Free(alloc, p->litProbs);
 | 
				
			||||||
 | 
					   alloc->Free(alloc, p->saveState.litProbs);
 | 
				
			||||||
 | 
					@@ -2074,7 +2074,7 @@ SRes LzmaEnc_MemPrepare(CLzmaEncHandle p
 | 
				
			||||||
 | 
					   return LzmaEnc_AllocAndInit(p, keepWindowSize, alloc, allocBig);
 | 
				
			||||||
 | 
					 }
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					-void LzmaEnc_Finish(CLzmaEncHandle pp)
 | 
				
			||||||
 | 
					+static void LzmaEnc_Finish(CLzmaEncHandle pp)
 | 
				
			||||||
 | 
					 {
 | 
				
			||||||
 | 
					   #ifndef _7ZIP_ST
 | 
				
			||||||
 | 
					   CLzmaEnc *p = (CLzmaEnc *)pp;
 | 
				
			||||||
 | 
					@@ -2108,7 +2108,7 @@ static size_t MyWrite(void *pp, const vo
 | 
				
			||||||
 | 
					 }
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					-UInt32 LzmaEnc_GetNumAvailableBytes(CLzmaEncHandle pp)
 | 
				
			||||||
 | 
					+static UInt32 __maybe_unused LzmaEnc_GetNumAvailableBytes(CLzmaEncHandle pp)
 | 
				
			||||||
 | 
					 {
 | 
				
			||||||
 | 
					   const CLzmaEnc *p = (CLzmaEnc *)pp;
 | 
				
			||||||
 | 
					   return p->matchFinder.GetNumAvailableBytes(p->matchFinderObj);
 | 
				
			||||||
 | 
					@@ -2120,7 +2120,7 @@ const Byte *LzmaEnc_GetCurBuf(CLzmaEncHa
 | 
				
			||||||
 | 
					   return p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - p->additionalOffset;
 | 
				
			||||||
 | 
					 }
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					-SRes LzmaEnc_CodeOneMemBlock(CLzmaEncHandle pp, Bool reInit,
 | 
				
			||||||
 | 
					+static SRes __maybe_unused LzmaEnc_CodeOneMemBlock(CLzmaEncHandle pp, Bool reInit,
 | 
				
			||||||
 | 
					     Byte *dest, size_t *destLen, UInt32 desiredPackSize, UInt32 *unpackSize)
 | 
				
			||||||
 | 
					 {
 | 
				
			||||||
 | 
					   CLzmaEnc *p = (CLzmaEnc *)pp;
 | 
				
			||||||
 | 
					@@ -2248,7 +2248,7 @@ SRes LzmaEnc_MemEncode(CLzmaEncHandle pp
 | 
				
			||||||
 | 
					   return res;
 | 
				
			||||||
 | 
					 }
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					-SRes LzmaEncode(Byte *dest, SizeT *destLen, const Byte *src, SizeT srcLen,
 | 
				
			||||||
 | 
					+static __maybe_unused SRes LzmaEncode(Byte *dest, SizeT *destLen, const Byte *src, SizeT srcLen,
 | 
				
			||||||
 | 
					     const CLzmaEncProps *props, Byte *propsEncoded, SizeT *propsSize, int writeEndMark,
 | 
				
			||||||
 | 
					     ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig)
 | 
				
			||||||
 | 
					 {
 | 
				
			||||||
 | 
					--- a/include/linux/lzma/LzFind.h
 | 
				
			||||||
 | 
					+++ b/include/linux/lzma/LzFind.h
 | 
				
			||||||
 | 
					@@ -55,11 +55,6 @@ typedef struct _CMatchFinder
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 #define Inline_MatchFinder_GetNumAvailableBytes(p) ((p)->streamPos - (p)->pos)
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					-int MatchFinder_NeedMove(CMatchFinder *p);
 | 
				
			||||||
 | 
					-Byte *MatchFinder_GetPointerToCurrentPos(CMatchFinder *p);
 | 
				
			||||||
 | 
					-void MatchFinder_MoveBlock(CMatchFinder *p);
 | 
				
			||||||
 | 
					-void MatchFinder_ReadIfRequired(CMatchFinder *p);
 | 
				
			||||||
 | 
					-
 | 
				
			||||||
 | 
					 void MatchFinder_Construct(CMatchFinder *p);
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 /* Conditions:
 | 
				
			||||||
 | 
					@@ -70,12 +65,6 @@ int MatchFinder_Create(CMatchFinder *p,
 | 
				
			||||||
 | 
					     UInt32 keepAddBufferBefore, UInt32 matchMaxLen, UInt32 keepAddBufferAfter,
 | 
				
			||||||
 | 
					     ISzAlloc *alloc);
 | 
				
			||||||
 | 
					 void MatchFinder_Free(CMatchFinder *p, ISzAlloc *alloc);
 | 
				
			||||||
 | 
					-void MatchFinder_Normalize3(UInt32 subValue, CLzRef *items, UInt32 numItems);
 | 
				
			||||||
 | 
					-void MatchFinder_ReduceOffsets(CMatchFinder *p, UInt32 subValue);
 | 
				
			||||||
 | 
					-
 | 
				
			||||||
 | 
					-UInt32 * GetMatchesSpec1(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const Byte *buffer, CLzRef *son,
 | 
				
			||||||
 | 
					-    UInt32 _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 _cutValue,
 | 
				
			||||||
 | 
					-    UInt32 *distances, UInt32 maxLen);
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 /*
 | 
				
			||||||
 | 
					 Conditions:
 | 
				
			||||||
 | 
					@@ -102,12 +91,6 @@ typedef struct _IMatchFinder
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 void MatchFinder_CreateVTable(CMatchFinder *p, IMatchFinder *vTable);
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					-void MatchFinder_Init(CMatchFinder *p);
 | 
				
			||||||
 | 
					-UInt32 Bt3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances);
 | 
				
			||||||
 | 
					-UInt32 Hc3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances);
 | 
				
			||||||
 | 
					-void Bt3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num);
 | 
				
			||||||
 | 
					-void Hc3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num);
 | 
				
			||||||
 | 
					-
 | 
				
			||||||
 | 
					 #ifdef __cplusplus
 | 
				
			||||||
 | 
					 }
 | 
				
			||||||
 | 
					 #endif
 | 
				
			||||||
 | 
					--- a/lib/lzma/LzFind.c
 | 
				
			||||||
 | 
					+++ b/lib/lzma/LzFind.c
 | 
				
			||||||
 | 
					@@ -42,12 +42,12 @@ static int LzInWindow_Create(CMatchFinde
 | 
				
			||||||
 | 
					   return (p->bufferBase != 0);
 | 
				
			||||||
 | 
					 }
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					-Byte *MatchFinder_GetPointerToCurrentPos(CMatchFinder *p) { return p->buffer; }
 | 
				
			||||||
 | 
					-Byte MatchFinder_GetIndexByte(CMatchFinder *p, Int32 index) { return p->buffer[index]; }
 | 
				
			||||||
 | 
					+static Byte *MatchFinder_GetPointerToCurrentPos(CMatchFinder *p) { return p->buffer; }
 | 
				
			||||||
 | 
					+static Byte MatchFinder_GetIndexByte(CMatchFinder *p, Int32 index) { return p->buffer[index]; }
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					-UInt32 MatchFinder_GetNumAvailableBytes(CMatchFinder *p) { return p->streamPos - p->pos; }
 | 
				
			||||||
 | 
					+static UInt32 MatchFinder_GetNumAvailableBytes(CMatchFinder *p) { return p->streamPos - p->pos; }
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					-void MatchFinder_ReduceOffsets(CMatchFinder *p, UInt32 subValue)
 | 
				
			||||||
 | 
					+static void MatchFinder_ReduceOffsets(CMatchFinder *p, UInt32 subValue)
 | 
				
			||||||
 | 
					 {
 | 
				
			||||||
 | 
					   p->posLimit -= subValue;
 | 
				
			||||||
 | 
					   p->pos -= subValue;
 | 
				
			||||||
 | 
					@@ -268,7 +268,7 @@ static void MatchFinder_SetLimits(CMatch
 | 
				
			||||||
 | 
					   p->posLimit = p->pos + limit;
 | 
				
			||||||
 | 
					 }
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					-void MatchFinder_Init(CMatchFinder *p)
 | 
				
			||||||
 | 
					+static void MatchFinder_Init(CMatchFinder *p)
 | 
				
			||||||
 | 
					 {
 | 
				
			||||||
 | 
					   UInt32 i;
 | 
				
			||||||
 | 
					   for (i = 0; i < p->hashSizeSum; i++)
 | 
				
			||||||
 | 
					@@ -287,7 +287,7 @@ static UInt32 MatchFinder_GetSubValue(CM
 | 
				
			||||||
 | 
					   return (p->pos - p->historySize - 1) & kNormalizeMask;
 | 
				
			||||||
 | 
					 }
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					-void MatchFinder_Normalize3(UInt32 subValue, CLzRef *items, UInt32 numItems)
 | 
				
			||||||
 | 
					+static void MatchFinder_Normalize3(UInt32 subValue, CLzRef *items, UInt32 numItems)
 | 
				
			||||||
 | 
					 {
 | 
				
			||||||
 | 
					   UInt32 i;
 | 
				
			||||||
 | 
					   for (i = 0; i < numItems; i++)
 | 
				
			||||||
 | 
					@@ -350,7 +350,7 @@ static UInt32 * Hc_GetMatchesSpec(UInt32
 | 
				
			||||||
 | 
					   }
 | 
				
			||||||
 | 
					 }
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					-UInt32 * GetMatchesSpec1(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const Byte *cur, CLzRef *son,
 | 
				
			||||||
 | 
					+static UInt32 * GetMatchesSpec1(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const Byte *cur, CLzRef *son,
 | 
				
			||||||
 | 
					     UInt32 _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 cutValue,
 | 
				
			||||||
 | 
					     UInt32 *distances, UInt32 maxLen)
 | 
				
			||||||
 | 
					 {
 | 
				
			||||||
 | 
					@@ -492,7 +492,7 @@ static UInt32 Bt2_MatchFinder_GetMatches
 | 
				
			||||||
 | 
					   GET_MATCHES_FOOTER(offset, 1)
 | 
				
			||||||
 | 
					 }
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					-UInt32 Bt3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
 | 
				
			||||||
 | 
					+static __maybe_unused UInt32 Bt3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
 | 
				
			||||||
 | 
					 {
 | 
				
			||||||
 | 
					   UInt32 offset;
 | 
				
			||||||
 | 
					   GET_MATCHES_HEADER(3)
 | 
				
			||||||
 | 
					@@ -632,7 +632,7 @@ static UInt32 Hc4_MatchFinder_GetMatches
 | 
				
			||||||
 | 
					   MOVE_POS_RET
 | 
				
			||||||
 | 
					 }
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					-UInt32 Hc3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
 | 
				
			||||||
 | 
					+static __maybe_unused UInt32 Hc3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
 | 
				
			||||||
 | 
					 {
 | 
				
			||||||
 | 
					   UInt32 offset;
 | 
				
			||||||
 | 
					   GET_MATCHES_HEADER(3)
 | 
				
			||||||
 | 
					@@ -657,7 +657,7 @@ static void Bt2_MatchFinder_Skip(CMatchF
 | 
				
			||||||
 | 
					   while (--num != 0);
 | 
				
			||||||
 | 
					 }
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					-void Bt3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num)
 | 
				
			||||||
 | 
					+static __maybe_unused void Bt3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num)
 | 
				
			||||||
 | 
					 {
 | 
				
			||||||
 | 
					   do
 | 
				
			||||||
 | 
					   {
 | 
				
			||||||
 | 
					@@ -718,7 +718,7 @@ static void Hc4_MatchFinder_Skip(CMatchF
 | 
				
			||||||
 | 
					   while (--num != 0);
 | 
				
			||||||
 | 
					 }
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					-void Hc3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num)
 | 
				
			||||||
 | 
					+static __maybe_unused void Hc3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num)
 | 
				
			||||||
 | 
					 {
 | 
				
			||||||
 | 
					   do
 | 
				
			||||||
 | 
					   {
 | 
				
			||||||
							
								
								
									
										132
									
								
								target/linux/generic/patches-3.1/512-jffs2_eofdetect.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										132
									
								
								target/linux/generic/patches-3.1/512-jffs2_eofdetect.patch
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,132 @@
 | 
				
			|||||||
 | 
					--- a/fs/jffs2/build.c
 | 
				
			||||||
 | 
					+++ b/fs/jffs2/build.c
 | 
				
			||||||
 | 
					@@ -112,6 +112,17 @@ static int jffs2_build_filesystem(struct
 | 
				
			||||||
 | 
					 	dbg_fsbuild("scanned flash completely\n");
 | 
				
			||||||
 | 
					 	jffs2_dbg_dump_block_lists_nolock(c);
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					+	if (c->flags & (1 << 7)) {
 | 
				
			||||||
 | 
					+		printk("%s(): unlocking the mtd device... ", __func__);
 | 
				
			||||||
 | 
					+		if (c->mtd->unlock)
 | 
				
			||||||
 | 
					+			c->mtd->unlock(c->mtd, 0, c->mtd->size);
 | 
				
			||||||
 | 
					+		printk("done.\n");
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+		printk("%s(): erasing all blocks after the end marker... ", __func__);
 | 
				
			||||||
 | 
					+		jffs2_erase_pending_blocks(c, -1);
 | 
				
			||||||
 | 
					+		printk("done.\n");
 | 
				
			||||||
 | 
					+	}
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					 	dbg_fsbuild("pass 1 starting\n");
 | 
				
			||||||
 | 
					 	c->flags |= JFFS2_SB_FLAG_BUILDING;
 | 
				
			||||||
 | 
					 	/* Now scan the directory tree, increasing nlink according to every dirent found. */
 | 
				
			||||||
 | 
					--- a/fs/jffs2/scan.c
 | 
				
			||||||
 | 
					+++ b/fs/jffs2/scan.c
 | 
				
			||||||
 | 
					@@ -72,7 +72,7 @@ static int file_dirty(struct jffs2_sb_in
 | 
				
			||||||
 | 
					 		return ret;
 | 
				
			||||||
 | 
					 	if ((ret = jffs2_scan_dirty_space(c, jeb, jeb->free_size)))
 | 
				
			||||||
 | 
					 		return ret;
 | 
				
			||||||
 | 
					-	/* Turned wasted size into dirty, since we apparently 
 | 
				
			||||||
 | 
					+	/* Turned wasted size into dirty, since we apparently
 | 
				
			||||||
 | 
					 	   think it's recoverable now. */
 | 
				
			||||||
 | 
					 	jeb->dirty_size += jeb->wasted_size;
 | 
				
			||||||
 | 
					 	c->dirty_size += jeb->wasted_size;
 | 
				
			||||||
 | 
					@@ -147,8 +147,11 @@ int jffs2_scan_medium(struct jffs2_sb_in
 | 
				
			||||||
 | 
					 		/* reset summary info for next eraseblock scan */
 | 
				
			||||||
 | 
					 		jffs2_sum_reset_collected(s);
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					-		ret = jffs2_scan_eraseblock(c, jeb, buf_size?flashbuf:(flashbuf+jeb->offset),
 | 
				
			||||||
 | 
					-						buf_size, s);
 | 
				
			||||||
 | 
					+		if (c->flags & (1 << 7))
 | 
				
			||||||
 | 
					+			ret = BLK_STATE_ALLFF;
 | 
				
			||||||
 | 
					+		else
 | 
				
			||||||
 | 
					+			ret = jffs2_scan_eraseblock(c, jeb, buf_size?flashbuf:(flashbuf+jeb->offset),
 | 
				
			||||||
 | 
					+							buf_size, s);
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 		if (ret < 0)
 | 
				
			||||||
 | 
					 			goto out;
 | 
				
			||||||
 | 
					@@ -405,7 +408,7 @@ static int jffs2_scan_xref_node(struct j
 | 
				
			||||||
 | 
					 	if (!ref)
 | 
				
			||||||
 | 
					 		return -ENOMEM;
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					-	/* BEFORE jffs2_build_xattr_subsystem() called, 
 | 
				
			||||||
 | 
					+	/* BEFORE jffs2_build_xattr_subsystem() called,
 | 
				
			||||||
 | 
					 	 * and AFTER xattr_ref is marked as a dead xref,
 | 
				
			||||||
 | 
					 	 * ref->xid is used to store 32bit xid, xd is not used
 | 
				
			||||||
 | 
					 	 * ref->ino is used to store 32bit inode-number, ic is not used
 | 
				
			||||||
 | 
					@@ -478,7 +481,7 @@ static int jffs2_scan_eraseblock (struct
 | 
				
			||||||
 | 
					 		struct jffs2_sum_marker *sm;
 | 
				
			||||||
 | 
					 		void *sumptr = NULL;
 | 
				
			||||||
 | 
					 		uint32_t sumlen;
 | 
				
			||||||
 | 
					-	      
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					 		if (!buf_size) {
 | 
				
			||||||
 | 
					 			/* XIP case. Just look, point at the summary if it's there */
 | 
				
			||||||
 | 
					 			sm = (void *)buf + c->sector_size - sizeof(*sm);
 | 
				
			||||||
 | 
					@@ -494,9 +497,9 @@ static int jffs2_scan_eraseblock (struct
 | 
				
			||||||
 | 
					 				buf_len = sizeof(*sm);
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 			/* Read as much as we want into the _end_ of the preallocated buffer */
 | 
				
			||||||
 | 
					-			err = jffs2_fill_scan_buf(c, buf + buf_size - buf_len, 
 | 
				
			||||||
 | 
					+			err = jffs2_fill_scan_buf(c, buf + buf_size - buf_len,
 | 
				
			||||||
 | 
					 						  jeb->offset + c->sector_size - buf_len,
 | 
				
			||||||
 | 
					-						  buf_len);				
 | 
				
			||||||
 | 
					+						  buf_len);
 | 
				
			||||||
 | 
					 			if (err)
 | 
				
			||||||
 | 
					 				return err;
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					@@ -515,9 +518,9 @@ static int jffs2_scan_eraseblock (struct
 | 
				
			||||||
 | 
					 				}
 | 
				
			||||||
 | 
					 				if (buf_len < sumlen) {
 | 
				
			||||||
 | 
					 					/* Need to read more so that the entire summary node is present */
 | 
				
			||||||
 | 
					-					err = jffs2_fill_scan_buf(c, sumptr, 
 | 
				
			||||||
 | 
					+					err = jffs2_fill_scan_buf(c, sumptr,
 | 
				
			||||||
 | 
					 								  jeb->offset + c->sector_size - sumlen,
 | 
				
			||||||
 | 
					-								  sumlen - buf_len);				
 | 
				
			||||||
 | 
					+								  sumlen - buf_len);
 | 
				
			||||||
 | 
					 					if (err)
 | 
				
			||||||
 | 
					 						return err;
 | 
				
			||||||
 | 
					 				}
 | 
				
			||||||
 | 
					@@ -530,7 +533,7 @@ static int jffs2_scan_eraseblock (struct
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 			if (buf_size && sumlen > buf_size)
 | 
				
			||||||
 | 
					 				kfree(sumptr);
 | 
				
			||||||
 | 
					-			/* If it returns with a real error, bail. 
 | 
				
			||||||
 | 
					+			/* If it returns with a real error, bail.
 | 
				
			||||||
 | 
					 			   If it returns positive, that's a block classification
 | 
				
			||||||
 | 
					 			   (i.e. BLK_STATE_xxx) so return that too.
 | 
				
			||||||
 | 
					 			   If it returns zero, fall through to full scan. */
 | 
				
			||||||
 | 
					@@ -551,6 +554,17 @@ static int jffs2_scan_eraseblock (struct
 | 
				
			||||||
 | 
					 			return err;
 | 
				
			||||||
 | 
					 	}
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					+	if ((buf[0] == 0xde) &&
 | 
				
			||||||
 | 
					+		(buf[1] == 0xad) &&
 | 
				
			||||||
 | 
					+		(buf[2] == 0xc0) &&
 | 
				
			||||||
 | 
					+		(buf[3] == 0xde)) {
 | 
				
			||||||
 | 
					+		/* end of filesystem. erase everything after this point */
 | 
				
			||||||
 | 
					+		printk("%s(): End of filesystem marker found at 0x%x\n", __func__, jeb->offset);
 | 
				
			||||||
 | 
					+		c->flags |= (1 << 7);
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+		return BLK_STATE_ALLFF;
 | 
				
			||||||
 | 
					+	}
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					 	/* We temporarily use 'ofs' as a pointer into the buffer/jeb */
 | 
				
			||||||
 | 
					 	ofs = 0;
 | 
				
			||||||
 | 
					 	max_ofs = EMPTY_SCAN_SIZE(c->sector_size);
 | 
				
			||||||
 | 
					@@ -676,7 +690,7 @@ scan_more:
 | 
				
			||||||
 | 
					 				scan_end = buf_len;
 | 
				
			||||||
 | 
					 				goto more_empty;
 | 
				
			||||||
 | 
					 			}
 | 
				
			||||||
 | 
					-			
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					 			/* See how much more there is to read in this eraseblock... */
 | 
				
			||||||
 | 
					 			buf_len = min_t(uint32_t, buf_size, jeb->offset + c->sector_size - ofs);
 | 
				
			||||||
 | 
					 			if (!buf_len) {
 | 
				
			||||||
 | 
					@@ -912,7 +926,7 @@ scan_more:
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 	D1(printk(KERN_DEBUG "Block at 0x%08x: free 0x%08x, dirty 0x%08x, unchecked 0x%08x, used 0x%08x, wasted 0x%08x\n",
 | 
				
			||||||
 | 
					 		  jeb->offset,jeb->free_size, jeb->dirty_size, jeb->unchecked_size, jeb->used_size, jeb->wasted_size));
 | 
				
			||||||
 | 
					-	
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					 	/* mark_node_obsolete can add to wasted !! */
 | 
				
			||||||
 | 
					 	if (jeb->wasted_size) {
 | 
				
			||||||
 | 
					 		jeb->dirty_size += jeb->wasted_size;
 | 
				
			||||||
@@ -0,0 +1,25 @@
 | 
				
			|||||||
 | 
					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,
 | 
				
			||||||
							
								
								
									
										2132
									
								
								target/linux/generic/patches-3.1/600-netfilter_layer7_2.22.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										2132
									
								
								target/linux/generic/patches-3.1/600-netfilter_layer7_2.22.patch
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							@@ -0,0 +1,108 @@
 | 
				
			|||||||
 | 
					--- 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){
 | 
				
			||||||
@@ -0,0 +1,51 @@
 | 
				
			|||||||
 | 
					--- 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
 | 
				
			||||||
 | 
					 }
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
@@ -0,0 +1,61 @@
 | 
				
			|||||||
 | 
					--- a/net/netfilter/Kconfig
 | 
				
			||||||
 | 
					+++ b/net/netfilter/Kconfig
 | 
				
			||||||
 | 
					@@ -832,6 +832,27 @@ config NETFILTER_XT_MATCH_IPVS
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 	  If unsure, say N.
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					+config NETFILTER_XT_MATCH_LAYER7
 | 
				
			||||||
 | 
					+	tristate '"layer7" match support'
 | 
				
			||||||
 | 
					+	depends on EXPERIMENTAL
 | 
				
			||||||
 | 
					+	depends on NETFILTER_XTABLES
 | 
				
			||||||
 | 
					+	depends on NETFILTER_ADVANCED
 | 
				
			||||||
 | 
					+	depends on NF_CONNTRACK
 | 
				
			||||||
 | 
					+	help
 | 
				
			||||||
 | 
					+	  Say Y if you want to be able to classify connections (and their
 | 
				
			||||||
 | 
					+	  packets) based on regular expression matching of their application
 | 
				
			||||||
 | 
					+	  layer data.   This is one way to classify applications such as
 | 
				
			||||||
 | 
					+	  peer-to-peer filesharing systems that do not always use the same
 | 
				
			||||||
 | 
					+	  port.
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	  To compile it as a module, choose M here.  If unsure, say N.
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+config NETFILTER_XT_MATCH_LAYER7_DEBUG
 | 
				
			||||||
 | 
					+	bool 'Layer 7 debugging output'
 | 
				
			||||||
 | 
					+	depends on NETFILTER_XT_MATCH_LAYER7
 | 
				
			||||||
 | 
					+	help
 | 
				
			||||||
 | 
					+	  Say Y to get lots of debugging output.
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					 config NETFILTER_XT_MATCH_LENGTH
 | 
				
			||||||
 | 
					 	tristate '"length" match support'
 | 
				
			||||||
 | 
					 	depends on NETFILTER_ADVANCED
 | 
				
			||||||
 | 
					@@ -1018,26 +1039,11 @@ config NETFILTER_XT_MATCH_STATE
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 	  To compile it as a module, choose M here.  If unsure, say N.
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					-config NETFILTER_XT_MATCH_LAYER7
 | 
				
			||||||
 | 
					-	tristate '"layer7" match support'
 | 
				
			||||||
 | 
					-	depends on NETFILTER_XTABLES
 | 
				
			||||||
 | 
					-	depends on EXPERIMENTAL && (IP_NF_CONNTRACK || NF_CONNTRACK)
 | 
				
			||||||
 | 
					-       depends on NETFILTER_ADVANCED
 | 
				
			||||||
 | 
					-	help
 | 
				
			||||||
 | 
					-	  Say Y if you want to be able to classify connections (and their
 | 
				
			||||||
 | 
					-	  packets) based on regular expression matching of their application
 | 
				
			||||||
 | 
					-	  layer data.   This is one way to classify applications such as
 | 
				
			||||||
 | 
					-	  peer-to-peer filesharing systems that do not always use the same
 | 
				
			||||||
 | 
					-	  port.
 | 
				
			||||||
 | 
					-
 | 
				
			||||||
 | 
					-	  To compile it as a module, choose M here.  If unsure, say N.
 | 
				
			||||||
 | 
					-
 | 
				
			||||||
 | 
					 config NETFILTER_XT_MATCH_LAYER7_DEBUG
 | 
				
			||||||
 | 
					-        bool 'Layer 7 debugging output'
 | 
				
			||||||
 | 
					-        depends on NETFILTER_XT_MATCH_LAYER7
 | 
				
			||||||
 | 
					-        help
 | 
				
			||||||
 | 
					-          Say Y to get lots of debugging output.
 | 
				
			||||||
 | 
					-
 | 
				
			||||||
 | 
					+	bool 'Layer 7 debugging output'
 | 
				
			||||||
 | 
					+	depends on NETFILTER_XT_MATCH_LAYER7
 | 
				
			||||||
 | 
					+	help
 | 
				
			||||||
 | 
					+	  Say Y to get lots of debugging output.
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 config NETFILTER_XT_MATCH_STATISTIC
 | 
				
			||||||
 | 
					 	tristate '"statistic" match support'
 | 
				
			||||||
@@ -0,0 +1,118 @@
 | 
				
			|||||||
 | 
					--- a/include/linux/netfilter/nf_conntrack_sip.h
 | 
				
			||||||
 | 
					+++ b/include/linux/netfilter/nf_conntrack_sip.h
 | 
				
			||||||
 | 
					@@ -2,12 +2,15 @@
 | 
				
			||||||
 | 
					 #define __NF_CONNTRACK_SIP_H__
 | 
				
			||||||
 | 
					 #ifdef __KERNEL__
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					+#include <linux/types.h>
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					 #define SIP_PORT	5060
 | 
				
			||||||
 | 
					 #define SIP_TIMEOUT	3600
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 struct nf_ct_sip_master {
 | 
				
			||||||
 | 
					 	unsigned int	register_cseq;
 | 
				
			||||||
 | 
					 	unsigned int	invite_cseq;
 | 
				
			||||||
 | 
					+	__be16		forced_dport;
 | 
				
			||||||
 | 
					 };
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 enum sip_expectation_classes {
 | 
				
			||||||
 | 
					--- a/net/ipv4/netfilter/nf_nat_sip.c
 | 
				
			||||||
 | 
					+++ b/net/ipv4/netfilter/nf_nat_sip.c
 | 
				
			||||||
 | 
					@@ -73,6 +73,7 @@ static int map_addr(struct sk_buff *skb,
 | 
				
			||||||
 | 
					 	enum ip_conntrack_info ctinfo;
 | 
				
			||||||
 | 
					 	struct nf_conn *ct = nf_ct_get(skb, &ctinfo);
 | 
				
			||||||
 | 
					 	enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo);
 | 
				
			||||||
 | 
					+	struct nf_conn_help *help = nfct_help(ct);
 | 
				
			||||||
 | 
					 	char buffer[sizeof("nnn.nnn.nnn.nnn:nnnnn")];
 | 
				
			||||||
 | 
					 	unsigned int buflen;
 | 
				
			||||||
 | 
					 	__be32 newaddr;
 | 
				
			||||||
 | 
					@@ -85,7 +86,8 @@ static int map_addr(struct sk_buff *skb,
 | 
				
			||||||
 | 
					 	} else if (ct->tuplehash[dir].tuple.dst.u3.ip == addr->ip &&
 | 
				
			||||||
 | 
					 		   ct->tuplehash[dir].tuple.dst.u.udp.port == port) {
 | 
				
			||||||
 | 
					 		newaddr = ct->tuplehash[!dir].tuple.src.u3.ip;
 | 
				
			||||||
 | 
					-		newport = ct->tuplehash[!dir].tuple.src.u.udp.port;
 | 
				
			||||||
 | 
					+		newport = help->help.ct_sip_info.forced_dport ? :
 | 
				
			||||||
 | 
					+			  ct->tuplehash[!dir].tuple.src.u.udp.port;
 | 
				
			||||||
 | 
					 	} else
 | 
				
			||||||
 | 
					 		return 1;
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					@@ -121,6 +123,7 @@ static unsigned int ip_nat_sip(struct sk
 | 
				
			||||||
 | 
					 	enum ip_conntrack_info ctinfo;
 | 
				
			||||||
 | 
					 	struct nf_conn *ct = nf_ct_get(skb, &ctinfo);
 | 
				
			||||||
 | 
					 	enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo);
 | 
				
			||||||
 | 
					+	struct nf_conn_help *help = nfct_help(ct);
 | 
				
			||||||
 | 
					 	unsigned int coff, matchoff, matchlen;
 | 
				
			||||||
 | 
					 	enum sip_header_types hdr;
 | 
				
			||||||
 | 
					 	union nf_inet_addr addr;
 | 
				
			||||||
 | 
					@@ -229,6 +232,20 @@ next:
 | 
				
			||||||
 | 
					 	    !map_sip_addr(skb, dataoff, dptr, datalen, SIP_HDR_TO))
 | 
				
			||||||
 | 
					 		return NF_DROP;
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					+	/* Mangle destination port for Cisco phones, then fix up checksums */
 | 
				
			||||||
 | 
					+	if (dir == IP_CT_DIR_REPLY && help->help.ct_sip_info.forced_dport) {
 | 
				
			||||||
 | 
					+		struct udphdr *uh;
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+		if (!skb_make_writable(skb, skb->len))
 | 
				
			||||||
 | 
					+			return NF_DROP;
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+		uh = (struct udphdr *)(skb->data + ip_hdrlen(skb));
 | 
				
			||||||
 | 
					+		uh->dest = help->help.ct_sip_info.forced_dport;
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+		if (!nf_nat_mangle_udp_packet(skb, ct, ctinfo, 0, 0, NULL, 0))
 | 
				
			||||||
 | 
					+			return NF_DROP;
 | 
				
			||||||
 | 
					+	}
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					 	return NF_ACCEPT;
 | 
				
			||||||
 | 
					 }
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					@@ -280,8 +297,10 @@ static unsigned int ip_nat_sip_expect(st
 | 
				
			||||||
 | 
					 	enum ip_conntrack_info ctinfo;
 | 
				
			||||||
 | 
					 	struct nf_conn *ct = nf_ct_get(skb, &ctinfo);
 | 
				
			||||||
 | 
					 	enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo);
 | 
				
			||||||
 | 
					+	struct nf_conn_help *help = nfct_help(ct);
 | 
				
			||||||
 | 
					 	__be32 newip;
 | 
				
			||||||
 | 
					 	u_int16_t port;
 | 
				
			||||||
 | 
					+	__be16 srcport;
 | 
				
			||||||
 | 
					 	char buffer[sizeof("nnn.nnn.nnn.nnn:nnnnn")];
 | 
				
			||||||
 | 
					 	unsigned buflen;
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					@@ -294,8 +313,9 @@ static unsigned int ip_nat_sip_expect(st
 | 
				
			||||||
 | 
					 	/* If the signalling port matches the connection's source port in the
 | 
				
			||||||
 | 
					 	 * original direction, try to use the destination port in the opposite
 | 
				
			||||||
 | 
					 	 * direction. */
 | 
				
			||||||
 | 
					-	if (exp->tuple.dst.u.udp.port ==
 | 
				
			||||||
 | 
					-	    ct->tuplehash[dir].tuple.src.u.udp.port)
 | 
				
			||||||
 | 
					+	srcport = help->help.ct_sip_info.forced_dport ? :
 | 
				
			||||||
 | 
					+		  ct->tuplehash[dir].tuple.src.u.udp.port;
 | 
				
			||||||
 | 
					+	if (exp->tuple.dst.u.udp.port == srcport)
 | 
				
			||||||
 | 
					 		port = ntohs(ct->tuplehash[!dir].tuple.dst.u.udp.port);
 | 
				
			||||||
 | 
					 	else
 | 
				
			||||||
 | 
					 		port = ntohs(exp->tuple.dst.u.udp.port);
 | 
				
			||||||
 | 
					--- a/net/netfilter/nf_conntrack_sip.c
 | 
				
			||||||
 | 
					+++ b/net/netfilter/nf_conntrack_sip.c
 | 
				
			||||||
 | 
					@@ -1363,8 +1363,25 @@ static int process_sip_request(struct sk
 | 
				
			||||||
 | 
					 {
 | 
				
			||||||
 | 
					 	enum ip_conntrack_info ctinfo;
 | 
				
			||||||
 | 
					 	struct nf_conn *ct = nf_ct_get(skb, &ctinfo);
 | 
				
			||||||
 | 
					+	struct nf_conn_help *help = nfct_help(ct);
 | 
				
			||||||
 | 
					+	enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo);
 | 
				
			||||||
 | 
					 	unsigned int matchoff, matchlen;
 | 
				
			||||||
 | 
					 	unsigned int cseq, i;
 | 
				
			||||||
 | 
					+	union nf_inet_addr addr;
 | 
				
			||||||
 | 
					+	__be16 port;
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	/* Many Cisco IP phones use a high source port for SIP requests, but
 | 
				
			||||||
 | 
					+	 * listen for the response on port 5060.  If we are the local
 | 
				
			||||||
 | 
					+	 * router for one of these phones, save the port number from the
 | 
				
			||||||
 | 
					+	 * Via: header so that nf_nat_sip can redirect the responses to
 | 
				
			||||||
 | 
					+	 * the correct port.
 | 
				
			||||||
 | 
					+	 */
 | 
				
			||||||
 | 
					+	if (ct_sip_parse_header_uri(ct, *dptr, NULL, *datalen,
 | 
				
			||||||
 | 
					+				    SIP_HDR_VIA_UDP, NULL, &matchoff,
 | 
				
			||||||
 | 
					+				    &matchlen, &addr, &port) > 0 &&
 | 
				
			||||||
 | 
					+	    port != ct->tuplehash[dir].tuple.src.u.udp.port &&
 | 
				
			||||||
 | 
					+	    nf_inet_addr_cmp(&addr, &ct->tuplehash[dir].tuple.src.u3))
 | 
				
			||||||
 | 
					+		help->help.ct_sip_info.forced_dport = port;
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 	for (i = 0; i < ARRAY_SIZE(sip_handlers); i++) {
 | 
				
			||||||
 | 
					 		const struct sip_handler *handler;
 | 
				
			||||||
							
								
								
									
										1366
									
								
								target/linux/generic/patches-3.1/605-netfilter_rtsp.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1366
									
								
								target/linux/generic/patches-3.1/605-netfilter_rtsp.patch
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							@@ -0,0 +1,90 @@
 | 
				
			|||||||
 | 
					--- a/include/linux/netfilter_ipv4/ip_tables.h
 | 
				
			||||||
 | 
					+++ b/include/linux/netfilter_ipv4/ip_tables.h
 | 
				
			||||||
 | 
					@@ -93,6 +93,7 @@ struct ipt_ip {
 | 
				
			||||||
 | 
					 #define IPT_F_FRAG		0x01	/* Set if rule is a fragment rule */
 | 
				
			||||||
 | 
					 #define IPT_F_GOTO		0x02	/* Set if jump is a goto */
 | 
				
			||||||
 | 
					 #define IPT_F_MASK		0x03	/* All possible flag bits mask. */
 | 
				
			||||||
 | 
					+#define IPT_F_NO_DEF_MATCH	0x80	/* Internal: no default match rules present */
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 /* Values for "inv" field in struct ipt_ip. */
 | 
				
			||||||
 | 
					 #define IPT_INV_VIA_IN		0x01	/* Invert the sense of IN IFACE. */
 | 
				
			||||||
 | 
					--- a/net/ipv4/netfilter/ip_tables.c
 | 
				
			||||||
 | 
					+++ b/net/ipv4/netfilter/ip_tables.c
 | 
				
			||||||
 | 
					@@ -81,6 +81,9 @@ ip_packet_match(const struct iphdr *ip,
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 #define FWINV(bool, invflg) ((bool) ^ !!(ipinfo->invflags & (invflg)))
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					+	if (ipinfo->flags & IPT_F_NO_DEF_MATCH)
 | 
				
			||||||
 | 
					+		return true;
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					 	if (FWINV((ip->saddr&ipinfo->smsk.s_addr) != ipinfo->src.s_addr,
 | 
				
			||||||
 | 
					 		  IPT_INV_SRCIP) ||
 | 
				
			||||||
 | 
					 	    FWINV((ip->daddr&ipinfo->dmsk.s_addr) != ipinfo->dst.s_addr,
 | 
				
			||||||
 | 
					@@ -134,6 +137,26 @@ 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->proto)
 | 
				
			||||||
 | 
					+		return;
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	ip->flags |= IPT_F_NO_DEF_MATCH;
 | 
				
			||||||
 | 
					+}
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					 static bool
 | 
				
			||||||
 | 
					 ip_checkentry(const struct ipt_ip *ip)
 | 
				
			||||||
 | 
					 {
 | 
				
			||||||
 | 
					@@ -561,7 +584,7 @@ static void cleanup_match(struct xt_entr
 | 
				
			||||||
 | 
					 }
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 static int
 | 
				
			||||||
 | 
					-check_entry(const struct ipt_entry *e, const char *name)
 | 
				
			||||||
 | 
					+check_entry(struct ipt_entry *e, const char *name)
 | 
				
			||||||
 | 
					 {
 | 
				
			||||||
 | 
					 	const struct xt_entry_target *t;
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					@@ -570,6 +593,8 @@ check_entry(const struct ipt_entry *e, c
 | 
				
			||||||
 | 
					 		return -EINVAL;
 | 
				
			||||||
 | 
					 	}
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					+	ip_checkdefault(&e->ip);
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					 	if (e->target_offset + sizeof(struct xt_entry_target) >
 | 
				
			||||||
 | 
					 	    e->next_offset)
 | 
				
			||||||
 | 
					 		return -EINVAL;
 | 
				
			||||||
 | 
					@@ -931,6 +956,7 @@ copy_entries_to_user(unsigned int total_
 | 
				
			||||||
 | 
					 	const struct xt_table_info *private = table->private;
 | 
				
			||||||
 | 
					 	int ret = 0;
 | 
				
			||||||
 | 
					 	const void *loc_cpu_entry;
 | 
				
			||||||
 | 
					+	u8 flags;
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 	counters = alloc_counters(table);
 | 
				
			||||||
 | 
					 	if (IS_ERR(counters))
 | 
				
			||||||
 | 
					@@ -961,6 +987,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;
 | 
				
			||||||
@@ -0,0 +1,81 @@
 | 
				
			|||||||
 | 
					--- a/net/ipv4/netfilter/ip_tables.c
 | 
				
			||||||
 | 
					+++ b/net/ipv4/netfilter/ip_tables.c
 | 
				
			||||||
 | 
					@@ -307,6 +307,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,
 | 
				
			||||||
 | 
					@@ -331,6 +358,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
 | 
				
			||||||
 | 
					@@ -345,18 +391,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]));
 | 
				
			||||||
@@ -0,0 +1,16 @@
 | 
				
			|||||||
 | 
					--- 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->smsk.s_addr &&
 | 
				
			||||||
 | 
					+		  (ip->daddr&ipinfo->dmsk.s_addr) != ipinfo->dst.s_addr,
 | 
				
			||||||
 | 
					 		  IPT_INV_DSTIP)) {
 | 
				
			||||||
 | 
					 		dprintf("Source or dest mismatch.\n");
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
@@ -0,0 +1,36 @@
 | 
				
			|||||||
 | 
					--- a/net/netfilter/nf_conntrack_proto_tcp.c
 | 
				
			||||||
 | 
					+++ b/net/netfilter/nf_conntrack_proto_tcp.c
 | 
				
			||||||
 | 
					@@ -29,6 +29,9 @@
 | 
				
			||||||
 | 
					 #include <net/netfilter/ipv4/nf_conntrack_ipv4.h>
 | 
				
			||||||
 | 
					 #include <net/netfilter/ipv6/nf_conntrack_ipv6.h>
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					+/* Do not check the TCP window for incoming packets  */
 | 
				
			||||||
 | 
					+static int nf_ct_tcp_no_window_check __read_mostly = 1;
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					 /* "Be conservative in what you do,
 | 
				
			||||||
 | 
					     be liberal in what you accept from others."
 | 
				
			||||||
 | 
					     If it's non-zero, we mark only out of window RST segments as INVALID. */
 | 
				
			||||||
 | 
					@@ -524,6 +527,9 @@ static bool tcp_in_window(const struct n
 | 
				
			||||||
 | 
					 	s16 receiver_offset;
 | 
				
			||||||
 | 
					 	bool res;
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					+	if (nf_ct_tcp_no_window_check)
 | 
				
			||||||
 | 
					+		return true;
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					 	/*
 | 
				
			||||||
 | 
					 	 * Get the required data from the packet.
 | 
				
			||||||
 | 
					 	 */
 | 
				
			||||||
 | 
					@@ -1321,6 +1327,13 @@ static struct ctl_table tcp_sysctl_table
 | 
				
			||||||
 | 
					 		.proc_handler	= proc_dointvec,
 | 
				
			||||||
 | 
					 	},
 | 
				
			||||||
 | 
					 	{
 | 
				
			||||||
 | 
					+		.procname       = "nf_conntrack_tcp_no_window_check",
 | 
				
			||||||
 | 
					+		.data           = &nf_ct_tcp_no_window_check,
 | 
				
			||||||
 | 
					+		.maxlen         = sizeof(unsigned int),
 | 
				
			||||||
 | 
					+		.mode           = 0644,
 | 
				
			||||||
 | 
					+		.proc_handler   = proc_dointvec,
 | 
				
			||||||
 | 
					+	},
 | 
				
			||||||
 | 
					+	{
 | 
				
			||||||
 | 
					 		.procname       = "nf_conntrack_tcp_be_liberal",
 | 
				
			||||||
 | 
					 		.data           = &nf_ct_tcp_be_liberal,
 | 
				
			||||||
 | 
					 		.maxlen         = sizeof(unsigned int),
 | 
				
			||||||
							
								
								
									
										795
									
								
								target/linux/generic/patches-3.1/620-sched_esfq.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										795
									
								
								target/linux/generic/patches-3.1/620-sched_esfq.patch
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,795 @@
 | 
				
			|||||||
 | 
					--- a/include/linux/pkt_sched.h
 | 
				
			||||||
 | 
					+++ b/include/linux/pkt_sched.h
 | 
				
			||||||
 | 
					@@ -173,8 +173,37 @@ struct tc_sfq_xstats {
 | 
				
			||||||
 | 
					  *
 | 
				
			||||||
 | 
					  *	The only reason for this is efficiency, it is possible
 | 
				
			||||||
 | 
					  *	to change these parameters in compile time.
 | 
				
			||||||
 | 
					+ *
 | 
				
			||||||
 | 
					+ *	If you need to play with these values, use esfq instead.
 | 
				
			||||||
 | 
					  */
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					+/* ESFQ section */
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+enum
 | 
				
			||||||
 | 
					+{
 | 
				
			||||||
 | 
					+        /* traditional */
 | 
				
			||||||
 | 
					+	TCA_SFQ_HASH_CLASSIC,
 | 
				
			||||||
 | 
					+	TCA_SFQ_HASH_DST,
 | 
				
			||||||
 | 
					+	TCA_SFQ_HASH_SRC,
 | 
				
			||||||
 | 
					+	TCA_SFQ_HASH_FWMARK,
 | 
				
			||||||
 | 
					+	/* conntrack */
 | 
				
			||||||
 | 
					+	TCA_SFQ_HASH_CTORIGDST,
 | 
				
			||||||
 | 
					+	TCA_SFQ_HASH_CTORIGSRC,
 | 
				
			||||||
 | 
					+	TCA_SFQ_HASH_CTREPLDST,
 | 
				
			||||||
 | 
					+	TCA_SFQ_HASH_CTREPLSRC,
 | 
				
			||||||
 | 
					+	TCA_SFQ_HASH_CTNATCHG,
 | 
				
			||||||
 | 
					+};
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+struct tc_esfq_qopt
 | 
				
			||||||
 | 
					+{
 | 
				
			||||||
 | 
					+	unsigned	quantum;	/* Bytes per round allocated to flow */
 | 
				
			||||||
 | 
					+	int		perturb_period;	/* Period of hash perturbation */
 | 
				
			||||||
 | 
					+	__u32		limit;		/* Maximal packets in queue */
 | 
				
			||||||
 | 
					+	unsigned	divisor;	/* Hash divisor  */
 | 
				
			||||||
 | 
					+	unsigned	flows;		/* Maximal number of flows  */
 | 
				
			||||||
 | 
					+	unsigned	hash_kind;	/* Hash function to use for flow identification */
 | 
				
			||||||
 | 
					+};
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					 /* RED section */
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 enum {
 | 
				
			||||||
 | 
					--- a/net/sched/Kconfig
 | 
				
			||||||
 | 
					+++ b/net/sched/Kconfig
 | 
				
			||||||
 | 
					@@ -148,6 +148,37 @@ config NET_SCH_SFQ
 | 
				
			||||||
 | 
					 	  To compile this code as a module, choose M here: the
 | 
				
			||||||
 | 
					 	  module will be called sch_sfq.
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					+config NET_SCH_ESFQ
 | 
				
			||||||
 | 
					+	tristate "Enhanced Stochastic Fairness Queueing (ESFQ)"
 | 
				
			||||||
 | 
					+	---help---
 | 
				
			||||||
 | 
					+	  Say Y here if you want to use the Enhanced Stochastic Fairness
 | 
				
			||||||
 | 
					+	  Queueing (ESFQ) packet scheduling algorithm for some of your network
 | 
				
			||||||
 | 
					+	  devices or as a leaf discipline for a classful qdisc such as HTB or
 | 
				
			||||||
 | 
					+	  CBQ (see the top of <file:net/sched/sch_esfq.c> for details and
 | 
				
			||||||
 | 
					+	  references to the SFQ algorithm).
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	  This is an enchanced SFQ version which allows you to control some
 | 
				
			||||||
 | 
					+	  hardcoded values in the SFQ scheduler.
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	  ESFQ also adds control of the hash function used to identify packet
 | 
				
			||||||
 | 
					+	  flows. The original SFQ discipline hashes by connection; ESFQ add
 | 
				
			||||||
 | 
					+	  several other hashing methods, such as by src IP or by dst IP, which
 | 
				
			||||||
 | 
					+	  can be more fair to users in some networking situations.
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	  To compile this code as a module, choose M here: the
 | 
				
			||||||
 | 
					+	  module will be called sch_esfq.
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+config NET_SCH_ESFQ_NFCT
 | 
				
			||||||
 | 
					+	bool "Connection Tracking Hash Types"
 | 
				
			||||||
 | 
					+	depends on NET_SCH_ESFQ && NF_CONNTRACK
 | 
				
			||||||
 | 
					+	---help---
 | 
				
			||||||
 | 
					+	  Say Y here to enable support for hashing based on netfilter connection
 | 
				
			||||||
 | 
					+	  tracking information. This is useful for a router that is also using
 | 
				
			||||||
 | 
					+	  NAT to connect privately-addressed hosts to the Internet. If you want
 | 
				
			||||||
 | 
					+	  to provide fair distribution of upstream bandwidth, ESFQ must use
 | 
				
			||||||
 | 
					+	  connection tracking information, since all outgoing packets will share
 | 
				
			||||||
 | 
					+	  the same source address.
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					 config NET_SCH_TEQL
 | 
				
			||||||
 | 
					 	tristate "True Link Equalizer (TEQL)"
 | 
				
			||||||
 | 
					 	---help---
 | 
				
			||||||
 | 
					--- a/net/sched/Makefile
 | 
				
			||||||
 | 
					+++ b/net/sched/Makefile
 | 
				
			||||||
 | 
					@@ -26,6 +26,7 @@ obj-$(CONFIG_NET_SCH_INGRESS)	+= sch_ing
 | 
				
			||||||
 | 
					 obj-$(CONFIG_NET_SCH_DSMARK)	+= sch_dsmark.o
 | 
				
			||||||
 | 
					 obj-$(CONFIG_NET_SCH_SFB)	+= sch_sfb.o
 | 
				
			||||||
 | 
					 obj-$(CONFIG_NET_SCH_SFQ)	+= sch_sfq.o
 | 
				
			||||||
 | 
					+obj-$(CONFIG_NET_SCH_ESFQ)	+= sch_esfq.o
 | 
				
			||||||
 | 
					 obj-$(CONFIG_NET_SCH_TBF)	+= sch_tbf.o
 | 
				
			||||||
 | 
					 obj-$(CONFIG_NET_SCH_TEQL)	+= sch_teql.o
 | 
				
			||||||
 | 
					 obj-$(CONFIG_NET_SCH_PRIO)	+= sch_prio.o
 | 
				
			||||||
 | 
					--- /dev/null
 | 
				
			||||||
 | 
					+++ b/net/sched/sch_esfq.c
 | 
				
			||||||
 | 
					@@ -0,0 +1,702 @@
 | 
				
			||||||
 | 
					+/*
 | 
				
			||||||
 | 
					+ * net/sched/sch_esfq.c	Extended Stochastic Fairness Queueing discipline.
 | 
				
			||||||
 | 
					+ *
 | 
				
			||||||
 | 
					+ *		This program is free software; you can redistribute it and/or
 | 
				
			||||||
 | 
					+ *		modify it under the terms of the GNU General Public License
 | 
				
			||||||
 | 
					+ *		as published by the Free Software Foundation; either version
 | 
				
			||||||
 | 
					+ *		2 of the License, or (at your option) any later version.
 | 
				
			||||||
 | 
					+ *
 | 
				
			||||||
 | 
					+ * Authors:	Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru>
 | 
				
			||||||
 | 
					+ *
 | 
				
			||||||
 | 
					+ * Changes:	Alexander Atanasov, <alex@ssi.bg>
 | 
				
			||||||
 | 
					+ *		Added dynamic depth,limit,divisor,hash_kind options.
 | 
				
			||||||
 | 
					+ *		Added dst and src hashes.
 | 
				
			||||||
 | 
					+ *
 | 
				
			||||||
 | 
					+ * 		Alexander Clouter, <alex@digriz.org.uk>
 | 
				
			||||||
 | 
					+ *		Ported ESFQ to Linux 2.6.
 | 
				
			||||||
 | 
					+ *
 | 
				
			||||||
 | 
					+ * 		Corey Hickey, <bugfood-c@fatooh.org>
 | 
				
			||||||
 | 
					+ *		Maintenance of the Linux 2.6 port.
 | 
				
			||||||
 | 
					+ *		Added fwmark hash (thanks to Robert Kurjata).
 | 
				
			||||||
 | 
					+ *		Added usage of jhash.
 | 
				
			||||||
 | 
					+ *		Added conntrack support.
 | 
				
			||||||
 | 
					+ *		Added ctnatchg hash (thanks to Ben Pfountz).
 | 
				
			||||||
 | 
					+ */
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+#include <linux/module.h>
 | 
				
			||||||
 | 
					+#include <asm/uaccess.h>
 | 
				
			||||||
 | 
					+#include <asm/system.h>
 | 
				
			||||||
 | 
					+#include <linux/bitops.h>
 | 
				
			||||||
 | 
					+#include <linux/types.h>
 | 
				
			||||||
 | 
					+#include <linux/kernel.h>
 | 
				
			||||||
 | 
					+#include <linux/jiffies.h>
 | 
				
			||||||
 | 
					+#include <linux/string.h>
 | 
				
			||||||
 | 
					+#include <linux/mm.h>
 | 
				
			||||||
 | 
					+#include <linux/socket.h>
 | 
				
			||||||
 | 
					+#include <linux/sockios.h>
 | 
				
			||||||
 | 
					+#include <linux/in.h>
 | 
				
			||||||
 | 
					+#include <linux/errno.h>
 | 
				
			||||||
 | 
					+#include <linux/interrupt.h>
 | 
				
			||||||
 | 
					+#include <linux/if_ether.h>
 | 
				
			||||||
 | 
					+#include <linux/inet.h>
 | 
				
			||||||
 | 
					+#include <linux/netdevice.h>
 | 
				
			||||||
 | 
					+#include <linux/etherdevice.h>
 | 
				
			||||||
 | 
					+#include <linux/notifier.h>
 | 
				
			||||||
 | 
					+#include <linux/init.h>
 | 
				
			||||||
 | 
					+#include <net/ip.h>
 | 
				
			||||||
 | 
					+#include <net/netlink.h>
 | 
				
			||||||
 | 
					+#include <linux/ipv6.h>
 | 
				
			||||||
 | 
					+#include <net/route.h>
 | 
				
			||||||
 | 
					+#include <linux/skbuff.h>
 | 
				
			||||||
 | 
					+#include <net/sock.h>
 | 
				
			||||||
 | 
					+#include <net/pkt_sched.h>
 | 
				
			||||||
 | 
					+#include <linux/jhash.h>
 | 
				
			||||||
 | 
					+#ifdef CONFIG_NET_SCH_ESFQ_NFCT
 | 
				
			||||||
 | 
					+#include <net/netfilter/nf_conntrack.h>
 | 
				
			||||||
 | 
					+#endif
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+/*	Stochastic Fairness Queuing algorithm.
 | 
				
			||||||
 | 
					+	For more comments look at sch_sfq.c.
 | 
				
			||||||
 | 
					+	The difference is that you can change limit, depth,
 | 
				
			||||||
 | 
					+	hash table size and choose alternate hash types.
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	classic:	same as in sch_sfq.c
 | 
				
			||||||
 | 
					+	dst:		destination IP address
 | 
				
			||||||
 | 
					+	src:		source IP address
 | 
				
			||||||
 | 
					+	fwmark:		netfilter mark value
 | 
				
			||||||
 | 
					+	ctorigdst:	original destination IP address
 | 
				
			||||||
 | 
					+	ctorigsrc:	original source IP address
 | 
				
			||||||
 | 
					+	ctrepldst:	reply destination IP address
 | 
				
			||||||
 | 
					+	ctreplsrc:	reply source IP
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+*/
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+#define ESFQ_HEAD 0
 | 
				
			||||||
 | 
					+#define ESFQ_TAIL 1
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+/* This type should contain at least SFQ_DEPTH*2 values */
 | 
				
			||||||
 | 
					+typedef unsigned int esfq_index;
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+struct esfq_head
 | 
				
			||||||
 | 
					+{
 | 
				
			||||||
 | 
					+	esfq_index	next;
 | 
				
			||||||
 | 
					+	esfq_index	prev;
 | 
				
			||||||
 | 
					+};
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+struct esfq_sched_data
 | 
				
			||||||
 | 
					+{
 | 
				
			||||||
 | 
					+/* Parameters */
 | 
				
			||||||
 | 
					+	int		perturb_period;
 | 
				
			||||||
 | 
					+	unsigned	quantum;	/* Allotment per round: MUST BE >= MTU */
 | 
				
			||||||
 | 
					+	int		limit;
 | 
				
			||||||
 | 
					+	unsigned	depth;
 | 
				
			||||||
 | 
					+	unsigned	hash_divisor;
 | 
				
			||||||
 | 
					+	unsigned	hash_kind;
 | 
				
			||||||
 | 
					+/* Variables */
 | 
				
			||||||
 | 
					+	struct timer_list perturb_timer;
 | 
				
			||||||
 | 
					+	int		perturbation;
 | 
				
			||||||
 | 
					+	esfq_index	tail;		/* Index of current slot in round */
 | 
				
			||||||
 | 
					+	esfq_index	max_depth;	/* Maximal depth */
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	esfq_index	*ht;			/* Hash table */
 | 
				
			||||||
 | 
					+	esfq_index	*next;			/* Active slots link */
 | 
				
			||||||
 | 
					+	short		*allot;			/* Current allotment per slot */
 | 
				
			||||||
 | 
					+	unsigned short	*hash;			/* Hash value indexed by slots */
 | 
				
			||||||
 | 
					+	struct sk_buff_head	*qs;		/* Slot queue */
 | 
				
			||||||
 | 
					+	struct esfq_head	*dep;		/* Linked list of slots, indexed by depth */
 | 
				
			||||||
 | 
					+};
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+/* This contains the info we will hash. */
 | 
				
			||||||
 | 
					+struct esfq_packet_info
 | 
				
			||||||
 | 
					+{
 | 
				
			||||||
 | 
					+	u32	proto;		/* protocol or port */
 | 
				
			||||||
 | 
					+	u32	src;		/* source from packet header */
 | 
				
			||||||
 | 
					+	u32	dst;		/* destination from packet header */
 | 
				
			||||||
 | 
					+	u32	ctorigsrc;	/* original source from conntrack */
 | 
				
			||||||
 | 
					+	u32	ctorigdst;	/* original destination from conntrack */
 | 
				
			||||||
 | 
					+	u32	ctreplsrc;	/* reply source from conntrack */
 | 
				
			||||||
 | 
					+	u32	ctrepldst;	/* reply destination from conntrack */
 | 
				
			||||||
 | 
					+	u32	mark;		/* netfilter mark (fwmark) */
 | 
				
			||||||
 | 
					+};
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+static __inline__ unsigned esfq_jhash_1word(struct esfq_sched_data *q,u32 a)
 | 
				
			||||||
 | 
					+{
 | 
				
			||||||
 | 
					+	return jhash_1word(a, q->perturbation) & (q->hash_divisor-1);
 | 
				
			||||||
 | 
					+}
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+static __inline__ unsigned esfq_jhash_2words(struct esfq_sched_data *q, u32 a, u32 b)
 | 
				
			||||||
 | 
					+{
 | 
				
			||||||
 | 
					+	return jhash_2words(a, b, q->perturbation) & (q->hash_divisor-1);
 | 
				
			||||||
 | 
					+}
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+static __inline__ unsigned esfq_jhash_3words(struct esfq_sched_data *q, u32 a, u32 b, u32 c)
 | 
				
			||||||
 | 
					+{
 | 
				
			||||||
 | 
					+	return jhash_3words(a, b, c, q->perturbation) & (q->hash_divisor-1);
 | 
				
			||||||
 | 
					+}
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+static unsigned esfq_hash(struct esfq_sched_data *q, struct sk_buff *skb)
 | 
				
			||||||
 | 
					+{
 | 
				
			||||||
 | 
					+	struct esfq_packet_info info;
 | 
				
			||||||
 | 
					+#ifdef CONFIG_NET_SCH_ESFQ_NFCT
 | 
				
			||||||
 | 
					+	enum ip_conntrack_info ctinfo;
 | 
				
			||||||
 | 
					+	struct nf_conn *ct = nf_ct_get(skb, &ctinfo);
 | 
				
			||||||
 | 
					+#endif
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	switch (skb->protocol) {
 | 
				
			||||||
 | 
					+	case __constant_htons(ETH_P_IP):
 | 
				
			||||||
 | 
					+	{
 | 
				
			||||||
 | 
					+		struct iphdr *iph = ip_hdr(skb);
 | 
				
			||||||
 | 
					+		info.dst = iph->daddr;
 | 
				
			||||||
 | 
					+		info.src = iph->saddr;
 | 
				
			||||||
 | 
					+		if (!(iph->frag_off&htons(IP_MF|IP_OFFSET)) &&
 | 
				
			||||||
 | 
					+		    (iph->protocol == IPPROTO_TCP ||
 | 
				
			||||||
 | 
					+		     iph->protocol == IPPROTO_UDP ||
 | 
				
			||||||
 | 
					+		     iph->protocol == IPPROTO_SCTP ||
 | 
				
			||||||
 | 
					+		     iph->protocol == IPPROTO_DCCP ||
 | 
				
			||||||
 | 
					+		     iph->protocol == IPPROTO_ESP))
 | 
				
			||||||
 | 
					+			info.proto = *(((u32*)iph) + iph->ihl);
 | 
				
			||||||
 | 
					+		else
 | 
				
			||||||
 | 
					+			info.proto = iph->protocol;
 | 
				
			||||||
 | 
					+		break;
 | 
				
			||||||
 | 
					+	}
 | 
				
			||||||
 | 
					+	case __constant_htons(ETH_P_IPV6):
 | 
				
			||||||
 | 
					+	{
 | 
				
			||||||
 | 
					+		struct ipv6hdr *iph = ipv6_hdr(skb);
 | 
				
			||||||
 | 
					+		/* Hash ipv6 addresses into a u32. This isn't ideal,
 | 
				
			||||||
 | 
					+		 * but the code is simple. */
 | 
				
			||||||
 | 
					+		info.dst = jhash2(iph->daddr.s6_addr32, 4, q->perturbation);
 | 
				
			||||||
 | 
					+		info.src = jhash2(iph->saddr.s6_addr32, 4, q->perturbation);
 | 
				
			||||||
 | 
					+		if (iph->nexthdr == IPPROTO_TCP ||
 | 
				
			||||||
 | 
					+		    iph->nexthdr == IPPROTO_UDP ||
 | 
				
			||||||
 | 
					+		    iph->nexthdr == IPPROTO_SCTP ||
 | 
				
			||||||
 | 
					+		    iph->nexthdr == IPPROTO_DCCP ||
 | 
				
			||||||
 | 
					+		    iph->nexthdr == IPPROTO_ESP)
 | 
				
			||||||
 | 
					+			info.proto = *(u32*)&iph[1];
 | 
				
			||||||
 | 
					+		else
 | 
				
			||||||
 | 
					+			info.proto = iph->nexthdr;
 | 
				
			||||||
 | 
					+		break;
 | 
				
			||||||
 | 
					+	}
 | 
				
			||||||
 | 
					+	default:
 | 
				
			||||||
 | 
					+		info.dst   = (u32)(unsigned long)skb_dst(skb);
 | 
				
			||||||
 | 
					+		info.src   = (u32)(unsigned long)skb->sk;
 | 
				
			||||||
 | 
					+		info.proto = skb->protocol;
 | 
				
			||||||
 | 
					+	}
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	info.mark = skb->mark;
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+#ifdef CONFIG_NET_SCH_ESFQ_NFCT
 | 
				
			||||||
 | 
					+	/* defaults if there is no conntrack info */
 | 
				
			||||||
 | 
					+	info.ctorigsrc = info.src;
 | 
				
			||||||
 | 
					+	info.ctorigdst = info.dst;
 | 
				
			||||||
 | 
					+	info.ctreplsrc = info.dst;
 | 
				
			||||||
 | 
					+	info.ctrepldst = info.src;
 | 
				
			||||||
 | 
					+	/* collect conntrack info */
 | 
				
			||||||
 | 
					+	if (ct && ct != &nf_conntrack_untracked) {
 | 
				
			||||||
 | 
					+		if (skb->protocol == __constant_htons(ETH_P_IP)) {
 | 
				
			||||||
 | 
					+			info.ctorigsrc = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u3.ip;
 | 
				
			||||||
 | 
					+			info.ctorigdst = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.u3.ip;
 | 
				
			||||||
 | 
					+			info.ctreplsrc = ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.u3.ip;
 | 
				
			||||||
 | 
					+			info.ctrepldst = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u3.ip;
 | 
				
			||||||
 | 
					+		}
 | 
				
			||||||
 | 
					+		else if (skb->protocol == __constant_htons(ETH_P_IPV6)) {
 | 
				
			||||||
 | 
					+			/* Again, hash ipv6 addresses into a single u32. */
 | 
				
			||||||
 | 
					+			info.ctorigsrc = jhash2(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u3.ip6, 4, q->perturbation);
 | 
				
			||||||
 | 
					+			info.ctorigdst = jhash2(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.u3.ip6, 4, q->perturbation);
 | 
				
			||||||
 | 
					+			info.ctreplsrc = jhash2(ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.u3.ip6, 4, q->perturbation);
 | 
				
			||||||
 | 
					+			info.ctrepldst = jhash2(ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u3.ip6, 4, q->perturbation);
 | 
				
			||||||
 | 
					+		}
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	}
 | 
				
			||||||
 | 
					+#endif
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	switch(q->hash_kind) {
 | 
				
			||||||
 | 
					+	case TCA_SFQ_HASH_CLASSIC:
 | 
				
			||||||
 | 
					+		return esfq_jhash_3words(q, info.dst, info.src, info.proto);
 | 
				
			||||||
 | 
					+	case TCA_SFQ_HASH_DST:
 | 
				
			||||||
 | 
					+		return esfq_jhash_1word(q, info.dst);
 | 
				
			||||||
 | 
					+	case TCA_SFQ_HASH_SRC:
 | 
				
			||||||
 | 
					+		return esfq_jhash_1word(q, info.src);
 | 
				
			||||||
 | 
					+	case TCA_SFQ_HASH_FWMARK:
 | 
				
			||||||
 | 
					+		return esfq_jhash_1word(q, info.mark);
 | 
				
			||||||
 | 
					+#ifdef CONFIG_NET_SCH_ESFQ_NFCT
 | 
				
			||||||
 | 
					+	case TCA_SFQ_HASH_CTORIGDST:
 | 
				
			||||||
 | 
					+		return esfq_jhash_1word(q, info.ctorigdst);
 | 
				
			||||||
 | 
					+	case TCA_SFQ_HASH_CTORIGSRC:
 | 
				
			||||||
 | 
					+		return esfq_jhash_1word(q, info.ctorigsrc);
 | 
				
			||||||
 | 
					+	case TCA_SFQ_HASH_CTREPLDST:
 | 
				
			||||||
 | 
					+		return esfq_jhash_1word(q, info.ctrepldst);
 | 
				
			||||||
 | 
					+	case TCA_SFQ_HASH_CTREPLSRC:
 | 
				
			||||||
 | 
					+		return esfq_jhash_1word(q, info.ctreplsrc);
 | 
				
			||||||
 | 
					+	case TCA_SFQ_HASH_CTNATCHG:
 | 
				
			||||||
 | 
					+	{
 | 
				
			||||||
 | 
					+		if (info.ctorigdst == info.ctreplsrc)
 | 
				
			||||||
 | 
					+			return esfq_jhash_1word(q, info.ctorigsrc);
 | 
				
			||||||
 | 
					+		return esfq_jhash_1word(q, info.ctreplsrc);
 | 
				
			||||||
 | 
					+	}
 | 
				
			||||||
 | 
					+#endif
 | 
				
			||||||
 | 
					+	default:
 | 
				
			||||||
 | 
					+		if (net_ratelimit())
 | 
				
			||||||
 | 
					+			printk(KERN_WARNING "ESFQ: Unknown hash method. Falling back to classic.\n");
 | 
				
			||||||
 | 
					+	}
 | 
				
			||||||
 | 
					+	return esfq_jhash_3words(q, info.dst, info.src, info.proto);
 | 
				
			||||||
 | 
					+}
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+static inline void esfq_link(struct esfq_sched_data *q, esfq_index x)
 | 
				
			||||||
 | 
					+{
 | 
				
			||||||
 | 
					+	esfq_index p, n;
 | 
				
			||||||
 | 
					+	int d = q->qs[x].qlen + q->depth;
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	p = d;
 | 
				
			||||||
 | 
					+	n = q->dep[d].next;
 | 
				
			||||||
 | 
					+	q->dep[x].next = n;
 | 
				
			||||||
 | 
					+	q->dep[x].prev = p;
 | 
				
			||||||
 | 
					+	q->dep[p].next = q->dep[n].prev = x;
 | 
				
			||||||
 | 
					+}
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+static inline void esfq_dec(struct esfq_sched_data *q, esfq_index x)
 | 
				
			||||||
 | 
					+{
 | 
				
			||||||
 | 
					+	esfq_index p, n;
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	n = q->dep[x].next;
 | 
				
			||||||
 | 
					+	p = q->dep[x].prev;
 | 
				
			||||||
 | 
					+	q->dep[p].next = n;
 | 
				
			||||||
 | 
					+	q->dep[n].prev = p;
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	if (n == p && q->max_depth == q->qs[x].qlen + 1)
 | 
				
			||||||
 | 
					+		q->max_depth--;
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	esfq_link(q, x);
 | 
				
			||||||
 | 
					+}
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+static inline void esfq_inc(struct esfq_sched_data *q, esfq_index x)
 | 
				
			||||||
 | 
					+{
 | 
				
			||||||
 | 
					+	esfq_index p, n;
 | 
				
			||||||
 | 
					+	int d;
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	n = q->dep[x].next;
 | 
				
			||||||
 | 
					+	p = q->dep[x].prev;
 | 
				
			||||||
 | 
					+	q->dep[p].next = n;
 | 
				
			||||||
 | 
					+	q->dep[n].prev = p;
 | 
				
			||||||
 | 
					+	d = q->qs[x].qlen;
 | 
				
			||||||
 | 
					+	if (q->max_depth < d)
 | 
				
			||||||
 | 
					+		q->max_depth = d;
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	esfq_link(q, x);
 | 
				
			||||||
 | 
					+}
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+static unsigned int esfq_drop(struct Qdisc *sch)
 | 
				
			||||||
 | 
					+{
 | 
				
			||||||
 | 
					+	struct esfq_sched_data *q = qdisc_priv(sch);
 | 
				
			||||||
 | 
					+	esfq_index d = q->max_depth;
 | 
				
			||||||
 | 
					+	struct sk_buff *skb;
 | 
				
			||||||
 | 
					+	unsigned int len;
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	/* Queue is full! Find the longest slot and
 | 
				
			||||||
 | 
					+	   drop a packet from it */
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	if (d > 1) {
 | 
				
			||||||
 | 
					+		esfq_index x = q->dep[d+q->depth].next;
 | 
				
			||||||
 | 
					+		skb = q->qs[x].prev;
 | 
				
			||||||
 | 
					+		len = skb->len;
 | 
				
			||||||
 | 
					+		__skb_unlink(skb, &q->qs[x]);
 | 
				
			||||||
 | 
					+		kfree_skb(skb);
 | 
				
			||||||
 | 
					+		esfq_dec(q, x);
 | 
				
			||||||
 | 
					+		sch->q.qlen--;
 | 
				
			||||||
 | 
					+		sch->qstats.drops++;
 | 
				
			||||||
 | 
					+		sch->qstats.backlog -= len;
 | 
				
			||||||
 | 
					+		return len;
 | 
				
			||||||
 | 
					+	}
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	if (d == 1) {
 | 
				
			||||||
 | 
					+		/* It is difficult to believe, but ALL THE SLOTS HAVE LENGTH 1. */
 | 
				
			||||||
 | 
					+		d = q->next[q->tail];
 | 
				
			||||||
 | 
					+		q->next[q->tail] = q->next[d];
 | 
				
			||||||
 | 
					+		q->allot[q->next[d]] += q->quantum;
 | 
				
			||||||
 | 
					+		skb = q->qs[d].prev;
 | 
				
			||||||
 | 
					+		len = skb->len;
 | 
				
			||||||
 | 
					+		__skb_unlink(skb, &q->qs[d]);
 | 
				
			||||||
 | 
					+		kfree_skb(skb);
 | 
				
			||||||
 | 
					+		esfq_dec(q, d);
 | 
				
			||||||
 | 
					+		sch->q.qlen--;
 | 
				
			||||||
 | 
					+		q->ht[q->hash[d]] = q->depth;
 | 
				
			||||||
 | 
					+		sch->qstats.drops++;
 | 
				
			||||||
 | 
					+		sch->qstats.backlog -= len;
 | 
				
			||||||
 | 
					+		return len;
 | 
				
			||||||
 | 
					+	}
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	return 0;
 | 
				
			||||||
 | 
					+}
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+static void esfq_q_enqueue(struct sk_buff *skb, struct esfq_sched_data *q, unsigned int end)
 | 
				
			||||||
 | 
					+{
 | 
				
			||||||
 | 
					+	unsigned hash = esfq_hash(q, skb);
 | 
				
			||||||
 | 
					+	unsigned depth = q->depth;
 | 
				
			||||||
 | 
					+	esfq_index x;
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	x = q->ht[hash];
 | 
				
			||||||
 | 
					+	if (x == depth) {
 | 
				
			||||||
 | 
					+		q->ht[hash] = x = q->dep[depth].next;
 | 
				
			||||||
 | 
					+		q->hash[x] = hash;
 | 
				
			||||||
 | 
					+	}
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	if (end == ESFQ_TAIL)
 | 
				
			||||||
 | 
					+		__skb_queue_tail(&q->qs[x], skb);
 | 
				
			||||||
 | 
					+	else
 | 
				
			||||||
 | 
					+		__skb_queue_head(&q->qs[x], skb);
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	esfq_inc(q, x);
 | 
				
			||||||
 | 
					+	if (q->qs[x].qlen == 1) {		/* The flow is new */
 | 
				
			||||||
 | 
					+		if (q->tail == depth) {	/* It is the first flow */
 | 
				
			||||||
 | 
					+			q->tail = x;
 | 
				
			||||||
 | 
					+			q->next[x] = x;
 | 
				
			||||||
 | 
					+			q->allot[x] = q->quantum;
 | 
				
			||||||
 | 
					+		} else {
 | 
				
			||||||
 | 
					+			q->next[x] = q->next[q->tail];
 | 
				
			||||||
 | 
					+			q->next[q->tail] = x;
 | 
				
			||||||
 | 
					+			q->tail = x;
 | 
				
			||||||
 | 
					+		}
 | 
				
			||||||
 | 
					+	}
 | 
				
			||||||
 | 
					+}
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+static int esfq_enqueue(struct sk_buff *skb, struct Qdisc* sch)
 | 
				
			||||||
 | 
					+{
 | 
				
			||||||
 | 
					+	struct esfq_sched_data *q = qdisc_priv(sch);
 | 
				
			||||||
 | 
					+	esfq_q_enqueue(skb, q, ESFQ_TAIL);
 | 
				
			||||||
 | 
					+	sch->qstats.backlog += skb->len;
 | 
				
			||||||
 | 
					+	if (++sch->q.qlen < q->limit-1) {
 | 
				
			||||||
 | 
					+		sch->bstats.bytes += skb->len;
 | 
				
			||||||
 | 
					+		sch->bstats.packets++;
 | 
				
			||||||
 | 
					+		return 0;
 | 
				
			||||||
 | 
					+	}
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	sch->qstats.drops++;
 | 
				
			||||||
 | 
					+	esfq_drop(sch);
 | 
				
			||||||
 | 
					+	return NET_XMIT_CN;
 | 
				
			||||||
 | 
					+}
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+static struct sk_buff *esfq_peek(struct Qdisc* sch)
 | 
				
			||||||
 | 
					+{
 | 
				
			||||||
 | 
					+	struct esfq_sched_data *q = qdisc_priv(sch);
 | 
				
			||||||
 | 
					+	esfq_index a;
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	/* No active slots */
 | 
				
			||||||
 | 
					+	if (q->tail == q->depth)
 | 
				
			||||||
 | 
					+		return NULL;
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	a = q->next[q->tail];
 | 
				
			||||||
 | 
					+	return skb_peek(&q->qs[a]);
 | 
				
			||||||
 | 
					+}
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+static struct sk_buff *esfq_q_dequeue(struct esfq_sched_data *q)
 | 
				
			||||||
 | 
					+{
 | 
				
			||||||
 | 
					+	struct sk_buff *skb;
 | 
				
			||||||
 | 
					+	unsigned depth = q->depth;
 | 
				
			||||||
 | 
					+	esfq_index a, old_a;
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	/* No active slots */
 | 
				
			||||||
 | 
					+	if (q->tail == depth)
 | 
				
			||||||
 | 
					+		return NULL;
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	a = old_a = q->next[q->tail];
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	/* Grab packet */
 | 
				
			||||||
 | 
					+	skb = __skb_dequeue(&q->qs[a]);
 | 
				
			||||||
 | 
					+	esfq_dec(q, a);
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	/* Is the slot empty? */
 | 
				
			||||||
 | 
					+	if (q->qs[a].qlen == 0) {
 | 
				
			||||||
 | 
					+		q->ht[q->hash[a]] = depth;
 | 
				
			||||||
 | 
					+		a = q->next[a];
 | 
				
			||||||
 | 
					+		if (a == old_a) {
 | 
				
			||||||
 | 
					+			q->tail = depth;
 | 
				
			||||||
 | 
					+			return skb;
 | 
				
			||||||
 | 
					+		}
 | 
				
			||||||
 | 
					+		q->next[q->tail] = a;
 | 
				
			||||||
 | 
					+		q->allot[a] += q->quantum;
 | 
				
			||||||
 | 
					+	} else if ((q->allot[a] -= skb->len) <= 0) {
 | 
				
			||||||
 | 
					+		q->tail = a;
 | 
				
			||||||
 | 
					+		a = q->next[a];
 | 
				
			||||||
 | 
					+		q->allot[a] += q->quantum;
 | 
				
			||||||
 | 
					+	}
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	return skb;
 | 
				
			||||||
 | 
					+}
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+static struct sk_buff *esfq_dequeue(struct Qdisc* sch)
 | 
				
			||||||
 | 
					+{
 | 
				
			||||||
 | 
					+	struct esfq_sched_data *q = qdisc_priv(sch);
 | 
				
			||||||
 | 
					+	struct sk_buff *skb;
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	skb = esfq_q_dequeue(q);
 | 
				
			||||||
 | 
					+	if (skb == NULL)
 | 
				
			||||||
 | 
					+		return NULL;
 | 
				
			||||||
 | 
					+	sch->q.qlen--;
 | 
				
			||||||
 | 
					+	sch->qstats.backlog -= skb->len;
 | 
				
			||||||
 | 
					+	return skb;
 | 
				
			||||||
 | 
					+}
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+static void esfq_q_destroy(struct esfq_sched_data *q)
 | 
				
			||||||
 | 
					+{
 | 
				
			||||||
 | 
					+	del_timer(&q->perturb_timer);
 | 
				
			||||||
 | 
					+	if(q->ht)
 | 
				
			||||||
 | 
					+		kfree(q->ht);
 | 
				
			||||||
 | 
					+	if(q->dep)
 | 
				
			||||||
 | 
					+		kfree(q->dep);
 | 
				
			||||||
 | 
					+	if(q->next)
 | 
				
			||||||
 | 
					+		kfree(q->next);
 | 
				
			||||||
 | 
					+	if(q->allot)
 | 
				
			||||||
 | 
					+		kfree(q->allot);
 | 
				
			||||||
 | 
					+	if(q->hash)
 | 
				
			||||||
 | 
					+		kfree(q->hash);
 | 
				
			||||||
 | 
					+	if(q->qs)
 | 
				
			||||||
 | 
					+		kfree(q->qs);
 | 
				
			||||||
 | 
					+}
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+static void esfq_destroy(struct Qdisc *sch)
 | 
				
			||||||
 | 
					+{
 | 
				
			||||||
 | 
					+	struct esfq_sched_data *q = qdisc_priv(sch);
 | 
				
			||||||
 | 
					+	esfq_q_destroy(q);
 | 
				
			||||||
 | 
					+}
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+static void esfq_reset(struct Qdisc* sch)
 | 
				
			||||||
 | 
					+{
 | 
				
			||||||
 | 
					+	struct sk_buff *skb;
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	while ((skb = esfq_dequeue(sch)) != NULL)
 | 
				
			||||||
 | 
					+		kfree_skb(skb);
 | 
				
			||||||
 | 
					+}
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+static void esfq_perturbation(unsigned long arg)
 | 
				
			||||||
 | 
					+{
 | 
				
			||||||
 | 
					+	struct Qdisc *sch = (struct Qdisc*)arg;
 | 
				
			||||||
 | 
					+	struct esfq_sched_data *q = qdisc_priv(sch);
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	q->perturbation = net_random()&0x1F;
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	if (q->perturb_period) {
 | 
				
			||||||
 | 
					+		q->perturb_timer.expires = jiffies + q->perturb_period;
 | 
				
			||||||
 | 
					+		add_timer(&q->perturb_timer);
 | 
				
			||||||
 | 
					+	}
 | 
				
			||||||
 | 
					+}
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+static unsigned int esfq_check_hash(unsigned int kind)
 | 
				
			||||||
 | 
					+{
 | 
				
			||||||
 | 
					+	switch (kind) {
 | 
				
			||||||
 | 
					+	case TCA_SFQ_HASH_CTORIGDST:
 | 
				
			||||||
 | 
					+	case TCA_SFQ_HASH_CTORIGSRC:
 | 
				
			||||||
 | 
					+	case TCA_SFQ_HASH_CTREPLDST:
 | 
				
			||||||
 | 
					+	case TCA_SFQ_HASH_CTREPLSRC:
 | 
				
			||||||
 | 
					+	case TCA_SFQ_HASH_CTNATCHG:
 | 
				
			||||||
 | 
					+#ifndef CONFIG_NET_SCH_ESFQ_NFCT
 | 
				
			||||||
 | 
					+	{
 | 
				
			||||||
 | 
					+		if (net_ratelimit())
 | 
				
			||||||
 | 
					+			printk(KERN_WARNING "ESFQ: Conntrack hash types disabled in kernel config. Falling back to classic.\n");
 | 
				
			||||||
 | 
					+		return TCA_SFQ_HASH_CLASSIC;
 | 
				
			||||||
 | 
					+	}
 | 
				
			||||||
 | 
					+#endif
 | 
				
			||||||
 | 
					+	case TCA_SFQ_HASH_CLASSIC:
 | 
				
			||||||
 | 
					+	case TCA_SFQ_HASH_DST:
 | 
				
			||||||
 | 
					+	case TCA_SFQ_HASH_SRC:
 | 
				
			||||||
 | 
					+	case TCA_SFQ_HASH_FWMARK:
 | 
				
			||||||
 | 
					+		return kind;
 | 
				
			||||||
 | 
					+	default:
 | 
				
			||||||
 | 
					+	{
 | 
				
			||||||
 | 
					+		if (net_ratelimit())
 | 
				
			||||||
 | 
					+			printk(KERN_WARNING "ESFQ: Unknown hash type. Falling back to classic.\n");
 | 
				
			||||||
 | 
					+		return TCA_SFQ_HASH_CLASSIC;
 | 
				
			||||||
 | 
					+	}
 | 
				
			||||||
 | 
					+	}
 | 
				
			||||||
 | 
					+}
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+static int esfq_q_init(struct esfq_sched_data *q, struct nlattr *opt)
 | 
				
			||||||
 | 
					+{
 | 
				
			||||||
 | 
					+	struct tc_esfq_qopt *ctl = nla_data(opt);
 | 
				
			||||||
 | 
					+	esfq_index p = ~0U/2;
 | 
				
			||||||
 | 
					+	int i;
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	if (opt && opt->nla_len < nla_attr_size(sizeof(*ctl)))
 | 
				
			||||||
 | 
					+		return -EINVAL;
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	q->perturbation = 0;
 | 
				
			||||||
 | 
					+	q->hash_kind = TCA_SFQ_HASH_CLASSIC;
 | 
				
			||||||
 | 
					+	q->max_depth = 0;
 | 
				
			||||||
 | 
					+	if (opt == NULL) {
 | 
				
			||||||
 | 
					+		q->perturb_period = 0;
 | 
				
			||||||
 | 
					+		q->hash_divisor = 1024;
 | 
				
			||||||
 | 
					+		q->tail = q->limit = q->depth = 128;
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	} else {
 | 
				
			||||||
 | 
					+		struct tc_esfq_qopt *ctl = nla_data(opt);
 | 
				
			||||||
 | 
					+		if (ctl->quantum)
 | 
				
			||||||
 | 
					+			q->quantum = ctl->quantum;
 | 
				
			||||||
 | 
					+		q->perturb_period = ctl->perturb_period*HZ;
 | 
				
			||||||
 | 
					+		q->hash_divisor = ctl->divisor ? : 1024;
 | 
				
			||||||
 | 
					+		q->tail = q->limit = q->depth = ctl->flows ? : 128;
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+		if ( q->depth > p - 1 )
 | 
				
			||||||
 | 
					+			return -EINVAL;
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+		if (ctl->limit)
 | 
				
			||||||
 | 
					+			q->limit = min_t(u32, ctl->limit, q->depth);
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+		if (ctl->hash_kind) {
 | 
				
			||||||
 | 
					+			q->hash_kind = esfq_check_hash(ctl->hash_kind);
 | 
				
			||||||
 | 
					+		}
 | 
				
			||||||
 | 
					+	}
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	q->ht = kmalloc(q->hash_divisor*sizeof(esfq_index), GFP_KERNEL);
 | 
				
			||||||
 | 
					+	if (!q->ht)
 | 
				
			||||||
 | 
					+		goto err_case;
 | 
				
			||||||
 | 
					+	q->dep = kmalloc((1+q->depth*2)*sizeof(struct esfq_head), GFP_KERNEL);
 | 
				
			||||||
 | 
					+	if (!q->dep)
 | 
				
			||||||
 | 
					+		goto err_case;
 | 
				
			||||||
 | 
					+	q->next = kmalloc(q->depth*sizeof(esfq_index), GFP_KERNEL);
 | 
				
			||||||
 | 
					+	if (!q->next)
 | 
				
			||||||
 | 
					+		goto err_case;
 | 
				
			||||||
 | 
					+	q->allot = kmalloc(q->depth*sizeof(short), GFP_KERNEL);
 | 
				
			||||||
 | 
					+	if (!q->allot)
 | 
				
			||||||
 | 
					+		goto err_case;
 | 
				
			||||||
 | 
					+	q->hash = kmalloc(q->depth*sizeof(unsigned short), GFP_KERNEL);
 | 
				
			||||||
 | 
					+	if (!q->hash)
 | 
				
			||||||
 | 
					+		goto err_case;
 | 
				
			||||||
 | 
					+	q->qs = kmalloc(q->depth*sizeof(struct sk_buff_head), GFP_KERNEL);
 | 
				
			||||||
 | 
					+	if (!q->qs)
 | 
				
			||||||
 | 
					+		goto err_case;
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	for (i=0; i< q->hash_divisor; i++)
 | 
				
			||||||
 | 
					+		q->ht[i] = q->depth;
 | 
				
			||||||
 | 
					+	for (i=0; i<q->depth; i++) {
 | 
				
			||||||
 | 
					+		skb_queue_head_init(&q->qs[i]);
 | 
				
			||||||
 | 
					+		q->dep[i+q->depth].next = i+q->depth;
 | 
				
			||||||
 | 
					+		q->dep[i+q->depth].prev = i+q->depth;
 | 
				
			||||||
 | 
					+	}
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	for (i=0; i<q->depth; i++)
 | 
				
			||||||
 | 
					+		esfq_link(q, i);
 | 
				
			||||||
 | 
					+	return 0;
 | 
				
			||||||
 | 
					+err_case:
 | 
				
			||||||
 | 
					+	esfq_q_destroy(q);
 | 
				
			||||||
 | 
					+	return -ENOBUFS;
 | 
				
			||||||
 | 
					+}
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+static int esfq_init(struct Qdisc *sch, struct nlattr *opt)
 | 
				
			||||||
 | 
					+{
 | 
				
			||||||
 | 
					+	struct esfq_sched_data *q = qdisc_priv(sch);
 | 
				
			||||||
 | 
					+	int err;
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	q->quantum = psched_mtu(qdisc_dev(sch)); /* default */
 | 
				
			||||||
 | 
					+	if ((err = esfq_q_init(q, opt)))
 | 
				
			||||||
 | 
					+		return err;
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	init_timer(&q->perturb_timer);
 | 
				
			||||||
 | 
					+	q->perturb_timer.data = (unsigned long)sch;
 | 
				
			||||||
 | 
					+	q->perturb_timer.function = esfq_perturbation;
 | 
				
			||||||
 | 
					+	if (q->perturb_period) {
 | 
				
			||||||
 | 
					+		q->perturb_timer.expires = jiffies + q->perturb_period;
 | 
				
			||||||
 | 
					+		add_timer(&q->perturb_timer);
 | 
				
			||||||
 | 
					+	}
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	return 0;
 | 
				
			||||||
 | 
					+}
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+static int esfq_change(struct Qdisc *sch, struct nlattr *opt)
 | 
				
			||||||
 | 
					+{
 | 
				
			||||||
 | 
					+	struct esfq_sched_data *q = qdisc_priv(sch);
 | 
				
			||||||
 | 
					+	struct esfq_sched_data new;
 | 
				
			||||||
 | 
					+	struct sk_buff *skb;
 | 
				
			||||||
 | 
					+	int err;
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	/* set up new queue */
 | 
				
			||||||
 | 
					+	memset(&new, 0, sizeof(struct esfq_sched_data));
 | 
				
			||||||
 | 
					+	new.quantum = psched_mtu(qdisc_dev(sch)); /* default */
 | 
				
			||||||
 | 
					+	if ((err = esfq_q_init(&new, opt)))
 | 
				
			||||||
 | 
					+		return err;
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	/* copy all packets from the old queue to the new queue */
 | 
				
			||||||
 | 
					+	sch_tree_lock(sch);
 | 
				
			||||||
 | 
					+	while ((skb = esfq_q_dequeue(q)) != NULL)
 | 
				
			||||||
 | 
					+		esfq_q_enqueue(skb, &new, ESFQ_TAIL);
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	/* clean up the old queue */
 | 
				
			||||||
 | 
					+	esfq_q_destroy(q);
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	/* copy elements of the new queue into the old queue */
 | 
				
			||||||
 | 
					+	q->perturb_period = new.perturb_period;
 | 
				
			||||||
 | 
					+	q->quantum        = new.quantum;
 | 
				
			||||||
 | 
					+	q->limit          = new.limit;
 | 
				
			||||||
 | 
					+	q->depth          = new.depth;
 | 
				
			||||||
 | 
					+	q->hash_divisor   = new.hash_divisor;
 | 
				
			||||||
 | 
					+	q->hash_kind      = new.hash_kind;
 | 
				
			||||||
 | 
					+	q->tail           = new.tail;
 | 
				
			||||||
 | 
					+	q->max_depth      = new.max_depth;
 | 
				
			||||||
 | 
					+	q->ht    = new.ht;
 | 
				
			||||||
 | 
					+	q->dep   = new.dep;
 | 
				
			||||||
 | 
					+	q->next  = new.next;
 | 
				
			||||||
 | 
					+	q->allot = new.allot;
 | 
				
			||||||
 | 
					+	q->hash  = new.hash;
 | 
				
			||||||
 | 
					+	q->qs    = new.qs;
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	/* finish up */
 | 
				
			||||||
 | 
					+	if (q->perturb_period) {
 | 
				
			||||||
 | 
					+		q->perturb_timer.expires = jiffies + q->perturb_period;
 | 
				
			||||||
 | 
					+		add_timer(&q->perturb_timer);
 | 
				
			||||||
 | 
					+	} else {
 | 
				
			||||||
 | 
					+		q->perturbation = 0;
 | 
				
			||||||
 | 
					+	}
 | 
				
			||||||
 | 
					+	sch_tree_unlock(sch);
 | 
				
			||||||
 | 
					+	return 0;
 | 
				
			||||||
 | 
					+}
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+static int esfq_dump(struct Qdisc *sch, struct sk_buff *skb)
 | 
				
			||||||
 | 
					+{
 | 
				
			||||||
 | 
					+	struct esfq_sched_data *q = qdisc_priv(sch);
 | 
				
			||||||
 | 
					+	unsigned char *b = skb_tail_pointer(skb);
 | 
				
			||||||
 | 
					+	struct tc_esfq_qopt opt;
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	opt.quantum = q->quantum;
 | 
				
			||||||
 | 
					+	opt.perturb_period = q->perturb_period/HZ;
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	opt.limit = q->limit;
 | 
				
			||||||
 | 
					+	opt.divisor = q->hash_divisor;
 | 
				
			||||||
 | 
					+	opt.flows = q->depth;
 | 
				
			||||||
 | 
					+	opt.hash_kind = q->hash_kind;
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	NLA_PUT(skb, TCA_OPTIONS, sizeof(opt), &opt);
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	return skb->len;
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+nla_put_failure:
 | 
				
			||||||
 | 
					+	nlmsg_trim(skb, b);
 | 
				
			||||||
 | 
					+	return -1;
 | 
				
			||||||
 | 
					+}
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+static struct Qdisc_ops esfq_qdisc_ops =
 | 
				
			||||||
 | 
					+{
 | 
				
			||||||
 | 
					+	.next		=	NULL,
 | 
				
			||||||
 | 
					+	.cl_ops		=	NULL,
 | 
				
			||||||
 | 
					+	.id		=	"esfq",
 | 
				
			||||||
 | 
					+	.priv_size	=	sizeof(struct esfq_sched_data),
 | 
				
			||||||
 | 
					+	.enqueue	=	esfq_enqueue,
 | 
				
			||||||
 | 
					+	.dequeue	=	esfq_dequeue,
 | 
				
			||||||
 | 
					+	.peek		=	esfq_peek,
 | 
				
			||||||
 | 
					+	.drop		=	esfq_drop,
 | 
				
			||||||
 | 
					+	.init		=	esfq_init,
 | 
				
			||||||
 | 
					+	.reset		=	esfq_reset,
 | 
				
			||||||
 | 
					+	.destroy	=	esfq_destroy,
 | 
				
			||||||
 | 
					+	.change		=	esfq_change,
 | 
				
			||||||
 | 
					+	.dump		=	esfq_dump,
 | 
				
			||||||
 | 
					+	.owner		=	THIS_MODULE,
 | 
				
			||||||
 | 
					+};
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+static int __init esfq_module_init(void)
 | 
				
			||||||
 | 
					+{
 | 
				
			||||||
 | 
					+	return register_qdisc(&esfq_qdisc_ops);
 | 
				
			||||||
 | 
					+}
 | 
				
			||||||
 | 
					+static void __exit esfq_module_exit(void)
 | 
				
			||||||
 | 
					+{
 | 
				
			||||||
 | 
					+	unregister_qdisc(&esfq_qdisc_ops);
 | 
				
			||||||
 | 
					+}
 | 
				
			||||||
 | 
					+module_init(esfq_module_init)
 | 
				
			||||||
 | 
					+module_exit(esfq_module_exit)
 | 
				
			||||||
 | 
					+MODULE_LICENSE("GPL");
 | 
				
			||||||
							
								
								
									
										172
									
								
								target/linux/generic/patches-3.1/621-sched_act_connmark.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										172
									
								
								target/linux/generic/patches-3.1/621-sched_act_connmark.patch
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,172 @@
 | 
				
			|||||||
 | 
					--- /dev/null
 | 
				
			||||||
 | 
					+++ b/net/sched/act_connmark.c
 | 
				
			||||||
 | 
					@@ -0,0 +1,137 @@
 | 
				
			||||||
 | 
					+/*
 | 
				
			||||||
 | 
					+ * Copyright (c) 2011 Felix Fietkau <nbd@openwrt.org>
 | 
				
			||||||
 | 
					+ *
 | 
				
			||||||
 | 
					+ * This program is free software; you can redistribute it and/or modify it
 | 
				
			||||||
 | 
					+ * under the terms and conditions of the GNU General Public License,
 | 
				
			||||||
 | 
					+ * version 2, as published by the Free Software Foundation.
 | 
				
			||||||
 | 
					+ *
 | 
				
			||||||
 | 
					+ * This program is distributed in the hope it will be useful, but WITHOUT
 | 
				
			||||||
 | 
					+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 | 
				
			||||||
 | 
					+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
 | 
				
			||||||
 | 
					+ * more details.
 | 
				
			||||||
 | 
					+ *
 | 
				
			||||||
 | 
					+ * You should have received a copy of the GNU General Public License along with
 | 
				
			||||||
 | 
					+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
 | 
				
			||||||
 | 
					+ * Place - Suite 330, Boston, MA 02111-1307 USA.
 | 
				
			||||||
 | 
					+ */
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+#include <linux/module.h>
 | 
				
			||||||
 | 
					+#include <linux/init.h>
 | 
				
			||||||
 | 
					+#include <linux/kernel.h>
 | 
				
			||||||
 | 
					+#include <linux/skbuff.h>
 | 
				
			||||||
 | 
					+#include <linux/rtnetlink.h>
 | 
				
			||||||
 | 
					+#include <linux/pkt_cls.h>
 | 
				
			||||||
 | 
					+#include <linux/ip.h>
 | 
				
			||||||
 | 
					+#include <linux/ipv6.h>
 | 
				
			||||||
 | 
					+#include <net/netlink.h>
 | 
				
			||||||
 | 
					+#include <net/pkt_sched.h>
 | 
				
			||||||
 | 
					+#include <net/act_api.h>
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+#include <net/netfilter/nf_conntrack.h>
 | 
				
			||||||
 | 
					+#include <net/netfilter/nf_conntrack_core.h>
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+#define TCA_ACT_CONNMARK	20
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+#define CONNMARK_TAB_MASK     3
 | 
				
			||||||
 | 
					+static struct tcf_common *tcf_connmark_ht[CONNMARK_TAB_MASK + 1];
 | 
				
			||||||
 | 
					+static u32 connmark_idx_gen;
 | 
				
			||||||
 | 
					+static DEFINE_RWLOCK(connmark_lock);
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+static struct tcf_hashinfo connmark_hash_info = {
 | 
				
			||||||
 | 
					+	.htab	=	tcf_connmark_ht,
 | 
				
			||||||
 | 
					+	.hmask	=	CONNMARK_TAB_MASK,
 | 
				
			||||||
 | 
					+	.lock	=	&connmark_lock,
 | 
				
			||||||
 | 
					+};
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+static int tcf_connmark(struct sk_buff *skb, struct tc_action *a,
 | 
				
			||||||
 | 
					+		       struct tcf_result *res)
 | 
				
			||||||
 | 
					+{
 | 
				
			||||||
 | 
					+	struct nf_conn *c;
 | 
				
			||||||
 | 
					+	enum ip_conntrack_info ctinfo;
 | 
				
			||||||
 | 
					+	int proto;
 | 
				
			||||||
 | 
					+	int r;
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	if (skb->protocol == htons(ETH_P_IP)) {
 | 
				
			||||||
 | 
					+		if (skb->len < sizeof(struct iphdr))
 | 
				
			||||||
 | 
					+			goto out;
 | 
				
			||||||
 | 
					+		proto = PF_INET;
 | 
				
			||||||
 | 
					+	} else if (skb->protocol == htons(ETH_P_IPV6)) {
 | 
				
			||||||
 | 
					+		if (skb->len < sizeof(struct ipv6hdr))
 | 
				
			||||||
 | 
					+			goto out;
 | 
				
			||||||
 | 
					+		proto = PF_INET6;
 | 
				
			||||||
 | 
					+	} else
 | 
				
			||||||
 | 
					+		goto out;
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	r = nf_conntrack_in(dev_net(skb->dev), proto, NF_INET_PRE_ROUTING, skb);
 | 
				
			||||||
 | 
					+	if (r != NF_ACCEPT)
 | 
				
			||||||
 | 
					+		goto out;
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	c = nf_ct_get(skb, &ctinfo);
 | 
				
			||||||
 | 
					+	if (!c)
 | 
				
			||||||
 | 
					+		goto out;
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	skb->mark = c->mark;
 | 
				
			||||||
 | 
					+	nf_conntrack_put(skb->nfct);
 | 
				
			||||||
 | 
					+	skb->nfct = NULL;
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+out:
 | 
				
			||||||
 | 
					+	return TC_ACT_PIPE;
 | 
				
			||||||
 | 
					+}
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+static int tcf_connmark_init(struct nlattr *nla, struct nlattr *est,
 | 
				
			||||||
 | 
					+			 struct tc_action *a, int ovr, int bind)
 | 
				
			||||||
 | 
					+{
 | 
				
			||||||
 | 
					+	struct tcf_common *pc;
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	pc = tcf_hash_create(0, est, a, sizeof(*pc), bind,
 | 
				
			||||||
 | 
					+			     &connmark_idx_gen, &connmark_hash_info);
 | 
				
			||||||
 | 
					+	if (IS_ERR(pc))
 | 
				
			||||||
 | 
					+	    return PTR_ERR(pc);
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	tcf_hash_insert(pc, &connmark_hash_info);
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	return ACT_P_CREATED;
 | 
				
			||||||
 | 
					+}
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+static inline int tcf_connmark_cleanup(struct tc_action *a, int bind)
 | 
				
			||||||
 | 
					+{
 | 
				
			||||||
 | 
					+	if (a->priv)
 | 
				
			||||||
 | 
					+		return tcf_hash_release(a->priv, bind, &connmark_hash_info);
 | 
				
			||||||
 | 
					+	return 0;
 | 
				
			||||||
 | 
					+}
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+static inline int tcf_connmark_dump(struct sk_buff *skb, struct tc_action *a,
 | 
				
			||||||
 | 
					+				int bind, int ref)
 | 
				
			||||||
 | 
					+{
 | 
				
			||||||
 | 
					+	return skb->len;
 | 
				
			||||||
 | 
					+}
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+static struct tc_action_ops act_connmark_ops = {
 | 
				
			||||||
 | 
					+	.kind		=	"connmark",
 | 
				
			||||||
 | 
					+	.hinfo		=	&connmark_hash_info,
 | 
				
			||||||
 | 
					+	.type		=	TCA_ACT_CONNMARK,
 | 
				
			||||||
 | 
					+	.capab		=	TCA_CAP_NONE,
 | 
				
			||||||
 | 
					+	.owner		=	THIS_MODULE,
 | 
				
			||||||
 | 
					+	.act		=	tcf_connmark,
 | 
				
			||||||
 | 
					+	.dump		=	tcf_connmark_dump,
 | 
				
			||||||
 | 
					+	.cleanup	=	tcf_connmark_cleanup,
 | 
				
			||||||
 | 
					+	.init		=	tcf_connmark_init,
 | 
				
			||||||
 | 
					+	.walk		=	tcf_generic_walker,
 | 
				
			||||||
 | 
					+};
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+MODULE_AUTHOR("Felix Fietkau <nbd@openwrt.org>");
 | 
				
			||||||
 | 
					+MODULE_DESCRIPTION("Connection tracking mark restoring");
 | 
				
			||||||
 | 
					+MODULE_LICENSE("GPL");
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+static int __init connmark_init_module(void)
 | 
				
			||||||
 | 
					+{
 | 
				
			||||||
 | 
					+	return tcf_register_action(&act_connmark_ops);
 | 
				
			||||||
 | 
					+}
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+static void __exit connmark_cleanup_module(void)
 | 
				
			||||||
 | 
					+{
 | 
				
			||||||
 | 
					+	tcf_unregister_action(&act_connmark_ops);
 | 
				
			||||||
 | 
					+}
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+module_init(connmark_init_module);
 | 
				
			||||||
 | 
					+module_exit(connmark_cleanup_module);
 | 
				
			||||||
 | 
					--- a/net/sched/Kconfig
 | 
				
			||||||
 | 
					+++ b/net/sched/Kconfig
 | 
				
			||||||
 | 
					@@ -602,6 +602,19 @@ config NET_ACT_CSUM
 | 
				
			||||||
 | 
					 	  To compile this code as a module, choose M here: the
 | 
				
			||||||
 | 
					 	  module will be called act_csum.
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					+config NET_ACT_CONNMARK
 | 
				
			||||||
 | 
					+        tristate "Connection Tracking Marking"
 | 
				
			||||||
 | 
					+        depends on NET_CLS_ACT
 | 
				
			||||||
 | 
					+        depends on NF_CONNTRACK
 | 
				
			||||||
 | 
					+	 depends on NF_CONNTRACK_MARK
 | 
				
			||||||
 | 
					+        ---help---
 | 
				
			||||||
 | 
					+	  Say Y here to restore the connmark from a scheduler action
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	  If unsure, say N.
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	  To compile this code as a module, choose M here: the
 | 
				
			||||||
 | 
					+	  module will be called act_connmark.
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					 config NET_CLS_IND
 | 
				
			||||||
 | 
					 	bool "Incoming device classification"
 | 
				
			||||||
 | 
					 	depends on NET_CLS_U32 || NET_CLS_FW
 | 
				
			||||||
 | 
					--- a/net/sched/Makefile
 | 
				
			||||||
 | 
					+++ b/net/sched/Makefile
 | 
				
			||||||
 | 
					@@ -16,6 +16,7 @@ obj-$(CONFIG_NET_ACT_PEDIT)	+= act_pedit
 | 
				
			||||||
 | 
					 obj-$(CONFIG_NET_ACT_SIMP)	+= act_simple.o
 | 
				
			||||||
 | 
					 obj-$(CONFIG_NET_ACT_SKBEDIT)	+= act_skbedit.o
 | 
				
			||||||
 | 
					 obj-$(CONFIG_NET_ACT_CSUM)	+= act_csum.o
 | 
				
			||||||
 | 
					+obj-$(CONFIG_NET_ACT_CONNMARK)	+= act_connmark.o
 | 
				
			||||||
 | 
					 obj-$(CONFIG_NET_SCH_FIFO)	+= sch_fifo.o
 | 
				
			||||||
 | 
					 obj-$(CONFIG_NET_SCH_CBQ)	+= sch_cbq.o
 | 
				
			||||||
 | 
					 obj-$(CONFIG_NET_SCH_HTB)	+= sch_htb.o
 | 
				
			||||||
							
								
								
									
										132
									
								
								target/linux/generic/patches-3.1/630-packet_socket_type.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										132
									
								
								target/linux/generic/patches-3.1/630-packet_socket_type.patch
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,132 @@
 | 
				
			|||||||
 | 
					This patch allows the user to specify desired packet types (outgoing,
 | 
				
			||||||
 | 
					broadcast, unicast, etc.) on packet sockets via setsockopt.
 | 
				
			||||||
 | 
					This can reduce the load in situations where only a limited number
 | 
				
			||||||
 | 
					of packet types are necessary
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Signed-off-by: Felix Fietkau <nbd@openwrt.org>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					--- a/include/linux/if_packet.h
 | 
				
			||||||
 | 
					+++ b/include/linux/if_packet.h
 | 
				
			||||||
 | 
					@@ -29,6 +29,8 @@ struct sockaddr_ll {
 | 
				
			||||||
 | 
					 /* These ones are invisible by user level */
 | 
				
			||||||
 | 
					 #define PACKET_LOOPBACK		5		/* MC/BRD frame looped back */
 | 
				
			||||||
 | 
					 #define PACKET_FASTROUTE	6		/* Fastrouted frame	*/
 | 
				
			||||||
 | 
					+#define PACKET_MASK_ANY		0xffffffff	/* mask for packet type bits */
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 /* Packet socket options */
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					@@ -50,6 +52,7 @@ struct sockaddr_ll {
 | 
				
			||||||
 | 
					 #define PACKET_TX_TIMESTAMP		16
 | 
				
			||||||
 | 
					 #define PACKET_TIMESTAMP		17
 | 
				
			||||||
 | 
					 #define PACKET_FANOUT			18
 | 
				
			||||||
 | 
					+#define PACKET_RECV_TYPE		19
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 #define PACKET_FANOUT_HASH		0
 | 
				
			||||||
 | 
					 #define PACKET_FANOUT_LB		1
 | 
				
			||||||
 | 
					--- a/net/packet/af_packet.c
 | 
				
			||||||
 | 
					+++ b/net/packet/af_packet.c
 | 
				
			||||||
 | 
					@@ -212,6 +212,7 @@ struct packet_sock {
 | 
				
			||||||
 | 
					 	unsigned int		tp_loss:1;
 | 
				
			||||||
 | 
					 	unsigned int		tp_tstamp;
 | 
				
			||||||
 | 
					 	struct packet_type	prot_hook ____cacheline_aligned_in_smp;
 | 
				
			||||||
 | 
					+	unsigned int		pkt_type;
 | 
				
			||||||
 | 
					 };
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 #define PACKET_FANOUT_MAX	256
 | 
				
			||||||
 | 
					@@ -661,6 +662,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
 | 
				
			||||||
 | 
					@@ -668,6 +670,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
 | 
				
			||||||
 | 
					@@ -680,7 +683,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)))
 | 
				
			||||||
 | 
					@@ -873,12 +876,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;
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					@@ -994,12 +997,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;
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					@@ -1826,6 +1829,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;
 | 
				
			||||||
 | 
					@@ -2410,6 +2414,16 @@ packet_setsockopt(struct socket *sock, i
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 		return fanout_add(sk, val & 0xffff, val >> 16);
 | 
				
			||||||
 | 
					 	}
 | 
				
			||||||
 | 
					+        case PACKET_RECV_TYPE:
 | 
				
			||||||
 | 
					+        {
 | 
				
			||||||
 | 
					+                unsigned int val;
 | 
				
			||||||
 | 
					+                if (optlen != sizeof(val))
 | 
				
			||||||
 | 
					+                        return -EINVAL;
 | 
				
			||||||
 | 
					+                if (copy_from_user(&val, optval, sizeof(val)))
 | 
				
			||||||
 | 
					+                        return -EFAULT;
 | 
				
			||||||
 | 
					+                po->pkt_type = val & ~PACKET_LOOPBACK;
 | 
				
			||||||
 | 
					+                return 0;
 | 
				
			||||||
 | 
					+        }
 | 
				
			||||||
 | 
					 	default:
 | 
				
			||||||
 | 
					 		return -ENOPROTOOPT;
 | 
				
			||||||
 | 
					 	}
 | 
				
			||||||
 | 
					@@ -2467,6 +2481,13 @@ static int packet_getsockopt(struct sock
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 		data = &val;
 | 
				
			||||||
 | 
					 		break;
 | 
				
			||||||
 | 
					+	case PACKET_RECV_TYPE:
 | 
				
			||||||
 | 
					+		if (len > sizeof(unsigned int))
 | 
				
			||||||
 | 
					+			len = sizeof(unsigned int);
 | 
				
			||||||
 | 
					+		val = po->pkt_type;
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+		data = &val;
 | 
				
			||||||
 | 
					+		break;
 | 
				
			||||||
 | 
					 	case PACKET_VERSION:
 | 
				
			||||||
 | 
					 		if (len > sizeof(int))
 | 
				
			||||||
 | 
					 			len = sizeof(int);
 | 
				
			||||||
@@ -0,0 +1,15 @@
 | 
				
			|||||||
 | 
					--- a/net/bridge/br_input.c
 | 
				
			||||||
 | 
					+++ b/net/bridge/br_input.c
 | 
				
			||||||
 | 
					@@ -77,7 +77,11 @@ int br_handle_frame_finish(struct sk_buf
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 	dst = NULL;
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					-	if (is_broadcast_ether_addr(dest))
 | 
				
			||||||
 | 
					+	if (skb->protocol == htons(ETH_P_PAE)) {
 | 
				
			||||||
 | 
					+		skb2 = skb;
 | 
				
			||||||
 | 
					+		/* Do not forward 802.1x/EAP frames */
 | 
				
			||||||
 | 
					+		skb = NULL;
 | 
				
			||||||
 | 
					+	} else if (is_broadcast_ether_addr(dest))
 | 
				
			||||||
 | 
					 		skb2 = skb;
 | 
				
			||||||
 | 
					 	else if (is_multicast_ether_addr(dest)) {
 | 
				
			||||||
 | 
					 		mdst = br_mdb_get(br, skb);
 | 
				
			||||||
@@ -0,0 +1,11 @@
 | 
				
			|||||||
 | 
					--- a/net/bridge/br_input.c
 | 
				
			||||||
 | 
					+++ b/net/bridge/br_input.c
 | 
				
			||||||
 | 
					@@ -64,7 +64,7 @@ int br_handle_frame_finish(struct sk_buf
 | 
				
			||||||
 | 
					 	    br_multicast_rcv(br, p, skb))
 | 
				
			||||||
 | 
					 		goto drop;
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					-	if (p->state == BR_STATE_LEARNING)
 | 
				
			||||||
 | 
					+	if ((p->state == BR_STATE_LEARNING) && skb->protocol != htons(ETH_P_PAE))
 | 
				
			||||||
 | 
					 		goto drop;
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 	BR_INPUT_SKB_CB(skb)->brdev = br->dev;
 | 
				
			||||||
							
								
								
									
										103
									
								
								target/linux/generic/patches-3.1/642-bridge_port_isolate.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										103
									
								
								target/linux/generic/patches-3.1/642-bridge_port_isolate.patch
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,103 @@
 | 
				
			|||||||
 | 
					--- a/net/bridge/br_private.h
 | 
				
			||||||
 | 
					+++ b/net/bridge/br_private.h
 | 
				
			||||||
 | 
					@@ -134,6 +134,7 @@ struct net_bridge_port
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 	unsigned long 			flags;
 | 
				
			||||||
 | 
					 #define BR_HAIRPIN_MODE		0x00000001
 | 
				
			||||||
 | 
					+#define BR_ISOLATE_MODE		0x00000002
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 #ifdef CONFIG_BRIDGE_IGMP_SNOOPING
 | 
				
			||||||
 | 
					 	u32				multicast_startup_queries_sent;
 | 
				
			||||||
 | 
					--- a/net/bridge/br_sysfs_if.c
 | 
				
			||||||
 | 
					+++ b/net/bridge/br_sysfs_if.c
 | 
				
			||||||
 | 
					@@ -149,6 +149,22 @@ static int store_hairpin_mode(struct net
 | 
				
			||||||
 | 
					 static BRPORT_ATTR(hairpin_mode, S_IRUGO | S_IWUSR,
 | 
				
			||||||
 | 
					 		   show_hairpin_mode, store_hairpin_mode);
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					+static ssize_t show_isolate_mode(struct net_bridge_port *p, char *buf)
 | 
				
			||||||
 | 
					+{
 | 
				
			||||||
 | 
					+	int isolate_mode = (p->flags & BR_ISOLATE_MODE) ? 1 : 0;
 | 
				
			||||||
 | 
					+	return sprintf(buf, "%d\n", isolate_mode);
 | 
				
			||||||
 | 
					+}
 | 
				
			||||||
 | 
					+static ssize_t store_isolate_mode(struct net_bridge_port *p, unsigned long v)
 | 
				
			||||||
 | 
					+{
 | 
				
			||||||
 | 
					+	if (v)
 | 
				
			||||||
 | 
					+		p->flags |= BR_ISOLATE_MODE;
 | 
				
			||||||
 | 
					+	else
 | 
				
			||||||
 | 
					+		p->flags &= ~BR_ISOLATE_MODE;
 | 
				
			||||||
 | 
					+	return 0;
 | 
				
			||||||
 | 
					+}
 | 
				
			||||||
 | 
					+static BRPORT_ATTR(isolate_mode, S_IRUGO | S_IWUSR,
 | 
				
			||||||
 | 
					+		   show_isolate_mode, store_isolate_mode);
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					 #ifdef CONFIG_BRIDGE_IGMP_SNOOPING
 | 
				
			||||||
 | 
					 static ssize_t show_multicast_router(struct net_bridge_port *p, char *buf)
 | 
				
			||||||
 | 
					 {
 | 
				
			||||||
 | 
					@@ -181,6 +197,7 @@ static struct brport_attribute *brport_a
 | 
				
			||||||
 | 
					 	&brport_attr_hold_timer,
 | 
				
			||||||
 | 
					 	&brport_attr_flush,
 | 
				
			||||||
 | 
					 	&brport_attr_hairpin_mode,
 | 
				
			||||||
 | 
					+	&brport_attr_isolate_mode,
 | 
				
			||||||
 | 
					 #ifdef CONFIG_BRIDGE_IGMP_SNOOPING
 | 
				
			||||||
 | 
					 	&brport_attr_multicast_router,
 | 
				
			||||||
 | 
					 #endif
 | 
				
			||||||
 | 
					--- a/net/bridge/br_input.c
 | 
				
			||||||
 | 
					+++ b/net/bridge/br_input.c
 | 
				
			||||||
 | 
					@@ -97,7 +97,8 @@ int br_handle_frame_finish(struct sk_buf
 | 
				
			||||||
 | 
					 			skb2 = skb;
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 		br->dev->stats.multicast++;
 | 
				
			||||||
 | 
					-	} else if ((dst = __br_fdb_get(br, dest)) && dst->is_local) {
 | 
				
			||||||
 | 
					+	} else if ((p->flags & BR_ISOLATE_MODE) ||
 | 
				
			||||||
 | 
					+		   ((dst = __br_fdb_get(br, dest)) && dst->is_local)) {
 | 
				
			||||||
 | 
					 		skb2 = skb;
 | 
				
			||||||
 | 
					 		/* Do not forward the packet since it's local. */
 | 
				
			||||||
 | 
					 		skb = NULL;
 | 
				
			||||||
 | 
					--- a/net/bridge/br_forward.c
 | 
				
			||||||
 | 
					+++ b/net/bridge/br_forward.c
 | 
				
			||||||
 | 
					@@ -109,7 +109,7 @@ void br_deliver(const struct net_bridge_
 | 
				
			||||||
 | 
					 /* called with rcu_read_lock */
 | 
				
			||||||
 | 
					 void br_forward(const struct net_bridge_port *to, struct sk_buff *skb, struct sk_buff *skb0)
 | 
				
			||||||
 | 
					 {
 | 
				
			||||||
 | 
					-	if (should_deliver(to, skb)) {
 | 
				
			||||||
 | 
					+	if (should_deliver(to, skb) && !(to->flags & BR_ISOLATE_MODE)) {
 | 
				
			||||||
 | 
					 		if (skb0)
 | 
				
			||||||
 | 
					 			deliver_clone(to, skb, __br_forward);
 | 
				
			||||||
 | 
					 		else
 | 
				
			||||||
 | 
					@@ -164,7 +164,8 @@ out:
 | 
				
			||||||
 | 
					 static void br_flood(struct net_bridge *br, struct sk_buff *skb,
 | 
				
			||||||
 | 
					 		     struct sk_buff *skb0,
 | 
				
			||||||
 | 
					 		     void (*__packet_hook)(const struct net_bridge_port *p,
 | 
				
			||||||
 | 
					-					   struct sk_buff *skb))
 | 
				
			||||||
 | 
					+					   struct sk_buff *skb),
 | 
				
			||||||
 | 
					+		     bool forward)
 | 
				
			||||||
 | 
					 {
 | 
				
			||||||
 | 
					 	struct net_bridge_port *p;
 | 
				
			||||||
 | 
					 	struct net_bridge_port *prev;
 | 
				
			||||||
 | 
					@@ -172,6 +173,9 @@ static void br_flood(struct net_bridge *
 | 
				
			||||||
 | 
					 	prev = NULL;
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 	list_for_each_entry_rcu(p, &br->port_list, list) {
 | 
				
			||||||
 | 
					+		if (forward && (p->flags & BR_ISOLATE_MODE))
 | 
				
			||||||
 | 
					+			continue;
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					 		prev = maybe_deliver(prev, p, skb, __packet_hook);
 | 
				
			||||||
 | 
					 		if (IS_ERR(prev))
 | 
				
			||||||
 | 
					 			goto out;
 | 
				
			||||||
 | 
					@@ -195,14 +199,14 @@ out:
 | 
				
			||||||
 | 
					 /* called with rcu_read_lock */
 | 
				
			||||||
 | 
					 void br_flood_deliver(struct net_bridge *br, struct sk_buff *skb)
 | 
				
			||||||
 | 
					 {
 | 
				
			||||||
 | 
					-	br_flood(br, skb, NULL, __br_deliver);
 | 
				
			||||||
 | 
					+	br_flood(br, skb, NULL, __br_deliver, false);
 | 
				
			||||||
 | 
					 }
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 /* called under bridge lock */
 | 
				
			||||||
 | 
					 void br_flood_forward(struct net_bridge *br, struct sk_buff *skb,
 | 
				
			||||||
 | 
					 		      struct sk_buff *skb2)
 | 
				
			||||||
 | 
					 {
 | 
				
			||||||
 | 
					-	br_flood(br, skb, skb2, __br_forward);
 | 
				
			||||||
 | 
					+	br_flood(br, skb, skb2, __br_forward, true);
 | 
				
			||||||
 | 
					 }
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 #ifdef CONFIG_BRIDGE_IGMP_SNOOPING
 | 
				
			||||||
@@ -0,0 +1,101 @@
 | 
				
			|||||||
 | 
					--- a/include/net/addrconf.h
 | 
				
			||||||
 | 
					+++ b/include/net/addrconf.h
 | 
				
			||||||
 | 
					@@ -91,6 +91,12 @@ extern void			addrconf_join_solict(struc
 | 
				
			||||||
 | 
					 extern void			addrconf_leave_solict(struct inet6_dev *idev,
 | 
				
			||||||
 | 
					 					const struct in6_addr *addr);
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					+extern int			(*ipv6_dev_get_saddr_hook)(struct net *net,
 | 
				
			||||||
 | 
					+						struct net_device *dev,
 | 
				
			||||||
 | 
					+						const struct in6_addr *daddr,
 | 
				
			||||||
 | 
					+						unsigned int srcprefs,
 | 
				
			||||||
 | 
					+						struct in6_addr *saddr);
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					 static inline unsigned long addrconf_timeout_fixup(u32 timeout,
 | 
				
			||||||
 | 
					 						    unsigned unit)
 | 
				
			||||||
 | 
					 {
 | 
				
			||||||
 | 
					--- a/net/bridge/Kconfig
 | 
				
			||||||
 | 
					+++ b/net/bridge/Kconfig
 | 
				
			||||||
 | 
					@@ -6,7 +6,6 @@ config BRIDGE
 | 
				
			||||||
 | 
					 	tristate "802.1d Ethernet Bridging"
 | 
				
			||||||
 | 
					 	select LLC
 | 
				
			||||||
 | 
					 	select STP
 | 
				
			||||||
 | 
					-	depends on IPV6 || IPV6=n
 | 
				
			||||||
 | 
					 	---help---
 | 
				
			||||||
 | 
					 	  If you say Y here, then your Linux box will be able to act as an
 | 
				
			||||||
 | 
					 	  Ethernet bridge, which means that the different Ethernet segments it
 | 
				
			||||||
 | 
					--- a/net/ipv6/Makefile
 | 
				
			||||||
 | 
					+++ b/net/ipv6/Makefile
 | 
				
			||||||
 | 
					@@ -40,3 +40,4 @@ obj-$(CONFIG_IPV6_TUNNEL) += ip6_tunnel.
 | 
				
			||||||
 | 
					 obj-y += addrconf_core.o exthdrs_core.o
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 obj-$(subst m,y,$(CONFIG_IPV6)) += inet6_hashtables.o
 | 
				
			||||||
 | 
					+obj-$(subst m,y,$(CONFIG_IPV6)) += inet6_stubs.o
 | 
				
			||||||
 | 
					--- a/net/ipv6/addrconf.c
 | 
				
			||||||
 | 
					+++ b/net/ipv6/addrconf.c
 | 
				
			||||||
 | 
					@@ -1106,7 +1106,7 @@ out:
 | 
				
			||||||
 | 
					 	return ret;
 | 
				
			||||||
 | 
					 }
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					-int ipv6_dev_get_saddr(struct net *net, struct net_device *dst_dev,
 | 
				
			||||||
 | 
					+static int __ipv6_dev_get_saddr(struct net *net, struct net_device *dst_dev,
 | 
				
			||||||
 | 
					 		       const struct in6_addr *daddr, unsigned int prefs,
 | 
				
			||||||
 | 
					 		       struct in6_addr *saddr)
 | 
				
			||||||
 | 
					 {
 | 
				
			||||||
 | 
					@@ -1231,7 +1231,6 @@ try_nextdev:
 | 
				
			||||||
 | 
					 	in6_ifa_put(hiscore->ifa);
 | 
				
			||||||
 | 
					 	return 0;
 | 
				
			||||||
 | 
					 }
 | 
				
			||||||
 | 
					-EXPORT_SYMBOL(ipv6_dev_get_saddr);
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 int ipv6_get_lladdr(struct net_device *dev, struct in6_addr *addr,
 | 
				
			||||||
 | 
					 		    unsigned char banned_flags)
 | 
				
			||||||
 | 
					@@ -4748,6 +4747,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);
 | 
				
			||||||
 | 
					@@ -4766,6 +4768,9 @@ void addrconf_cleanup(void)
 | 
				
			||||||
 | 
					 	struct net_device *dev;
 | 
				
			||||||
 | 
					 	int i;
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					+	rcu_assign_pointer(ipv6_dev_get_saddr_hook, NULL);
 | 
				
			||||||
 | 
					+	synchronize_rcu();
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					 	unregister_netdevice_notifier(&ipv6_dev_notf);
 | 
				
			||||||
 | 
					 	unregister_pernet_subsys(&addrconf_ops);
 | 
				
			||||||
 | 
					 	ipv6_addr_label_cleanup();
 | 
				
			||||||
 | 
					--- /dev/null
 | 
				
			||||||
 | 
					+++ b/net/ipv6/inet6_stubs.c
 | 
				
			||||||
 | 
					@@ -0,0 +1,27 @@
 | 
				
			||||||
 | 
					+/*
 | 
				
			||||||
 | 
					+ *      This program is free software; you can redistribute it and/or
 | 
				
			||||||
 | 
					+ *      modify it under the terms of the GNU General Public License
 | 
				
			||||||
 | 
					+ *      as published by the Free Software Foundation; either version
 | 
				
			||||||
 | 
					+ *      2 of the License, or (at your option) any later version.
 | 
				
			||||||
 | 
					+ */
 | 
				
			||||||
 | 
					+#include <net/ipv6.h>
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+int (*ipv6_dev_get_saddr_hook)(struct net *net, struct net_device *dev,
 | 
				
			||||||
 | 
					+			const struct in6_addr *daddr, unsigned int srcprefs,
 | 
				
			||||||
 | 
					+			struct in6_addr *saddr);
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+EXPORT_SYMBOL(ipv6_dev_get_saddr_hook);
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+int ipv6_dev_get_saddr(struct net *net, struct net_device *dst_dev,
 | 
				
			||||||
 | 
					+			const struct in6_addr *daddr, unsigned int prefs,
 | 
				
			||||||
 | 
					+			struct in6_addr *saddr)
 | 
				
			||||||
 | 
					+{
 | 
				
			||||||
 | 
					+	typeof(ipv6_dev_get_saddr_hook) dev_get_saddr = rcu_dereference(ipv6_dev_get_saddr_hook);
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	if (dev_get_saddr)
 | 
				
			||||||
 | 
					+		return dev_get_saddr(net, dst_dev, daddr, prefs, saddr);
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	return -EADDRNOTAVAIL;
 | 
				
			||||||
 | 
					+}
 | 
				
			||||||
 | 
					+EXPORT_SYMBOL(ipv6_dev_get_saddr);
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
							
								
								
									
										20
									
								
								target/linux/generic/patches-3.1/650-pppoe_header_pad.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								target/linux/generic/patches-3.1/650-pppoe_header_pad.patch
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,20 @@
 | 
				
			|||||||
 | 
					--- a/drivers/net/pppoe.c
 | 
				
			||||||
 | 
					+++ b/drivers/net/pppoe.c
 | 
				
			||||||
 | 
					@@ -856,7 +856,7 @@ static int pppoe_sendmsg(struct kiocb *i
 | 
				
			||||||
 | 
					 		goto end;
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					-	skb = sock_wmalloc(sk, total_len + dev->hard_header_len + 32,
 | 
				
			||||||
 | 
					+	skb = sock_wmalloc(sk, total_len + dev->hard_header_len + 32 + NET_SKB_PAD,
 | 
				
			||||||
 | 
					 			   0, GFP_KERNEL);
 | 
				
			||||||
 | 
					 	if (!skb) {
 | 
				
			||||||
 | 
					 		error = -ENOMEM;
 | 
				
			||||||
 | 
					@@ -864,7 +864,7 @@ static int pppoe_sendmsg(struct kiocb *i
 | 
				
			||||||
 | 
					 	}
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 	/* Reserve space for headers. */
 | 
				
			||||||
 | 
					-	skb_reserve(skb, dev->hard_header_len);
 | 
				
			||||||
 | 
					+	skb_reserve(skb, dev->hard_header_len + NET_SKB_PAD);
 | 
				
			||||||
 | 
					 	skb_reset_network_header(skb);
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 	skb->dev = dev;
 | 
				
			||||||
@@ -0,0 +1,11 @@
 | 
				
			|||||||
 | 
					--- a/include/linux/netdevice.h
 | 
				
			||||||
 | 
					+++ b/include/linux/netdevice.h
 | 
				
			||||||
 | 
					@@ -142,7 +142,7 @@ static inline bool dev_xmit_complete(int
 | 
				
			||||||
 | 
					  */
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 #if defined(CONFIG_WLAN) || defined(CONFIG_AX25) || defined(CONFIG_AX25_MODULE)
 | 
				
			||||||
 | 
					-# if defined(CONFIG_MAC80211_MESH)
 | 
				
			||||||
 | 
					+# if 1 || defined(CONFIG_MAC80211_MESH)
 | 
				
			||||||
 | 
					 #  define LL_MAX_HEADER 128
 | 
				
			||||||
 | 
					 # else
 | 
				
			||||||
 | 
					 #  define LL_MAX_HEADER 96
 | 
				
			||||||
@@ -0,0 +1,12 @@
 | 
				
			|||||||
 | 
					--- a/include/linux/atm.h
 | 
				
			||||||
 | 
					+++ b/include/linux/atm.h
 | 
				
			||||||
 | 
					@@ -139,6 +139,9 @@ struct atm_trafprm {
 | 
				
			||||||
 | 
					 	int		min_pcr;	/* minimum PCR in cells per second */
 | 
				
			||||||
 | 
					 	int		max_cdv;	/* maximum CDV in microseconds */
 | 
				
			||||||
 | 
					 	int		max_sdu;	/* maximum SDU in bytes */
 | 
				
			||||||
 | 
					+	int		scr;		/* sustained rate in cells per second */
 | 
				
			||||||
 | 
					+	int		mbs;		/* maximum burst size (MBS) in cells */
 | 
				
			||||||
 | 
					+	int		cdv;		/* Cell delay varition */
 | 
				
			||||||
 | 
					         /* extra params for ABR */
 | 
				
			||||||
 | 
					         unsigned int 	icr;         	/* Initial Cell Rate (24-bit) */
 | 
				
			||||||
 | 
					         unsigned int	tbe;		/* Transient Buffer Exposure (24-bit) */ 
 | 
				
			||||||
							
								
								
									
										25
									
								
								target/linux/generic/patches-3.1/700-swconfig.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								target/linux/generic/patches-3.1/700-swconfig.patch
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,25 @@
 | 
				
			|||||||
 | 
					--- a/drivers/net/phy/Kconfig
 | 
				
			||||||
 | 
					+++ b/drivers/net/phy/Kconfig
 | 
				
			||||||
 | 
					@@ -13,6 +13,12 @@ menuconfig PHYLIB
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 if PHYLIB
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					+config SWCONFIG
 | 
				
			||||||
 | 
					+	tristate "Switch configuration API"
 | 
				
			||||||
 | 
					+	---help---
 | 
				
			||||||
 | 
					+	  Switch configuration API using netlink. This allows
 | 
				
			||||||
 | 
					+	  you to configure the VLAN features of certain switches.
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					 comment "MII PHY device drivers"
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 config MARVELL_PHY
 | 
				
			||||||
 | 
					--- a/drivers/net/phy/Makefile
 | 
				
			||||||
 | 
					+++ b/drivers/net/phy/Makefile
 | 
				
			||||||
 | 
					@@ -3,6 +3,7 @@
 | 
				
			||||||
 | 
					 libphy-objs			:= phy.o phy_device.o mdio_bus.o
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 obj-$(CONFIG_PHYLIB)		+= libphy.o
 | 
				
			||||||
 | 
					+obj-$(CONFIG_SWCONFIG)		+= swconfig.o
 | 
				
			||||||
 | 
					 obj-$(CONFIG_MARVELL_PHY)	+= marvell.o
 | 
				
			||||||
 | 
					 obj-$(CONFIG_DAVICOM_PHY)	+= davicom.o
 | 
				
			||||||
 | 
					 obj-$(CONFIG_CICADA_PHY)	+= cicada.o
 | 
				
			||||||
							
								
								
									
										72
									
								
								target/linux/generic/patches-3.1/701-phy_extension.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										72
									
								
								target/linux/generic/patches-3.1/701-phy_extension.patch
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,72 @@
 | 
				
			|||||||
 | 
					--- a/drivers/net/phy/phy.c
 | 
				
			||||||
 | 
					+++ b/drivers/net/phy/phy.c
 | 
				
			||||||
 | 
					@@ -299,6 +299,50 @@ int phy_ethtool_gset(struct phy_device *
 | 
				
			||||||
 | 
					 }
 | 
				
			||||||
 | 
					 EXPORT_SYMBOL(phy_ethtool_gset);
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					+int phy_ethtool_ioctl(struct phy_device *phydev, void *useraddr)
 | 
				
			||||||
 | 
					+{
 | 
				
			||||||
 | 
					+	u32 cmd;
 | 
				
			||||||
 | 
					+	int tmp;
 | 
				
			||||||
 | 
					+	struct ethtool_cmd ecmd = { ETHTOOL_GSET };
 | 
				
			||||||
 | 
					+	struct ethtool_value edata = { ETHTOOL_GLINK };
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	if (get_user(cmd, (u32 *) useraddr))
 | 
				
			||||||
 | 
					+		return -EFAULT;
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	switch (cmd) {
 | 
				
			||||||
 | 
					+	case ETHTOOL_GSET:
 | 
				
			||||||
 | 
					+		phy_ethtool_gset(phydev, &ecmd);
 | 
				
			||||||
 | 
					+		if (copy_to_user(useraddr, &ecmd, sizeof(ecmd)))
 | 
				
			||||||
 | 
					+			return -EFAULT;
 | 
				
			||||||
 | 
					+		return 0;
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	case ETHTOOL_SSET:
 | 
				
			||||||
 | 
					+		if (copy_from_user(&ecmd, useraddr, sizeof(ecmd)))
 | 
				
			||||||
 | 
					+			return -EFAULT;
 | 
				
			||||||
 | 
					+		return phy_ethtool_sset(phydev, &ecmd);
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	case ETHTOOL_NWAY_RST:
 | 
				
			||||||
 | 
					+		/* if autoneg is off, it's an error */
 | 
				
			||||||
 | 
					+		tmp = phy_read(phydev, MII_BMCR);
 | 
				
			||||||
 | 
					+		if (tmp & BMCR_ANENABLE) {
 | 
				
			||||||
 | 
					+			tmp |= (BMCR_ANRESTART);
 | 
				
			||||||
 | 
					+			phy_write(phydev, MII_BMCR, tmp);
 | 
				
			||||||
 | 
					+			return 0;
 | 
				
			||||||
 | 
					+		}
 | 
				
			||||||
 | 
					+		return -EINVAL;
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	case ETHTOOL_GLINK:
 | 
				
			||||||
 | 
					+		edata.data = (phy_read(phydev,
 | 
				
			||||||
 | 
					+				MII_BMSR) & BMSR_LSTATUS) ? 1 : 0;
 | 
				
			||||||
 | 
					+		if (copy_to_user(useraddr, &edata, sizeof(edata)))
 | 
				
			||||||
 | 
					+			return -EFAULT;
 | 
				
			||||||
 | 
					+		return 0;
 | 
				
			||||||
 | 
					+	}
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	return -EOPNOTSUPP;
 | 
				
			||||||
 | 
					+}
 | 
				
			||||||
 | 
					+EXPORT_SYMBOL(phy_ethtool_ioctl);
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					 /**
 | 
				
			||||||
 | 
					  * phy_mii_ioctl - generic PHY MII ioctl interface
 | 
				
			||||||
 | 
					  * @phydev: the phy_device struct
 | 
				
			||||||
 | 
					@@ -474,7 +518,7 @@ static void phy_force_reduction(struct p
 | 
				
			||||||
 | 
					 	int idx;
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 	idx = phy_find_setting(phydev->speed, phydev->duplex);
 | 
				
			||||||
 | 
					-	
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					 	idx++;
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 	idx = phy_find_valid(idx, phydev->supported);
 | 
				
			||||||
 | 
					--- a/include/linux/phy.h
 | 
				
			||||||
 | 
					+++ b/include/linux/phy.h
 | 
				
			||||||
 | 
					@@ -510,6 +510,7 @@ void phy_start_machine(struct phy_device
 | 
				
			||||||
 | 
					 void phy_stop_machine(struct phy_device *phydev);
 | 
				
			||||||
 | 
					 int phy_ethtool_sset(struct phy_device *phydev, struct ethtool_cmd *cmd);
 | 
				
			||||||
 | 
					 int phy_ethtool_gset(struct phy_device *phydev, struct ethtool_cmd *cmd);
 | 
				
			||||||
 | 
					+int phy_ethtool_ioctl(struct phy_device *phydev, void *useraddr);
 | 
				
			||||||
 | 
					 int phy_mii_ioctl(struct phy_device *phydev,
 | 
				
			||||||
 | 
					 		struct ifreq *ifr, int cmd);
 | 
				
			||||||
 | 
					 int phy_start_interrupts(struct phy_device *phydev);
 | 
				
			||||||
@@ -0,0 +1,45 @@
 | 
				
			|||||||
 | 
					--- a/include/linux/phy.h
 | 
				
			||||||
 | 
					+++ b/include/linux/phy.h
 | 
				
			||||||
 | 
					@@ -388,9 +388,18 @@ struct phy_driver {
 | 
				
			||||||
 | 
					 	 */
 | 
				
			||||||
 | 
					 	int (*config_aneg)(struct phy_device *phydev);
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					+	/* Determine if autonegotiation is done */
 | 
				
			||||||
 | 
					+	int (*aneg_done)(struct phy_device *phydev);
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					 	/* Determines the negotiated speed and duplex */
 | 
				
			||||||
 | 
					 	int (*read_status)(struct phy_device *phydev);
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					+	/* 
 | 
				
			||||||
 | 
					+	 * Update the value in phydev->link to reflect the 
 | 
				
			||||||
 | 
					+	 * current link value
 | 
				
			||||||
 | 
					+	 */
 | 
				
			||||||
 | 
					+	int (*update_link)(struct phy_device *phydev);
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					 	/* Clears any pending interrupts */
 | 
				
			||||||
 | 
					 	int (*ack_interrupt)(struct phy_device *phydev);
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					--- a/drivers/net/phy/phy_device.c
 | 
				
			||||||
 | 
					+++ b/drivers/net/phy/phy_device.c
 | 
				
			||||||
 | 
					@@ -719,6 +719,9 @@ int genphy_update_link(struct phy_device
 | 
				
			||||||
 | 
					 {
 | 
				
			||||||
 | 
					 	int status;
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					+	if (phydev->drv->update_link)
 | 
				
			||||||
 | 
					+		return phydev->drv->update_link(phydev);
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					 	/* Do a fake read */
 | 
				
			||||||
 | 
					 	status = phy_read(phydev, MII_BMSR);
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					--- a/drivers/net/phy/phy.c
 | 
				
			||||||
 | 
					+++ b/drivers/net/phy/phy.c
 | 
				
			||||||
 | 
					@@ -106,6 +106,9 @@ static inline int phy_aneg_done(struct p
 | 
				
			||||||
 | 
					 {
 | 
				
			||||||
 | 
					 	int retval;
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					+	if (phydev->drv->aneg_done)
 | 
				
			||||||
 | 
					+		return phydev->drv->aneg_done(phydev);
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					 	retval = phy_read(phydev, MII_BMSR);
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 	return (retval < 0) ? retval : (retval & BMSR_ANEGCOMPLETE);
 | 
				
			||||||
							
								
								
									
										26
									
								
								target/linux/generic/patches-3.1/720-phy_adm6996.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								target/linux/generic/patches-3.1/720-phy_adm6996.patch
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,26 @@
 | 
				
			|||||||
 | 
					--- a/drivers/net/phy/Kconfig
 | 
				
			||||||
 | 
					+++ b/drivers/net/phy/Kconfig
 | 
				
			||||||
 | 
					@@ -98,6 +98,13 @@ config MICREL_PHY
 | 
				
			||||||
 | 
					 	---help---
 | 
				
			||||||
 | 
					 	  Supports the KSZ9021, VSC8201, KS8001 PHYs.
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					+config ADM6996_PHY
 | 
				
			||||||
 | 
					+	tristate "Driver for ADM6996 switches"
 | 
				
			||||||
 | 
					+	select SWCONFIG
 | 
				
			||||||
 | 
					+	---help---
 | 
				
			||||||
 | 
					+	  Currently supports the ADM6996FC and ADM6996M switches.
 | 
				
			||||||
 | 
					+	  Support for FC is very limited.
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					 config FIXED_PHY
 | 
				
			||||||
 | 
					 	bool "Driver for MDIO Bus/PHY emulation with fixed speed/link PHYs"
 | 
				
			||||||
 | 
					 	depends on PHYLIB=y
 | 
				
			||||||
 | 
					--- a/drivers/net/phy/Makefile
 | 
				
			||||||
 | 
					+++ b/drivers/net/phy/Makefile
 | 
				
			||||||
 | 
					@@ -14,6 +14,7 @@ obj-$(CONFIG_VITESSE_PHY)	+= vitesse.o
 | 
				
			||||||
 | 
					 obj-$(CONFIG_BROADCOM_PHY)	+= broadcom.o
 | 
				
			||||||
 | 
					 obj-$(CONFIG_BCM63XX_PHY)	+= bcm63xx.o
 | 
				
			||||||
 | 
					 obj-$(CONFIG_ICPLUS_PHY)	+= icplus.o
 | 
				
			||||||
 | 
					+obj-$(CONFIG_ADM6996_PHY)	+= adm6996.o
 | 
				
			||||||
 | 
					 obj-$(CONFIG_REALTEK_PHY)	+= realtek.o
 | 
				
			||||||
 | 
					 obj-$(CONFIG_LSI_ET1011C_PHY)	+= et1011c.o
 | 
				
			||||||
 | 
					 obj-$(CONFIG_FIXED_PHY)		+= fixed.o
 | 
				
			||||||
							
								
								
									
										63
									
								
								target/linux/generic/patches-3.1/721-phy_packets.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										63
									
								
								target/linux/generic/patches-3.1/721-phy_packets.patch
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,63 @@
 | 
				
			|||||||
 | 
					--- a/drivers/net/phy/phy_device.c
 | 
				
			||||||
 | 
					+++ b/drivers/net/phy/phy_device.c
 | 
				
			||||||
 | 
					@@ -149,6 +149,18 @@ int phy_scan_fixups(struct phy_device *p
 | 
				
			||||||
 | 
					 }
 | 
				
			||||||
 | 
					 EXPORT_SYMBOL(phy_scan_fixups);
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					+static int generic_receive_skb(struct sk_buff *skb)
 | 
				
			||||||
 | 
					+{
 | 
				
			||||||
 | 
					+	skb->protocol = eth_type_trans(skb, skb->dev);
 | 
				
			||||||
 | 
					+	return netif_receive_skb(skb);
 | 
				
			||||||
 | 
					+}
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+static int generic_rx(struct sk_buff *skb)
 | 
				
			||||||
 | 
					+{
 | 
				
			||||||
 | 
					+	skb->protocol = eth_type_trans(skb, skb->dev);
 | 
				
			||||||
 | 
					+	return netif_rx(skb);
 | 
				
			||||||
 | 
					+}
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					 static struct phy_device* phy_device_create(struct mii_bus *bus,
 | 
				
			||||||
 | 
					 					    int addr, int phy_id)
 | 
				
			||||||
 | 
					 {
 | 
				
			||||||
 | 
					@@ -180,6 +192,8 @@ static struct phy_device* phy_device_cre
 | 
				
			||||||
 | 
					 	dev_set_name(&dev->dev, PHY_ID_FMT, bus->id, addr);
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 	dev->state = PHY_DOWN;
 | 
				
			||||||
 | 
					+	dev->netif_receive_skb = &generic_receive_skb;
 | 
				
			||||||
 | 
					+	dev->netif_rx = &generic_rx;
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 	mutex_init(&dev->lock);
 | 
				
			||||||
 | 
					 	INIT_DELAYED_WORK(&dev->state_queue, phy_state_machine);
 | 
				
			||||||
 | 
					--- a/include/linux/phy.h
 | 
				
			||||||
 | 
					+++ b/include/linux/phy.h
 | 
				
			||||||
 | 
					@@ -334,6 +334,20 @@ struct phy_device {
 | 
				
			||||||
 | 
					 	void (*adjust_link)(struct net_device *dev);
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 	void (*adjust_state)(struct net_device *dev);
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	/*
 | 
				
			||||||
 | 
					+	 * By default these point to the original functions
 | 
				
			||||||
 | 
					+	 * with the same name. adding them to the phy_device
 | 
				
			||||||
 | 
					+	 * allows the phy driver to override them for packet
 | 
				
			||||||
 | 
					+	 * mangling if the ethernet driver supports it
 | 
				
			||||||
 | 
					+	 * This is required to support some really horrible
 | 
				
			||||||
 | 
					+	 * switches such as the Marvell 88E6060
 | 
				
			||||||
 | 
					+	 */
 | 
				
			||||||
 | 
					+	int (*netif_receive_skb)(struct sk_buff *skb);
 | 
				
			||||||
 | 
					+	int (*netif_rx)(struct sk_buff *skb);
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	/* alignment offset for packets */
 | 
				
			||||||
 | 
					+	int pkt_align;
 | 
				
			||||||
 | 
					 };
 | 
				
			||||||
 | 
					 #define to_phy_device(d) container_of(d, struct phy_device, dev)
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					--- a/include/linux/netdevice.h
 | 
				
			||||||
 | 
					+++ b/include/linux/netdevice.h
 | 
				
			||||||
 | 
					@@ -1153,6 +1153,7 @@ struct net_device {
 | 
				
			||||||
 | 
					 	void			*ax25_ptr;	/* AX.25 specific data */
 | 
				
			||||||
 | 
					 	struct wireless_dev	*ieee80211_ptr;	/* IEEE 802.11 specific data,
 | 
				
			||||||
 | 
					 						   assign before registering */
 | 
				
			||||||
 | 
					+	void			*phy_ptr; /* PHY device specific data */
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 /*
 | 
				
			||||||
 | 
					  * Cache lines mostly used on receive path (including eth_type_trans())
 | 
				
			||||||
							
								
								
									
										22
									
								
								target/linux/generic/patches-3.1/722-phy_mvswitch.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								target/linux/generic/patches-3.1/722-phy_mvswitch.patch
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,22 @@
 | 
				
			|||||||
 | 
					--- a/drivers/net/phy/Kconfig
 | 
				
			||||||
 | 
					+++ b/drivers/net/phy/Kconfig
 | 
				
			||||||
 | 
					@@ -105,6 +105,9 @@ config ADM6996_PHY
 | 
				
			||||||
 | 
					 	  Currently supports the ADM6996FC and ADM6996M switches.
 | 
				
			||||||
 | 
					 	  Support for FC is very limited.
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					+config MVSWITCH_PHY
 | 
				
			||||||
 | 
					+	tristate "Driver for Marvell 88E6060 switches"
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					 config FIXED_PHY
 | 
				
			||||||
 | 
					 	bool "Driver for MDIO Bus/PHY emulation with fixed speed/link PHYs"
 | 
				
			||||||
 | 
					 	depends on PHYLIB=y
 | 
				
			||||||
 | 
					--- a/drivers/net/phy/Makefile
 | 
				
			||||||
 | 
					+++ b/drivers/net/phy/Makefile
 | 
				
			||||||
 | 
					@@ -15,6 +15,7 @@ obj-$(CONFIG_BROADCOM_PHY)	+= broadcom.o
 | 
				
			||||||
 | 
					 obj-$(CONFIG_BCM63XX_PHY)	+= bcm63xx.o
 | 
				
			||||||
 | 
					 obj-$(CONFIG_ICPLUS_PHY)	+= icplus.o
 | 
				
			||||||
 | 
					 obj-$(CONFIG_ADM6996_PHY)	+= adm6996.o
 | 
				
			||||||
 | 
					+obj-$(CONFIG_MVSWITCH_PHY)	+= mvswitch.o
 | 
				
			||||||
 | 
					 obj-$(CONFIG_REALTEK_PHY)	+= realtek.o
 | 
				
			||||||
 | 
					 obj-$(CONFIG_LSI_ET1011C_PHY)	+= et1011c.o
 | 
				
			||||||
 | 
					 obj-$(CONFIG_FIXED_PHY)		+= fixed.o
 | 
				
			||||||
							
								
								
									
										23
									
								
								target/linux/generic/patches-3.1/723-phy_ip175c.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								target/linux/generic/patches-3.1/723-phy_ip175c.patch
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,23 @@
 | 
				
			|||||||
 | 
					--- a/drivers/net/phy/Kconfig
 | 
				
			||||||
 | 
					+++ b/drivers/net/phy/Kconfig
 | 
				
			||||||
 | 
					@@ -108,6 +108,10 @@ config ADM6996_PHY
 | 
				
			||||||
 | 
					 config MVSWITCH_PHY
 | 
				
			||||||
 | 
					 	tristate "Driver for Marvell 88E6060 switches"
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					+config IP17XX_PHY
 | 
				
			||||||
 | 
					+	tristate "Driver for IC+ IP17xx switches"
 | 
				
			||||||
 | 
					+	select SWCONFIG
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					 config FIXED_PHY
 | 
				
			||||||
 | 
					 	bool "Driver for MDIO Bus/PHY emulation with fixed speed/link PHYs"
 | 
				
			||||||
 | 
					 	depends on PHYLIB=y
 | 
				
			||||||
 | 
					--- a/drivers/net/phy/Makefile
 | 
				
			||||||
 | 
					+++ b/drivers/net/phy/Makefile
 | 
				
			||||||
 | 
					@@ -16,6 +16,7 @@ obj-$(CONFIG_BCM63XX_PHY)	+= bcm63xx.o
 | 
				
			||||||
 | 
					 obj-$(CONFIG_ICPLUS_PHY)	+= icplus.o
 | 
				
			||||||
 | 
					 obj-$(CONFIG_ADM6996_PHY)	+= adm6996.o
 | 
				
			||||||
 | 
					 obj-$(CONFIG_MVSWITCH_PHY)	+= mvswitch.o
 | 
				
			||||||
 | 
					+obj-$(CONFIG_IP17XX_PHY)	+= ip17xx.o
 | 
				
			||||||
 | 
					 obj-$(CONFIG_REALTEK_PHY)	+= realtek.o
 | 
				
			||||||
 | 
					 obj-$(CONFIG_LSI_ET1011C_PHY)	+= et1011c.o
 | 
				
			||||||
 | 
					 obj-$(CONFIG_FIXED_PHY)		+= fixed.o
 | 
				
			||||||
							
								
								
									
										23
									
								
								target/linux/generic/patches-3.1/724-phy_ar8216.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								target/linux/generic/patches-3.1/724-phy_ar8216.patch
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,23 @@
 | 
				
			|||||||
 | 
					--- a/drivers/net/phy/Kconfig
 | 
				
			||||||
 | 
					+++ b/drivers/net/phy/Kconfig
 | 
				
			||||||
 | 
					@@ -112,6 +112,10 @@ config IP17XX_PHY
 | 
				
			||||||
 | 
					 	tristate "Driver for IC+ IP17xx switches"
 | 
				
			||||||
 | 
					 	select SWCONFIG
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					+config AR8216_PHY
 | 
				
			||||||
 | 
					+	tristate "Driver for Atheros AR8216 switches"
 | 
				
			||||||
 | 
					+	select SWCONFIG
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					 config FIXED_PHY
 | 
				
			||||||
 | 
					 	bool "Driver for MDIO Bus/PHY emulation with fixed speed/link PHYs"
 | 
				
			||||||
 | 
					 	depends on PHYLIB=y
 | 
				
			||||||
 | 
					--- a/drivers/net/phy/Makefile
 | 
				
			||||||
 | 
					+++ b/drivers/net/phy/Makefile
 | 
				
			||||||
 | 
					@@ -18,6 +18,7 @@ obj-$(CONFIG_ADM6996_PHY)	+= adm6996.o
 | 
				
			||||||
 | 
					 obj-$(CONFIG_MVSWITCH_PHY)	+= mvswitch.o
 | 
				
			||||||
 | 
					 obj-$(CONFIG_IP17XX_PHY)	+= ip17xx.o
 | 
				
			||||||
 | 
					 obj-$(CONFIG_REALTEK_PHY)	+= realtek.o
 | 
				
			||||||
 | 
					+obj-$(CONFIG_AR8216_PHY)	+= ar8216.o
 | 
				
			||||||
 | 
					 obj-$(CONFIG_LSI_ET1011C_PHY)	+= et1011c.o
 | 
				
			||||||
 | 
					 obj-$(CONFIG_FIXED_PHY)		+= fixed.o
 | 
				
			||||||
 | 
					 obj-$(CONFIG_MDIO_BITBANG)	+= mdio-bitbang.o
 | 
				
			||||||
							
								
								
									
										23
									
								
								target/linux/generic/patches-3.1/725-phy_rtl8306.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								target/linux/generic/patches-3.1/725-phy_rtl8306.patch
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,23 @@
 | 
				
			|||||||
 | 
					--- a/drivers/net/phy/Kconfig
 | 
				
			||||||
 | 
					+++ b/drivers/net/phy/Kconfig
 | 
				
			||||||
 | 
					@@ -116,6 +116,10 @@ config AR8216_PHY
 | 
				
			||||||
 | 
					 	tristate "Driver for Atheros AR8216 switches"
 | 
				
			||||||
 | 
					 	select SWCONFIG
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					+config RTL8306_PHY
 | 
				
			||||||
 | 
					+	tristate "Driver for Realtek RTL8306S switches"
 | 
				
			||||||
 | 
					+	select SWCONFIG
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					 config FIXED_PHY
 | 
				
			||||||
 | 
					 	bool "Driver for MDIO Bus/PHY emulation with fixed speed/link PHYs"
 | 
				
			||||||
 | 
					 	depends on PHYLIB=y
 | 
				
			||||||
 | 
					--- a/drivers/net/phy/Makefile
 | 
				
			||||||
 | 
					+++ b/drivers/net/phy/Makefile
 | 
				
			||||||
 | 
					@@ -19,6 +19,7 @@ obj-$(CONFIG_MVSWITCH_PHY)	+= mvswitch.o
 | 
				
			||||||
 | 
					 obj-$(CONFIG_IP17XX_PHY)	+= ip17xx.o
 | 
				
			||||||
 | 
					 obj-$(CONFIG_REALTEK_PHY)	+= realtek.o
 | 
				
			||||||
 | 
					 obj-$(CONFIG_AR8216_PHY)	+= ar8216.o
 | 
				
			||||||
 | 
					+obj-$(CONFIG_RTL8306_PHY)	+= rtl8306.o
 | 
				
			||||||
 | 
					 obj-$(CONFIG_LSI_ET1011C_PHY)	+= et1011c.o
 | 
				
			||||||
 | 
					 obj-$(CONFIG_FIXED_PHY)		+= fixed.o
 | 
				
			||||||
 | 
					 obj-$(CONFIG_MDIO_BITBANG)	+= mdio-bitbang.o
 | 
				
			||||||
							
								
								
									
										44
									
								
								target/linux/generic/patches-3.1/726-phy_rtl8366.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										44
									
								
								target/linux/generic/patches-3.1/726-phy_rtl8366.patch
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,44 @@
 | 
				
			|||||||
 | 
					--- a/drivers/net/phy/Kconfig
 | 
				
			||||||
 | 
					+++ b/drivers/net/phy/Kconfig
 | 
				
			||||||
 | 
					@@ -158,4 +158,29 @@ config MDIO_OCTEON
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 	  If in doubt, say Y.
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					+config RTL8366_SMI
 | 
				
			||||||
 | 
					+	tristate "Driver for the RTL8366 SMI interface"
 | 
				
			||||||
 | 
					+	depends on GENERIC_GPIO
 | 
				
			||||||
 | 
					+	---help---
 | 
				
			||||||
 | 
					+	  This module implements the SMI interface protocol which is used
 | 
				
			||||||
 | 
					+	  by some RTL8366 ethernet switch devices via the generic GPIO API.
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+if RTL8366_SMI
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+config RTL8366S_PHY
 | 
				
			||||||
 | 
					+	tristate "Driver for the Realtek RTL8366S switch"
 | 
				
			||||||
 | 
					+	select SWCONFIG
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+config RTL8366RB_PHY
 | 
				
			||||||
 | 
					+	tristate "Driver for the Realtek RTL8366RB switch"
 | 
				
			||||||
 | 
					+	select SWCONFIG
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+config RTL8366S_PHY_DEBUG_FS
 | 
				
			||||||
 | 
					+	bool "RTL8366 switch driver DEBUG_FS support"
 | 
				
			||||||
 | 
					+	depends on RTL8366S_PHY || RTL8366RB_PHY
 | 
				
			||||||
 | 
					+	depends on DEBUG_FS
 | 
				
			||||||
 | 
					+	default n
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+endif # RTL8366_SMI
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					 endif # PHYLIB
 | 
				
			||||||
 | 
					--- a/drivers/net/phy/Makefile
 | 
				
			||||||
 | 
					+++ b/drivers/net/phy/Makefile
 | 
				
			||||||
 | 
					@@ -20,6 +20,9 @@ obj-$(CONFIG_IP17XX_PHY)	+= ip17xx.o
 | 
				
			||||||
 | 
					 obj-$(CONFIG_REALTEK_PHY)	+= realtek.o
 | 
				
			||||||
 | 
					 obj-$(CONFIG_AR8216_PHY)	+= ar8216.o
 | 
				
			||||||
 | 
					 obj-$(CONFIG_RTL8306_PHY)	+= rtl8306.o
 | 
				
			||||||
 | 
					+obj-$(CONFIG_RTL8366_SMI)	+= rtl8366_smi.o
 | 
				
			||||||
 | 
					+obj-$(CONFIG_RTL8366S_PHY)	+= rtl8366s.o
 | 
				
			||||||
 | 
					+obj-$(CONFIG_RTL8366RB_PHY)	+= rtl8366rb.o
 | 
				
			||||||
 | 
					 obj-$(CONFIG_LSI_ET1011C_PHY)	+= et1011c.o
 | 
				
			||||||
 | 
					 obj-$(CONFIG_FIXED_PHY)		+= fixed.o
 | 
				
			||||||
 | 
					 obj-$(CONFIG_MDIO_BITBANG)	+= mdio-bitbang.o
 | 
				
			||||||
							
								
								
									
										154
									
								
								target/linux/generic/patches-3.1/750-hostap_txpower.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										154
									
								
								target/linux/generic/patches-3.1/750-hostap_txpower.patch
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,154 @@
 | 
				
			|||||||
 | 
					--- a/drivers/net/wireless/hostap/hostap_ap.c
 | 
				
			||||||
 | 
					+++ b/drivers/net/wireless/hostap/hostap_ap.c
 | 
				
			||||||
 | 
					@@ -2338,13 +2338,13 @@ int prism2_ap_get_sta_qual(local_info_t
 | 
				
			||||||
 | 
					 		addr[count].sa_family = ARPHRD_ETHER;
 | 
				
			||||||
 | 
					 		memcpy(addr[count].sa_data, sta->addr, ETH_ALEN);
 | 
				
			||||||
 | 
					 		if (sta->last_rx_silence == 0)
 | 
				
			||||||
 | 
					-			qual[count].qual = sta->last_rx_signal < 27 ?
 | 
				
			||||||
 | 
					-				0 : (sta->last_rx_signal - 27) * 92 / 127;
 | 
				
			||||||
 | 
					+                        qual[count].qual = (sta->last_rx_signal - 156) == 0 ?
 | 
				
			||||||
 | 
					+                                0 : (sta->last_rx_signal - 156) * 92 / 64;
 | 
				
			||||||
 | 
					 		else
 | 
				
			||||||
 | 
					-			qual[count].qual = sta->last_rx_signal -
 | 
				
			||||||
 | 
					-				sta->last_rx_silence - 35;
 | 
				
			||||||
 | 
					-		qual[count].level = HFA384X_LEVEL_TO_dBm(sta->last_rx_signal);
 | 
				
			||||||
 | 
					-		qual[count].noise = HFA384X_LEVEL_TO_dBm(sta->last_rx_silence);
 | 
				
			||||||
 | 
					+                        qual[count].qual = (sta->last_rx_signal -
 | 
				
			||||||
 | 
					+                                sta->last_rx_silence) * 92 / 64;
 | 
				
			||||||
 | 
					+                qual[count].level = sta->last_rx_signal;
 | 
				
			||||||
 | 
					+                qual[count].noise = sta->last_rx_silence;
 | 
				
			||||||
 | 
					 		qual[count].updated = sta->last_rx_updated;
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 		sta->last_rx_updated = IW_QUAL_DBM;
 | 
				
			||||||
 | 
					@@ -2410,13 +2410,13 @@ int prism2_ap_translate_scan(struct net_
 | 
				
			||||||
 | 
					 		memset(&iwe, 0, sizeof(iwe));
 | 
				
			||||||
 | 
					 		iwe.cmd = IWEVQUAL;
 | 
				
			||||||
 | 
					 		if (sta->last_rx_silence == 0)
 | 
				
			||||||
 | 
					-			iwe.u.qual.qual = sta->last_rx_signal < 27 ?
 | 
				
			||||||
 | 
					-				0 : (sta->last_rx_signal - 27) * 92 / 127;
 | 
				
			||||||
 | 
					+	                iwe.u.qual.qual = (sta->last_rx_signal -156) == 0 ?
 | 
				
			||||||
 | 
					+	                        0 : (sta->last_rx_signal - 156) * 92 / 64;
 | 
				
			||||||
 | 
					 		else
 | 
				
			||||||
 | 
					-			iwe.u.qual.qual = sta->last_rx_signal -
 | 
				
			||||||
 | 
					-				sta->last_rx_silence - 35;
 | 
				
			||||||
 | 
					-		iwe.u.qual.level = HFA384X_LEVEL_TO_dBm(sta->last_rx_signal);
 | 
				
			||||||
 | 
					-		iwe.u.qual.noise = HFA384X_LEVEL_TO_dBm(sta->last_rx_silence);
 | 
				
			||||||
 | 
					+                        iwe.u.qual.qual = (sta->last_rx_signal -
 | 
				
			||||||
 | 
					+                                sta->last_rx_silence) * 92 / 64;
 | 
				
			||||||
 | 
					+                iwe.u.qual.level = sta->last_rx_signal;
 | 
				
			||||||
 | 
					+                iwe.u.qual.noise = sta->last_rx_silence;
 | 
				
			||||||
 | 
					 		iwe.u.qual.updated = sta->last_rx_updated;
 | 
				
			||||||
 | 
					 		iwe.len = IW_EV_QUAL_LEN;
 | 
				
			||||||
 | 
					 		current_ev = iwe_stream_add_event(info, current_ev, end_buf,
 | 
				
			||||||
 | 
					--- a/drivers/net/wireless/hostap/hostap_config.h
 | 
				
			||||||
 | 
					+++ b/drivers/net/wireless/hostap/hostap_config.h
 | 
				
			||||||
 | 
					@@ -45,4 +45,9 @@
 | 
				
			||||||
 | 
					  */
 | 
				
			||||||
 | 
					 /* #define PRISM2_NO_STATION_MODES */
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					+/* Enable TX power Setting functions
 | 
				
			||||||
 | 
					+ * (min att = -128 , max att =  127)
 | 
				
			||||||
 | 
					+ */
 | 
				
			||||||
 | 
					+#define RAW_TXPOWER_SETTING
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					 #endif /* HOSTAP_CONFIG_H */
 | 
				
			||||||
 | 
					--- a/drivers/net/wireless/hostap/hostap.h
 | 
				
			||||||
 | 
					+++ b/drivers/net/wireless/hostap/hostap.h
 | 
				
			||||||
 | 
					@@ -90,6 +90,7 @@ extern const struct iw_handler_def hosta
 | 
				
			||||||
 | 
					 extern const struct ethtool_ops prism2_ethtool_ops;
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 int hostap_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd);
 | 
				
			||||||
 | 
					+int hostap_restore_power(struct net_device *dev);
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 #endif /* HOSTAP_H */
 | 
				
			||||||
 | 
					--- a/drivers/net/wireless/hostap/hostap_hw.c
 | 
				
			||||||
 | 
					+++ b/drivers/net/wireless/hostap/hostap_hw.c
 | 
				
			||||||
 | 
					@@ -932,6 +932,7 @@ static int hfa384x_set_rid(struct net_de
 | 
				
			||||||
 | 
					 			prism2_hw_reset(dev);
 | 
				
			||||||
 | 
					 	}
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					+	hostap_restore_power(dev);
 | 
				
			||||||
 | 
					 	return res;
 | 
				
			||||||
 | 
					 }
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					--- a/drivers/net/wireless/hostap/hostap_info.c
 | 
				
			||||||
 | 
					+++ b/drivers/net/wireless/hostap/hostap_info.c
 | 
				
			||||||
 | 
					@@ -433,6 +433,11 @@ static void handle_info_queue_linkstatus
 | 
				
			||||||
 | 
					 	}
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 	/* Get BSSID if we have a valid AP address */
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	if ( val == HFA384X_LINKSTATUS_CONNECTED ||
 | 
				
			||||||
 | 
					+	     val == HFA384X_LINKSTATUS_DISCONNECTED )
 | 
				
			||||||
 | 
					+			hostap_restore_power(local->dev);
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					 	if (connected) {
 | 
				
			||||||
 | 
					 		netif_carrier_on(local->dev);
 | 
				
			||||||
 | 
					 		netif_carrier_on(local->ddev);
 | 
				
			||||||
 | 
					--- a/drivers/net/wireless/hostap/hostap_ioctl.c
 | 
				
			||||||
 | 
					+++ b/drivers/net/wireless/hostap/hostap_ioctl.c
 | 
				
			||||||
 | 
					@@ -1477,23 +1477,20 @@ static int prism2_txpower_hfa386x_to_dBm
 | 
				
			||||||
 | 
					 		val = 255;
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 	tmp = val;
 | 
				
			||||||
 | 
					-	tmp >>= 2;
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					-	return -12 - tmp;
 | 
				
			||||||
 | 
					+	return tmp;
 | 
				
			||||||
 | 
					 }
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 static u16 prism2_txpower_dBm_to_hfa386x(int val)
 | 
				
			||||||
 | 
					 {
 | 
				
			||||||
 | 
					 	signed char tmp;
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					-	if (val > 20)
 | 
				
			||||||
 | 
					-		return 128;
 | 
				
			||||||
 | 
					-	else if (val < -43)
 | 
				
			||||||
 | 
					+	if (val > 127)
 | 
				
			||||||
 | 
					 		return 127;
 | 
				
			||||||
 | 
					+	else if (val < -128)
 | 
				
			||||||
 | 
					+		return 128;
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 	tmp = val;
 | 
				
			||||||
 | 
					-	tmp = -12 - tmp;
 | 
				
			||||||
 | 
					-	tmp <<= 2;
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 	return (unsigned char) tmp;
 | 
				
			||||||
 | 
					 }
 | 
				
			||||||
 | 
					@@ -4056,3 +4053,35 @@ int hostap_ioctl(struct net_device *dev,
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 	return ret;
 | 
				
			||||||
 | 
					 }
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+/* BUG FIX: Restore power setting value when lost due to F/W bug */
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+int hostap_restore_power(struct net_device *dev)
 | 
				
			||||||
 | 
					+{
 | 
				
			||||||
 | 
					+        struct hostap_interface *iface = netdev_priv(dev);
 | 
				
			||||||
 | 
					+       local_info_t *local = iface->local;
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+       u16 val;
 | 
				
			||||||
 | 
					+       int ret = 0;
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+       if (local->txpower_type == PRISM2_TXPOWER_OFF) {
 | 
				
			||||||
 | 
					+                       val = 0xff; /* use all standby and sleep modes */
 | 
				
			||||||
 | 
					+                       ret = local->func->cmd(dev, HFA384X_CMDCODE_WRITEMIF,
 | 
				
			||||||
 | 
					+                                              HFA386X_CR_A_D_TEST_MODES2,
 | 
				
			||||||
 | 
					+                                              &val, NULL);
 | 
				
			||||||
 | 
					+       }
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+#ifdef RAW_TXPOWER_SETTING
 | 
				
			||||||
 | 
					+       if (local->txpower_type == PRISM2_TXPOWER_FIXED) {
 | 
				
			||||||
 | 
					+               val = HFA384X_TEST_CFG_BIT_ALC;
 | 
				
			||||||
 | 
					+               local->func->cmd(dev, HFA384X_CMDCODE_TEST |
 | 
				
			||||||
 | 
					+                                (HFA384X_TEST_CFG_BITS << 8), 0, &val, NULL);
 | 
				
			||||||
 | 
					+               val = prism2_txpower_dBm_to_hfa386x(local->txpower);
 | 
				
			||||||
 | 
					+               ret = (local->func->cmd(dev, HFA384X_CMDCODE_WRITEMIF,
 | 
				
			||||||
 | 
					+                            HFA386X_CR_MANUAL_TX_POWER, &val, NULL));
 | 
				
			||||||
 | 
					+       }
 | 
				
			||||||
 | 
					+#endif /* RAW_TXPOWER_SETTING */
 | 
				
			||||||
 | 
					+       return (ret ? -EOPNOTSUPP : 0);
 | 
				
			||||||
 | 
					+}
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+EXPORT_SYMBOL(hostap_restore_power);
 | 
				
			||||||
@@ -0,0 +1,43 @@
 | 
				
			|||||||
 | 
					--- a/drivers/pci/Kconfig
 | 
				
			||||||
 | 
					+++ b/drivers/pci/Kconfig
 | 
				
			||||||
 | 
					@@ -62,6 +62,12 @@ config XEN_PCIDEV_FE_DEBUG
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 	  When in doubt, say N.
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					+config PCI_DISABLE_COMMON_QUIRKS
 | 
				
			||||||
 | 
					+	bool "PCI disable common quirks"
 | 
				
			||||||
 | 
					+	depends on PCI
 | 
				
			||||||
 | 
					+	help
 | 
				
			||||||
 | 
					+	  If you don't know what to do here, say N.
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					 config HT_IRQ
 | 
				
			||||||
 | 
					 	bool "Interrupts on hypertransport devices"
 | 
				
			||||||
 | 
					 	default y
 | 
				
			||||||
 | 
					--- a/drivers/pci/quirks.c
 | 
				
			||||||
 | 
					+++ b/drivers/pci/quirks.c
 | 
				
			||||||
 | 
					@@ -104,6 +104,7 @@ static void __devinit quirk_mmio_always_
 | 
				
			||||||
 | 
					 }
 | 
				
			||||||
 | 
					 DECLARE_PCI_FIXUP_EARLY(PCI_ANY_ID, PCI_ANY_ID, quirk_mmio_always_on);
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					+#ifndef CONFIG_PCI_DISABLE_COMMON_QUIRKS
 | 
				
			||||||
 | 
					 /* The Mellanox Tavor device gives false positive parity errors
 | 
				
			||||||
 | 
					  * Mark this device with a broken_parity_status, to allow
 | 
				
			||||||
 | 
					  * PCI scanning code to "skip" this now blacklisted device.
 | 
				
			||||||
 | 
					@@ -1989,7 +1990,9 @@ static void __devinit fixup_rev1_53c810(
 | 
				
			||||||
 | 
					 	}
 | 
				
			||||||
 | 
					 }
 | 
				
			||||||
 | 
					 DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_NCR, PCI_DEVICE_ID_NCR_53C810, fixup_rev1_53c810);
 | 
				
			||||||
 | 
					+#endif /* !CONFIG_PCI_DISABLE_COMMON_QUIRKS */
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					+#ifndef CONFIG_PCI_DISABLE_COMMON_QUIRKS
 | 
				
			||||||
 | 
					 /* Enable 1k I/O space granularity on the Intel P64H2 */
 | 
				
			||||||
 | 
					 static void __devinit quirk_p64h2_1k_io(struct pci_dev *dev)
 | 
				
			||||||
 | 
					 {
 | 
				
			||||||
 | 
					@@ -2665,6 +2668,7 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AT
 | 
				
			||||||
 | 
					 			quirk_msi_intx_disable_bug);
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 #endif /* CONFIG_PCI_MSI */
 | 
				
			||||||
 | 
					+#endif /* !CONFIG_PCI_DISABLE_COMMON_QUIRKS */
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 /* Allow manual resource allocation for PCI hotplug bridges
 | 
				
			||||||
 | 
					  * via pci=hpmemsize=nnM and pci=hpiosize=nnM parameters. For
 | 
				
			||||||
@@ -0,0 +1,18 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
 | 
					--- a/drivers/usb/host/pci-quirks.c
 | 
				
			||||||
 | 
					+++ b/drivers/usb/host/pci-quirks.c
 | 
				
			||||||
 | 
					@@ -429,6 +429,8 @@ reset_needed:
 | 
				
			||||||
 | 
					 }
 | 
				
			||||||
 | 
					 EXPORT_SYMBOL_GPL(uhci_check_and_reset_hc);
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					+#ifndef CONFIG_PCI_DISABLE_COMMON_QUIRKS
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					 static inline int io_type_enabled(struct pci_dev *pdev, unsigned int mask)
 | 
				
			||||||
 | 
					 {
 | 
				
			||||||
 | 
					 	u16 cmd;
 | 
				
			||||||
 | 
					@@ -883,3 +885,5 @@ static void __devinit quirk_usb_early_ha
 | 
				
			||||||
 | 
					 		quirk_usb_handoff_xhci(pdev);
 | 
				
			||||||
 | 
					 }
 | 
				
			||||||
 | 
					 DECLARE_PCI_FIXUP_FINAL(PCI_ANY_ID, PCI_ANY_ID, quirk_usb_early_handoff);
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+#endif
 | 
				
			||||||
@@ -0,0 +1,84 @@
 | 
				
			|||||||
 | 
					--- a/drivers/usb/core/usb.c
 | 
				
			||||||
 | 
					+++ b/drivers/usb/core/usb.c
 | 
				
			||||||
 | 
					@@ -651,6 +651,71 @@ int __usb_get_extra_descriptor(char *buf
 | 
				
			||||||
 | 
					 }
 | 
				
			||||||
 | 
					 EXPORT_SYMBOL_GPL(__usb_get_extra_descriptor);
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					+static struct usb_device *match_device_name(struct usb_device *dev,
 | 
				
			||||||
 | 
					+					    const char *name)
 | 
				
			||||||
 | 
					+{
 | 
				
			||||||
 | 
					+	struct usb_device *ret_dev = NULL;
 | 
				
			||||||
 | 
					+	int child;
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	dev_dbg(&dev->dev, "check for name %s ...\n", name);
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	/* see if this device matches */
 | 
				
			||||||
 | 
					+	if (strcmp(dev_name(&dev->dev), name) == 0 ) {
 | 
				
			||||||
 | 
					+		dev_dbg(&dev->dev, "matched this device!\n");
 | 
				
			||||||
 | 
					+		ret_dev = usb_get_dev(dev);
 | 
				
			||||||
 | 
					+		goto exit;
 | 
				
			||||||
 | 
					+	}
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	/* look through all of the children of this device */
 | 
				
			||||||
 | 
					+	for (child = 0; child < dev->maxchild; ++child) {
 | 
				
			||||||
 | 
					+		if (dev->children[child]) {
 | 
				
			||||||
 | 
					+			usb_lock_device(dev->children[child]);
 | 
				
			||||||
 | 
					+			ret_dev = match_device_name(dev->children[child], name);
 | 
				
			||||||
 | 
					+			usb_unlock_device(dev->children[child]);
 | 
				
			||||||
 | 
					+			if (ret_dev)
 | 
				
			||||||
 | 
					+				goto exit;
 | 
				
			||||||
 | 
					+		}
 | 
				
			||||||
 | 
					+	}
 | 
				
			||||||
 | 
					+exit:
 | 
				
			||||||
 | 
					+	return ret_dev;
 | 
				
			||||||
 | 
					+}
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+/**
 | 
				
			||||||
 | 
					+ * usb_find_device_by_name - find a specific usb device in the system
 | 
				
			||||||
 | 
					+ * @name: the name of the device to find
 | 
				
			||||||
 | 
					+ *
 | 
				
			||||||
 | 
					+ * Returns a pointer to a struct usb_device if such a specified usb
 | 
				
			||||||
 | 
					+ * device is present in the system currently.  The usage count of the
 | 
				
			||||||
 | 
					+ * device will be incremented if a device is found.  Make sure to call
 | 
				
			||||||
 | 
					+ * usb_put_dev() when the caller is finished with the device.
 | 
				
			||||||
 | 
					+ *
 | 
				
			||||||
 | 
					+ * If a device with the specified bus id is not found, NULL is returned.
 | 
				
			||||||
 | 
					+ */
 | 
				
			||||||
 | 
					+struct usb_device *usb_find_device_by_name(const char *name)
 | 
				
			||||||
 | 
					+{
 | 
				
			||||||
 | 
					+	struct list_head *buslist;
 | 
				
			||||||
 | 
					+	struct usb_bus *bus;
 | 
				
			||||||
 | 
					+	struct usb_device *dev = NULL;
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	mutex_lock(&usb_bus_list_lock);
 | 
				
			||||||
 | 
					+	for (buslist = usb_bus_list.next;
 | 
				
			||||||
 | 
					+	     buslist != &usb_bus_list;
 | 
				
			||||||
 | 
					+	     buslist = buslist->next) {
 | 
				
			||||||
 | 
					+		bus = container_of(buslist, struct usb_bus, bus_list);
 | 
				
			||||||
 | 
					+		if (!bus->root_hub)
 | 
				
			||||||
 | 
					+			continue;
 | 
				
			||||||
 | 
					+		usb_lock_device(bus->root_hub);
 | 
				
			||||||
 | 
					+		dev = match_device_name(bus->root_hub, name);
 | 
				
			||||||
 | 
					+		usb_unlock_device(bus->root_hub);
 | 
				
			||||||
 | 
					+		if (dev)
 | 
				
			||||||
 | 
					+			goto exit;
 | 
				
			||||||
 | 
					+	}
 | 
				
			||||||
 | 
					+exit:
 | 
				
			||||||
 | 
					+	mutex_unlock(&usb_bus_list_lock);
 | 
				
			||||||
 | 
					+	return dev;
 | 
				
			||||||
 | 
					+}
 | 
				
			||||||
 | 
					+EXPORT_SYMBOL_GPL(usb_find_device_by_name);
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					 /**
 | 
				
			||||||
 | 
					  * usb_alloc_coherent - allocate dma-consistent buffer for URB_NO_xxx_DMA_MAP
 | 
				
			||||||
 | 
					  * @dev: device the buffer will be used with
 | 
				
			||||||
 | 
					--- a/include/linux/usb.h
 | 
				
			||||||
 | 
					+++ b/include/linux/usb.h
 | 
				
			||||||
 | 
					@@ -513,6 +513,7 @@ extern int usb_lock_device_for_reset(str
 | 
				
			||||||
 | 
					 extern int usb_reset_device(struct usb_device *dev);
 | 
				
			||||||
 | 
					 extern void usb_queue_reset_device(struct usb_interface *dev);
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					+extern struct usb_device *usb_find_device_by_name(const char *name);
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 /* USB autosuspend and autoresume */
 | 
				
			||||||
 | 
					 #ifdef CONFIG_USB_SUSPEND
 | 
				
			||||||
							
								
								
									
										18
									
								
								target/linux/generic/patches-3.1/830-ledtrig_morse.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								target/linux/generic/patches-3.1/830-ledtrig_morse.patch
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,18 @@
 | 
				
			|||||||
 | 
					--- a/drivers/leds/Kconfig
 | 
				
			||||||
 | 
					+++ b/drivers/leds/Kconfig
 | 
				
			||||||
 | 
					@@ -453,4 +453,8 @@ config LEDS_TRIGGER_DEFAULT_ON
 | 
				
			||||||
 | 
					 comment "iptables trigger is under Netfilter config (LED target)"
 | 
				
			||||||
 | 
					 	depends on LEDS_TRIGGERS
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					+config LEDS_TRIGGER_MORSE
 | 
				
			||||||
 | 
					+	tristate "LED Morse Trigger"
 | 
				
			||||||
 | 
					+	depends on LEDS_TRIGGERS
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					 endif # NEW_LEDS
 | 
				
			||||||
 | 
					--- a/drivers/leds/Makefile
 | 
				
			||||||
 | 
					+++ b/drivers/leds/Makefile
 | 
				
			||||||
 | 
					@@ -54,3 +54,4 @@ obj-$(CONFIG_LEDS_TRIGGER_HEARTBEAT)	+=
 | 
				
			||||||
 | 
					 obj-$(CONFIG_LEDS_TRIGGER_BACKLIGHT)	+= ledtrig-backlight.o
 | 
				
			||||||
 | 
					 obj-$(CONFIG_LEDS_TRIGGER_GPIO)		+= ledtrig-gpio.o
 | 
				
			||||||
 | 
					 obj-$(CONFIG_LEDS_TRIGGER_DEFAULT_ON)	+= ledtrig-default-on.o
 | 
				
			||||||
 | 
					+obj-$(CONFIG_LEDS_TRIGGER_MORSE)	+= ledtrig-morse.o
 | 
				
			||||||
							
								
								
									
										43
									
								
								target/linux/generic/patches-3.1/831-ledtrig_netdev.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										43
									
								
								target/linux/generic/patches-3.1/831-ledtrig_netdev.patch
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,43 @@
 | 
				
			|||||||
 | 
					--- a/drivers/leds/Kconfig
 | 
				
			||||||
 | 
					+++ b/drivers/leds/Kconfig
 | 
				
			||||||
 | 
					@@ -457,4 +457,11 @@ config LEDS_TRIGGER_MORSE
 | 
				
			||||||
 | 
					 	tristate "LED Morse Trigger"
 | 
				
			||||||
 | 
					 	depends on LEDS_TRIGGERS
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					+config LEDS_TRIGGER_NETDEV
 | 
				
			||||||
 | 
					+	tristate "LED Netdev Trigger"
 | 
				
			||||||
 | 
					+	depends on NET && LEDS_TRIGGERS
 | 
				
			||||||
 | 
					+	help
 | 
				
			||||||
 | 
					+	  This allows LEDs to be controlled by network device activity.
 | 
				
			||||||
 | 
					+	  If unsure, say Y.
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					 endif # NEW_LEDS
 | 
				
			||||||
 | 
					--- a/drivers/leds/Makefile
 | 
				
			||||||
 | 
					+++ b/drivers/leds/Makefile
 | 
				
			||||||
 | 
					@@ -55,3 +55,4 @@ obj-$(CONFIG_LEDS_TRIGGER_BACKLIGHT)	+=
 | 
				
			||||||
 | 
					 obj-$(CONFIG_LEDS_TRIGGER_GPIO)		+= ledtrig-gpio.o
 | 
				
			||||||
 | 
					 obj-$(CONFIG_LEDS_TRIGGER_DEFAULT_ON)	+= ledtrig-default-on.o
 | 
				
			||||||
 | 
					 obj-$(CONFIG_LEDS_TRIGGER_MORSE)	+= ledtrig-morse.o
 | 
				
			||||||
 | 
					+obj-$(CONFIG_LEDS_TRIGGER_NETDEV)	+= ledtrig-netdev.o
 | 
				
			||||||
 | 
					--- a/drivers/leds/ledtrig-netdev.c
 | 
				
			||||||
 | 
					+++ b/drivers/leds/ledtrig-netdev.c
 | 
				
			||||||
 | 
					@@ -307,8 +307,9 @@ done:
 | 
				
			||||||
 | 
					 static void netdev_trig_timer(unsigned long arg)
 | 
				
			||||||
 | 
					 {
 | 
				
			||||||
 | 
					 	struct led_netdev_data *trigger_data = (struct led_netdev_data *)arg;
 | 
				
			||||||
 | 
					-	const struct net_device_stats *dev_stats;
 | 
				
			||||||
 | 
					+	struct rtnl_link_stats64 *dev_stats;
 | 
				
			||||||
 | 
					 	unsigned new_activity;
 | 
				
			||||||
 | 
					+	struct rtnl_link_stats64 temp;
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 	write_lock(&trigger_data->lock);
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					@@ -318,7 +319,7 @@ static void netdev_trig_timer(unsigned l
 | 
				
			||||||
 | 
					 		goto no_restart;
 | 
				
			||||||
 | 
					 	}
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					-	dev_stats = dev_get_stats(trigger_data->net_dev);
 | 
				
			||||||
 | 
					+	dev_stats = dev_get_stats(trigger_data->net_dev, &temp);
 | 
				
			||||||
 | 
					 	new_activity =
 | 
				
			||||||
 | 
					 		((trigger_data->mode & MODE_TX) ? dev_stats->tx_packets : 0) +
 | 
				
			||||||
 | 
					 		((trigger_data->mode & MODE_RX) ? dev_stats->rx_packets : 0);
 | 
				
			||||||
							
								
								
									
										21
									
								
								target/linux/generic/patches-3.1/832-ledtrig_usbdev.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								target/linux/generic/patches-3.1/832-ledtrig_usbdev.patch
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,21 @@
 | 
				
			|||||||
 | 
					--- a/drivers/leds/Kconfig
 | 
				
			||||||
 | 
					+++ b/drivers/leds/Kconfig
 | 
				
			||||||
 | 
					@@ -464,4 +464,11 @@ config LEDS_TRIGGER_NETDEV
 | 
				
			||||||
 | 
					 	  This allows LEDs to be controlled by network device activity.
 | 
				
			||||||
 | 
					 	  If unsure, say Y.
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					+config LEDS_TRIGGER_USBDEV
 | 
				
			||||||
 | 
					+	tristate "LED USB device Trigger"
 | 
				
			||||||
 | 
					+	depends on USB && LEDS_TRIGGERS
 | 
				
			||||||
 | 
					+	help
 | 
				
			||||||
 | 
					+	  This allows LEDs to be controlled by the presence/activity of
 | 
				
			||||||
 | 
					+	  an USB device. If unsure, say N.
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					 endif # NEW_LEDS
 | 
				
			||||||
 | 
					--- a/drivers/leds/Makefile
 | 
				
			||||||
 | 
					+++ b/drivers/leds/Makefile
 | 
				
			||||||
 | 
					@@ -56,3 +56,4 @@ obj-$(CONFIG_LEDS_TRIGGER_GPIO)		+= ledt
 | 
				
			||||||
 | 
					 obj-$(CONFIG_LEDS_TRIGGER_DEFAULT_ON)	+= ledtrig-default-on.o
 | 
				
			||||||
 | 
					 obj-$(CONFIG_LEDS_TRIGGER_MORSE)	+= ledtrig-morse.o
 | 
				
			||||||
 | 
					 obj-$(CONFIG_LEDS_TRIGGER_NETDEV)	+= ledtrig-netdev.o
 | 
				
			||||||
 | 
					+obj-$(CONFIG_LEDS_TRIGGER_USBDEV)	+= ledtrig-usbdev.o
 | 
				
			||||||
							
								
								
									
										30
									
								
								target/linux/generic/patches-3.1/833-gpio_buttons.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										30
									
								
								target/linux/generic/patches-3.1/833-gpio_buttons.patch
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,30 @@
 | 
				
			|||||||
 | 
					--- a/drivers/input/misc/Kconfig
 | 
				
			||||||
 | 
					+++ b/drivers/input/misc/Kconfig
 | 
				
			||||||
 | 
					@@ -527,4 +527,20 @@ config INPUT_XEN_KBDDEV_FRONTEND
 | 
				
			||||||
 | 
					 	  To compile this driver as a module, choose M here: the
 | 
				
			||||||
 | 
					 	  module will be called xen-kbdfront.
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					+config INPUT_GPIO_BUTTONS
 | 
				
			||||||
 | 
					+	tristate "Polled GPIO buttons interface"
 | 
				
			||||||
 | 
					+	depends on GENERIC_GPIO
 | 
				
			||||||
 | 
					+	select INPUT_POLLDEV
 | 
				
			||||||
 | 
					+	help
 | 
				
			||||||
 | 
					+	  This driver implements support for buttons connected
 | 
				
			||||||
 | 
					+	  to GPIO pins of various CPUs (and some other chips).
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	  Say Y here if your device has buttons connected
 | 
				
			||||||
 | 
					+	  directly to such GPIO pins.  Your board-specific
 | 
				
			||||||
 | 
					+	  setup logic must also provide a platform device,
 | 
				
			||||||
 | 
					+	  with configuration data saying which GPIOs are used.
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	  To compile this driver as a module, choose M here: the
 | 
				
			||||||
 | 
					+	  module will be called gpio-buttons.
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					 endif
 | 
				
			||||||
 | 
					--- a/drivers/input/misc/Makefile
 | 
				
			||||||
 | 
					+++ b/drivers/input/misc/Makefile
 | 
				
			||||||
 | 
					@@ -49,3 +49,4 @@ obj-$(CONFIG_INPUT_WISTRON_BTNS)	+= wist
 | 
				
			||||||
 | 
					 obj-$(CONFIG_INPUT_WM831X_ON)		+= wm831x-on.o
 | 
				
			||||||
 | 
					 obj-$(CONFIG_INPUT_XEN_KBDDEV_FRONTEND)	+= xen-kbdfront.o
 | 
				
			||||||
 | 
					 obj-$(CONFIG_INPUT_YEALINK)		+= yealink.o
 | 
				
			||||||
 | 
					+obj-$(CONFIG_INPUT_GPIO_BUTTONS)	+= gpio_buttons.o
 | 
				
			||||||
							
								
								
									
										27
									
								
								target/linux/generic/patches-3.1/835-gpiodev.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								target/linux/generic/patches-3.1/835-gpiodev.patch
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,27 @@
 | 
				
			|||||||
 | 
					--- a/drivers/char/Kconfig
 | 
				
			||||||
 | 
					+++ b/drivers/char/Kconfig
 | 
				
			||||||
 | 
					@@ -511,6 +511,14 @@ config NSC_GPIO
 | 
				
			||||||
 | 
					 	  pc8736x_gpio drivers.  If those drivers are built as
 | 
				
			||||||
 | 
					 	  modules, this one will be too, named nsc_gpio
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					+config GPIO_DEVICE
 | 
				
			||||||
 | 
					+	tristate "GPIO device support"
 | 
				
			||||||
 | 
					+	depends on GENERIC_GPIO
 | 
				
			||||||
 | 
					+	help
 | 
				
			||||||
 | 
					+	  Say Y to enable Linux GPIO device support.  This allows control of
 | 
				
			||||||
 | 
					+	  GPIO pins using a character device
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					 config RAW_DRIVER
 | 
				
			||||||
 | 
					 	tristate "RAW driver (/dev/raw/rawN)"
 | 
				
			||||||
 | 
					 	depends on BLOCK
 | 
				
			||||||
 | 
					--- a/drivers/char/Makefile
 | 
				
			||||||
 | 
					+++ b/drivers/char/Makefile
 | 
				
			||||||
 | 
					@@ -47,6 +47,7 @@ obj-$(CONFIG_NWFLASH)		+= nwflash.o
 | 
				
			||||||
 | 
					 obj-$(CONFIG_SCx200_GPIO)	+= scx200_gpio.o
 | 
				
			||||||
 | 
					 obj-$(CONFIG_PC8736x_GPIO)	+= pc8736x_gpio.o
 | 
				
			||||||
 | 
					 obj-$(CONFIG_NSC_GPIO)		+= nsc_gpio.o
 | 
				
			||||||
 | 
					+obj-$(CONFIG_GPIO_DEVICE)	+= gpio_dev.o
 | 
				
			||||||
 | 
					 obj-$(CONFIG_GPIO_TB0219)	+= tb0219.o
 | 
				
			||||||
 | 
					 obj-$(CONFIG_TELCLOCK)		+= tlclk.o
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
							
								
								
									
										250
									
								
								target/linux/generic/patches-3.1/840-rtc7301.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										250
									
								
								target/linux/generic/patches-3.1/840-rtc7301.patch
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,250 @@
 | 
				
			|||||||
 | 
					--- a/drivers/rtc/Kconfig
 | 
				
			||||||
 | 
					+++ b/drivers/rtc/Kconfig
 | 
				
			||||||
 | 
					@@ -719,6 +719,15 @@ config RTC_DRV_NUC900
 | 
				
			||||||
 | 
					 	  If you say yes here you get support for the RTC subsystem of the
 | 
				
			||||||
 | 
					 	  NUC910/NUC920 used in embedded systems.
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					+config RTC_DRV_RTC7301
 | 
				
			||||||
 | 
					+	tristate "Epson RTC-7301 SF/DG"
 | 
				
			||||||
 | 
					+	help
 | 
				
			||||||
 | 
					+	  If you say Y here you will get support for the
 | 
				
			||||||
 | 
					+	  Epson RTC-7301 SF/DG RTC chips.
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	  This driver can also be built as a module. If so, the module
 | 
				
			||||||
 | 
					+	  will be called rtc-7301.
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					 comment "on-CPU RTC drivers"
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 config RTC_DRV_DAVINCI
 | 
				
			||||||
 | 
					--- a/drivers/rtc/Makefile
 | 
				
			||||||
 | 
					+++ b/drivers/rtc/Makefile
 | 
				
			||||||
 | 
					@@ -86,6 +86,7 @@ obj-$(CONFIG_RTC_DRV_RP5C01)	+= rtc-rp5c
 | 
				
			||||||
 | 
					 obj-$(CONFIG_RTC_DRV_RS5C313)	+= rtc-rs5c313.o
 | 
				
			||||||
 | 
					 obj-$(CONFIG_RTC_DRV_RS5C348)	+= rtc-rs5c348.o
 | 
				
			||||||
 | 
					 obj-$(CONFIG_RTC_DRV_RS5C372)	+= rtc-rs5c372.o
 | 
				
			||||||
 | 
					+obj-$(CONFIG_RTC_DRV_RTC7301)	+= rtc-rtc7301.o
 | 
				
			||||||
 | 
					 obj-$(CONFIG_RTC_DRV_RV3029C2)	+= rtc-rv3029c2.o
 | 
				
			||||||
 | 
					 obj-$(CONFIG_RTC_DRV_RX8025)	+= rtc-rx8025.o
 | 
				
			||||||
 | 
					 obj-$(CONFIG_RTC_DRV_RX8581)	+= rtc-rx8581.o
 | 
				
			||||||
 | 
					--- /dev/null
 | 
				
			||||||
 | 
					+++ b/drivers/rtc/rtc-rtc7301.c
 | 
				
			||||||
 | 
					@@ -0,0 +1,219 @@
 | 
				
			||||||
 | 
					+/*
 | 
				
			||||||
 | 
					+ * Driver for Epson RTC-7301SF/DG
 | 
				
			||||||
 | 
					+ *
 | 
				
			||||||
 | 
					+ * Copyright (C) 2009 Jose Vasconcellos
 | 
				
			||||||
 | 
					+ *
 | 
				
			||||||
 | 
					+ * 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/module.h>
 | 
				
			||||||
 | 
					+#include <linux/rtc.h>
 | 
				
			||||||
 | 
					+#include <linux/platform_device.h>
 | 
				
			||||||
 | 
					+#include <linux/io.h>
 | 
				
			||||||
 | 
					+#include <linux/delay.h>
 | 
				
			||||||
 | 
					+#include <linux/bcd.h>
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+#define RTC_NAME "rtc7301"
 | 
				
			||||||
 | 
					+#define RTC_VERSION "0.1"
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+/* Epson RTC-7301 register addresses */
 | 
				
			||||||
 | 
					+#define RTC7301_SEC		0x00
 | 
				
			||||||
 | 
					+#define RTC7301_SEC10		0x01
 | 
				
			||||||
 | 
					+#define RTC7301_MIN		0x02
 | 
				
			||||||
 | 
					+#define RTC7301_MIN10		0x03
 | 
				
			||||||
 | 
					+#define RTC7301_HOUR		0x04
 | 
				
			||||||
 | 
					+#define RTC7301_HOUR10		0x05
 | 
				
			||||||
 | 
					+#define RTC7301_WEEKDAY		0x06
 | 
				
			||||||
 | 
					+#define RTC7301_DAY		0x07
 | 
				
			||||||
 | 
					+#define RTC7301_DAY10		0x08
 | 
				
			||||||
 | 
					+#define RTC7301_MON		0x09
 | 
				
			||||||
 | 
					+#define RTC7301_MON10		0x0A
 | 
				
			||||||
 | 
					+#define RTC7301_YEAR		0x0B
 | 
				
			||||||
 | 
					+#define RTC7301_YEAR10		0x0C
 | 
				
			||||||
 | 
					+#define RTC7301_YEAR100		0x0D
 | 
				
			||||||
 | 
					+#define RTC7301_YEAR1000	0x0E
 | 
				
			||||||
 | 
					+#define RTC7301_CTRLREG		0x0F
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+static uint8_t __iomem *rtc7301_base;
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+#define read_reg(offset) (readb(rtc7301_base + offset) & 0xf)
 | 
				
			||||||
 | 
					+#define write_reg(offset, data) writeb(data, rtc7301_base + (offset))
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+#define rtc7301_isbusy() (read_reg(RTC7301_CTRLREG) & 1)
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+static void rtc7301_init_settings(void)
 | 
				
			||||||
 | 
					+{
 | 
				
			||||||
 | 
					+	int i;
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	write_reg(RTC7301_CTRLREG, 2);
 | 
				
			||||||
 | 
					+	write_reg(RTC7301_YEAR1000, 2);
 | 
				
			||||||
 | 
					+	udelay(122);
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	/* bank 1 */
 | 
				
			||||||
 | 
					+	write_reg(RTC7301_CTRLREG, 6);
 | 
				
			||||||
 | 
					+	for (i=0; i<15; i++)
 | 
				
			||||||
 | 
					+		write_reg(i, 0);
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	/* bank 2 */
 | 
				
			||||||
 | 
					+	write_reg(RTC7301_CTRLREG, 14);
 | 
				
			||||||
 | 
					+	for (i=0; i<15; i++)
 | 
				
			||||||
 | 
					+		write_reg(i, 0);
 | 
				
			||||||
 | 
					+	write_reg(RTC7301_CTRLREG, 0);
 | 
				
			||||||
 | 
					+}
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+static int rtc7301_get_datetime(struct device *dev, struct rtc_time *dt)
 | 
				
			||||||
 | 
					+{
 | 
				
			||||||
 | 
					+	int cnt;
 | 
				
			||||||
 | 
					+	uint8_t buf[16];
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	cnt = 0;
 | 
				
			||||||
 | 
					+	while (rtc7301_isbusy()) {
 | 
				
			||||||
 | 
					+		udelay(244);
 | 
				
			||||||
 | 
					+		if (cnt++ > 100) {
 | 
				
			||||||
 | 
					+			dev_err(dev, "%s: timeout error %x\n", __func__, rtc7301_base[RTC7301_CTRLREG]);
 | 
				
			||||||
 | 
					+			return -EIO;
 | 
				
			||||||
 | 
					+		}
 | 
				
			||||||
 | 
					+	}
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	for (cnt=0; cnt<16; cnt++)
 | 
				
			||||||
 | 
					+		buf[cnt] = read_reg(cnt);
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	if (buf[RTC7301_SEC10] & 8) {
 | 
				
			||||||
 | 
					+		dev_err(dev, "%s: RTC not set\n", __func__);
 | 
				
			||||||
 | 
					+		return -EINVAL;
 | 
				
			||||||
 | 
					+	}
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	memset(dt, 0, sizeof(*dt));
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	dt->tm_sec =  buf[RTC7301_SEC] + buf[RTC7301_SEC10]*10;
 | 
				
			||||||
 | 
					+	dt->tm_min =  buf[RTC7301_MIN] + buf[RTC7301_MIN10]*10;
 | 
				
			||||||
 | 
					+	dt->tm_hour = buf[RTC7301_HOUR] + buf[RTC7301_HOUR10]*10;
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	dt->tm_mday = buf[RTC7301_DAY] + buf[RTC7301_DAY10]*10;
 | 
				
			||||||
 | 
					+	dt->tm_mon =  buf[RTC7301_MON] + buf[RTC7301_MON10]*10 - 1;
 | 
				
			||||||
 | 
					+	dt->tm_year = buf[RTC7301_YEAR] + buf[RTC7301_YEAR10]*10 +
 | 
				
			||||||
 | 
					+		      buf[RTC7301_YEAR100]*100 +
 | 
				
			||||||
 | 
					+		      ((buf[RTC7301_YEAR1000] & 3)*1000) - 1900;
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	/* the rtc device may contain illegal values on power up
 | 
				
			||||||
 | 
					+	 * according to the data sheet. make sure they are valid.
 | 
				
			||||||
 | 
					+	 */
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	return rtc_valid_tm(dt);
 | 
				
			||||||
 | 
					+}
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+static int rtc7301_set_datetime(struct device *dev, struct rtc_time *dt)
 | 
				
			||||||
 | 
					+{
 | 
				
			||||||
 | 
					+	int data;
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	data = dt->tm_year + 1900;
 | 
				
			||||||
 | 
					+	if (data >= 2100 || data < 1900)
 | 
				
			||||||
 | 
					+		return -EINVAL;
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	write_reg(RTC7301_CTRLREG, 2);
 | 
				
			||||||
 | 
					+       	udelay(122);
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	data = bin2bcd(dt->tm_sec);
 | 
				
			||||||
 | 
					+	write_reg(RTC7301_SEC, data);
 | 
				
			||||||
 | 
					+	write_reg(RTC7301_SEC10, (data >> 4));
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	data = bin2bcd(dt->tm_min);
 | 
				
			||||||
 | 
					+	write_reg(RTC7301_MIN, data );
 | 
				
			||||||
 | 
					+	write_reg(RTC7301_MIN10, (data >> 4));
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	data = bin2bcd(dt->tm_hour);
 | 
				
			||||||
 | 
					+	write_reg(RTC7301_HOUR, data);
 | 
				
			||||||
 | 
					+	write_reg(RTC7301_HOUR10, (data >> 4));
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	data = bin2bcd(dt->tm_mday);
 | 
				
			||||||
 | 
					+	write_reg(RTC7301_DAY, data);
 | 
				
			||||||
 | 
					+	write_reg(RTC7301_DAY10, (data>> 4));
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	data = bin2bcd(dt->tm_mon + 1);
 | 
				
			||||||
 | 
					+	write_reg(RTC7301_MON, data);
 | 
				
			||||||
 | 
					+	write_reg(RTC7301_MON10, (data >> 4));
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	data = bin2bcd(dt->tm_year % 100);
 | 
				
			||||||
 | 
					+	write_reg(RTC7301_YEAR, data);
 | 
				
			||||||
 | 
					+	write_reg(RTC7301_YEAR10, (data >> 4));
 | 
				
			||||||
 | 
					+	data = bin2bcd((1900 + dt->tm_year) / 100);
 | 
				
			||||||
 | 
					+	write_reg(RTC7301_YEAR100, data);
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	data = bin2bcd(dt->tm_wday);
 | 
				
			||||||
 | 
					+	write_reg(RTC7301_WEEKDAY, data);
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	write_reg(RTC7301_CTRLREG, 0);
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	return 0;
 | 
				
			||||||
 | 
					+}
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+static const struct rtc_class_ops rtc7301_rtc_ops = {
 | 
				
			||||||
 | 
					+	.read_time	= rtc7301_get_datetime,
 | 
				
			||||||
 | 
					+	.set_time	= rtc7301_set_datetime,
 | 
				
			||||||
 | 
					+};
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+static int __devinit rtc7301_probe(struct platform_device *pdev)
 | 
				
			||||||
 | 
					+{
 | 
				
			||||||
 | 
					+	struct rtc_device *rtc;
 | 
				
			||||||
 | 
					+	struct resource *res;
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 | 
				
			||||||
 | 
					+	if (!res)
 | 
				
			||||||
 | 
					+		return -ENOENT;
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	rtc7301_base = ioremap_nocache(res->start, 0x1000 /*res->end - res->start + 1*/);
 | 
				
			||||||
 | 
					+	if (!rtc7301_base)
 | 
				
			||||||
 | 
					+		return -EINVAL;
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	rtc = rtc_device_register(RTC_NAME, &pdev->dev,
 | 
				
			||||||
 | 
					+				&rtc7301_rtc_ops, THIS_MODULE);
 | 
				
			||||||
 | 
					+	if (IS_ERR(rtc)) {
 | 
				
			||||||
 | 
					+		iounmap(rtc7301_base);
 | 
				
			||||||
 | 
					+		return PTR_ERR(rtc);
 | 
				
			||||||
 | 
					+	}
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	platform_set_drvdata(pdev, rtc);
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	rtc7301_init_settings();
 | 
				
			||||||
 | 
					+	return 0;
 | 
				
			||||||
 | 
					+}
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+static int __devexit rtc7301_remove(struct platform_device *pdev)
 | 
				
			||||||
 | 
					+{
 | 
				
			||||||
 | 
					+	struct rtc_device *rtc = platform_get_drvdata(pdev);
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	if (rtc)
 | 
				
			||||||
 | 
					+		rtc_device_unregister(rtc);
 | 
				
			||||||
 | 
					+	if (rtc7301_base)
 | 
				
			||||||
 | 
					+		iounmap(rtc7301_base);
 | 
				
			||||||
 | 
					+	return 0;
 | 
				
			||||||
 | 
					+}
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+static struct platform_driver rtc7301_driver = {
 | 
				
			||||||
 | 
					+	.driver = {
 | 
				
			||||||
 | 
					+		.name	= RTC_NAME,
 | 
				
			||||||
 | 
					+		.owner	= THIS_MODULE,
 | 
				
			||||||
 | 
					+	},
 | 
				
			||||||
 | 
					+	.probe	= rtc7301_probe,
 | 
				
			||||||
 | 
					+	.remove = __devexit_p(rtc7301_remove),
 | 
				
			||||||
 | 
					+};
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+static __init int rtc7301_init(void)
 | 
				
			||||||
 | 
					+{
 | 
				
			||||||
 | 
					+	return platform_driver_register(&rtc7301_driver);
 | 
				
			||||||
 | 
					+}
 | 
				
			||||||
 | 
					+module_init(rtc7301_init);
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+static __exit void rtc7301_exit(void)
 | 
				
			||||||
 | 
					+{
 | 
				
			||||||
 | 
					+	platform_driver_unregister(&rtc7301_driver);
 | 
				
			||||||
 | 
					+}
 | 
				
			||||||
 | 
					+module_exit(rtc7301_exit);
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+MODULE_DESCRIPTION("Epson 7301 RTC driver");
 | 
				
			||||||
 | 
					+MODULE_AUTHOR("Jose Vasconcellos <jvasco@verizon.net>");
 | 
				
			||||||
 | 
					+MODULE_LICENSE("GPL");
 | 
				
			||||||
 | 
					+MODULE_ALIAS("platform:" RTC_NAME);
 | 
				
			||||||
 | 
					+MODULE_VERSION(RTC_VERSION);
 | 
				
			||||||
							
								
								
									
										21
									
								
								target/linux/generic/patches-3.1/850-glamo_headers.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								target/linux/generic/patches-3.1/850-glamo_headers.patch
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,21 @@
 | 
				
			|||||||
 | 
					--- a/include/linux/fb.h
 | 
				
			||||||
 | 
					+++ b/include/linux/fb.h
 | 
				
			||||||
 | 
					@@ -125,6 +125,7 @@
 | 
				
			||||||
 | 
					 #define FB_ACCEL_TRIDENT_BLADE3D 52	/* Trident Blade3D		*/
 | 
				
			||||||
 | 
					 #define FB_ACCEL_TRIDENT_BLADEXP 53	/* Trident BladeXP		*/
 | 
				
			||||||
 | 
					 #define FB_ACCEL_CIRRUS_ALPINE   53	/* Cirrus Logic 543x/544x/5480	*/
 | 
				
			||||||
 | 
					+#define FB_ACCEL_GLAMO		50	/* SMedia Glamo                 */
 | 
				
			||||||
 | 
					 #define FB_ACCEL_NEOMAGIC_NM2070 90	/* NeoMagic NM2070              */
 | 
				
			||||||
 | 
					 #define FB_ACCEL_NEOMAGIC_NM2090 91	/* NeoMagic NM2090              */
 | 
				
			||||||
 | 
					 #define FB_ACCEL_NEOMAGIC_NM2093 92	/* NeoMagic NM2093              */
 | 
				
			||||||
 | 
					--- a/include/linux/Kbuild
 | 
				
			||||||
 | 
					+++ b/include/linux/Kbuild
 | 
				
			||||||
 | 
					@@ -144,6 +144,8 @@ header-y += generic_serial.h
 | 
				
			||||||
 | 
					 header-y += genetlink.h
 | 
				
			||||||
 | 
					 header-y += gfs2_ondisk.h
 | 
				
			||||||
 | 
					 header-y += gigaset_dev.h
 | 
				
			||||||
 | 
					+header-y += glamofb.h
 | 
				
			||||||
 | 
					+header-y += glamo-engine.h
 | 
				
			||||||
 | 
					 header-y += hdlc.h
 | 
				
			||||||
 | 
					 header-y += hdlcdrv.h
 | 
				
			||||||
 | 
					 header-y += hdreg.h
 | 
				
			||||||
@@ -0,0 +1,60 @@
 | 
				
			|||||||
 | 
					Fix spi-gpio for hotplug.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					--mb
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					--- a/drivers/spi/spi-gpio.c
 | 
				
			||||||
 | 
					+++ b/drivers/spi/spi-gpio.c
 | 
				
			||||||
 | 
					@@ -255,7 +255,7 @@ static void spi_gpio_cleanup(struct spi_
 | 
				
			||||||
 | 
					 	spi_bitbang_cleanup(spi);
 | 
				
			||||||
 | 
					 }
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					-static int __init spi_gpio_alloc(unsigned pin, const char *label, bool is_in)
 | 
				
			||||||
 | 
					+static int __devinit spi_gpio_alloc(unsigned pin, const char *label, bool is_in)
 | 
				
			||||||
 | 
					 {
 | 
				
			||||||
 | 
					 	int value;
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					@@ -269,7 +269,7 @@ static int __init spi_gpio_alloc(unsigne
 | 
				
			||||||
 | 
					 	return value;
 | 
				
			||||||
 | 
					 }
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					-static int __init
 | 
				
			||||||
 | 
					+static int __devinit
 | 
				
			||||||
 | 
					 spi_gpio_request(struct spi_gpio_platform_data *pdata, const char *label,
 | 
				
			||||||
 | 
					 	u16 *res_flags)
 | 
				
			||||||
 | 
					 {
 | 
				
			||||||
 | 
					@@ -311,7 +311,7 @@ done:
 | 
				
			||||||
 | 
					 	return value;
 | 
				
			||||||
 | 
					 }
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					-static int __init spi_gpio_probe(struct platform_device *pdev)
 | 
				
			||||||
 | 
					+static int __devinit spi_gpio_probe(struct platform_device *pdev)
 | 
				
			||||||
 | 
					 {
 | 
				
			||||||
 | 
					 	int				status;
 | 
				
			||||||
 | 
					 	struct spi_master		*master;
 | 
				
			||||||
 | 
					@@ -379,7 +379,7 @@ gpio_free:
 | 
				
			||||||
 | 
					 	return status;
 | 
				
			||||||
 | 
					 }
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					-static int __exit spi_gpio_remove(struct platform_device *pdev)
 | 
				
			||||||
 | 
					+static int __devexit spi_gpio_remove(struct platform_device *pdev)
 | 
				
			||||||
 | 
					 {
 | 
				
			||||||
 | 
					 	struct spi_gpio			*spi_gpio;
 | 
				
			||||||
 | 
					 	struct spi_gpio_platform_data	*pdata;
 | 
				
			||||||
 | 
					@@ -408,12 +408,13 @@ MODULE_ALIAS("platform:" DRIVER_NAME);
 | 
				
			||||||
 | 
					 static struct platform_driver spi_gpio_driver = {
 | 
				
			||||||
 | 
					 	.driver.name	= DRIVER_NAME,
 | 
				
			||||||
 | 
					 	.driver.owner	= THIS_MODULE,
 | 
				
			||||||
 | 
					-	.remove		= __exit_p(spi_gpio_remove),
 | 
				
			||||||
 | 
					+	.probe		= spi_gpio_probe,
 | 
				
			||||||
 | 
					+	.remove		= __devexit_p(spi_gpio_remove),
 | 
				
			||||||
 | 
					 };
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 static int __init spi_gpio_init(void)
 | 
				
			||||||
 | 
					 {
 | 
				
			||||||
 | 
					-	return platform_driver_probe(&spi_gpio_driver, spi_gpio_probe);
 | 
				
			||||||
 | 
					+	return platform_driver_register(&spi_gpio_driver);
 | 
				
			||||||
 | 
					 }
 | 
				
			||||||
 | 
					 module_init(spi_gpio_init);
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
@@ -0,0 +1,58 @@
 | 
				
			|||||||
 | 
					Implement the SPI-GPIO delay function for busses that need speed limitation.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					--mb
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					--- a/drivers/spi/spi-gpio.c
 | 
				
			||||||
 | 
					+++ b/drivers/spi/spi-gpio.c
 | 
				
			||||||
 | 
					@@ -21,6 +21,7 @@
 | 
				
			||||||
 | 
					 #include <linux/init.h>
 | 
				
			||||||
 | 
					 #include <linux/platform_device.h>
 | 
				
			||||||
 | 
					 #include <linux/gpio.h>
 | 
				
			||||||
 | 
					+#include <linux/delay.h>
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 #include <linux/spi/spi.h>
 | 
				
			||||||
 | 
					 #include <linux/spi/spi_bitbang.h>
 | 
				
			||||||
 | 
					@@ -69,6 +70,7 @@ struct spi_gpio {
 | 
				
			||||||
 | 
					  *		#define	SPI_MOSI_GPIO	120
 | 
				
			||||||
 | 
					  *		#define	SPI_SCK_GPIO	121
 | 
				
			||||||
 | 
					  *		#define	SPI_N_CHIPSEL	4
 | 
				
			||||||
 | 
					+ *		#undef NEED_SPIDELAY
 | 
				
			||||||
 | 
					  *		#include "spi-gpio.c"
 | 
				
			||||||
 | 
					  */
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					@@ -76,6 +78,7 @@ struct spi_gpio {
 | 
				
			||||||
 | 
					 #define DRIVER_NAME	"spi_gpio"
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 #define GENERIC_BITBANG	/* vs tight inlines */
 | 
				
			||||||
 | 
					+#define NEED_SPIDELAY	1
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 /* all functions referencing these symbols must define pdata */
 | 
				
			||||||
 | 
					 #define SPI_MISO_GPIO	((pdata)->miso)
 | 
				
			||||||
 | 
					@@ -120,12 +123,20 @@ static inline int getmiso(const struct s
 | 
				
			||||||
 | 
					 #undef pdata
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 /*
 | 
				
			||||||
 | 
					- * NOTE:  this clocks "as fast as we can".  It "should" be a function of the
 | 
				
			||||||
 | 
					- * requested device clock.  Software overhead means we usually have trouble
 | 
				
			||||||
 | 
					- * reaching even one Mbit/sec (except when we can inline bitops), so for now
 | 
				
			||||||
 | 
					- * we'll just assume we never need additional per-bit slowdowns.
 | 
				
			||||||
 | 
					+ * NOTE:  to clock "as fast as we can", set spi_device.max_speed_hz
 | 
				
			||||||
 | 
					+ * and spi_transfer.speed_hz to 0.
 | 
				
			||||||
 | 
					+ * Otherwise this is a function of the requested device clock.
 | 
				
			||||||
 | 
					+ * Software overhead means we usually have trouble
 | 
				
			||||||
 | 
					+ * reaching even one Mbit/sec (except when we can inline bitops). So on small
 | 
				
			||||||
 | 
					+ * embedded devices with fast SPI slaves you usually don't need a delay.
 | 
				
			||||||
 | 
					  */
 | 
				
			||||||
 | 
					-#define spidelay(nsecs)	do {} while (0)
 | 
				
			||||||
 | 
					+static inline void spidelay(unsigned nsecs)
 | 
				
			||||||
 | 
					+{
 | 
				
			||||||
 | 
					+#ifdef NEED_SPIDELAY
 | 
				
			||||||
 | 
					+	if (unlikely(nsecs))
 | 
				
			||||||
 | 
					+		ndelay(nsecs);
 | 
				
			||||||
 | 
					+#endif /* NEED_SPIDELAY */
 | 
				
			||||||
 | 
					+}
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 #include "spi-bitbang-txrx.h"
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
							
								
								
									
										373
									
								
								target/linux/generic/patches-3.1/862-gpio_spi_driver.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										373
									
								
								target/linux/generic/patches-3.1/862-gpio_spi_driver.patch
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,373 @@
 | 
				
			|||||||
 | 
					THIS CODE IS DEPRECATED.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Please use the new mainline SPI-GPIO driver, as of 2.6.29.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					--mb
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					---
 | 
				
			||||||
 | 
					 drivers/spi/Kconfig              |    9 +
 | 
				
			||||||
 | 
					 drivers/spi/Makefile             |    1 
 | 
				
			||||||
 | 
					 drivers/spi/spi_gpio_old.c       |  251 +++++++++++++++++++++++++++++++++++++++
 | 
				
			||||||
 | 
					 include/linux/spi/spi_gpio_old.h |   73 +++++++++++
 | 
				
			||||||
 | 
					 4 files changed, 334 insertions(+)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					--- /dev/null
 | 
				
			||||||
 | 
					+++ b/include/linux/spi/spi_gpio_old.h
 | 
				
			||||||
 | 
					@@ -0,0 +1,73 @@
 | 
				
			||||||
 | 
					+/*
 | 
				
			||||||
 | 
					+ * spi_gpio interface to platform code
 | 
				
			||||||
 | 
					+ *
 | 
				
			||||||
 | 
					+ * Copyright (c) 2008 Piotr Skamruk
 | 
				
			||||||
 | 
					+ * Copyright (c) 2008 Michael Buesch
 | 
				
			||||||
 | 
					+ *
 | 
				
			||||||
 | 
					+ * 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.
 | 
				
			||||||
 | 
					+ */
 | 
				
			||||||
 | 
					+#ifndef _LINUX_SPI_SPI_GPIO
 | 
				
			||||||
 | 
					+#define _LINUX_SPI_SPI_GPIO
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+#include <linux/types.h>
 | 
				
			||||||
 | 
					+#include <linux/spi/spi.h>
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+/**
 | 
				
			||||||
 | 
					+ * struct spi_gpio_platform_data - Data definitions for a SPI-GPIO device.
 | 
				
			||||||
 | 
					+ *
 | 
				
			||||||
 | 
					+ * This structure holds information about a GPIO-based SPI device.
 | 
				
			||||||
 | 
					+ *
 | 
				
			||||||
 | 
					+ * @pin_clk: The GPIO pin number of the CLOCK pin.
 | 
				
			||||||
 | 
					+ *
 | 
				
			||||||
 | 
					+ * @pin_miso: The GPIO pin number of the MISO pin.
 | 
				
			||||||
 | 
					+ *
 | 
				
			||||||
 | 
					+ * @pin_mosi: The GPIO pin number of the MOSI pin.
 | 
				
			||||||
 | 
					+ *
 | 
				
			||||||
 | 
					+ * @pin_cs: The GPIO pin number of the CHIPSELECT pin.
 | 
				
			||||||
 | 
					+ *
 | 
				
			||||||
 | 
					+ * @cs_activelow: If true, the chip is selected when the CS line is low.
 | 
				
			||||||
 | 
					+ *
 | 
				
			||||||
 | 
					+ * @no_spi_delay: If true, no delay is done in the lowlevel bitbanging.
 | 
				
			||||||
 | 
					+ *                Note that doing no delay is not standards compliant,
 | 
				
			||||||
 | 
					+ *                but it might be needed to speed up transfers on some
 | 
				
			||||||
 | 
					+ *                slow embedded machines.
 | 
				
			||||||
 | 
					+ *
 | 
				
			||||||
 | 
					+ * @boardinfo_setup: This callback is called after the
 | 
				
			||||||
 | 
					+ *                   SPI master device was registered, but before the
 | 
				
			||||||
 | 
					+ *                   device is registered.
 | 
				
			||||||
 | 
					+ * @boardinfo_setup_data: Data argument passed to boardinfo_setup().
 | 
				
			||||||
 | 
					+ */
 | 
				
			||||||
 | 
					+struct spi_gpio_platform_data {
 | 
				
			||||||
 | 
					+	unsigned int pin_clk;
 | 
				
			||||||
 | 
					+	unsigned int pin_miso;
 | 
				
			||||||
 | 
					+	unsigned int pin_mosi;
 | 
				
			||||||
 | 
					+	unsigned int pin_cs;
 | 
				
			||||||
 | 
					+	bool cs_activelow;
 | 
				
			||||||
 | 
					+	bool no_spi_delay;
 | 
				
			||||||
 | 
					+	int (*boardinfo_setup)(struct spi_board_info *bi,
 | 
				
			||||||
 | 
					+			       struct spi_master *master,
 | 
				
			||||||
 | 
					+			       void *data);
 | 
				
			||||||
 | 
					+	void *boardinfo_setup_data;
 | 
				
			||||||
 | 
					+};
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+/**
 | 
				
			||||||
 | 
					+ * SPI_GPIO_PLATDEV_NAME - The platform device name string.
 | 
				
			||||||
 | 
					+ *
 | 
				
			||||||
 | 
					+ * The name string that has to be used for platform_device_alloc
 | 
				
			||||||
 | 
					+ * when allocating a spi-gpio device.
 | 
				
			||||||
 | 
					+ */
 | 
				
			||||||
 | 
					+#define SPI_GPIO_PLATDEV_NAME	"spi-gpio"
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+/**
 | 
				
			||||||
 | 
					+ * spi_gpio_next_id - Get another platform device ID number.
 | 
				
			||||||
 | 
					+ *
 | 
				
			||||||
 | 
					+ * This returns the next platform device ID number that has to be used
 | 
				
			||||||
 | 
					+ * for platform_device_alloc. The ID is opaque and should not be used for
 | 
				
			||||||
 | 
					+ * anything else.
 | 
				
			||||||
 | 
					+ */
 | 
				
			||||||
 | 
					+int spi_gpio_next_id(void);
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+#endif /* _LINUX_SPI_SPI_GPIO */
 | 
				
			||||||
 | 
					--- /dev/null
 | 
				
			||||||
 | 
					+++ b/drivers/spi/spi_gpio_old.c
 | 
				
			||||||
 | 
					@@ -0,0 +1,251 @@
 | 
				
			||||||
 | 
					+/*
 | 
				
			||||||
 | 
					+ * Bitbanging SPI bus driver using GPIO API
 | 
				
			||||||
 | 
					+ *
 | 
				
			||||||
 | 
					+ * Copyright (c) 2008 Piotr Skamruk
 | 
				
			||||||
 | 
					+ * Copyright (c) 2008 Michael Buesch
 | 
				
			||||||
 | 
					+ *
 | 
				
			||||||
 | 
					+ * based on spi_s3c2410_gpio.c
 | 
				
			||||||
 | 
					+ *   Copyright (c) 2006 Ben Dooks
 | 
				
			||||||
 | 
					+ *   Copyright (c) 2006 Simtec Electronics
 | 
				
			||||||
 | 
					+ * and on i2c-gpio.c
 | 
				
			||||||
 | 
					+ *   Copyright (C) 2007 Atmel Corporation
 | 
				
			||||||
 | 
					+ *
 | 
				
			||||||
 | 
					+ * 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/kernel.h>
 | 
				
			||||||
 | 
					+#include <linux/init.h>
 | 
				
			||||||
 | 
					+#include <linux/delay.h>
 | 
				
			||||||
 | 
					+#include <linux/spinlock.h>
 | 
				
			||||||
 | 
					+#include <linux/workqueue.h>
 | 
				
			||||||
 | 
					+#include <linux/module.h>
 | 
				
			||||||
 | 
					+#include <linux/platform_device.h>
 | 
				
			||||||
 | 
					+#include <linux/spi/spi.h>
 | 
				
			||||||
 | 
					+#include <linux/spi/spi_bitbang.h>
 | 
				
			||||||
 | 
					+#include <linux/spi/spi_gpio_old.h>
 | 
				
			||||||
 | 
					+#include <linux/gpio.h>
 | 
				
			||||||
 | 
					+#include <asm/atomic.h>
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+struct spi_gpio {
 | 
				
			||||||
 | 
					+	struct spi_bitbang bitbang;
 | 
				
			||||||
 | 
					+	struct spi_gpio_platform_data *info;
 | 
				
			||||||
 | 
					+	struct platform_device *pdev;
 | 
				
			||||||
 | 
					+	struct spi_board_info bi;
 | 
				
			||||||
 | 
					+};
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+static inline struct spi_gpio *spidev_to_sg(struct spi_device *dev)
 | 
				
			||||||
 | 
					+{
 | 
				
			||||||
 | 
					+	return dev->controller_data;
 | 
				
			||||||
 | 
					+}
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+static inline void setsck(struct spi_device *dev, int val)
 | 
				
			||||||
 | 
					+{
 | 
				
			||||||
 | 
					+	struct spi_gpio *sp = spidev_to_sg(dev);
 | 
				
			||||||
 | 
					+	gpio_set_value(sp->info->pin_clk, val ? 1 : 0);
 | 
				
			||||||
 | 
					+}
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+static inline void setmosi(struct spi_device *dev, int val)
 | 
				
			||||||
 | 
					+{
 | 
				
			||||||
 | 
					+	struct spi_gpio *sp = spidev_to_sg(dev);
 | 
				
			||||||
 | 
					+	gpio_set_value(sp->info->pin_mosi, val ? 1 : 0);
 | 
				
			||||||
 | 
					+}
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+static inline u32 getmiso(struct spi_device *dev)
 | 
				
			||||||
 | 
					+{
 | 
				
			||||||
 | 
					+	struct spi_gpio *sp = spidev_to_sg(dev);
 | 
				
			||||||
 | 
					+	return gpio_get_value(sp->info->pin_miso) ? 1 : 0;
 | 
				
			||||||
 | 
					+}
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+static inline void do_spidelay(struct spi_device *dev, unsigned nsecs)
 | 
				
			||||||
 | 
					+{
 | 
				
			||||||
 | 
					+	struct spi_gpio *sp = spidev_to_sg(dev);
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	if (!sp->info->no_spi_delay)
 | 
				
			||||||
 | 
					+		ndelay(nsecs);
 | 
				
			||||||
 | 
					+}
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+#define spidelay(nsecs) do {					\
 | 
				
			||||||
 | 
					+	/* Steal the spi_device pointer from our caller.	\
 | 
				
			||||||
 | 
					+	 * The bitbang-API should probably get fixed here... */	\
 | 
				
			||||||
 | 
					+	do_spidelay(spi, nsecs);				\
 | 
				
			||||||
 | 
					+  } while (0)
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+#define EXPAND_BITBANG_TXRX
 | 
				
			||||||
 | 
					+#include "spi-bitbang-txrx.h"
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+static u32 spi_gpio_txrx_mode0(struct spi_device *spi,
 | 
				
			||||||
 | 
					+			       unsigned nsecs, u32 word, u8 bits)
 | 
				
			||||||
 | 
					+{
 | 
				
			||||||
 | 
					+	return bitbang_txrx_be_cpha0(spi, nsecs, 0, 0, word, bits);
 | 
				
			||||||
 | 
					+}
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+static u32 spi_gpio_txrx_mode1(struct spi_device *spi,
 | 
				
			||||||
 | 
					+			       unsigned nsecs, u32 word, u8 bits)
 | 
				
			||||||
 | 
					+{
 | 
				
			||||||
 | 
					+	return bitbang_txrx_be_cpha1(spi, nsecs, 0, 0, word, bits);
 | 
				
			||||||
 | 
					+}
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+static u32 spi_gpio_txrx_mode2(struct spi_device *spi,
 | 
				
			||||||
 | 
					+			       unsigned nsecs, u32 word, u8 bits)
 | 
				
			||||||
 | 
					+{
 | 
				
			||||||
 | 
					+	return bitbang_txrx_be_cpha0(spi, nsecs, 1, 0, word, bits);
 | 
				
			||||||
 | 
					+}
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+static u32 spi_gpio_txrx_mode3(struct spi_device *spi,
 | 
				
			||||||
 | 
					+			       unsigned nsecs, u32 word, u8 bits)
 | 
				
			||||||
 | 
					+{
 | 
				
			||||||
 | 
					+	return bitbang_txrx_be_cpha1(spi, nsecs, 1, 0, word, bits);
 | 
				
			||||||
 | 
					+}
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+static void spi_gpio_chipselect(struct spi_device *dev, int on)
 | 
				
			||||||
 | 
					+{
 | 
				
			||||||
 | 
					+	struct spi_gpio *sp = spidev_to_sg(dev);
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	if (sp->info->cs_activelow)
 | 
				
			||||||
 | 
					+		on = !on;
 | 
				
			||||||
 | 
					+	gpio_set_value(sp->info->pin_cs, on ? 1 : 0);
 | 
				
			||||||
 | 
					+}
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+static int spi_gpio_probe(struct platform_device *pdev)
 | 
				
			||||||
 | 
					+{
 | 
				
			||||||
 | 
					+	struct spi_master *master;
 | 
				
			||||||
 | 
					+	struct spi_gpio_platform_data *pdata;
 | 
				
			||||||
 | 
					+	struct spi_gpio *sp;
 | 
				
			||||||
 | 
					+	struct spi_device *spidev;
 | 
				
			||||||
 | 
					+	int err;
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	pdata = pdev->dev.platform_data;
 | 
				
			||||||
 | 
					+	if (!pdata)
 | 
				
			||||||
 | 
					+		return -ENXIO;
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	err = -ENOMEM;
 | 
				
			||||||
 | 
					+	master = spi_alloc_master(&pdev->dev, sizeof(struct spi_gpio));
 | 
				
			||||||
 | 
					+	if (!master)
 | 
				
			||||||
 | 
					+		goto err_alloc_master;
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	sp = spi_master_get_devdata(master);
 | 
				
			||||||
 | 
					+	platform_set_drvdata(pdev, sp);
 | 
				
			||||||
 | 
					+	sp->info = pdata;
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	err = gpio_request(pdata->pin_clk, "spi_clock");
 | 
				
			||||||
 | 
					+	if (err)
 | 
				
			||||||
 | 
					+		goto err_request_clk;
 | 
				
			||||||
 | 
					+	err = gpio_request(pdata->pin_mosi, "spi_mosi");
 | 
				
			||||||
 | 
					+	if (err)
 | 
				
			||||||
 | 
					+		goto err_request_mosi;
 | 
				
			||||||
 | 
					+	err = gpio_request(pdata->pin_miso, "spi_miso");
 | 
				
			||||||
 | 
					+	if (err)
 | 
				
			||||||
 | 
					+		goto err_request_miso;
 | 
				
			||||||
 | 
					+	err = gpio_request(pdata->pin_cs, "spi_cs");
 | 
				
			||||||
 | 
					+	if (err)
 | 
				
			||||||
 | 
					+		goto err_request_cs;
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	sp->bitbang.master = spi_master_get(master);
 | 
				
			||||||
 | 
					+	sp->bitbang.master->bus_num = -1;
 | 
				
			||||||
 | 
					+	sp->bitbang.master->num_chipselect = 1;
 | 
				
			||||||
 | 
					+	sp->bitbang.chipselect = spi_gpio_chipselect;
 | 
				
			||||||
 | 
					+	sp->bitbang.txrx_word[SPI_MODE_0] = spi_gpio_txrx_mode0;
 | 
				
			||||||
 | 
					+	sp->bitbang.txrx_word[SPI_MODE_1] = spi_gpio_txrx_mode1;
 | 
				
			||||||
 | 
					+	sp->bitbang.txrx_word[SPI_MODE_2] = spi_gpio_txrx_mode2;
 | 
				
			||||||
 | 
					+	sp->bitbang.txrx_word[SPI_MODE_3] = spi_gpio_txrx_mode3;
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	gpio_direction_output(pdata->pin_clk, 0);
 | 
				
			||||||
 | 
					+	gpio_direction_output(pdata->pin_mosi, 0);
 | 
				
			||||||
 | 
					+	gpio_direction_output(pdata->pin_cs,
 | 
				
			||||||
 | 
					+			      pdata->cs_activelow ? 1 : 0);
 | 
				
			||||||
 | 
					+	gpio_direction_input(pdata->pin_miso);
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	err = spi_bitbang_start(&sp->bitbang);
 | 
				
			||||||
 | 
					+	if (err)
 | 
				
			||||||
 | 
					+		goto err_no_bitbang;
 | 
				
			||||||
 | 
					+	err = pdata->boardinfo_setup(&sp->bi, master,
 | 
				
			||||||
 | 
					+				     pdata->boardinfo_setup_data);
 | 
				
			||||||
 | 
					+	if (err)
 | 
				
			||||||
 | 
					+		goto err_bi_setup;
 | 
				
			||||||
 | 
					+	sp->bi.controller_data = sp;
 | 
				
			||||||
 | 
					+	spidev = spi_new_device(master, &sp->bi);
 | 
				
			||||||
 | 
					+	if (!spidev)
 | 
				
			||||||
 | 
					+		goto err_new_dev;
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	return 0;
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+err_new_dev:
 | 
				
			||||||
 | 
					+err_bi_setup:
 | 
				
			||||||
 | 
					+	spi_bitbang_stop(&sp->bitbang);
 | 
				
			||||||
 | 
					+err_no_bitbang:
 | 
				
			||||||
 | 
					+	spi_master_put(sp->bitbang.master);
 | 
				
			||||||
 | 
					+	gpio_free(pdata->pin_cs);
 | 
				
			||||||
 | 
					+err_request_cs:
 | 
				
			||||||
 | 
					+	gpio_free(pdata->pin_miso);
 | 
				
			||||||
 | 
					+err_request_miso:
 | 
				
			||||||
 | 
					+	gpio_free(pdata->pin_mosi);
 | 
				
			||||||
 | 
					+err_request_mosi:
 | 
				
			||||||
 | 
					+	gpio_free(pdata->pin_clk);
 | 
				
			||||||
 | 
					+err_request_clk:
 | 
				
			||||||
 | 
					+	kfree(master);
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+err_alloc_master:
 | 
				
			||||||
 | 
					+	return err;
 | 
				
			||||||
 | 
					+}
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+static int __devexit spi_gpio_remove(struct platform_device *pdev)
 | 
				
			||||||
 | 
					+{
 | 
				
			||||||
 | 
					+	struct spi_gpio *sp;
 | 
				
			||||||
 | 
					+	struct spi_gpio_platform_data *pdata;
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	pdata = pdev->dev.platform_data;
 | 
				
			||||||
 | 
					+	sp = platform_get_drvdata(pdev);
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	gpio_free(pdata->pin_clk);
 | 
				
			||||||
 | 
					+	gpio_free(pdata->pin_mosi);
 | 
				
			||||||
 | 
					+	gpio_free(pdata->pin_miso);
 | 
				
			||||||
 | 
					+	gpio_free(pdata->pin_cs);
 | 
				
			||||||
 | 
					+	spi_bitbang_stop(&sp->bitbang);
 | 
				
			||||||
 | 
					+	spi_master_put(sp->bitbang.master);
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	return 0;
 | 
				
			||||||
 | 
					+}
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+static struct platform_driver spi_gpio_driver = {
 | 
				
			||||||
 | 
					+	.driver		= {
 | 
				
			||||||
 | 
					+		.name	= SPI_GPIO_PLATDEV_NAME,
 | 
				
			||||||
 | 
					+		.owner	= THIS_MODULE,
 | 
				
			||||||
 | 
					+	},
 | 
				
			||||||
 | 
					+	.probe		= spi_gpio_probe,
 | 
				
			||||||
 | 
					+	.remove		= __devexit_p(spi_gpio_remove),
 | 
				
			||||||
 | 
					+};
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+int spi_gpio_next_id(void)
 | 
				
			||||||
 | 
					+{
 | 
				
			||||||
 | 
					+	static atomic_t counter = ATOMIC_INIT(-1);
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	return atomic_inc_return(&counter);
 | 
				
			||||||
 | 
					+}
 | 
				
			||||||
 | 
					+EXPORT_SYMBOL(spi_gpio_next_id);
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+static int __init spi_gpio_init(void)
 | 
				
			||||||
 | 
					+{
 | 
				
			||||||
 | 
					+	int err;
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	err = platform_driver_register(&spi_gpio_driver);
 | 
				
			||||||
 | 
					+	if (err)
 | 
				
			||||||
 | 
					+		printk(KERN_ERR "spi-gpio: register failed: %d\n", err);
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	return err;
 | 
				
			||||||
 | 
					+}
 | 
				
			||||||
 | 
					+module_init(spi_gpio_init);
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+static void __exit spi_gpio_exit(void)
 | 
				
			||||||
 | 
					+{
 | 
				
			||||||
 | 
					+	platform_driver_unregister(&spi_gpio_driver);
 | 
				
			||||||
 | 
					+}
 | 
				
			||||||
 | 
					+module_exit(spi_gpio_exit);
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+MODULE_AUTHOR("Piot Skamruk <piotr.skamruk at gmail.com>");
 | 
				
			||||||
 | 
					+MODULE_AUTHOR("Michael Buesch");
 | 
				
			||||||
 | 
					+MODULE_DESCRIPTION("Platform independent GPIO bitbanging SPI driver");
 | 
				
			||||||
 | 
					+MODULE_LICENSE("GPL v2");
 | 
				
			||||||
 | 
					--- a/drivers/spi/Kconfig
 | 
				
			||||||
 | 
					+++ b/drivers/spi/Kconfig
 | 
				
			||||||
 | 
					@@ -154,6 +154,15 @@ config SPI_GPIO
 | 
				
			||||||
 | 
					 	  GPIO operations, you should be able to leverage that for better
 | 
				
			||||||
 | 
					 	  speed with a custom version of this driver; see the source code.
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					+config SPI_GPIO_OLD
 | 
				
			||||||
 | 
					+	tristate "Old GPIO API based bitbanging SPI controller (DEPRECATED)"
 | 
				
			||||||
 | 
					+	depends on SPI_MASTER && GENERIC_GPIO
 | 
				
			||||||
 | 
					+	select SPI_BITBANG
 | 
				
			||||||
 | 
					+	help
 | 
				
			||||||
 | 
					+	  This code is deprecated. Please use the new mainline SPI-GPIO driver.
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	  If unsure, say N.
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					 config SPI_IMX
 | 
				
			||||||
 | 
					 	tristate "Freescale i.MX SPI controllers"
 | 
				
			||||||
 | 
					 	depends on ARCH_MXC
 | 
				
			||||||
 | 
					--- a/drivers/spi/Makefile
 | 
				
			||||||
 | 
					+++ b/drivers/spi/Makefile
 | 
				
			||||||
 | 
					@@ -29,6 +29,7 @@ obj-$(CONFIG_SPI_FSL_LIB)		+= spi-fsl-li
 | 
				
			||||||
 | 
					 obj-$(CONFIG_SPI_FSL_ESPI)		+= spi-fsl-espi.o
 | 
				
			||||||
 | 
					 obj-$(CONFIG_SPI_FSL_SPI)		+= spi-fsl-spi.o
 | 
				
			||||||
 | 
					 obj-$(CONFIG_SPI_GPIO)			+= spi-gpio.o
 | 
				
			||||||
 | 
					+obj-$(CONFIG_SPI_GPIO_OLD)		+= spi_gpio_old.o
 | 
				
			||||||
 | 
					 obj-$(CONFIG_SPI_IMX)			+= spi-imx.o
 | 
				
			||||||
 | 
					 obj-$(CONFIG_SPI_LM70_LLP)		+= spi-lm70llp.o
 | 
				
			||||||
 | 
					 obj-$(CONFIG_SPI_MPC512x_PSC)		+= spi-mpc512x-psc.o
 | 
				
			||||||
							
								
								
									
										843
									
								
								target/linux/generic/patches-3.1/863-gpiommc.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										843
									
								
								target/linux/generic/patches-3.1/863-gpiommc.patch
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,843 @@
 | 
				
			|||||||
 | 
					--- /dev/null
 | 
				
			||||||
 | 
					+++ b/drivers/mmc/host/gpiommc.c
 | 
				
			||||||
 | 
					@@ -0,0 +1,608 @@
 | 
				
			||||||
 | 
					+/*
 | 
				
			||||||
 | 
					+ * Driver an MMC/SD card on a bitbanging GPIO SPI bus.
 | 
				
			||||||
 | 
					+ * This module hooks up the mmc_spi and spi_gpio modules and also
 | 
				
			||||||
 | 
					+ * provides a configfs interface.
 | 
				
			||||||
 | 
					+ *
 | 
				
			||||||
 | 
					+ * Copyright 2008 Michael Buesch <mb@bu3sch.de>
 | 
				
			||||||
 | 
					+ *
 | 
				
			||||||
 | 
					+ * Licensed under the GNU/GPL. See COPYING for details.
 | 
				
			||||||
 | 
					+ */
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+#include <linux/mmc/gpiommc.h>
 | 
				
			||||||
 | 
					+#include <linux/platform_device.h>
 | 
				
			||||||
 | 
					+#include <linux/list.h>
 | 
				
			||||||
 | 
					+#include <linux/mutex.h>
 | 
				
			||||||
 | 
					+#include <linux/spi/spi_gpio_old.h>
 | 
				
			||||||
 | 
					+#include <linux/configfs.h>
 | 
				
			||||||
 | 
					+#include <linux/gpio.h>
 | 
				
			||||||
 | 
					+#include <asm/atomic.h>
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+#define PFX				"gpio-mmc: "
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+struct gpiommc_device {
 | 
				
			||||||
 | 
					+	struct platform_device *pdev;
 | 
				
			||||||
 | 
					+	struct platform_device *spi_pdev;
 | 
				
			||||||
 | 
					+	struct spi_board_info boardinfo;
 | 
				
			||||||
 | 
					+};
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+MODULE_DESCRIPTION("GPIO based MMC driver");
 | 
				
			||||||
 | 
					+MODULE_AUTHOR("Michael Buesch");
 | 
				
			||||||
 | 
					+MODULE_LICENSE("GPL");
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+static int gpiommc_boardinfo_setup(struct spi_board_info *bi,
 | 
				
			||||||
 | 
					+				   struct spi_master *master,
 | 
				
			||||||
 | 
					+				   void *data)
 | 
				
			||||||
 | 
					+{
 | 
				
			||||||
 | 
					+	struct gpiommc_device *d = data;
 | 
				
			||||||
 | 
					+	struct gpiommc_platform_data *pdata = d->pdev->dev.platform_data;
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	/* Bind the SPI master to the MMC-SPI host driver. */
 | 
				
			||||||
 | 
					+	strlcpy(bi->modalias, "mmc_spi", sizeof(bi->modalias));
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	bi->max_speed_hz = pdata->max_bus_speed;
 | 
				
			||||||
 | 
					+	bi->bus_num = master->bus_num;
 | 
				
			||||||
 | 
					+	bi->mode = pdata->mode;
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	return 0;
 | 
				
			||||||
 | 
					+}
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+static int gpiommc_probe(struct platform_device *pdev)
 | 
				
			||||||
 | 
					+{
 | 
				
			||||||
 | 
					+	struct gpiommc_platform_data *mmc_pdata = pdev->dev.platform_data;
 | 
				
			||||||
 | 
					+	struct spi_gpio_platform_data spi_pdata;
 | 
				
			||||||
 | 
					+	struct gpiommc_device *d;
 | 
				
			||||||
 | 
					+	int err;
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	err = -ENXIO;
 | 
				
			||||||
 | 
					+	if (!mmc_pdata)
 | 
				
			||||||
 | 
					+		goto error;
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+#ifdef CONFIG_MMC_SPI_MODULE
 | 
				
			||||||
 | 
					+	err = request_module("mmc_spi");
 | 
				
			||||||
 | 
					+	if (err) {
 | 
				
			||||||
 | 
					+		printk(KERN_WARNING PFX
 | 
				
			||||||
 | 
					+		       "Failed to request mmc_spi module.\n");
 | 
				
			||||||
 | 
					+	}
 | 
				
			||||||
 | 
					+#endif /* CONFIG_MMC_SPI_MODULE */
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	/* Allocate the GPIO-MMC device */
 | 
				
			||||||
 | 
					+	err = -ENOMEM;
 | 
				
			||||||
 | 
					+	d = kzalloc(sizeof(*d), GFP_KERNEL);
 | 
				
			||||||
 | 
					+	if (!d)
 | 
				
			||||||
 | 
					+		goto error;
 | 
				
			||||||
 | 
					+	d->pdev = pdev;
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	/* Create the SPI-GPIO device */
 | 
				
			||||||
 | 
					+	d->spi_pdev = platform_device_alloc(SPI_GPIO_PLATDEV_NAME,
 | 
				
			||||||
 | 
					+					    spi_gpio_next_id());
 | 
				
			||||||
 | 
					+	if (!d->spi_pdev)
 | 
				
			||||||
 | 
					+		goto err_free_d;
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	memset(&spi_pdata, 0, sizeof(spi_pdata));
 | 
				
			||||||
 | 
					+	spi_pdata.pin_clk = mmc_pdata->pins.gpio_clk;
 | 
				
			||||||
 | 
					+	spi_pdata.pin_miso = mmc_pdata->pins.gpio_do;
 | 
				
			||||||
 | 
					+	spi_pdata.pin_mosi = mmc_pdata->pins.gpio_di;
 | 
				
			||||||
 | 
					+	spi_pdata.pin_cs = mmc_pdata->pins.gpio_cs;
 | 
				
			||||||
 | 
					+	spi_pdata.cs_activelow = mmc_pdata->pins.cs_activelow;
 | 
				
			||||||
 | 
					+	spi_pdata.no_spi_delay = mmc_pdata->no_spi_delay;
 | 
				
			||||||
 | 
					+	spi_pdata.boardinfo_setup = gpiommc_boardinfo_setup;
 | 
				
			||||||
 | 
					+	spi_pdata.boardinfo_setup_data = d;
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	err = platform_device_add_data(d->spi_pdev, &spi_pdata,
 | 
				
			||||||
 | 
					+				       sizeof(spi_pdata));
 | 
				
			||||||
 | 
					+	if (err)
 | 
				
			||||||
 | 
					+		goto err_free_pdev;
 | 
				
			||||||
 | 
					+	err = platform_device_add(d->spi_pdev);
 | 
				
			||||||
 | 
					+	if (err)
 | 
				
			||||||
 | 
					+		goto err_free_pdata;
 | 
				
			||||||
 | 
					+	platform_set_drvdata(pdev, d);
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	printk(KERN_INFO PFX "MMC-Card \"%s\" "
 | 
				
			||||||
 | 
					+	       "attached to GPIO pins di=%u, do=%u, clk=%u, cs=%u\n",
 | 
				
			||||||
 | 
					+	       mmc_pdata->name, mmc_pdata->pins.gpio_di,
 | 
				
			||||||
 | 
					+	       mmc_pdata->pins.gpio_do,
 | 
				
			||||||
 | 
					+	       mmc_pdata->pins.gpio_clk,
 | 
				
			||||||
 | 
					+	       mmc_pdata->pins.gpio_cs);
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	return 0;
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+err_free_pdata:
 | 
				
			||||||
 | 
					+	kfree(d->spi_pdev->dev.platform_data);
 | 
				
			||||||
 | 
					+	d->spi_pdev->dev.platform_data = NULL;
 | 
				
			||||||
 | 
					+err_free_pdev:
 | 
				
			||||||
 | 
					+	platform_device_put(d->spi_pdev);
 | 
				
			||||||
 | 
					+err_free_d:
 | 
				
			||||||
 | 
					+	kfree(d);
 | 
				
			||||||
 | 
					+error:
 | 
				
			||||||
 | 
					+	return err;
 | 
				
			||||||
 | 
					+}
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+static int gpiommc_remove(struct platform_device *pdev)
 | 
				
			||||||
 | 
					+{
 | 
				
			||||||
 | 
					+	struct gpiommc_device *d = platform_get_drvdata(pdev);
 | 
				
			||||||
 | 
					+	struct gpiommc_platform_data *pdata = d->pdev->dev.platform_data;
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	platform_device_unregister(d->spi_pdev);
 | 
				
			||||||
 | 
					+	printk(KERN_INFO PFX "GPIO based MMC-Card \"%s\" removed\n",
 | 
				
			||||||
 | 
					+	       pdata->name);
 | 
				
			||||||
 | 
					+	platform_device_put(d->spi_pdev);
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	return 0;
 | 
				
			||||||
 | 
					+}
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+#ifdef CONFIG_GPIOMMC_CONFIGFS
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+/* A device that was created through configfs */
 | 
				
			||||||
 | 
					+struct gpiommc_configfs_device {
 | 
				
			||||||
 | 
					+	struct config_item item;
 | 
				
			||||||
 | 
					+	/* The platform device, after registration. */
 | 
				
			||||||
 | 
					+	struct platform_device *pdev;
 | 
				
			||||||
 | 
					+	/* The configuration */
 | 
				
			||||||
 | 
					+	struct gpiommc_platform_data pdata;
 | 
				
			||||||
 | 
					+};
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+#define GPIO_INVALID	-1
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+static inline bool gpiommc_is_registered(struct gpiommc_configfs_device *dev)
 | 
				
			||||||
 | 
					+{
 | 
				
			||||||
 | 
					+	return (dev->pdev != NULL);
 | 
				
			||||||
 | 
					+}
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+static inline struct gpiommc_configfs_device *ci_to_gpiommc(struct config_item *item)
 | 
				
			||||||
 | 
					+{
 | 
				
			||||||
 | 
					+	return item ? container_of(item, struct gpiommc_configfs_device, item) : NULL;
 | 
				
			||||||
 | 
					+}
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+static struct configfs_attribute gpiommc_attr_DI = {
 | 
				
			||||||
 | 
					+	.ca_owner = THIS_MODULE,
 | 
				
			||||||
 | 
					+	.ca_name = "gpio_data_in",
 | 
				
			||||||
 | 
					+	.ca_mode = S_IRUGO | S_IWUSR,
 | 
				
			||||||
 | 
					+};
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+static struct configfs_attribute gpiommc_attr_DO = {
 | 
				
			||||||
 | 
					+	.ca_owner = THIS_MODULE,
 | 
				
			||||||
 | 
					+	.ca_name = "gpio_data_out",
 | 
				
			||||||
 | 
					+	.ca_mode = S_IRUGO | S_IWUSR,
 | 
				
			||||||
 | 
					+};
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+static struct configfs_attribute gpiommc_attr_CLK = {
 | 
				
			||||||
 | 
					+	.ca_owner = THIS_MODULE,
 | 
				
			||||||
 | 
					+	.ca_name = "gpio_clock",
 | 
				
			||||||
 | 
					+	.ca_mode = S_IRUGO | S_IWUSR,
 | 
				
			||||||
 | 
					+};
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+static struct configfs_attribute gpiommc_attr_CS = {
 | 
				
			||||||
 | 
					+	.ca_owner = THIS_MODULE,
 | 
				
			||||||
 | 
					+	.ca_name = "gpio_chipselect",
 | 
				
			||||||
 | 
					+	.ca_mode = S_IRUGO | S_IWUSR,
 | 
				
			||||||
 | 
					+};
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+static struct configfs_attribute gpiommc_attr_CS_activelow = {
 | 
				
			||||||
 | 
					+	.ca_owner = THIS_MODULE,
 | 
				
			||||||
 | 
					+	.ca_name = "gpio_chipselect_activelow",
 | 
				
			||||||
 | 
					+	.ca_mode = S_IRUGO | S_IWUSR,
 | 
				
			||||||
 | 
					+};
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+static struct configfs_attribute gpiommc_attr_spimode = {
 | 
				
			||||||
 | 
					+	.ca_owner = THIS_MODULE,
 | 
				
			||||||
 | 
					+	.ca_name = "spi_mode",
 | 
				
			||||||
 | 
					+	.ca_mode = S_IRUGO | S_IWUSR,
 | 
				
			||||||
 | 
					+};
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+static struct configfs_attribute gpiommc_attr_spidelay = {
 | 
				
			||||||
 | 
					+	.ca_owner = THIS_MODULE,
 | 
				
			||||||
 | 
					+	.ca_name = "spi_delay",
 | 
				
			||||||
 | 
					+	.ca_mode = S_IRUGO | S_IWUSR,
 | 
				
			||||||
 | 
					+};
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+static struct configfs_attribute gpiommc_attr_max_bus_speed = {
 | 
				
			||||||
 | 
					+	.ca_owner = THIS_MODULE,
 | 
				
			||||||
 | 
					+	.ca_name = "max_bus_speed",
 | 
				
			||||||
 | 
					+	.ca_mode = S_IRUGO | S_IWUSR,
 | 
				
			||||||
 | 
					+};
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+static struct configfs_attribute gpiommc_attr_register = {
 | 
				
			||||||
 | 
					+	.ca_owner = THIS_MODULE,
 | 
				
			||||||
 | 
					+	.ca_name = "register",
 | 
				
			||||||
 | 
					+	.ca_mode = S_IRUGO | S_IWUSR,
 | 
				
			||||||
 | 
					+};
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+static struct configfs_attribute *gpiommc_config_attrs[] = {
 | 
				
			||||||
 | 
					+	&gpiommc_attr_DI,
 | 
				
			||||||
 | 
					+	&gpiommc_attr_DO,
 | 
				
			||||||
 | 
					+	&gpiommc_attr_CLK,
 | 
				
			||||||
 | 
					+	&gpiommc_attr_CS,
 | 
				
			||||||
 | 
					+	&gpiommc_attr_CS_activelow,
 | 
				
			||||||
 | 
					+	&gpiommc_attr_spimode,
 | 
				
			||||||
 | 
					+	&gpiommc_attr_spidelay,
 | 
				
			||||||
 | 
					+	&gpiommc_attr_max_bus_speed,
 | 
				
			||||||
 | 
					+	&gpiommc_attr_register,
 | 
				
			||||||
 | 
					+	NULL,
 | 
				
			||||||
 | 
					+};
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+static ssize_t gpiommc_config_attr_show(struct config_item *item,
 | 
				
			||||||
 | 
					+					struct configfs_attribute *attr,
 | 
				
			||||||
 | 
					+					char *page)
 | 
				
			||||||
 | 
					+{
 | 
				
			||||||
 | 
					+	struct gpiommc_configfs_device *dev = ci_to_gpiommc(item);
 | 
				
			||||||
 | 
					+	ssize_t count = 0;
 | 
				
			||||||
 | 
					+	unsigned int gpio;
 | 
				
			||||||
 | 
					+	int err = 0;
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	if (attr == &gpiommc_attr_DI) {
 | 
				
			||||||
 | 
					+		gpio = dev->pdata.pins.gpio_di;
 | 
				
			||||||
 | 
					+		if (gpio == GPIO_INVALID)
 | 
				
			||||||
 | 
					+			count = snprintf(page, PAGE_SIZE, "not configured\n");
 | 
				
			||||||
 | 
					+		else
 | 
				
			||||||
 | 
					+			count = snprintf(page, PAGE_SIZE, "%u\n", gpio);
 | 
				
			||||||
 | 
					+		goto out;
 | 
				
			||||||
 | 
					+	}
 | 
				
			||||||
 | 
					+	if (attr == &gpiommc_attr_DO) {
 | 
				
			||||||
 | 
					+		gpio = dev->pdata.pins.gpio_do;
 | 
				
			||||||
 | 
					+		if (gpio == GPIO_INVALID)
 | 
				
			||||||
 | 
					+			count = snprintf(page, PAGE_SIZE, "not configured\n");
 | 
				
			||||||
 | 
					+		else
 | 
				
			||||||
 | 
					+			count = snprintf(page, PAGE_SIZE, "%u\n", gpio);
 | 
				
			||||||
 | 
					+		goto out;
 | 
				
			||||||
 | 
					+	}
 | 
				
			||||||
 | 
					+	if (attr == &gpiommc_attr_CLK) {
 | 
				
			||||||
 | 
					+		gpio = dev->pdata.pins.gpio_clk;
 | 
				
			||||||
 | 
					+		if (gpio == GPIO_INVALID)
 | 
				
			||||||
 | 
					+			count = snprintf(page, PAGE_SIZE, "not configured\n");
 | 
				
			||||||
 | 
					+		else
 | 
				
			||||||
 | 
					+			count = snprintf(page, PAGE_SIZE, "%u\n", gpio);
 | 
				
			||||||
 | 
					+		goto out;
 | 
				
			||||||
 | 
					+	}
 | 
				
			||||||
 | 
					+	if (attr == &gpiommc_attr_CS) {
 | 
				
			||||||
 | 
					+		gpio = dev->pdata.pins.gpio_cs;
 | 
				
			||||||
 | 
					+		if (gpio == GPIO_INVALID)
 | 
				
			||||||
 | 
					+			count = snprintf(page, PAGE_SIZE, "not configured\n");
 | 
				
			||||||
 | 
					+		else
 | 
				
			||||||
 | 
					+			count = snprintf(page, PAGE_SIZE, "%u\n", gpio);
 | 
				
			||||||
 | 
					+		goto out;
 | 
				
			||||||
 | 
					+	}
 | 
				
			||||||
 | 
					+	if (attr == &gpiommc_attr_CS_activelow) {
 | 
				
			||||||
 | 
					+		count = snprintf(page, PAGE_SIZE, "%u\n",
 | 
				
			||||||
 | 
					+				 dev->pdata.pins.cs_activelow);
 | 
				
			||||||
 | 
					+		goto out;
 | 
				
			||||||
 | 
					+	}
 | 
				
			||||||
 | 
					+	if (attr == &gpiommc_attr_spimode) {
 | 
				
			||||||
 | 
					+		count = snprintf(page, PAGE_SIZE, "%u\n",
 | 
				
			||||||
 | 
					+				 dev->pdata.mode);
 | 
				
			||||||
 | 
					+		goto out;
 | 
				
			||||||
 | 
					+	}
 | 
				
			||||||
 | 
					+	if (attr == &gpiommc_attr_spidelay) {
 | 
				
			||||||
 | 
					+		count = snprintf(page, PAGE_SIZE, "%u\n",
 | 
				
			||||||
 | 
					+				 !dev->pdata.no_spi_delay);
 | 
				
			||||||
 | 
					+		goto out;
 | 
				
			||||||
 | 
					+	}
 | 
				
			||||||
 | 
					+	if (attr == &gpiommc_attr_max_bus_speed) {
 | 
				
			||||||
 | 
					+		count = snprintf(page, PAGE_SIZE, "%u\n",
 | 
				
			||||||
 | 
					+				 dev->pdata.max_bus_speed);
 | 
				
			||||||
 | 
					+		goto out;
 | 
				
			||||||
 | 
					+	}
 | 
				
			||||||
 | 
					+	if (attr == &gpiommc_attr_register) {
 | 
				
			||||||
 | 
					+		count = snprintf(page, PAGE_SIZE, "%u\n",
 | 
				
			||||||
 | 
					+				 gpiommc_is_registered(dev));
 | 
				
			||||||
 | 
					+		goto out;
 | 
				
			||||||
 | 
					+	}
 | 
				
			||||||
 | 
					+	WARN_ON(1);
 | 
				
			||||||
 | 
					+	err = -ENOSYS;
 | 
				
			||||||
 | 
					+out:
 | 
				
			||||||
 | 
					+	return err ? err : count;
 | 
				
			||||||
 | 
					+}
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+static int gpiommc_do_register(struct gpiommc_configfs_device *dev,
 | 
				
			||||||
 | 
					+			       const char *name)
 | 
				
			||||||
 | 
					+{
 | 
				
			||||||
 | 
					+	int err;
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	if (gpiommc_is_registered(dev))
 | 
				
			||||||
 | 
					+		return 0;
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	if (!gpio_is_valid(dev->pdata.pins.gpio_di) ||
 | 
				
			||||||
 | 
					+	    !gpio_is_valid(dev->pdata.pins.gpio_do) ||
 | 
				
			||||||
 | 
					+	    !gpio_is_valid(dev->pdata.pins.gpio_clk) ||
 | 
				
			||||||
 | 
					+	    !gpio_is_valid(dev->pdata.pins.gpio_cs)) {
 | 
				
			||||||
 | 
					+		printk(KERN_ERR PFX
 | 
				
			||||||
 | 
					+		       "configfs: Invalid GPIO pin number(s)\n");
 | 
				
			||||||
 | 
					+		return -EINVAL;
 | 
				
			||||||
 | 
					+	}
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	strlcpy(dev->pdata.name, name,
 | 
				
			||||||
 | 
					+		sizeof(dev->pdata.name));
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	dev->pdev = platform_device_alloc(GPIOMMC_PLATDEV_NAME,
 | 
				
			||||||
 | 
					+					  gpiommc_next_id());
 | 
				
			||||||
 | 
					+	if (!dev->pdev)
 | 
				
			||||||
 | 
					+		return -ENOMEM;
 | 
				
			||||||
 | 
					+	err = platform_device_add_data(dev->pdev, &dev->pdata,
 | 
				
			||||||
 | 
					+				       sizeof(dev->pdata));
 | 
				
			||||||
 | 
					+	if (err) {
 | 
				
			||||||
 | 
					+		platform_device_put(dev->pdev);
 | 
				
			||||||
 | 
					+		return err;
 | 
				
			||||||
 | 
					+	}
 | 
				
			||||||
 | 
					+	err = platform_device_add(dev->pdev);
 | 
				
			||||||
 | 
					+	if (err) {
 | 
				
			||||||
 | 
					+		platform_device_put(dev->pdev);
 | 
				
			||||||
 | 
					+		return err;
 | 
				
			||||||
 | 
					+	}
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	return 0;
 | 
				
			||||||
 | 
					+}
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+static void gpiommc_do_unregister(struct gpiommc_configfs_device *dev)
 | 
				
			||||||
 | 
					+{
 | 
				
			||||||
 | 
					+	if (!gpiommc_is_registered(dev))
 | 
				
			||||||
 | 
					+		return;
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	platform_device_unregister(dev->pdev);
 | 
				
			||||||
 | 
					+	dev->pdev = NULL;
 | 
				
			||||||
 | 
					+}
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+static ssize_t gpiommc_config_attr_store(struct config_item *item,
 | 
				
			||||||
 | 
					+					 struct configfs_attribute *attr,
 | 
				
			||||||
 | 
					+					 const char *page, size_t count)
 | 
				
			||||||
 | 
					+{
 | 
				
			||||||
 | 
					+	struct gpiommc_configfs_device *dev = ci_to_gpiommc(item);
 | 
				
			||||||
 | 
					+	int err = -EINVAL;
 | 
				
			||||||
 | 
					+	unsigned long data;
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	if (attr == &gpiommc_attr_register) {
 | 
				
			||||||
 | 
					+		err = strict_strtoul(page, 10, &data);
 | 
				
			||||||
 | 
					+		if (err)
 | 
				
			||||||
 | 
					+			goto out;
 | 
				
			||||||
 | 
					+		err = -EINVAL;
 | 
				
			||||||
 | 
					+		if (data == 1)
 | 
				
			||||||
 | 
					+			err = gpiommc_do_register(dev, item->ci_name);
 | 
				
			||||||
 | 
					+		if (data == 0) {
 | 
				
			||||||
 | 
					+			gpiommc_do_unregister(dev);
 | 
				
			||||||
 | 
					+			err = 0;
 | 
				
			||||||
 | 
					+		}
 | 
				
			||||||
 | 
					+		goto out;
 | 
				
			||||||
 | 
					+	}
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	if (gpiommc_is_registered(dev)) {
 | 
				
			||||||
 | 
					+		/* The rest of the config parameters can only be set
 | 
				
			||||||
 | 
					+		 * as long as the device is not registered, yet. */
 | 
				
			||||||
 | 
					+		err = -EBUSY;
 | 
				
			||||||
 | 
					+		goto out;
 | 
				
			||||||
 | 
					+	}
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	if (attr == &gpiommc_attr_DI) {
 | 
				
			||||||
 | 
					+		err = strict_strtoul(page, 10, &data);
 | 
				
			||||||
 | 
					+		if (err)
 | 
				
			||||||
 | 
					+			goto out;
 | 
				
			||||||
 | 
					+		err = -EINVAL;
 | 
				
			||||||
 | 
					+		if (!gpio_is_valid(data))
 | 
				
			||||||
 | 
					+			goto out;
 | 
				
			||||||
 | 
					+		dev->pdata.pins.gpio_di = data;
 | 
				
			||||||
 | 
					+		err = 0;
 | 
				
			||||||
 | 
					+		goto out;
 | 
				
			||||||
 | 
					+	}
 | 
				
			||||||
 | 
					+	if (attr == &gpiommc_attr_DO) {
 | 
				
			||||||
 | 
					+		err = strict_strtoul(page, 10, &data);
 | 
				
			||||||
 | 
					+		if (err)
 | 
				
			||||||
 | 
					+			goto out;
 | 
				
			||||||
 | 
					+		err = -EINVAL;
 | 
				
			||||||
 | 
					+		if (!gpio_is_valid(data))
 | 
				
			||||||
 | 
					+			goto out;
 | 
				
			||||||
 | 
					+		dev->pdata.pins.gpio_do = data;
 | 
				
			||||||
 | 
					+		err = 0;
 | 
				
			||||||
 | 
					+		goto out;
 | 
				
			||||||
 | 
					+	}
 | 
				
			||||||
 | 
					+	if (attr == &gpiommc_attr_CLK) {
 | 
				
			||||||
 | 
					+		err = strict_strtoul(page, 10, &data);
 | 
				
			||||||
 | 
					+		if (err)
 | 
				
			||||||
 | 
					+			goto out;
 | 
				
			||||||
 | 
					+		err = -EINVAL;
 | 
				
			||||||
 | 
					+		if (!gpio_is_valid(data))
 | 
				
			||||||
 | 
					+			goto out;
 | 
				
			||||||
 | 
					+		dev->pdata.pins.gpio_clk = data;
 | 
				
			||||||
 | 
					+		err = 0;
 | 
				
			||||||
 | 
					+		goto out;
 | 
				
			||||||
 | 
					+	}
 | 
				
			||||||
 | 
					+	if (attr == &gpiommc_attr_CS) {
 | 
				
			||||||
 | 
					+		err = strict_strtoul(page, 10, &data);
 | 
				
			||||||
 | 
					+		if (err)
 | 
				
			||||||
 | 
					+			goto out;
 | 
				
			||||||
 | 
					+		err = -EINVAL;
 | 
				
			||||||
 | 
					+		if (!gpio_is_valid(data))
 | 
				
			||||||
 | 
					+			goto out;
 | 
				
			||||||
 | 
					+		dev->pdata.pins.gpio_cs = data;
 | 
				
			||||||
 | 
					+		err = 0;
 | 
				
			||||||
 | 
					+		goto out;
 | 
				
			||||||
 | 
					+	}
 | 
				
			||||||
 | 
					+	if (attr == &gpiommc_attr_CS_activelow) {
 | 
				
			||||||
 | 
					+		err = strict_strtoul(page, 10, &data);
 | 
				
			||||||
 | 
					+		if (err)
 | 
				
			||||||
 | 
					+			goto out;
 | 
				
			||||||
 | 
					+		err = -EINVAL;
 | 
				
			||||||
 | 
					+		if (data != 0 && data != 1)
 | 
				
			||||||
 | 
					+			goto out;
 | 
				
			||||||
 | 
					+		dev->pdata.pins.cs_activelow = data;
 | 
				
			||||||
 | 
					+		err = 0;
 | 
				
			||||||
 | 
					+		goto out;
 | 
				
			||||||
 | 
					+	}
 | 
				
			||||||
 | 
					+	if (attr == &gpiommc_attr_spimode) {
 | 
				
			||||||
 | 
					+		err = strict_strtoul(page, 10, &data);
 | 
				
			||||||
 | 
					+		if (err)
 | 
				
			||||||
 | 
					+			goto out;
 | 
				
			||||||
 | 
					+		err = -EINVAL;
 | 
				
			||||||
 | 
					+		switch (data) {
 | 
				
			||||||
 | 
					+		case 0:
 | 
				
			||||||
 | 
					+			dev->pdata.mode = SPI_MODE_0;
 | 
				
			||||||
 | 
					+			break;
 | 
				
			||||||
 | 
					+		case 1:
 | 
				
			||||||
 | 
					+			dev->pdata.mode = SPI_MODE_1;
 | 
				
			||||||
 | 
					+			break;
 | 
				
			||||||
 | 
					+		case 2:
 | 
				
			||||||
 | 
					+			dev->pdata.mode = SPI_MODE_2;
 | 
				
			||||||
 | 
					+			break;
 | 
				
			||||||
 | 
					+		case 3:
 | 
				
			||||||
 | 
					+			dev->pdata.mode = SPI_MODE_3;
 | 
				
			||||||
 | 
					+			break;
 | 
				
			||||||
 | 
					+		default:
 | 
				
			||||||
 | 
					+			goto out;
 | 
				
			||||||
 | 
					+		}
 | 
				
			||||||
 | 
					+		err = 0;
 | 
				
			||||||
 | 
					+		goto out;
 | 
				
			||||||
 | 
					+	}
 | 
				
			||||||
 | 
					+	if (attr == &gpiommc_attr_spidelay) {
 | 
				
			||||||
 | 
					+		err = strict_strtoul(page, 10, &data);
 | 
				
			||||||
 | 
					+		if (err)
 | 
				
			||||||
 | 
					+			goto out;
 | 
				
			||||||
 | 
					+		err = -EINVAL;
 | 
				
			||||||
 | 
					+		if (data != 0 && data != 1)
 | 
				
			||||||
 | 
					+			goto out;
 | 
				
			||||||
 | 
					+		dev->pdata.no_spi_delay = !data;
 | 
				
			||||||
 | 
					+		err = 0;
 | 
				
			||||||
 | 
					+		goto out;
 | 
				
			||||||
 | 
					+	}
 | 
				
			||||||
 | 
					+	if (attr == &gpiommc_attr_max_bus_speed) {
 | 
				
			||||||
 | 
					+		err = strict_strtoul(page, 10, &data);
 | 
				
			||||||
 | 
					+		if (err)
 | 
				
			||||||
 | 
					+			goto out;
 | 
				
			||||||
 | 
					+		err = -EINVAL;
 | 
				
			||||||
 | 
					+		if (data > UINT_MAX)
 | 
				
			||||||
 | 
					+			goto out;
 | 
				
			||||||
 | 
					+		dev->pdata.max_bus_speed = data;
 | 
				
			||||||
 | 
					+		err = 0;
 | 
				
			||||||
 | 
					+		goto out;
 | 
				
			||||||
 | 
					+	}
 | 
				
			||||||
 | 
					+	WARN_ON(1);
 | 
				
			||||||
 | 
					+	err = -ENOSYS;
 | 
				
			||||||
 | 
					+out:
 | 
				
			||||||
 | 
					+	return err ? err : count;
 | 
				
			||||||
 | 
					+}
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+static void gpiommc_config_item_release(struct config_item *item)
 | 
				
			||||||
 | 
					+{
 | 
				
			||||||
 | 
					+	struct gpiommc_configfs_device *dev = ci_to_gpiommc(item);
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	kfree(dev);
 | 
				
			||||||
 | 
					+}
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+static struct configfs_item_operations gpiommc_config_item_ops = {
 | 
				
			||||||
 | 
					+	.release		= gpiommc_config_item_release,
 | 
				
			||||||
 | 
					+	.show_attribute		= gpiommc_config_attr_show,
 | 
				
			||||||
 | 
					+	.store_attribute	= gpiommc_config_attr_store,
 | 
				
			||||||
 | 
					+};
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+static struct config_item_type gpiommc_dev_ci_type = {
 | 
				
			||||||
 | 
					+	.ct_item_ops	= &gpiommc_config_item_ops,
 | 
				
			||||||
 | 
					+	.ct_attrs	= gpiommc_config_attrs,
 | 
				
			||||||
 | 
					+	.ct_owner	= THIS_MODULE,
 | 
				
			||||||
 | 
					+};
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+static struct config_item *gpiommc_make_item(struct config_group *group,
 | 
				
			||||||
 | 
					+					     const char *name)
 | 
				
			||||||
 | 
					+{
 | 
				
			||||||
 | 
					+	struct gpiommc_configfs_device *dev;
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	if (strlen(name) > GPIOMMC_MAX_NAMELEN) {
 | 
				
			||||||
 | 
					+		printk(KERN_ERR PFX "configfs: device name too long\n");
 | 
				
			||||||
 | 
					+		return NULL;
 | 
				
			||||||
 | 
					+	}
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	dev = kzalloc(sizeof(*dev), GFP_KERNEL);
 | 
				
			||||||
 | 
					+	if (!dev)
 | 
				
			||||||
 | 
					+		return NULL;
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	config_item_init_type_name(&dev->item, name,
 | 
				
			||||||
 | 
					+				   &gpiommc_dev_ci_type);
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	/* Assign default configuration */
 | 
				
			||||||
 | 
					+	dev->pdata.pins.gpio_di = GPIO_INVALID;
 | 
				
			||||||
 | 
					+	dev->pdata.pins.gpio_do = GPIO_INVALID;
 | 
				
			||||||
 | 
					+	dev->pdata.pins.gpio_clk = GPIO_INVALID;
 | 
				
			||||||
 | 
					+	dev->pdata.pins.gpio_cs = GPIO_INVALID;
 | 
				
			||||||
 | 
					+	dev->pdata.pins.cs_activelow = 1;
 | 
				
			||||||
 | 
					+	dev->pdata.mode = SPI_MODE_0;
 | 
				
			||||||
 | 
					+	dev->pdata.no_spi_delay = 0;
 | 
				
			||||||
 | 
					+	dev->pdata.max_bus_speed = 5000000; /* 5 MHz */
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	return &(dev->item);
 | 
				
			||||||
 | 
					+}
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+static void gpiommc_drop_item(struct config_group *group,
 | 
				
			||||||
 | 
					+			      struct config_item *item)
 | 
				
			||||||
 | 
					+{
 | 
				
			||||||
 | 
					+	struct gpiommc_configfs_device *dev = ci_to_gpiommc(item);
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	gpiommc_do_unregister(dev);
 | 
				
			||||||
 | 
					+	kfree(dev);
 | 
				
			||||||
 | 
					+}
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+static struct configfs_group_operations gpiommc_ct_group_ops = {
 | 
				
			||||||
 | 
					+	.make_item	= gpiommc_make_item,
 | 
				
			||||||
 | 
					+	.drop_item	= gpiommc_drop_item,
 | 
				
			||||||
 | 
					+};
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+static struct config_item_type gpiommc_ci_type = {
 | 
				
			||||||
 | 
					+	.ct_group_ops	= &gpiommc_ct_group_ops,
 | 
				
			||||||
 | 
					+	.ct_owner	= THIS_MODULE,
 | 
				
			||||||
 | 
					+};
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+static struct configfs_subsystem gpiommc_subsys = {
 | 
				
			||||||
 | 
					+	.su_group = {
 | 
				
			||||||
 | 
					+		.cg_item = {
 | 
				
			||||||
 | 
					+			.ci_namebuf = GPIOMMC_PLATDEV_NAME,
 | 
				
			||||||
 | 
					+			.ci_type = &gpiommc_ci_type,
 | 
				
			||||||
 | 
					+		},
 | 
				
			||||||
 | 
					+	},
 | 
				
			||||||
 | 
					+	.su_mutex = __MUTEX_INITIALIZER(gpiommc_subsys.su_mutex),
 | 
				
			||||||
 | 
					+};
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+#endif /* CONFIG_GPIOMMC_CONFIGFS */
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+static struct platform_driver gpiommc_plat_driver = {
 | 
				
			||||||
 | 
					+	.probe	= gpiommc_probe,
 | 
				
			||||||
 | 
					+	.remove	= gpiommc_remove,
 | 
				
			||||||
 | 
					+	.driver	= {
 | 
				
			||||||
 | 
					+		.name	= GPIOMMC_PLATDEV_NAME,
 | 
				
			||||||
 | 
					+		.owner	= THIS_MODULE,
 | 
				
			||||||
 | 
					+	},
 | 
				
			||||||
 | 
					+};
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+int gpiommc_next_id(void)
 | 
				
			||||||
 | 
					+{
 | 
				
			||||||
 | 
					+	static atomic_t counter = ATOMIC_INIT(-1);
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	return atomic_inc_return(&counter);
 | 
				
			||||||
 | 
					+}
 | 
				
			||||||
 | 
					+EXPORT_SYMBOL(gpiommc_next_id);
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+static int __init gpiommc_modinit(void)
 | 
				
			||||||
 | 
					+{
 | 
				
			||||||
 | 
					+	int err;
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	err = platform_driver_register(&gpiommc_plat_driver);
 | 
				
			||||||
 | 
					+	if (err)
 | 
				
			||||||
 | 
					+		return err;
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+#ifdef CONFIG_GPIOMMC_CONFIGFS
 | 
				
			||||||
 | 
					+	config_group_init(&gpiommc_subsys.su_group);
 | 
				
			||||||
 | 
					+	err = configfs_register_subsystem(&gpiommc_subsys);
 | 
				
			||||||
 | 
					+	if (err) {
 | 
				
			||||||
 | 
					+		platform_driver_unregister(&gpiommc_plat_driver);
 | 
				
			||||||
 | 
					+		return err;
 | 
				
			||||||
 | 
					+	}
 | 
				
			||||||
 | 
					+#endif /* CONFIG_GPIOMMC_CONFIGFS */
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	return 0;
 | 
				
			||||||
 | 
					+}
 | 
				
			||||||
 | 
					+module_init(gpiommc_modinit);
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+static void __exit gpiommc_modexit(void)
 | 
				
			||||||
 | 
					+{
 | 
				
			||||||
 | 
					+#ifdef CONFIG_GPIOMMC_CONFIGFS
 | 
				
			||||||
 | 
					+	configfs_unregister_subsystem(&gpiommc_subsys);
 | 
				
			||||||
 | 
					+#endif
 | 
				
			||||||
 | 
					+	platform_driver_unregister(&gpiommc_plat_driver);
 | 
				
			||||||
 | 
					+}
 | 
				
			||||||
 | 
					+module_exit(gpiommc_modexit);
 | 
				
			||||||
 | 
					--- a/drivers/mmc/host/Kconfig
 | 
				
			||||||
 | 
					+++ b/drivers/mmc/host/Kconfig
 | 
				
			||||||
 | 
					@@ -474,6 +474,31 @@ config MMC_SDHI
 | 
				
			||||||
 | 
					 	  This provides support for the SDHI SD/SDIO controller found in
 | 
				
			||||||
 | 
					 	  SuperH and ARM SH-Mobile SoCs
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					+config GPIOMMC
 | 
				
			||||||
 | 
					+	tristate "MMC/SD over GPIO-based SPI"
 | 
				
			||||||
 | 
					+	depends on MMC && MMC_SPI && SPI_GPIO_OLD
 | 
				
			||||||
 | 
					+	help
 | 
				
			||||||
 | 
					+	  This driver hooks up the mmc_spi and spi_gpio modules so that
 | 
				
			||||||
 | 
					+	  MMC/SD cards can be used on a GPIO based bus by bitbanging
 | 
				
			||||||
 | 
					+	  the SPI protocol in software.
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	  This driver provides a configfs interface to dynamically create
 | 
				
			||||||
 | 
					+	  and destroy GPIO-based MMC/SD card devices. It also provides
 | 
				
			||||||
 | 
					+	  a platform device interface API.
 | 
				
			||||||
 | 
					+	  See Documentation/gpiommc.txt for details.
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	  The module will be called gpiommc.
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	  If unsure, say N.
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+config GPIOMMC_CONFIGFS
 | 
				
			||||||
 | 
					+	bool
 | 
				
			||||||
 | 
					+	depends on GPIOMMC && CONFIGFS_FS
 | 
				
			||||||
 | 
					+	default y
 | 
				
			||||||
 | 
					+	help
 | 
				
			||||||
 | 
					+	  This option automatically enables configfs support for gpiommc
 | 
				
			||||||
 | 
					+	  if configfs is available.
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					 config MMC_CB710
 | 
				
			||||||
 | 
					 	tristate "ENE CB710 MMC/SD Interface support"
 | 
				
			||||||
 | 
					 	depends on PCI
 | 
				
			||||||
 | 
					--- a/drivers/mmc/host/Makefile
 | 
				
			||||||
 | 
					+++ b/drivers/mmc/host/Makefile
 | 
				
			||||||
 | 
					@@ -36,6 +36,7 @@ tmio_mmc_core-$(subst m,y,$(CONFIG_MMC_S
 | 
				
			||||||
 | 
					 obj-$(CONFIG_MMC_SDHI)		+= sh_mobile_sdhi.o
 | 
				
			||||||
 | 
					 obj-$(CONFIG_MMC_CB710)		+= cb710-mmc.o
 | 
				
			||||||
 | 
					 obj-$(CONFIG_MMC_VIA_SDMMC)	+= via-sdmmc.o
 | 
				
			||||||
 | 
					+obj-$(CONFIG_GPIOMMC)		+= gpiommc.o
 | 
				
			||||||
 | 
					 obj-$(CONFIG_SDH_BFIN)		+= bfin_sdh.o
 | 
				
			||||||
 | 
					 obj-$(CONFIG_MMC_DW)		+= dw_mmc.o
 | 
				
			||||||
 | 
					 obj-$(CONFIG_MMC_SH_MMCIF)	+= sh_mmcif.o
 | 
				
			||||||
 | 
					--- /dev/null
 | 
				
			||||||
 | 
					+++ b/include/linux/mmc/gpiommc.h
 | 
				
			||||||
 | 
					@@ -0,0 +1,71 @@
 | 
				
			||||||
 | 
					+/*
 | 
				
			||||||
 | 
					+ * Device driver for MMC/SD cards driven over a GPIO bus.
 | 
				
			||||||
 | 
					+ *
 | 
				
			||||||
 | 
					+ * Copyright (c) 2008 Michael Buesch
 | 
				
			||||||
 | 
					+ *
 | 
				
			||||||
 | 
					+ * Licensed under the GNU/GPL version 2.
 | 
				
			||||||
 | 
					+ */
 | 
				
			||||||
 | 
					+#ifndef LINUX_GPIOMMC_H_
 | 
				
			||||||
 | 
					+#define LINUX_GPIOMMC_H_
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+#include <linux/types.h>
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+#define GPIOMMC_MAX_NAMELEN		15
 | 
				
			||||||
 | 
					+#define GPIOMMC_MAX_NAMELEN_STR		__stringify(GPIOMMC_MAX_NAMELEN)
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+/**
 | 
				
			||||||
 | 
					+ * struct gpiommc_pins - Hardware pin assignments
 | 
				
			||||||
 | 
					+ *
 | 
				
			||||||
 | 
					+ * @gpio_di: The GPIO number of the DATA IN pin
 | 
				
			||||||
 | 
					+ * @gpio_do: The GPIO number of the DATA OUT pin
 | 
				
			||||||
 | 
					+ * @gpio_clk: The GPIO number of the CLOCK pin
 | 
				
			||||||
 | 
					+ * @gpio_cs: The GPIO number of the CHIPSELECT pin
 | 
				
			||||||
 | 
					+ * @cs_activelow: If true, the chip is considered selected if @gpio_cs is low.
 | 
				
			||||||
 | 
					+ */
 | 
				
			||||||
 | 
					+struct gpiommc_pins {
 | 
				
			||||||
 | 
					+	unsigned int gpio_di;
 | 
				
			||||||
 | 
					+	unsigned int gpio_do;
 | 
				
			||||||
 | 
					+	unsigned int gpio_clk;
 | 
				
			||||||
 | 
					+	unsigned int gpio_cs;
 | 
				
			||||||
 | 
					+	bool cs_activelow;
 | 
				
			||||||
 | 
					+};
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+/**
 | 
				
			||||||
 | 
					+ * struct gpiommc_platform_data - Platform data for a MMC-over-SPI-GPIO device.
 | 
				
			||||||
 | 
					+ *
 | 
				
			||||||
 | 
					+ * @name: The unique name string of the device.
 | 
				
			||||||
 | 
					+ * @pins: The hardware pin assignments.
 | 
				
			||||||
 | 
					+ * @mode: The hardware mode. This is either SPI_MODE_0,
 | 
				
			||||||
 | 
					+ *        SPI_MODE_1, SPI_MODE_2 or SPI_MODE_3. See the SPI documentation.
 | 
				
			||||||
 | 
					+ * @no_spi_delay: Do not use delays in the lowlevel SPI bitbanging code.
 | 
				
			||||||
 | 
					+ *                This is not standards compliant, but may be required for some
 | 
				
			||||||
 | 
					+ *                embedded machines to gain reasonable speed.
 | 
				
			||||||
 | 
					+ * @max_bus_speed: The maximum speed of the SPI bus, in Hertz.
 | 
				
			||||||
 | 
					+ */
 | 
				
			||||||
 | 
					+struct gpiommc_platform_data {
 | 
				
			||||||
 | 
					+	char name[GPIOMMC_MAX_NAMELEN + 1];
 | 
				
			||||||
 | 
					+	struct gpiommc_pins pins;
 | 
				
			||||||
 | 
					+	u8 mode;
 | 
				
			||||||
 | 
					+	bool no_spi_delay;
 | 
				
			||||||
 | 
					+	unsigned int max_bus_speed;
 | 
				
			||||||
 | 
					+};
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+/**
 | 
				
			||||||
 | 
					+ * GPIOMMC_PLATDEV_NAME - The platform device name string.
 | 
				
			||||||
 | 
					+ *
 | 
				
			||||||
 | 
					+ * The name string that has to be used for platform_device_alloc
 | 
				
			||||||
 | 
					+ * when allocating a gpiommc device.
 | 
				
			||||||
 | 
					+ */
 | 
				
			||||||
 | 
					+#define GPIOMMC_PLATDEV_NAME	"gpiommc"
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+/**
 | 
				
			||||||
 | 
					+ * gpiommc_next_id - Get another platform device ID number.
 | 
				
			||||||
 | 
					+ *
 | 
				
			||||||
 | 
					+ * This returns the next platform device ID number that has to be used
 | 
				
			||||||
 | 
					+ * for platform_device_alloc. The ID is opaque and should not be used for
 | 
				
			||||||
 | 
					+ * anything else.
 | 
				
			||||||
 | 
					+ */
 | 
				
			||||||
 | 
					+int gpiommc_next_id(void);
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+#endif /* LINUX_GPIOMMC_H_ */
 | 
				
			||||||
 | 
					--- /dev/null
 | 
				
			||||||
 | 
					+++ b/Documentation/gpiommc.txt
 | 
				
			||||||
 | 
					@@ -0,0 +1,97 @@
 | 
				
			||||||
 | 
					+GPIOMMC - Driver for an MMC/SD card on a bitbanging GPIO SPI bus
 | 
				
			||||||
 | 
					+================================================================
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+The gpiommc module hooks up the mmc_spi and spi_gpio modules for running an
 | 
				
			||||||
 | 
					+MMC or SD card on GPIO pins.
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+Two interfaces for registering a new MMC/SD card device are provided:
 | 
				
			||||||
 | 
					+A static platform-device based mechanism and a dynamic configfs based interface.
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+Registering devices via platform-device
 | 
				
			||||||
 | 
					+=======================================
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+The platform-device interface is used for registering MMC/SD devices that are
 | 
				
			||||||
 | 
					+part of the hardware platform. This is most useful only for embedded machines
 | 
				
			||||||
 | 
					+with MMC/SD devices statically connected to the platform GPIO bus.
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+The data structures are declared in <linux/mmc/gpiommc.h>.
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+To register a new device, define an instance of struct gpiommc_platform_data.
 | 
				
			||||||
 | 
					+This structure holds any information about how the device is hooked up to the
 | 
				
			||||||
 | 
					+GPIO pins and what hardware modes the device supports. See the docbook-style
 | 
				
			||||||
 | 
					+documentation in the header file for more information on the struct fields.
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+Then allocate a new instance of a platform device by doing:
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	pdev = platform_device_alloc(GPIOMMC_PLATDEV_NAME, gpiommc_next_id());
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+This will allocate the platform device data structures and hook it up to the
 | 
				
			||||||
 | 
					+gpiommc driver.
 | 
				
			||||||
 | 
					+Then add the gpiommc_platform_data to the platform device.
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	err = platform_device_add_data(pdev, pdata, sizeof(struct gpiommc_platform_data));
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+You may free the local instance of struct gpiommc_platform_data now. (So the
 | 
				
			||||||
 | 
					+struct may be allocated on the stack, too).
 | 
				
			||||||
 | 
					+Now simply register the platform device.
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	err = platform_device_add(pdev);
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+Done. The gpiommc probe routine will be invoked now and you should see a kernel
 | 
				
			||||||
 | 
					+log message for the added device.
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+Registering devices via configfs
 | 
				
			||||||
 | 
					+================================
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+MMC/SD cards connected via GPIO often are a pretty dynamic thing, as for example
 | 
				
			||||||
 | 
					+selfmade hacks for soldering an MMC/SD card to standard GPIO pins on embedded
 | 
				
			||||||
 | 
					+hardware are a common situation.
 | 
				
			||||||
 | 
					+So we provide a dynamic interface to conveniently handle adding and removing
 | 
				
			||||||
 | 
					+devices from userspace, without the need to recompile the kernel.
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+The "gpiommc" subdirectory at the configfs mountpoint is used for handling
 | 
				
			||||||
 | 
					+the dynamic configuration.
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+To create a new device, it must first be allocated with mkdir.
 | 
				
			||||||
 | 
					+The following command will allocate a device named "my_mmc":
 | 
				
			||||||
 | 
					+	mkdir /config/gpiommc/my_mmc
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+There are several configuration files available in the new
 | 
				
			||||||
 | 
					+/config/gpiommc/my_mmc/ directory:
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+gpio_data_in			= The SPI data-IN GPIO pin number.
 | 
				
			||||||
 | 
					+gpio_data_out			= The SPI data-OUT GPIO pin number.
 | 
				
			||||||
 | 
					+gpio_clock			= The SPI Clock GPIO pin number.
 | 
				
			||||||
 | 
					+gpio_chipselect			= The SPI Chipselect GPIO pin number.
 | 
				
			||||||
 | 
					+gpio_chipselect_activelow	= Boolean. If 0, Chipselect is active-HIGH.
 | 
				
			||||||
 | 
					+				  If 1, Chipselect is active-LOW.
 | 
				
			||||||
 | 
					+spi_mode			= The SPI data mode. Can be 0-3.
 | 
				
			||||||
 | 
					+spi_delay			= Enable all delays in the lowlevel bitbanging.
 | 
				
			||||||
 | 
					+max_bus_speed			= The maximum SPI bus speed. In Hertz.
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+register			= Not a configuration parameter.
 | 
				
			||||||
 | 
					+				  Used to register the configured card
 | 
				
			||||||
 | 
					+				  with the kernel.
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+The device must first get configured and then registered by writing "1" to
 | 
				
			||||||
 | 
					+the "register" file.
 | 
				
			||||||
 | 
					+The configuration parameters "gpio_data_in", "gpio_data_out", "gpio_clock"
 | 
				
			||||||
 | 
					+and "gpio_chipselect" are essential and _must_ be configured before writing
 | 
				
			||||||
 | 
					+"1" to the "register" file. The registration will fail, otherwise.
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+The default values for the other parameters are:
 | 
				
			||||||
 | 
					+gpio_chipselect_activelow	= 1		(CS active-LOW)
 | 
				
			||||||
 | 
					+spi_mode			= 0		(SPI_MODE_0)
 | 
				
			||||||
 | 
					+spi_delay			= 1		(enabled)
 | 
				
			||||||
 | 
					+max_bus_speed			= 5000000	(5 Mhz)
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+Configuration values can not be changed after registration. To unregister
 | 
				
			||||||
 | 
					+the device, write a "0" to the "register" file. The configuration can be
 | 
				
			||||||
 | 
					+changed again after unregistering.
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+To completely remove the device, simply rmdir the directory
 | 
				
			||||||
 | 
					+(/config/gpiommc/my_mmc in this example).
 | 
				
			||||||
 | 
					+There's no need to first unregister the device before removing it. That will
 | 
				
			||||||
 | 
					+be done automatically.
 | 
				
			||||||
 | 
					--- a/MAINTAINERS
 | 
				
			||||||
 | 
					+++ b/MAINTAINERS
 | 
				
			||||||
 | 
					@@ -2933,6 +2933,11 @@ L:	linuxppc-dev@lists.ozlabs.org
 | 
				
			||||||
 | 
					 S:	Odd Fixes
 | 
				
			||||||
 | 
					 F:	drivers/tty/hvc/
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					+GPIOMMC DRIVER
 | 
				
			||||||
 | 
					+P:	Michael Buesch
 | 
				
			||||||
 | 
					+M:	mb@bu3sch.de
 | 
				
			||||||
 | 
					+S:	Maintained
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					 HARDWARE MONITORING
 | 
				
			||||||
 | 
					 M:	Jean Delvare <khali@linux-fr.org>
 | 
				
			||||||
 | 
					 M:	Guenter Roeck <guenter.roeck@ericsson.com>
 | 
				
			||||||
@@ -0,0 +1,58 @@
 | 
				
			|||||||
 | 
					The gpiommc configfs context structure needs locking, as configfs
 | 
				
			||||||
 | 
					does not lock access between files.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					--- a/drivers/mmc/host/gpiommc.c
 | 
				
			||||||
 | 
					+++ b/drivers/mmc/host/gpiommc.c
 | 
				
			||||||
 | 
					@@ -143,6 +143,8 @@ struct gpiommc_configfs_device {
 | 
				
			||||||
 | 
					 	struct platform_device *pdev;
 | 
				
			||||||
 | 
					 	/* The configuration */
 | 
				
			||||||
 | 
					 	struct gpiommc_platform_data pdata;
 | 
				
			||||||
 | 
					+	/* Mutex to protect this structure */
 | 
				
			||||||
 | 
					+	struct mutex mutex;
 | 
				
			||||||
 | 
					 };
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 #define GPIO_INVALID	-1
 | 
				
			||||||
 | 
					@@ -233,6 +235,8 @@ static ssize_t gpiommc_config_attr_show(
 | 
				
			||||||
 | 
					 	unsigned int gpio;
 | 
				
			||||||
 | 
					 	int err = 0;
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					+	mutex_lock(&dev->mutex);
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					 	if (attr == &gpiommc_attr_DI) {
 | 
				
			||||||
 | 
					 		gpio = dev->pdata.pins.gpio_di;
 | 
				
			||||||
 | 
					 		if (gpio == GPIO_INVALID)
 | 
				
			||||||
 | 
					@@ -293,6 +297,8 @@ static ssize_t gpiommc_config_attr_show(
 | 
				
			||||||
 | 
					 	WARN_ON(1);
 | 
				
			||||||
 | 
					 	err = -ENOSYS;
 | 
				
			||||||
 | 
					 out:
 | 
				
			||||||
 | 
					+	mutex_unlock(&dev->mutex);
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					 	return err ? err : count;
 | 
				
			||||||
 | 
					 }
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					@@ -352,6 +358,8 @@ static ssize_t gpiommc_config_attr_store
 | 
				
			||||||
 | 
					 	int err = -EINVAL;
 | 
				
			||||||
 | 
					 	unsigned long data;
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					+	mutex_lock(&dev->mutex);
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					 	if (attr == &gpiommc_attr_register) {
 | 
				
			||||||
 | 
					 		err = strict_strtoul(page, 10, &data);
 | 
				
			||||||
 | 
					 		if (err)
 | 
				
			||||||
 | 
					@@ -477,6 +485,8 @@ static ssize_t gpiommc_config_attr_store
 | 
				
			||||||
 | 
					 	WARN_ON(1);
 | 
				
			||||||
 | 
					 	err = -ENOSYS;
 | 
				
			||||||
 | 
					 out:
 | 
				
			||||||
 | 
					+	mutex_unlock(&dev->mutex);
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					 	return err ? err : count;
 | 
				
			||||||
 | 
					 }
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					@@ -513,6 +523,7 @@ static struct config_item *gpiommc_make_
 | 
				
			||||||
 | 
					 	if (!dev)
 | 
				
			||||||
 | 
					 		return NULL;
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					+	mutex_init(&dev->mutex);
 | 
				
			||||||
 | 
					 	config_item_init_type_name(&dev->item, name,
 | 
				
			||||||
 | 
					 				   &gpiommc_dev_ci_type);
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
Some files were not shown because too many files have changed in this diff Show More
		Reference in New Issue
	
	Block a user