mirror of
https://github.com/Ysurac/openmptcprouter.git
synced 2025-03-09 15:40:20 +00:00
Fix RUTX support
This commit is contained in:
parent
6fc4d11e09
commit
0b14e36374
98 changed files with 11611 additions and 893 deletions
File diff suppressed because it is too large
Load diff
|
@ -0,0 +1,80 @@
|
|||
Index: linux-5.4.147/kernel/bpf/syscall.c
|
||||
===================================================================
|
||||
--- linux-5.4.147.orig/kernel/bpf/syscall.c
|
||||
+++ linux-5.4.147/kernel/bpf/syscall.c
|
||||
@@ -593,6 +593,11 @@ static int map_create(union bpf_attr *at
|
||||
err = PTR_ERR(btf);
|
||||
goto free_map;
|
||||
}
|
||||
+ if (btf_is_kernel(btf)) {
|
||||
+ btf_put(btf);
|
||||
+ err = -EACCES;
|
||||
+ goto free_map;
|
||||
+ }
|
||||
|
||||
err = map_check_btf(map, btf, attr->btf_key_type_id,
|
||||
attr->btf_value_type_id);
|
||||
Index: linux-5.4.147/kernel/bpf/verifier.c
|
||||
===================================================================
|
||||
--- linux-5.4.147.orig/kernel/bpf/verifier.c
|
||||
+++ linux-5.4.147/kernel/bpf/verifier.c
|
||||
@@ -6959,6 +6959,11 @@ static int check_btf_info(struct bpf_ver
|
||||
btf = btf_get_by_fd(attr->prog_btf_fd);
|
||||
if (IS_ERR(btf))
|
||||
return PTR_ERR(btf);
|
||||
+ if (btf_is_kernel(btf)) {
|
||||
+ btf_put(btf);
|
||||
+ return -EACCES;
|
||||
+ }
|
||||
+
|
||||
env->prog->aux->btf = btf;
|
||||
|
||||
err = check_btf_func(env, attr, uattr);
|
||||
Index: linux-5.4.147/include/linux/btf.h
|
||||
===================================================================
|
||||
--- linux-5.4.147.orig/include/linux/btf.h
|
||||
+++ linux-5.4.147/include/linux/btf.h
|
||||
@@ -47,6 +47,7 @@ void btf_type_seq_show(const struct btf
|
||||
struct seq_file *m);
|
||||
int btf_get_fd_by_id(u32 id);
|
||||
u32 btf_id(const struct btf *btf);
|
||||
+bool btf_is_kernel(const struct btf *btf);
|
||||
bool btf_member_is_reg_int(const struct btf *btf, const struct btf_type *s,
|
||||
const struct btf_member *m,
|
||||
u32 expected_offset, u32 expected_size);
|
||||
Index: linux-5.4.147/kernel/bpf/btf.c
|
||||
===================================================================
|
||||
--- linux-5.4.147.orig/kernel/bpf/btf.c
|
||||
+++ linux-5.4.147/kernel/bpf/btf.c
|
||||
@@ -212,6 +212,7 @@ struct btf {
|
||||
refcount_t refcnt;
|
||||
u32 id;
|
||||
struct rcu_head rcu;
|
||||
+ bool kernel_btf;
|
||||
};
|
||||
|
||||
enum verifier_phase {
|
||||
@@ -352,6 +353,11 @@ static bool btf_type_nosize(const struct
|
||||
btf_type_is_func(t) || btf_type_is_func_proto(t);
|
||||
}
|
||||
|
||||
+bool btf_is_kernel(const struct btf *btf)
|
||||
+{
|
||||
+ return btf->kernel_btf;
|
||||
+}
|
||||
+
|
||||
static bool btf_type_nosize_or_null(const struct btf_type *t)
|
||||
{
|
||||
return !t || btf_type_nosize(t);
|
||||
Index: linux-5.4.147/include/uapi/linux/bpf.h
|
||||
===================================================================
|
||||
--- linux-5.4.147.orig/include/uapi/linux/bpf.h
|
||||
+++ linux-5.4.147/include/uapi/linux/bpf.h
|
||||
@@ -3275,6 +3275,7 @@ struct bpf_btf_info {
|
||||
__aligned_u64 btf;
|
||||
__u32 btf_size;
|
||||
__u32 id;
|
||||
+ __u32 kernel_btf;
|
||||
} __attribute__((aligned(8)));
|
||||
|
||||
/* User bpf_sock_addr struct to access socket fields and sockaddr struct passed
|
|
@ -0,0 +1,53 @@
|
|||
From: Bui Quang Minh @ 2021-01-26 8:26 UTC (permalink / raw)
|
||||
To: ast, daniel, davem, kuba, hawk, john.fastabend, andrii, kafai,
|
||||
songliubraving, yhs, kpsingh, jakub, lmb
|
||||
Cc: netdev, bpf, linux-kernel, minhquangbui99
|
||||
|
||||
In 32-bit architecture, the result of sizeof() is a 32-bit integer so
|
||||
the expression becomes the multiplication between 2 32-bit integer which
|
||||
can potentially leads to integer overflow. As a result,
|
||||
bpf_map_area_alloc() allocates less memory than needed.
|
||||
|
||||
Fix this by casting 1 operand to u64.
|
||||
|
||||
Signed-off-by: Bui Quang Minh <minhquangbui99@gmail.com>
|
||||
---
|
||||
kernel/bpf/devmap.c | 4 ++--
|
||||
net/core/sock_map.c | 2 +-
|
||||
2 files changed, 3 insertions(+), 3 deletions(-)
|
||||
|
||||
Index: linux-5.4.147/kernel/bpf/devmap.c
|
||||
===================================================================
|
||||
--- linux-5.4.147.orig/kernel/bpf/devmap.c
|
||||
+++ linux-5.4.147/kernel/bpf/devmap.c
|
||||
@@ -94,7 +94,7 @@ static struct hlist_head *dev_map_create
|
||||
int i;
|
||||
struct hlist_head *hash;
|
||||
|
||||
- hash = bpf_map_area_alloc(entries * sizeof(*hash), numa_node);
|
||||
+ hash = bpf_map_area_alloc((u64) entries * sizeof(*hash), numa_node);
|
||||
if (hash != NULL)
|
||||
for (i = 0; i < entries; i++)
|
||||
INIT_HLIST_HEAD(&hash[i]);
|
||||
@@ -159,7 +159,7 @@ static int dev_map_init_map(struct bpf_d
|
||||
|
||||
spin_lock_init(&dtab->index_lock);
|
||||
} else {
|
||||
- dtab->netdev_map = bpf_map_area_alloc(dtab->map.max_entries *
|
||||
+ dtab->netdev_map = bpf_map_area_alloc((u64) dtab->map.max_entries *
|
||||
sizeof(struct bpf_dtab_netdev *),
|
||||
dtab->map.numa_node);
|
||||
if (!dtab->netdev_map)
|
||||
Index: linux-5.4.147/net/core/sock_map.c
|
||||
===================================================================
|
||||
--- linux-5.4.147.orig/net/core/sock_map.c
|
||||
+++ linux-5.4.147/net/core/sock_map.c
|
||||
@@ -48,7 +48,7 @@ static struct bpf_map *sock_map_alloc(un
|
||||
if (err)
|
||||
goto free_stab;
|
||||
|
||||
- stab->sks = bpf_map_area_alloc(stab->map.max_entries *
|
||||
+ stab->sks = bpf_map_area_alloc((u64) stab->map.max_entries *
|
||||
sizeof(struct sock *),
|
||||
stab->map.numa_node);
|
||||
if (stab->sks)
|
|
@ -0,0 +1,48 @@
|
|||
From 05acefb4872dae89e772729efb194af754c877e8 Mon Sep 17 00:00:00 2001
|
||||
From: Miklos Szeredi <mszeredi@redhat.com>
|
||||
Date: Tue, 2 Jun 2020 22:20:26 +0200
|
||||
Subject: ovl: check permission to open real file
|
||||
|
||||
Call inode_permission() on real inode before opening regular file on one of
|
||||
the underlying layers.
|
||||
|
||||
In some cases ovl_permission() already checks access to an underlying file,
|
||||
but it misses the metacopy case, and possibly other ones as well.
|
||||
|
||||
Removing the redundant permission check from ovl_permission() should be
|
||||
considered later.
|
||||
|
||||
Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
|
||||
---
|
||||
fs/overlayfs/file.c | 16 ++++++++++++++--
|
||||
1 file changed, 14 insertions(+), 2 deletions(-)
|
||||
|
||||
Index: linux-5.4.147/fs/overlayfs/file.c
|
||||
===================================================================
|
||||
--- linux-5.4.147.orig/fs/overlayfs/file.c
|
||||
+++ linux-5.4.147/fs/overlayfs/file.c
|
||||
@@ -34,10 +34,22 @@ static struct file *ovl_open_realfile(co
|
||||
struct file *realfile;
|
||||
const struct cred *old_cred;
|
||||
int flags = file->f_flags | OVL_OPEN_FLAGS;
|
||||
+ int acc_mode = ACC_MODE(flags);
|
||||
+ int err;
|
||||
+
|
||||
+ if (flags & O_APPEND)
|
||||
+ acc_mode |= MAY_APPEND;
|
||||
|
||||
old_cred = ovl_override_creds(inode->i_sb);
|
||||
- realfile = open_with_fake_path(&file->f_path, flags, realinode,
|
||||
- current_cred());
|
||||
+ err = inode_permission(realinode, MAY_OPEN | acc_mode);
|
||||
+ if (err) {
|
||||
+ realfile = ERR_PTR(err);
|
||||
+ } else if (!inode_owner_or_capable(realinode)) {
|
||||
+ realfile = ERR_PTR(-EPERM);
|
||||
+ } else {
|
||||
+ realfile = open_with_fake_path(&file->f_path, flags, realinode,
|
||||
+ current_cred());
|
||||
+ }
|
||||
revert_creds(old_cred);
|
||||
|
||||
pr_debug("open(%p[%pD2/%c], 0%o) -> (%p, 0%o)\n",
|
|
@ -0,0 +1,73 @@
|
|||
From 48bd024b8a40d73ad6b086de2615738da0c7004f Mon Sep 17 00:00:00 2001
|
||||
From: Miklos Szeredi <mszeredi@redhat.com>
|
||||
Date: Tue, 2 Jun 2020 22:20:25 +0200
|
||||
Subject: ovl: switch to mounter creds in readdir
|
||||
|
||||
In preparation for more permission checking, override credentials for
|
||||
directory operations on the underlying filesystems.
|
||||
|
||||
Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
|
||||
---
|
||||
fs/overlayfs/readdir.c | 27 +++++++++++++++++++++------
|
||||
1 file changed, 21 insertions(+), 6 deletions(-)
|
||||
|
||||
Index: linux-5.4.147/fs/overlayfs/readdir.c
|
||||
===================================================================
|
||||
--- linux-5.4.147.orig/fs/overlayfs/readdir.c
|
||||
+++ linux-5.4.147/fs/overlayfs/readdir.c
|
||||
@@ -732,8 +732,10 @@ static int ovl_iterate(struct file *file
|
||||
struct ovl_dir_file *od = file->private_data;
|
||||
struct dentry *dentry = file->f_path.dentry;
|
||||
struct ovl_cache_entry *p;
|
||||
+ const struct cred *old_cred;
|
||||
int err;
|
||||
|
||||
+ old_cred = ovl_override_creds(dentry->d_sb);
|
||||
if (!ctx->pos)
|
||||
ovl_dir_reset(file);
|
||||
|
||||
@@ -747,17 +749,20 @@ static int ovl_iterate(struct file *file
|
||||
(ovl_same_sb(dentry->d_sb) &&
|
||||
(ovl_is_impure_dir(file) ||
|
||||
OVL_TYPE_MERGE(ovl_path_type(dentry->d_parent))))) {
|
||||
- return ovl_iterate_real(file, ctx);
|
||||
+ err = ovl_iterate_real(file, ctx);
|
||||
+ } else {
|
||||
+ err = iterate_dir(od->realfile, ctx);
|
||||
}
|
||||
- return iterate_dir(od->realfile, ctx);
|
||||
+ goto out;
|
||||
}
|
||||
|
||||
if (!od->cache) {
|
||||
struct ovl_dir_cache *cache;
|
||||
|
||||
cache = ovl_cache_get(dentry);
|
||||
+ err = PTR_ERR(cache);
|
||||
if (IS_ERR(cache))
|
||||
- return PTR_ERR(cache);
|
||||
+ goto out;
|
||||
|
||||
od->cache = cache;
|
||||
ovl_seek_cursor(od, ctx->pos);
|
||||
@@ -769,7 +774,7 @@ static int ovl_iterate(struct file *file
|
||||
if (!p->ino) {
|
||||
err = ovl_cache_update_ino(&file->f_path, p);
|
||||
if (err)
|
||||
- return err;
|
||||
+ goto out;
|
||||
}
|
||||
if (!dir_emit(ctx, p->name, p->len, p->ino, p->type))
|
||||
break;
|
||||
@@ -777,7 +782,10 @@ static int ovl_iterate(struct file *file
|
||||
od->cursor = p->l_node.next;
|
||||
ctx->pos++;
|
||||
}
|
||||
- return 0;
|
||||
+ err = 0;
|
||||
+out:
|
||||
+ revert_creds(old_cred);
|
||||
+ return err;
|
||||
}
|
||||
|
||||
static loff_t ovl_dir_llseek(struct file *file, loff_t offset, int origin)
|
|
@ -0,0 +1,61 @@
|
|||
From 56230d956739b9cb1cbde439d76227d77979a04d Mon Sep 17 00:00:00 2001
|
||||
From: Miklos Szeredi <mszeredi@redhat.com>
|
||||
Date: Tue, 2 Jun 2020 22:20:26 +0200
|
||||
Subject: ovl: verify permissions in ovl_path_open()
|
||||
|
||||
Check permission before opening a real file.
|
||||
|
||||
ovl_path_open() is used by readdir and copy-up routines.
|
||||
|
||||
ovl_permission() theoretically already checked copy up permissions, but it
|
||||
doesn't hurt to re-do these checks during the actual copy-up.
|
||||
|
||||
For directory reading ovl_permission() only checks access to topmost
|
||||
underlying layer. Readdir on a merged directory accesses layers below the
|
||||
topmost one as well. Permission wasn't checked for these layers.
|
||||
|
||||
Note: modifying ovl_permission() to perform this check would be far more
|
||||
complex and hence more bug prone. The result is less precise permissions
|
||||
returned in access(2). If this turns out to be an issue, we can revisit
|
||||
this bug.
|
||||
|
||||
Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
|
||||
---
|
||||
fs/overlayfs/util.c | 27 ++++++++++++++++++++++++++-
|
||||
1 file changed, 26 insertions(+), 1 deletion(-)
|
||||
|
||||
Index: linux-5.4.147/fs/overlayfs/util.c
|
||||
===================================================================
|
||||
--- linux-5.4.147.orig/fs/overlayfs/util.c
|
||||
+++ linux-5.4.147/fs/overlayfs/util.c
|
||||
@@ -475,7 +475,29 @@ bool ovl_is_whiteout(struct dentry *dent
|
||||
|
||||
struct file *ovl_path_open(struct path *path, int flags)
|
||||
{
|
||||
- return dentry_open(path, flags | O_NOATIME, current_cred());
|
||||
+ struct inode *inode = d_inode(path->dentry);
|
||||
+ int err, acc_mode;
|
||||
+
|
||||
+ switch (flags & O_ACCMODE) {
|
||||
+ case O_RDONLY:
|
||||
+ acc_mode = MAY_READ;
|
||||
+ break;
|
||||
+ case O_WRONLY:
|
||||
+ acc_mode = MAY_WRITE;
|
||||
+ break;
|
||||
+ default:
|
||||
+ BUG();
|
||||
+ }
|
||||
+
|
||||
+ err = inode_permission(inode, acc_mode | MAY_OPEN);
|
||||
+ if (err)
|
||||
+ return ERR_PTR(err);
|
||||
+
|
||||
+ /* O_NOATIME is an optimization, don't fail if not permitted */
|
||||
+ if (inode_owner_or_capable(inode))
|
||||
+ flags |= O_NOATIME;
|
||||
+
|
||||
+ return dentry_open(path, flags, current_cred());
|
||||
}
|
||||
|
||||
/* Caller should hold ovl_inode->lock */
|
|
@ -0,0 +1,46 @@
|
|||
From b6650dab404c701d7fe08a108b746542a934da84 Mon Sep 17 00:00:00 2001
|
||||
From: Miklos Szeredi <mszeredi@redhat.com>
|
||||
Date: Mon, 14 Dec 2020 15:26:14 +0100
|
||||
Subject: ovl: do not fail because of O_NOATIME
|
||||
|
||||
In case the file cannot be opened with O_NOATIME because of lack of
|
||||
capabilities, then clear O_NOATIME instead of failing.
|
||||
|
||||
Remove WARN_ON(), since it would now trigger if O_NOATIME was cleared.
|
||||
Noticed by Amir Goldstein.
|
||||
|
||||
Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
|
||||
---
|
||||
fs/overlayfs/file.c | 11 +++--------
|
||||
1 file changed, 3 insertions(+), 8 deletions(-)
|
||||
|
||||
Index: linux-5.4.147/fs/overlayfs/file.c
|
||||
===================================================================
|
||||
--- linux-5.4.147.orig/fs/overlayfs/file.c
|
||||
+++ linux-5.4.147/fs/overlayfs/file.c
|
||||
@@ -44,9 +44,10 @@ static struct file *ovl_open_realfile(co
|
||||
err = inode_permission(realinode, MAY_OPEN | acc_mode);
|
||||
if (err) {
|
||||
realfile = ERR_PTR(err);
|
||||
- } else if (!inode_owner_or_capable(realinode)) {
|
||||
- realfile = ERR_PTR(-EPERM);
|
||||
} else {
|
||||
+ if (!inode_owner_or_capable(realinode))
|
||||
+ flags &= ~O_NOATIME;
|
||||
+
|
||||
realfile = open_with_fake_path(&file->f_path, flags, realinode,
|
||||
current_cred());
|
||||
}
|
||||
@@ -66,12 +67,6 @@ static int ovl_change_flags(struct file
|
||||
struct inode *inode = file_inode(file);
|
||||
int err;
|
||||
|
||||
- flags |= OVL_OPEN_FLAGS;
|
||||
-
|
||||
- /* If some flag changed that cannot be changed then something's amiss */
|
||||
- if (WARN_ON((file->f_flags ^ flags) & ~OVL_SETFL_MASK))
|
||||
- return -EIO;
|
||||
-
|
||||
flags &= OVL_SETFL_MASK;
|
||||
|
||||
if (((flags ^ file->f_flags) & O_APPEND) && IS_APPEND(inode))
|
|
@ -0,0 +1,17 @@
|
|||
Index: linux-5.4.124/drivers/net/ppp/pppoe.c
|
||||
===================================================================
|
||||
--- linux-5.4.124.orig/drivers/net/ppp/pppoe.c
|
||||
+++ linux-5.4.124/drivers/net/ppp/pppoe.c
|
||||
@@ -502,6 +502,12 @@ static int pppoe_disc_rcv(struct sk_buff
|
||||
if (ph->code != PADT_CODE)
|
||||
goto abort;
|
||||
|
||||
+ // compare the dst addr to the current net device addr and ignore packet if not matching
|
||||
+ // otherwise it will terminate the connection
|
||||
+ if(!ether_addr_equal(eth_hdr(skb)->h_dest, dev->dev_addr)) {
|
||||
+ goto abort;
|
||||
+ }
|
||||
+
|
||||
pn = pppoe_pernet(dev_net(dev));
|
||||
po = get_item(pn, ph->sid, eth_hdr(skb)->h_source, dev->ifindex);
|
||||
if (po)
|
|
@ -0,0 +1,50 @@
|
|||
Index: linux-5.4.124/drivers/mtd/spi-nor/spi-nor.c
|
||||
===================================================================
|
||||
--- linux-5.4.124.orig/drivers/mtd/spi-nor/spi-nor.c
|
||||
+++ linux-5.4.124/drivers/mtd/spi-nor/spi-nor.c
|
||||
@@ -2241,6 +2241,9 @@ static const struct flash_info spi_nor_i
|
||||
.fixups = &gd25q256_fixups,
|
||||
},
|
||||
|
||||
+ /* Zbit */
|
||||
+ { "zb25vq128", INFO(0xC84018, 0, 64 * 1024, 64, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
|
||||
+
|
||||
/* Intel/Numonyx -- xxxs33b */
|
||||
{ "160s33b", INFO(0x898911, 0, 64 * 1024, 32, 0) },
|
||||
{ "320s33b", INFO(0x898912, 0, 64 * 1024, 64, 0) },
|
||||
@@ -2405,6 +2408,7 @@ static const struct flash_info spi_nor_i
|
||||
{ "m25p32", INFO(0x202016, 0, 64 * 1024, 64, 0) },
|
||||
{ "m25p64", INFO(0x202017, 0, 64 * 1024, 128, 0) },
|
||||
{ "m25p128", INFO(0x202018, 0, 256 * 1024, 64, 0) },
|
||||
+ { "n25q032", INFO(0x20ba16, 0, 64 * 1024, 64, 0) },
|
||||
|
||||
{ "m25p05-nonjedec", INFO(0, 0, 32 * 1024, 2, 0) },
|
||||
{ "m25p10-nonjedec", INFO(0, 0, 32 * 1024, 4, 0) },
|
||||
@@ -2508,10 +2512,14 @@ static const struct flash_info spi_nor_i
|
||||
{ "XM25QH128A", INFO(0x207018, 0, 64 * 1024, 256, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
|
||||
|
||||
/* XTX Technology (Shenzhen) Limited */
|
||||
+ { "XT25F128A", INFO(0x207018, 0, 64 * 1024, 256, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
|
||||
{ "xt25f128b", INFO(0x0B4018, 0, 64 * 1024, 256, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
|
||||
{ },
|
||||
};
|
||||
|
||||
+static const struct flash_info spi_nor_unknown_id =
|
||||
+ { "undefined", INFO(0x0, 0, 64 * 1024, 256, SECT_4K) };
|
||||
+
|
||||
static const struct flash_info *spi_nor_read_id(struct spi_nor *nor)
|
||||
{
|
||||
int tmp;
|
||||
@@ -2542,9 +2550,12 @@ static const struct flash_info *spi_nor_
|
||||
return &spi_nor_ids[tmp];
|
||||
}
|
||||
}
|
||||
+ return &spi_nor_unknown_id; // for Teltonikia RUT devices
|
||||
+ /*
|
||||
dev_err(nor->dev, "unrecognized JEDEC id bytes: %*ph\n",
|
||||
SPI_NOR_MAX_ID_LEN, id);
|
||||
return ERR_PTR(-ENODEV);
|
||||
+ */
|
||||
}
|
||||
|
||||
static int spi_nor_read(struct mtd_info *mtd, loff_t from, size_t len,
|
|
@ -0,0 +1,198 @@
|
|||
From a07e31adf2753cad2fd9790db5bfc047c81e8152 Mon Sep 17 00:00:00 2001
|
||||
From: Felix Matouschek <felix@matouschek.org>
|
||||
Date: Fri, 2 Jul 2021 20:31:23 +0200
|
||||
Subject: [PATCH] mtd: spinand: Add support for XTX XT26G0xA
|
||||
|
||||
Add support for XTX Technology XT26G01AXXXXX, XTX26G02AXXXXX and
|
||||
XTX26G04AXXXXX SPI NAND.
|
||||
|
||||
These are 3V, 1G/2G/4Gbit serial SLC NAND flash devices with on-die ECC
|
||||
(8bit strength per 512bytes).
|
||||
|
||||
Tested on Teltonika RUTX10 flashed with OpenWrt.
|
||||
|
||||
Datasheets available at
|
||||
http://www.xtxtech.com/download/?AId=225
|
||||
https://datasheet.lcsc.com/szlcsc/2005251034_XTX-XT26G01AWSEGA_C558841.pdf
|
||||
|
||||
Signed-off-by: Felix Matouschek <felix@matouschek.org>
|
||||
---
|
||||
drivers/mtd/nand/spi/Makefile | 2 +-
|
||||
drivers/mtd/nand/spi/core.c | 1 +
|
||||
drivers/mtd/nand/spi/xtx.c | 122 ++++++++++++++++++++++++++++++++++
|
||||
include/linux/mtd/spinand.h | 1 +
|
||||
4 files changed, 125 insertions(+), 1 deletion(-)
|
||||
create mode 100644 drivers/mtd/nand/spi/xtx.c
|
||||
|
||||
Index: linux-5.4.132/drivers/mtd/nand/spi/Makefile
|
||||
===================================================================
|
||||
--- linux-5.4.132.orig/drivers/mtd/nand/spi/Makefile
|
||||
+++ linux-5.4.132/drivers/mtd/nand/spi/Makefile
|
||||
@@ -1,3 +1,3 @@
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
-spinand-objs := core.o gigadevice.o macronix.o micron.o paragon.o toshiba.o winbond.o
|
||||
+spinand-objs := core.o gigadevice.o macronix.o micron.o paragon.o toshiba.o winbond.o xtx.o
|
||||
obj-$(CONFIG_MTD_SPI_NAND) += spinand.o
|
||||
Index: linux-5.4.132/drivers/mtd/nand/spi/core.c
|
||||
===================================================================
|
||||
--- linux-5.4.132.orig/drivers/mtd/nand/spi/core.c
|
||||
+++ linux-5.4.132/drivers/mtd/nand/spi/core.c
|
||||
@@ -758,6 +758,7 @@ static const struct spinand_manufacturer
|
||||
¶gon_spinand_manufacturer,
|
||||
&toshiba_spinand_manufacturer,
|
||||
&winbond_spinand_manufacturer,
|
||||
+ &xtx_spinand_manufacturer,
|
||||
};
|
||||
|
||||
static int spinand_manufacturer_detect(struct spinand_device *spinand)
|
||||
Index: linux-5.4.132/drivers/mtd/nand/spi/xtx.c
|
||||
===================================================================
|
||||
--- /dev/null
|
||||
+++ linux-5.4.132/drivers/mtd/nand/spi/xtx.c
|
||||
@@ -0,0 +1,134 @@
|
||||
+// SPDX-License-Identifier: GPL-2.0
|
||||
+/*
|
||||
+ * Author:
|
||||
+ * Felix Matouschek <felix@matouschek.org>
|
||||
+ */
|
||||
+
|
||||
+#include <linux/device.h>
|
||||
+#include <linux/kernel.h>
|
||||
+#include <linux/mtd/spinand.h>
|
||||
+
|
||||
+#define SPINAND_MFR_XTX 0x0B
|
||||
+
|
||||
+#define XT26G0XA_STATUS_ECC_MASK GENMASK(5, 2)
|
||||
+#define XT26G0XA_STATUS_ECC_NO_DETECTED (0 << 2)
|
||||
+#define XT26G0XA_STATUS_ECC_8_CORRECTED (3 << 4)
|
||||
+#define XT26G0XA_STATUS_ECC_UNCOR_ERROR (2 << 4)
|
||||
+
|
||||
+static SPINAND_OP_VARIANTS(read_cache_variants,
|
||||
+ SPINAND_PAGE_READ_FROM_CACHE_QUADIO_OP(0, 1, NULL, 0),
|
||||
+ SPINAND_PAGE_READ_FROM_CACHE_X4_OP(0, 1, NULL, 0),
|
||||
+ SPINAND_PAGE_READ_FROM_CACHE_DUALIO_OP(0, 1, NULL, 0),
|
||||
+ SPINAND_PAGE_READ_FROM_CACHE_X2_OP(0, 1, NULL, 0),
|
||||
+ SPINAND_PAGE_READ_FROM_CACHE_OP(true, 0, 1, NULL, 0),
|
||||
+ SPINAND_PAGE_READ_FROM_CACHE_OP(false, 0, 1, NULL, 0));
|
||||
+
|
||||
+static SPINAND_OP_VARIANTS(write_cache_variants,
|
||||
+ SPINAND_PROG_LOAD_X4(true, 0, NULL, 0),
|
||||
+ SPINAND_PROG_LOAD(true, 0, NULL, 0));
|
||||
+
|
||||
+static SPINAND_OP_VARIANTS(update_cache_variants,
|
||||
+ SPINAND_PROG_LOAD_X4(false, 0, NULL, 0),
|
||||
+ SPINAND_PROG_LOAD(false, 0, NULL, 0));
|
||||
+
|
||||
+static int xt26g0xa_ooblayout_ecc(struct mtd_info *mtd, int section,
|
||||
+ struct mtd_oob_region *region)
|
||||
+{
|
||||
+ if (section)
|
||||
+ return -ERANGE;
|
||||
+
|
||||
+ region->offset = 8;
|
||||
+ region->length = 40;
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int xt26g0xa_ooblayout_free(struct mtd_info *mtd, int section,
|
||||
+ struct mtd_oob_region *region)
|
||||
+{
|
||||
+ if (section)
|
||||
+ return -ERANGE;
|
||||
+
|
||||
+ region->offset = 1;
|
||||
+ region->length = 7;
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static const struct mtd_ooblayout_ops xt26g0xa_ooblayout = {
|
||||
+ .ecc = xt26g0xa_ooblayout_ecc,
|
||||
+ .free = xt26g0xa_ooblayout_free,
|
||||
+};
|
||||
+
|
||||
+static int xt26g0xa_ecc_get_status(struct spinand_device *spinand,
|
||||
+ u8 status)
|
||||
+{
|
||||
+ switch (status & XT26G0XA_STATUS_ECC_MASK) {
|
||||
+ case XT26G0XA_STATUS_ECC_NO_DETECTED:
|
||||
+ return 0;
|
||||
+ case XT26G0XA_STATUS_ECC_8_CORRECTED:
|
||||
+ return 8;
|
||||
+ case XT26G0XA_STATUS_ECC_UNCOR_ERROR:
|
||||
+ return -EBADMSG;
|
||||
+ default: /* (1 << 2) through (7 << 2) are 1-7 corrected errors */
|
||||
+ return (status & XT26G0XA_STATUS_ECC_MASK) >> 2;
|
||||
+ }
|
||||
+
|
||||
+ return -EINVAL;
|
||||
+}
|
||||
+
|
||||
+static const struct spinand_info xtx_spinand_table[] = {
|
||||
+ SPINAND_INFO("XT26G01A", 0xE1,
|
||||
+ NAND_MEMORG(1, 2048, 64, 64, 1024, 20, 1, 1, 1),
|
||||
+ NAND_ECCREQ(8, 512),
|
||||
+ SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
|
||||
+ &write_cache_variants,
|
||||
+ &update_cache_variants),
|
||||
+ SPINAND_HAS_QE_BIT,
|
||||
+ SPINAND_ECCINFO(&xt26g0xa_ooblayout,
|
||||
+ xt26g0xa_ecc_get_status)),
|
||||
+ SPINAND_INFO("XT26G02A", 0xE2,
|
||||
+ NAND_MEMORG(1, 2048, 64, 64, 2048, 40, 1, 1, 1),
|
||||
+ NAND_ECCREQ(8, 512),
|
||||
+ SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
|
||||
+ &write_cache_variants,
|
||||
+ &update_cache_variants),
|
||||
+ SPINAND_HAS_QE_BIT,
|
||||
+ SPINAND_ECCINFO(&xt26g0xa_ooblayout,
|
||||
+ xt26g0xa_ecc_get_status)),
|
||||
+ SPINAND_INFO("XT26G04A", 0xE3,
|
||||
+ NAND_MEMORG(1, 2048, 64, 128, 2048, 40, 1, 1, 1),
|
||||
+ NAND_ECCREQ(8, 512),
|
||||
+ SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
|
||||
+ &write_cache_variants,
|
||||
+ &update_cache_variants),
|
||||
+ SPINAND_HAS_QE_BIT,
|
||||
+ SPINAND_ECCINFO(&xt26g0xa_ooblayout,
|
||||
+ xt26g0xa_ecc_get_status)),
|
||||
+};
|
||||
+
|
||||
+static int xtx_spinand_detect(struct spinand_device *spinand)
|
||||
+{
|
||||
+ u8 *id = spinand->id.data;
|
||||
+ int ret;
|
||||
+
|
||||
+ if (id[1] != SPINAND_MFR_XTX)
|
||||
+ return 0;
|
||||
+
|
||||
+ ret = spinand_match_and_init(spinand, xtx_spinand_table,
|
||||
+ ARRAY_SIZE(xtx_spinand_table), id[2]);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+
|
||||
+ return 1;
|
||||
+}
|
||||
+
|
||||
+static const struct spinand_manufacturer_ops xtx_spinand_manuf_ops = {
|
||||
+ .detect = xtx_spinand_detect,
|
||||
+};
|
||||
+
|
||||
+const struct spinand_manufacturer xtx_spinand_manufacturer = {
|
||||
+ .id = SPINAND_MFR_XTX,
|
||||
+ .name = "XTX",
|
||||
+ .ops = &xtx_spinand_manuf_ops,
|
||||
+};
|
||||
Index: linux-5.4.132/include/linux/mtd/spinand.h
|
||||
===================================================================
|
||||
--- linux-5.4.132.orig/include/linux/mtd/spinand.h
|
||||
+++ linux-5.4.132/include/linux/mtd/spinand.h
|
||||
@@ -230,6 +230,7 @@ extern const struct spinand_manufacturer
|
||||
extern const struct spinand_manufacturer paragon_spinand_manufacturer;
|
||||
extern const struct spinand_manufacturer toshiba_spinand_manufacturer;
|
||||
extern const struct spinand_manufacturer winbond_spinand_manufacturer;
|
||||
+extern const struct spinand_manufacturer xtx_spinand_manufacturer;
|
||||
|
||||
/**
|
||||
* struct spinand_op_variants - SPI NAND operation variants
|
Loading…
Add table
Add a link
Reference in a new issue