mirror of
git://projects.qi-hardware.com/openwrt-xburst.git
synced 2024-11-27 17:15:00 +02:00
linux/2.6.31: R.I.P.
git-svn-id: svn://svn.openwrt.org/openwrt/trunk@31412 3c298f89-4303-0410-b956-a3cf2f4a3e73
This commit is contained in:
parent
f480dd5941
commit
407157942b
File diff suppressed because it is too large
Load Diff
@ -1,244 +0,0 @@
|
||||
From 6c4419d997d4431bb62e73475cd6b084e83efbd1 Mon Sep 17 00:00:00 2001
|
||||
From: Phillip Lougher <phillip@lougher.demon.co.uk>
|
||||
Date: Tue, 22 Sep 2009 19:25:24 +0100
|
||||
Subject: [PATCH] Squashfs: move zlib decompression wrapper code into a separate file
|
||||
|
||||
Signed-off-by: Phillip Lougher <phillip@lougher.demon.co.uk>
|
||||
---
|
||||
fs/squashfs/Makefile | 2 +-
|
||||
fs/squashfs/block.c | 74 ++----------------------------
|
||||
fs/squashfs/squashfs.h | 4 ++
|
||||
fs/squashfs/zlib_wrapper.c | 109 ++++++++++++++++++++++++++++++++++++++++++++
|
||||
4 files changed, 118 insertions(+), 71 deletions(-)
|
||||
create mode 100644 fs/squashfs/zlib_wrapper.c
|
||||
|
||||
--- a/fs/squashfs/Makefile
|
||||
+++ b/fs/squashfs/Makefile
|
||||
@@ -4,4 +4,4 @@
|
||||
|
||||
obj-$(CONFIG_SQUASHFS) += squashfs.o
|
||||
squashfs-y += block.o cache.o dir.o export.o file.o fragment.o id.o inode.o
|
||||
-squashfs-y += namei.o super.o symlink.o
|
||||
+squashfs-y += namei.o super.o symlink.o zlib_wrapper.o
|
||||
--- a/fs/squashfs/block.c
|
||||
+++ b/fs/squashfs/block.c
|
||||
@@ -29,7 +29,6 @@
|
||||
#include <linux/fs.h>
|
||||
#include <linux/vfs.h>
|
||||
#include <linux/slab.h>
|
||||
-#include <linux/mutex.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/buffer_head.h>
|
||||
#include <linux/zlib.h>
|
||||
@@ -153,72 +152,10 @@ int squashfs_read_data(struct super_bloc
|
||||
}
|
||||
|
||||
if (compressed) {
|
||||
- int zlib_err = 0, zlib_init = 0;
|
||||
-
|
||||
- /*
|
||||
- * Uncompress block.
|
||||
- */
|
||||
-
|
||||
- mutex_lock(&msblk->read_data_mutex);
|
||||
-
|
||||
- msblk->stream.avail_out = 0;
|
||||
- msblk->stream.avail_in = 0;
|
||||
-
|
||||
- bytes = length;
|
||||
- do {
|
||||
- if (msblk->stream.avail_in == 0 && k < b) {
|
||||
- avail = min(bytes, msblk->devblksize - offset);
|
||||
- bytes -= avail;
|
||||
- wait_on_buffer(bh[k]);
|
||||
- if (!buffer_uptodate(bh[k]))
|
||||
- goto release_mutex;
|
||||
-
|
||||
- if (avail == 0) {
|
||||
- offset = 0;
|
||||
- put_bh(bh[k++]);
|
||||
- continue;
|
||||
- }
|
||||
-
|
||||
- msblk->stream.next_in = bh[k]->b_data + offset;
|
||||
- msblk->stream.avail_in = avail;
|
||||
- offset = 0;
|
||||
- }
|
||||
-
|
||||
- if (msblk->stream.avail_out == 0 && page < pages) {
|
||||
- msblk->stream.next_out = buffer[page++];
|
||||
- msblk->stream.avail_out = PAGE_CACHE_SIZE;
|
||||
- }
|
||||
-
|
||||
- if (!zlib_init) {
|
||||
- zlib_err = zlib_inflateInit(&msblk->stream);
|
||||
- if (zlib_err != Z_OK) {
|
||||
- ERROR("zlib_inflateInit returned"
|
||||
- " unexpected result 0x%x,"
|
||||
- " srclength %d\n", zlib_err,
|
||||
- srclength);
|
||||
- goto release_mutex;
|
||||
- }
|
||||
- zlib_init = 1;
|
||||
- }
|
||||
-
|
||||
- zlib_err = zlib_inflate(&msblk->stream, Z_SYNC_FLUSH);
|
||||
-
|
||||
- if (msblk->stream.avail_in == 0 && k < b)
|
||||
- put_bh(bh[k++]);
|
||||
- } while (zlib_err == Z_OK);
|
||||
-
|
||||
- if (zlib_err != Z_STREAM_END) {
|
||||
- ERROR("zlib_inflate error, data probably corrupt\n");
|
||||
- goto release_mutex;
|
||||
- }
|
||||
-
|
||||
- zlib_err = zlib_inflateEnd(&msblk->stream);
|
||||
- if (zlib_err != Z_OK) {
|
||||
- ERROR("zlib_inflate error, data probably corrupt\n");
|
||||
- goto release_mutex;
|
||||
- }
|
||||
- length = msblk->stream.total_out;
|
||||
- mutex_unlock(&msblk->read_data_mutex);
|
||||
+ length = zlib_uncompress(msblk, buffer, bh, b, offset, length,
|
||||
+ srclength, pages);
|
||||
+ if (length < 0)
|
||||
+ goto read_failure;
|
||||
} else {
|
||||
/*
|
||||
* Block is uncompressed.
|
||||
@@ -255,9 +192,6 @@ int squashfs_read_data(struct super_bloc
|
||||
kfree(bh);
|
||||
return length;
|
||||
|
||||
-release_mutex:
|
||||
- mutex_unlock(&msblk->read_data_mutex);
|
||||
-
|
||||
block_release:
|
||||
for (; k < b; k++)
|
||||
put_bh(bh[k]);
|
||||
--- a/fs/squashfs/squashfs.h
|
||||
+++ b/fs/squashfs/squashfs.h
|
||||
@@ -70,6 +70,10 @@ extern struct inode *squashfs_iget(struc
|
||||
unsigned int);
|
||||
extern int squashfs_read_inode(struct inode *, long long);
|
||||
|
||||
+/* zlib_wrapper.c */
|
||||
+extern int zlib_uncompress(struct squashfs_sb_info *, void **,
|
||||
+ struct buffer_head **, int, int, int, int, int);
|
||||
+
|
||||
/*
|
||||
* Inodes and files operations
|
||||
*/
|
||||
--- /dev/null
|
||||
+++ b/fs/squashfs/zlib_wrapper.c
|
||||
@@ -0,0 +1,109 @@
|
||||
+/*
|
||||
+ * Squashfs - a compressed read only filesystem for Linux
|
||||
+ *
|
||||
+ * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
|
||||
+ * Phillip Lougher <phillip@lougher.demon.co.uk>
|
||||
+ *
|
||||
+ * 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,
|
||||
+ * or (at your option) any later version.
|
||||
+ *
|
||||
+ * This program is distributed in the hope that 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, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
+ *
|
||||
+ * zlib_wrapper.c
|
||||
+ */
|
||||
+
|
||||
+
|
||||
+#include <linux/mutex.h>
|
||||
+#include <linux/buffer_head.h>
|
||||
+#include <linux/zlib.h>
|
||||
+
|
||||
+#include "squashfs_fs.h"
|
||||
+#include "squashfs_fs_sb.h"
|
||||
+#include "squashfs_fs_i.h"
|
||||
+#include "squashfs.h"
|
||||
+
|
||||
+int zlib_uncompress(struct squashfs_sb_info *msblk, void **buffer,
|
||||
+ struct buffer_head **bh, int b, int offset, int length, int srclength,
|
||||
+ int pages)
|
||||
+{
|
||||
+ int zlib_err = 0, zlib_init = 0;
|
||||
+ int avail, bytes, k = 0, page = 0;
|
||||
+
|
||||
+ mutex_lock(&msblk->read_data_mutex);
|
||||
+
|
||||
+ msblk->stream.avail_out = 0;
|
||||
+ msblk->stream.avail_in = 0;
|
||||
+
|
||||
+ bytes = length;
|
||||
+ do {
|
||||
+ if (msblk->stream.avail_in == 0 && k < b) {
|
||||
+ avail = min(bytes, msblk->devblksize - offset);
|
||||
+ bytes -= avail;
|
||||
+ wait_on_buffer(bh[k]);
|
||||
+ if (!buffer_uptodate(bh[k]))
|
||||
+ goto release_mutex;
|
||||
+
|
||||
+ if (avail == 0) {
|
||||
+ offset = 0;
|
||||
+ put_bh(bh[k++]);
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
+ msblk->stream.next_in = bh[k]->b_data + offset;
|
||||
+ msblk->stream.avail_in = avail;
|
||||
+ offset = 0;
|
||||
+ }
|
||||
+
|
||||
+ if (msblk->stream.avail_out == 0 && page < pages) {
|
||||
+ msblk->stream.next_out = buffer[page++];
|
||||
+ msblk->stream.avail_out = PAGE_CACHE_SIZE;
|
||||
+ }
|
||||
+
|
||||
+ if (!zlib_init) {
|
||||
+ zlib_err = zlib_inflateInit(&msblk->stream);
|
||||
+ if (zlib_err != Z_OK) {
|
||||
+ ERROR("zlib_inflateInit returned unexpected "
|
||||
+ "result 0x%x, srclength %d\n",
|
||||
+ zlib_err, srclength);
|
||||
+ goto release_mutex;
|
||||
+ }
|
||||
+ zlib_init = 1;
|
||||
+ }
|
||||
+
|
||||
+ zlib_err = zlib_inflate(&msblk->stream, Z_SYNC_FLUSH);
|
||||
+
|
||||
+ if (msblk->stream.avail_in == 0 && k < b)
|
||||
+ put_bh(bh[k++]);
|
||||
+ } while (zlib_err == Z_OK);
|
||||
+
|
||||
+ if (zlib_err != Z_STREAM_END) {
|
||||
+ ERROR("zlib_inflate error, data probably corrupt\n");
|
||||
+ goto release_mutex;
|
||||
+ }
|
||||
+
|
||||
+ zlib_err = zlib_inflateEnd(&msblk->stream);
|
||||
+ if (zlib_err != Z_OK) {
|
||||
+ ERROR("zlib_inflate error, data probably corrupt\n");
|
||||
+ goto release_mutex;
|
||||
+ }
|
||||
+
|
||||
+ mutex_unlock(&msblk->read_data_mutex);
|
||||
+ return msblk->stream.total_out;
|
||||
+
|
||||
+release_mutex:
|
||||
+ mutex_unlock(&msblk->read_data_mutex);
|
||||
+
|
||||
+ for (; k < b; k++)
|
||||
+ put_bh(bh[k]);
|
||||
+
|
||||
+ return -EIO;
|
||||
+}
|
@ -1,317 +0,0 @@
|
||||
From 37c44e85fd49676ec15ccaeea065662c1fbcda7d Mon Sep 17 00:00:00 2001
|
||||
From: Phillip Lougher <phillip@lougher.demon.co.uk>
|
||||
Date: Wed, 23 Sep 2009 19:04:49 +0100
|
||||
Subject: [PATCH] Squashfs: Factor out remaining zlib dependencies into separate wrapper file
|
||||
|
||||
Move zlib buffer init/destroy code into separate wrapper file. Also
|
||||
make zlib z_stream field a void * removing the need to include zlib.h
|
||||
for most files.
|
||||
|
||||
Signed-off-by: Phillip Lougher <phillip@lougher.demon.co.uk>
|
||||
---
|
||||
fs/squashfs/block.c | 1 -
|
||||
fs/squashfs/cache.c | 1 -
|
||||
fs/squashfs/dir.c | 1 -
|
||||
fs/squashfs/export.c | 1 -
|
||||
fs/squashfs/file.c | 1 -
|
||||
fs/squashfs/fragment.c | 1 -
|
||||
fs/squashfs/id.c | 1 -
|
||||
fs/squashfs/inode.c | 1 -
|
||||
fs/squashfs/namei.c | 1 -
|
||||
fs/squashfs/squashfs.h | 2 +
|
||||
fs/squashfs/squashfs_fs_sb.h | 2 +-
|
||||
fs/squashfs/super.c | 14 +++------
|
||||
fs/squashfs/symlink.c | 1 -
|
||||
fs/squashfs/zlib_wrapper.c | 56 ++++++++++++++++++++++++++++++++---------
|
||||
14 files changed, 51 insertions(+), 33 deletions(-)
|
||||
|
||||
--- a/fs/squashfs/block.c
|
||||
+++ b/fs/squashfs/block.c
|
||||
@@ -31,7 +31,6 @@
|
||||
#include <linux/slab.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/buffer_head.h>
|
||||
-#include <linux/zlib.h>
|
||||
|
||||
#include "squashfs_fs.h"
|
||||
#include "squashfs_fs_sb.h"
|
||||
--- a/fs/squashfs/cache.c
|
||||
+++ b/fs/squashfs/cache.c
|
||||
@@ -51,7 +51,6 @@
|
||||
#include <linux/sched.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/wait.h>
|
||||
-#include <linux/zlib.h>
|
||||
#include <linux/pagemap.h>
|
||||
|
||||
#include "squashfs_fs.h"
|
||||
--- a/fs/squashfs/dir.c
|
||||
+++ b/fs/squashfs/dir.c
|
||||
@@ -30,7 +30,6 @@
|
||||
#include <linux/fs.h>
|
||||
#include <linux/vfs.h>
|
||||
#include <linux/slab.h>
|
||||
-#include <linux/zlib.h>
|
||||
|
||||
#include "squashfs_fs.h"
|
||||
#include "squashfs_fs_sb.h"
|
||||
--- a/fs/squashfs/export.c
|
||||
+++ b/fs/squashfs/export.c
|
||||
@@ -39,7 +39,6 @@
|
||||
#include <linux/vfs.h>
|
||||
#include <linux/dcache.h>
|
||||
#include <linux/exportfs.h>
|
||||
-#include <linux/zlib.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
#include "squashfs_fs.h"
|
||||
--- a/fs/squashfs/file.c
|
||||
+++ b/fs/squashfs/file.c
|
||||
@@ -47,7 +47,6 @@
|
||||
#include <linux/string.h>
|
||||
#include <linux/pagemap.h>
|
||||
#include <linux/mutex.h>
|
||||
-#include <linux/zlib.h>
|
||||
|
||||
#include "squashfs_fs.h"
|
||||
#include "squashfs_fs_sb.h"
|
||||
--- a/fs/squashfs/fragment.c
|
||||
+++ b/fs/squashfs/fragment.c
|
||||
@@ -36,7 +36,6 @@
|
||||
#include <linux/fs.h>
|
||||
#include <linux/vfs.h>
|
||||
#include <linux/slab.h>
|
||||
-#include <linux/zlib.h>
|
||||
|
||||
#include "squashfs_fs.h"
|
||||
#include "squashfs_fs_sb.h"
|
||||
--- a/fs/squashfs/id.c
|
||||
+++ b/fs/squashfs/id.c
|
||||
@@ -34,7 +34,6 @@
|
||||
#include <linux/fs.h>
|
||||
#include <linux/vfs.h>
|
||||
#include <linux/slab.h>
|
||||
-#include <linux/zlib.h>
|
||||
|
||||
#include "squashfs_fs.h"
|
||||
#include "squashfs_fs_sb.h"
|
||||
--- a/fs/squashfs/inode.c
|
||||
+++ b/fs/squashfs/inode.c
|
||||
@@ -40,7 +40,6 @@
|
||||
|
||||
#include <linux/fs.h>
|
||||
#include <linux/vfs.h>
|
||||
-#include <linux/zlib.h>
|
||||
|
||||
#include "squashfs_fs.h"
|
||||
#include "squashfs_fs_sb.h"
|
||||
--- a/fs/squashfs/namei.c
|
||||
+++ b/fs/squashfs/namei.c
|
||||
@@ -57,7 +57,6 @@
|
||||
#include <linux/slab.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/dcache.h>
|
||||
-#include <linux/zlib.h>
|
||||
|
||||
#include "squashfs_fs.h"
|
||||
#include "squashfs_fs_sb.h"
|
||||
--- a/fs/squashfs/squashfs.h
|
||||
+++ b/fs/squashfs/squashfs.h
|
||||
@@ -71,6 +71,8 @@ extern struct inode *squashfs_iget(struc
|
||||
extern int squashfs_read_inode(struct inode *, long long);
|
||||
|
||||
/* zlib_wrapper.c */
|
||||
+extern void *zlib_init(void);
|
||||
+extern void zlib_free(void *);
|
||||
extern int zlib_uncompress(struct squashfs_sb_info *, void **,
|
||||
struct buffer_head **, int, int, int, int, int);
|
||||
|
||||
--- a/fs/squashfs/squashfs_fs_sb.h
|
||||
+++ b/fs/squashfs/squashfs_fs_sb.h
|
||||
@@ -64,7 +64,7 @@ struct squashfs_sb_info {
|
||||
struct mutex read_data_mutex;
|
||||
struct mutex meta_index_mutex;
|
||||
struct meta_index *meta_index;
|
||||
- z_stream stream;
|
||||
+ void *stream;
|
||||
__le64 *inode_lookup_table;
|
||||
u64 inode_table;
|
||||
u64 directory_table;
|
||||
--- a/fs/squashfs/super.c
|
||||
+++ b/fs/squashfs/super.c
|
||||
@@ -35,7 +35,6 @@
|
||||
#include <linux/pagemap.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/module.h>
|
||||
-#include <linux/zlib.h>
|
||||
#include <linux/magic.h>
|
||||
|
||||
#include "squashfs_fs.h"
|
||||
@@ -87,12 +86,9 @@ static int squashfs_fill_super(struct su
|
||||
}
|
||||
msblk = sb->s_fs_info;
|
||||
|
||||
- msblk->stream.workspace = kmalloc(zlib_inflate_workspacesize(),
|
||||
- GFP_KERNEL);
|
||||
- if (msblk->stream.workspace == NULL) {
|
||||
- ERROR("Failed to allocate zlib workspace\n");
|
||||
+ msblk->stream = zlib_init();
|
||||
+ if (msblk->stream == NULL)
|
||||
goto failure;
|
||||
- }
|
||||
|
||||
sblk = kzalloc(sizeof(*sblk), GFP_KERNEL);
|
||||
if (sblk == NULL) {
|
||||
@@ -292,17 +288,17 @@ failed_mount:
|
||||
squashfs_cache_delete(msblk->block_cache);
|
||||
squashfs_cache_delete(msblk->fragment_cache);
|
||||
squashfs_cache_delete(msblk->read_page);
|
||||
+ zlib_free(msblk->stream);
|
||||
kfree(msblk->inode_lookup_table);
|
||||
kfree(msblk->fragment_index);
|
||||
kfree(msblk->id_table);
|
||||
- kfree(msblk->stream.workspace);
|
||||
kfree(sb->s_fs_info);
|
||||
sb->s_fs_info = NULL;
|
||||
kfree(sblk);
|
||||
return err;
|
||||
|
||||
failure:
|
||||
- kfree(msblk->stream.workspace);
|
||||
+ zlib_free(msblk->stream);
|
||||
kfree(sb->s_fs_info);
|
||||
sb->s_fs_info = NULL;
|
||||
return -ENOMEM;
|
||||
@@ -346,10 +342,10 @@ static void squashfs_put_super(struct su
|
||||
squashfs_cache_delete(sbi->block_cache);
|
||||
squashfs_cache_delete(sbi->fragment_cache);
|
||||
squashfs_cache_delete(sbi->read_page);
|
||||
+ zlib_free(sbi->stream);
|
||||
kfree(sbi->id_table);
|
||||
kfree(sbi->fragment_index);
|
||||
kfree(sbi->meta_index);
|
||||
- kfree(sbi->stream.workspace);
|
||||
kfree(sb->s_fs_info);
|
||||
sb->s_fs_info = NULL;
|
||||
}
|
||||
--- a/fs/squashfs/symlink.c
|
||||
+++ b/fs/squashfs/symlink.c
|
||||
@@ -36,7 +36,6 @@
|
||||
#include <linux/slab.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/pagemap.h>
|
||||
-#include <linux/zlib.h>
|
||||
|
||||
#include "squashfs_fs.h"
|
||||
#include "squashfs_fs_sb.h"
|
||||
--- a/fs/squashfs/zlib_wrapper.c
|
||||
+++ b/fs/squashfs/zlib_wrapper.c
|
||||
@@ -31,21 +31,51 @@
|
||||
#include "squashfs_fs_i.h"
|
||||
#include "squashfs.h"
|
||||
|
||||
+void *zlib_init()
|
||||
+{
|
||||
+ z_stream *stream = kmalloc(sizeof(z_stream), GFP_KERNEL);
|
||||
+ if (stream == NULL)
|
||||
+ goto failed;
|
||||
+ stream->workspace = kmalloc(zlib_inflate_workspacesize(),
|
||||
+ GFP_KERNEL);
|
||||
+ if (stream->workspace == NULL)
|
||||
+ goto failed;
|
||||
+
|
||||
+ return stream;
|
||||
+
|
||||
+failed:
|
||||
+ ERROR("Failed to allocate zlib workspace\n");
|
||||
+ kfree(stream);
|
||||
+ return NULL;
|
||||
+}
|
||||
+
|
||||
+
|
||||
+void zlib_free(void *strm)
|
||||
+{
|
||||
+ z_stream *stream = strm;
|
||||
+
|
||||
+ if (stream)
|
||||
+ kfree(stream->workspace);
|
||||
+ kfree(stream);
|
||||
+}
|
||||
+
|
||||
+
|
||||
int zlib_uncompress(struct squashfs_sb_info *msblk, void **buffer,
|
||||
struct buffer_head **bh, int b, int offset, int length, int srclength,
|
||||
int pages)
|
||||
{
|
||||
int zlib_err = 0, zlib_init = 0;
|
||||
int avail, bytes, k = 0, page = 0;
|
||||
+ z_stream *stream = msblk->stream;
|
||||
|
||||
mutex_lock(&msblk->read_data_mutex);
|
||||
|
||||
- msblk->stream.avail_out = 0;
|
||||
- msblk->stream.avail_in = 0;
|
||||
+ stream->avail_out = 0;
|
||||
+ stream->avail_in = 0;
|
||||
|
||||
bytes = length;
|
||||
do {
|
||||
- if (msblk->stream.avail_in == 0 && k < b) {
|
||||
+ if (stream->avail_in == 0 && k < b) {
|
||||
avail = min(bytes, msblk->devblksize - offset);
|
||||
bytes -= avail;
|
||||
wait_on_buffer(bh[k]);
|
||||
@@ -58,18 +88,18 @@ int zlib_uncompress(struct squashfs_sb_i
|
||||
continue;
|
||||
}
|
||||
|
||||
- msblk->stream.next_in = bh[k]->b_data + offset;
|
||||
- msblk->stream.avail_in = avail;
|
||||
+ stream->next_in = bh[k]->b_data + offset;
|
||||
+ stream->avail_in = avail;
|
||||
offset = 0;
|
||||
}
|
||||
|
||||
- if (msblk->stream.avail_out == 0 && page < pages) {
|
||||
- msblk->stream.next_out = buffer[page++];
|
||||
- msblk->stream.avail_out = PAGE_CACHE_SIZE;
|
||||
+ if (stream->avail_out == 0 && page < pages) {
|
||||
+ stream->next_out = buffer[page++];
|
||||
+ stream->avail_out = PAGE_CACHE_SIZE;
|
||||
}
|
||||
|
||||
if (!zlib_init) {
|
||||
- zlib_err = zlib_inflateInit(&msblk->stream);
|
||||
+ zlib_err = zlib_inflateInit(stream);
|
||||
if (zlib_err != Z_OK) {
|
||||
ERROR("zlib_inflateInit returned unexpected "
|
||||
"result 0x%x, srclength %d\n",
|
||||
@@ -79,9 +109,9 @@ int zlib_uncompress(struct squashfs_sb_i
|
||||
zlib_init = 1;
|
||||
}
|
||||
|
||||
- zlib_err = zlib_inflate(&msblk->stream, Z_SYNC_FLUSH);
|
||||
+ zlib_err = zlib_inflate(stream, Z_SYNC_FLUSH);
|
||||
|
||||
- if (msblk->stream.avail_in == 0 && k < b)
|
||||
+ if (stream->avail_in == 0 && k < b)
|
||||
put_bh(bh[k++]);
|
||||
} while (zlib_err == Z_OK);
|
||||
|
||||
@@ -90,14 +120,14 @@ int zlib_uncompress(struct squashfs_sb_i
|
||||
goto release_mutex;
|
||||
}
|
||||
|
||||
- zlib_err = zlib_inflateEnd(&msblk->stream);
|
||||
+ zlib_err = zlib_inflateEnd(stream);
|
||||
if (zlib_err != Z_OK) {
|
||||
ERROR("zlib_inflate error, data probably corrupt\n");
|
||||
goto release_mutex;
|
||||
}
|
||||
|
||||
mutex_unlock(&msblk->read_data_mutex);
|
||||
- return msblk->stream.total_out;
|
||||
+ return stream->total_out;
|
||||
|
||||
release_mutex:
|
||||
mutex_unlock(&msblk->read_data_mutex);
|
@ -1,426 +0,0 @@
|
||||
From 327fbf47a419befc6bff74f3ca42d2b6f0841903 Mon Sep 17 00:00:00 2001
|
||||
From: Phillip Lougher <phillip@lougher.demon.co.uk>
|
||||
Date: Tue, 6 Oct 2009 04:04:15 +0100
|
||||
Subject: [PATCH] Squashfs: add a decompressor framework
|
||||
|
||||
This adds a decompressor framework which allows multiple compression
|
||||
algorithms to be cleanly supported.
|
||||
|
||||
Also update zlib wrapper and other code to use the new framework.
|
||||
|
||||
Signed-off-by: Phillip Lougher <phillip@lougher.demon.co.uk>
|
||||
---
|
||||
fs/squashfs/Makefile | 2 +-
|
||||
fs/squashfs/block.c | 6 ++--
|
||||
fs/squashfs/decompressor.c | 58 ++++++++++++++++++++++++++++++++++++++++++
|
||||
fs/squashfs/decompressor.h | 55 +++++++++++++++++++++++++++++++++++++++
|
||||
fs/squashfs/squashfs.h | 14 +++++-----
|
||||
fs/squashfs/squashfs_fs_sb.h | 41 +++++++++++++++--------------
|
||||
fs/squashfs/super.c | 45 ++++++++++++++++++-------------
|
||||
fs/squashfs/zlib_wrapper.c | 17 ++++++++++--
|
||||
8 files changed, 185 insertions(+), 53 deletions(-)
|
||||
create mode 100644 fs/squashfs/decompressor.c
|
||||
create mode 100644 fs/squashfs/decompressor.h
|
||||
|
||||
--- a/fs/squashfs/Makefile
|
||||
+++ b/fs/squashfs/Makefile
|
||||
@@ -4,4 +4,4 @@
|
||||
|
||||
obj-$(CONFIG_SQUASHFS) += squashfs.o
|
||||
squashfs-y += block.o cache.o dir.o export.o file.o fragment.o id.o inode.o
|
||||
-squashfs-y += namei.o super.o symlink.o zlib_wrapper.o
|
||||
+squashfs-y += namei.o super.o symlink.o zlib_wrapper.o decompressor.o
|
||||
--- a/fs/squashfs/block.c
|
||||
+++ b/fs/squashfs/block.c
|
||||
@@ -36,7 +36,7 @@
|
||||
#include "squashfs_fs_sb.h"
|
||||
#include "squashfs_fs_i.h"
|
||||
#include "squashfs.h"
|
||||
-
|
||||
+#include "decompressor.h"
|
||||
/*
|
||||
* Read the metadata block length, this is stored in the first two
|
||||
* bytes of the metadata block.
|
||||
@@ -151,8 +151,8 @@ int squashfs_read_data(struct super_bloc
|
||||
}
|
||||
|
||||
if (compressed) {
|
||||
- length = zlib_uncompress(msblk, buffer, bh, b, offset, length,
|
||||
- srclength, pages);
|
||||
+ length = squashfs_decompress(msblk, buffer, bh, b, offset,
|
||||
+ length, srclength, pages);
|
||||
if (length < 0)
|
||||
goto read_failure;
|
||||
} else {
|
||||
--- /dev/null
|
||||
+++ b/fs/squashfs/decompressor.c
|
||||
@@ -0,0 +1,58 @@
|
||||
+/*
|
||||
+ * Squashfs - a compressed read only filesystem for Linux
|
||||
+ *
|
||||
+ * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
|
||||
+ * Phillip Lougher <phillip@lougher.demon.co.uk>
|
||||
+ *
|
||||
+ * 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,
|
||||
+ * or (at your option) any later version.
|
||||
+ *
|
||||
+ * This program is distributed in the hope that 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, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
+ *
|
||||
+ * decompressor.c
|
||||
+ */
|
||||
+
|
||||
+#include <linux/types.h>
|
||||
+#include <linux/mutex.h>
|
||||
+#include <linux/buffer_head.h>
|
||||
+
|
||||
+#include "squashfs_fs.h"
|
||||
+#include "squashfs_fs_sb.h"
|
||||
+#include "squashfs_fs_i.h"
|
||||
+#include "decompressor.h"
|
||||
+#include "squashfs.h"
|
||||
+
|
||||
+/*
|
||||
+ * This file (and decompressor.h) implements a decompressor framework for
|
||||
+ * Squashfs, allowing multiple decompressors to be easily supported
|
||||
+ */
|
||||
+
|
||||
+static const struct squashfs_decompressor squashfs_unknown_comp_ops = {
|
||||
+ NULL, NULL, NULL, 0, "unknown", 0
|
||||
+};
|
||||
+
|
||||
+static const struct squashfs_decompressor *decompressor[] = {
|
||||
+ &squashfs_zlib_comp_ops,
|
||||
+ &squashfs_unknown_comp_ops
|
||||
+};
|
||||
+
|
||||
+
|
||||
+const struct squashfs_decompressor *squashfs_lookup_decompressor(int id)
|
||||
+{
|
||||
+ int i;
|
||||
+
|
||||
+ for (i = 0; decompressor[i]->id; i++)
|
||||
+ if (id == decompressor[i]->id)
|
||||
+ break;
|
||||
+
|
||||
+ return decompressor[i];
|
||||
+}
|
||||
--- /dev/null
|
||||
+++ b/fs/squashfs/decompressor.h
|
||||
@@ -0,0 +1,55 @@
|
||||
+#ifndef DECOMPRESSOR_H
|
||||
+#define DECOMPRESSOR_H
|
||||
+/*
|
||||
+ * Squashfs - a compressed read only filesystem for Linux
|
||||
+ *
|
||||
+ * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
|
||||
+ * Phillip Lougher <phillip@lougher.demon.co.uk>
|
||||
+ *
|
||||
+ * 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,
|
||||
+ * or (at your option) any later version.
|
||||
+ *
|
||||
+ * This program is distributed in the hope that 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, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
+ *
|
||||
+ * decompressor.h
|
||||
+ */
|
||||
+
|
||||
+struct squashfs_decompressor {
|
||||
+ void *(*init)(void);
|
||||
+ void (*free)(void *);
|
||||
+ int (*decompress)(struct squashfs_sb_info *, void **,
|
||||
+ struct buffer_head **, int, int, int, int, int);
|
||||
+ int id;
|
||||
+ char *name;
|
||||
+ int supported;
|
||||
+};
|
||||
+
|
||||
+static inline void *squashfs_decompressor_init(struct squashfs_sb_info *msblk)
|
||||
+{
|
||||
+ return msblk->decompressor->init();
|
||||
+}
|
||||
+
|
||||
+static inline void squashfs_decompressor_free(struct squashfs_sb_info *msblk,
|
||||
+ void *s)
|
||||
+{
|
||||
+ if (msblk->decompressor)
|
||||
+ msblk->decompressor->free(s);
|
||||
+}
|
||||
+
|
||||
+static inline int squashfs_decompress(struct squashfs_sb_info *msblk,
|
||||
+ void **buffer, struct buffer_head **bh, int b, int offset, int length,
|
||||
+ int srclength, int pages)
|
||||
+{
|
||||
+ return msblk->decompressor->decompress(msblk, buffer, bh, b, offset,
|
||||
+ length, srclength, pages);
|
||||
+}
|
||||
+#endif
|
||||
--- a/fs/squashfs/squashfs.h
|
||||
+++ b/fs/squashfs/squashfs.h
|
||||
@@ -51,6 +51,9 @@ extern struct squashfs_cache_entry *squa
|
||||
u64, int);
|
||||
extern int squashfs_read_table(struct super_block *, void *, u64, int);
|
||||
|
||||
+/* decompressor.c */
|
||||
+extern const struct squashfs_decompressor *squashfs_lookup_decompressor(int);
|
||||
+
|
||||
/* export.c */
|
||||
extern __le64 *squashfs_read_inode_lookup_table(struct super_block *, u64,
|
||||
unsigned int);
|
||||
@@ -70,14 +73,8 @@ extern struct inode *squashfs_iget(struc
|
||||
unsigned int);
|
||||
extern int squashfs_read_inode(struct inode *, long long);
|
||||
|
||||
-/* zlib_wrapper.c */
|
||||
-extern void *zlib_init(void);
|
||||
-extern void zlib_free(void *);
|
||||
-extern int zlib_uncompress(struct squashfs_sb_info *, void **,
|
||||
- struct buffer_head **, int, int, int, int, int);
|
||||
-
|
||||
/*
|
||||
- * Inodes and files operations
|
||||
+ * Inodes, files and decompressor operations
|
||||
*/
|
||||
|
||||
/* dir.c */
|
||||
@@ -94,3 +91,6 @@ extern const struct inode_operations squ
|
||||
|
||||
/* symlink.c */
|
||||
extern const struct address_space_operations squashfs_symlink_aops;
|
||||
+
|
||||
+/* zlib_wrapper.c */
|
||||
+extern const struct squashfs_decompressor squashfs_zlib_comp_ops;
|
||||
--- a/fs/squashfs/squashfs_fs_sb.h
|
||||
+++ b/fs/squashfs/squashfs_fs_sb.h
|
||||
@@ -52,25 +52,26 @@ struct squashfs_cache_entry {
|
||||
};
|
||||
|
||||
struct squashfs_sb_info {
|
||||
- int devblksize;
|
||||
- int devblksize_log2;
|
||||
- struct squashfs_cache *block_cache;
|
||||
- struct squashfs_cache *fragment_cache;
|
||||
- struct squashfs_cache *read_page;
|
||||
- int next_meta_index;
|
||||
- __le64 *id_table;
|
||||
- __le64 *fragment_index;
|
||||
- unsigned int *fragment_index_2;
|
||||
- struct mutex read_data_mutex;
|
||||
- struct mutex meta_index_mutex;
|
||||
- struct meta_index *meta_index;
|
||||
- void *stream;
|
||||
- __le64 *inode_lookup_table;
|
||||
- u64 inode_table;
|
||||
- u64 directory_table;
|
||||
- unsigned int block_size;
|
||||
- unsigned short block_log;
|
||||
- long long bytes_used;
|
||||
- unsigned int inodes;
|
||||
+ const struct squashfs_decompressor *decompressor;
|
||||
+ int devblksize;
|
||||
+ int devblksize_log2;
|
||||
+ struct squashfs_cache *block_cache;
|
||||
+ struct squashfs_cache *fragment_cache;
|
||||
+ struct squashfs_cache *read_page;
|
||||
+ int next_meta_index;
|
||||
+ __le64 *id_table;
|
||||
+ __le64 *fragment_index;
|
||||
+ unsigned int *fragment_index_2;
|
||||
+ struct mutex read_data_mutex;
|
||||
+ struct mutex meta_index_mutex;
|
||||
+ struct meta_index *meta_index;
|
||||
+ void *stream;
|
||||
+ __le64 *inode_lookup_table;
|
||||
+ u64 inode_table;
|
||||
+ u64 directory_table;
|
||||
+ unsigned int block_size;
|
||||
+ unsigned short block_log;
|
||||
+ long long bytes_used;
|
||||
+ unsigned int inodes;
|
||||
};
|
||||
#endif
|
||||
--- a/fs/squashfs/super.c
|
||||
+++ b/fs/squashfs/super.c
|
||||
@@ -41,27 +41,35 @@
|
||||
#include "squashfs_fs_sb.h"
|
||||
#include "squashfs_fs_i.h"
|
||||
#include "squashfs.h"
|
||||
+#include "decompressor.h"
|
||||
|
||||
static struct file_system_type squashfs_fs_type;
|
||||
static struct super_operations squashfs_super_ops;
|
||||
|
||||
-static int supported_squashfs_filesystem(short major, short minor, short comp)
|
||||
+static const struct squashfs_decompressor *supported_squashfs_filesystem(short
|
||||
+ major, short minor, short id)
|
||||
{
|
||||
+ const struct squashfs_decompressor *decompressor;
|
||||
+
|
||||
if (major < SQUASHFS_MAJOR) {
|
||||
ERROR("Major/Minor mismatch, older Squashfs %d.%d "
|
||||
"filesystems are unsupported\n", major, minor);
|
||||
- return -EINVAL;
|
||||
+ return NULL;
|
||||
} else if (major > SQUASHFS_MAJOR || minor > SQUASHFS_MINOR) {
|
||||
ERROR("Major/Minor mismatch, trying to mount newer "
|
||||
"%d.%d filesystem\n", major, minor);
|
||||
ERROR("Please update your kernel\n");
|
||||
- return -EINVAL;
|
||||
+ return NULL;
|
||||
}
|
||||
|
||||
- if (comp != ZLIB_COMPRESSION)
|
||||
- return -EINVAL;
|
||||
+ decompressor = squashfs_lookup_decompressor(id);
|
||||
+ if (!decompressor->supported) {
|
||||
+ ERROR("Filesystem uses \"%s\" compression. This is not "
|
||||
+ "supported\n", decompressor->name);
|
||||
+ return NULL;
|
||||
+ }
|
||||
|
||||
- return 0;
|
||||
+ return decompressor;
|
||||
}
|
||||
|
||||
|
||||
@@ -86,10 +94,6 @@ static int squashfs_fill_super(struct su
|
||||
}
|
||||
msblk = sb->s_fs_info;
|
||||
|
||||
- msblk->stream = zlib_init();
|
||||
- if (msblk->stream == NULL)
|
||||
- goto failure;
|
||||
-
|
||||
sblk = kzalloc(sizeof(*sblk), GFP_KERNEL);
|
||||
if (sblk == NULL) {
|
||||
ERROR("Failed to allocate squashfs_super_block\n");
|
||||
@@ -116,25 +120,25 @@ static int squashfs_fill_super(struct su
|
||||
goto failed_mount;
|
||||
}
|
||||
|
||||
+ err = -EINVAL;
|
||||
+
|
||||
/* Check it is a SQUASHFS superblock */
|
||||
sb->s_magic = le32_to_cpu(sblk->s_magic);
|
||||
if (sb->s_magic != SQUASHFS_MAGIC) {
|
||||
if (!silent)
|
||||
ERROR("Can't find a SQUASHFS superblock on %s\n",
|
||||
bdevname(sb->s_bdev, b));
|
||||
- err = -EINVAL;
|
||||
goto failed_mount;
|
||||
}
|
||||
|
||||
- /* Check the MAJOR & MINOR versions and compression type */
|
||||
- err = supported_squashfs_filesystem(le16_to_cpu(sblk->s_major),
|
||||
+ /* Check the MAJOR & MINOR versions and lookup compression type */
|
||||
+ msblk->decompressor = supported_squashfs_filesystem(
|
||||
+ le16_to_cpu(sblk->s_major),
|
||||
le16_to_cpu(sblk->s_minor),
|
||||
le16_to_cpu(sblk->compression));
|
||||
- if (err < 0)
|
||||
+ if (msblk->decompressor == NULL)
|
||||
goto failed_mount;
|
||||
|
||||
- err = -EINVAL;
|
||||
-
|
||||
/*
|
||||
* Check if there's xattrs in the filesystem. These are not
|
||||
* supported in this version, so warn that they will be ignored.
|
||||
@@ -201,6 +205,10 @@ static int squashfs_fill_super(struct su
|
||||
|
||||
err = -ENOMEM;
|
||||
|
||||
+ msblk->stream = squashfs_decompressor_init(msblk);
|
||||
+ if (msblk->stream == NULL)
|
||||
+ goto failed_mount;
|
||||
+
|
||||
msblk->block_cache = squashfs_cache_init("metadata",
|
||||
SQUASHFS_CACHED_BLKS, SQUASHFS_METADATA_SIZE);
|
||||
if (msblk->block_cache == NULL)
|
||||
@@ -288,7 +296,7 @@ failed_mount:
|
||||
squashfs_cache_delete(msblk->block_cache);
|
||||
squashfs_cache_delete(msblk->fragment_cache);
|
||||
squashfs_cache_delete(msblk->read_page);
|
||||
- zlib_free(msblk->stream);
|
||||
+ squashfs_decompressor_free(msblk, msblk->stream);
|
||||
kfree(msblk->inode_lookup_table);
|
||||
kfree(msblk->fragment_index);
|
||||
kfree(msblk->id_table);
|
||||
@@ -298,7 +306,6 @@ failed_mount:
|
||||
return err;
|
||||
|
||||
failure:
|
||||
- zlib_free(msblk->stream);
|
||||
kfree(sb->s_fs_info);
|
||||
sb->s_fs_info = NULL;
|
||||
return -ENOMEM;
|
||||
@@ -342,7 +349,7 @@ static void squashfs_put_super(struct su
|
||||
squashfs_cache_delete(sbi->block_cache);
|
||||
squashfs_cache_delete(sbi->fragment_cache);
|
||||
squashfs_cache_delete(sbi->read_page);
|
||||
- zlib_free(sbi->stream);
|
||||
+ squashfs_decompressor_free(sbi, sbi->stream);
|
||||
kfree(sbi->id_table);
|
||||
kfree(sbi->fragment_index);
|
||||
kfree(sbi->meta_index);
|
||||
--- a/fs/squashfs/zlib_wrapper.c
|
||||
+++ b/fs/squashfs/zlib_wrapper.c
|
||||
@@ -30,8 +30,9 @@
|
||||
#include "squashfs_fs_sb.h"
|
||||
#include "squashfs_fs_i.h"
|
||||
#include "squashfs.h"
|
||||
+#include "decompressor.h"
|
||||
|
||||
-void *zlib_init()
|
||||
+static void *zlib_init(void)
|
||||
{
|
||||
z_stream *stream = kmalloc(sizeof(z_stream), GFP_KERNEL);
|
||||
if (stream == NULL)
|
||||
@@ -50,7 +51,7 @@ failed:
|
||||
}
|
||||
|
||||
|
||||
-void zlib_free(void *strm)
|
||||
+static void zlib_free(void *strm)
|
||||
{
|
||||
z_stream *stream = strm;
|
||||
|
||||
@@ -60,7 +61,7 @@ void zlib_free(void *strm)
|
||||
}
|
||||
|
||||
|
||||
-int zlib_uncompress(struct squashfs_sb_info *msblk, void **buffer,
|
||||
+static int zlib_uncompress(struct squashfs_sb_info *msblk, void **buffer,
|
||||
struct buffer_head **bh, int b, int offset, int length, int srclength,
|
||||
int pages)
|
||||
{
|
||||
@@ -137,3 +138,13 @@ release_mutex:
|
||||
|
||||
return -EIO;
|
||||
}
|
||||
+
|
||||
+const struct squashfs_decompressor squashfs_zlib_comp_ops = {
|
||||
+ .init = zlib_init,
|
||||
+ .free = zlib_free,
|
||||
+ .decompress = zlib_uncompress,
|
||||
+ .id = ZLIB_COMPRESSION,
|
||||
+ .name = "zlib",
|
||||
+ .supported = 1
|
||||
+};
|
||||
+
|
@ -1,54 +0,0 @@
|
||||
From 1885ca0a1973944684f252094a703b7c80dfc974 Mon Sep 17 00:00:00 2001
|
||||
From: Phillip Lougher <phillip@lougher.demon.co.uk>
|
||||
Date: Wed, 14 Oct 2009 03:58:11 +0100
|
||||
Subject: [PATCH] Squashfs: add decompressor entries for lzma and lzo
|
||||
|
||||
Add knowledge of lzma/lzo compression formats to the decompressor
|
||||
framework. For now these are added as unsupported. Without
|
||||
these entries lzma/lzo compressed filesystems will be flagged as
|
||||
having unknown compression which is undesirable.
|
||||
|
||||
Signed-off-by: Phillip Lougher <phillip@lougher.demon.co.uk>
|
||||
---
|
||||
fs/squashfs/decompressor.c | 10 ++++++++++
|
||||
fs/squashfs/squashfs_fs.h | 4 +++-
|
||||
2 files changed, 13 insertions(+), 1 deletions(-)
|
||||
|
||||
--- a/fs/squashfs/decompressor.c
|
||||
+++ b/fs/squashfs/decompressor.c
|
||||
@@ -36,12 +36,22 @@
|
||||
* Squashfs, allowing multiple decompressors to be easily supported
|
||||
*/
|
||||
|
||||
+static const struct squashfs_decompressor squashfs_lzma_unsupported_comp_ops = {
|
||||
+ NULL, NULL, NULL, LZMA_COMPRESSION, "lzma", 0
|
||||
+};
|
||||
+
|
||||
+static const struct squashfs_decompressor squashfs_lzo_unsupported_comp_ops = {
|
||||
+ NULL, NULL, NULL, LZO_COMPRESSION, "lzo", 0
|
||||
+};
|
||||
+
|
||||
static const struct squashfs_decompressor squashfs_unknown_comp_ops = {
|
||||
NULL, NULL, NULL, 0, "unknown", 0
|
||||
};
|
||||
|
||||
static const struct squashfs_decompressor *decompressor[] = {
|
||||
&squashfs_zlib_comp_ops,
|
||||
+ &squashfs_lzma_unsupported_comp_ops,
|
||||
+ &squashfs_lzo_unsupported_comp_ops,
|
||||
&squashfs_unknown_comp_ops
|
||||
};
|
||||
|
||||
--- a/fs/squashfs/squashfs_fs.h
|
||||
+++ b/fs/squashfs/squashfs_fs.h
|
||||
@@ -211,7 +211,9 @@ struct meta_index {
|
||||
/*
|
||||
* definitions for structures on disk
|
||||
*/
|
||||
-#define ZLIB_COMPRESSION 1
|
||||
+#define ZLIB_COMPRESSION 1
|
||||
+#define LZMA_COMPRESSION 2
|
||||
+#define LZO_COMPRESSION 3
|
||||
|
||||
struct squashfs_super_block {
|
||||
__le32 s_magic;
|
@ -1,42 +0,0 @@
|
||||
From 5f393ede3ddb5dd4cc2a9f243182fac45f1ce10b Mon Sep 17 00:00:00 2001
|
||||
From: Phillip Lougher <phillip@lougher.demon.co.uk>
|
||||
Date: Wed, 14 Oct 2009 04:07:54 +0100
|
||||
Subject: [PATCH] Squashfs: add an extra parameter to the decompressor init function
|
||||
|
||||
Signed-off-by: Phillip Lougher <phillip@lougher.demon.co.uk>
|
||||
---
|
||||
fs/squashfs/decompressor.h | 4 ++--
|
||||
fs/squashfs/zlib_wrapper.c | 2 +-
|
||||
2 files changed, 3 insertions(+), 3 deletions(-)
|
||||
|
||||
--- a/fs/squashfs/decompressor.h
|
||||
+++ b/fs/squashfs/decompressor.h
|
||||
@@ -24,7 +24,7 @@
|
||||
*/
|
||||
|
||||
struct squashfs_decompressor {
|
||||
- void *(*init)(void);
|
||||
+ void *(*init)(struct squashfs_sb_info *);
|
||||
void (*free)(void *);
|
||||
int (*decompress)(struct squashfs_sb_info *, void **,
|
||||
struct buffer_head **, int, int, int, int, int);
|
||||
@@ -35,7 +35,7 @@ struct squashfs_decompressor {
|
||||
|
||||
static inline void *squashfs_decompressor_init(struct squashfs_sb_info *msblk)
|
||||
{
|
||||
- return msblk->decompressor->init();
|
||||
+ return msblk->decompressor->init(msblk);
|
||||
}
|
||||
|
||||
static inline void squashfs_decompressor_free(struct squashfs_sb_info *msblk,
|
||||
--- a/fs/squashfs/zlib_wrapper.c
|
||||
+++ b/fs/squashfs/zlib_wrapper.c
|
||||
@@ -32,7 +32,7 @@
|
||||
#include "squashfs.h"
|
||||
#include "decompressor.h"
|
||||
|
||||
-static void *zlib_init(void)
|
||||
+static void *zlib_init(struct squashfs_sb_info *dummy)
|
||||
{
|
||||
z_stream *stream = kmalloc(sizeof(z_stream), GFP_KERNEL);
|
||||
if (stream == NULL)
|
@ -1,216 +0,0 @@
|
||||
From f49e1efdd179d54e814ff2a8e8f469496583062c Mon Sep 17 00:00:00 2001
|
||||
From: Phillip Lougher <phillip@lougher.demon.co.uk>
|
||||
Date: Tue, 20 Oct 2009 10:54:36 +0100
|
||||
Subject: [PATCH] Squashfs: add LZMA compression
|
||||
|
||||
Add support for LZMA compressed filesystems. This is an initial
|
||||
implementation.
|
||||
|
||||
Signed-off-by: Phillip Lougher <phillip@lougher.demon.co.uk>
|
||||
---
|
||||
fs/squashfs/Kconfig | 5 ++
|
||||
fs/squashfs/Makefile | 1 +
|
||||
fs/squashfs/decompressor.c | 4 +
|
||||
fs/squashfs/lzma_wrapper.c | 151 ++++++++++++++++++++++++++++++++++++++++++++
|
||||
fs/squashfs/squashfs.h | 3 +
|
||||
5 files changed, 164 insertions(+), 0 deletions(-)
|
||||
create mode 100644 fs/squashfs/lzma_wrapper.c
|
||||
|
||||
--- a/fs/squashfs/Kconfig
|
||||
+++ b/fs/squashfs/Kconfig
|
||||
@@ -26,6 +26,11 @@ config SQUASHFS
|
||||
|
||||
If unsure, say N.
|
||||
|
||||
+config SQUASHFS_LZMA
|
||||
+ bool "Include support for LZMA compressed file systems"
|
||||
+ depends on SQUASHFS
|
||||
+ select DECOMPRESS_LZMA
|
||||
+
|
||||
config SQUASHFS_EMBEDDED
|
||||
|
||||
bool "Additional option for memory-constrained systems"
|
||||
--- a/fs/squashfs/Makefile
|
||||
+++ b/fs/squashfs/Makefile
|
||||
@@ -5,3 +5,4 @@
|
||||
obj-$(CONFIG_SQUASHFS) += squashfs.o
|
||||
squashfs-y += block.o cache.o dir.o export.o file.o fragment.o id.o inode.o
|
||||
squashfs-y += namei.o super.o symlink.o zlib_wrapper.o decompressor.o
|
||||
+squashfs-$(CONFIG_SQUASHFS_LZMA) += lzma_wrapper.o
|
||||
--- a/fs/squashfs/decompressor.c
|
||||
+++ b/fs/squashfs/decompressor.c
|
||||
@@ -50,7 +50,11 @@ static const struct squashfs_decompresso
|
||||
|
||||
static const struct squashfs_decompressor *decompressor[] = {
|
||||
&squashfs_zlib_comp_ops,
|
||||
+#ifdef CONFIG_SQUASHFS_LZMA
|
||||
+ &squashfs_lzma_comp_ops,
|
||||
+#else
|
||||
&squashfs_lzma_unsupported_comp_ops,
|
||||
+#endif
|
||||
&squashfs_lzo_unsupported_comp_ops,
|
||||
&squashfs_unknown_comp_ops
|
||||
};
|
||||
--- /dev/null
|
||||
+++ b/fs/squashfs/lzma_wrapper.c
|
||||
@@ -0,0 +1,151 @@
|
||||
+/*
|
||||
+ * Squashfs - a compressed read only filesystem for Linux
|
||||
+ *
|
||||
+ * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
|
||||
+ * Phillip Lougher <phillip@lougher.demon.co.uk>
|
||||
+ *
|
||||
+ * 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,
|
||||
+ * or (at your option) any later version.
|
||||
+ *
|
||||
+ * This program is distributed in the hope that 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, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
+ *
|
||||
+ * lzma_wrapper.c
|
||||
+ */
|
||||
+
|
||||
+#include <asm/unaligned.h>
|
||||
+#include <linux/buffer_head.h>
|
||||
+#include <linux/mutex.h>
|
||||
+#include <linux/vmalloc.h>
|
||||
+#include <linux/decompress/unlzma.h>
|
||||
+
|
||||
+#include "squashfs_fs.h"
|
||||
+#include "squashfs_fs_sb.h"
|
||||
+#include "squashfs_fs_i.h"
|
||||
+#include "squashfs.h"
|
||||
+#include "decompressor.h"
|
||||
+
|
||||
+struct squashfs_lzma {
|
||||
+ void *input;
|
||||
+ void *output;
|
||||
+};
|
||||
+
|
||||
+/* decompress_unlzma.c is currently non re-entrant... */
|
||||
+DEFINE_MUTEX(lzma_mutex);
|
||||
+
|
||||
+/* decompress_unlzma.c doesn't provide any context in its callbacks... */
|
||||
+static int lzma_error;
|
||||
+
|
||||
+static void error(char *m)
|
||||
+{
|
||||
+ ERROR("unlzma error: %s\n", m);
|
||||
+ lzma_error = 1;
|
||||
+}
|
||||
+
|
||||
+
|
||||
+static void *lzma_init(struct squashfs_sb_info *msblk)
|
||||
+{
|
||||
+ struct squashfs_lzma *stream = kzalloc(sizeof(*stream), GFP_KERNEL);
|
||||
+ if (stream == NULL)
|
||||
+ goto failed;
|
||||
+ stream->input = vmalloc(msblk->block_size);
|
||||
+ if (stream->input == NULL)
|
||||
+ goto failed;
|
||||
+ stream->output = vmalloc(msblk->block_size);
|
||||
+ if (stream->output == NULL)
|
||||
+ goto failed2;
|
||||
+
|
||||
+ return stream;
|
||||
+
|
||||
+failed2:
|
||||
+ vfree(stream->input);
|
||||
+failed:
|
||||
+ ERROR("failed to allocate lzma workspace\n");
|
||||
+ kfree(stream);
|
||||
+ return NULL;
|
||||
+}
|
||||
+
|
||||
+
|
||||
+static void lzma_free(void *strm)
|
||||
+{
|
||||
+ struct squashfs_lzma *stream = strm;
|
||||
+
|
||||
+ if (stream) {
|
||||
+ vfree(stream->input);
|
||||
+ vfree(stream->output);
|
||||
+ }
|
||||
+ kfree(stream);
|
||||
+}
|
||||
+
|
||||
+
|
||||
+static int lzma_uncompress(struct squashfs_sb_info *msblk, void **buffer,
|
||||
+ struct buffer_head **bh, int b, int offset, int length, int srclength,
|
||||
+ int pages)
|
||||
+{
|
||||
+ struct squashfs_lzma *stream = msblk->stream;
|
||||
+ void *buff = stream->input;
|
||||
+ int avail, i, bytes = length, res;
|
||||
+
|
||||
+ mutex_lock(&lzma_mutex);
|
||||
+
|
||||
+ for (i = 0; i < b; i++) {
|
||||
+ wait_on_buffer(bh[i]);
|
||||
+ if (!buffer_uptodate(bh[i]))
|
||||
+ goto block_release;
|
||||
+
|
||||
+ avail = min(bytes, msblk->devblksize - offset);
|
||||
+ memcpy(buff, bh[i]->b_data + offset, avail);
|
||||
+ buff += avail;
|
||||
+ bytes -= avail;
|
||||
+ offset = 0;
|
||||
+ put_bh(bh[i]);
|
||||
+ }
|
||||
+
|
||||
+ lzma_error = 0;
|
||||
+ res = unlzma(stream->input, length, NULL, NULL, stream->output, NULL,
|
||||
+ error);
|
||||
+ if (res || lzma_error)
|
||||
+ goto failed;
|
||||
+
|
||||
+ /* uncompressed size is stored in the LZMA header (5 byte offset) */
|
||||
+ res = bytes = get_unaligned_le32(stream->input + 5);
|
||||
+ for (i = 0, buff = stream->output; bytes && i < pages; i++) {
|
||||
+ avail = min_t(int, bytes, PAGE_CACHE_SIZE);
|
||||
+ memcpy(buffer[i], buff, avail);
|
||||
+ buff += avail;
|
||||
+ bytes -= avail;
|
||||
+ }
|
||||
+ if (bytes)
|
||||
+ goto failed;
|
||||
+
|
||||
+ mutex_unlock(&lzma_mutex);
|
||||
+ return res;
|
||||
+
|
||||
+block_release:
|
||||
+ for (; i < b; i++)
|
||||
+ put_bh(bh[i]);
|
||||
+
|
||||
+failed:
|
||||
+ mutex_unlock(&lzma_mutex);
|
||||
+
|
||||
+ ERROR("lzma decompression failed, data probably corrupt\n");
|
||||
+ return -EIO;
|
||||
+}
|
||||
+
|
||||
+const struct squashfs_decompressor squashfs_lzma_comp_ops = {
|
||||
+ .init = lzma_init,
|
||||
+ .free = lzma_free,
|
||||
+ .decompress = lzma_uncompress,
|
||||
+ .id = LZMA_COMPRESSION,
|
||||
+ .name = "lzma",
|
||||
+ .supported = 1
|
||||
+};
|
||||
+
|
||||
--- a/fs/squashfs/squashfs.h
|
||||
+++ b/fs/squashfs/squashfs.h
|
||||
@@ -94,3 +94,6 @@ extern const struct address_space_operat
|
||||
|
||||
/* zlib_wrapper.c */
|
||||
extern const struct squashfs_decompressor squashfs_zlib_comp_ops;
|
||||
+
|
||||
+/* lzma wrapper.c */
|
||||
+extern const struct squashfs_decompressor squashfs_lzma_comp_ops;
|
@ -1,165 +0,0 @@
|
||||
From fdf23ed283bc6ef5c25076ce2065f892120ff556 Mon Sep 17 00:00:00 2001
|
||||
From: Phillip Lougher <phillip@lougher.demon.co.uk>
|
||||
Date: Thu, 22 Oct 2009 04:57:38 +0100
|
||||
Subject: [PATCH] Squashfs: Make unlzma available to non initramfs/initrd code
|
||||
|
||||
Add a config option DECOMPRESS_LZMA_NEEDED which allows subsystems to
|
||||
specify they need the unlzma code. Normally decompress_unlzma.c is
|
||||
compiled with __init and unlzma is not exported to modules.
|
||||
|
||||
Signed-off-by: Phillip Lougher <phillip@lougher.demon.co.uk>
|
||||
---
|
||||
fs/squashfs/Kconfig | 1 +
|
||||
include/linux/decompress/bunzip2_mm.h | 12 ++++++++++++
|
||||
include/linux/decompress/inflate_mm.h | 12 ++++++++++++
|
||||
include/linux/decompress/mm.h | 3 ---
|
||||
include/linux/decompress/unlzma_mm.h | 20 ++++++++++++++++++++
|
||||
lib/Kconfig | 3 +++
|
||||
lib/decompress_bunzip2.c | 1 +
|
||||
lib/decompress_inflate.c | 1 +
|
||||
lib/decompress_unlzma.c | 5 ++++-
|
||||
9 files changed, 54 insertions(+), 4 deletions(-)
|
||||
create mode 100644 include/linux/decompress/bunzip2_mm.h
|
||||
create mode 100644 include/linux/decompress/inflate_mm.h
|
||||
create mode 100644 include/linux/decompress/unlzma_mm.h
|
||||
|
||||
--- a/fs/squashfs/Kconfig
|
||||
+++ b/fs/squashfs/Kconfig
|
||||
@@ -30,6 +30,7 @@ config SQUASHFS_LZMA
|
||||
bool "Include support for LZMA compressed file systems"
|
||||
depends on SQUASHFS
|
||||
select DECOMPRESS_LZMA
|
||||
+ select DECOMPRESS_LZMA_NEEDED
|
||||
|
||||
config SQUASHFS_EMBEDDED
|
||||
|
||||
--- /dev/null
|
||||
+++ b/include/linux/decompress/bunzip2_mm.h
|
||||
@@ -0,0 +1,12 @@
|
||||
+#ifndef BUNZIP2_MM_H
|
||||
+#define BUNZIP2_MM_H
|
||||
+
|
||||
+#ifdef STATIC
|
||||
+/* Code active when included from pre-boot environment: */
|
||||
+#define INIT
|
||||
+#else
|
||||
+/* Compile for initramfs/initrd code only */
|
||||
+#define INIT __init
|
||||
+#endif
|
||||
+
|
||||
+#endif
|
||||
--- /dev/null
|
||||
+++ b/include/linux/decompress/inflate_mm.h
|
||||
@@ -0,0 +1,12 @@
|
||||
+#ifndef INFLATE_MM_H
|
||||
+#define INFLATE_MM_H
|
||||
+
|
||||
+#ifdef STATIC
|
||||
+/* Code active when included from pre-boot environment: */
|
||||
+#define INIT
|
||||
+#else
|
||||
+/* Compile for initramfs/initrd code only */
|
||||
+#define INIT __init
|
||||
+#endif
|
||||
+
|
||||
+#endif
|
||||
--- a/include/linux/decompress/mm.h
|
||||
+++ b/include/linux/decompress/mm.h
|
||||
@@ -53,8 +53,6 @@ static void free(void *where)
|
||||
|
||||
#define set_error_fn(x)
|
||||
|
||||
-#define INIT
|
||||
-
|
||||
#else /* STATIC */
|
||||
|
||||
/* Code active when compiled standalone for use when loading ramdisk: */
|
||||
@@ -77,7 +75,6 @@ static void free(void *where)
|
||||
static void(*error)(char *m);
|
||||
#define set_error_fn(x) error = x;
|
||||
|
||||
-#define INIT __init
|
||||
#define STATIC
|
||||
|
||||
#include <linux/init.h>
|
||||
--- /dev/null
|
||||
+++ b/include/linux/decompress/unlzma_mm.h
|
||||
@@ -0,0 +1,20 @@
|
||||
+#ifndef UNLZMA_MM_H
|
||||
+#define UNLZMA_MM_H
|
||||
+
|
||||
+#ifdef STATIC
|
||||
+
|
||||
+/* Code active when included from pre-boot environment: */
|
||||
+#define INIT
|
||||
+
|
||||
+#elif defined(CONFIG_DECOMPRESS_LZMA_NEEDED)
|
||||
+
|
||||
+/* Make it available to non initramfs/initrd code */
|
||||
+#define INIT
|
||||
+#include <linux/module.h>
|
||||
+#else
|
||||
+
|
||||
+/* Compile for initramfs/initrd code only */
|
||||
+#define INIT __init
|
||||
+#endif
|
||||
+
|
||||
+#endif
|
||||
--- a/lib/Kconfig
|
||||
+++ b/lib/Kconfig
|
||||
@@ -117,6 +117,9 @@ config DECOMPRESS_BZIP2
|
||||
config DECOMPRESS_LZMA
|
||||
tristate
|
||||
|
||||
+config DECOMPRESS_LZMA_NEEDED
|
||||
+ boolean
|
||||
+
|
||||
#
|
||||
# Generic allocator support is selected if needed
|
||||
#
|
||||
--- a/lib/decompress_bunzip2.c
|
||||
+++ b/lib/decompress_bunzip2.c
|
||||
@@ -52,6 +52,7 @@
|
||||
#include <linux/slab.h>
|
||||
#endif /* STATIC */
|
||||
|
||||
+#include <linux/decompress/bunzip2_mm.h>
|
||||
#include <linux/decompress/mm.h>
|
||||
|
||||
#ifndef INT_MAX
|
||||
--- a/lib/decompress_inflate.c
|
||||
+++ b/lib/decompress_inflate.c
|
||||
@@ -23,6 +23,7 @@
|
||||
|
||||
#endif /* STATIC */
|
||||
|
||||
+#include <linux/decompress/inflate_mm.h>
|
||||
#include <linux/decompress/mm.h>
|
||||
|
||||
#define GZIP_IOBUF_SIZE (16*1024)
|
||||
--- a/lib/decompress_unlzma.c
|
||||
+++ b/lib/decompress_unlzma.c
|
||||
@@ -36,6 +36,7 @@
|
||||
#include <linux/slab.h>
|
||||
#endif /* STATIC */
|
||||
|
||||
+#include <linux/decompress/unlzma_mm.h>
|
||||
#include <linux/decompress/mm.h>
|
||||
|
||||
#define MIN(a, b) (((a) < (b)) ? (a) : (b))
|
||||
@@ -523,7 +524,7 @@ static inline void INIT process_bit1(str
|
||||
|
||||
|
||||
|
||||
-STATIC inline int INIT unlzma(unsigned char *buf, int in_len,
|
||||
+STATIC int INIT unlzma(unsigned char *buf, int in_len,
|
||||
int(*fill)(void*, unsigned int),
|
||||
int(*flush)(void*, unsigned int),
|
||||
unsigned char *output,
|
||||
@@ -656,4 +657,6 @@ STATIC int INIT decompress(unsigned char
|
||||
{
|
||||
return unlzma(buf, in_len - 4, fill, flush, output, posp, error_fn);
|
||||
}
|
||||
+#elif defined(CONFIG_DECOMPRESS_LZMA_NEEDED)
|
||||
+EXPORT_SYMBOL(unlzma);
|
||||
#endif
|
@ -1,11 +0,0 @@
|
||||
--- a/arch/mips/kernel/head.S
|
||||
+++ b/arch/mips/kernel/head.S
|
||||
@@ -121,6 +121,8 @@
|
||||
#endif
|
||||
.endm
|
||||
|
||||
+ j kernel_entry
|
||||
+ nop
|
||||
#ifndef CONFIG_NO_EXCEPT_FILL
|
||||
/*
|
||||
* Reserved space for exception handlers.
|
@ -1,21 +0,0 @@
|
||||
--- a/Makefile
|
||||
+++ b/Makefile
|
||||
@@ -521,7 +521,7 @@ all: vmlinux
|
||||
ifdef CONFIG_CC_OPTIMIZE_FOR_SIZE
|
||||
KBUILD_CFLAGS += -Os
|
||||
else
|
||||
-KBUILD_CFLAGS += -O2
|
||||
+KBUILD_CFLAGS += -O2 -fno-reorder-blocks -fno-tree-ch
|
||||
endif
|
||||
|
||||
include $(srctree)/arch/$(SRCARCH)/Makefile
|
||||
@@ -559,6 +559,9 @@ endif
|
||||
NOSTDINC_FLAGS += -nostdinc -isystem $(shell $(CC) -print-file-name=include)
|
||||
CHECKFLAGS += $(NOSTDINC_FLAGS)
|
||||
|
||||
+# improve gcc optimization
|
||||
+CFLAGS += $(call cc-option,-funit-at-a-time,)
|
||||
+
|
||||
# warn about C99 declaration after statement
|
||||
KBUILD_CFLAGS += $(call cc-option,-Wdeclaration-after-statement,)
|
||||
|
@ -1,11 +0,0 @@
|
||||
--- a/arch/mips/include/asm/system.h
|
||||
+++ b/arch/mips/include/asm/system.h
|
||||
@@ -187,7 +187,7 @@ extern __u64 __xchg_u64_unsupported_on_3
|
||||
if something tries to do an invalid xchg(). */
|
||||
extern void __xchg_called_with_bad_pointer(void);
|
||||
|
||||
-static inline unsigned long __xchg(unsigned long x, volatile void * ptr, int size)
|
||||
+static __always_inline unsigned long __xchg(unsigned long x, volatile void * ptr, int size)
|
||||
{
|
||||
switch (size) {
|
||||
case 4:
|
@ -1,36 +0,0 @@
|
||||
--- a/drivers/mtd/chips/cfi_cmdset_0002.c
|
||||
+++ b/drivers/mtd/chips/cfi_cmdset_0002.c
|
||||
@@ -51,6 +51,7 @@
|
||||
#define SST49LF040B 0x0050
|
||||
#define SST49LF008A 0x005a
|
||||
#define AT49BV6416 0x00d6
|
||||
+#define MANUFACTURER_SAMSUNG 0x00ec
|
||||
|
||||
static int cfi_amdstd_read (struct mtd_info *, loff_t, size_t, size_t *, u_char *);
|
||||
static int cfi_amdstd_write_words(struct mtd_info *, loff_t, size_t, size_t *, const u_char *);
|
||||
@@ -375,12 +376,19 @@ struct mtd_info *cfi_cmdset_0002(struct
|
||||
|
||||
if (extp->MajorVersion != '1' ||
|
||||
(extp->MinorVersion < '0' || extp->MinorVersion > '4')) {
|
||||
- printk(KERN_ERR " Unknown Amd/Fujitsu Extended Query "
|
||||
- "version %c.%c.\n", extp->MajorVersion,
|
||||
- extp->MinorVersion);
|
||||
- kfree(extp);
|
||||
- kfree(mtd);
|
||||
- return NULL;
|
||||
+ if (cfi->mfr == MANUFACTURER_SAMSUNG &&
|
||||
+ (extp->MajorVersion == '3' && extp->MinorVersion == '3')) {
|
||||
+ printk(KERN_NOTICE " Newer Samsung flash detected, "
|
||||
+ "should be compatibile with Amd/Fujitsu.\n");
|
||||
+ }
|
||||
+ else {
|
||||
+ printk(KERN_ERR " Unknown Amd/Fujitsu Extended Query "
|
||||
+ "version %c.%c.\n", extp->MajorVersion,
|
||||
+ extp->MinorVersion);
|
||||
+ kfree(extp);
|
||||
+ kfree(mtd);
|
||||
+ return NULL;
|
||||
+ }
|
||||
}
|
||||
|
||||
/* Install our own private info structure */
|
@ -1,173 +0,0 @@
|
||||
--- /dev/null
|
||||
+++ b/arch/mips/include/asm/mips_machine.h
|
||||
@@ -0,0 +1,47 @@
|
||||
+/*
|
||||
+ * Copyright (C) 2008-2009 Gabor Juhos <juhosg@openwrt.org>
|
||||
+ *
|
||||
+ * This program is free software; you can redistribute it and/or modify it
|
||||
+ * under the terms of the GNU General Public License version 2 as published
|
||||
+ * by the Free Software Foundation.
|
||||
+ *
|
||||
+ */
|
||||
+
|
||||
+#ifndef __ASM_MIPS_MACHINE_H
|
||||
+#define __ASM_MIPS_MACHINE_H
|
||||
+
|
||||
+#include <linux/init.h>
|
||||
+#include <linux/list.h>
|
||||
+
|
||||
+struct mips_machine {
|
||||
+ unsigned long mach_type;
|
||||
+ void (*mach_setup)(void);
|
||||
+ char *mach_name;
|
||||
+ struct list_head list;
|
||||
+};
|
||||
+
|
||||
+void mips_machine_register(struct mips_machine *) __init;
|
||||
+void mips_machine_setup(unsigned long machtype) __init;
|
||||
+void mips_machine_set_name(char *name) __init;
|
||||
+
|
||||
+extern char *mips_machine_name;
|
||||
+
|
||||
+#define MIPS_MACHINE(_type, _name, _setup) \
|
||||
+static char machine_name_##_type[] __initdata = _name; \
|
||||
+static struct mips_machine machine_##_type __initdata = \
|
||||
+{ \
|
||||
+ .mach_type = _type, \
|
||||
+ .mach_name = machine_name_##_type, \
|
||||
+ .mach_setup = _setup, \
|
||||
+}; \
|
||||
+ \
|
||||
+static int __init register_machine_##_type(void) \
|
||||
+{ \
|
||||
+ mips_machine_register(&machine_##_type); \
|
||||
+ return 0; \
|
||||
+} \
|
||||
+ \
|
||||
+pure_initcall(register_machine_##_type)
|
||||
+
|
||||
+#endif /* __ASM_MIPS_MACHINE_H */
|
||||
+
|
||||
--- /dev/null
|
||||
+++ b/arch/mips/kernel/mips_machine.c
|
||||
@@ -0,0 +1,74 @@
|
||||
+/*
|
||||
+ * Copyright (C) 2008-2009 Gabor Juhos <juhosg@openwrt.org>
|
||||
+ *
|
||||
+ * This program is free software; you can redistribute it and/or modify it
|
||||
+ * under the terms of the GNU General Public License version 2 as published
|
||||
+ * by the Free Software Foundation.
|
||||
+ *
|
||||
+ */
|
||||
+#include <linux/mm.h>
|
||||
+
|
||||
+#include <asm/mips_machine.h>
|
||||
+#include <asm/bootinfo.h>
|
||||
+
|
||||
+static struct list_head mips_machines __initdata =
|
||||
+ LIST_HEAD_INIT(mips_machines);
|
||||
+
|
||||
+char *mips_machine_name = "Unknown";
|
||||
+
|
||||
+static struct mips_machine * __init mips_machine_find(unsigned long machtype)
|
||||
+{
|
||||
+ struct list_head *this;
|
||||
+
|
||||
+ list_for_each(this, &mips_machines) {
|
||||
+ struct mips_machine *mach;
|
||||
+
|
||||
+ mach = list_entry(this, struct mips_machine, list);
|
||||
+ if (mach->mach_type == machtype)
|
||||
+ return mach;
|
||||
+ }
|
||||
+
|
||||
+ return NULL;
|
||||
+}
|
||||
+
|
||||
+void __init mips_machine_register(struct mips_machine *mach)
|
||||
+{
|
||||
+ list_add_tail(&mach->list, &mips_machines);
|
||||
+}
|
||||
+
|
||||
+void __init mips_machine_set_name(char *name)
|
||||
+{
|
||||
+ unsigned int len;
|
||||
+ char *p;
|
||||
+
|
||||
+ if (name == NULL)
|
||||
+ return;
|
||||
+
|
||||
+ len = strlen(name);
|
||||
+ p = kmalloc(len + 1, GFP_KERNEL);
|
||||
+ if (p) {
|
||||
+ strncpy(p, name, len);
|
||||
+ p[len] = '\0';
|
||||
+ mips_machine_name = p;
|
||||
+ } else {
|
||||
+ printk(KERN_WARNING "MIPS: no memory for machine_name\n");
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+void __init mips_machine_setup(unsigned long machtype)
|
||||
+{
|
||||
+ struct mips_machine *mach;
|
||||
+
|
||||
+ mach = mips_machine_find(machtype);
|
||||
+ if (!mach) {
|
||||
+ printk(KERN_ALERT "MIPS: no machine registered for "
|
||||
+ "machtype %lu\n", machtype);
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ mips_machine_set_name(mach->mach_name);
|
||||
+ printk(KERN_INFO "MIPS: machine is %s\n", mips_machine_name);
|
||||
+
|
||||
+ if (mach->mach_setup)
|
||||
+ mach->mach_setup();
|
||||
+}
|
||||
--- a/arch/mips/kernel/Makefile
|
||||
+++ b/arch/mips/kernel/Makefile
|
||||
@@ -87,6 +87,7 @@ obj-$(CONFIG_GPIO_TXX9) += gpio_txx9.o
|
||||
|
||||
obj-$(CONFIG_KEXEC) += machine_kexec.o relocate_kernel.o
|
||||
obj-$(CONFIG_EARLY_PRINTK) += early_printk.o
|
||||
+obj-$(CONFIG_MIPS_MACHINE) += mips_machine.o
|
||||
|
||||
CFLAGS_cpu-bugs64.o = $(shell if $(CC) $(KBUILD_CFLAGS) -Wa,-mdaddi -c -o /dev/null -xc /dev/null >/dev/null 2>&1; then echo "-DHAVE_AS_SET_DADDI"; fi)
|
||||
|
||||
--- a/arch/mips/Kconfig
|
||||
+++ b/arch/mips/Kconfig
|
||||
@@ -837,6 +837,9 @@ config MIPS_DISABLE_OBSOLETE_IDE
|
||||
config SYNC_R4K
|
||||
bool
|
||||
|
||||
+config MIPS_MACHINE
|
||||
+ def_bool n
|
||||
+
|
||||
config NO_IOPORT
|
||||
def_bool n
|
||||
|
||||
--- a/arch/mips/kernel/proc.c
|
||||
+++ b/arch/mips/kernel/proc.c
|
||||
@@ -12,6 +12,7 @@
|
||||
#include <asm/cpu-features.h>
|
||||
#include <asm/mipsregs.h>
|
||||
#include <asm/processor.h>
|
||||
+#include <asm/mips_machine.h>
|
||||
|
||||
unsigned int vced_count, vcei_count;
|
||||
|
||||
@@ -31,8 +32,12 @@ static int show_cpuinfo(struct seq_file
|
||||
/*
|
||||
* For the first processor also print the system type
|
||||
*/
|
||||
- if (n == 0)
|
||||
+ if (n == 0) {
|
||||
seq_printf(m, "system type\t\t: %s\n", get_system_type());
|
||||
+#ifdef CONFIG_MIPS_MACHINE
|
||||
+ seq_printf(m, "machine\t\t\t: %s\n", mips_machine_name);
|
||||
+#endif
|
||||
+ }
|
||||
|
||||
seq_printf(m, "processor\t\t: %ld\n", n);
|
||||
sprintf(fmt, "cpu model\t\t: %%s V%%d.%%d%s\n",
|
@ -1,28 +0,0 @@
|
||||
--- a/arch/mips/Kconfig
|
||||
+++ b/arch/mips/Kconfig
|
||||
@@ -840,6 +840,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
|
||||
@@ -143,6 +143,12 @@ FEXPORT(__kernel_entry)
|
||||
j kernel_entry
|
||||
#endif
|
||||
|
||||
+#ifdef CONFIG_IMAGE_CMDLINE_HACK
|
||||
+ .ascii "CMDLINE:"
|
||||
+EXPORT(__image_cmdline)
|
||||
+ .fill 0x400
|
||||
+#endif /* CONFIG_IMAGE_CMDLINE_HACK */
|
||||
+
|
||||
__REF
|
||||
|
||||
NESTED(kernel_entry, 16, sp) # kernel entry point
|
@ -1,18 +0,0 @@
|
||||
--- a/arch/mips/include/asm/thread_info.h
|
||||
+++ b/arch/mips/include/asm/thread_info.h
|
||||
@@ -83,6 +83,7 @@ register struct thread_info *__current_t
|
||||
#define THREAD_SIZE (PAGE_SIZE << THREAD_SIZE_ORDER)
|
||||
#define THREAD_MASK (THREAD_SIZE - 1UL)
|
||||
|
||||
+#if 0
|
||||
#define __HAVE_ARCH_THREAD_INFO_ALLOCATOR
|
||||
|
||||
#ifdef CONFIG_DEBUG_STACK_USAGE
|
||||
@@ -99,6 +100,7 @@ register struct thread_info *__current_t
|
||||
#endif
|
||||
|
||||
#define free_thread_info(info) kfree(info)
|
||||
+#endif
|
||||
|
||||
#endif /* !__ASSEMBLY__ */
|
||||
|
@ -1,11 +0,0 @@
|
||||
--- a/arch/mips/kernel/machine_kexec.c
|
||||
+++ b/arch/mips/kernel/machine_kexec.c
|
||||
@@ -52,7 +52,7 @@ machine_kexec(struct kimage *image)
|
||||
reboot_code_buffer =
|
||||
(unsigned long)page_address(image->control_code_page);
|
||||
|
||||
- kexec_start_address = image->start;
|
||||
+ kexec_start_address = (unsigned long) phys_to_virt(image->start);
|
||||
kexec_indirection_page =
|
||||
(unsigned long) phys_to_virt(image->head & PAGE_MASK);
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,155 +0,0 @@
|
||||
MIPS: allow disabling the kernel FPU emulator
|
||||
|
||||
This patch allows turning off the in-kernel Algorithmics
|
||||
FPU emulator support, which allows one to save a couple of
|
||||
precious blocks on an embedded system.
|
||||
|
||||
Signed-off-by: Florian Fainelli <florian@openwrt.org>
|
||||
--
|
||||
--- a/arch/mips/Kconfig
|
||||
+++ b/arch/mips/Kconfig
|
||||
@@ -825,6 +825,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,12 +2,14 @@
|
||||
# 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
|
||||
|
||||
EXTRA_CFLAGS += -Werror
|
||||
--- a/arch/mips/math-emu/cp1emu.c
|
||||
+++ b/arch/mips/math-emu/cp1emu.c
|
||||
@@ -56,6 +56,12 @@
|
||||
#endif
|
||||
#define __mips 4
|
||||
|
||||
+/* Further private data for which no space exists in mips_fpu_struct */
|
||||
+
|
||||
+struct mips_fpu_emulator_stats fpuemustats;
|
||||
+
|
||||
+#ifdef CONFIG_MIPS_FPU_EMU
|
||||
+
|
||||
/* Function which emulates a floating point instruction. */
|
||||
|
||||
static int fpu_emu(struct pt_regs *, struct mips_fpu_struct *,
|
||||
@@ -66,10 +72,6 @@ static int fpux_emu(struct pt_regs *,
|
||||
struct mips_fpu_struct *, mips_instruction);
|
||||
#endif
|
||||
|
||||
-/* Further private data for which no space exists in mips_fpu_struct */
|
||||
-
|
||||
-struct mips_fpu_emulator_stats fpuemustats;
|
||||
-
|
||||
/* Control registers */
|
||||
|
||||
#define FPCREG_RID 0 /* $0 = revision id */
|
||||
@@ -1273,6 +1275,13 @@ int fpu_emulator_cop1Handler(struct pt_r
|
||||
|
||||
return sig;
|
||||
}
|
||||
+#else
|
||||
+int fpu_emulator_cop1Handler(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
|
||||
+ int has_fpu)
|
||||
+{
|
||||
+ return 0;
|
||||
+}
|
||||
+#endif /* CONFIG_MIPS_FPU_EMU */
|
||||
|
||||
#ifdef CONFIG_DEBUG_FS
|
||||
extern struct dentry *mips_debugfs_dir;
|
||||
--- a/arch/mips/math-emu/dsemul.c
|
||||
+++ b/arch/mips/math-emu/dsemul.c
|
||||
@@ -109,6 +109,7 @@ int mips_dsemul(struct pt_regs *regs, mi
|
||||
return SIGILL; /* force out of emulation loop */
|
||||
}
|
||||
|
||||
+#ifdef CONFIG_MIPS_FPU_EMU
|
||||
int do_dsemulret(struct pt_regs *xcp)
|
||||
{
|
||||
struct emuframe __user *fr;
|
||||
@@ -165,3 +166,9 @@ int do_dsemulret(struct pt_regs *xcp)
|
||||
|
||||
return 1;
|
||||
}
|
||||
+#else
|
||||
+int do_dsemulret(struct pt_regs *xcp)
|
||||
+{
|
||||
+ return 0;
|
||||
+}
|
||||
+#endif /* CONFIG_MIPS_FPU_EMU */
|
||||
--- a/arch/mips/math-emu/kernel_linkage.c
|
||||
+++ b/arch/mips/math-emu/kernel_linkage.c
|
||||
@@ -29,6 +29,7 @@
|
||||
|
||||
#define SIGNALLING_NAN 0x7ff800007ff80000LL
|
||||
|
||||
+#ifdef CONFIG_MIPS_FPU_EMU
|
||||
void fpu_emulator_init_fpu(void)
|
||||
{
|
||||
static int first = 1;
|
||||
@@ -112,4 +113,36 @@ int fpu_emulator_restore_context32(struc
|
||||
|
||||
return err;
|
||||
}
|
||||
-#endif
|
||||
+#endif /* CONFIG_64BIT */
|
||||
+#else
|
||||
+
|
||||
+void fpu_emulator_init_fpu(void)
|
||||
+{
|
||||
+ printk(KERN_INFO "FPU emulator disabled, make sure your toolchain"
|
||||
+ "was compiled with software floating point support (soft-float)\n");
|
||||
+ return;
|
||||
+}
|
||||
+
|
||||
+int fpu_emulator_save_context(struct sigcontext __user *sc)
|
||||
+{
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+int fpu_emulator_restore_context(struct sigcontext __user *sc)
|
||||
+{
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+int fpu_emulator_save_context32(struct sigcontext32 __user *sc)
|
||||
+{
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+int fpu_emulator_restore_context32(struct sigcontext32 __user *sc)
|
||||
+{
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+#ifdef CONFIG_64BIT
|
||||
+#endif /* CONFIG_64BIT */
|
||||
+#endif /* CONFIG_MIPS_FPU_EMU */
|
@ -1,368 +0,0 @@
|
||||
--- a/arch/mips/Makefile
|
||||
+++ b/arch/mips/Makefile
|
||||
@@ -83,7 +83,7 @@ all-$(CONFIG_BOOT_ELF64) := $(vmlinux-64
|
||||
cflags-y += -G 0 -mno-abicalls -fno-pic -pipe
|
||||
cflags-y += -msoft-float
|
||||
LDFLAGS_vmlinux += -G 0 -static -n -nostdlib
|
||||
-MODFLAGS += -mlong-calls
|
||||
+MODFLAGS += -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
|
||||
@@ -43,6 +43,117 @@ static struct mips_hi16 *mips_hi16_list;
|
||||
static LIST_HEAD(dbe_list);
|
||||
static DEFINE_SPINLOCK(dbe_lock);
|
||||
|
||||
+/*
|
||||
+ * Get the potential max trampolines size required of the init and
|
||||
+ * non-init sections. Only used if we cannot find enough contiguous
|
||||
+ * physically mapped memory to put the module into.
|
||||
+ */
|
||||
+static unsigned int
|
||||
+get_plt_size(const Elf_Ehdr *hdr, const Elf_Shdr *sechdrs,
|
||||
+ const char *secstrings, unsigned int symindex, bool is_init)
|
||||
+{
|
||||
+ unsigned long ret = 0;
|
||||
+ unsigned int i, j;
|
||||
+ Elf_Sym *syms;
|
||||
+
|
||||
+ /* Everything marked ALLOC (this includes the exported symbols) */
|
||||
+ for (i = 1; i < hdr->e_shnum; ++i) {
|
||||
+ unsigned int info = sechdrs[i].sh_info;
|
||||
+
|
||||
+ if (sechdrs[i].sh_type != SHT_REL
|
||||
+ && sechdrs[i].sh_type != SHT_RELA)
|
||||
+ continue;
|
||||
+
|
||||
+ /* Not a valid relocation section? */
|
||||
+ if (info >= hdr->e_shnum)
|
||||
+ continue;
|
||||
+
|
||||
+ /* Don't bother with non-allocated sections */
|
||||
+ if (!(sechdrs[info].sh_flags & SHF_ALLOC))
|
||||
+ continue;
|
||||
+
|
||||
+ /* If it's called *.init*, and we're not init, we're
|
||||
+ not interested */
|
||||
+ if ((strstr(secstrings + sechdrs[i].sh_name, ".init") != 0)
|
||||
+ != is_init)
|
||||
+ continue;
|
||||
+
|
||||
+ syms = (Elf_Sym *) sechdrs[symindex].sh_addr;
|
||||
+ if (sechdrs[i].sh_type == SHT_REL) {
|
||||
+ Elf_Mips_Rel *rel = (void *) sechdrs[i].sh_addr;
|
||||
+ unsigned int size = sechdrs[i].sh_size / sizeof(*rel);
|
||||
+
|
||||
+ for (j = 0; j < size; ++j) {
|
||||
+ Elf_Sym *sym;
|
||||
+
|
||||
+ if (ELF_MIPS_R_TYPE(rel[j]) != R_MIPS_26)
|
||||
+ continue;
|
||||
+
|
||||
+ sym = syms + ELF_MIPS_R_SYM(rel[j]);
|
||||
+ if (!is_init && sym->st_shndx != SHN_UNDEF)
|
||||
+ continue;
|
||||
+
|
||||
+ ret += 4 * sizeof(int);
|
||||
+ }
|
||||
+ } else {
|
||||
+ Elf_Mips_Rela *rela = (void *) sechdrs[i].sh_addr;
|
||||
+ unsigned int size = sechdrs[i].sh_size / sizeof(*rela);
|
||||
+
|
||||
+ for (j = 0; j < size; ++j) {
|
||||
+ Elf_Sym *sym;
|
||||
+
|
||||
+ if (ELF_MIPS_R_TYPE(rela[j]) != R_MIPS_26)
|
||||
+ continue;
|
||||
+
|
||||
+ sym = syms + ELF_MIPS_R_SYM(rela[j]);
|
||||
+ if (!is_init && sym->st_shndx != SHN_UNDEF)
|
||||
+ continue;
|
||||
+
|
||||
+ ret += 4 * sizeof(int);
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+#ifndef MODULE_START
|
||||
+static void *alloc_phys(unsigned long size)
|
||||
+{
|
||||
+ unsigned order;
|
||||
+ struct page *page;
|
||||
+ struct page *p;
|
||||
+
|
||||
+ size = PAGE_ALIGN(size);
|
||||
+ order = get_order(size);
|
||||
+
|
||||
+ page = alloc_pages(GFP_KERNEL | __GFP_NORETRY | __GFP_NOWARN |
|
||||
+ __GFP_THISNODE, order);
|
||||
+ if (!page)
|
||||
+ return NULL;
|
||||
+
|
||||
+ split_page(page, order);
|
||||
+
|
||||
+ for (p = page + (size >> PAGE_SHIFT); p < page + (1 << order); ++p)
|
||||
+ __free_page(p);
|
||||
+
|
||||
+ return page_address(page);
|
||||
+}
|
||||
+#endif
|
||||
+
|
||||
+static void free_phys(void *ptr, unsigned long size)
|
||||
+{
|
||||
+ struct page *page;
|
||||
+ struct page *end;
|
||||
+
|
||||
+ page = virt_to_page(ptr);
|
||||
+ end = page + (PAGE_ALIGN(size) >> PAGE_SHIFT);
|
||||
+
|
||||
+ for (; page < end; ++page)
|
||||
+ __free_page(page);
|
||||
+}
|
||||
+
|
||||
+
|
||||
void *module_alloc(unsigned long size)
|
||||
{
|
||||
#ifdef MODULE_START
|
||||
@@ -58,21 +169,99 @@ void *module_alloc(unsigned long size)
|
||||
|
||||
return __vmalloc_area(area, GFP_KERNEL, PAGE_KERNEL);
|
||||
#else
|
||||
+ void *ptr;
|
||||
+
|
||||
if (size == 0)
|
||||
return NULL;
|
||||
- return vmalloc(size);
|
||||
+
|
||||
+ ptr = alloc_phys(size);
|
||||
+
|
||||
+ /* If we failed to allocate physically contiguous memory,
|
||||
+ * fall back to regular vmalloc. The module loader code will
|
||||
+ * create jump tables to handle long jumps */
|
||||
+ if (!ptr)
|
||||
+ return vmalloc(size);
|
||||
+
|
||||
+ return ptr;
|
||||
+#endif
|
||||
+}
|
||||
+
|
||||
+static inline bool is_phys_addr(void *ptr)
|
||||
+{
|
||||
+#ifdef CONFIG_64BIT
|
||||
+ return (KSEGX((unsigned long)ptr) == CKSEG0);
|
||||
+#else
|
||||
+ return (KSEGX(ptr) == KSEG0);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Free memory returned from module_alloc */
|
||||
void module_free(struct module *mod, void *module_region)
|
||||
{
|
||||
- vfree(module_region);
|
||||
+ if (is_phys_addr(module_region)) {
|
||||
+ if (mod->module_init == module_region)
|
||||
+ free_phys(module_region, mod->init_size);
|
||||
+ else if (mod->module_core == module_region)
|
||||
+ free_phys(module_region, mod->core_size);
|
||||
+ else
|
||||
+ BUG();
|
||||
+ } else {
|
||||
+ vfree(module_region);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+static void *__module_alloc(int size, bool phys)
|
||||
+{
|
||||
+ void *ptr;
|
||||
+
|
||||
+ if (phys)
|
||||
+ ptr = kmalloc(size, GFP_KERNEL);
|
||||
+ else
|
||||
+ ptr = vmalloc(size);
|
||||
+ return ptr;
|
||||
+}
|
||||
+
|
||||
+static void __module_free(void *ptr)
|
||||
+{
|
||||
+ if (is_phys_addr(ptr))
|
||||
+ kfree(ptr);
|
||||
+ else
|
||||
+ vfree(ptr);
|
||||
}
|
||||
|
||||
int module_frob_arch_sections(Elf_Ehdr *hdr, Elf_Shdr *sechdrs,
|
||||
char *secstrings, struct module *mod)
|
||||
{
|
||||
+ unsigned int symindex = 0;
|
||||
+ unsigned int core_size, init_size;
|
||||
+ int i;
|
||||
+
|
||||
+ for (i = 1; i < hdr->e_shnum; i++)
|
||||
+ if (sechdrs[i].sh_type == SHT_SYMTAB)
|
||||
+ symindex = i;
|
||||
+
|
||||
+ core_size = get_plt_size(hdr, sechdrs, secstrings, symindex, false);
|
||||
+ init_size = get_plt_size(hdr, sechdrs, secstrings, symindex, true);
|
||||
+
|
||||
+ mod->arch.phys_plt_offset = 0;
|
||||
+ mod->arch.virt_plt_offset = 0;
|
||||
+ mod->arch.phys_plt_tbl = NULL;
|
||||
+ mod->arch.virt_plt_tbl = NULL;
|
||||
+
|
||||
+ if ((core_size + init_size) == 0)
|
||||
+ return 0;
|
||||
+
|
||||
+ mod->arch.phys_plt_tbl = __module_alloc(core_size + init_size, 1);
|
||||
+ if (!mod->arch.phys_plt_tbl)
|
||||
+ return -ENOMEM;
|
||||
+
|
||||
+ mod->arch.virt_plt_tbl = __module_alloc(core_size + init_size, 0);
|
||||
+ if (!mod->arch.virt_plt_tbl) {
|
||||
+ __module_free(mod->arch.phys_plt_tbl);
|
||||
+ mod->arch.phys_plt_tbl = NULL;
|
||||
+ return -ENOMEM;
|
||||
+ }
|
||||
+
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -95,28 +284,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",
|
||||
@@ -125,17 +322,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;
|
||||
@@ -400,11 +611,32 @@ int module_finalize(const Elf_Ehdr *hdr,
|
||||
list_add(&me->arch.dbe_list, &dbe_list);
|
||||
spin_unlock_irq(&dbe_lock);
|
||||
}
|
||||
+
|
||||
+ /* Get rid of the fixup trampoline if we're running the module
|
||||
+ * from physically mapped address space */
|
||||
+ if (me->arch.phys_plt_offset == 0) {
|
||||
+ __module_free(me->arch.phys_plt_tbl);
|
||||
+ me->arch.phys_plt_tbl = NULL;
|
||||
+ }
|
||||
+ if (me->arch.virt_plt_offset == 0) {
|
||||
+ __module_free(me->arch.virt_plt_tbl);
|
||||
+ me->arch.virt_plt_tbl = NULL;
|
||||
+ }
|
||||
+
|
||||
return 0;
|
||||
}
|
||||
|
||||
void module_arch_cleanup(struct module *mod)
|
||||
{
|
||||
+ if (mod->arch.phys_plt_tbl) {
|
||||
+ __module_free(mod->arch.phys_plt_tbl);
|
||||
+ mod->arch.phys_plt_tbl = NULL;
|
||||
+ }
|
||||
+ if (mod->arch.virt_plt_tbl) {
|
||||
+ __module_free(mod->arch.virt_plt_tbl);
|
||||
+ mod->arch.virt_plt_tbl = NULL;
|
||||
+ }
|
||||
+
|
||||
spin_lock_irq(&dbe_lock);
|
||||
list_del(&mod->arch.dbe_list);
|
||||
spin_unlock_irq(&dbe_lock);
|
@ -1,201 +0,0 @@
|
||||
--- a/include/asm-generic/vmlinux.lds.h
|
||||
+++ b/include/asm-generic/vmlinux.lds.h
|
||||
@@ -55,6 +55,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 *(__ksymtab.*)
|
||||
+#define SYMTAB_DISCARD
|
||||
+#else
|
||||
+#define SYMTAB_DISCARD *(__ksymtab.*)
|
||||
+#endif
|
||||
+
|
||||
+#ifndef SYMTAB_KEEP_GPL
|
||||
+#define SYMTAB_KEEP_GPL *(__ksymtab_gpl.*)
|
||||
+#define SYMTAB_DISCARD_GPL
|
||||
+#else
|
||||
+#define SYMTAB_DISCARD_GPL *(__ksymtab_gpl.*)
|
||||
+#endif
|
||||
+
|
||||
#ifndef VMLINUX_SYMBOL
|
||||
#define VMLINUX_SYMBOL(_sym_) _sym_
|
||||
#endif
|
||||
@@ -256,35 +277,35 @@
|
||||
/* Kernel symbol table: Normal symbols */ \
|
||||
__ksymtab : AT(ADDR(__ksymtab) - LOAD_OFFSET) { \
|
||||
VMLINUX_SYMBOL(__start___ksymtab) = .; \
|
||||
- *(__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) = .; \
|
||||
- *(__ksymtab_gpl) \
|
||||
+ SYMTAB_KEEP_GPL \
|
||||
VMLINUX_SYMBOL(__stop___ksymtab_gpl) = .; \
|
||||
} \
|
||||
\
|
||||
/* Kernel symbol table: Normal unused symbols */ \
|
||||
__ksymtab_unused : AT(ADDR(__ksymtab_unused) - LOAD_OFFSET) { \
|
||||
VMLINUX_SYMBOL(__start___ksymtab_unused) = .; \
|
||||
- *(__ksymtab_unused) \
|
||||
+ *(__ksymtab_unused.*) \
|
||||
VMLINUX_SYMBOL(__stop___ksymtab_unused) = .; \
|
||||
} \
|
||||
\
|
||||
/* Kernel symbol table: GPL-only unused symbols */ \
|
||||
__ksymtab_unused_gpl : AT(ADDR(__ksymtab_unused_gpl) - LOAD_OFFSET) { \
|
||||
VMLINUX_SYMBOL(__start___ksymtab_unused_gpl) = .; \
|
||||
- *(__ksymtab_unused_gpl) \
|
||||
+ *(__ksymtab_unused_gpl.*) \
|
||||
VMLINUX_SYMBOL(__stop___ksymtab_unused_gpl) = .; \
|
||||
} \
|
||||
\
|
||||
/* Kernel symbol table: GPL-future-only symbols */ \
|
||||
__ksymtab_gpl_future : AT(ADDR(__ksymtab_gpl_future) - LOAD_OFFSET) { \
|
||||
VMLINUX_SYMBOL(__start___ksymtab_gpl_future) = .; \
|
||||
- *(__ksymtab_gpl_future) \
|
||||
+ *(__ksymtab_gpl_future.*) \
|
||||
VMLINUX_SYMBOL(__stop___ksymtab_gpl_future) = .; \
|
||||
} \
|
||||
\
|
||||
@@ -325,7 +346,13 @@
|
||||
\
|
||||
/* Kernel symbol table: strings */ \
|
||||
__ksymtab_strings : AT(ADDR(__ksymtab_strings) - LOAD_OFFSET) { \
|
||||
- *(__ksymtab_strings) \
|
||||
+ SYMTAB_KEEP_STR \
|
||||
+ } \
|
||||
+ \
|
||||
+ /DISCARD/ : { \
|
||||
+ SYMTAB_DISCARD \
|
||||
+ SYMTAB_DISCARD_GPL \
|
||||
+ SYMTAB_DISCARD_STR \
|
||||
} \
|
||||
\
|
||||
/* __*init sections */ \
|
||||
--- a/include/linux/module.h
|
||||
+++ b/include/linux/module.h
|
||||
@@ -188,16 +188,24 @@ void *__symbol_get_gpl(const char *symbo
|
||||
#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 \
|
||||
- __attribute__((section("__ksymtab" sec), unused)) \
|
||||
+ __attribute__((section("__ksymtab" sec \
|
||||
+ __EXPORT_SUFFIX(sym)), unused)) \
|
||||
= { (unsigned long)&sym, __kstrtab_##sym }
|
||||
|
||||
#define EXPORT_SYMBOL(sym) \
|
||||
--- a/arch/arm/kernel/vmlinux.lds.S
|
||||
+++ b/arch/arm/kernel/vmlinux.lds.S
|
||||
@@ -79,26 +79,6 @@ SECTIONS
|
||||
#endif
|
||||
}
|
||||
|
||||
- /DISCARD/ : { /* Exit code and data */
|
||||
- EXIT_TEXT
|
||||
- EXIT_DATA
|
||||
- *(.exitcall.exit)
|
||||
- *(.ARM.exidx.exit.text)
|
||||
- *(.ARM.extab.exit.text)
|
||||
-#ifndef CONFIG_HOTPLUG_CPU
|
||||
- *(.ARM.exidx.cpuexit.text)
|
||||
- *(.ARM.extab.cpuexit.text)
|
||||
-#endif
|
||||
-#ifndef CONFIG_HOTPLUG
|
||||
- *(.ARM.exidx.devexit.text)
|
||||
- *(.ARM.extab.devexit.text)
|
||||
-#endif
|
||||
-#ifndef CONFIG_MMU
|
||||
- *(.fixup)
|
||||
- *(__ex_table)
|
||||
-#endif
|
||||
- }
|
||||
-
|
||||
.text : { /* Real text segment */
|
||||
_text = .; /* Text and read-only data */
|
||||
__exception_text_start = .;
|
||||
@@ -205,6 +185,28 @@ SECTIONS
|
||||
__bss_stop = .;
|
||||
_end = .;
|
||||
}
|
||||
+
|
||||
+ /DISCARD/ : { /* Exit code and data */
|
||||
+ EXIT_TEXT
|
||||
+ EXIT_DATA
|
||||
+ *(.discard)
|
||||
+ *(.exitcall.exit)
|
||||
+ *(.ARM.exidx.exit.text)
|
||||
+ *(.ARM.extab.exit.text)
|
||||
+#ifndef CONFIG_HOTPLUG_CPU
|
||||
+ *(.ARM.exidx.cpuexit.text)
|
||||
+ *(.ARM.extab.cpuexit.text)
|
||||
+#endif
|
||||
+#ifndef CONFIG_HOTPLUG
|
||||
+ *(.ARM.exidx.devexit.text)
|
||||
+ *(.ARM.extab.devexit.text)
|
||||
+#endif
|
||||
+#ifndef CONFIG_MMU
|
||||
+ *(.fixup)
|
||||
+ *(__ex_table)
|
||||
+#endif
|
||||
+ }
|
||||
+
|
||||
/* Stabs debugging sections. */
|
||||
.stab 0 : { *(.stab) }
|
||||
.stabstr 0 : { *(.stabstr) }
|
||||
--- a/arch/powerpc/kernel/vmlinux.lds.S
|
||||
+++ b/arch/powerpc/kernel/vmlinux.lds.S
|
||||
@@ -37,12 +37,6 @@ jiffies = jiffies_64 + 4;
|
||||
#endif
|
||||
SECTIONS
|
||||
{
|
||||
- /* Sections to be discarded. */
|
||||
- /DISCARD/ : {
|
||||
- *(.exitcall.exit)
|
||||
- EXIT_DATA
|
||||
- }
|
||||
-
|
||||
. = KERNELBASE;
|
||||
|
||||
/*
|
||||
@@ -295,6 +289,12 @@ SECTIONS
|
||||
__bss_stop = .;
|
||||
}
|
||||
|
||||
+ /* Sections to be discarded. */
|
||||
+ /DISCARD/ : {
|
||||
+ *(.exitcall.exit)
|
||||
+ EXIT_DATA
|
||||
+ }
|
||||
+
|
||||
. = ALIGN(PAGE_SIZE);
|
||||
_end = . ;
|
||||
PROVIDE32 (end = .);
|
@ -1,13 +0,0 @@
|
||||
--- a/arch/arm/kernel/module.c
|
||||
+++ b/arch/arm/kernel/module.c
|
||||
@@ -120,6 +120,10 @@ apply_relocate(Elf32_Shdr *sechdrs, cons
|
||||
return -ENOEXEC;
|
||||
}
|
||||
|
||||
+ if ((IS_ERR_VALUE(sym->st_value) || !sym->st_value) &&
|
||||
+ ELF_ST_BIND(sym->st_info) == STB_WEAK)
|
||||
+ continue;
|
||||
+
|
||||
loc = dstsec->sh_addr + rel->r_offset;
|
||||
|
||||
switch (ELF32_R_TYPE(rel->r_info)) {
|
@ -1,43 +0,0 @@
|
||||
--- a/drivers/pci/Kconfig
|
||||
+++ b/drivers/pci/Kconfig
|
||||
@@ -51,6 +51,12 @@ config PCI_STUB
|
||||
|
||||
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
|
||||
@@ -98,6 +98,7 @@ static void __devinit quirk_resource_ali
|
||||
}
|
||||
DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID, PCI_ANY_ID, quirk_resource_alignment);
|
||||
|
||||
+#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.
|
||||
@@ -1867,7 +1868,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)
|
||||
{
|
||||
@@ -2498,6 +2501,7 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_I
|
||||
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x150d, quirk_i82576_sriov);
|
||||
|
||||
#endif /* CONFIG_PCI_IOV */
|
||||
+#endif /* !CONFIG_PCI_DISABLE_COMMON_QUIRKS */
|
||||
|
||||
static void pci_do_fixups(struct pci_dev *dev, struct pci_fixup *f,
|
||||
struct pci_fixup *end)
|
@ -1,226 +0,0 @@
|
||||
GCC 4.4.x looks to be adding support for generating out-of-line register
|
||||
saves/restores based on:
|
||||
|
||||
http://gcc.gnu.org/ml/gcc-patches/2008-04/msg01678.html
|
||||
|
||||
This breaks the kernel build as we'd have to link with libgcc to get the
|
||||
implementation of the register save/restores.
|
||||
|
||||
To workaround this issue, we just stole the save/restore code from gcc
|
||||
and simplified it down for our needs (integer only). We only do this if
|
||||
PPC32 as gcc makes believe the linker on ppc64 will deal with this and
|
||||
only if CONFIG_CC_OPTIMIZE_FOR_SIZE is set (thus -Os).
|
||||
|
||||
Signed-off-by: Kumar Gala <[EMAIL PROTECTED]>
|
||||
---
|
||||
|
||||
If someone using cutting edge toolchains for ppc64 could test and make
|
||||
sure if we enable CONFIG_CC_OPTIMIZE_FOR_SIZE things work that would be
|
||||
nice.
|
||||
|
||||
- k
|
||||
|
||||
arch/powerpc/kernel/misc_32.S | 77 +++++++++++++++++++++++++++
|
||||
arch/powerpc/kernel/ppc_ksyms.c | 111 +++++++++++++++++++++++++++++++++++++++
|
||||
2 files changed, 188 insertions(+), 0 deletions(-)
|
||||
|
||||
--- a/arch/powerpc/kernel/misc_32.S
|
||||
+++ b/arch/powerpc/kernel/misc_32.S
|
||||
@@ -813,3 +813,80 @@ relocate_new_kernel_end:
|
||||
relocate_new_kernel_size:
|
||||
.long relocate_new_kernel_end - relocate_new_kernel
|
||||
#endif
|
||||
+
|
||||
+#if defined(CONFIG_PPC32) && defined(CONFIG_CC_OPTIMIZE_FOR_SIZE)
|
||||
+/* Routines for saving integer registers, called by the compiler. */
|
||||
+/* Called with r11 pointing to the stack header word of the caller of the */
|
||||
+/* function, just beyond the end of the integer save area. */
|
||||
+
|
||||
+_GLOBAL(_savegpr_14) stw 14,-72(11) /* save gp registers */
|
||||
+_GLOBAL(_savegpr_15) stw 15,-68(11)
|
||||
+_GLOBAL(_savegpr_16) stw 16,-64(11)
|
||||
+_GLOBAL(_savegpr_17) stw 17,-60(11)
|
||||
+_GLOBAL(_savegpr_18) stw 18,-56(11)
|
||||
+_GLOBAL(_savegpr_19) stw 19,-52(11)
|
||||
+_GLOBAL(_savegpr_20) stw 20,-48(11)
|
||||
+_GLOBAL(_savegpr_21) stw 21,-44(11)
|
||||
+_GLOBAL(_savegpr_22) stw 22,-40(11)
|
||||
+_GLOBAL(_savegpr_23) stw 23,-36(11)
|
||||
+_GLOBAL(_savegpr_24) stw 24,-32(11)
|
||||
+_GLOBAL(_savegpr_25) stw 25,-28(11)
|
||||
+_GLOBAL(_savegpr_26) stw 26,-24(11)
|
||||
+_GLOBAL(_savegpr_27) stw 27,-20(11)
|
||||
+_GLOBAL(_savegpr_28) stw 28,-16(11)
|
||||
+_GLOBAL(_savegpr_29) stw 29,-12(11)
|
||||
+_GLOBAL(_savegpr_30) stw 30,-8(11)
|
||||
+_GLOBAL(_savegpr_31) stw 31,-4(11)
|
||||
+ blr
|
||||
+
|
||||
+/* Routines for restoring integer registers, called by the compiler. */
|
||||
+/* Called with r11 pointing to the stack header word of the caller of the */
|
||||
+/* function, just beyond the end of the integer restore area. */
|
||||
+
|
||||
+_GLOBAL(_restgpr_14) lwz 14,-72(11) /* restore gp registers */
|
||||
+_GLOBAL(_restgpr_15) lwz 15,-68(11)
|
||||
+_GLOBAL(_restgpr_16) lwz 16,-64(11)
|
||||
+_GLOBAL(_restgpr_17) lwz 17,-60(11)
|
||||
+_GLOBAL(_restgpr_18) lwz 18,-56(11)
|
||||
+_GLOBAL(_restgpr_19) lwz 19,-52(11)
|
||||
+_GLOBAL(_restgpr_20) lwz 20,-48(11)
|
||||
+_GLOBAL(_restgpr_21) lwz 21,-44(11)
|
||||
+_GLOBAL(_restgpr_22) lwz 22,-40(11)
|
||||
+_GLOBAL(_restgpr_23) lwz 23,-36(11)
|
||||
+_GLOBAL(_restgpr_24) lwz 24,-32(11)
|
||||
+_GLOBAL(_restgpr_25) lwz 25,-28(11)
|
||||
+_GLOBAL(_restgpr_26) lwz 26,-24(11)
|
||||
+_GLOBAL(_restgpr_27) lwz 27,-20(11)
|
||||
+_GLOBAL(_restgpr_28) lwz 28,-16(11)
|
||||
+_GLOBAL(_restgpr_29) lwz 29,-12(11)
|
||||
+_GLOBAL(_restgpr_30) lwz 30,-8(11)
|
||||
+_GLOBAL(_restgpr_31) lwz 31,-4(11)
|
||||
+ blr
|
||||
+
|
||||
+/* Routines for restoring integer registers, called by the compiler. */
|
||||
+/* Called with r11 pointing to the stack header word of the caller of the */
|
||||
+/* function, just beyond the end of the integer restore area. */
|
||||
+
|
||||
+_GLOBAL(_restgpr_14_x) lwz 14,-72(11) /* restore gp registers */
|
||||
+_GLOBAL(_restgpr_15_x) lwz 15,-68(11)
|
||||
+_GLOBAL(_restgpr_16_x) lwz 16,-64(11)
|
||||
+_GLOBAL(_restgpr_17_x) lwz 17,-60(11)
|
||||
+_GLOBAL(_restgpr_18_x) lwz 18,-56(11)
|
||||
+_GLOBAL(_restgpr_19_x) lwz 19,-52(11)
|
||||
+_GLOBAL(_restgpr_20_x) lwz 20,-48(11)
|
||||
+_GLOBAL(_restgpr_21_x) lwz 21,-44(11)
|
||||
+_GLOBAL(_restgpr_22_x) lwz 22,-40(11)
|
||||
+_GLOBAL(_restgpr_23_x) lwz 23,-36(11)
|
||||
+_GLOBAL(_restgpr_24_x) lwz 24,-32(11)
|
||||
+_GLOBAL(_restgpr_25_x) lwz 25,-28(11)
|
||||
+_GLOBAL(_restgpr_26_x) lwz 26,-24(11)
|
||||
+_GLOBAL(_restgpr_27_x) lwz 27,-20(11)
|
||||
+_GLOBAL(_restgpr_28_x) lwz 28,-16(11)
|
||||
+_GLOBAL(_restgpr_29_x) lwz 29,-12(11)
|
||||
+_GLOBAL(_restgpr_30_x) lwz 30,-8(11)
|
||||
+_GLOBAL(_restgpr_31_x) lwz 0,4(11)
|
||||
+ lwz 31,-4(11)
|
||||
+ mtlr 0
|
||||
+ mr 1,11
|
||||
+ blr
|
||||
+#endif
|
||||
--- a/arch/powerpc/kernel/ppc_ksyms.c
|
||||
+++ b/arch/powerpc/kernel/ppc_ksyms.c
|
||||
@@ -188,3 +188,114 @@ EXPORT_SYMBOL(__mtdcr);
|
||||
EXPORT_SYMBOL(__mfdcr);
|
||||
#endif
|
||||
EXPORT_SYMBOL(empty_zero_page);
|
||||
+
|
||||
+#if defined(CONFIG_PPC32) && defined(CONFIG_CC_OPTIMIZE_FOR_SIZE)
|
||||
+void _savegpr_14(void);
|
||||
+void _savegpr_15(void);
|
||||
+void _savegpr_16(void);
|
||||
+void _savegpr_17(void);
|
||||
+void _savegpr_18(void);
|
||||
+void _savegpr_19(void);
|
||||
+void _savegpr_20(void);
|
||||
+void _savegpr_21(void);
|
||||
+void _savegpr_22(void);
|
||||
+void _savegpr_23(void);
|
||||
+void _savegpr_24(void);
|
||||
+void _savegpr_25(void);
|
||||
+void _savegpr_26(void);
|
||||
+void _savegpr_27(void);
|
||||
+void _savegpr_28(void);
|
||||
+void _savegpr_29(void);
|
||||
+void _savegpr_30(void);
|
||||
+void _savegpr_31(void);
|
||||
+void _restgpr_14(void);
|
||||
+void _restgpr_15(void);
|
||||
+void _restgpr_16(void);
|
||||
+void _restgpr_17(void);
|
||||
+void _restgpr_18(void);
|
||||
+void _restgpr_19(void);
|
||||
+void _restgpr_20(void);
|
||||
+void _restgpr_21(void);
|
||||
+void _restgpr_22(void);
|
||||
+void _restgpr_23(void);
|
||||
+void _restgpr_24(void);
|
||||
+void _restgpr_25(void);
|
||||
+void _restgpr_26(void);
|
||||
+void _restgpr_27(void);
|
||||
+void _restgpr_28(void);
|
||||
+void _restgpr_29(void);
|
||||
+void _restgpr_30(void);
|
||||
+void _restgpr_31(void);
|
||||
+void _restgpr_14_x(void);
|
||||
+void _restgpr_15_x(void);
|
||||
+void _restgpr_16_x(void);
|
||||
+void _restgpr_17_x(void);
|
||||
+void _restgpr_18_x(void);
|
||||
+void _restgpr_19_x(void);
|
||||
+void _restgpr_20_x(void);
|
||||
+void _restgpr_21_x(void);
|
||||
+void _restgpr_22_x(void);
|
||||
+void _restgpr_23_x(void);
|
||||
+void _restgpr_24_x(void);
|
||||
+void _restgpr_25_x(void);
|
||||
+void _restgpr_26_x(void);
|
||||
+void _restgpr_27_x(void);
|
||||
+void _restgpr_28_x(void);
|
||||
+void _restgpr_29_x(void);
|
||||
+void _restgpr_30_x(void);
|
||||
+void _restgpr_31_x(void);
|
||||
+EXPORT_SYMBOL(_savegpr_14);
|
||||
+EXPORT_SYMBOL(_savegpr_15);
|
||||
+EXPORT_SYMBOL(_savegpr_16);
|
||||
+EXPORT_SYMBOL(_savegpr_17);
|
||||
+EXPORT_SYMBOL(_savegpr_18);
|
||||
+EXPORT_SYMBOL(_savegpr_19);
|
||||
+EXPORT_SYMBOL(_savegpr_20);
|
||||
+EXPORT_SYMBOL(_savegpr_21);
|
||||
+EXPORT_SYMBOL(_savegpr_22);
|
||||
+EXPORT_SYMBOL(_savegpr_23);
|
||||
+EXPORT_SYMBOL(_savegpr_24);
|
||||
+EXPORT_SYMBOL(_savegpr_25);
|
||||
+EXPORT_SYMBOL(_savegpr_26);
|
||||
+EXPORT_SYMBOL(_savegpr_27);
|
||||
+EXPORT_SYMBOL(_savegpr_28);
|
||||
+EXPORT_SYMBOL(_savegpr_29);
|
||||
+EXPORT_SYMBOL(_savegpr_30);
|
||||
+EXPORT_SYMBOL(_savegpr_31);
|
||||
+EXPORT_SYMBOL(_restgpr_14);
|
||||
+EXPORT_SYMBOL(_restgpr_15);
|
||||
+EXPORT_SYMBOL(_restgpr_16);
|
||||
+EXPORT_SYMBOL(_restgpr_17);
|
||||
+EXPORT_SYMBOL(_restgpr_18);
|
||||
+EXPORT_SYMBOL(_restgpr_19);
|
||||
+EXPORT_SYMBOL(_restgpr_20);
|
||||
+EXPORT_SYMBOL(_restgpr_21);
|
||||
+EXPORT_SYMBOL(_restgpr_22);
|
||||
+EXPORT_SYMBOL(_restgpr_23);
|
||||
+EXPORT_SYMBOL(_restgpr_24);
|
||||
+EXPORT_SYMBOL(_restgpr_25);
|
||||
+EXPORT_SYMBOL(_restgpr_26);
|
||||
+EXPORT_SYMBOL(_restgpr_27);
|
||||
+EXPORT_SYMBOL(_restgpr_28);
|
||||
+EXPORT_SYMBOL(_restgpr_29);
|
||||
+EXPORT_SYMBOL(_restgpr_30);
|
||||
+EXPORT_SYMBOL(_restgpr_31);
|
||||
+EXPORT_SYMBOL(_restgpr_14_x);
|
||||
+EXPORT_SYMBOL(_restgpr_15_x);
|
||||
+EXPORT_SYMBOL(_restgpr_16_x);
|
||||
+EXPORT_SYMBOL(_restgpr_17_x);
|
||||
+EXPORT_SYMBOL(_restgpr_18_x);
|
||||
+EXPORT_SYMBOL(_restgpr_19_x);
|
||||
+EXPORT_SYMBOL(_restgpr_20_x);
|
||||
+EXPORT_SYMBOL(_restgpr_21_x);
|
||||
+EXPORT_SYMBOL(_restgpr_22_x);
|
||||
+EXPORT_SYMBOL(_restgpr_23_x);
|
||||
+EXPORT_SYMBOL(_restgpr_24_x);
|
||||
+EXPORT_SYMBOL(_restgpr_25_x);
|
||||
+EXPORT_SYMBOL(_restgpr_26_x);
|
||||
+EXPORT_SYMBOL(_restgpr_27_x);
|
||||
+EXPORT_SYMBOL(_restgpr_28_x);
|
||||
+EXPORT_SYMBOL(_restgpr_29_x);
|
||||
+EXPORT_SYMBOL(_restgpr_30_x);
|
||||
+EXPORT_SYMBOL(_restgpr_31_x);
|
||||
+#endif /* CONFIG_PPC32 && CONFIG_CC_OPTIMIZE_FOR_SIZE */
|
@ -1,11 +0,0 @@
|
||||
--- a/arch/mips/kernel/Makefile
|
||||
+++ b/arch/mips/kernel/Makefile
|
||||
@@ -4,6 +4,8 @@
|
||||
|
||||
CPPFLAGS_vmlinux.lds := $(KBUILD_CFLAGS)
|
||||
|
||||
+CPPFLAGS_vmlinux.lds := $(KBUILD_CFLAGS) $(EXTRA_LDSFLAGS)
|
||||
+
|
||||
extra-y := head.o init_task.o vmlinux.lds
|
||||
|
||||
obj-y += cpu-probe.o branch.o entry.o genex.o irq.o process.o \
|
@ -1,72 +0,0 @@
|
||||
From 2fa4341074cd02fb39aa23410740764948755635 Mon Sep 17 00:00:00 2001
|
||||
From: Albin Tonnerre <albin.tonnerre@free-electrons.com>
|
||||
Date: Wed, 23 Sep 2009 15:57:38 -0700
|
||||
Subject: [PATCH] include/linux/unaligned/{l,b}e_byteshift.h: fix usage for compressed kernels
|
||||
|
||||
When unaligned accesses are required for uncompressing a kernel (such as
|
||||
for LZO decompression on ARM in a patch that follows), including
|
||||
<linux/kernel.h> causes issues as it brings in a lot of things that are
|
||||
not available in the decompression environment.
|
||||
|
||||
linux/kernel.h brings at least:
|
||||
extern int console_printk[];
|
||||
extern const char hex_asc[];
|
||||
which causes errors at link-time as they are not available when
|
||||
compiling the pre-boot environement. There are also a few others:
|
||||
|
||||
arch/arm/boot/compressed/misc.o: In function `valid_user_regs':
|
||||
arch/arm/include/asm/ptrace.h:158: undefined reference to `elf_hwcap'
|
||||
arch/arm/boot/compressed/misc.o: In function `console_silent':
|
||||
include/linux/kernel.h:292: undefined reference to `console_printk'
|
||||
arch/arm/boot/compressed/misc.o: In function `console_verbose':
|
||||
include/linux/kernel.h:297: undefined reference to `console_printk'
|
||||
arch/arm/boot/compressed/misc.o: In function `pack_hex_byte':
|
||||
include/linux/kernel.h:360: undefined reference to `hex_asc'
|
||||
arch/arm/boot/compressed/misc.o: In function `hweight_long':
|
||||
include/linux/bitops.h:45: undefined reference to `hweight32'
|
||||
arch/arm/boot/compressed/misc.o: In function `__cmpxchg_local_generic':
|
||||
include/asm-generic/cmpxchg-local.h:21: undefined reference to `wrong_size_cmpxchg'
|
||||
include/asm-generic/cmpxchg-local.h:42: undefined reference to `wrong_size_cmpxchg'
|
||||
arch/arm/boot/compressed/misc.o: In function `__xchg':
|
||||
arch/arm/include/asm/system.h:309: undefined reference to `__bad_xchg'
|
||||
|
||||
However, those files apparently use nothing from <linux/kernel.h>, all
|
||||
they need is the declaration of types such as u32 or u64, so
|
||||
<linux/types.h> should be enough
|
||||
|
||||
Signed-off-by: Albin Tonnerre <albin.tonnerre@free-electrons.com>
|
||||
Cc: Sam Ravnborg <sam@ravnborg.org>
|
||||
Cc: Russell King <rmk@arm.linux.org.uk>
|
||||
Cc: Ingo Molnar <mingo@elte.hu>
|
||||
Cc: Thomas Gleixner <tglx@linutronix.de>
|
||||
Cc: "H. Peter Anvin" <hpa@zytor.com>
|
||||
Cc: Phillip Lougher <phillip@lougher.demon.co.uk>
|
||||
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
|
||||
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
|
||||
---
|
||||
include/linux/unaligned/be_byteshift.h | 2 +-
|
||||
include/linux/unaligned/le_byteshift.h | 2 +-
|
||||
2 files changed, 2 insertions(+), 2 deletions(-)
|
||||
|
||||
--- a/include/linux/unaligned/be_byteshift.h
|
||||
+++ b/include/linux/unaligned/be_byteshift.h
|
||||
@@ -1,7 +1,7 @@
|
||||
#ifndef _LINUX_UNALIGNED_BE_BYTESHIFT_H
|
||||
#define _LINUX_UNALIGNED_BE_BYTESHIFT_H
|
||||
|
||||
-#include <linux/kernel.h>
|
||||
+#include <linux/types.h>
|
||||
|
||||
static inline u16 __get_unaligned_be16(const u8 *p)
|
||||
{
|
||||
--- a/include/linux/unaligned/le_byteshift.h
|
||||
+++ b/include/linux/unaligned/le_byteshift.h
|
||||
@@ -1,7 +1,7 @@
|
||||
#ifndef _LINUX_UNALIGNED_LE_BYTESHIFT_H
|
||||
#define _LINUX_UNALIGNED_LE_BYTESHIFT_H
|
||||
|
||||
-#include <linux/kernel.h>
|
||||
+#include <linux/types.h>
|
||||
|
||||
static inline u16 __get_unaligned_le16(const u8 *p)
|
||||
{
|
@ -1,309 +0,0 @@
|
||||
--- /dev/null
|
||||
+++ b/include/linux/decompress/unlzo.h
|
||||
@@ -0,0 +1,10 @@
|
||||
+#ifndef DECOMPRESS_UNLZO_H
|
||||
+#define DECOMPRESS_UNLZO_H
|
||||
+
|
||||
+int unlzo(unsigned char *inbuf, int len,
|
||||
+ int(*fill)(void*, unsigned int),
|
||||
+ int(*flush)(void*, unsigned int),
|
||||
+ unsigned char *output,
|
||||
+ int *pos,
|
||||
+ void(*error)(char *x));
|
||||
+#endif
|
||||
--- a/init/Kconfig
|
||||
+++ b/init/Kconfig
|
||||
@@ -115,10 +115,13 @@ config HAVE_KERNEL_BZIP2
|
||||
config HAVE_KERNEL_LZMA
|
||||
bool
|
||||
|
||||
+config HAVE_KERNEL_LZO
|
||||
+ bool
|
||||
+
|
||||
choice
|
||||
prompt "Kernel compression mode"
|
||||
default KERNEL_GZIP
|
||||
- depends on HAVE_KERNEL_GZIP || HAVE_KERNEL_BZIP2 || HAVE_KERNEL_LZMA
|
||||
+ depends on HAVE_KERNEL_GZIP || HAVE_KERNEL_BZIP2 || HAVE_KERNEL_LZMA || HAVE_KERNEL_LZO
|
||||
help
|
||||
The linux kernel is a kind of self-extracting executable.
|
||||
Several compression algorithms are available, which differ
|
||||
@@ -141,9 +144,8 @@ config KERNEL_GZIP
|
||||
bool "Gzip"
|
||||
depends on HAVE_KERNEL_GZIP
|
||||
help
|
||||
- The old and tried gzip compression. Its compression ratio is
|
||||
- the poorest among the 3 choices; however its speed (both
|
||||
- compression and decompression) is the fastest.
|
||||
+ The old and tried gzip compression. It provides a good balance
|
||||
+ between compression ratio and decompression speed.
|
||||
|
||||
config KERNEL_BZIP2
|
||||
bool "Bzip2"
|
||||
@@ -164,6 +166,14 @@ config KERNEL_LZMA
|
||||
two. Compression is slowest. The kernel size is about 33%
|
||||
smaller with LZMA in comparison to gzip.
|
||||
|
||||
+config KERNEL_LZO
|
||||
+ bool "LZO"
|
||||
+ depends on HAVE_KERNEL_LZO
|
||||
+ help
|
||||
+ Its compression ratio is the poorest among the 4. The kernel
|
||||
+ size is about about 10% bigger than gzip; however its speed
|
||||
+ (both compression and decompression) is the fastest.
|
||||
+
|
||||
endchoice
|
||||
|
||||
config SWAP
|
||||
--- /dev/null
|
||||
+++ b/lib/decompress_unlzo.c
|
||||
@@ -0,0 +1,208 @@
|
||||
+/*
|
||||
+ * LZO decompressor for the Linux kernel. Code borrowed from the lzo
|
||||
+ * implementation by Markus Franz Xaver Johannes Oberhumer.
|
||||
+ *
|
||||
+ * Linux kernel adaptation:
|
||||
+ * Copyright (C) 2009
|
||||
+ * Albin Tonnerre, Free Electrons <albin.tonnerre@free-electrons.com>
|
||||
+ *
|
||||
+ * Original code:
|
||||
+ * Copyright (C) 1996-2005 Markus Franz Xaver Johannes Oberhumer
|
||||
+ * All Rights Reserved.
|
||||
+ *
|
||||
+ * lzop and the LZO library are free software; you can redistribute them
|
||||
+ * and/or modify them 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.
|
||||
+ *
|
||||
+ * This program is distributed in the hope that 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; see the file COPYING.
|
||||
+ * If not, write to the Free Software Foundation, Inc.,
|
||||
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
+ *
|
||||
+ * Markus F.X.J. Oberhumer
|
||||
+ * <markus@oberhumer.com>
|
||||
+ * http://www.oberhumer.com/opensource/lzop/
|
||||
+ */
|
||||
+
|
||||
+#ifdef STATIC
|
||||
+#include "lzo/lzo1x_decompress.c"
|
||||
+#else
|
||||
+#include <linux/slab.h>
|
||||
+#include <linux/decompress/unlzo.h>
|
||||
+#endif
|
||||
+
|
||||
+#include <linux/types.h>
|
||||
+#include <linux/lzo.h>
|
||||
+#include <linux/decompress/mm.h>
|
||||
+
|
||||
+#include <linux/compiler.h>
|
||||
+#include <asm/unaligned.h>
|
||||
+
|
||||
+static const unsigned char lzop_magic[] =
|
||||
+ { 0x89, 0x4c, 0x5a, 0x4f, 0x00, 0x0d, 0x0a, 0x1a, 0x0a };
|
||||
+
|
||||
+#define LZO_BLOCK_SIZE (256*1024l)
|
||||
+#define HEADER_HAS_FILTER 0x00000800L
|
||||
+
|
||||
+STATIC inline int INIT parse_header(u8 *input, u8 *skip)
|
||||
+{
|
||||
+ int l;
|
||||
+ u8 *parse = input;
|
||||
+ u8 level = 0;
|
||||
+ u16 version;
|
||||
+
|
||||
+ /* read magic: 9 first bits */
|
||||
+ for (l = 0; l < 9; l++) {
|
||||
+ if (*parse++ != lzop_magic[l])
|
||||
+ return 0;
|
||||
+ }
|
||||
+ /* get version (2bytes), skip library version (2),
|
||||
+ * 'need to be extracted' version (2) and
|
||||
+ * method (1) */
|
||||
+ version = get_unaligned_be16(parse);
|
||||
+ parse += 7;
|
||||
+ if (version >= 0x0940)
|
||||
+ level = *parse++;
|
||||
+ if (get_unaligned_be32(parse) & HEADER_HAS_FILTER)
|
||||
+ parse += 8; /* flags + filter info */
|
||||
+ else
|
||||
+ parse += 4; /* flags */
|
||||
+
|
||||
+ /* skip mode and mtime_low */
|
||||
+ parse += 8;
|
||||
+ if (version >= 0x0940)
|
||||
+ parse += 4; /* skip mtime_high */
|
||||
+
|
||||
+ l = *parse++;
|
||||
+ /* don't care about the file name, and skip checksum */
|
||||
+ parse += l + 4;
|
||||
+
|
||||
+ *skip = parse - input;
|
||||
+ return 1;
|
||||
+}
|
||||
+
|
||||
+STATIC inline int INIT unlzo(u8 *input, int in_len,
|
||||
+ int (*fill) (void *, unsigned int),
|
||||
+ int (*flush) (void *, unsigned int),
|
||||
+ u8 *output, int *posp,
|
||||
+ void (*error_fn) (char *x))
|
||||
+{
|
||||
+ u8 skip = 0, r = 0;
|
||||
+ u32 src_len, dst_len;
|
||||
+ size_t tmp;
|
||||
+ u8 *in_buf, *in_buf_save, *out_buf;
|
||||
+ int obytes_processed = 0;
|
||||
+
|
||||
+ set_error_fn(error_fn);
|
||||
+
|
||||
+ if (output)
|
||||
+ out_buf = output;
|
||||
+ else if (!flush) {
|
||||
+ error("NULL output pointer and no flush function provided");
|
||||
+ goto exit;
|
||||
+ } else {
|
||||
+ out_buf = malloc(LZO_BLOCK_SIZE);
|
||||
+ if (!out_buf) {
|
||||
+ error("Could not allocate output buffer");
|
||||
+ goto exit;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ if (input && fill) {
|
||||
+ error("Both input pointer and fill function provided, don't know what to do");
|
||||
+ goto exit_1;
|
||||
+ } else if (input)
|
||||
+ in_buf = input;
|
||||
+ else if (!fill || !posp) {
|
||||
+ error("NULL input pointer and missing position pointer or fill function");
|
||||
+ goto exit_1;
|
||||
+ } else {
|
||||
+ in_buf = malloc(lzo1x_worst_compress(LZO_BLOCK_SIZE));
|
||||
+ if (!in_buf) {
|
||||
+ error("Could not allocate input buffer");
|
||||
+ goto exit_1;
|
||||
+ }
|
||||
+ }
|
||||
+ in_buf_save = in_buf;
|
||||
+
|
||||
+ if (posp)
|
||||
+ *posp = 0;
|
||||
+
|
||||
+ if (fill)
|
||||
+ fill(in_buf, lzo1x_worst_compress(LZO_BLOCK_SIZE));
|
||||
+
|
||||
+ if (!parse_header(input, &skip)) {
|
||||
+ error("invalid header");
|
||||
+ goto exit_2;
|
||||
+ }
|
||||
+ in_buf += skip;
|
||||
+
|
||||
+ if (posp)
|
||||
+ *posp = skip;
|
||||
+
|
||||
+ for (;;) {
|
||||
+ /* read uncompressed block size */
|
||||
+ dst_len = get_unaligned_be32(in_buf);
|
||||
+ in_buf += 4;
|
||||
+
|
||||
+ /* exit if last block */
|
||||
+ if (dst_len == 0) {
|
||||
+ if (posp)
|
||||
+ *posp += 4;
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ if (dst_len > LZO_BLOCK_SIZE) {
|
||||
+ error("dest len longer than block size");
|
||||
+ goto exit_2;
|
||||
+ }
|
||||
+
|
||||
+ /* read compressed block size, and skip block checksum info */
|
||||
+ src_len = get_unaligned_be32(in_buf);
|
||||
+ in_buf += 8;
|
||||
+
|
||||
+ if (src_len <= 0 || src_len > dst_len) {
|
||||
+ error("file corrupted");
|
||||
+ goto exit_2;
|
||||
+ }
|
||||
+
|
||||
+ /* decompress */
|
||||
+ tmp = dst_len;
|
||||
+ r = lzo1x_decompress_safe((u8 *) in_buf, src_len, out_buf, &tmp);
|
||||
+
|
||||
+ if (r != LZO_E_OK || dst_len != tmp) {
|
||||
+ error("Compressed data violation");
|
||||
+ goto exit_2;
|
||||
+ }
|
||||
+
|
||||
+ obytes_processed += dst_len;
|
||||
+ if (flush)
|
||||
+ flush(out_buf, dst_len);
|
||||
+ if (output)
|
||||
+ out_buf += dst_len;
|
||||
+ if (posp)
|
||||
+ *posp += src_len + 12;
|
||||
+ if (fill) {
|
||||
+ in_buf = in_buf_save;
|
||||
+ fill(in_buf, lzo1x_worst_compress(LZO_BLOCK_SIZE));
|
||||
+ } else
|
||||
+ in_buf += src_len;
|
||||
+ }
|
||||
+
|
||||
+exit_2:
|
||||
+ if (!input)
|
||||
+ free(in_buf);
|
||||
+exit_1:
|
||||
+ if (!output)
|
||||
+ free(out_buf);
|
||||
+exit:
|
||||
+ return obytes_processed;
|
||||
+}
|
||||
+
|
||||
+#define decompress unlzo
|
||||
--- a/lib/lzo/lzo1x_decompress.c
|
||||
+++ b/lib/lzo/lzo1x_decompress.c
|
||||
@@ -11,11 +11,13 @@
|
||||
* Richard Purdie <rpurdie@openedhand.com>
|
||||
*/
|
||||
|
||||
+#ifndef STATIC
|
||||
#include <linux/module.h>
|
||||
#include <linux/kernel.h>
|
||||
-#include <linux/lzo.h>
|
||||
-#include <asm/byteorder.h>
|
||||
+#endif
|
||||
+
|
||||
#include <asm/unaligned.h>
|
||||
+#include <linux/lzo.h>
|
||||
#include "lzodefs.h"
|
||||
|
||||
#define HAVE_IP(x, ip_end, ip) ((size_t)(ip_end - ip) < (x))
|
||||
@@ -244,9 +246,10 @@ lookbehind_overrun:
|
||||
*out_len = op - out;
|
||||
return LZO_E_LOOKBEHIND_OVERRUN;
|
||||
}
|
||||
-
|
||||
+#ifndef STATIC
|
||||
EXPORT_SYMBOL_GPL(lzo1x_decompress_safe);
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_DESCRIPTION("LZO1X Decompressor");
|
||||
|
||||
+#endif
|
||||
--- a/scripts/Makefile.lib
|
||||
+++ b/scripts/Makefile.lib
|
||||
@@ -230,3 +230,8 @@ quiet_cmd_lzma = LZMA $@
|
||||
cmd_lzma = (cat $(filter-out FORCE,$^) | \
|
||||
lzma -9 && $(call size_append, $(filter-out FORCE,$^))) > $@ || \
|
||||
(rm -f $@ ; false)
|
||||
+
|
||||
+quiet_cmd_lzo = LZO $@
|
||||
+cmd_lzo = (cat $(filter-out FORCE,$^) | \
|
||||
+ lzop -9 && $(call size_append, $(filter-out FORCE,$^))) > $@ || \
|
||||
+ (rm -f $@ ; false)
|
@ -1,283 +0,0 @@
|
||||
--- a/arch/arm/Kconfig
|
||||
+++ b/arch/arm/Kconfig
|
||||
@@ -18,6 +18,8 @@ config ARM
|
||||
select HAVE_KRETPROBES if (HAVE_KPROBES)
|
||||
select HAVE_FUNCTION_TRACER if (!XIP_KERNEL)
|
||||
select HAVE_GENERIC_DMA_COHERENT
|
||||
+ select HAVE_KERNEL_GZIP
|
||||
+ select HAVE_KERNEL_LZO
|
||||
help
|
||||
The ARM series is a line of low-power-consumption RISC chip designs
|
||||
licensed by ARM Ltd and targeted at embedded applications and
|
||||
--- a/arch/arm/boot/compressed/Makefile
|
||||
+++ b/arch/arm/boot/compressed/Makefile
|
||||
@@ -63,8 +63,12 @@ endif
|
||||
|
||||
SEDFLAGS = s/TEXT_START/$(ZTEXTADDR)/;s/BSS_START/$(ZBSSADDR)/
|
||||
|
||||
-targets := vmlinux vmlinux.lds piggy.gz piggy.o font.o font.c \
|
||||
- head.o misc.o $(OBJS)
|
||||
+suffix_$(CONFIG_KERNEL_GZIP) = gzip
|
||||
+suffix_$(CONFIG_KERNEL_LZO) = lzo
|
||||
+
|
||||
+targets := vmlinux vmlinux.lds \
|
||||
+ piggy.$(suffix_y) piggy.$(suffix_y).o \
|
||||
+ font.o font.c head.o misc.o $(OBJS)
|
||||
|
||||
ifeq ($(CONFIG_FUNCTION_TRACER),y)
|
||||
ORIG_CFLAGS := $(KBUILD_CFLAGS)
|
||||
@@ -87,22 +91,31 @@ endif
|
||||
ifneq ($(PARAMS_PHYS),)
|
||||
LDFLAGS_vmlinux += --defsym params_phys=$(PARAMS_PHYS)
|
||||
endif
|
||||
-LDFLAGS_vmlinux += -p --no-undefined -X \
|
||||
- $(shell $(CC) $(KBUILD_CFLAGS) --print-libgcc-file-name) -T
|
||||
+# ?
|
||||
+LDFLAGS_vmlinux += -p
|
||||
+# Report unresolved symbol references
|
||||
+LDFLAGS_vmlinux += --no-undefined
|
||||
+# Delete all temporary local symbols
|
||||
+LDFLAGS_vmlinux += -X
|
||||
+# Next argument is a linker script
|
||||
+LDFLAGS_vmlinux += -T
|
||||
+
|
||||
+# For __aeabi_uidivmod
|
||||
+lib1funcs = $(srctree)/arch/$(SRCARCH)/lib/lib1funcs.o
|
||||
|
||||
# Don't allow any static data in misc.o, which
|
||||
# would otherwise mess up our GOT table
|
||||
CFLAGS_misc.o := -Dstatic=
|
||||
|
||||
-$(obj)/vmlinux: $(obj)/vmlinux.lds $(obj)/$(HEAD) $(obj)/piggy.o \
|
||||
- $(addprefix $(obj)/, $(OBJS)) FORCE
|
||||
+$(obj)/vmlinux: $(obj)/vmlinux.lds $(obj)/$(HEAD) $(obj)/piggy.$(suffix_y).o \
|
||||
+ $(addprefix $(obj)/, $(OBJS)) $(lib1funcs) FORCE
|
||||
$(call if_changed,ld)
|
||||
@:
|
||||
|
||||
-$(obj)/piggy.gz: $(obj)/../Image FORCE
|
||||
- $(call if_changed,gzip)
|
||||
+$(obj)/piggy.$(suffix_y): $(obj)/../Image FORCE
|
||||
+ $(call if_changed,$(suffix_y))
|
||||
|
||||
-$(obj)/piggy.o: $(obj)/piggy.gz FORCE
|
||||
+$(obj)/piggy.$(suffix_y).o: $(obj)/piggy.$(suffix_y) FORCE
|
||||
|
||||
CFLAGS_font.o := -Dstatic=
|
||||
|
||||
--- a/arch/arm/boot/compressed/misc.c
|
||||
+++ b/arch/arm/boot/compressed/misc.c
|
||||
@@ -18,10 +18,15 @@
|
||||
|
||||
unsigned int __machine_arch_type;
|
||||
|
||||
+#define _LINUX_STRING_H_
|
||||
+
|
||||
#include <linux/compiler.h> /* for inline */
|
||||
#include <linux/types.h> /* for size_t */
|
||||
#include <linux/stddef.h> /* for NULL */
|
||||
#include <asm/string.h>
|
||||
+#include <linux/linkage.h>
|
||||
+
|
||||
+#include <asm/unaligned.h>
|
||||
|
||||
#ifdef STANDALONE_DEBUG
|
||||
#define putstr printf
|
||||
@@ -188,34 +193,8 @@ static inline __ptr_t memcpy(__ptr_t __d
|
||||
/*
|
||||
* gzip delarations
|
||||
*/
|
||||
-#define OF(args) args
|
||||
#define STATIC static
|
||||
|
||||
-typedef unsigned char uch;
|
||||
-typedef unsigned short ush;
|
||||
-typedef unsigned long ulg;
|
||||
-
|
||||
-#define WSIZE 0x8000 /* Window size must be at least 32k, */
|
||||
- /* and a power of two */
|
||||
-
|
||||
-static uch *inbuf; /* input buffer */
|
||||
-static uch window[WSIZE]; /* Sliding window buffer */
|
||||
-
|
||||
-static unsigned insize; /* valid bytes in inbuf */
|
||||
-static unsigned inptr; /* index of next byte to be processed in inbuf */
|
||||
-static unsigned outcnt; /* bytes in output buffer */
|
||||
-
|
||||
-/* gzip flag byte */
|
||||
-#define ASCII_FLAG 0x01 /* bit 0 set: file probably ascii text */
|
||||
-#define CONTINUATION 0x02 /* bit 1 set: continuation of multi-part gzip file */
|
||||
-#define EXTRA_FIELD 0x04 /* bit 2 set: extra field present */
|
||||
-#define ORIG_NAME 0x08 /* bit 3 set: original file name present */
|
||||
-#define COMMENT 0x10 /* bit 4 set: file comment present */
|
||||
-#define ENCRYPTED 0x20 /* bit 5 set: file is encrypted */
|
||||
-#define RESERVED 0xC0 /* bit 6,7: reserved */
|
||||
-
|
||||
-#define get_byte() (inptr < insize ? inbuf[inptr++] : fill_inbuf())
|
||||
-
|
||||
/* Diagnostic functions */
|
||||
#ifdef DEBUG
|
||||
# define Assert(cond,msg) {if(!(cond)) error(msg);}
|
||||
@@ -233,24 +212,20 @@ static unsigned outcnt; /* bytes in out
|
||||
# define Tracecv(c,x)
|
||||
#endif
|
||||
|
||||
-static int fill_inbuf(void);
|
||||
-static void flush_window(void);
|
||||
static void error(char *m);
|
||||
|
||||
extern char input_data[];
|
||||
extern char input_data_end[];
|
||||
|
||||
-static uch *output_data;
|
||||
-static ulg output_ptr;
|
||||
-static ulg bytes_out;
|
||||
+static unsigned char *output_data;
|
||||
+static unsigned long output_ptr;
|
||||
|
||||
static void error(char *m);
|
||||
|
||||
static void putstr(const char *);
|
||||
|
||||
-extern int end;
|
||||
-static ulg free_mem_ptr;
|
||||
-static ulg free_mem_end_ptr;
|
||||
+static unsigned long free_mem_ptr;
|
||||
+static unsigned long free_mem_end_ptr;
|
||||
|
||||
#ifdef STANDALONE_DEBUG
|
||||
#define NO_INFLATE_MALLOC
|
||||
@@ -258,46 +233,13 @@ static ulg free_mem_end_ptr;
|
||||
|
||||
#define ARCH_HAS_DECOMP_WDOG
|
||||
|
||||
-#include "../../../../lib/inflate.c"
|
||||
-
|
||||
-/* ===========================================================================
|
||||
- * Fill the input buffer. This is called only when the buffer is empty
|
||||
- * and at least one byte is really needed.
|
||||
- */
|
||||
-int fill_inbuf(void)
|
||||
-{
|
||||
- if (insize != 0)
|
||||
- error("ran out of input data");
|
||||
-
|
||||
- inbuf = input_data;
|
||||
- insize = &input_data_end[0] - &input_data[0];
|
||||
-
|
||||
- inptr = 1;
|
||||
- return inbuf[0];
|
||||
-}
|
||||
+#ifdef CONFIG_KERNEL_GZIP
|
||||
+#include "../../../../lib/decompress_inflate.c"
|
||||
+#endif
|
||||
|
||||
-/* ===========================================================================
|
||||
- * Write the output window window[0..outcnt-1] and update crc and bytes_out.
|
||||
- * (Used for the decompressed data only.)
|
||||
- */
|
||||
-void flush_window(void)
|
||||
-{
|
||||
- ulg c = crc;
|
||||
- unsigned n;
|
||||
- uch *in, *out, ch;
|
||||
-
|
||||
- in = window;
|
||||
- out = &output_data[output_ptr];
|
||||
- for (n = 0; n < outcnt; n++) {
|
||||
- ch = *out++ = *in++;
|
||||
- c = crc_32_tab[((int)c ^ ch) & 0xff] ^ (c >> 8);
|
||||
- }
|
||||
- crc = c;
|
||||
- bytes_out += (ulg)outcnt;
|
||||
- output_ptr += (ulg)outcnt;
|
||||
- outcnt = 0;
|
||||
- putstr(".");
|
||||
-}
|
||||
+#ifdef CONFIG_KERNEL_LZO
|
||||
+#include "../../../../lib/decompress_unlzo.c"
|
||||
+#endif
|
||||
|
||||
#ifndef arch_error
|
||||
#define arch_error(x)
|
||||
@@ -314,22 +256,33 @@ static void error(char *x)
|
||||
while(1); /* Halt */
|
||||
}
|
||||
|
||||
+asmlinkage void __div0(void)
|
||||
+{
|
||||
+ error("Attempting division by 0!");
|
||||
+}
|
||||
+
|
||||
#ifndef STANDALONE_DEBUG
|
||||
|
||||
-ulg
|
||||
-decompress_kernel(ulg output_start, ulg free_mem_ptr_p, ulg free_mem_ptr_end_p,
|
||||
- int arch_id)
|
||||
+unsigned long
|
||||
+decompress_kernel(unsigned long output_start, unsigned long free_mem_ptr_p,
|
||||
+ unsigned long free_mem_ptr_end_p,
|
||||
+ int arch_id)
|
||||
{
|
||||
- output_data = (uch *)output_start; /* Points to kernel start */
|
||||
+ unsigned char *tmp;
|
||||
+
|
||||
+ output_data = (unsigned char *)output_start;
|
||||
free_mem_ptr = free_mem_ptr_p;
|
||||
free_mem_end_ptr = free_mem_ptr_end_p;
|
||||
__machine_arch_type = arch_id;
|
||||
|
||||
arch_decomp_setup();
|
||||
|
||||
- makecrc();
|
||||
+ tmp = (unsigned char *) (((unsigned long)input_data_end) - 4);
|
||||
+ output_ptr = get_unaligned_le32(tmp);
|
||||
+
|
||||
putstr("Uncompressing Linux...");
|
||||
- gunzip();
|
||||
+ decompress(input_data, input_data_end - input_data,
|
||||
+ NULL, NULL, output_data, NULL, error);
|
||||
putstr(" done, booting the kernel.\n");
|
||||
return output_ptr;
|
||||
}
|
||||
@@ -341,11 +294,10 @@ int main()
|
||||
{
|
||||
output_data = output_buffer;
|
||||
|
||||
- makecrc();
|
||||
putstr("Uncompressing Linux...");
|
||||
- gunzip();
|
||||
+ decompress(input_data, input_data_end - input_data,
|
||||
+ NULL, NULL, output_data, NULL, error);
|
||||
putstr("done.\n");
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
-
|
||||
--- a/arch/arm/boot/compressed/piggy.S
|
||||
+++ /dev/null
|
||||
@@ -1,6 +0,0 @@
|
||||
- .section .piggydata,#alloc
|
||||
- .globl input_data
|
||||
-input_data:
|
||||
- .incbin "arch/arm/boot/compressed/piggy.gz"
|
||||
- .globl input_data_end
|
||||
-input_data_end:
|
||||
--- /dev/null
|
||||
+++ b/arch/arm/boot/compressed/piggy.gzip.S
|
||||
@@ -0,0 +1,6 @@
|
||||
+ .section .piggydata,#alloc
|
||||
+ .globl input_data
|
||||
+input_data:
|
||||
+ .incbin "arch/arm/boot/compressed/piggy.gzip"
|
||||
+ .globl input_data_end
|
||||
+input_data_end:
|
||||
--- /dev/null
|
||||
+++ b/arch/arm/boot/compressed/piggy.lzo.S
|
||||
@@ -0,0 +1,6 @@
|
||||
+ .section .piggydata,#alloc
|
||||
+ .globl input_data
|
||||
+input_data:
|
||||
+ .incbin "arch/arm/boot/compressed/piggy.lzo"
|
||||
+ .globl input_data_end
|
||||
+input_data_end:
|
@ -1,48 +0,0 @@
|
||||
--- a/arch/x86/Kconfig
|
||||
+++ b/arch/x86/Kconfig
|
||||
@@ -49,6 +49,7 @@ config X86
|
||||
select HAVE_KERNEL_GZIP
|
||||
select HAVE_KERNEL_BZIP2
|
||||
select HAVE_KERNEL_LZMA
|
||||
+ select HAVE_KERNEL_LZO
|
||||
select HAVE_ARCH_KMEMCHECK
|
||||
|
||||
config OUTPUT_FORMAT
|
||||
--- a/arch/x86/boot/compressed/Makefile
|
||||
+++ b/arch/x86/boot/compressed/Makefile
|
||||
@@ -4,7 +4,7 @@
|
||||
# create a compressed vmlinux image from the original vmlinux
|
||||
#
|
||||
|
||||
-targets := vmlinux.lds vmlinux vmlinux.bin vmlinux.bin.gz vmlinux.bin.bz2 vmlinux.bin.lzma head_$(BITS).o misc.o piggy.o
|
||||
+targets := vmlinux.lds vmlinux vmlinux.bin vmlinux.bin.gz vmlinux.bin.bz2 vmlinux.bin.lzma vmlinux.bin.lzo head_$(BITS).o misc.o piggy.o
|
||||
|
||||
KBUILD_CFLAGS := -m$(BITS) -D__KERNEL__ $(LINUX_INCLUDE) -O2
|
||||
KBUILD_CFLAGS += -fno-strict-aliasing -fPIC
|
||||
@@ -48,10 +48,13 @@ $(obj)/vmlinux.bin.bz2: $(vmlinux.bin.al
|
||||
$(call if_changed,bzip2)
|
||||
$(obj)/vmlinux.bin.lzma: $(vmlinux.bin.all-y) FORCE
|
||||
$(call if_changed,lzma)
|
||||
+$(obj)/vmlinux.bin.lzo: $(vmlinux.bin.all-y) FORCE
|
||||
+ $(call if_changed,lzo)
|
||||
|
||||
suffix-$(CONFIG_KERNEL_GZIP) := gz
|
||||
suffix-$(CONFIG_KERNEL_BZIP2) := bz2
|
||||
suffix-$(CONFIG_KERNEL_LZMA) := lzma
|
||||
+suffix-$(CONFIG_KERNEL_LZO) := lzo
|
||||
|
||||
quiet_cmd_mkpiggy = MKPIGGY $@
|
||||
cmd_mkpiggy = $(obj)/mkpiggy $< > $@ || ( rm -f $@ ; false )
|
||||
--- a/arch/x86/boot/compressed/misc.c
|
||||
+++ b/arch/x86/boot/compressed/misc.c
|
||||
@@ -162,6 +162,10 @@ static int lines, cols;
|
||||
#include "../../../../lib/decompress_unlzma.c"
|
||||
#endif
|
||||
|
||||
+#ifdef CONFIG_KERNEL_LZO
|
||||
+#include "../../../../lib/decompress_unlzo.c"
|
||||
+#endif
|
||||
+
|
||||
static void scroll(void)
|
||||
{
|
||||
int i;
|
@ -1,106 +0,0 @@
|
||||
--- a/lib/Kconfig
|
||||
+++ b/lib/Kconfig
|
||||
@@ -120,6 +120,10 @@ config DECOMPRESS_LZMA
|
||||
config DECOMPRESS_LZMA_NEEDED
|
||||
boolean
|
||||
|
||||
+config DECOMPRESS_LZO
|
||||
+ select LZO_DECOMPRESS
|
||||
+ tristate
|
||||
+
|
||||
#
|
||||
# Generic allocator support is selected if needed
|
||||
#
|
||||
--- a/lib/Makefile
|
||||
+++ b/lib/Makefile
|
||||
@@ -69,6 +69,7 @@ obj-$(CONFIG_LZO_DECOMPRESS) += lzo/
|
||||
lib-$(CONFIG_DECOMPRESS_GZIP) += decompress_inflate.o
|
||||
lib-$(CONFIG_DECOMPRESS_BZIP2) += decompress_bunzip2.o
|
||||
lib-$(CONFIG_DECOMPRESS_LZMA) += decompress_unlzma.o
|
||||
+lib-$(CONFIG_DECOMPRESS_LZO) += decompress_unlzo.o
|
||||
|
||||
obj-$(CONFIG_TEXTSEARCH) += textsearch.o
|
||||
obj-$(CONFIG_TEXTSEARCH_KMP) += ts_kmp.o
|
||||
--- a/lib/decompress.c
|
||||
+++ b/lib/decompress.c
|
||||
@@ -9,6 +9,7 @@
|
||||
#include <linux/decompress/bunzip2.h>
|
||||
#include <linux/decompress/unlzma.h>
|
||||
#include <linux/decompress/inflate.h>
|
||||
+#include <linux/decompress/unlzo.h>
|
||||
|
||||
#include <linux/types.h>
|
||||
#include <linux/string.h>
|
||||
@@ -22,6 +23,9 @@
|
||||
#ifndef CONFIG_DECOMPRESS_LZMA
|
||||
# define unlzma NULL
|
||||
#endif
|
||||
+#ifndef CONFIG_DECOMPRESS_LZO
|
||||
+# define unlzo NULL
|
||||
+#endif
|
||||
|
||||
static const struct compress_format {
|
||||
unsigned char magic[2];
|
||||
@@ -32,6 +36,7 @@ static const struct compress_format {
|
||||
{ {037, 0236}, "gzip", gunzip },
|
||||
{ {0x42, 0x5a}, "bzip2", bunzip2 },
|
||||
{ {0x5d, 0x00}, "lzma", unlzma },
|
||||
+ { {0x89, 0x4c}, "lzo", unlzo },
|
||||
{ {0, 0}, NULL, NULL }
|
||||
};
|
||||
|
||||
--- a/usr/Kconfig
|
||||
+++ b/usr/Kconfig
|
||||
@@ -72,6 +72,15 @@ config RD_LZMA
|
||||
Support loading of a LZMA encoded initial ramdisk or cpio buffer
|
||||
If unsure, say N.
|
||||
|
||||
+config RD_LZO
|
||||
+ bool "Support initial ramdisks compressed using LZO" if EMBEDDED
|
||||
+ default !EMBEDDED
|
||||
+ depends on BLK_DEV_INITRD && HAVE_KERNEL_LZO
|
||||
+ select DECOMPRESS_LZO
|
||||
+ help
|
||||
+ Support loading of a LZO encoded initial ramdisk or cpio buffer
|
||||
+ If unsure, say N.
|
||||
+
|
||||
choice
|
||||
prompt "Built-in initramfs compression mode" if INITRAMFS_SOURCE!=""
|
||||
help
|
||||
@@ -108,16 +117,15 @@ config INITRAMFS_COMPRESSION_GZIP
|
||||
bool "Gzip"
|
||||
depends on RD_GZIP
|
||||
help
|
||||
- The old and tried gzip compression. Its compression ratio is
|
||||
- the poorest among the 3 choices; however its speed (both
|
||||
- compression and decompression) is the fastest.
|
||||
+ The old and tried gzip compression. It provides a good balance
|
||||
+ between compression ratio and decompression speed.
|
||||
|
||||
config INITRAMFS_COMPRESSION_BZIP2
|
||||
bool "Bzip2"
|
||||
depends on RD_BZIP2
|
||||
help
|
||||
Its compression ratio and speed is intermediate.
|
||||
- Decompression speed is slowest among the three. The initramfs
|
||||
+ Decompression speed is slowest among the four. The initramfs
|
||||
size is about 10% smaller with bzip2, in comparison to gzip.
|
||||
Bzip2 uses a large amount of memory. For modern kernels you
|
||||
will need at least 8MB RAM or more for booting.
|
||||
@@ -128,7 +136,15 @@ config INITRAMFS_COMPRESSION_LZMA
|
||||
help
|
||||
The most recent compression algorithm.
|
||||
Its ratio is best, decompression speed is between the other
|
||||
- two. Compression is slowest. The initramfs size is about 33%
|
||||
+ three. Compression is slowest. The initramfs size is about 33%
|
||||
smaller with LZMA in comparison to gzip.
|
||||
|
||||
+config INITRAMFS_COMPRESSION_LZO
|
||||
+ bool "LZO"
|
||||
+ depends on RD_LZO
|
||||
+ help
|
||||
+ Its compression ratio is the poorest among the four. The kernel
|
||||
+ size is about about 10% bigger than gzip; however its speed
|
||||
+ (both compression and decompression) is the fastest.
|
||||
+
|
||||
endchoice
|
@ -1,57 +0,0 @@
|
||||
From d0f226a0f104c7d1da1d215b8013359273e39e18 Mon Sep 17 00:00:00 2001
|
||||
From: Albin Tonnerre <albin.tonnerre@free-electrons.com>
|
||||
Date: Fri, 16 Oct 2009 16:17:22 +0200
|
||||
Subject: [PATCH] Add LZMA decompression on ARM
|
||||
|
||||
|
||||
Signed-off-by: Albin Tonnerre <albin.tonnerre@free-electrons.com>
|
||||
---
|
||||
arch/arm/Kconfig | 1 +
|
||||
arch/arm/boot/compressed/Makefile | 1 +
|
||||
arch/arm/boot/compressed/misc.c | 4 ++++
|
||||
arch/arm/boot/compressed/piggy.lzma.S | 6 ++++++
|
||||
4 files changed, 12 insertions(+), 0 deletions(-)
|
||||
create mode 100644 arch/arm/boot/compressed/piggy.lzma.S
|
||||
|
||||
--- a/arch/arm/Kconfig
|
||||
+++ b/arch/arm/Kconfig
|
||||
@@ -20,6 +20,7 @@ config ARM
|
||||
select HAVE_GENERIC_DMA_COHERENT
|
||||
select HAVE_KERNEL_GZIP
|
||||
select HAVE_KERNEL_LZO
|
||||
+ select HAVE_KERNEL_LZMA
|
||||
help
|
||||
The ARM series is a line of low-power-consumption RISC chip designs
|
||||
licensed by ARM Ltd and targeted at embedded applications and
|
||||
--- a/arch/arm/boot/compressed/Makefile
|
||||
+++ b/arch/arm/boot/compressed/Makefile
|
||||
@@ -65,6 +65,7 @@ SEDFLAGS = s/TEXT_START/$(ZTEXTADDR)/;s/
|
||||
|
||||
suffix_$(CONFIG_KERNEL_GZIP) = gzip
|
||||
suffix_$(CONFIG_KERNEL_LZO) = lzo
|
||||
+suffix_$(CONFIG_KERNEL_LZMA) = lzma
|
||||
|
||||
targets := vmlinux vmlinux.lds \
|
||||
piggy.$(suffix_y) piggy.$(suffix_y).o \
|
||||
--- a/arch/arm/boot/compressed/misc.c
|
||||
+++ b/arch/arm/boot/compressed/misc.c
|
||||
@@ -237,6 +237,10 @@ static unsigned long free_mem_end_ptr;
|
||||
#include "../../../../lib/decompress_inflate.c"
|
||||
#endif
|
||||
|
||||
+#ifdef CONFIG_KERNEL_LZMA
|
||||
+#include "../../../../lib/decompress_unlzma.c"
|
||||
+#endif
|
||||
+
|
||||
#ifdef CONFIG_KERNEL_LZO
|
||||
#include "../../../../lib/decompress_unlzo.c"
|
||||
#endif
|
||||
--- /dev/null
|
||||
+++ b/arch/arm/boot/compressed/piggy.lzma.S
|
||||
@@ -0,0 +1,6 @@
|
||||
+ .section .piggydata,#alloc
|
||||
+ .globl input_data
|
||||
+input_data:
|
||||
+ .incbin "arch/arm/boot/compressed/piggy.lzma"
|
||||
+ .globl input_data_end
|
||||
+input_data_end:
|
@ -1,110 +0,0 @@
|
||||
--- a/drivers/mtd/devices/block2mtd.c
|
||||
+++ b/drivers/mtd/devices/block2mtd.c
|
||||
@@ -14,6 +14,7 @@
|
||||
#include <linux/list.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/mtd/mtd.h>
|
||||
+#include <linux/mtd/partitions.h>
|
||||
#include <linux/buffer_head.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/mount.h>
|
||||
@@ -232,10 +233,11 @@ 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)
|
||||
{
|
||||
struct block_device *bdev;
|
||||
struct block2mtd_dev *dev;
|
||||
+ struct mtd_partition *part;
|
||||
char *name;
|
||||
|
||||
if (!devname)
|
||||
@@ -273,17 +275,17 @@ static struct block2mtd_dev *add_device(
|
||||
|
||||
mutex_init(&dev->write_mutex);
|
||||
|
||||
- /* Setup the MTD structure */
|
||||
- /* make the name contain the block device in */
|
||||
- name = kmalloc(sizeof("block2mtd: ") + strlen(devname) + 1,
|
||||
- GFP_KERNEL);
|
||||
+ if (!mtdname)
|
||||
+ mtdname = devname;
|
||||
+
|
||||
+ name = kmalloc(strlen(mtdname) + 1, GFP_KERNEL);
|
||||
if (!name)
|
||||
goto devinit_err;
|
||||
|
||||
- sprintf(name, "block2mtd: %s", devname);
|
||||
+ 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;
|
||||
@@ -296,14 +298,17 @@ static struct block2mtd_dev *add_device(
|
||||
dev->mtd.priv = dev;
|
||||
dev->mtd.owner = THIS_MODULE;
|
||||
|
||||
- if (add_mtd_device(&dev->mtd)) {
|
||||
+ part = kzalloc(sizeof(struct mtd_partition), GFP_KERNEL);
|
||||
+ part->name = dev->mtd.name;
|
||||
+ part->offset = 0;
|
||||
+ part->size = dev->mtd.size;
|
||||
+ if (add_mtd_partitions(&dev->mtd, part, 1)) {
|
||||
/* Device didnt 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:
|
||||
@@ -376,9 +381,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;
|
||||
@@ -389,7 +394,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)
|
||||
@@ -408,8 +413,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;
|
||||
}
|
||||
@@ -443,7 +450,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)
|
||||
{
|
@ -1,627 +0,0 @@
|
||||
--- a/drivers/mtd/Kconfig
|
||||
+++ b/drivers/mtd/Kconfig
|
||||
@@ -53,6 +53,16 @@ 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"
|
||||
+ depends on MTD_PARTITIONS
|
||||
+ default y
|
||||
+
|
||||
+config MTD_ROOTFS_SPLIT
|
||||
+ bool "Automatically split 'rootfs' partition for squashfs"
|
||||
+ depends on MTD_PARTITIONS
|
||||
+ default y
|
||||
+
|
||||
config MTD_REDBOOT_PARTS
|
||||
tristate "RedBoot partition table parsing"
|
||||
depends on MTD_PARTITIONS
|
||||
--- a/drivers/mtd/mtdpart.c
|
||||
+++ b/drivers/mtd/mtdpart.c
|
||||
@@ -18,6 +18,8 @@
|
||||
#include <linux/mtd/mtd.h>
|
||||
#include <linux/mtd/partitions.h>
|
||||
#include <linux/mtd/compatmac.h>
|
||||
+#include <linux/root_dev.h>
|
||||
+#include <linux/magic.h>
|
||||
|
||||
/* Our partition linked list */
|
||||
static LIST_HEAD(mtd_partitions);
|
||||
@@ -35,7 +37,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
|
||||
@@ -502,6 +504,152 @@ out_register:
|
||||
return slave;
|
||||
}
|
||||
|
||||
+#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 split_offset = 0;
|
||||
+ int ret;
|
||||
+
|
||||
+ 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 = add_one_partition(master, dpart, 0, split_offset);
|
||||
+ if (!slave) {
|
||||
+ kfree(dpart);
|
||||
+ return -ENOMEM;
|
||||
+ }
|
||||
+ 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
|
||||
@@ -517,7 +665,7 @@ int add_mtd_partitions(struct mtd_info *
|
||||
{
|
||||
struct mtd_part *slave;
|
||||
uint64_t cur_offset = 0;
|
||||
- int i;
|
||||
+ int i, ret;
|
||||
|
||||
printk(KERN_NOTICE "Creating %d MTD partitions on \"%s\":\n", nbparts, master->name);
|
||||
|
||||
@@ -525,6 +673,21 @@ int add_mtd_partitions(struct mtd_info *
|
||||
slave = add_one_partition(master, parts + i, i, cur_offset);
|
||||
if (!slave)
|
||||
return -ENOMEM;
|
||||
+
|
||||
+ 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;
|
||||
}
|
||||
|
||||
@@ -532,6 +695,32 @@ int add_mtd_partitions(struct mtd_info *
|
||||
}
|
||||
EXPORT_SYMBOL(add_mtd_partitions);
|
||||
|
||||
+int refresh_mtd_partitions(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(refresh_mtd_partitions);
|
||||
+
|
||||
static DEFINE_SPINLOCK(part_parser_lock);
|
||||
static LIST_HEAD(part_parsers);
|
||||
|
||||
--- a/drivers/mtd/devices/block2mtd.c
|
||||
+++ b/drivers/mtd/devices/block2mtd.c
|
||||
@@ -29,6 +29,8 @@ struct block2mtd_dev {
|
||||
struct block_device *blkdev;
|
||||
struct mtd_info mtd;
|
||||
struct mutex write_mutex;
|
||||
+ rwlock_t bdev_mutex;
|
||||
+ char devname[0];
|
||||
};
|
||||
|
||||
|
||||
@@ -81,6 +83,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,52 +246,29 @@ static int block2mtd_write(struct mtd_in
|
||||
static void block2mtd_sync(struct mtd_info *mtd)
|
||||
{
|
||||
struct block2mtd_dev *dev = mtd->priv;
|
||||
- sync_blockdev(dev->blkdev);
|
||||
- return;
|
||||
-}
|
||||
-
|
||||
-
|
||||
-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);
|
||||
- close_bdev_exclusive(dev->blkdev, FMODE_READ|FMODE_WRITE);
|
||||
- }
|
||||
+ read_lock(&dev->bdev_mutex);
|
||||
+ if (dev->blkdev)
|
||||
+ sync_blockdev(dev->blkdev);
|
||||
+ read_unlock(&dev->bdev_mutex);
|
||||
|
||||
- kfree(dev);
|
||||
+ return;
|
||||
}
|
||||
|
||||
|
||||
-/* FIXME: ensure that mtd->size % erase_size == 0 */
|
||||
-static struct block2mtd_dev *add_device(char *devname, int erase_size, const char *mtdname)
|
||||
+static int _open_bdev(struct block2mtd_dev *dev)
|
||||
{
|
||||
struct block_device *bdev;
|
||||
- struct block2mtd_dev *dev;
|
||||
- struct mtd_partition *part;
|
||||
- char *name;
|
||||
-
|
||||
- if (!devname)
|
||||
- return NULL;
|
||||
-
|
||||
- dev = kzalloc(sizeof(struct block2mtd_dev), GFP_KERNEL);
|
||||
- if (!dev)
|
||||
- return NULL;
|
||||
|
||||
/* Get a handle on the device */
|
||||
- bdev = open_bdev_exclusive(devname, FMODE_READ|FMODE_WRITE, NULL);
|
||||
+ bdev = open_bdev_exclusive(dev->devname, FMODE_READ|FMODE_WRITE, NULL);
|
||||
#ifndef MODULE
|
||||
if (IS_ERR(bdev)) {
|
||||
|
||||
/* We might not have rootfs mounted at this point. Try
|
||||
to resolve the device name by other means. */
|
||||
|
||||
- dev_t devt = name_to_dev_t(devname);
|
||||
+ dev_t devt = name_to_dev_t(dev->devname);
|
||||
if (devt) {
|
||||
bdev = open_by_devnum(devt, FMODE_WRITE | FMODE_READ);
|
||||
}
|
||||
@@ -263,17 +276,98 @@ static struct block2mtd_dev *add_device(
|
||||
#endif
|
||||
|
||||
if (IS_ERR(bdev)) {
|
||||
- ERROR("error: cannot open device %s", devname);
|
||||
- goto devinit_err;
|
||||
+ 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");
|
||||
- goto devinit_err;
|
||||
+ 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);
|
||||
+ close_bdev_exclusive(dev->blkdev, FMODE_READ|FMODE_WRITE);
|
||||
+ dev->blkdev = NULL;
|
||||
+}
|
||||
+
|
||||
+static void block2mtd_free_device(struct block2mtd_dev *dev)
|
||||
+{
|
||||
+ if (!dev)
|
||||
+ return;
|
||||
+
|
||||
+ kfree(dev->mtd.name);
|
||||
+ _close_bdev(dev);
|
||||
+ kfree(dev);
|
||||
+}
|
||||
+
|
||||
+
|
||||
+static int block2mtd_refresh(struct mtd_info *mtd)
|
||||
+{
|
||||
+ 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 = open_by_devnum(devt, FMODE_WRITE | FMODE_READ);
|
||||
+ if (!bdev || !bdev->bd_disk)
|
||||
+ err = -EINVAL;
|
||||
+#ifndef CONFIG_MTD_BLOCK2MTD_MODULE
|
||||
+ else
|
||||
+ err = rescan_partitions(bdev->bd_disk, bdev);
|
||||
+#endif
|
||||
+ if (bdev)
|
||||
+ close_bdev_exclusive(bdev, FMODE_READ|FMODE_WRITE);
|
||||
+
|
||||
+ /* 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;
|
||||
+
|
||||
+ if (!devname)
|
||||
+ return NULL;
|
||||
+
|
||||
+ dev = kzalloc(sizeof(struct block2mtd_dev) + strlen(devname) + 1, GFP_KERNEL);
|
||||
+ if (!dev)
|
||||
+ return NULL;
|
||||
+
|
||||
+ strcpy(dev->devname, devname);
|
||||
+
|
||||
+ if (_open_bdev(dev))
|
||||
+ goto devinit_err;
|
||||
+
|
||||
mutex_init(&dev->write_mutex);
|
||||
+ rwlock_init(&dev->bdev_mutex);
|
||||
|
||||
if (!mtdname)
|
||||
mtdname = devname;
|
||||
@@ -297,6 +391,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 = dev->mtd.name;
|
||||
--- a/drivers/mtd/mtdchar.c
|
||||
+++ b/drivers/mtd/mtdchar.c
|
||||
@@ -18,6 +18,7 @@
|
||||
|
||||
#include <linux/mtd/mtd.h>
|
||||
#include <linux/mtd/compatmac.h>
|
||||
+#include <linux/mtd/partitions.h>
|
||||
|
||||
#include <asm/uaccess.h>
|
||||
|
||||
@@ -814,6 +815,13 @@ static int mtd_ioctl(struct inode *inode
|
||||
file->f_pos = 0;
|
||||
break;
|
||||
}
|
||||
+#ifdef CONFIG_MTD_PARTITIONS
|
||||
+ case MTDREFRESH:
|
||||
+ {
|
||||
+ ret = refresh_mtd_partitions(mtd);
|
||||
+ break;
|
||||
+ }
|
||||
+#endif
|
||||
|
||||
default:
|
||||
ret = -ENOTTY;
|
||||
--- a/include/linux/mtd/mtd.h
|
||||
+++ b/include/linux/mtd/mtd.h
|
||||
@@ -101,6 +101,7 @@ struct mtd_oob_ops {
|
||||
uint8_t *oobbuf;
|
||||
};
|
||||
|
||||
+struct mtd_info;
|
||||
struct mtd_info {
|
||||
u_char type;
|
||||
uint32_t flags;
|
||||
@@ -241,6 +242,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
|
||||
--- 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)
|
||||
@@ -51,6 +53,7 @@ struct mtd_info;
|
||||
|
||||
int add_mtd_partitions(struct mtd_info *, const struct mtd_partition *, int);
|
||||
int del_mtd_partitions(struct mtd_info *);
|
||||
+int refresh_mtd_partitions(struct mtd_info *);
|
||||
|
||||
/*
|
||||
* Functions dealing with the various ways of partitioning the space
|
||||
--- a/include/mtd/mtd-abi.h
|
||||
+++ b/include/mtd/mtd-abi.h
|
||||
@@ -110,6 +110,7 @@ struct otp_info {
|
||||
#define MEMERASE64 _IOW('M', 20, struct erase_info_user64)
|
||||
#define MEMWRITEOOB64 _IOWR('M', 21, struct mtd_oob_buf64)
|
||||
#define MEMREADOOB64 _IOWR('M', 22, struct mtd_oob_buf64)
|
||||
+#define MTDREFRESH _IO('M', 50)
|
||||
|
||||
/*
|
||||
* Obsolete legacy interface. Keep it in order not to break userspace
|
@ -1,10 +0,0 @@
|
||||
--- a/drivers/mtd/devices/block2mtd.c
|
||||
+++ b/drivers/mtd/devices/block2mtd.c
|
||||
@@ -268,6 +268,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();
|
||||
dev_t devt = name_to_dev_t(dev->devname);
|
||||
if (devt) {
|
||||
bdev = open_by_devnum(devt, FMODE_WRITE | FMODE_READ);
|
@ -1,30 +0,0 @@
|
||||
--- a/drivers/mtd/redboot.c
|
||||
+++ b/drivers/mtd/redboot.c
|
||||
@@ -249,14 +249,21 @@ static int parse_redboot_partitions(stru
|
||||
#endif
|
||||
names += strlen(names)+1;
|
||||
|
||||
-#ifdef CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED
|
||||
if(fl->next && fl->img->flash_base + fl->img->size + master->erasesize <= fl->next->img->flash_base) {
|
||||
- i++;
|
||||
- parts[i].offset = parts[i-1].size + parts[i-1].offset;
|
||||
- parts[i].size = fl->next->img->flash_base - parts[i].offset;
|
||||
- parts[i].name = nullname;
|
||||
- }
|
||||
+ if (!strcmp(parts[i].name, "rootfs")) {
|
||||
+ parts[i].size = fl->next->img->flash_base;
|
||||
+ parts[i].size &= ~(master->erasesize - 1);
|
||||
+ parts[i].size -= parts[i].offset;
|
||||
+#ifdef CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED
|
||||
+ nrparts--;
|
||||
+ } else {
|
||||
+ i++;
|
||||
+ parts[i].offset = parts[i-1].size + parts[i-1].offset;
|
||||
+ parts[i].size = fl->next->img->flash_base - parts[i].offset;
|
||||
+ parts[i].name = nullname;
|
||||
#endif
|
||||
+ }
|
||||
+ }
|
||||
tmp_fl = fl;
|
||||
fl = fl->next;
|
||||
kfree(tmp_fl);
|
@ -1,60 +0,0 @@
|
||||
--- a/drivers/mtd/redboot.c
|
||||
+++ b/drivers/mtd/redboot.c
|
||||
@@ -11,6 +11,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
|
||||
@@ -41,6 +43,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;
|
||||
@@ -209,14 +212,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);
|
||||
@@ -235,6 +238,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;
|
||||
@@ -268,6 +273,14 @@ static int parse_redboot_partitions(stru
|
||||
fl = fl->next;
|
||||
kfree(tmp_fl);
|
||||
}
|
||||
+ if(master->size - max_offset >= master->erasesize)
|
||||
+ {
|
||||
+ parts[nrparts].size = master->size - max_offset;
|
||||
+ parts[nrparts].offset = max_offset;
|
||||
+ parts[nrparts].name = names;
|
||||
+ strcpy(names, BOARD_CONFIG_PART);
|
||||
+ nrparts++;
|
||||
+ }
|
||||
ret = nrparts;
|
||||
*pparts = parts;
|
||||
out:
|
@ -1,32 +0,0 @@
|
||||
--- a/include/linux/mtd/nand.h
|
||||
+++ b/include/linux/mtd/nand.h
|
||||
@@ -575,6 +575,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
|
||||
@@ -80,7 +80,18 @@ static int __devinit plat_nand_probe(str
|
||||
}
|
||||
|
||||
/* Scan to find existance of the device */
|
||||
- if (nand_scan(&data->mtd, 1)) {
|
||||
+ if (nand_scan_ident(&data->mtd, 1)) {
|
||||
+ 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)) {
|
||||
res = -ENXIO;
|
||||
goto out;
|
||||
}
|
@ -1,35 +0,0 @@
|
||||
--- a/drivers/mtd/Kconfig
|
||||
+++ b/drivers/mtd/Kconfig
|
||||
@@ -181,6 +181,22 @@ config MTD_AR7_PARTS
|
||||
---help---
|
||||
TI AR7 partitioning support
|
||||
|
||||
+config MTD_MYLOADER_PARTS
|
||||
+ tristate "MyLoader partition parsing"
|
||||
+ depends on MTD_PARTITIONS && (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
|
||||
@@ -13,6 +13,7 @@ obj-$(CONFIG_MTD_CMDLINE_PARTS) += cmdli
|
||||
obj-$(CONFIG_MTD_AFS_PARTS) += afs.o
|
||||
obj-$(CONFIG_MTD_AR7_PARTS) += ar7part.o
|
||||
obj-$(CONFIG_MTD_OF_PARTS) += ofpart.o
|
||||
+obj-$(CONFIG_MTD_MYLOADER_PARTS) += myloader.o
|
||||
|
||||
# 'Users' - code which presents functionality to userspace.
|
||||
obj-$(CONFIG_MTD_CHAR) += mtdchar.o
|
@ -1,18 +0,0 @@
|
||||
--- a/include/linux/mtd/partitions.h
|
||||
+++ b/include/linux/mtd/partitions.h
|
||||
@@ -33,6 +33,7 @@
|
||||
* Note: writeable partitions require their size and offset be
|
||||
* erasesize aligned (e.g. use MTDPART_OFS_NEXTBLK).
|
||||
*/
|
||||
+struct mtd_info;
|
||||
|
||||
struct mtd_partition;
|
||||
struct mtd_partition {
|
||||
@@ -49,7 +50,6 @@ struct mtd_partition {
|
||||
#define MTDPART_SIZ_FULL (0)
|
||||
|
||||
|
||||
-struct mtd_info;
|
||||
|
||||
int add_mtd_partitions(struct mtd_info *, const struct mtd_partition *, int);
|
||||
int del_mtd_partitions(struct mtd_info *);
|
@ -1,12 +0,0 @@
|
||||
--- a/drivers/mtd/nand/nand_ecc.c
|
||||
+++ b/drivers/mtd/nand/nand_ecc.c
|
||||
@@ -492,8 +492,7 @@ int nand_correct_data(struct mtd_info *m
|
||||
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);
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,108 +0,0 @@
|
||||
--- a/include/linux/netfilter/xt_layer7.h
|
||||
+++ b/include/linux/netfilter/xt_layer7.h
|
||||
@@ -8,6 +8,7 @@ struct xt_layer7_info {
|
||||
char protocol[MAX_PROTOCOL_LEN];
|
||||
char pattern[MAX_PATTERN_LEN];
|
||||
u_int8_t invert;
|
||||
+ u_int8_t pkt;
|
||||
};
|
||||
|
||||
#endif /* _XT_LAYER7_H */
|
||||
--- a/net/netfilter/xt_layer7.c
|
||||
+++ b/net/netfilter/xt_layer7.c
|
||||
@@ -314,33 +314,35 @@ static int match_no_append(struct nf_con
|
||||
}
|
||||
|
||||
/* add the new app data to the conntrack. Return number of bytes added. */
|
||||
-static int add_data(struct nf_conn * master_conntrack,
|
||||
- char * app_data, int appdatalen)
|
||||
+static int add_datastr(char *target, int offset, char *app_data, int len)
|
||||
{
|
||||
int length = 0, i;
|
||||
- int oldlength = master_conntrack->layer7.app_data_len;
|
||||
-
|
||||
- /* This is a fix for a race condition by Deti Fliegl. However, I'm not
|
||||
- clear on whether the race condition exists or whether this really
|
||||
- fixes it. I might just be being dense... Anyway, if it's not really
|
||||
- a fix, all it does is waste a very small amount of time. */
|
||||
- if(!master_conntrack->layer7.app_data) return 0;
|
||||
+ if (!target) return 0;
|
||||
|
||||
/* Strip nulls. Make everything lower case (our regex lib doesn't
|
||||
do case insensitivity). Add it to the end of the current data. */
|
||||
- for(i = 0; i < maxdatalen-oldlength-1 &&
|
||||
- i < appdatalen; i++) {
|
||||
+ for(i = 0; i < maxdatalen-offset-1 && i < len; i++) {
|
||||
if(app_data[i] != '\0') {
|
||||
/* the kernel version of tolower mungs 'upper ascii' */
|
||||
- master_conntrack->layer7.app_data[length+oldlength] =
|
||||
+ target[length+offset] =
|
||||
isascii(app_data[i])?
|
||||
tolower(app_data[i]) : app_data[i];
|
||||
length++;
|
||||
}
|
||||
}
|
||||
+ target[length+offset] = '\0';
|
||||
+
|
||||
+ return length;
|
||||
+}
|
||||
+
|
||||
+/* add the new app data to the conntrack. Return number of bytes added. */
|
||||
+static int add_data(struct nf_conn * master_conntrack,
|
||||
+ char * app_data, int appdatalen)
|
||||
+{
|
||||
+ int length;
|
||||
|
||||
- master_conntrack->layer7.app_data[length+oldlength] = '\0';
|
||||
- master_conntrack->layer7.app_data_len = length + oldlength;
|
||||
+ length = add_datastr(master_conntrack->layer7.app_data, master_conntrack->layer7.app_data_len, app_data, appdatalen);
|
||||
+ master_conntrack->layer7.app_data_len += length;
|
||||
|
||||
return length;
|
||||
}
|
||||
@@ -438,7 +440,7 @@ match(const struct sk_buff *skbin,
|
||||
|
||||
enum ip_conntrack_info master_ctinfo, ctinfo;
|
||||
struct nf_conn *master_conntrack, *conntrack;
|
||||
- unsigned char * app_data;
|
||||
+ unsigned char *app_data, *tmp_data;
|
||||
unsigned int pattern_result, appdatalen;
|
||||
regexp * comppattern;
|
||||
|
||||
@@ -466,8 +468,8 @@ match(const struct sk_buff *skbin,
|
||||
master_conntrack = master_ct(master_conntrack);
|
||||
|
||||
/* if we've classified it or seen too many packets */
|
||||
- if(total_acct_packets(master_conntrack) > num_packets ||
|
||||
- master_conntrack->layer7.app_proto) {
|
||||
+ if(!info->pkt && (total_acct_packets(master_conntrack) > num_packets ||
|
||||
+ master_conntrack->layer7.app_proto)) {
|
||||
|
||||
pattern_result = match_no_append(conntrack, master_conntrack,
|
||||
ctinfo, master_ctinfo, info);
|
||||
@@ -500,6 +502,25 @@ match(const struct sk_buff *skbin,
|
||||
/* the return value gets checked later, when we're ready to use it */
|
||||
comppattern = compile_and_cache(info->pattern, info->protocol);
|
||||
|
||||
+ if (info->pkt) {
|
||||
+ tmp_data = kmalloc(maxdatalen, GFP_ATOMIC);
|
||||
+ if(!tmp_data){
|
||||
+ if (net_ratelimit())
|
||||
+ printk(KERN_ERR "layer7: out of memory in match, bailing.\n");
|
||||
+ return info->invert;
|
||||
+ }
|
||||
+
|
||||
+ tmp_data[0] = '\0';
|
||||
+ add_datastr(tmp_data, 0, app_data, appdatalen);
|
||||
+ pattern_result = ((comppattern && regexec(comppattern, tmp_data)) ? 1 : 0);
|
||||
+
|
||||
+ kfree(tmp_data);
|
||||
+ tmp_data = NULL;
|
||||
+ spin_unlock_bh(&l7_lock);
|
||||
+
|
||||
+ return (pattern_result ^ info->invert);
|
||||
+ }
|
||||
+
|
||||
/* On the first packet of a connection, allocate space for app data */
|
||||
if(total_acct_packets(master_conntrack) == 1 && !skb->cb[0] &&
|
||||
!master_conntrack->layer7.app_data){
|
@ -1,144 +0,0 @@
|
||||
--- a/include/linux/netfilter_ipv4/ip_tables.h
|
||||
+++ b/include/linux/netfilter_ipv4/ip_tables.h
|
||||
@@ -62,6 +62,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
|
||||
@@ -87,6 +87,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,
|
||||
@@ -137,13 +140,35 @@ ip_packet_match(const struct iphdr *ip,
|
||||
return false;
|
||||
}
|
||||
|
||||
+#undef FWINV
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
-ip_checkentry(const struct ipt_ip *ip)
|
||||
+ip_checkentry(struct ipt_ip *ip)
|
||||
{
|
||||
- if (ip->flags & ~IPT_F_MASK) {
|
||||
+#define FWINV(bool, invflg) ((bool) || (ip->invflags & (invflg)))
|
||||
+
|
||||
+ if (FWINV(ip->smsk.s_addr, IPT_INV_SRCIP) ||
|
||||
+ FWINV(ip->dmsk.s_addr, IPT_INV_DSTIP))
|
||||
+ goto has_match_rules;
|
||||
+
|
||||
+ if (FWINV(!!((const unsigned long *)ip->iniface_mask)[0],
|
||||
+ IPT_INV_VIA_IN) ||
|
||||
+ FWINV(!!((const unsigned long *)ip->outiface_mask)[0],
|
||||
+ IPT_INV_VIA_OUT))
|
||||
+ goto has_match_rules;
|
||||
+
|
||||
+ if (FWINV(ip->proto, IPT_INV_PROTO))
|
||||
+ goto has_match_rules;
|
||||
+
|
||||
+ if (FWINV(ip->flags&IPT_F_FRAG, IPT_INV_FRAG))
|
||||
+ goto has_match_rules;
|
||||
+
|
||||
+ ip->flags |= IPT_F_NO_DEF_MATCH;
|
||||
+
|
||||
+has_match_rules:
|
||||
+ if (ip->flags & ~(IPT_F_MASK|IPT_F_NO_DEF_MATCH)) {
|
||||
duprintf("Unknown flag bits set: %08X\n",
|
||||
ip->flags & ~IPT_F_MASK);
|
||||
return false;
|
||||
@@ -153,6 +178,8 @@ ip_checkentry(const struct ipt_ip *ip)
|
||||
ip->invflags & ~IPT_INV_MASK);
|
||||
return false;
|
||||
}
|
||||
+
|
||||
+#undef FWINV
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -200,7 +227,6 @@ unconditional(const struct ipt_ip *ip)
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
-#undef FWINV
|
||||
}
|
||||
|
||||
#if defined(CONFIG_NETFILTER_XT_TARGET_TRACE) || \
|
||||
@@ -326,8 +352,28 @@ ipt_do_table(struct sk_buff *skb,
|
||||
struct xt_match_param mtpar;
|
||||
struct xt_target_param tgpar;
|
||||
|
||||
- /* Initialization */
|
||||
ip = ip_hdr(skb);
|
||||
+
|
||||
+ IP_NF_ASSERT(table->valid_hooks & (1 << hook));
|
||||
+ xt_info_rdlock_bh();
|
||||
+ private = table->private;
|
||||
+ table_base = private->entries[smp_processor_id()];
|
||||
+ e = get_entry(table_base, private->hook_entry[hook]);
|
||||
+
|
||||
+ if (e->target_offset <= sizeof(struct ipt_entry) &&
|
||||
+ (e->ip.flags & IPT_F_NO_DEF_MATCH)) {
|
||||
+ struct ipt_entry_target *t = ipt_get_target(e);
|
||||
+ if (!t->u.kernel.target->target) {
|
||||
+ int v = ((struct ipt_standard_target *)t)->verdict;
|
||||
+ if ((v < 0) && (v != IPT_RETURN)) {
|
||||
+ ADD_COUNTER(e->counters, ntohs(ip->tot_len), 1);
|
||||
+ xt_info_rdunlock_bh();
|
||||
+ return (unsigned)(-v) - 1;
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ /* Initialization */
|
||||
datalen = skb->len - ip->ihl * 4;
|
||||
indev = in ? in->name : nulldevname;
|
||||
outdev = out ? out->name : nulldevname;
|
||||
@@ -345,13 +391,6 @@ ipt_do_table(struct sk_buff *skb,
|
||||
mtpar.family = tgpar.family = NFPROTO_IPV4;
|
||||
mtpar.hooknum = tgpar.hooknum = hook;
|
||||
|
||||
- IP_NF_ASSERT(table->valid_hooks & (1 << hook));
|
||||
- xt_info_rdlock_bh();
|
||||
- private = table->private;
|
||||
- table_base = private->entries[smp_processor_id()];
|
||||
-
|
||||
- e = get_entry(table_base, private->hook_entry[hook]);
|
||||
-
|
||||
/* For return from builtin chain */
|
||||
back = get_entry(table_base, private->underflow[hook]);
|
||||
|
||||
@@ -978,6 +1017,7 @@ copy_entries_to_user(unsigned int total_
|
||||
unsigned int i;
|
||||
const struct ipt_entry_match *m;
|
||||
const struct ipt_entry_target *t;
|
||||
+ u8 flags;
|
||||
|
||||
e = (struct ipt_entry *)(loc_cpu_entry + off);
|
||||
if (copy_to_user(userptr + off
|
||||
@@ -987,6 +1027,14 @@ copy_entries_to_user(unsigned int total_
|
||||
ret = -EFAULT;
|
||||
goto free_counters;
|
||||
}
|
||||
+
|
||||
+ flags = e->ip.flags & ~IPT_F_NO_DEF_MATCH;
|
||||
+ if (copy_to_user(userptr + off
|
||||
+ + offsetof(struct ipt_entry, ip.flags),
|
||||
+ &flags, sizeof(flags)) != 0) {
|
||||
+ ret = -EFAULT;
|
||||
+ goto free_counters;
|
||||
+ }
|
||||
|
||||
for (i = sizeof(struct ipt_entry);
|
||||
i < e->target_offset;
|
@ -1,71 +0,0 @@
|
||||
--- a/include/linux/netfilter/xt_recent.h
|
||||
+++ b/include/linux/netfilter/xt_recent.h
|
||||
@@ -9,6 +9,7 @@ enum {
|
||||
XT_RECENT_UPDATE = 1 << 2,
|
||||
XT_RECENT_REMOVE = 1 << 3,
|
||||
XT_RECENT_TTL = 1 << 4,
|
||||
+ XT_RECENT_REAP = 1 << 5,
|
||||
|
||||
XT_RECENT_SOURCE = 0,
|
||||
XT_RECENT_DEST = 1,
|
||||
@@ -16,6 +17,9 @@ enum {
|
||||
XT_RECENT_NAME_LEN = 200,
|
||||
};
|
||||
|
||||
+/* Only allowed with --rcheck and --update */
|
||||
+#define XT_RECENT_MODIFIERS (XT_RECENT_TTL|XT_RECENT_REAP)
|
||||
+
|
||||
struct xt_recent_mtinfo {
|
||||
__u32 seconds;
|
||||
__u32 hit_count;
|
||||
--- a/net/netfilter/xt_recent.c
|
||||
+++ b/net/netfilter/xt_recent.c
|
||||
@@ -142,6 +142,25 @@ static void recent_entry_remove(struct r
|
||||
t->entries--;
|
||||
}
|
||||
|
||||
+/*
|
||||
+ * Drop entries with timestamps older then 'time'.
|
||||
+ */
|
||||
+static void recent_entry_reap(struct recent_table *t, unsigned long time)
|
||||
+{
|
||||
+ struct recent_entry *e;
|
||||
+
|
||||
+ /*
|
||||
+ * The head of the LRU list is always the oldest entry.
|
||||
+ */
|
||||
+ e = list_entry(t->lru_list.next, struct recent_entry, lru_list);
|
||||
+
|
||||
+ /*
|
||||
+ * The last time stamp is the most recent.
|
||||
+ */
|
||||
+ if (time_after(time, e->stamps[e->index-1]))
|
||||
+ recent_entry_remove(t, e);
|
||||
+}
|
||||
+
|
||||
static struct recent_entry *
|
||||
recent_entry_init(struct recent_table *t, const union nf_inet_addr *addr,
|
||||
u_int16_t family, u_int8_t ttl)
|
||||
@@ -265,6 +284,10 @@ recent_mt(const struct sk_buff *skb, con
|
||||
break;
|
||||
}
|
||||
}
|
||||
+
|
||||
+ /* info->seconds must be non-zero */
|
||||
+ if (info->check_set & XT_RECENT_REAP)
|
||||
+ recent_entry_reap(t, time);
|
||||
}
|
||||
|
||||
if (info->check_set & XT_RECENT_SET ||
|
||||
@@ -292,7 +315,10 @@ static bool recent_mt_check(const struct
|
||||
XT_RECENT_CHECK | XT_RECENT_UPDATE)) != 1)
|
||||
return false;
|
||||
if ((info->check_set & (XT_RECENT_SET | XT_RECENT_REMOVE)) &&
|
||||
- (info->seconds || info->hit_count))
|
||||
+ (info->seconds || info->hit_count ||
|
||||
+ (info->check_set & XT_RECENT_MODIFIERS)))
|
||||
+ return false;
|
||||
+ if ((info->check_set & XT_RECENT_REAP) && !info->seconds)
|
||||
return false;
|
||||
if (info->hit_count > ip_pkt_list_tot)
|
||||
return false;
|
@ -1,26 +0,0 @@
|
||||
From: Fernando Luis Vazquez Cao <fernando@oss.ntt.co.jp>
|
||||
Date: Tue, 10 May 2011 08:00:21 +0000 (+0200)
|
||||
Subject: netfilter: IPv6: fix DSCP mangle code
|
||||
X-Git-Tag: v2.6.39~15^2~13^2~1
|
||||
X-Git-Url: http://git390.marist.edu/cgi-bin/gitweb.cgi?p=linux-2.6.git;a=commitdiff_plain;h=1ed2f73d90fb49bcf5704aee7e9084adb882bfc5
|
||||
|
||||
netfilter: IPv6: fix DSCP mangle code
|
||||
|
||||
The mask indicates the bits one wants to zero out, so it needs to be
|
||||
inverted before applying to the original TOS field.
|
||||
|
||||
Signed-off-by: Fernando Luis Vazquez Cao <fernando@oss.ntt.co.jp>
|
||||
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||
---
|
||||
|
||||
--- a/net/netfilter/xt_DSCP.c
|
||||
+++ b/net/netfilter/xt_DSCP.c
|
||||
@@ -135,7 +135,7 @@ tos_tg6(struct sk_buff *skb, const struc
|
||||
u_int8_t orig, nv;
|
||||
|
||||
orig = ipv6_get_dsfield(iph);
|
||||
- nv = (orig & info->tos_mask) ^ info->tos_value;
|
||||
+ nv = (orig & ~info->tos_mask) ^ info->tos_value;
|
||||
|
||||
if (orig != nv) {
|
||||
if (!skb_make_writable(skb, sizeof(struct iphdr)))
|
@ -1,18 +0,0 @@
|
||||
--- a/net/netfilter/Kconfig
|
||||
+++ b/net/netfilter/Kconfig
|
||||
@@ -160,7 +160,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
|
||||
@@ -493,7 +492,6 @@ config NETFILTER_XT_TARGET_SECMARK
|
||||
|
||||
config NETFILTER_XT_TARGET_TCPMSS
|
||||
tristate '"TCPMSS" target support'
|
||||
- depends on (IPV6 || IPV6=n)
|
||||
default m if NETFILTER_ADVANCED=n
|
||||
---help---
|
||||
This option adds a `TCPMSS' target, which allows you to alter the
|
@ -1,795 +0,0 @@
|
||||
--- a/include/linux/pkt_sched.h
|
||||
+++ b/include/linux/pkt_sched.h
|
||||
@@ -182,8 +182,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
|
||||
@@ -137,6 +137,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
|
||||
@@ -24,6 +24,7 @@ obj-$(CONFIG_NET_SCH_GRED) += sch_gred.o
|
||||
obj-$(CONFIG_NET_SCH_INGRESS) += sch_ingress.o
|
||||
obj-$(CONFIG_NET_SCH_DSMARK) += sch_dsmark.o
|
||||
obj-$(CONFIG_NET_SCH_SFQ) += sch_sfq.o
|
||||
+obj-$(CONFIG_NET_SCH_ESFQ) += sch_esfq.o
|
||||
obj-$(CONFIG_NET_SCH_TBF) += sch_tbf.o
|
||||
obj-$(CONFIG_NET_SCH_TEQL) += sch_teql.o
|
||||
obj-$(CONFIG_NET_SCH_PRIO) += sch_prio.o
|
||||
--- /dev/null
|
||||
+++ b/net/sched/sch_esfq.c
|
||||
@@ -0,0 +1,702 @@
|
||||
+/*
|
||||
+ * net/sched/sch_esfq.c Extended Stochastic Fairness Queueing discipline.
|
||||
+ *
|
||||
+ * This program is free software; you can redistribute it and/or
|
||||
+ * modify it under the terms of the GNU General Public License
|
||||
+ * as published by the Free Software Foundation; either version
|
||||
+ * 2 of the License, or (at your option) any later version.
|
||||
+ *
|
||||
+ * Authors: Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru>
|
||||
+ *
|
||||
+ * Changes: Alexander Atanasov, <alex@ssi.bg>
|
||||
+ * Added dynamic depth,limit,divisor,hash_kind options.
|
||||
+ * Added dst and src hashes.
|
||||
+ *
|
||||
+ * Alexander Clouter, <alex@digriz.org.uk>
|
||||
+ * Ported ESFQ to Linux 2.6.
|
||||
+ *
|
||||
+ * Corey Hickey, <bugfood-c@fatooh.org>
|
||||
+ * Maintenance of the Linux 2.6 port.
|
||||
+ * Added fwmark hash (thanks to Robert Kurjata).
|
||||
+ * Added usage of jhash.
|
||||
+ * Added conntrack support.
|
||||
+ * Added ctnatchg hash (thanks to Ben Pfountz).
|
||||
+ */
|
||||
+
|
||||
+#include <linux/module.h>
|
||||
+#include <asm/uaccess.h>
|
||||
+#include <asm/system.h>
|
||||
+#include <linux/bitops.h>
|
||||
+#include <linux/types.h>
|
||||
+#include <linux/kernel.h>
|
||||
+#include <linux/jiffies.h>
|
||||
+#include <linux/string.h>
|
||||
+#include <linux/mm.h>
|
||||
+#include <linux/socket.h>
|
||||
+#include <linux/sockios.h>
|
||||
+#include <linux/in.h>
|
||||
+#include <linux/errno.h>
|
||||
+#include <linux/interrupt.h>
|
||||
+#include <linux/if_ether.h>
|
||||
+#include <linux/inet.h>
|
||||
+#include <linux/netdevice.h>
|
||||
+#include <linux/etherdevice.h>
|
||||
+#include <linux/notifier.h>
|
||||
+#include <linux/init.h>
|
||||
+#include <net/ip.h>
|
||||
+#include <net/netlink.h>
|
||||
+#include <linux/ipv6.h>
|
||||
+#include <net/route.h>
|
||||
+#include <linux/skbuff.h>
|
||||
+#include <net/sock.h>
|
||||
+#include <net/pkt_sched.h>
|
||||
+#include <linux/jhash.h>
|
||||
+#ifdef CONFIG_NET_SCH_ESFQ_NFCT
|
||||
+#include <net/netfilter/nf_conntrack.h>
|
||||
+#endif
|
||||
+
|
||||
+/* Stochastic Fairness Queuing algorithm.
|
||||
+ For more comments look at sch_sfq.c.
|
||||
+ The difference is that you can change limit, depth,
|
||||
+ hash table size and choose alternate hash types.
|
||||
+
|
||||
+ classic: same as in sch_sfq.c
|
||||
+ dst: destination IP address
|
||||
+ src: source IP address
|
||||
+ fwmark: netfilter mark value
|
||||
+ ctorigdst: original destination IP address
|
||||
+ ctorigsrc: original source IP address
|
||||
+ ctrepldst: reply destination IP address
|
||||
+ ctreplsrc: reply source IP
|
||||
+
|
||||
+*/
|
||||
+
|
||||
+#define ESFQ_HEAD 0
|
||||
+#define ESFQ_TAIL 1
|
||||
+
|
||||
+/* This type should contain at least SFQ_DEPTH*2 values */
|
||||
+typedef unsigned int esfq_index;
|
||||
+
|
||||
+struct esfq_head
|
||||
+{
|
||||
+ esfq_index next;
|
||||
+ esfq_index prev;
|
||||
+};
|
||||
+
|
||||
+struct esfq_sched_data
|
||||
+{
|
||||
+/* Parameters */
|
||||
+ int perturb_period;
|
||||
+ unsigned quantum; /* Allotment per round: MUST BE >= MTU */
|
||||
+ int limit;
|
||||
+ unsigned depth;
|
||||
+ unsigned hash_divisor;
|
||||
+ unsigned hash_kind;
|
||||
+/* Variables */
|
||||
+ struct timer_list perturb_timer;
|
||||
+ int perturbation;
|
||||
+ esfq_index tail; /* Index of current slot in round */
|
||||
+ esfq_index max_depth; /* Maximal depth */
|
||||
+
|
||||
+ esfq_index *ht; /* Hash table */
|
||||
+ esfq_index *next; /* Active slots link */
|
||||
+ short *allot; /* Current allotment per slot */
|
||||
+ unsigned short *hash; /* Hash value indexed by slots */
|
||||
+ struct sk_buff_head *qs; /* Slot queue */
|
||||
+ struct esfq_head *dep; /* Linked list of slots, indexed by depth */
|
||||
+};
|
||||
+
|
||||
+/* This contains the info we will hash. */
|
||||
+struct esfq_packet_info
|
||||
+{
|
||||
+ u32 proto; /* protocol or port */
|
||||
+ u32 src; /* source from packet header */
|
||||
+ u32 dst; /* destination from packet header */
|
||||
+ u32 ctorigsrc; /* original source from conntrack */
|
||||
+ u32 ctorigdst; /* original destination from conntrack */
|
||||
+ u32 ctreplsrc; /* reply source from conntrack */
|
||||
+ u32 ctrepldst; /* reply destination from conntrack */
|
||||
+ u32 mark; /* netfilter mark (fwmark) */
|
||||
+};
|
||||
+
|
||||
+static __inline__ unsigned esfq_jhash_1word(struct esfq_sched_data *q,u32 a)
|
||||
+{
|
||||
+ return jhash_1word(a, q->perturbation) & (q->hash_divisor-1);
|
||||
+}
|
||||
+
|
||||
+static __inline__ unsigned esfq_jhash_2words(struct esfq_sched_data *q, u32 a, u32 b)
|
||||
+{
|
||||
+ return jhash_2words(a, b, q->perturbation) & (q->hash_divisor-1);
|
||||
+}
|
||||
+
|
||||
+static __inline__ unsigned esfq_jhash_3words(struct esfq_sched_data *q, u32 a, u32 b, u32 c)
|
||||
+{
|
||||
+ return jhash_3words(a, b, c, q->perturbation) & (q->hash_divisor-1);
|
||||
+}
|
||||
+
|
||||
+static unsigned esfq_hash(struct esfq_sched_data *q, struct sk_buff *skb)
|
||||
+{
|
||||
+ struct esfq_packet_info info;
|
||||
+#ifdef CONFIG_NET_SCH_ESFQ_NFCT
|
||||
+ enum ip_conntrack_info ctinfo;
|
||||
+ struct nf_conn *ct = nf_ct_get(skb, &ctinfo);
|
||||
+#endif
|
||||
+
|
||||
+ switch (skb->protocol) {
|
||||
+ case __constant_htons(ETH_P_IP):
|
||||
+ {
|
||||
+ struct iphdr *iph = ip_hdr(skb);
|
||||
+ info.dst = iph->daddr;
|
||||
+ info.src = iph->saddr;
|
||||
+ if (!(iph->frag_off&htons(IP_MF|IP_OFFSET)) &&
|
||||
+ (iph->protocol == IPPROTO_TCP ||
|
||||
+ iph->protocol == IPPROTO_UDP ||
|
||||
+ iph->protocol == IPPROTO_SCTP ||
|
||||
+ iph->protocol == IPPROTO_DCCP ||
|
||||
+ iph->protocol == IPPROTO_ESP))
|
||||
+ info.proto = *(((u32*)iph) + iph->ihl);
|
||||
+ else
|
||||
+ info.proto = iph->protocol;
|
||||
+ break;
|
||||
+ }
|
||||
+ case __constant_htons(ETH_P_IPV6):
|
||||
+ {
|
||||
+ struct ipv6hdr *iph = ipv6_hdr(skb);
|
||||
+ /* Hash ipv6 addresses into a u32. This isn't ideal,
|
||||
+ * but the code is simple. */
|
||||
+ info.dst = jhash2(iph->daddr.s6_addr32, 4, q->perturbation);
|
||||
+ info.src = jhash2(iph->saddr.s6_addr32, 4, q->perturbation);
|
||||
+ if (iph->nexthdr == IPPROTO_TCP ||
|
||||
+ iph->nexthdr == IPPROTO_UDP ||
|
||||
+ iph->nexthdr == IPPROTO_SCTP ||
|
||||
+ iph->nexthdr == IPPROTO_DCCP ||
|
||||
+ iph->nexthdr == IPPROTO_ESP)
|
||||
+ info.proto = *(u32*)&iph[1];
|
||||
+ else
|
||||
+ info.proto = iph->nexthdr;
|
||||
+ break;
|
||||
+ }
|
||||
+ default:
|
||||
+ info.dst = (u32)(unsigned long)skb_dst(skb);
|
||||
+ info.src = (u32)(unsigned long)skb->sk;
|
||||
+ info.proto = skb->protocol;
|
||||
+ }
|
||||
+
|
||||
+ info.mark = skb->mark;
|
||||
+
|
||||
+#ifdef CONFIG_NET_SCH_ESFQ_NFCT
|
||||
+ /* defaults if there is no conntrack info */
|
||||
+ info.ctorigsrc = info.src;
|
||||
+ info.ctorigdst = info.dst;
|
||||
+ info.ctreplsrc = info.dst;
|
||||
+ info.ctrepldst = info.src;
|
||||
+ /* collect conntrack info */
|
||||
+ if (ct && ct != &nf_conntrack_untracked) {
|
||||
+ if (skb->protocol == __constant_htons(ETH_P_IP)) {
|
||||
+ info.ctorigsrc = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u3.ip;
|
||||
+ info.ctorigdst = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.u3.ip;
|
||||
+ info.ctreplsrc = ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.u3.ip;
|
||||
+ info.ctrepldst = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u3.ip;
|
||||
+ }
|
||||
+ else if (skb->protocol == __constant_htons(ETH_P_IPV6)) {
|
||||
+ /* Again, hash ipv6 addresses into a single u32. */
|
||||
+ info.ctorigsrc = jhash2(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u3.ip6, 4, q->perturbation);
|
||||
+ info.ctorigdst = jhash2(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.u3.ip6, 4, q->perturbation);
|
||||
+ info.ctreplsrc = jhash2(ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.u3.ip6, 4, q->perturbation);
|
||||
+ info.ctrepldst = jhash2(ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u3.ip6, 4, q->perturbation);
|
||||
+ }
|
||||
+
|
||||
+ }
|
||||
+#endif
|
||||
+
|
||||
+ switch(q->hash_kind) {
|
||||
+ case TCA_SFQ_HASH_CLASSIC:
|
||||
+ return esfq_jhash_3words(q, info.dst, info.src, info.proto);
|
||||
+ case TCA_SFQ_HASH_DST:
|
||||
+ return esfq_jhash_1word(q, info.dst);
|
||||
+ case TCA_SFQ_HASH_SRC:
|
||||
+ return esfq_jhash_1word(q, info.src);
|
||||
+ case TCA_SFQ_HASH_FWMARK:
|
||||
+ return esfq_jhash_1word(q, info.mark);
|
||||
+#ifdef CONFIG_NET_SCH_ESFQ_NFCT
|
||||
+ case TCA_SFQ_HASH_CTORIGDST:
|
||||
+ return esfq_jhash_1word(q, info.ctorigdst);
|
||||
+ case TCA_SFQ_HASH_CTORIGSRC:
|
||||
+ return esfq_jhash_1word(q, info.ctorigsrc);
|
||||
+ case TCA_SFQ_HASH_CTREPLDST:
|
||||
+ return esfq_jhash_1word(q, info.ctrepldst);
|
||||
+ case TCA_SFQ_HASH_CTREPLSRC:
|
||||
+ return esfq_jhash_1word(q, info.ctreplsrc);
|
||||
+ case TCA_SFQ_HASH_CTNATCHG:
|
||||
+ {
|
||||
+ if (info.ctorigdst == info.ctreplsrc)
|
||||
+ return esfq_jhash_1word(q, info.ctorigsrc);
|
||||
+ return esfq_jhash_1word(q, info.ctreplsrc);
|
||||
+ }
|
||||
+#endif
|
||||
+ default:
|
||||
+ if (net_ratelimit())
|
||||
+ printk(KERN_WARNING "ESFQ: Unknown hash method. Falling back to classic.\n");
|
||||
+ }
|
||||
+ return esfq_jhash_3words(q, info.dst, info.src, info.proto);
|
||||
+}
|
||||
+
|
||||
+static inline void esfq_link(struct esfq_sched_data *q, esfq_index x)
|
||||
+{
|
||||
+ esfq_index p, n;
|
||||
+ int d = q->qs[x].qlen + q->depth;
|
||||
+
|
||||
+ p = d;
|
||||
+ n = q->dep[d].next;
|
||||
+ q->dep[x].next = n;
|
||||
+ q->dep[x].prev = p;
|
||||
+ q->dep[p].next = q->dep[n].prev = x;
|
||||
+}
|
||||
+
|
||||
+static inline void esfq_dec(struct esfq_sched_data *q, esfq_index x)
|
||||
+{
|
||||
+ esfq_index p, n;
|
||||
+
|
||||
+ n = q->dep[x].next;
|
||||
+ p = q->dep[x].prev;
|
||||
+ q->dep[p].next = n;
|
||||
+ q->dep[n].prev = p;
|
||||
+
|
||||
+ if (n == p && q->max_depth == q->qs[x].qlen + 1)
|
||||
+ q->max_depth--;
|
||||
+
|
||||
+ esfq_link(q, x);
|
||||
+}
|
||||
+
|
||||
+static inline void esfq_inc(struct esfq_sched_data *q, esfq_index x)
|
||||
+{
|
||||
+ esfq_index p, n;
|
||||
+ int d;
|
||||
+
|
||||
+ n = q->dep[x].next;
|
||||
+ p = q->dep[x].prev;
|
||||
+ q->dep[p].next = n;
|
||||
+ q->dep[n].prev = p;
|
||||
+ d = q->qs[x].qlen;
|
||||
+ if (q->max_depth < d)
|
||||
+ q->max_depth = d;
|
||||
+
|
||||
+ esfq_link(q, x);
|
||||
+}
|
||||
+
|
||||
+static unsigned int esfq_drop(struct Qdisc *sch)
|
||||
+{
|
||||
+ struct esfq_sched_data *q = qdisc_priv(sch);
|
||||
+ esfq_index d = q->max_depth;
|
||||
+ struct sk_buff *skb;
|
||||
+ unsigned int len;
|
||||
+
|
||||
+ /* Queue is full! Find the longest slot and
|
||||
+ drop a packet from it */
|
||||
+
|
||||
+ if (d > 1) {
|
||||
+ esfq_index x = q->dep[d+q->depth].next;
|
||||
+ skb = q->qs[x].prev;
|
||||
+ len = skb->len;
|
||||
+ __skb_unlink(skb, &q->qs[x]);
|
||||
+ kfree_skb(skb);
|
||||
+ esfq_dec(q, x);
|
||||
+ sch->q.qlen--;
|
||||
+ sch->qstats.drops++;
|
||||
+ sch->qstats.backlog -= len;
|
||||
+ return len;
|
||||
+ }
|
||||
+
|
||||
+ if (d == 1) {
|
||||
+ /* It is difficult to believe, but ALL THE SLOTS HAVE LENGTH 1. */
|
||||
+ d = q->next[q->tail];
|
||||
+ q->next[q->tail] = q->next[d];
|
||||
+ q->allot[q->next[d]] += q->quantum;
|
||||
+ skb = q->qs[d].prev;
|
||||
+ len = skb->len;
|
||||
+ __skb_unlink(skb, &q->qs[d]);
|
||||
+ kfree_skb(skb);
|
||||
+ esfq_dec(q, d);
|
||||
+ sch->q.qlen--;
|
||||
+ q->ht[q->hash[d]] = q->depth;
|
||||
+ sch->qstats.drops++;
|
||||
+ sch->qstats.backlog -= len;
|
||||
+ return len;
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static void esfq_q_enqueue(struct sk_buff *skb, struct esfq_sched_data *q, unsigned int end)
|
||||
+{
|
||||
+ unsigned hash = esfq_hash(q, skb);
|
||||
+ unsigned depth = q->depth;
|
||||
+ esfq_index x;
|
||||
+
|
||||
+ x = q->ht[hash];
|
||||
+ if (x == depth) {
|
||||
+ q->ht[hash] = x = q->dep[depth].next;
|
||||
+ q->hash[x] = hash;
|
||||
+ }
|
||||
+
|
||||
+ if (end == ESFQ_TAIL)
|
||||
+ __skb_queue_tail(&q->qs[x], skb);
|
||||
+ else
|
||||
+ __skb_queue_head(&q->qs[x], skb);
|
||||
+
|
||||
+ esfq_inc(q, x);
|
||||
+ if (q->qs[x].qlen == 1) { /* The flow is new */
|
||||
+ if (q->tail == depth) { /* It is the first flow */
|
||||
+ q->tail = x;
|
||||
+ q->next[x] = x;
|
||||
+ q->allot[x] = q->quantum;
|
||||
+ } else {
|
||||
+ q->next[x] = q->next[q->tail];
|
||||
+ q->next[q->tail] = x;
|
||||
+ q->tail = x;
|
||||
+ }
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+static int esfq_enqueue(struct sk_buff *skb, struct Qdisc* sch)
|
||||
+{
|
||||
+ struct esfq_sched_data *q = qdisc_priv(sch);
|
||||
+ esfq_q_enqueue(skb, q, ESFQ_TAIL);
|
||||
+ sch->qstats.backlog += skb->len;
|
||||
+ if (++sch->q.qlen < q->limit-1) {
|
||||
+ sch->bstats.bytes += skb->len;
|
||||
+ sch->bstats.packets++;
|
||||
+ return 0;
|
||||
+ }
|
||||
+
|
||||
+ sch->qstats.drops++;
|
||||
+ esfq_drop(sch);
|
||||
+ return NET_XMIT_CN;
|
||||
+}
|
||||
+
|
||||
+static struct sk_buff *esfq_peek(struct Qdisc* sch)
|
||||
+{
|
||||
+ struct esfq_sched_data *q = qdisc_priv(sch);
|
||||
+ esfq_index a;
|
||||
+
|
||||
+ /* No active slots */
|
||||
+ if (q->tail == q->depth)
|
||||
+ return NULL;
|
||||
+
|
||||
+ a = q->next[q->tail];
|
||||
+ return skb_peek(&q->qs[a]);
|
||||
+}
|
||||
+
|
||||
+static struct sk_buff *esfq_q_dequeue(struct esfq_sched_data *q)
|
||||
+{
|
||||
+ struct sk_buff *skb;
|
||||
+ unsigned depth = q->depth;
|
||||
+ esfq_index a, old_a;
|
||||
+
|
||||
+ /* No active slots */
|
||||
+ if (q->tail == depth)
|
||||
+ return NULL;
|
||||
+
|
||||
+ a = old_a = q->next[q->tail];
|
||||
+
|
||||
+ /* Grab packet */
|
||||
+ skb = __skb_dequeue(&q->qs[a]);
|
||||
+ esfq_dec(q, a);
|
||||
+
|
||||
+ /* Is the slot empty? */
|
||||
+ if (q->qs[a].qlen == 0) {
|
||||
+ q->ht[q->hash[a]] = depth;
|
||||
+ a = q->next[a];
|
||||
+ if (a == old_a) {
|
||||
+ q->tail = depth;
|
||||
+ return skb;
|
||||
+ }
|
||||
+ q->next[q->tail] = a;
|
||||
+ q->allot[a] += q->quantum;
|
||||
+ } else if ((q->allot[a] -= skb->len) <= 0) {
|
||||
+ q->tail = a;
|
||||
+ a = q->next[a];
|
||||
+ q->allot[a] += q->quantum;
|
||||
+ }
|
||||
+
|
||||
+ return skb;
|
||||
+}
|
||||
+
|
||||
+static struct sk_buff *esfq_dequeue(struct Qdisc* sch)
|
||||
+{
|
||||
+ struct esfq_sched_data *q = qdisc_priv(sch);
|
||||
+ struct sk_buff *skb;
|
||||
+
|
||||
+ skb = esfq_q_dequeue(q);
|
||||
+ if (skb == NULL)
|
||||
+ return NULL;
|
||||
+ sch->q.qlen--;
|
||||
+ sch->qstats.backlog -= skb->len;
|
||||
+ return skb;
|
||||
+}
|
||||
+
|
||||
+static void esfq_q_destroy(struct esfq_sched_data *q)
|
||||
+{
|
||||
+ del_timer(&q->perturb_timer);
|
||||
+ if(q->ht)
|
||||
+ kfree(q->ht);
|
||||
+ if(q->dep)
|
||||
+ kfree(q->dep);
|
||||
+ if(q->next)
|
||||
+ kfree(q->next);
|
||||
+ if(q->allot)
|
||||
+ kfree(q->allot);
|
||||
+ if(q->hash)
|
||||
+ kfree(q->hash);
|
||||
+ if(q->qs)
|
||||
+ kfree(q->qs);
|
||||
+}
|
||||
+
|
||||
+static void esfq_destroy(struct Qdisc *sch)
|
||||
+{
|
||||
+ struct esfq_sched_data *q = qdisc_priv(sch);
|
||||
+ esfq_q_destroy(q);
|
||||
+}
|
||||
+
|
||||
+
|
||||
+static void esfq_reset(struct Qdisc* sch)
|
||||
+{
|
||||
+ struct sk_buff *skb;
|
||||
+
|
||||
+ while ((skb = esfq_dequeue(sch)) != NULL)
|
||||
+ kfree_skb(skb);
|
||||
+}
|
||||
+
|
||||
+static void esfq_perturbation(unsigned long arg)
|
||||
+{
|
||||
+ struct Qdisc *sch = (struct Qdisc*)arg;
|
||||
+ struct esfq_sched_data *q = qdisc_priv(sch);
|
||||
+
|
||||
+ q->perturbation = net_random()&0x1F;
|
||||
+
|
||||
+ if (q->perturb_period) {
|
||||
+ q->perturb_timer.expires = jiffies + q->perturb_period;
|
||||
+ add_timer(&q->perturb_timer);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+static unsigned int esfq_check_hash(unsigned int kind)
|
||||
+{
|
||||
+ switch (kind) {
|
||||
+ case TCA_SFQ_HASH_CTORIGDST:
|
||||
+ case TCA_SFQ_HASH_CTORIGSRC:
|
||||
+ case TCA_SFQ_HASH_CTREPLDST:
|
||||
+ case TCA_SFQ_HASH_CTREPLSRC:
|
||||
+ case TCA_SFQ_HASH_CTNATCHG:
|
||||
+#ifndef CONFIG_NET_SCH_ESFQ_NFCT
|
||||
+ {
|
||||
+ if (net_ratelimit())
|
||||
+ printk(KERN_WARNING "ESFQ: Conntrack hash types disabled in kernel config. Falling back to classic.\n");
|
||||
+ return TCA_SFQ_HASH_CLASSIC;
|
||||
+ }
|
||||
+#endif
|
||||
+ case TCA_SFQ_HASH_CLASSIC:
|
||||
+ case TCA_SFQ_HASH_DST:
|
||||
+ case TCA_SFQ_HASH_SRC:
|
||||
+ case TCA_SFQ_HASH_FWMARK:
|
||||
+ return kind;
|
||||
+ default:
|
||||
+ {
|
||||
+ if (net_ratelimit())
|
||||
+ printk(KERN_WARNING "ESFQ: Unknown hash type. Falling back to classic.\n");
|
||||
+ return TCA_SFQ_HASH_CLASSIC;
|
||||
+ }
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+static int esfq_q_init(struct esfq_sched_data *q, struct nlattr *opt)
|
||||
+{
|
||||
+ struct tc_esfq_qopt *ctl = nla_data(opt);
|
||||
+ esfq_index p = ~0U/2;
|
||||
+ int i;
|
||||
+
|
||||
+ if (opt && opt->nla_len < nla_attr_size(sizeof(*ctl)))
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ q->perturbation = 0;
|
||||
+ q->hash_kind = TCA_SFQ_HASH_CLASSIC;
|
||||
+ q->max_depth = 0;
|
||||
+ if (opt == NULL) {
|
||||
+ q->perturb_period = 0;
|
||||
+ q->hash_divisor = 1024;
|
||||
+ q->tail = q->limit = q->depth = 128;
|
||||
+
|
||||
+ } else {
|
||||
+ struct tc_esfq_qopt *ctl = nla_data(opt);
|
||||
+ if (ctl->quantum)
|
||||
+ q->quantum = ctl->quantum;
|
||||
+ q->perturb_period = ctl->perturb_period*HZ;
|
||||
+ q->hash_divisor = ctl->divisor ? : 1024;
|
||||
+ q->tail = q->limit = q->depth = ctl->flows ? : 128;
|
||||
+
|
||||
+ if ( q->depth > p - 1 )
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ if (ctl->limit)
|
||||
+ q->limit = min_t(u32, ctl->limit, q->depth);
|
||||
+
|
||||
+ if (ctl->hash_kind) {
|
||||
+ q->hash_kind = esfq_check_hash(ctl->hash_kind);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ q->ht = kmalloc(q->hash_divisor*sizeof(esfq_index), GFP_KERNEL);
|
||||
+ if (!q->ht)
|
||||
+ goto err_case;
|
||||
+ q->dep = kmalloc((1+q->depth*2)*sizeof(struct esfq_head), GFP_KERNEL);
|
||||
+ if (!q->dep)
|
||||
+ goto err_case;
|
||||
+ q->next = kmalloc(q->depth*sizeof(esfq_index), GFP_KERNEL);
|
||||
+ if (!q->next)
|
||||
+ goto err_case;
|
||||
+ q->allot = kmalloc(q->depth*sizeof(short), GFP_KERNEL);
|
||||
+ if (!q->allot)
|
||||
+ goto err_case;
|
||||
+ q->hash = kmalloc(q->depth*sizeof(unsigned short), GFP_KERNEL);
|
||||
+ if (!q->hash)
|
||||
+ goto err_case;
|
||||
+ q->qs = kmalloc(q->depth*sizeof(struct sk_buff_head), GFP_KERNEL);
|
||||
+ if (!q->qs)
|
||||
+ goto err_case;
|
||||
+
|
||||
+ for (i=0; i< q->hash_divisor; i++)
|
||||
+ q->ht[i] = q->depth;
|
||||
+ for (i=0; i<q->depth; i++) {
|
||||
+ skb_queue_head_init(&q->qs[i]);
|
||||
+ q->dep[i+q->depth].next = i+q->depth;
|
||||
+ q->dep[i+q->depth].prev = i+q->depth;
|
||||
+ }
|
||||
+
|
||||
+ for (i=0; i<q->depth; i++)
|
||||
+ esfq_link(q, i);
|
||||
+ return 0;
|
||||
+err_case:
|
||||
+ esfq_q_destroy(q);
|
||||
+ return -ENOBUFS;
|
||||
+}
|
||||
+
|
||||
+static int esfq_init(struct Qdisc *sch, struct nlattr *opt)
|
||||
+{
|
||||
+ struct esfq_sched_data *q = qdisc_priv(sch);
|
||||
+ int err;
|
||||
+
|
||||
+ q->quantum = psched_mtu(qdisc_dev(sch)); /* default */
|
||||
+ if ((err = esfq_q_init(q, opt)))
|
||||
+ return err;
|
||||
+
|
||||
+ init_timer(&q->perturb_timer);
|
||||
+ q->perturb_timer.data = (unsigned long)sch;
|
||||
+ q->perturb_timer.function = esfq_perturbation;
|
||||
+ if (q->perturb_period) {
|
||||
+ q->perturb_timer.expires = jiffies + q->perturb_period;
|
||||
+ add_timer(&q->perturb_timer);
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int esfq_change(struct Qdisc *sch, struct nlattr *opt)
|
||||
+{
|
||||
+ struct esfq_sched_data *q = qdisc_priv(sch);
|
||||
+ struct esfq_sched_data new;
|
||||
+ struct sk_buff *skb;
|
||||
+ int err;
|
||||
+
|
||||
+ /* set up new queue */
|
||||
+ memset(&new, 0, sizeof(struct esfq_sched_data));
|
||||
+ new.quantum = psched_mtu(qdisc_dev(sch)); /* default */
|
||||
+ if ((err = esfq_q_init(&new, opt)))
|
||||
+ return err;
|
||||
+
|
||||
+ /* copy all packets from the old queue to the new queue */
|
||||
+ sch_tree_lock(sch);
|
||||
+ while ((skb = esfq_q_dequeue(q)) != NULL)
|
||||
+ esfq_q_enqueue(skb, &new, ESFQ_TAIL);
|
||||
+
|
||||
+ /* clean up the old queue */
|
||||
+ esfq_q_destroy(q);
|
||||
+
|
||||
+ /* copy elements of the new queue into the old queue */
|
||||
+ q->perturb_period = new.perturb_period;
|
||||
+ q->quantum = new.quantum;
|
||||
+ q->limit = new.limit;
|
||||
+ q->depth = new.depth;
|
||||
+ q->hash_divisor = new.hash_divisor;
|
||||
+ q->hash_kind = new.hash_kind;
|
||||
+ q->tail = new.tail;
|
||||
+ q->max_depth = new.max_depth;
|
||||
+ q->ht = new.ht;
|
||||
+ q->dep = new.dep;
|
||||
+ q->next = new.next;
|
||||
+ q->allot = new.allot;
|
||||
+ q->hash = new.hash;
|
||||
+ q->qs = new.qs;
|
||||
+
|
||||
+ /* finish up */
|
||||
+ if (q->perturb_period) {
|
||||
+ q->perturb_timer.expires = jiffies + q->perturb_period;
|
||||
+ add_timer(&q->perturb_timer);
|
||||
+ } else {
|
||||
+ q->perturbation = 0;
|
||||
+ }
|
||||
+ sch_tree_unlock(sch);
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int esfq_dump(struct Qdisc *sch, struct sk_buff *skb)
|
||||
+{
|
||||
+ struct esfq_sched_data *q = qdisc_priv(sch);
|
||||
+ unsigned char *b = skb_tail_pointer(skb);
|
||||
+ struct tc_esfq_qopt opt;
|
||||
+
|
||||
+ opt.quantum = q->quantum;
|
||||
+ opt.perturb_period = q->perturb_period/HZ;
|
||||
+
|
||||
+ opt.limit = q->limit;
|
||||
+ opt.divisor = q->hash_divisor;
|
||||
+ opt.flows = q->depth;
|
||||
+ opt.hash_kind = q->hash_kind;
|
||||
+
|
||||
+ NLA_PUT(skb, TCA_OPTIONS, sizeof(opt), &opt);
|
||||
+
|
||||
+ return skb->len;
|
||||
+
|
||||
+nla_put_failure:
|
||||
+ nlmsg_trim(skb, b);
|
||||
+ return -1;
|
||||
+}
|
||||
+
|
||||
+static struct Qdisc_ops esfq_qdisc_ops =
|
||||
+{
|
||||
+ .next = NULL,
|
||||
+ .cl_ops = NULL,
|
||||
+ .id = "esfq",
|
||||
+ .priv_size = sizeof(struct esfq_sched_data),
|
||||
+ .enqueue = esfq_enqueue,
|
||||
+ .dequeue = esfq_dequeue,
|
||||
+ .peek = esfq_peek,
|
||||
+ .drop = esfq_drop,
|
||||
+ .init = esfq_init,
|
||||
+ .reset = esfq_reset,
|
||||
+ .destroy = esfq_destroy,
|
||||
+ .change = esfq_change,
|
||||
+ .dump = esfq_dump,
|
||||
+ .owner = THIS_MODULE,
|
||||
+};
|
||||
+
|
||||
+static int __init esfq_module_init(void)
|
||||
+{
|
||||
+ return register_qdisc(&esfq_qdisc_ops);
|
||||
+}
|
||||
+static void __exit esfq_module_exit(void)
|
||||
+{
|
||||
+ unregister_qdisc(&esfq_qdisc_ops);
|
||||
+}
|
||||
+module_init(esfq_module_init)
|
||||
+module_exit(esfq_module_exit)
|
||||
+MODULE_LICENSE("GPL");
|
@ -1,227 +0,0 @@
|
||||
--- a/include/linux/jhash.h
|
||||
+++ b/include/linux/jhash.h
|
||||
@@ -3,80 +3,95 @@
|
||||
|
||||
/* jhash.h: Jenkins hash support.
|
||||
*
|
||||
- * Copyright (C) 1996 Bob Jenkins (bob_jenkins@burtleburtle.net)
|
||||
+ * Copyright (C) 2006. Bob Jenkins (bob_jenkins@burtleburtle.net)
|
||||
*
|
||||
* http://burtleburtle.net/bob/hash/
|
||||
*
|
||||
* These are the credits from Bob's sources:
|
||||
*
|
||||
- * lookup2.c, by Bob Jenkins, December 1996, Public Domain.
|
||||
- * hash(), hash2(), hash3, and mix() are externally useful functions.
|
||||
- * Routines to test the hash are included if SELF_TEST is defined.
|
||||
- * You can use this free for any purpose. It has no warranty.
|
||||
+ * lookup3.c, by Bob Jenkins, May 2006, Public Domain.
|
||||
*
|
||||
- * Copyright (C) 2003 David S. Miller (davem@redhat.com)
|
||||
+ * These are functions for producing 32-bit hashes for hash table lookup.
|
||||
+ * hashword(), hashlittle(), hashlittle2(), hashbig(), mix(), and final()
|
||||
+ * are externally useful functions. Routines to test the hash are included
|
||||
+ * if SELF_TEST is defined. You can use this free for any purpose. It's in
|
||||
+ * the public domain. It has no warranty.
|
||||
+ *
|
||||
+ * Copyright (C) 2009 Jozsef Kadlecsik (kadlec@blackhole.kfki.hu)
|
||||
*
|
||||
* I've modified Bob's hash to be useful in the Linux kernel, and
|
||||
- * any bugs present are surely my fault. -DaveM
|
||||
+ * any bugs present are my fault. Jozsef
|
||||
*/
|
||||
|
||||
-/* NOTE: Arguments are modified. */
|
||||
-#define __jhash_mix(a, b, c) \
|
||||
+#define __rot(x,k) (((x)<<(k)) | ((x)>>(32-(k))))
|
||||
+
|
||||
+/* __jhash_mix - mix 3 32-bit values reversibly. */
|
||||
+#define __jhash_mix(a,b,c) \
|
||||
+{ \
|
||||
+ a -= c; a ^= __rot(c, 4); c += b; \
|
||||
+ b -= a; b ^= __rot(a, 6); a += c; \
|
||||
+ c -= b; c ^= __rot(b, 8); b += a; \
|
||||
+ a -= c; a ^= __rot(c,16); c += b; \
|
||||
+ b -= a; b ^= __rot(a,19); a += c; \
|
||||
+ c -= b; c ^= __rot(b, 4); b += a; \
|
||||
+}
|
||||
+
|
||||
+/* __jhash_final - final mixing of 3 32-bit values (a,b,c) into c */
|
||||
+#define __jhash_final(a,b,c) \
|
||||
{ \
|
||||
- a -= b; a -= c; a ^= (c>>13); \
|
||||
- b -= c; b -= a; b ^= (a<<8); \
|
||||
- c -= a; c -= b; c ^= (b>>13); \
|
||||
- a -= b; a -= c; a ^= (c>>12); \
|
||||
- b -= c; b -= a; b ^= (a<<16); \
|
||||
- c -= a; c -= b; c ^= (b>>5); \
|
||||
- a -= b; a -= c; a ^= (c>>3); \
|
||||
- b -= c; b -= a; b ^= (a<<10); \
|
||||
- c -= a; c -= b; c ^= (b>>15); \
|
||||
+ c ^= b; c -= __rot(b,14); \
|
||||
+ a ^= c; a -= __rot(c,11); \
|
||||
+ b ^= a; b -= __rot(a,25); \
|
||||
+ c ^= b; c -= __rot(b,16); \
|
||||
+ a ^= c; a -= __rot(c,4); \
|
||||
+ b ^= a; b -= __rot(a,14); \
|
||||
+ c ^= b; c -= __rot(b,24); \
|
||||
}
|
||||
|
||||
-/* The golden ration: an arbitrary value */
|
||||
-#define JHASH_GOLDEN_RATIO 0x9e3779b9
|
||||
+/* An arbitrary initial parameter */
|
||||
+#define JHASH_GOLDEN_RATIO 0xdeadbeef
|
||||
|
||||
/* The most generic version, hashes an arbitrary sequence
|
||||
* of bytes. No alignment or length assumptions are made about
|
||||
- * the input key.
|
||||
+ * the input key. The result depends on endianness.
|
||||
*/
|
||||
static inline u32 jhash(const void *key, u32 length, u32 initval)
|
||||
{
|
||||
- u32 a, b, c, len;
|
||||
+ u32 a,b,c;
|
||||
const u8 *k = key;
|
||||
|
||||
- len = length;
|
||||
- a = b = JHASH_GOLDEN_RATIO;
|
||||
- c = initval;
|
||||
-
|
||||
- while (len >= 12) {
|
||||
- a += (k[0] +((u32)k[1]<<8) +((u32)k[2]<<16) +((u32)k[3]<<24));
|
||||
- b += (k[4] +((u32)k[5]<<8) +((u32)k[6]<<16) +((u32)k[7]<<24));
|
||||
- c += (k[8] +((u32)k[9]<<8) +((u32)k[10]<<16)+((u32)k[11]<<24));
|
||||
-
|
||||
- __jhash_mix(a,b,c);
|
||||
+ /* Set up the internal state */
|
||||
+ a = b = c = JHASH_GOLDEN_RATIO + length + initval;
|
||||
|
||||
+ /* all but the last block: affect some 32 bits of (a,b,c) */
|
||||
+ while (length > 12) {
|
||||
+ a += (k[0] + ((u32)k[1]<<8) + ((u32)k[2]<<16) + ((u32)k[3]<<24));
|
||||
+ b += (k[4] + ((u32)k[5]<<8) + ((u32)k[6]<<16) + ((u32)k[7]<<24));
|
||||
+ c += (k[8] + ((u32)k[9]<<8) + ((u32)k[10]<<16) + ((u32)k[11]<<24));
|
||||
+ __jhash_mix(a, b, c);
|
||||
+ length -= 12;
|
||||
k += 12;
|
||||
- len -= 12;
|
||||
}
|
||||
|
||||
- c += length;
|
||||
- switch (len) {
|
||||
- case 11: c += ((u32)k[10]<<24);
|
||||
- case 10: c += ((u32)k[9]<<16);
|
||||
- case 9 : c += ((u32)k[8]<<8);
|
||||
- case 8 : b += ((u32)k[7]<<24);
|
||||
- case 7 : b += ((u32)k[6]<<16);
|
||||
- case 6 : b += ((u32)k[5]<<8);
|
||||
+ /* last block: affect all 32 bits of (c) */
|
||||
+ /* all the case statements fall through */
|
||||
+ switch (length) {
|
||||
+ case 12: c += (u32)k[11]<<24;
|
||||
+ case 11: c += (u32)k[10]<<16;
|
||||
+ case 10: c += (u32)k[9]<<8;
|
||||
+ case 9 : c += k[8];
|
||||
+ case 8 : b += (u32)k[7]<<24;
|
||||
+ case 7 : b += (u32)k[6]<<16;
|
||||
+ case 6 : b += (u32)k[5]<<8;
|
||||
case 5 : b += k[4];
|
||||
- case 4 : a += ((u32)k[3]<<24);
|
||||
- case 3 : a += ((u32)k[2]<<16);
|
||||
- case 2 : a += ((u32)k[1]<<8);
|
||||
+ case 4 : a += (u32)k[3]<<24;
|
||||
+ case 3 : a += (u32)k[2]<<16;
|
||||
+ case 2 : a += (u32)k[1]<<8;
|
||||
case 1 : a += k[0];
|
||||
- };
|
||||
-
|
||||
- __jhash_mix(a,b,c);
|
||||
+ __jhash_final(a, b, c);
|
||||
+ case 0 :
|
||||
+ break;
|
||||
+ }
|
||||
|
||||
return c;
|
||||
}
|
||||
@@ -86,58 +101,57 @@ static inline u32 jhash(const void *key,
|
||||
*/
|
||||
static inline u32 jhash2(const u32 *k, u32 length, u32 initval)
|
||||
{
|
||||
- u32 a, b, c, len;
|
||||
+ u32 a, b, c;
|
||||
|
||||
- a = b = JHASH_GOLDEN_RATIO;
|
||||
- c = initval;
|
||||
- len = length;
|
||||
+ /* Set up the internal state */
|
||||
+ a = b = c = JHASH_GOLDEN_RATIO + (length<<2) + initval;
|
||||
|
||||
- while (len >= 3) {
|
||||
+ /* handle most of the key */
|
||||
+ while (length > 3) {
|
||||
a += k[0];
|
||||
b += k[1];
|
||||
c += k[2];
|
||||
__jhash_mix(a, b, c);
|
||||
- k += 3; len -= 3;
|
||||
+ length -= 3;
|
||||
+ k += 3;
|
||||
}
|
||||
|
||||
- c += length * 4;
|
||||
-
|
||||
- switch (len) {
|
||||
- case 2 : b += k[1];
|
||||
- case 1 : a += k[0];
|
||||
- };
|
||||
-
|
||||
- __jhash_mix(a,b,c);
|
||||
+ /* handle the last 3 u32's */
|
||||
+ /* all the case statements fall through */
|
||||
+ switch (length) {
|
||||
+ case 3: c += k[2];
|
||||
+ case 2: b += k[1];
|
||||
+ case 1: a += k[0];
|
||||
+ __jhash_final(a, b, c);
|
||||
+ case 0: /* case 0: nothing left to add */
|
||||
+ break;
|
||||
+ }
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
-
|
||||
/* A special ultra-optimized versions that knows they are hashing exactly
|
||||
* 3, 2 or 1 word(s).
|
||||
- *
|
||||
- * NOTE: In partilar the "c += length; __jhash_mix(a,b,c);" normally
|
||||
- * done at the end is not done here.
|
||||
*/
|
||||
static inline u32 jhash_3words(u32 a, u32 b, u32 c, u32 initval)
|
||||
{
|
||||
- a += JHASH_GOLDEN_RATIO;
|
||||
- b += JHASH_GOLDEN_RATIO;
|
||||
- c += initval;
|
||||
+ a += JHASH_GOLDEN_RATIO + initval;
|
||||
+ b += JHASH_GOLDEN_RATIO + initval;
|
||||
+ c += JHASH_GOLDEN_RATIO + initval;
|
||||
|
||||
- __jhash_mix(a, b, c);
|
||||
+ __jhash_final(a, b, c);
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
static inline u32 jhash_2words(u32 a, u32 b, u32 initval)
|
||||
{
|
||||
- return jhash_3words(a, b, 0, initval);
|
||||
+ return jhash_3words(0, a, b, initval);
|
||||
}
|
||||
|
||||
static inline u32 jhash_1word(u32 a, u32 initval)
|
||||
{
|
||||
- return jhash_3words(a, 0, 0, initval);
|
||||
+ return jhash_3words(0, 0, a, initval);
|
||||
}
|
||||
|
||||
#endif /* _LINUX_JHASH_H */
|
@ -1,83 +0,0 @@
|
||||
--- a/arch/mips/include/asm/string.h
|
||||
+++ b/arch/mips/include/asm/string.h
|
||||
@@ -133,11 +133,44 @@ strncmp(__const__ char *__cs, __const__
|
||||
|
||||
#define __HAVE_ARCH_MEMSET
|
||||
extern void *memset(void *__s, int __c, size_t __count);
|
||||
+#define memset(__s, __c, len) \
|
||||
+({ \
|
||||
+ size_t __len = (len); \
|
||||
+ void *__ret; \
|
||||
+ if (__builtin_constant_p(len) && __len >= 64) \
|
||||
+ __ret = memset((__s), (__c), __len); \
|
||||
+ else \
|
||||
+ __ret = __builtin_memset((__s), (__c), __len); \
|
||||
+ __ret; \
|
||||
+})
|
||||
|
||||
#define __HAVE_ARCH_MEMCPY
|
||||
extern void *memcpy(void *__to, __const__ void *__from, size_t __n);
|
||||
+#define memcpy(dst, src, len) \
|
||||
+({ \
|
||||
+ size_t __len = (len); \
|
||||
+ void *__ret; \
|
||||
+ if (__builtin_constant_p(len) && __len >= 64) \
|
||||
+ __ret = memcpy((dst), (src), __len); \
|
||||
+ else \
|
||||
+ __ret = __builtin_memcpy((dst), (src), __len); \
|
||||
+ __ret; \
|
||||
+})
|
||||
|
||||
#define __HAVE_ARCH_MEMMOVE
|
||||
extern void *memmove(void *__dest, __const__ void *__src, size_t __n);
|
||||
+#define memmove(dst, src, len) \
|
||||
+({ \
|
||||
+ size_t __len = (len); \
|
||||
+ void *__ret; \
|
||||
+ if (__builtin_constant_p(len) && __len >= 64) \
|
||||
+ __ret = memmove((dst), (src), __len); \
|
||||
+ else \
|
||||
+ __ret = __builtin_memmove((dst), (src), __len); \
|
||||
+ __ret; \
|
||||
+})
|
||||
+
|
||||
+#define __HAVE_ARCH_MEMCMP
|
||||
+#define memcmp(src1, src2, len) __builtin_memcmp((src1), (src2), (len))
|
||||
|
||||
#endif /* _ASM_STRING_H */
|
||||
--- a/arch/mips/lib/Makefile
|
||||
+++ b/arch/mips/lib/Makefile
|
||||
@@ -3,7 +3,7 @@
|
||||
#
|
||||
|
||||
lib-y += csum_partial.o delay.o memcpy.o memcpy-inatomic.o memset.o \
|
||||
- strlen_user.o strncpy_user.o strnlen_user.o uncached.o
|
||||
+ strlen_user.o strncpy_user.o strnlen_user.o uncached.o memcmp.o
|
||||
|
||||
obj-y += iomap.o
|
||||
obj-$(CONFIG_PCI) += iomap-pci.o
|
||||
--- /dev/null
|
||||
+++ b/arch/mips/lib/memcmp.c
|
||||
@@ -0,0 +1,22 @@
|
||||
+/*
|
||||
+ * copied from linux/lib/string.c
|
||||
+ *
|
||||
+ * Copyright (C) 1991, 1992 Linus Torvalds
|
||||
+ */
|
||||
+
|
||||
+#include <linux/module.h>
|
||||
+#include <linux/string.h>
|
||||
+
|
||||
+#undef memcmp
|
||||
+int memcmp(const void *cs, const void *ct, size_t count)
|
||||
+{
|
||||
+ const unsigned char *su1, *su2;
|
||||
+ int res = 0;
|
||||
+
|
||||
+ for (su1 = cs, su2 = ct; 0 < count; ++su1, ++su2, count--)
|
||||
+ if ((res = *su1 - *su2) != 0)
|
||||
+ break;
|
||||
+ return res;
|
||||
+}
|
||||
+EXPORT_SYMBOL(memcmp);
|
||||
+
|
@ -1,13 +0,0 @@
|
||||
--- a/include/linux/slab.h
|
||||
+++ b/include/linux/slab.h
|
||||
@@ -124,8 +124,8 @@ int kmem_ptr_validate(struct kmem_cache
|
||||
* to do various tricks to work around compiler limitations in order to
|
||||
* ensure proper constant folding.
|
||||
*/
|
||||
-#define KMALLOC_SHIFT_HIGH ((MAX_ORDER + PAGE_SHIFT - 1) <= 25 ? \
|
||||
- (MAX_ORDER + PAGE_SHIFT - 1) : 25)
|
||||
+#define KMALLOC_SHIFT_HIGH ((MAX_ORDER + PAGE_SHIFT - 1) <= 17 ? \
|
||||
+ (MAX_ORDER + PAGE_SHIFT - 1) : 17)
|
||||
|
||||
#define KMALLOC_MAX_SIZE (1UL << KMALLOC_SHIFT_HIGH)
|
||||
#define KMALLOC_MAX_ORDER (KMALLOC_SHIFT_HIGH - PAGE_SHIFT)
|
@ -1,132 +0,0 @@
|
||||
--- a/fs/jffs2/build.c
|
||||
+++ b/fs/jffs2/build.c
|
||||
@@ -111,6 +111,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;
|
||||
@@ -144,8 +144,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;
|
||||
@@ -400,7 +403,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
|
||||
@@ -473,7 +476,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);
|
||||
@@ -489,9 +492,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;
|
||||
|
||||
@@ -510,9 +513,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;
|
||||
}
|
||||
@@ -525,7 +528,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. */
|
||||
@@ -546,6 +549,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;
|
||||
|
||||
@@ -671,7 +685,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) {
|
||||
@@ -907,7 +921,7 @@ scan_more:
|
||||
|
||||
D1(printk(KERN_DEBUG "Block at 0x%08x: free 0x%08x, dirty 0x%08x, unchecked 0x%08x, used 0x%08x, wasted 0x%08x\n",
|
||||
jeb->offset,jeb->free_size, jeb->dirty_size, jeb->unchecked_size, jeb->used_size, jeb->wasted_size));
|
||||
-
|
||||
+
|
||||
/* mark_node_obsolete can add to wasted !! */
|
||||
if (jeb->wasted_size) {
|
||||
jeb->dirty_size += jeb->wasted_size;
|
@ -1,56 +0,0 @@
|
||||
--- a/include/linux/skbuff.h
|
||||
+++ b/include/linux/skbuff.h
|
||||
@@ -1369,11 +1369,18 @@ static inline int skb_network_offset(con
|
||||
*
|
||||
* Various parts of the networking layer expect at least 32 bytes of
|
||||
* headroom, you should not reduce this.
|
||||
+ *
|
||||
+ * This has been changed to 64 to acommodate for routing between ethernet
|
||||
+ * and wireless, but only for new allocations
|
||||
*/
|
||||
#ifndef NET_SKB_PAD
|
||||
#define NET_SKB_PAD 32
|
||||
#endif
|
||||
|
||||
+#ifndef NET_SKB_PAD_ALLOC
|
||||
+#define NET_SKB_PAD_ALLOC 64
|
||||
+#endif
|
||||
+
|
||||
extern int ___pskb_trim(struct sk_buff *skb, unsigned int len);
|
||||
|
||||
static inline void __skb_trim(struct sk_buff *skb, unsigned int len)
|
||||
@@ -1463,9 +1470,9 @@ static inline void __skb_queue_purge(str
|
||||
static inline struct sk_buff *__dev_alloc_skb(unsigned int length,
|
||||
gfp_t gfp_mask)
|
||||
{
|
||||
- struct sk_buff *skb = alloc_skb(length + NET_SKB_PAD, gfp_mask);
|
||||
+ struct sk_buff *skb = alloc_skb(length + NET_SKB_PAD_ALLOC, gfp_mask);
|
||||
if (likely(skb))
|
||||
- skb_reserve(skb, NET_SKB_PAD);
|
||||
+ skb_reserve(skb, NET_SKB_PAD_ALLOC);
|
||||
return skb;
|
||||
}
|
||||
|
||||
@@ -1538,7 +1545,7 @@ static inline int __skb_cow(struct sk_bu
|
||||
delta = headroom - skb_headroom(skb);
|
||||
|
||||
if (delta || cloned)
|
||||
- return pskb_expand_head(skb, ALIGN(delta, NET_SKB_PAD), 0,
|
||||
+ return pskb_expand_head(skb, ALIGN(delta, NET_SKB_PAD_ALLOC), 0,
|
||||
GFP_ATOMIC);
|
||||
return 0;
|
||||
}
|
||||
--- a/net/core/skbuff.c
|
||||
+++ b/net/core/skbuff.c
|
||||
@@ -259,9 +259,9 @@ struct sk_buff *__netdev_alloc_skb(struc
|
||||
int node = dev->dev.parent ? dev_to_node(dev->dev.parent) : -1;
|
||||
struct sk_buff *skb;
|
||||
|
||||
- skb = __alloc_skb(length + NET_SKB_PAD, gfp_mask, 0, node);
|
||||
+ skb = __alloc_skb(length + NET_SKB_PAD_ALLOC, gfp_mask, 0, node);
|
||||
if (likely(skb)) {
|
||||
- skb_reserve(skb, NET_SKB_PAD);
|
||||
+ skb_reserve(skb, NET_SKB_PAD_ALLOC);
|
||||
skb->dev = dev;
|
||||
}
|
||||
return skb;
|
@ -1,9 +0,0 @@
|
||||
--- /dev/null
|
||||
+++ b/include/asm-powerpc/segment.h
|
||||
@@ -0,0 +1,6 @@
|
||||
+#ifndef _ASM_SEGMENT_H
|
||||
+#define _ASM_SEGMENT_H
|
||||
+
|
||||
+/* Only here because we have some old header files that expect it.. */
|
||||
+
|
||||
+#endif /* _ASM_SEGMENT_H */
|
File diff suppressed because it is too large
Load Diff
@ -1,143 +0,0 @@
|
||||
--- a/fs/mini_fo/main.c
|
||||
+++ b/fs/mini_fo/main.c
|
||||
@@ -79,6 +79,7 @@ mini_fo_tri_interpose(dentry_t *hidden_d
|
||||
* of the new inode's fields
|
||||
*/
|
||||
|
||||
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,25)
|
||||
/*
|
||||
* original: inode = iget(sb, hidden_inode->i_ino);
|
||||
*/
|
||||
@@ -87,6 +88,13 @@ mini_fo_tri_interpose(dentry_t *hidden_d
|
||||
err = -EACCES; /* should be impossible??? */
|
||||
goto out;
|
||||
}
|
||||
+#else
|
||||
+ inode = mini_fo_iget(sb, iunique(sb, 25));
|
||||
+ if (IS_ERR(inode)) {
|
||||
+ err = PTR_ERR(inode);
|
||||
+ goto out;
|
||||
+ }
|
||||
+#endif
|
||||
|
||||
/*
|
||||
* interpose the inode if not already interposed
|
||||
@@ -184,9 +192,9 @@ mini_fo_parse_options(super_block_t *sb,
|
||||
hidden_root = ERR_PTR(err);
|
||||
goto out;
|
||||
}
|
||||
- hidden_root = nd.dentry;
|
||||
- stopd(sb)->base_dir_dentry = nd.dentry;
|
||||
- stopd(sb)->hidden_mnt = nd.mnt;
|
||||
+ hidden_root = nd_get_dentry(&nd);
|
||||
+ stopd(sb)->base_dir_dentry = nd_get_dentry(&nd);
|
||||
+ stopd(sb)->hidden_mnt = nd_get_mnt(&nd);
|
||||
|
||||
} else if(!strncmp("sto=", options, 4)) {
|
||||
/* parse the storage dir */
|
||||
@@ -204,9 +212,9 @@ mini_fo_parse_options(super_block_t *sb,
|
||||
hidden_root2 = ERR_PTR(err);
|
||||
goto out;
|
||||
}
|
||||
- hidden_root2 = nd2.dentry;
|
||||
- stopd(sb)->storage_dir_dentry = nd2.dentry;
|
||||
- stopd(sb)->hidden_mnt2 = nd2.mnt;
|
||||
+ hidden_root2 = nd_get_dentry(&nd2);
|
||||
+ stopd(sb)->storage_dir_dentry = nd_get_dentry(&nd2);
|
||||
+ stopd(sb)->hidden_mnt2 = nd_get_mnt(&nd2);
|
||||
stohs2(sb) = hidden_root2->d_sb;
|
||||
|
||||
/* validate storage dir, this is done in
|
||||
--- a/fs/mini_fo/mini_fo.h
|
||||
+++ b/fs/mini_fo/mini_fo.h
|
||||
@@ -302,6 +302,10 @@ extern int mini_fo_tri_interpose(dentry_
|
||||
extern int mini_fo_cp_cont(dentry_t *tgt_dentry, struct vfsmount *tgt_mnt,
|
||||
dentry_t *src_dentry, struct vfsmount *src_mnt);
|
||||
|
||||
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,25)
|
||||
+extern struct inode *mini_fo_iget(struct super_block *sb, unsigned long ino);
|
||||
+#endif
|
||||
+
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
|
||||
extern int mini_fo_create(inode_t *dir, dentry_t *dentry, int mode, struct nameidata *nd);
|
||||
|
||||
@@ -501,6 +505,29 @@ static inline void double_unlock(struct
|
||||
#endif /* if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) */
|
||||
#endif /* __KERNEL__ */
|
||||
|
||||
+
|
||||
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,25)
|
||||
+static inline dentry_t *nd_get_dentry(struct nameidata *nd)
|
||||
+{
|
||||
+ return (nd->path.dentry);
|
||||
+}
|
||||
+
|
||||
+static inline struct vfsmount *nd_get_mnt(struct nameidata *nd)
|
||||
+{
|
||||
+ return (nd->path.mnt);
|
||||
+}
|
||||
+#else
|
||||
+static inline dentry_t *nd_get_dentry(struct nameidata *nd)
|
||||
+{
|
||||
+ return (nd->dentry);
|
||||
+}
|
||||
+
|
||||
+static inline struct vfsmount *nd_get_mnt(struct nameidata *nd)
|
||||
+{
|
||||
+ return (nd->mnt);
|
||||
+}
|
||||
+#endif
|
||||
+
|
||||
/*
|
||||
* Definitions for user and kernel code
|
||||
*/
|
||||
--- a/fs/mini_fo/super.c
|
||||
+++ b/fs/mini_fo/super.c
|
||||
@@ -262,10 +262,31 @@ mini_fo_umount_begin(super_block_t *sb)
|
||||
}
|
||||
#endif
|
||||
|
||||
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,25)
|
||||
+struct inode *
|
||||
+mini_fo_iget(struct super_block *sb, unsigned long ino)
|
||||
+{
|
||||
+ struct inode *inode;
|
||||
+
|
||||
+ inode = iget_locked(sb, ino);
|
||||
+ if (!inode)
|
||||
+ return ERR_PTR(-ENOMEM);
|
||||
+
|
||||
+ if (!(inode->i_state & I_NEW))
|
||||
+ return inode;
|
||||
+
|
||||
+ mini_fo_read_inode(inode);
|
||||
+
|
||||
+ unlock_new_inode(inode);
|
||||
+ return inode;
|
||||
+}
|
||||
+#endif /* if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,25) */
|
||||
|
||||
struct super_operations mini_fo_sops =
|
||||
{
|
||||
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,25)
|
||||
read_inode: mini_fo_read_inode,
|
||||
+#endif
|
||||
#if defined(FIST_DEBUG) || defined(FIST_FILTER_SCA)
|
||||
write_inode: mini_fo_write_inode,
|
||||
#endif /* defined(FIST_DEBUG) || defined(FIST_FILTER_SCA) */
|
||||
--- a/fs/mini_fo/aux.c
|
||||
+++ b/fs/mini_fo/aux.c
|
||||
@@ -164,11 +164,11 @@ dentry_t *bpath_walk(super_block_t *sb,
|
||||
err = vfs_path_lookup(mnt->mnt_root, mnt, bpath+1, 0, &nd);
|
||||
|
||||
/* validate */
|
||||
- if (err || !nd.dentry || !nd.dentry->d_inode) {
|
||||
+ if (err || !nd_get_dentry(&nd) || !nd_get_dentry(&nd)->d_inode) {
|
||||
printk(KERN_CRIT "mini_fo: bpath_walk: path_walk failed.\n");
|
||||
return NULL;
|
||||
}
|
||||
- return nd.dentry;
|
||||
+ return nd_get_dentry(&nd);
|
||||
}
|
||||
|
||||
|
@ -1,66 +0,0 @@
|
||||
--- a/fs/mini_fo/meta.c
|
||||
+++ b/fs/mini_fo/meta.c
|
||||
@@ -442,6 +442,11 @@ int meta_write_d_entry(dentry_t *dentry,
|
||||
S_IRUSR | S_IWUSR);
|
||||
#endif
|
||||
}
|
||||
+
|
||||
+ /* $%& err, is this correct? */
|
||||
+ meta_mnt = stopd(dentry->d_inode->i_sb)->hidden_mnt2;
|
||||
+ mntget(meta_mnt);
|
||||
+
|
||||
/* open META-file for writing */
|
||||
meta_file = dentry_open(meta_dentry, meta_mnt, 0x1);
|
||||
if(!meta_file || IS_ERR(meta_file)) {
|
||||
@@ -535,6 +540,11 @@ int meta_write_r_entry(dentry_t *dentry,
|
||||
meta_dentry, S_IRUSR | S_IWUSR);
|
||||
#endif
|
||||
}
|
||||
+
|
||||
+ /* $%& err, is this correct? */
|
||||
+ meta_mnt = stopd(dentry->d_inode->i_sb)->hidden_mnt2;
|
||||
+ mntget(meta_mnt);
|
||||
+
|
||||
/* open META-file for writing */
|
||||
meta_file = dentry_open(meta_dentry, meta_mnt, 0x1);
|
||||
if(!meta_file || IS_ERR(meta_file)) {
|
||||
@@ -671,14 +681,16 @@ int meta_sync_d_list(dentry_t *dentry, i
|
||||
}
|
||||
}
|
||||
|
||||
+ /* $%& err, is this correct? */
|
||||
+ meta_mnt = stopd(dentry->d_inode->i_sb)->hidden_mnt2;
|
||||
+ mntget(meta_mnt);
|
||||
+
|
||||
/* open META-file for writing */
|
||||
meta_file = dentry_open(meta_dentry, meta_mnt, 0x1);
|
||||
if(!meta_file || IS_ERR(meta_file)) {
|
||||
printk(KERN_CRIT "mini_fo: meta_sync_d_list: \
|
||||
ERROR opening meta file.\n");
|
||||
- /* we don't mntget so we dont't mntput (for now)
|
||||
- * mntput(meta_mnt);
|
||||
- */
|
||||
+ mntput(meta_mnt);
|
||||
dput(meta_dentry);
|
||||
err = -1;
|
||||
goto out;
|
||||
@@ -811,14 +823,16 @@ int meta_sync_r_list(dentry_t *dentry, i
|
||||
}
|
||||
}
|
||||
|
||||
+ /* $%& err, is this correct? */
|
||||
+ meta_mnt = stopd(dentry->d_inode->i_sb)->hidden_mnt2;
|
||||
+ mntget(meta_mnt);
|
||||
+
|
||||
/* open META-file for writing */
|
||||
meta_file = dentry_open(meta_dentry, meta_mnt, 0x1);
|
||||
if(!meta_file || IS_ERR(meta_file)) {
|
||||
printk(KERN_CRIT "mini_fo: meta_sync_r_list: \
|
||||
ERROR opening meta file.\n");
|
||||
- /* we don't mntget so we dont't mntput (for now)
|
||||
- * mntput(meta_mnt);
|
||||
- */
|
||||
+ mntput(meta_mnt);
|
||||
dput(meta_dentry);
|
||||
err = -1;
|
||||
goto out;
|
@ -1,37 +0,0 @@
|
||||
--- a/fs/mini_fo/super.c
|
||||
+++ b/fs/mini_fo/super.c
|
||||
@@ -84,6 +84,7 @@ mini_fo_write_inode(inode_t *inode, int
|
||||
#endif /* defined(FIST_DEBUG) || defined(FIST_FILTER_SCA) */
|
||||
|
||||
|
||||
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,26)
|
||||
STATIC void
|
||||
mini_fo_put_inode(inode_t *inode)
|
||||
{
|
||||
@@ -99,6 +100,7 @@ mini_fo_put_inode(inode_t *inode)
|
||||
if (atomic_read(&inode->i_count) == 1)
|
||||
inode->i_nlink = 0;
|
||||
}
|
||||
+#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(2,6,26) */
|
||||
|
||||
|
||||
#if defined(FIST_DEBUG) || defined(FIST_FILTER_SCA)
|
||||
@@ -238,7 +240,7 @@ mini_fo_clear_inode(inode_t *inode)
|
||||
* dies.
|
||||
*/
|
||||
STATIC void
|
||||
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,18)
|
||||
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,18)) && (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,26))
|
||||
mini_fo_umount_begin(struct vfsmount *mnt, int flags)
|
||||
{
|
||||
struct vfsmount *hidden_mnt;
|
||||
@@ -290,7 +292,9 @@ struct super_operations mini_fo_sops =
|
||||
#if defined(FIST_DEBUG) || defined(FIST_FILTER_SCA)
|
||||
write_inode: mini_fo_write_inode,
|
||||
#endif /* defined(FIST_DEBUG) || defined(FIST_FILTER_SCA) */
|
||||
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,26)
|
||||
put_inode: mini_fo_put_inode,
|
||||
+#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(2,6,26) */
|
||||
#if defined(FIST_DEBUG) || defined(FIST_FILTER_SCA)
|
||||
delete_inode: mini_fo_delete_inode,
|
||||
#endif /* defined(FIST_DEBUG) || defined(FIST_FILTER_SCA) */
|
@ -1,41 +0,0 @@
|
||||
--- a/fs/mini_fo/inode.c
|
||||
+++ b/fs/mini_fo/inode.c
|
||||
@@ -439,7 +439,7 @@ mini_fo_symlink(inode_t *dir, dentry_t *
|
||||
int err=0;
|
||||
dentry_t *hidden_sto_dentry;
|
||||
dentry_t *hidden_sto_dir_dentry;
|
||||
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
|
||||
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)) && (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,27))
|
||||
umode_t mode;
|
||||
#endif
|
||||
|
||||
@@ -466,7 +466,7 @@ mini_fo_symlink(inode_t *dir, dentry_t *
|
||||
down(&hidden_sto_dir_dentry->d_inode->i_sem);
|
||||
#endif
|
||||
|
||||
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
|
||||
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)) && (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,27))
|
||||
mode = S_IALLUGO;
|
||||
err = vfs_symlink(hidden_sto_dir_dentry->d_inode,
|
||||
hidden_sto_dentry, symname, mode);
|
||||
@@ -1128,7 +1128,7 @@ void mini_fo_put_link(struct dentry *den
|
||||
#endif
|
||||
|
||||
STATIC int
|
||||
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
|
||||
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)) && (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,27))
|
||||
mini_fo_permission(inode_t *inode, int mask, struct nameidata *nd)
|
||||
#else
|
||||
mini_fo_permission(inode_t *inode, int mask)
|
||||
@@ -1150,8 +1150,9 @@ mini_fo_permission(inode_t *inode, int m
|
||||
* if (err)
|
||||
* goto out;
|
||||
*/
|
||||
-
|
||||
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
|
||||
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27)
|
||||
+ err = inode_permission(hidden_inode, mask);
|
||||
+#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
|
||||
err = permission(hidden_inode, mask, nd);
|
||||
#else
|
||||
err = permission(hidden_inode, mask);
|
@ -1,96 +0,0 @@
|
||||
--- a/fs/mini_fo/aux.c
|
||||
+++ b/fs/mini_fo/aux.c
|
||||
@@ -236,7 +236,7 @@ int mini_fo_cp_cont(dentry_t *tgt_dentry
|
||||
mntget(src_mnt);
|
||||
|
||||
/* open file write only */
|
||||
- tgt_file = dentry_open(tgt_dentry, tgt_mnt, 0x1);
|
||||
+ tgt_file = dentry_open(tgt_dentry, tgt_mnt, 0x1, current_cred());
|
||||
if(!tgt_file || IS_ERR(tgt_file)) {
|
||||
printk(KERN_CRIT "mini_fo_cp_cont: ERROR opening target file.\n");
|
||||
err = PTR_ERR(tgt_file);
|
||||
@@ -244,7 +244,7 @@ int mini_fo_cp_cont(dentry_t *tgt_dentry
|
||||
}
|
||||
|
||||
/* open file read only */
|
||||
- src_file = dentry_open(src_dentry, src_mnt, 0x0);
|
||||
+ src_file = dentry_open(src_dentry, src_mnt, 0x0, current_cred());
|
||||
if(!src_file || IS_ERR(src_file)) {
|
||||
printk(KERN_CRIT "mini_fo_cp_cont: ERROR opening source file.\n");
|
||||
err = PTR_ERR(src_file);
|
||||
--- a/fs/mini_fo/file.c
|
||||
+++ b/fs/mini_fo/file.c
|
||||
@@ -437,7 +437,7 @@ mini_fo_open(inode_t *inode, file_t *fil
|
||||
mntget(stopd(inode->i_sb)->hidden_mnt);
|
||||
hidden_file = dentry_open(hidden_dentry,
|
||||
stopd(inode->i_sb)->hidden_mnt,
|
||||
- hidden_flags);
|
||||
+ hidden_flags, file->f_cred);
|
||||
if (IS_ERR(hidden_file)) {
|
||||
err = PTR_ERR(hidden_file);
|
||||
dput(hidden_dentry);
|
||||
@@ -479,7 +479,7 @@ mini_fo_open(inode_t *inode, file_t *fil
|
||||
mntget(stopd(inode->i_sb)->hidden_mnt);
|
||||
hidden_file = dentry_open(hidden_dentry,
|
||||
stopd(inode->i_sb)->hidden_mnt,
|
||||
- hidden_flags);
|
||||
+ hidden_flags, file->f_cred);
|
||||
if (IS_ERR(hidden_file)) {
|
||||
err = PTR_ERR(hidden_file);
|
||||
dput(hidden_dentry);
|
||||
@@ -512,7 +512,7 @@ mini_fo_open(inode_t *inode, file_t *fil
|
||||
mntget(stopd(inode->i_sb)->hidden_mnt2);
|
||||
hidden_sto_file = dentry_open(hidden_sto_dentry,
|
||||
stopd(inode->i_sb)->hidden_mnt2,
|
||||
- hidden_flags);
|
||||
+ hidden_flags, file->f_cred);
|
||||
|
||||
/* dentry_open dputs the dentry if it fails */
|
||||
if (IS_ERR(hidden_sto_file)) {
|
||||
--- a/fs/mini_fo/meta.c
|
||||
+++ b/fs/mini_fo/meta.c
|
||||
@@ -56,7 +56,7 @@ int meta_build_lists(dentry_t *dentry)
|
||||
|
||||
|
||||
/* open META-file for reading */
|
||||
- meta_file = dentry_open(meta_dentry, meta_mnt, 0x0);
|
||||
+ meta_file = dentry_open(meta_dentry, meta_mnt, 0x0, current_cred());
|
||||
if(!meta_file || IS_ERR(meta_file)) {
|
||||
printk(KERN_CRIT "mini_fo: meta_build_lists: \
|
||||
ERROR opening META file.\n");
|
||||
@@ -448,7 +448,7 @@ int meta_write_d_entry(dentry_t *dentry,
|
||||
mntget(meta_mnt);
|
||||
|
||||
/* open META-file for writing */
|
||||
- meta_file = dentry_open(meta_dentry, meta_mnt, 0x1);
|
||||
+ meta_file = dentry_open(meta_dentry, meta_mnt, 0x1, current_cred());
|
||||
if(!meta_file || IS_ERR(meta_file)) {
|
||||
printk(KERN_CRIT "mini_fo: meta_write_d_entry: \
|
||||
ERROR opening meta file.\n");
|
||||
@@ -546,7 +546,7 @@ int meta_write_r_entry(dentry_t *dentry,
|
||||
mntget(meta_mnt);
|
||||
|
||||
/* open META-file for writing */
|
||||
- meta_file = dentry_open(meta_dentry, meta_mnt, 0x1);
|
||||
+ meta_file = dentry_open(meta_dentry, meta_mnt, 0x1, current_cred());
|
||||
if(!meta_file || IS_ERR(meta_file)) {
|
||||
printk(KERN_CRIT "mini_fo: meta_write_r_entry: \
|
||||
ERROR opening meta file.\n");
|
||||
@@ -686,7 +686,7 @@ int meta_sync_d_list(dentry_t *dentry, i
|
||||
mntget(meta_mnt);
|
||||
|
||||
/* open META-file for writing */
|
||||
- meta_file = dentry_open(meta_dentry, meta_mnt, 0x1);
|
||||
+ meta_file = dentry_open(meta_dentry, meta_mnt, 0x1, current_cred());
|
||||
if(!meta_file || IS_ERR(meta_file)) {
|
||||
printk(KERN_CRIT "mini_fo: meta_sync_d_list: \
|
||||
ERROR opening meta file.\n");
|
||||
@@ -828,7 +828,7 @@ int meta_sync_r_list(dentry_t *dentry, i
|
||||
mntget(meta_mnt);
|
||||
|
||||
/* open META-file for writing */
|
||||
- meta_file = dentry_open(meta_dentry, meta_mnt, 0x1);
|
||||
+ meta_file = dentry_open(meta_dentry, meta_mnt, 0x1, current_cred());
|
||||
if(!meta_file || IS_ERR(meta_file)) {
|
||||
printk(KERN_CRIT "mini_fo: meta_sync_r_list: \
|
||||
ERROR opening meta file.\n");
|
@ -1,157 +0,0 @@
|
||||
--- a/fs/mini_fo/aux.c
|
||||
+++ b/fs/mini_fo/aux.c
|
||||
@@ -86,8 +86,10 @@ int get_neg_sto_dentry(dentry_t *dentry)
|
||||
len = dentry->d_name.len;
|
||||
name = dentry->d_name.name;
|
||||
|
||||
+ mutex_lock(&dtohd2(dentry->d_parent)->d_inode->i_mutex);
|
||||
dtohd2(dentry) =
|
||||
lookup_one_len(name, dtohd2(dentry->d_parent), len);
|
||||
+ mutex_unlock(&dtohd2(dentry->d_parent)->d_inode->i_mutex);
|
||||
|
||||
out:
|
||||
return err;
|
||||
@@ -426,7 +428,9 @@ int build_sto_structure(dentry_t *dir, d
|
||||
const unsigned char *name;
|
||||
len = dtohd(dentry)->d_name.len;
|
||||
name = dtohd(dentry)->d_name.name;
|
||||
+ mutex_lock(&dtohd2(dir)->d_inode->i_mutex);
|
||||
hidden_sto_dentry = lookup_one_len(name, dtohd2(dir), len);
|
||||
+ mutex_unlock(&dtohd2(dir)->d_inode->i_mutex);
|
||||
dtohd2(dentry) = hidden_sto_dentry;
|
||||
}
|
||||
|
||||
--- a/fs/mini_fo/inode.c
|
||||
+++ b/fs/mini_fo/inode.c
|
||||
@@ -113,17 +113,23 @@ mini_fo_lookup(inode_t *dir, dentry_t *d
|
||||
hidden_dir_dentry = hidden_dentry->d_parent;
|
||||
kfree(bpath);
|
||||
}
|
||||
- else if(hidden_dir_dentry && hidden_dir_dentry->d_inode)
|
||||
+ else if(hidden_dir_dentry && hidden_dir_dentry->d_inode) {
|
||||
+ mutex_lock(&hidden_dir_dentry->d_inode->i_mutex);
|
||||
hidden_dentry =
|
||||
lookup_one_len(name, hidden_dir_dentry, namelen);
|
||||
- else
|
||||
+ mutex_unlock(&hidden_dir_dentry->d_inode->i_mutex);
|
||||
+ } else {
|
||||
hidden_dentry = NULL;
|
||||
+ }
|
||||
|
||||
- if(hidden_sto_dir_dentry && hidden_sto_dir_dentry->d_inode)
|
||||
+ if(hidden_sto_dir_dentry && hidden_sto_dir_dentry->d_inode) {
|
||||
+ mutex_lock(&hidden_sto_dir_dentry->d_inode->i_mutex);
|
||||
hidden_sto_dentry =
|
||||
lookup_one_len(name, hidden_sto_dir_dentry, namelen);
|
||||
- else
|
||||
+ mutex_unlock(&hidden_sto_dir_dentry->d_inode->i_mutex);
|
||||
+ } else {
|
||||
hidden_sto_dentry = NULL;
|
||||
+ }
|
||||
|
||||
/* catch error in lookup */
|
||||
if (IS_ERR(hidden_dentry) || IS_ERR(hidden_sto_dentry)) {
|
||||
@@ -553,9 +559,11 @@ mini_fo_rmdir(inode_t *dir, dentry_t *de
|
||||
#endif
|
||||
|
||||
/* Delete an old WOL file contained in the storage dir */
|
||||
+ mutex_lock(&hidden_sto_dentry->d_inode->i_mutex);
|
||||
meta_dentry = lookup_one_len(META_FILENAME,
|
||||
hidden_sto_dentry,
|
||||
strlen(META_FILENAME));
|
||||
+ mutex_unlock(&hidden_sto_dentry->d_inode->i_mutex);
|
||||
if(meta_dentry->d_inode) {
|
||||
err = vfs_unlink(hidden_sto_dentry->d_inode, meta_dentry);
|
||||
dput(meta_dentry);
|
||||
@@ -643,9 +651,11 @@ mini_fo_rmdir(inode_t *dir, dentry_t *de
|
||||
#endif
|
||||
|
||||
/* Delete an old WOL file contained in the storage dir */
|
||||
+ mutex_lock(&hidden_sto_dentry->d_inode->i_mutex);
|
||||
meta_dentry = lookup_one_len(META_FILENAME,
|
||||
hidden_sto_dentry,
|
||||
strlen(META_FILENAME));
|
||||
+ mutex_unlock(&hidden_sto_dentry->d_inode->i_mutex);
|
||||
if(meta_dentry->d_inode) {
|
||||
/* is this necessary? dget(meta_dentry); */
|
||||
err = vfs_unlink(hidden_sto_dentry->d_inode,
|
||||
@@ -688,9 +698,11 @@ mini_fo_rmdir(inode_t *dir, dentry_t *de
|
||||
#endif
|
||||
|
||||
/* Delete an old WOL file contained in the storage dir */
|
||||
+ mutex_lock(&hidden_sto_dentry->d_inode->i_mutex);
|
||||
meta_dentry = lookup_one_len(META_FILENAME,
|
||||
hidden_sto_dentry,
|
||||
strlen(META_FILENAME));
|
||||
+ mutex_unlock(&hidden_sto_dentry->d_inode->i_mutex);
|
||||
if(meta_dentry->d_inode) {
|
||||
/* is this necessary? dget(meta_dentry); */
|
||||
err = vfs_unlink(hidden_sto_dentry->d_inode,
|
||||
--- a/fs/mini_fo/meta.c
|
||||
+++ b/fs/mini_fo/meta.c
|
||||
@@ -43,9 +43,11 @@ int meta_build_lists(dentry_t *dentry)
|
||||
|
||||
/* might there be a META-file? */
|
||||
if(dtohd2(dentry) && dtohd2(dentry)->d_inode) {
|
||||
+ mutex_lock(&dtohd2(dentry)->d_inode->i_mutex);
|
||||
meta_dentry = lookup_one_len(META_FILENAME,
|
||||
dtohd2(dentry),
|
||||
strlen(META_FILENAME));
|
||||
+ mutex_unlock(&dtohd2(dentry)->d_inode->i_mutex);
|
||||
if(!meta_dentry->d_inode) {
|
||||
dput(meta_dentry);
|
||||
goto out_ok;
|
||||
@@ -426,8 +428,11 @@ int meta_write_d_entry(dentry_t *dentry,
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
+
|
||||
+ mutex_lock(&dtohd2(dentry)->d_inode->i_mutex);
|
||||
meta_dentry = lookup_one_len(META_FILENAME,
|
||||
dtohd2(dentry), strlen (META_FILENAME));
|
||||
+ mutex_unlock(&dtohd2(dentry)->d_inode->i_mutex);
|
||||
|
||||
/* We need to create a META-file */
|
||||
if(!meta_dentry->d_inode) {
|
||||
@@ -527,9 +532,13 @@ int meta_write_r_entry(dentry_t *dentry,
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
+
|
||||
+ mutex_lock(&dtohd2(dentry)->d_inode->i_mutex);
|
||||
meta_dentry = lookup_one_len(META_FILENAME,
|
||||
dtohd2(dentry),
|
||||
strlen (META_FILENAME));
|
||||
+ mutex_unlock(&dtohd2(dentry)->d_inode->i_mutex);
|
||||
+
|
||||
if(!meta_dentry->d_inode) {
|
||||
/* We need to create a META-file */
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
|
||||
@@ -641,9 +650,13 @@ int meta_sync_d_list(dentry_t *dentry, i
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
+
|
||||
+ mutex_lock(&dtohd2(dentry)->d_inode->i_mutex);
|
||||
meta_dentry = lookup_one_len(META_FILENAME,
|
||||
dtohd2(dentry),
|
||||
strlen(META_FILENAME));
|
||||
+ mutex_unlock(&dtohd2(dentry)->d_inode->i_mutex);
|
||||
+
|
||||
if(!meta_dentry->d_inode) {
|
||||
/* We need to create a META-file */
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
|
||||
@@ -784,9 +797,13 @@ int meta_sync_r_list(dentry_t *dentry, i
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
+
|
||||
+ mutex_lock(&dtohd2(dentry)->d_inode->i_mutex);
|
||||
meta_dentry = lookup_one_len(META_FILENAME,
|
||||
dtohd2(dentry),
|
||||
strlen(META_FILENAME));
|
||||
+ mutex_unlock(&dtohd2(dentry)->d_inode->i_mutex);
|
||||
+
|
||||
if(!meta_dentry->d_inode) {
|
||||
/* We need to create a META-file */
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
|
@ -1,25 +0,0 @@
|
||||
--- a/fs/mini_fo/state.c
|
||||
+++ b/fs/mini_fo/state.c
|
||||
@@ -537,17 +537,17 @@ int nondir_mod_to_del(dentry_t *dentry)
|
||||
dtohd(dentry) = NULL;
|
||||
dtost(dentry) = DELETED;
|
||||
|
||||
- /* add deleted file to META-file */
|
||||
- meta_add_d_entry(dentry->d_parent,
|
||||
- dentry->d_name.name,
|
||||
- dentry->d_name.len);
|
||||
-
|
||||
/* was: unlock_dir(hidden_sto_dir_dentry); */
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,16)
|
||||
mutex_unlock(&hidden_sto_dir_dentry->d_inode->i_mutex);
|
||||
#else
|
||||
up(&hidden_sto_dir_dentry->d_inode->i_sem);
|
||||
#endif
|
||||
+ /* add deleted file to META-file */
|
||||
+ meta_add_d_entry(dentry->d_parent,
|
||||
+ dentry->d_name.name,
|
||||
+ dentry->d_name.len);
|
||||
+
|
||||
dput(hidden_sto_dir_dentry);
|
||||
|
||||
out:
|
@ -1,42 +0,0 @@
|
||||
--- a/lib/kobject_uevent.c
|
||||
+++ b/lib/kobject_uevent.c
|
||||
@@ -29,7 +29,8 @@ u64 uevent_seqnum;
|
||||
char uevent_helper[UEVENT_HELPER_PATH_LEN] = CONFIG_UEVENT_HELPER_PATH;
|
||||
static DEFINE_SPINLOCK(sequence_lock);
|
||||
#if defined(CONFIG_NET)
|
||||
-static struct sock *uevent_sock;
|
||||
+struct sock *uevent_sock = NULL;
|
||||
+EXPORT_SYMBOL_GPL(uevent_sock);
|
||||
#endif
|
||||
|
||||
/* the strings here must match the enum in include/linux/kobject.h */
|
||||
@@ -42,6 +43,18 @@ static const char *kobject_actions[] = {
|
||||
[KOBJ_OFFLINE] = "offline",
|
||||
};
|
||||
|
||||
+u64 uevent_next_seqnum(void)
|
||||
+{
|
||||
+ u64 seq;
|
||||
+
|
||||
+ spin_lock(&sequence_lock);
|
||||
+ seq = ++uevent_seqnum;
|
||||
+ spin_unlock(&sequence_lock);
|
||||
+
|
||||
+ return seq;
|
||||
+}
|
||||
+EXPORT_SYMBOL_GPL(uevent_next_seqnum);
|
||||
+
|
||||
/**
|
||||
* kobject_action_type - translate action string to numeric type
|
||||
*
|
||||
@@ -201,9 +214,7 @@ int kobject_uevent_env(struct kobject *k
|
||||
kobj->state_remove_uevent_sent = 1;
|
||||
|
||||
/* we will send an event, so request a new sequence number */
|
||||
- spin_lock(&sequence_lock);
|
||||
- seq = ++uevent_seqnum;
|
||||
- spin_unlock(&sequence_lock);
|
||||
+ seq = uevent_next_seqnum();
|
||||
retval = add_uevent_var(env, "SEQNUM=%llu", (unsigned long long)seq);
|
||||
if (retval)
|
||||
goto exit;
|
@ -1,11 +0,0 @@
|
||||
--- a/sound/core/Kconfig
|
||||
+++ b/sound/core/Kconfig
|
||||
@@ -7,7 +7,7 @@ config SND_PCM
|
||||
select SND_TIMER
|
||||
|
||||
config SND_HWDEP
|
||||
- tristate
|
||||
+ tristate "Sound hardware support"
|
||||
|
||||
config SND_RAWMIDI
|
||||
tristate
|
@ -1,146 +0,0 @@
|
||||
--- a/drivers/mtd/mtdpart.c
|
||||
+++ b/drivers/mtd/mtdpart.c
|
||||
@@ -21,6 +21,8 @@
|
||||
#include <linux/root_dev.h>
|
||||
#include <linux/magic.h>
|
||||
|
||||
+#define MTD_ERASE_PARTIAL 0x8000 /* partition only covers parts of an erase block */
|
||||
+
|
||||
/* Our partition linked list */
|
||||
static LIST_HEAD(mtd_partitions);
|
||||
|
||||
@@ -226,13 +228,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;
|
||||
}
|
||||
|
||||
@@ -240,7 +289,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;
|
||||
@@ -472,18 +539,24 @@ static struct mtd_part *add_one_partitio
|
||||
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
|
||||
@@ -46,6 +46,10 @@ struct erase_info {
|
||||
u_long priv;
|
||||
u_char state;
|
||||
struct erase_info *next;
|
||||
+
|
||||
+ u8 *erase_buf;
|
||||
+ u32 erase_buf_ofs;
|
||||
+ bool partial_start;
|
||||
};
|
||||
|
||||
struct mtd_erase_region_info {
|
@ -1,132 +0,0 @@
|
||||
This patch allows the user to specify desired packet types (outgoing,
|
||||
broadcast, unicast, etc.) on packet sockets via setsockopt.
|
||||
This can reduce the load in situations where only a limited number
|
||||
of packet types are necessary
|
||||
|
||||
Signed-off-by: Felix Fietkau <nbd@openwrt.org>
|
||||
|
||||
--- a/include/linux/if_packet.h
|
||||
+++ b/include/linux/if_packet.h
|
||||
@@ -31,6 +31,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 */
|
||||
|
||||
@@ -48,6 +50,7 @@ struct sockaddr_ll
|
||||
#define PACKET_RESERVE 12
|
||||
#define PACKET_TX_RING 13
|
||||
#define PACKET_LOSS 14
|
||||
+#define PACKET_RECV_TYPE 15
|
||||
|
||||
struct tpacket_stats
|
||||
{
|
||||
--- a/net/packet/af_packet.c
|
||||
+++ b/net/packet/af_packet.c
|
||||
@@ -206,6 +206,7 @@ struct packet_sock {
|
||||
unsigned int tp_reserve;
|
||||
unsigned int tp_loss:1;
|
||||
#endif
|
||||
+ unsigned int pkt_type;
|
||||
};
|
||||
|
||||
struct packet_skb_cb {
|
||||
@@ -343,6 +344,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
|
||||
@@ -350,6 +352,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
|
||||
@@ -362,7 +365,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 (dev_net(dev) != sock_net(sk))
|
||||
@@ -546,12 +549,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 (dev_net(dev) != sock_net(sk))
|
||||
goto drop;
|
||||
|
||||
@@ -667,12 +670,12 @@ static int tpacket_rcv(struct sk_buff *s
|
||||
struct timeval tv;
|
||||
struct timespec ts;
|
||||
|
||||
- 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 (dev_net(dev) != sock_net(sk))
|
||||
goto drop;
|
||||
|
||||
@@ -1387,6 +1390,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;
|
||||
@@ -1733,6 +1737,16 @@ packet_setsockopt(struct socket *sock, i
|
||||
ret = packet_mc_drop(sk, &mreq);
|
||||
return ret;
|
||||
}
|
||||
+ 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;
|
||||
+ }
|
||||
|
||||
#ifdef CONFIG_PACKET_MMAP
|
||||
case PACKET_RX_RING:
|
||||
@@ -1878,6 +1892,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;
|
||||
#ifdef CONFIG_PACKET_MMAP
|
||||
case PACKET_VERSION:
|
||||
if (len > sizeof(int))
|
@ -1,20 +0,0 @@
|
||||
--- a/drivers/net/pppoe.c
|
||||
+++ b/drivers/net/pppoe.c
|
||||
@@ -863,7 +863,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;
|
||||
@@ -871,7 +871,7 @@ static int pppoe_sendmsg(struct kiocb *i
|
||||
}
|
||||
|
||||
/* Reserve space for headers. */
|
||||
- skb_reserve(skb, dev->hard_header_len);
|
||||
+ skb_reserve(skb, dev->hard_header_len + NET_SKB_PAD);
|
||||
skb_reset_network_header(skb);
|
||||
|
||||
skb->dev = dev;
|
@ -1,144 +0,0 @@
|
||||
--- a/net/sched/sch_generic.c
|
||||
+++ b/net/sched/sch_generic.c
|
||||
@@ -391,16 +391,50 @@ static const u8 prio2band[TC_PRIO_MAX+1]
|
||||
|
||||
#define PFIFO_FAST_BANDS 3
|
||||
|
||||
+struct pfifo_fast_sched_data {
|
||||
+ struct tcf_proto *filter_list;
|
||||
+ struct sk_buff_head list[PFIFO_FAST_BANDS];
|
||||
+};
|
||||
+
|
||||
static inline struct sk_buff_head *prio2list(struct sk_buff *skb,
|
||||
struct Qdisc *qdisc)
|
||||
{
|
||||
- struct sk_buff_head *list = qdisc_priv(qdisc);
|
||||
+ struct pfifo_fast_sched_data *q = qdisc_priv(qdisc);
|
||||
+ struct sk_buff_head *list = q->list;
|
||||
return list + prio2band[skb->priority & TC_PRIO_MAX];
|
||||
}
|
||||
|
||||
+static int pfifo_fast_filter(struct sk_buff *skb, struct Qdisc* qdisc)
|
||||
+{
|
||||
+#ifdef CONFIG_NET_CLS_ACT
|
||||
+ struct pfifo_fast_sched_data *q = qdisc_priv(qdisc);
|
||||
+ int result = 0, ret = NET_XMIT_SUCCESS | __NET_XMIT_STOLEN;
|
||||
+ struct tcf_result res;
|
||||
+
|
||||
+ if (q->filter_list != NULL)
|
||||
+ result = tc_classify(skb, q->filter_list, &res);
|
||||
+ if (result >= 0) {
|
||||
+ switch (result) {
|
||||
+ case TC_ACT_STOLEN:
|
||||
+ case TC_ACT_QUEUED:
|
||||
+ ret = NET_XMIT_SUCCESS | __NET_XMIT_STOLEN;
|
||||
+ case TC_ACT_SHOT:
|
||||
+ kfree_skb(skb);
|
||||
+ return ret;
|
||||
+ }
|
||||
+ }
|
||||
+#endif
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
static int pfifo_fast_enqueue(struct sk_buff *skb, struct Qdisc* qdisc)
|
||||
{
|
||||
struct sk_buff_head *list = prio2list(skb, qdisc);
|
||||
+ int ret;
|
||||
+
|
||||
+ ret = pfifo_fast_filter(skb, qdisc);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
|
||||
if (skb_queue_len(list) < qdisc_dev(qdisc)->tx_queue_len) {
|
||||
qdisc->q.qlen++;
|
||||
@@ -412,8 +446,9 @@ static int pfifo_fast_enqueue(struct sk_
|
||||
|
||||
static struct sk_buff *pfifo_fast_dequeue(struct Qdisc* qdisc)
|
||||
{
|
||||
+ struct pfifo_fast_sched_data *q = qdisc_priv(qdisc);
|
||||
+ struct sk_buff_head *list = q->list;
|
||||
int prio;
|
||||
- struct sk_buff_head *list = qdisc_priv(qdisc);
|
||||
|
||||
for (prio = 0; prio < PFIFO_FAST_BANDS; prio++) {
|
||||
if (!skb_queue_empty(list + prio)) {
|
||||
@@ -440,8 +475,9 @@ static struct sk_buff *pfifo_fast_peek(s
|
||||
|
||||
static void pfifo_fast_reset(struct Qdisc* qdisc)
|
||||
{
|
||||
+ struct pfifo_fast_sched_data *q = qdisc_priv(qdisc);
|
||||
+ struct sk_buff_head *list = q->list;
|
||||
int prio;
|
||||
- struct sk_buff_head *list = qdisc_priv(qdisc);
|
||||
|
||||
for (prio = 0; prio < PFIFO_FAST_BANDS; prio++)
|
||||
__qdisc_reset_queue(qdisc, list + prio);
|
||||
@@ -464,8 +500,9 @@ nla_put_failure:
|
||||
|
||||
static int pfifo_fast_init(struct Qdisc *qdisc, struct nlattr *opt)
|
||||
{
|
||||
+ struct pfifo_fast_sched_data *q = qdisc_priv(qdisc);
|
||||
+ struct sk_buff_head *list = q->list;
|
||||
int prio;
|
||||
- struct sk_buff_head *list = qdisc_priv(qdisc);
|
||||
|
||||
for (prio = 0; prio < PFIFO_FAST_BANDS; prio++)
|
||||
skb_queue_head_init(list + prio);
|
||||
@@ -473,9 +510,36 @@ static int pfifo_fast_init(struct Qdisc
|
||||
return 0;
|
||||
}
|
||||
|
||||
+static int pfifo_fast_change_class(struct Qdisc *qdisc, u32 classid, u32 parentid,
|
||||
+ struct nlattr **tca, unsigned long *arg)
|
||||
+{
|
||||
+ return -EOPNOTSUPP;
|
||||
+}
|
||||
+
|
||||
+static unsigned long pfifo_fast_get(struct Qdisc *qdisc, u32 classid)
|
||||
+{
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static struct tcf_proto **pfifo_fast_find_tcf(struct Qdisc *qdisc, unsigned long cl)
|
||||
+{
|
||||
+ struct pfifo_fast_sched_data *q = qdisc_priv(qdisc);
|
||||
+
|
||||
+ if (cl)
|
||||
+ return NULL;
|
||||
+ return &q->filter_list;
|
||||
+}
|
||||
+
|
||||
+static const struct Qdisc_class_ops pfifo_fast_class_ops = {
|
||||
+ .get = pfifo_fast_get,
|
||||
+ .change = pfifo_fast_change_class,
|
||||
+ .tcf_chain = pfifo_fast_find_tcf,
|
||||
+};
|
||||
+
|
||||
static struct Qdisc_ops pfifo_fast_ops __read_mostly = {
|
||||
.id = "pfifo_fast",
|
||||
- .priv_size = PFIFO_FAST_BANDS * sizeof(struct sk_buff_head),
|
||||
+ .cl_ops = &pfifo_fast_class_ops,
|
||||
+ .priv_size = sizeof(struct pfifo_fast_sched_data),
|
||||
.enqueue = pfifo_fast_enqueue,
|
||||
.dequeue = pfifo_fast_dequeue,
|
||||
.peek = pfifo_fast_peek,
|
||||
@@ -757,3 +821,18 @@ void dev_shutdown(struct net_device *dev
|
||||
shutdown_scheduler_queue(dev, &dev->rx_queue, &noop_qdisc);
|
||||
WARN_ON(timer_pending(&dev->watchdog_timer));
|
||||
}
|
||||
+
|
||||
+#ifdef CONFIG_NET_SCHED
|
||||
+static int __init sch_generic_init(void)
|
||||
+{
|
||||
+ return register_qdisc(&pfifo_fast_ops);
|
||||
+}
|
||||
+
|
||||
+static void __exit sch_generic_exit(void)
|
||||
+{
|
||||
+ unregister_qdisc(&pfifo_fast_ops);
|
||||
+}
|
||||
+
|
||||
+module_init(sch_generic_init)
|
||||
+module_exit(sch_generic_exit)
|
||||
+#endif
|
File diff suppressed because it is too large
Load Diff
@ -1,30 +0,0 @@
|
||||
--- a/net/ipv6/ndisc.c
|
||||
+++ b/net/ipv6/ndisc.c
|
||||
@@ -1106,6 +1106,18 @@ errout:
|
||||
rtnl_set_sk_err(net, RTNLGRP_ND_USEROPT, err);
|
||||
}
|
||||
|
||||
+static inline int accept_ra(struct inet6_dev *in6_dev)
|
||||
+{
|
||||
+ /*
|
||||
+ * If forwarding is enabled, RA are not accepted unless the special
|
||||
+ * hybrid mode (accept_ra=2) is enabled.
|
||||
+ */
|
||||
+ if (in6_dev->cnf.forwarding && in6_dev->cnf.accept_ra < 2)
|
||||
+ return 0;
|
||||
+
|
||||
+ return in6_dev->cnf.accept_ra;
|
||||
+}
|
||||
+
|
||||
static void ndisc_router_discovery(struct sk_buff *skb)
|
||||
{
|
||||
struct ra_msg *ra_msg = (struct ra_msg *)skb_transport_header(skb);
|
||||
@@ -1151,7 +1163,7 @@ static void ndisc_router_discovery(struc
|
||||
skb->dev->name);
|
||||
return;
|
||||
}
|
||||
- if (in6_dev->cnf.forwarding || !in6_dev->cnf.accept_ra) {
|
||||
+ if (!accept_ra(in6_dev)) {
|
||||
in6_dev_put(in6_dev);
|
||||
return;
|
||||
}
|
@ -1,12 +0,0 @@
|
||||
--- a/net/ipv6/addrconf.c
|
||||
+++ b/net/ipv6/addrconf.c
|
||||
@@ -2864,7 +2864,8 @@ static void addrconf_dad_completed(struc
|
||||
start sending router solicitations.
|
||||
*/
|
||||
|
||||
- if (ifp->idev->cnf.forwarding == 0 &&
|
||||
+ if ((ifp->idev->cnf.forwarding == 0 ||
|
||||
+ ifp->idev->cnf.forwarding == 2) &&
|
||||
ifp->idev->cnf.rtr_solicits > 0 &&
|
||||
(dev->flags&IFF_LOOPBACK) == 0 &&
|
||||
(ipv6_addr_type(&ifp->addr) & IPV6_ADDR_LINKLOCAL)) {
|
@ -1,18 +0,0 @@
|
||||
--- a/drivers/leds/Kconfig
|
||||
+++ b/drivers/leds/Kconfig
|
||||
@@ -297,4 +297,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
|
||||
@@ -39,3 +39,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
|
@ -1,21 +0,0 @@
|
||||
--- a/drivers/leds/Kconfig
|
||||
+++ b/drivers/leds/Kconfig
|
||||
@@ -301,4 +301,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
|
||||
@@ -40,3 +40,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
|
@ -1,31 +0,0 @@
|
||||
--- a/drivers/input/misc/Kconfig
|
||||
+++ b/drivers/input/misc/Kconfig
|
||||
@@ -269,4 +269,21 @@ config INPUT_DM355EVM
|
||||
|
||||
To compile this driver as a module, choose M here: the
|
||||
module will be called dm355evm_keys.
|
||||
+
|
||||
+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
|
||||
@@ -26,3 +26,4 @@ obj-$(CONFIG_INPUT_TWL4030_PWRBUTTON) +=
|
||||
obj-$(CONFIG_INPUT_UINPUT) += uinput.o
|
||||
obj-$(CONFIG_INPUT_WISTRON_BTNS) += wistron_btns.o
|
||||
obj-$(CONFIG_INPUT_YEALINK) += yealink.o
|
||||
+obj-$(CONFIG_INPUT_GPIO_BUTTONS) += gpio_buttons.o
|
@ -1,27 +0,0 @@
|
||||
--- a/drivers/char/Kconfig
|
||||
+++ b/drivers/char/Kconfig
|
||||
@@ -1029,6 +1029,14 @@ config CS5535_GPIO
|
||||
|
||||
If compiled as a module, it will be called cs5535_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
|
||||
@@ -95,6 +95,7 @@ obj-$(CONFIG_SCx200_GPIO) += scx200_gpio
|
||||
obj-$(CONFIG_PC8736x_GPIO) += pc8736x_gpio.o
|
||||
obj-$(CONFIG_NSC_GPIO) += nsc_gpio.o
|
||||
obj-$(CONFIG_CS5535_GPIO) += cs5535_gpio.o
|
||||
+obj-$(CONFIG_GPIO_DEVICE) += gpio_dev.o
|
||||
obj-$(CONFIG_GPIO_TB0219) += tb0219.o
|
||||
obj-$(CONFIG_TELCLOCK) += tlclk.o
|
||||
|
@ -1,17 +0,0 @@
|
||||
--- a/include/scsi/scsi.h
|
||||
+++ b/include/scsi/scsi.h
|
||||
@@ -142,10 +142,10 @@ struct scsi_cmnd;
|
||||
|
||||
/* defined in T10 SCSI Primary Commands-2 (SPC2) */
|
||||
struct scsi_varlen_cdb_hdr {
|
||||
- u8 opcode; /* opcode always == VARIABLE_LENGTH_CMD */
|
||||
- u8 control;
|
||||
- u8 misc[5];
|
||||
- u8 additional_cdb_length; /* total cdb length - 8 */
|
||||
+ __u8 opcode; /* opcode always == VARIABLE_LENGTH_CMD */
|
||||
+ __u8 control;
|
||||
+ __u8 misc[5];
|
||||
+ __u8 additional_cdb_length; /* total cdb length - 8 */
|
||||
__be16 service_action;
|
||||
/* service specific data follows */
|
||||
};
|
@ -1,17 +0,0 @@
|
||||
--- a/fs/Kconfig
|
||||
+++ b/fs/Kconfig
|
||||
@@ -188,6 +188,7 @@ source "fs/sysv/Kconfig"
|
||||
source "fs/ufs/Kconfig"
|
||||
source "fs/exofs/Kconfig"
|
||||
source "fs/nilfs2/Kconfig"
|
||||
+source "fs/yaffs2/Kconfig"
|
||||
|
||||
endif # MISC_FILESYSTEMS
|
||||
|
||||
--- a/fs/Makefile
|
||||
+++ b/fs/Makefile
|
||||
@@ -125,3 +125,4 @@ obj-$(CONFIG_OCFS2_FS) += ocfs2/
|
||||
obj-$(CONFIG_BTRFS_FS) += btrfs/
|
||||
obj-$(CONFIG_GFS2_FS) += gfs2/
|
||||
obj-$(CONFIG_EXOFS_FS) += exofs/
|
||||
+obj-$(CONFIG_YAFFS_FS) += yaffs2/
|
File diff suppressed because it is too large
Load Diff
@ -1,83 +0,0 @@
|
||||
--- a/drivers/net/phy/phy.c
|
||||
+++ b/drivers/net/phy/phy.c
|
||||
@@ -299,6 +299,50 @@ int phy_ethtool_gset(struct phy_device *
|
||||
}
|
||||
EXPORT_SYMBOL(phy_ethtool_gset);
|
||||
|
||||
+int phy_ethtool_ioctl(struct phy_device *phydev, void *useraddr)
|
||||
+{
|
||||
+ u32 cmd;
|
||||
+ int tmp;
|
||||
+ struct ethtool_cmd ecmd = { ETHTOOL_GSET };
|
||||
+ struct ethtool_value edata = { ETHTOOL_GLINK };
|
||||
+
|
||||
+ if (get_user(cmd, (u32 *) useraddr))
|
||||
+ return -EFAULT;
|
||||
+
|
||||
+ switch (cmd) {
|
||||
+ case ETHTOOL_GSET:
|
||||
+ phy_ethtool_gset(phydev, &ecmd);
|
||||
+ if (copy_to_user(useraddr, &ecmd, sizeof(ecmd)))
|
||||
+ return -EFAULT;
|
||||
+ return 0;
|
||||
+
|
||||
+ case ETHTOOL_SSET:
|
||||
+ if (copy_from_user(&ecmd, useraddr, sizeof(ecmd)))
|
||||
+ return -EFAULT;
|
||||
+ return phy_ethtool_sset(phydev, &ecmd);
|
||||
+
|
||||
+ case ETHTOOL_NWAY_RST:
|
||||
+ /* if autoneg is off, it's an error */
|
||||
+ tmp = phy_read(phydev, MII_BMCR);
|
||||
+ if (tmp & BMCR_ANENABLE) {
|
||||
+ tmp |= (BMCR_ANRESTART);
|
||||
+ phy_write(phydev, MII_BMCR, tmp);
|
||||
+ return 0;
|
||||
+ }
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ case ETHTOOL_GLINK:
|
||||
+ edata.data = (phy_read(phydev,
|
||||
+ MII_BMSR) & BMSR_LSTATUS) ? 1 : 0;
|
||||
+ if (copy_to_user(useraddr, &edata, sizeof(edata)))
|
||||
+ return -EFAULT;
|
||||
+ return 0;
|
||||
+ }
|
||||
+
|
||||
+ return -EOPNOTSUPP;
|
||||
+}
|
||||
+EXPORT_SYMBOL(phy_ethtool_ioctl);
|
||||
+
|
||||
/**
|
||||
* phy_mii_ioctl - generic PHY MII ioctl interface
|
||||
* @phydev: the phy_device struct
|
||||
@@ -355,8 +399,8 @@ int phy_mii_ioctl(struct phy_device *phy
|
||||
}
|
||||
|
||||
phy_write(phydev, mii_data->reg_num, val);
|
||||
-
|
||||
- if (mii_data->reg_num == MII_BMCR
|
||||
+
|
||||
+ if (mii_data->reg_num == MII_BMCR
|
||||
&& val & BMCR_RESET
|
||||
&& phydev->drv->config_init) {
|
||||
phy_scan_fixups(phydev);
|
||||
@@ -471,7 +515,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
|
||||
@@ -489,6 +489,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 mii_ioctl_data *mii_data, int cmd);
|
||||
int phy_start_interrupts(struct phy_device *phydev);
|
@ -1,45 +0,0 @@
|
||||
--- a/include/linux/phy.h
|
||||
+++ b/include/linux/phy.h
|
||||
@@ -379,9 +379,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
|
||||
@@ -681,6 +681,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
|
||||
@@ -107,6 +107,9 @@ static inline int phy_aneg_done(struct p
|
||||
{
|
||||
int retval;
|
||||
|
||||
+ if (phydev->drv->aneg_done)
|
||||
+ return phydev->drv->aneg_done(phydev);
|
||||
+
|
||||
retval = phy_read(phydev, MII_BMSR);
|
||||
|
||||
return (retval < 0) ? retval : (retval & BMSR_ANEGCOMPLETE);
|
@ -1,26 +0,0 @@
|
||||
--- a/drivers/net/phy/Kconfig
|
||||
+++ b/drivers/net/phy/Kconfig
|
||||
@@ -82,6 +82,13 @@ config LSI_ET1011C_PHY
|
||||
---help---
|
||||
Supports the LSI ET1011C PHY.
|
||||
|
||||
+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
|
||||
@@ -12,6 +12,7 @@ obj-$(CONFIG_SMSC_PHY) += smsc.o
|
||||
obj-$(CONFIG_VITESSE_PHY) += vitesse.o
|
||||
obj-$(CONFIG_BROADCOM_PHY) += broadcom.o
|
||||
obj-$(CONFIG_ICPLUS_PHY) += icplus.o
|
||||
+obj-$(CONFIG_ADM6996_PHY) += adm6996.o
|
||||
obj-$(CONFIG_REALTEK_PHY) += realtek.o
|
||||
obj-$(CONFIG_LSI_ET1011C_PHY) += et1011c.o
|
||||
obj-$(CONFIG_FIXED_PHY) += fixed.o
|
@ -1,63 +0,0 @@
|
||||
--- a/drivers/net/phy/phy_device.c
|
||||
+++ b/drivers/net/phy/phy_device.c
|
||||
@@ -146,6 +146,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);
|
||||
+}
|
||||
+
|
||||
struct phy_device* phy_device_create(struct mii_bus *bus, int addr, int phy_id)
|
||||
{
|
||||
struct phy_device *dev;
|
||||
@@ -175,6 +187,8 @@ struct phy_device* phy_device_create(str
|
||||
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);
|
||||
|
||||
--- a/include/linux/phy.h
|
||||
+++ b/include/linux/phy.h
|
||||
@@ -325,6 +325,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
|
||||
@@ -804,6 +804,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 line mostly used on receive path (including eth_type_trans())
|
@ -1,42 +0,0 @@
|
||||
commit 2e302ebfeac04beb5a5d6af1ac583c6a1fb76d1a
|
||||
Author: chas williams - CONTRACTOR <chas@cmf.nrl.navy.mil>
|
||||
Date: Fri Dec 4 11:06:32 2009 +0000
|
||||
|
||||
atm: [br2684] allow routed mode operation again
|
||||
|
||||
in routed mode, we don't have a hardware address so netdev_ops doesnt
|
||||
need to validate our hardware address via .ndo_validate_addr
|
||||
|
||||
Reported-by: Manuel Fuentes <mfuentes@agenciaefe.com>
|
||||
Signed-off-by: Chas Williams - CONTRACTOR <chas@cmf.nrl.navy.mil>
|
||||
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
|
||||
--- a/net/atm/br2684.c
|
||||
+++ b/net/atm/br2684.c
|
||||
@@ -536,6 +536,12 @@ static const struct net_device_ops br268
|
||||
.ndo_validate_addr = eth_validate_addr,
|
||||
};
|
||||
|
||||
+static const struct net_device_ops br2684_netdev_ops_routed = {
|
||||
+ .ndo_start_xmit = br2684_start_xmit,
|
||||
+ .ndo_set_mac_address = br2684_mac_addr,
|
||||
+ .ndo_change_mtu = eth_change_mtu
|
||||
+};
|
||||
+
|
||||
static void br2684_setup(struct net_device *netdev)
|
||||
{
|
||||
struct br2684_dev *brdev = BRPRIV(netdev);
|
||||
@@ -551,11 +557,10 @@ static void br2684_setup(struct net_devi
|
||||
static void br2684_setup_routed(struct net_device *netdev)
|
||||
{
|
||||
struct br2684_dev *brdev = BRPRIV(netdev);
|
||||
- brdev->net_dev = netdev;
|
||||
|
||||
+ brdev->net_dev = netdev;
|
||||
netdev->hard_header_len = 0;
|
||||
-
|
||||
- netdev->netdev_ops = &br2684_netdev_ops;
|
||||
+ netdev->netdev_ops = &br2684_netdev_ops_routed;
|
||||
netdev->addr_len = 0;
|
||||
netdev->mtu = 1500;
|
||||
netdev->type = ARPHRD_PPP;
|
@ -1,25 +0,0 @@
|
||||
--- 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
|
@ -1,22 +0,0 @@
|
||||
--- a/drivers/net/phy/Kconfig
|
||||
+++ b/drivers/net/phy/Kconfig
|
||||
@@ -95,6 +95,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
|
||||
@@ -14,6 +14,7 @@ obj-$(CONFIG_VITESSE_PHY) += vitesse.o
|
||||
obj-$(CONFIG_BROADCOM_PHY) += broadcom.o
|
||||
obj-$(CONFIG_ICPLUS_PHY) += icplus.o
|
||||
obj-$(CONFIG_ADM6996_PHY) += adm6996.o
|
||||
+obj-$(CONFIG_MVSWITCH_PHY) += mvswitch.o
|
||||
obj-$(CONFIG_REALTEK_PHY) += realtek.o
|
||||
obj-$(CONFIG_LSI_ET1011C_PHY) += et1011c.o
|
||||
obj-$(CONFIG_FIXED_PHY) += fixed.o
|
@ -1,23 +0,0 @@
|
||||
--- a/drivers/net/phy/Kconfig
|
||||
+++ b/drivers/net/phy/Kconfig
|
||||
@@ -98,6 +98,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
|
||||
@@ -15,6 +15,7 @@ obj-$(CONFIG_BROADCOM_PHY) += broadcom.o
|
||||
obj-$(CONFIG_ICPLUS_PHY) += icplus.o
|
||||
obj-$(CONFIG_ADM6996_PHY) += adm6996.o
|
||||
obj-$(CONFIG_MVSWITCH_PHY) += mvswitch.o
|
||||
+obj-$(CONFIG_IP17XX_PHY) += ip17xx.o
|
||||
obj-$(CONFIG_REALTEK_PHY) += realtek.o
|
||||
obj-$(CONFIG_LSI_ET1011C_PHY) += et1011c.o
|
||||
obj-$(CONFIG_FIXED_PHY) += fixed.o
|
@ -1,23 +0,0 @@
|
||||
--- a/drivers/net/phy/Kconfig
|
||||
+++ b/drivers/net/phy/Kconfig
|
||||
@@ -102,6 +102,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
|
||||
@@ -17,6 +17,7 @@ obj-$(CONFIG_ADM6996_PHY) += adm6996.o
|
||||
obj-$(CONFIG_MVSWITCH_PHY) += mvswitch.o
|
||||
obj-$(CONFIG_IP17XX_PHY) += ip17xx.o
|
||||
obj-$(CONFIG_REALTEK_PHY) += realtek.o
|
||||
+obj-$(CONFIG_AR8216_PHY) += ar8216.o
|
||||
obj-$(CONFIG_LSI_ET1011C_PHY) += et1011c.o
|
||||
obj-$(CONFIG_FIXED_PHY) += fixed.o
|
||||
obj-$(CONFIG_MDIO_BITBANG) += mdio-bitbang.o
|
@ -1,23 +0,0 @@
|
||||
--- a/drivers/net/phy/Kconfig
|
||||
+++ b/drivers/net/phy/Kconfig
|
||||
@@ -106,6 +106,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
|
||||
@@ -18,6 +18,7 @@ obj-$(CONFIG_MVSWITCH_PHY) += mvswitch.o
|
||||
obj-$(CONFIG_IP17XX_PHY) += ip17xx.o
|
||||
obj-$(CONFIG_REALTEK_PHY) += realtek.o
|
||||
obj-$(CONFIG_AR8216_PHY) += ar8216.o
|
||||
+obj-$(CONFIG_RTL8306_PHY) += rtl8306.o
|
||||
obj-$(CONFIG_LSI_ET1011C_PHY) += et1011c.o
|
||||
obj-$(CONFIG_FIXED_PHY) += fixed.o
|
||||
obj-$(CONFIG_MDIO_BITBANG) += mdio-bitbang.o
|
@ -1,44 +0,0 @@
|
||||
--- a/drivers/net/phy/Kconfig
|
||||
+++ b/drivers/net/phy/Kconfig
|
||||
@@ -137,4 +137,29 @@ config MDIO_GPIO
|
||||
To compile this driver as a module, choose M here: the module
|
||||
will be called mdio-gpio.
|
||||
|
||||
+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
|
||||
@@ -19,6 +19,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
|
@ -1,250 +0,0 @@
|
||||
--- a/drivers/rtc/Kconfig
|
||||
+++ b/drivers/rtc/Kconfig
|
||||
@@ -535,6 +535,15 @@ config RTC_DRV_PCF50633
|
||||
If you say yes here you get support for the RTC subsystem of the
|
||||
NXP PCF50633 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_OMAP
|
||||
--- a/drivers/rtc/Makefile
|
||||
+++ b/drivers/rtc/Makefile
|
||||
@@ -62,6 +62,7 @@ obj-$(CONFIG_RTC_DRV_R9701) += rtc-r9701
|
||||
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_RX8025) += rtc-rx8025.o
|
||||
obj-$(CONFIG_RTC_DRV_RX8581) += rtc-rx8581.o
|
||||
obj-$(CONFIG_RTC_DRV_S35390A) += rtc-s35390a.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);
|
@ -1,21 +0,0 @@
|
||||
--- a/include/linux/fb.h
|
||||
+++ b/include/linux/fb.h
|
||||
@@ -124,6 +124,7 @@ struct dentry;
|
||||
#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
|
||||
@@ -76,6 +76,8 @@ header-y += genetlink.h
|
||||
header-y += gen_stats.h
|
||||
header-y += gfs2_ondisk.h
|
||||
header-y += gigaset_dev.h
|
||||
+header-y += glamofb.h
|
||||
+header-y += glamo-engine.h
|
||||
header-y += hysdn_if.h
|
||||
header-y += i2o-dev.h
|
||||
header-y += i8k.h
|
@ -1,33 +0,0 @@
|
||||
commit 5ced436d549d911ce610ea47d85f71fae5bbfce4
|
||||
Author: Lars-Peter Clausen <lars@metafoo.de>
|
||||
Date: Fri Jul 31 18:26:48 2009 +0200
|
||||
|
||||
ASoC: jack: Fix race in snd_soc_jack_add_gpios
|
||||
|
||||
The irq can fire as soon as it has been requested, thus all fields accessed
|
||||
from within the irq handler must be initialized prior to requesting the irq.
|
||||
|
||||
Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
|
||||
|
||||
--- a/sound/soc/soc-jack.c
|
||||
+++ b/sound/soc/soc-jack.c
|
||||
@@ -220,6 +220,9 @@ int snd_soc_jack_add_gpios(struct snd_so
|
||||
if (ret)
|
||||
goto err;
|
||||
|
||||
+ INIT_WORK(&gpios[i].work, gpio_work);
|
||||
+ gpios[i].jack = jack;
|
||||
+
|
||||
ret = request_irq(gpio_to_irq(gpios[i].gpio),
|
||||
gpio_handler,
|
||||
IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
|
||||
@@ -227,9 +230,6 @@ int snd_soc_jack_add_gpios(struct snd_so
|
||||
&gpios[i]);
|
||||
if (ret)
|
||||
goto err;
|
||||
-
|
||||
- INIT_WORK(&gpios[i].work, gpio_work);
|
||||
- gpios[i].jack = jack;
|
||||
}
|
||||
|
||||
return 0;
|
@ -1,48 +0,0 @@
|
||||
--- a/drivers/usb/serial/option.c
|
||||
+++ b/drivers/usb/serial/option.c
|
||||
@@ -167,6 +167,11 @@ static int option_resume(struct usb_ser
|
||||
#define HUAWEI_PRODUCT_E143E 0x143E
|
||||
#define HUAWEI_PRODUCT_E143F 0x143F
|
||||
#define HUAWEI_PRODUCT_E14AC 0x14AC
|
||||
+#define HUAWEI_PRODUCT_K3770 0x14C9
|
||||
+#define HUAWEI_PRODUCT_K3771 0x14CA
|
||||
+#define HUAWEI_PRODUCT_K4510 0x14CB
|
||||
+#define HUAWEI_PRODUCT_K4511 0x14CC
|
||||
+#define HUAWEI_PRODUCT_E173S 0x1C05
|
||||
|
||||
#define QUANTA_VENDOR_ID 0x0408
|
||||
#define QUANTA_PRODUCT_Q101 0xEA02
|
||||
@@ -332,6 +337,7 @@ static int option_resume(struct usb_ser
|
||||
/* ALCATEL PRODUCTS */
|
||||
#define ALCATEL_VENDOR_ID 0x1bbb
|
||||
#define ALCATEL_PRODUCT_X060S 0x0000
|
||||
+#define ALCATEL_PRODUCT_X220D 0x0017
|
||||
|
||||
/* Airplus products */
|
||||
#define AIRPLUS_VENDOR_ID 0x1011
|
||||
@@ -437,8 +443,17 @@ static struct usb_device_id option_ids[]
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E143C, 0xff, 0xff, 0xff) },
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E143D, 0xff, 0xff, 0xff) },
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E143E, 0xff, 0xff, 0xff) },
|
||||
+ { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K3770, 0xff, 0x02, 0x31) },
|
||||
+ { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K3770, 0xff, 0x02, 0x32) },
|
||||
+ { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K3771, 0xff, 0x02, 0x31) },
|
||||
+ { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K3771, 0xff, 0x02, 0x32) },
|
||||
+ { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K4510, 0xff, 0x01, 0x31) },
|
||||
+ { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K4510, 0xff, 0x01, 0x32) },
|
||||
+ { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K4511, 0xff, 0x01, 0x31) },
|
||||
+ { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K4511, 0xff, 0x01, 0x32) },
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E143F, 0xff, 0xff, 0xff) },
|
||||
{ USB_DEVICE(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E14AC) },
|
||||
+ { USB_DEVICE(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E173S) },
|
||||
{ USB_DEVICE(AMOI_VENDOR_ID, AMOI_PRODUCT_9508) },
|
||||
{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_V640) }, /* Novatel Merlin V640/XV620 */
|
||||
{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_V620) }, /* Novatel Merlin V620/S620 */
|
||||
@@ -639,6 +654,7 @@ static struct usb_device_id option_ids[]
|
||||
{ USB_DEVICE(ALINK_VENDOR_ID, 0xce16) },
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(ALINK_VENDOR_ID, ALINK_PRODUCT_3GU, 0xff, 0xff, 0xff) },
|
||||
{ USB_DEVICE(ALCATEL_VENDOR_ID, ALCATEL_PRODUCT_X060S) },
|
||||
+ { USB_DEVICE(ALCATEL_VENDOR_ID, ALCATEL_PRODUCT_X220D) },
|
||||
{ USB_DEVICE(AIRPLUS_VENDOR_ID, AIRPLUS_PRODUCT_MCD650) },
|
||||
{ USB_DEVICE(TLAYTECH_VENDOR_ID, TLAYTECH_PRODUCT_TEU800) },
|
||||
{ USB_DEVICE(HAIER_VENDOR_ID, HAIER_PRODUCT_CE100) },
|
@ -1,11 +0,0 @@
|
||||
--- a/init/main.c
|
||||
+++ b/init/main.c
|
||||
@@ -839,7 +839,7 @@ static noinline int init_post(void)
|
||||
numa_default_policy();
|
||||
|
||||
if (sys_open((const char __user *) "/dev/console", O_RDWR, 0) < 0)
|
||||
- printk(KERN_WARNING "Warning: unable to open an initial console.\n");
|
||||
+ printk(KERN_WARNING "Please be patient, while OpenWrt loads ...\n");
|
||||
|
||||
(void) sys_dup(0);
|
||||
(void) sys_dup(0);
|
@ -1,102 +0,0 @@
|
||||
--- a/scripts/genksyms/parse.c_shipped
|
||||
+++ b/scripts/genksyms/parse.c_shipped
|
||||
@@ -160,7 +160,9 @@
|
||||
|
||||
|
||||
#include <assert.h>
|
||||
+#ifndef __APPLE__
|
||||
#include <malloc.h>
|
||||
+#endif
|
||||
#include "genksyms.h"
|
||||
|
||||
static int is_typedef;
|
||||
--- a/scripts/genksyms/parse.y
|
||||
+++ b/scripts/genksyms/parse.y
|
||||
@@ -24,7 +24,9 @@
|
||||
%{
|
||||
|
||||
#include <assert.h>
|
||||
+#ifndef __APPLE__
|
||||
#include <malloc.h>
|
||||
+#endif
|
||||
#include "genksyms.h"
|
||||
|
||||
static int is_typedef;
|
||||
--- 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
|
||||
@@ -97,6 +97,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)
|
||||
HOST_LOADLIBES = $(shell $(CONFIG_SHELL) $(check-lxdialog) -ldflags $(HOSTCC))
|
||||
+ifeq ($(shell uname -s),Darwin)
|
||||
+HOST_LOADLIBES += -lncurses
|
||||
+endif
|
||||
|
||||
HOST_EXTRACFLAGS += -DLOCALE
|
||||
|
||||
--- a/scripts/mod/mk_elfconfig.c
|
||||
+++ b/scripts/mod/mk_elfconfig.c
|
||||
@@ -1,7 +1,11 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
+#ifndef __APPLE__
|
||||
#include <elf.h>
|
||||
+#else
|
||||
+#include "../../../../../tools/sstrip/include/elf.h"
|
||||
+#endif
|
||||
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
--- a/scripts/mod/modpost.h
|
||||
+++ b/scripts/mod/modpost.h
|
||||
@@ -7,7 +7,11 @@
|
||||
#include <sys/mman.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
+#if !(defined(__APPLE__) || defined(__CYGWIN__))
|
||||
#include <elf.h>
|
||||
+#else
|
||||
+#include "../../../../../tools/sstrip/include/elf.h"
|
||||
+#endif
|
||||
|
||||
#include "elfconfig.h"
|
||||
|
@ -1,154 +0,0 @@
|
||||
--- a/drivers/net/wireless/hostap/hostap_ap.c
|
||||
+++ b/drivers/net/wireless/hostap/hostap_ap.c
|
||||
@@ -2335,13 +2335,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;
|
||||
@@ -2407,13 +2407,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
|
||||
@@ -431,6 +431,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
|
||||
@@ -1475,23 +1475,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;
|
||||
}
|
||||
@@ -4055,3 +4052,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);
|
@ -1,17 +0,0 @@
|
||||
--- a/include/linux/stddef.h
|
||||
+++ b/include/linux/stddef.h
|
||||
@@ -16,6 +16,7 @@ enum {
|
||||
false = 0,
|
||||
true = 1
|
||||
};
|
||||
+#endif /* __KERNEL__ */
|
||||
|
||||
#undef offsetof
|
||||
#ifdef __compiler_offsetof
|
||||
@@ -23,6 +24,5 @@ enum {
|
||||
#else
|
||||
#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
|
||||
#endif
|
||||
-#endif /* __KERNEL__ */
|
||||
|
||||
#endif
|
@ -1,60 +0,0 @@
|
||||
Fix spi-gpio for hotplug.
|
||||
|
||||
--mb
|
||||
|
||||
|
||||
|
||||
--- a/drivers/spi/spi_gpio.c
|
||||
+++ b/drivers/spi/spi_gpio.c
|
||||
@@ -218,7 +218,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;
|
||||
|
||||
@@ -232,7 +232,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)
|
||||
{
|
||||
int value;
|
||||
@@ -261,7 +261,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;
|
||||
@@ -317,7 +317,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;
|
||||
@@ -344,12 +344,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);
|
||||
|
@ -1,58 +0,0 @@
|
||||
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 */
|
||||
+}
|
||||
|
||||
#define EXPAND_BITBANG_TXRX
|
||||
#include <linux/spi/spi_bitbang.h>
|
@ -1,366 +0,0 @@
|
||||
THIS CODE IS DEPRECATED.
|
||||
|
||||
Please use the new mainline SPI-GPIO driver, as of 2.6.29.
|
||||
|
||||
--mb
|
||||
|
||||
|
||||
|
||||
--- /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 <linux/spi/spi_bitbang.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, 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, 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, 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, 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
|
||||
@@ -116,6 +116,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 iMX SPI controller"
|
||||
depends on ARCH_MX1 && EXPERIMENTAL
|
||||
--- a/drivers/spi/Makefile
|
||||
+++ b/drivers/spi/Makefile
|
||||
@@ -17,6 +17,7 @@ obj-$(CONFIG_SPI_BITBANG) += spi_bitban
|
||||
obj-$(CONFIG_SPI_AU1550) += au1550_spi.o
|
||||
obj-$(CONFIG_SPI_BUTTERFLY) += spi_butterfly.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_PXA2XX) += pxa2xx_spi.o
|
@ -1,843 +0,0 @@
|
||||
--- /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
|
||||
@@ -278,6 +278,31 @@ config MMC_TMIO
|
||||
This provides support for the SD/MMC cell found in TC6393XB,
|
||||
T7L66XB and also HTC ASIC3
|
||||
|
||||
+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
|
||||
@@ -33,6 +33,7 @@ obj-$(CONFIG_MMC_SDRICOH_CS) += sdricoh_
|
||||
obj-$(CONFIG_MMC_TMIO) += tmio_mmc.o
|
||||
obj-$(CONFIG_MMC_CB710) += cb710-mmc.o
|
||||
obj-$(CONFIG_MMC_VIA_SDMMC) += via-sdmmc.o
|
||||
+obj-$(CONFIG_GPIOMMC) += gpiommc.o
|
||||
|
||||
ifeq ($(CONFIG_CB710_DEBUG),y)
|
||||
CFLAGS-cb710-mmc += -DDEBUG
|
||||
--- /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
|
||||
@@ -2266,6 +2266,11 @@ T: git git://git.kernel.org/pub/scm/linu
|
||||
S: Maintained
|
||||
F: drivers/media/video/gspca/
|
||||
|
||||
+GPIOMMC DRIVER
|
||||
+P: Michael Buesch
|
||||
+M: mb@bu3sch.de
|
||||
+S: Maintained
|
||||
+
|
||||
HARDWARE MONITORING
|
||||
L: lm-sensors@lm-sensors.org
|
||||
W: http://www.lm-sensors.org/
|
@ -1,58 +0,0 @@
|
||||
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
Loading…
Reference in New Issue
Block a user