Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > linux.kernel > #1473080 > unrolled thread
| Started by | Daniel Walter <dwalter@sigma-star.at> |
|---|---|
| First post | 2016-08-31 09:30 +0200 |
| Last post | 2016-08-31 09:40 +0200 |
| Articles | 20 on this page of 45 — 1 participant |
Back to article view | Back to linux.kernel
[PATCH 00/46] Nandsim facelift (part I of II) Daniel Walter <dwalter@sigma-star.at> - 2016-08-31 09:30 +0200
[PATCH 10/46] mtd: nandsim: Add helper functions for pointer magic Daniel Walter <dwalter@sigma-star.at> - 2016-08-31 09:30 +0200
[PATCH 02/46] mtd: nand: TODO Propagate mtd_device_unregister() return value in tear down Daniel Walter <dwalter@sigma-star.at> - 2016-08-31 09:30 +0200
[PATCH 07/46] mtd: nandsim: Begin with removal of global state Daniel Walter <dwalter@sigma-star.at> - 2016-08-31 09:30 +0200
[PATCH 03/46] mtd: Don't unconditionally unregister reboot notifier Daniel Walter <dwalter@sigma-star.at> - 2016-08-31 09:30 +0200
[PATCH 45/46] mtd: nandsim: Always answer all 8 bytes from NAND_CMD_READID Daniel Walter <dwalter@sigma-star.at> - 2016-08-31 09:40 +0200
[PATCH 06/46] mtd: nandsim: Add basic control file support Daniel Walter <dwalter@sigma-star.at> - 2016-08-31 09:40 +0200
[PATCH 43/46] mtd: nandsim: Wire up NANDSIM_IOC_NEW_INSTANCE Daniel Walter <dwalter@sigma-star.at> - 2016-08-31 09:40 +0200
[PATCH 15/46] mtd: nandsim: Introduce backend operations Daniel Walter <dwalter@sigma-star.at> - 2016-08-31 09:40 +0200
[PATCH 09/46] mtd: nandsim: Don't directly use module parameters Daniel Walter <dwalter@sigma-star.at> - 2016-08-31 09:40 +0200
[PATCH 01/46] mtdpart: Propagate _get/put_device() Daniel Walter <dwalter@sigma-star.at> - 2016-08-31 09:40 +0200
[PATCH 27/46] mtd: nandsim: Add no_oob mode Daniel Walter <dwalter@sigma-star.at> - 2016-08-31 09:40 +0200
[PATCH 14/46] mtd: nandsim: Add simulator id to MTD parition name Daniel Walter <dwalter@sigma-star.at> - 2016-08-31 09:40 +0200
[PATCH 44/46] mtd: nandsim: Wire up NANDSIM_IOC_DESTROY_INSTANCE Daniel Walter <dwalter@sigma-star.at> - 2016-08-31 09:40 +0200
[PATCH 11/46] mtd: nandsim: Factor out nandsim parameters Daniel Walter <dwalter@sigma-star.at> - 2016-08-31 09:40 +0200
[PATCH 33/46] mtd: nandsim: Relax page size restrictions Daniel Walter <dwalter@sigma-star.at> - 2016-08-31 09:40 +0200
[PATCH 38/46] mtd: nandsim: Expose partition creation logic to user space Daniel Walter <dwalter@sigma-star.at> - 2016-08-31 09:40 +0200
[PATCH 24/46] mtd: nandsim: Wire up NANDSIM_MODE_CACHEFILE ioctl mode Daniel Walter <dwalter@sigma-star.at> - 2016-08-31 09:40 +0200
[PATCH 39/46] mtd: nandsim: Rework init error paths Daniel Walter <dwalter@sigma-star.at> - 2016-08-31 09:40 +0200
[PATCH 18/46] mtd: nandsim: Add basic support for a file backend Daniel Walter <dwalter@sigma-star.at> - 2016-08-31 09:40 +0200
[PATCH 08/46] mtd: nandsim: Kill global nsmtd Daniel Walter <dwalter@sigma-star.at> - 2016-08-31 09:40 +0200
[PATCH 40/46] mtd: nandsim: Expose BBT, delays, etc.. to userspace Daniel Walter <dwalter@sigma-star.at> - 2016-08-31 09:40 +0200
[PATCH 17/46] mtd: nandsim: Allow external backends Daniel Walter <dwalter@sigma-star.at> - 2016-08-31 09:40 +0200
[PATCH 46/46] mtd/nandsim: Add ioctl for info Daniel Walter <dwalter@sigma-star.at> - 2016-08-31 09:40 +0200
[PATCH 36/46] mtd: nandsim: Cleanup constants Daniel Walter <dwalter@sigma-star.at> - 2016-08-31 09:40 +0200
[PATCH 42/46] mtd: nandsim: Don't printk on ENOMEM Daniel Walter <dwalter@sigma-star.at> - 2016-08-31 09:40 +0200
[PATCH 19/46] mtd: nandsim: UAPI v1 Daniel Walter <dwalter@sigma-star.at> - 2016-08-31 09:40 +0200
[PATCH 20/46] mtd: nandsim: Implement preliminary constructor function Daniel Walter <dwalter@sigma-star.at> - 2016-08-31 09:40 +0200
[PATCH 12/46] mtd: nandsim: Make debugfs logic multi instance capable Daniel Walter <dwalter@sigma-star.at> - 2016-08-31 09:40 +0200
[PATCH 04/46] mtd: Don't unconditionally execute remove notifiers Daniel Walter <dwalter@sigma-star.at> - 2016-08-31 09:40 +0200
[PATCH 22/46] mtd: nandsim: Cleanup destroy handlers Daniel Walter <dwalter@sigma-star.at> - 2016-08-31 09:40 +0200
[PATCH 25/46] mtd: nandsim: Print backend name Daniel Walter <dwalter@sigma-star.at> - 2016-08-31 09:40 +0200
[PATCH 28/46] mtd: nandsim: Refine exports Daniel Walter <dwalter@sigma-star.at> - 2016-08-31 09:40 +0200
[PATCH 31/46] mtd: nandsim: Remove NS_RAW_OFFSET_OOB Daniel Walter <dwalter@sigma-star.at> - 2016-08-31 09:40 +0200
[PATCH 21/46] mtd: nandsim: Implement preliminary destructor function Daniel Walter <dwalter@sigma-star.at> - 2016-08-31 09:40 +0200
[PATCH 26/46] mtd: nandsim: use the existing output macros Daniel Walter <dwalter@sigma-star.at> - 2016-08-31 09:40 +0200
[PATCH 37/46] mtd: nandsim: Turn parts[] into a integer Daniel Walter <dwalter@sigma-star.at> - 2016-08-31 09:40 +0200
[PATCH 41/46] mtd: nandsim: Expose support for weakpages/blocks to userspace Daniel Walter <dwalter@sigma-star.at> - 2016-08-31 09:40 +0200
[PATCH 23/46] mtd: nandsim: Unify file backend init logic Daniel Walter <dwalter@sigma-star.at> - 2016-08-31 09:40 +0200
[PATCH 35/46] mtd: nandsim: Make NANDSIM_MAX_DEVICES part of uapi Daniel Walter <dwalter@sigma-star.at> - 2016-08-31 09:40 +0200
[PATCH 32/46] mtd: nandsim: Remove NS_IS_INITIALIZED Daniel Walter <dwalter@sigma-star.at> - 2016-08-31 09:40 +0200
[PATCH 29/46] um: Add nandsim backend driver Daniel Walter <dwalter@sigma-star.at> - 2016-08-31 09:40 +0200
[PATCH 34/46] mtd: nandsim: Support bitflip and read error emulation in file backend Daniel Walter <dwalter@sigma-star.at> - 2016-08-31 09:40 +0200
[PATCH 05/46] mtd: Don't print a scary message when trying to remove a busy MTD Daniel Walter <dwalter@sigma-star.at> - 2016-08-31 09:40 +0200
[PATCH 13/46] mtd: nandsim: Add final logic for multiple instances Daniel Walter <dwalter@sigma-star.at> - 2016-08-31 09:40 +0200
Page 2 of 3 — ← Prev page 1 [2] 3 Next page →
| From | Daniel Walter <dwalter@sigma-star.at> |
|---|---|
| Date | 2016-08-31 09:40 +0200 |
| Subject | [PATCH 08/46] mtd: nandsim: Kill global nsmtd |
| Message-ID | <sc8hR-7T2-63@gated-at.bofh.it> |
| In reply to | #1473080 |
From: Richard Weinberger <richard@nod.at>
Do it like UBI and support in future up to 32 instances.
For now we still keep a single instance and allow more when
all global state has been removed.
Signed-off-by: Richard Weinberger <richard@nod.at>
---
drivers/mtd/nand/nandsim.c | 14 +++++++++++---
1 file changed, 11 insertions(+), 3 deletions(-)
diff --git a/drivers/mtd/nand/nandsim.c b/drivers/mtd/nand/nandsim.c
index c49999d..e24ef8c 100644
--- a/drivers/mtd/nand/nandsim.c
+++ b/drivers/mtd/nand/nandsim.c
@@ -448,8 +448,10 @@ struct grave_page {
unsigned int reads_done;
};
+#define NS_MAX_DEVICES 32
+
/* MTD structure for NAND controller */
-static struct mtd_info *nsmtd;
+static struct mtd_info *ns_mtds[NS_MAX_DEVICES];
static int nandsim_debugfs_show(struct seq_file *m, void *private)
{
@@ -1451,6 +1453,9 @@ static int do_read_error(struct nandsim *ns, int num)
static void do_bit_flips(struct nandsim *ns, int num)
{
+ struct nand_chip *chip = ((struct nand_chip *)ns - 1);
+ struct mtd_info *nsmtd = nand_to_mtd(chip);
+
if (bitflips && prandom_u32() < (1 << 22)) {
int flips = 1;
if (bitflips > 1)
@@ -2268,6 +2273,7 @@ static int __init ns_init_default(void)
{
struct nand_chip *chip;
struct nandsim *nand;
+ struct mtd_info *nsmtd;
int retval = -ENOMEM, i;
if (bus_width != 8 && bus_width != 16) {
@@ -2283,8 +2289,9 @@ static int __init ns_init_default(void)
return -ENOMEM;
}
- nsmtd = nand_to_mtd(chip);
- nand = (struct nandsim *)(chip + 1);
+ WARN_ON(ns_mtds[0]);
+ nsmtd = ns_mtds[0] = nand_to_mtd(chip);
+ nand = (struct nandsim *)(chip + 1);
nand_set_controller_data(chip, (void *)nand);
INIT_LIST_HEAD(&nand->weak_blocks);
@@ -2447,6 +2454,7 @@ error:
static void __exit ns_cleanup_default(void)
{
+ struct mtd_info *nsmtd = ns_mtds[0];
struct nand_chip *chip = mtd_to_nand(nsmtd);
struct nandsim *ns = nand_get_controller_data(chip);
int i;
--
2.8.3
[toc] | [prev] | [next] | [standalone]
| From | Daniel Walter <dwalter@sigma-star.at> |
|---|---|
| Date | 2016-08-31 09:40 +0200 |
| Subject | [PATCH 40/46] mtd: nandsim: Expose BBT, delays, etc.. to userspace |
| Message-ID | <sc8hQ-7T2-43@gated-at.bofh.it> |
| In reply to | #1473080 |
From: Richard Weinberger <richard@nod.at>
Signed-off-by: Richard Weinberger <richard@nod.at>
---
drivers/mtd/nand/nandsim.c | 43 ++++++++++++++++++++++++++++++++++++-------
include/linux/mtd/nandsim.h | 2 +-
2 files changed, 37 insertions(+), 8 deletions(-)
diff --git a/drivers/mtd/nand/nandsim.c b/drivers/mtd/nand/nandsim.c
index 027b15d..222b2b8 100644
--- a/drivers/mtd/nand/nandsim.c
+++ b/drivers/mtd/nand/nandsim.c
@@ -2593,11 +2593,37 @@ static int ns_ctrl_new_instance(struct ns_new_instance_req *req)
nsparam->bus_width = req->bus_width;
nsparam->file_fd = req->file_fd;
nsparam->no_oob = !!req->no_oob;
-
- if (req->parts_num > NANDSIM_MAX_PARTS || req->parts_num < 0) {
- kfree(nsparam);
- return -EINVAL;
- }
+ nsparam->bbt = req->bbt_mode;
+ nsparam->bch = req->bch_strength;
+ nsparam->bitflips = req->bitflips;
+ nsparam->overridesize = req->overridesize;
+
+ if (req->bch_strength && req->no_oob)
+ goto err_inval;
+
+ if (req->access_delay && req->program_delay && req->erase_delay &&
+ req->output_cycle && req->input_cycle) {
+ if (req->access_delay > MAX_UDELAY_MS * 1000)
+ goto err_inval;
+ if (req->program_delay > MAX_UDELAY_MS * 1000)
+ goto err_inval;
+ if (req->erase_delay > 1000)
+ goto err_inval;
+ if (req->output_cycle > MAX_UDELAY_MS * 1000)
+ goto err_inval;
+ if (req->input_cycle > MAX_UDELAY_MS * 1000)
+ goto err_inval;
+
+ nsparam->access_delay = req->access_delay;
+ nsparam->program_delay = req->program_delay;
+ nsparam->erase_delay = req->erase_delay;
+ nsparam->output_cycle = req->output_cycle;
+ nsparam->input_cycle = req->input_cycle;
+ nsparam->do_delays = true;
+ }
+
+ if (req->parts_num > NANDSIM_MAX_PARTS || req->parts_num < 0)
+ goto err_inval;
if (req->parts_num > 0) {
nsparam->parts_num = req->parts_num;
@@ -2618,8 +2644,7 @@ static int ns_ctrl_new_instance(struct ns_new_instance_req *req)
break;
default:
- kfree(nsparam);
- return -EINVAL;
+ goto err_inval;
}
nsmtd = ns_new_instance(nsparam);
@@ -2632,6 +2657,10 @@ static int ns_ctrl_new_instance(struct ns_new_instance_req *req)
ns = nand_get_controller_data(chip);
return ns->index;
+
+err_inval:
+ kfree(nsparam);
+ return -EINVAL;
}
static int ns_ctrl_destroy_instance(struct ns_destroy_instance_req *req)
diff --git a/include/linux/mtd/nandsim.h b/include/linux/mtd/nandsim.h
index 07d32a9..880c0b1 100644
--- a/include/linux/mtd/nandsim.h
+++ b/include/linux/mtd/nandsim.h
@@ -11,7 +11,7 @@ struct nandsim_params {
unsigned int output_cycle;
unsigned int input_cycle;
unsigned int bus_width;
- unsigned int do_delays;
+ bool do_delays;
unsigned int parts[NANDSIM_MAX_PARTS];
unsigned int parts_num;
char *badblocks;
--
2.8.3
[toc] | [prev] | [next] | [standalone]
| From | Daniel Walter <dwalter@sigma-star.at> |
|---|---|
| Date | 2016-08-31 09:40 +0200 |
| Subject | [PATCH 17/46] mtd: nandsim: Allow external backends |
| Message-ID | <sc8hQ-7T2-57@gated-at.bofh.it> |
| In reply to | #1473080 |
From: Richard Weinberger <richard@nod.at>
This turns nandsim into a mini framework to allow
backends implemented in different drivers.
i.e. virtio or usermodelinux.
Signed-off-by: Richard Weinberger <richard@nod.at>
---
drivers/mtd/nand/nandsim.c | 124 +++++++++++++++++---------------------------
include/linux/mtd/nandsim.h | 83 +++++++++++++++++++++++++++++
2 files changed, 130 insertions(+), 77 deletions(-)
create mode 100644 include/linux/mtd/nandsim.h
diff --git a/drivers/mtd/nand/nandsim.c b/drivers/mtd/nand/nandsim.c
index e333c5c..21a6e1a 100644
--- a/drivers/mtd/nand/nandsim.c
+++ b/drivers/mtd/nand/nandsim.c
@@ -36,6 +36,7 @@
#include <linux/mtd/nand.h>
#include <linux/mtd/nand_bch.h>
#include <linux/mtd/partitions.h>
+#include <linux/mtd/nandsim.h>
#include <linux/delay.h>
#include <linux/list.h>
#include <linux/random.h>
@@ -294,42 +295,11 @@ MODULE_PARM_DESC(defaults, "Register a MTD during module load using default val
/* Maximum page cache pages needed to read or write a NAND page to the cache_file */
#define NS_MAX_HELD_PAGES 16
-struct nandsim_params {
- unsigned int access_delay;
- unsigned int program_delay;
- unsigned int erase_delay;
- unsigned int output_cycle;
- unsigned int input_cycle;
- unsigned int bus_width;
- unsigned int do_delays;
- unsigned long *parts;
- unsigned int parts_num;
- char *badblocks;
- char *weakblocks;
- char *weakpages;
- unsigned int bitflips;
- char *gravepages;
- unsigned int overridesize;
- char *cache_file;
- unsigned int bbt;
- unsigned int bch;
- unsigned char *id_bytes;
- struct ns_backend_ops *bops;
-};
-
struct nandsim_debug_info {
struct dentry *dfs_root;
struct dentry *dfs_wear_report;
};
-/*
- * A union to represent flash memory contents and flash buffer.
- */
-union ns_mem {
- u_char *byte; /* for byte access */
- uint16_t *word; /* for 16-bit word access */
-};
-
struct ns_ram_data {
/* The simulated NAND flash pages array */
union ns_mem *pages;
@@ -367,35 +337,8 @@ struct nandsim {
/* Internal buffer of page + OOB size bytes */
union ns_mem buf;
-
- /* NAND flash "geometry" */
- struct {
- uint64_t totsz; /* total flash size, bytes */
- uint32_t secsz; /* flash sector (erase block) size, bytes */
- uint pgsz; /* NAND flash page size, bytes */
- uint oobsz; /* page OOB area size, bytes */
- uint64_t totszoob; /* total flash size including OOB, bytes */
- uint pgszoob; /* page size including OOB , bytes*/
- uint secszoob; /* sector size including OOB, bytes */
- uint pgnum; /* total number of pages */
- uint pgsec; /* number of pages per sector */
- uint secshift; /* bits number in sector size */
- uint pgshift; /* bits number in page size */
- uint pgaddrbytes; /* bytes per page address */
- uint secaddrbytes; /* bytes per sector address */
- uint idbytes; /* the number ID bytes that this chip outputs */
- } geom;
-
- /* NAND flash internal registers */
- struct {
- unsigned command; /* the command register */
- u_char status; /* the status register */
- uint row; /* the page number */
- uint column; /* the offset within page */
- uint count; /* internal counter */
- uint num; /* number of bytes which must be processed */
- uint off; /* fixed page offset */
- } regs;
+ struct nandsim_geom geom;
+ struct nandsim_regs regs;
/* NAND flash lines state */
struct {
@@ -427,14 +370,6 @@ struct nandsim {
struct nandsim_debug_info dbg;
};
-struct ns_backend_ops {
- void (*erase_sector)(struct nandsim *ns);
- int (*prog_page)(struct nandsim *ns, int num);
- void (*read_page)(struct nandsim *ns, int num);
- int (*init)(struct nandsim *ns, struct nandsim_params *nsparam);
- void (*destroy)(struct nandsim *ns);
-};
-
static struct ns_backend_ops ns_ram_bops;
static struct ns_backend_ops ns_cachefile_bops;
@@ -736,6 +671,36 @@ err_close:
return err;
}
+struct nandsim_geom *nandsim_get_geom(struct nandsim *ns)
+{
+ return &ns->geom;
+}
+EXPORT_SYMBOL_GPL(nandsim_get_geom);
+
+struct nandsim_regs *nandsim_get_regs(struct nandsim *ns)
+{
+ return &ns->regs;
+}
+EXPORT_SYMBOL_GPL(nandsim_get_regs);
+
+void nandsim_set_backend_data(struct nandsim *ns, void *data)
+{
+ ns->backend_data = data;
+}
+EXPORT_SYMBOL_GPL(nandsim_set_backend_data);
+
+void *nandsim_get_backend_data(struct nandsim *ns)
+{
+ return ns->backend_data;
+}
+EXPORT_SYMBOL_GPL(nandsim_get_backend_data);
+
+union ns_mem *nandsim_get_buf(struct nandsim *ns)
+{
+ return &ns->buf;
+}
+EXPORT_SYMBOL_GPL(nandsim_get_buf);
+
static void ns_ram_destroy(struct nandsim *ns)
{
struct ns_ram_data *data = ns->backend_data;
@@ -2396,7 +2361,7 @@ static struct miscdevice nandsim_ctrl_cdev = {
.fops = &nansim_ctrl_fops,
};
-static int ns_new_instance(struct nandsim_params *nsparam)
+struct mtd_info *ns_new_instance(struct nandsim_params *nsparam)
{
struct nand_chip *chip;
struct nandsim *nand;
@@ -2406,7 +2371,7 @@ static int ns_new_instance(struct nandsim_params *nsparam)
if (nsparam->bus_width != 8 && nsparam->bus_width != 16) {
NS_ERR("wrong bus width (%d), use only 8 or 16\n", nsparam->bus_width);
- return -EINVAL;
+ return ERR_PTR(-EINVAL);
}
/* Allocate and initialize mtd_info, nand_chip and nandsim structures */
@@ -2414,7 +2379,7 @@ static int ns_new_instance(struct nandsim_params *nsparam)
GFP_KERNEL);
if (!chip) {
NS_ERR("unable to allocate core structures.\n");
- return -ENOMEM;
+ return ERR_PTR(-ENOMEM);
}
mutex_lock(&ns_mtd_mutex);
@@ -2588,7 +2553,7 @@ static int ns_new_instance(struct nandsim_params *nsparam)
if (retval != 0)
goto err_exit;
- return 0;
+ return nsmtd;
err_exit:
free_nandsim(nand);
@@ -2599,10 +2564,11 @@ error:
free_lists(nand);
kfree(chip);
- return retval;
+ return ERR_PTR(retval);
}
+EXPORT_SYMBOL_GPL(ns_new_instance);
-static void ns_destroy_instance(struct mtd_info *nsmtd)
+void ns_destroy_instance(struct mtd_info *nsmtd)
{
struct nand_chip *chip = mtd_to_nand(nsmtd);
struct nandsim *ns = nand_get_controller_data(chip);
@@ -2616,6 +2582,7 @@ static void ns_destroy_instance(struct mtd_info *nsmtd)
kfree(ns->partitions[i].name);
kfree(mtd_to_nand(nsmtd)); /* Free other structures */
}
+EXPORT_SYMBOL_GPL(ns_destroy_instance);
static void ns_destroy_all(void)
{
@@ -2630,7 +2597,7 @@ static void ns_destroy_all(void)
static int __init ns_init_default(void)
{
- int ret;
+ struct mtd_info *nsmtd;
struct nandsim_params *nsparam = kzalloc(sizeof(*nsparam), GFP_KERNEL);
if (!nsparam)
@@ -2661,10 +2628,13 @@ static int __init ns_init_default(void)
else
nsparam->bops = &ns_cachefile_bops;
- ret = ns_new_instance(nsparam);
+ nsmtd = ns_new_instance(nsparam);
kfree(nsparam);
- return ret;
+ if (IS_ERR(nsmtd))
+ return PTR_ERR(nsmtd);
+
+ return 0;
}
static int __init ns_init_module(void)
diff --git a/include/linux/mtd/nandsim.h b/include/linux/mtd/nandsim.h
new file mode 100644
index 0000000..2d596ad
--- /dev/null
+++ b/include/linux/mtd/nandsim.h
@@ -0,0 +1,83 @@
+#ifndef __LINUX_NANDSIM_H__
+#define __LINUX_NANDSIM_H__
+
+#include <linux/mtd/mtd.h>
+
+struct nandsim_params {
+ unsigned int access_delay;
+ unsigned int program_delay;
+ unsigned int erase_delay;
+ unsigned int output_cycle;
+ unsigned int input_cycle;
+ unsigned int bus_width;
+ unsigned int do_delays;
+ unsigned long *parts;
+ unsigned int parts_num;
+ char *badblocks;
+ char *weakblocks;
+ char *weakpages;
+ unsigned int bitflips;
+ char *gravepages;
+ unsigned int overridesize;
+ char *cache_file;
+ unsigned int bbt;
+ unsigned int bch;
+ unsigned char *id_bytes;
+ struct ns_backend_ops *bops;
+};
+
+/* NAND flash "geometry" */
+struct nandsim_geom {
+ uint64_t totsz; /* total flash size, bytes */
+ uint32_t secsz; /* flash sector (erase block) size, bytes */
+ uint pgsz; /* NAND flash page size, bytes */
+ uint oobsz; /* page OOB area size, bytes */
+ uint64_t totszoob; /* total flash size including OOB, bytes */
+ uint pgszoob; /* page size including OOB , bytes*/
+ uint secszoob; /* sector size including OOB, bytes */
+ uint pgnum; /* total number of pages */
+ uint pgsec; /* number of pages per sector */
+ uint secshift; /* bits number in sector size */
+ uint pgshift; /* bits number in page size */
+ uint pgaddrbytes; /* bytes per page address */
+ uint secaddrbytes; /* bytes per sector address */
+ uint idbytes; /* the number ID bytes that this chip outputs */
+};
+
+/* NAND flash internal registers */
+struct nandsim_regs {
+ unsigned command; /* the command register */
+ u_char status; /* the status register */
+ uint row; /* the page number */
+ uint column; /* the offset within page */
+ uint count; /* internal counter */
+ uint num; /* number of bytes which must be processed */
+ uint off; /* fixed page offset */
+};
+
+/*
+ * A union to represent flash memory contents and flash buffer.
+ */
+union ns_mem {
+ u_char *byte; /* for byte access */
+ uint16_t *word; /* for 16-bit word access */
+};
+
+struct nandsim;
+struct ns_backend_ops {
+ void (*erase_sector)(struct nandsim *ns);
+ int (*prog_page)(struct nandsim *ns, int num);
+ void (*read_page)(struct nandsim *ns, int num);
+ int (*init)(struct nandsim *ns, struct nandsim_params *nsparam);
+ void (*destroy)(struct nandsim *ns);
+};
+
+struct mtd_info *ns_new_instance(struct nandsim_params *nsparam);
+void ns_destroy_instance(struct mtd_info *nsmtd);
+struct nandsim_geom *nandsim_get_geom(struct nandsim *ns);
+struct nandsim_regs *nandsim_get_regs(struct nandsim *ns);
+void nandsim_set_backend_data(struct nandsim *ns, void *data);
+void *nandsim_get_backend_data(struct nandsim *ns);
+union ns_mem *nandsim_get_buf(struct nandsim *ns);
+
+#endif /* __LINUX_NANDSIM_H__ */
--
2.8.3
[toc] | [prev] | [next] | [standalone]
| From | Daniel Walter <dwalter@sigma-star.at> |
|---|---|
| Date | 2016-08-31 09:40 +0200 |
| Subject | [PATCH 46/46] mtd/nandsim: Add ioctl for info |
| Message-ID | <sc8hQ-7T2-59@gated-at.bofh.it> |
| In reply to | #1473080 |
Add a ioctl() call for nandsim information.
This information includes, nand id, backend type
and path to the file if the file backend is used
Signed-off-by: Daniel Walter <dwalter@sigma-star.at>
---
drivers/mtd/nand/nandsim.c | 65 +++++++++++++++++++++++++++++++++++++++++
include/uapi/mtd/nandsim-user.h | 11 +++++++
2 files changed, 76 insertions(+)
diff --git a/drivers/mtd/nand/nandsim.c b/drivers/mtd/nand/nandsim.c
index b50568f..e544d94 100644
--- a/drivers/mtd/nand/nandsim.c
+++ b/drivers/mtd/nand/nandsim.c
@@ -2893,6 +2893,56 @@ out:
return ret;
}
+static void ns_put_device(struct mtd_info *);
+static int ns_get_device(struct mtd_info *);
+
+static int ns_ctrl_info_instance(struct ns_info_instance_req *req)
+{
+ struct mtd_info *nsmtd;
+ int id = req->id, ret = 0;
+ struct nand_chip *chip;
+ struct nandsim *ns;
+ struct ns_file_data *file_data;
+ char buf[NANDSIM_FILENAME_SIZE];
+ char *tmp;
+
+ if (id < 0 || id >= NANDSIM_MAX_DEVICES)
+ return -EINVAL;
+
+ mutex_lock(&ns_mtd_mutex);
+ nsmtd = ns_mtds[id];
+ if (nsmtd) {
+ ret = ns_get_device(nsmtd);
+ if (ret)
+ goto out;
+ chip = mtd_to_nand(nsmtd);
+ ns = nand_get_controller_data(chip);
+ req->no_oob = ns->no_oob;
+ memcpy(req->id_bytes, ns->ids, 8);
+ req->parts_num = ns->nbparts;
+ if (ns->bops == &ns_cachefile_bops) {
+ req->backend = NANDSIM_BACKEND_CACHEFILE;
+ } else if (ns->bops == &ns_file_bops) {
+ req->backend = NANDSIM_BACKEND_FILE;
+ file_data = ns->backend_data;
+ tmp = d_path(&file_data->file->f_path, buf, NANDSIM_FILENAME_SIZE);
+ memcpy(req->filename, tmp, NANDSIM_FILENAME_SIZE);
+ } else if (ns->bops == &ns_ram_bops) {
+ req->backend = NANDSIM_BACKEND_RAM;
+ } else {
+ req->backend = -1;
+ }
+
+ ns_put_device(nsmtd);
+ } else {
+ ret = -EINVAL;
+ }
+out:
+ mutex_unlock(&ns_mtd_mutex);
+ return ret;
+
+}
+
static long ns_ctrl_ioctl(struct file *file, unsigned int cmd,
unsigned long arg)
{
@@ -2931,6 +2981,21 @@ static long ns_ctrl_ioctl(struct file *file, unsigned int cmd,
ret = ns_ctrl_destroy_instance(&req);
break;
}
+ case NANDSIM_IOC_INFO_INSTANCE:
+ {
+ struct ns_info_instance_req req;
+
+ ret = copy_from_user(&req, argp, sizeof(struct ns_info_instance_req));
+ if (ret) {
+ ret = -EFAULT;
+ goto out;
+ }
+ ret = ns_ctrl_info_instance(&req);
+ if (ret)
+ goto out;
+ ret = copy_to_user(argp, &req, sizeof(struct ns_info_instance_req));
+ break;
+ }
default:
ret = -ENOTTY;
diff --git a/include/uapi/mtd/nandsim-user.h b/include/uapi/mtd/nandsim-user.h
index 14ab42a..2351124 100644
--- a/include/uapi/mtd/nandsim-user.h
+++ b/include/uapi/mtd/nandsim-user.h
@@ -7,9 +7,11 @@
#define NANDSIM_IOC_NEW_INSTANCE _IOW(NANDSIM_IOC_MAGIC, 0, struct ns_new_instance_req)
#define NANDSIM_IOC_DESTROY_INSTANCE _IOW(NANDSIM_IOC_MAGIC, 1, struct ns_destroy_instance_req)
+#define NANDSIM_IOC_INFO_INSTANCE _IOW(NANDSIM_IOC_MAGIC, 2, struct ns_info_instance_req)
#define NANDSIM_MAX_DEVICES 32
#define NANDSIM_MAX_PARTS 32
+#define NANDSIM_FILENAME_SIZE 64
enum ns_backend_type {
NANDSIM_BACKEND_RAM = 0,
@@ -99,4 +101,13 @@ struct ns_destroy_instance_req {
__s8 padding[7];
} __packed;
+struct ns_info_instance_req {
+ __s8 id;
+ __s8 no_oob;
+ __s8 id_bytes[8];
+ __s8 parts_num;
+ __s8 backend;
+ __u8 filename[NANDSIM_FILENAME_SIZE];
+} __packed;
+
#endif /* __NANDSIM_USER_H__ */
--
2.8.3
[toc] | [prev] | [next] | [standalone]
| From | Daniel Walter <dwalter@sigma-star.at> |
|---|---|
| Date | 2016-08-31 09:40 +0200 |
| Subject | [PATCH 36/46] mtd: nandsim: Cleanup constants |
| Message-ID | <sc8hQ-7T2-53@gated-at.bofh.it> |
| In reply to | #1473080 |
From: Richard Weinberger <richard@nod.at>
Rename CONFIG_NANDSIM_* to NANDSIM_* since these
constants are not exposed to kconfig.
Signed-off-by: Richard Weinberger <richard@nod.at>
---
drivers/mtd/nand/nandsim.c | 74 ++++++++++++++++------------------------------
1 file changed, 25 insertions(+), 49 deletions(-)
diff --git a/drivers/mtd/nand/nandsim.c b/drivers/mtd/nand/nandsim.c
index 8bc8015..0176271 100644
--- a/drivers/mtd/nand/nandsim.c
+++ b/drivers/mtd/nand/nandsim.c
@@ -54,50 +54,26 @@
#include <linux/mutex.h>
#include <linux/file.h>
-/* Default simulator parameters values */
-#if !defined(CONFIG_NANDSIM_FIRST_ID_BYTE) || \
- !defined(CONFIG_NANDSIM_SECOND_ID_BYTE) || \
- !defined(CONFIG_NANDSIM_THIRD_ID_BYTE) || \
- !defined(CONFIG_NANDSIM_FOURTH_ID_BYTE)
-#define CONFIG_NANDSIM_FIRST_ID_BYTE 0x98
-#define CONFIG_NANDSIM_SECOND_ID_BYTE 0x39
-#define CONFIG_NANDSIM_THIRD_ID_BYTE 0xFF /* No byte */
-#define CONFIG_NANDSIM_FOURTH_ID_BYTE 0xFF /* No byte */
-#endif
-
-#ifndef CONFIG_NANDSIM_ACCESS_DELAY
-#define CONFIG_NANDSIM_ACCESS_DELAY 25
-#endif
-#ifndef CONFIG_NANDSIM_PROGRAMM_DELAY
-#define CONFIG_NANDSIM_PROGRAMM_DELAY 200
-#endif
-#ifndef CONFIG_NANDSIM_ERASE_DELAY
-#define CONFIG_NANDSIM_ERASE_DELAY 2
-#endif
-#ifndef CONFIG_NANDSIM_OUTPUT_CYCLE
-#define CONFIG_NANDSIM_OUTPUT_CYCLE 40
-#endif
-#ifndef CONFIG_NANDSIM_INPUT_CYCLE
-#define CONFIG_NANDSIM_INPUT_CYCLE 50
-#endif
-#ifndef CONFIG_NANDSIM_BUS_WIDTH
-#define CONFIG_NANDSIM_BUS_WIDTH 8
-#endif
-#ifndef CONFIG_NANDSIM_DO_DELAYS
-#define CONFIG_NANDSIM_DO_DELAYS 0
-#endif
-#ifndef CONFIG_NANDSIM_MAX_PARTS
-#define CONFIG_NANDSIM_MAX_PARTS 32
-#endif
-
-static uint access_delay = CONFIG_NANDSIM_ACCESS_DELAY;
-static uint programm_delay = CONFIG_NANDSIM_PROGRAMM_DELAY;
-static uint erase_delay = CONFIG_NANDSIM_ERASE_DELAY;
-static uint output_cycle = CONFIG_NANDSIM_OUTPUT_CYCLE;
-static uint input_cycle = CONFIG_NANDSIM_INPUT_CYCLE;
-static uint bus_width = CONFIG_NANDSIM_BUS_WIDTH;
-static uint do_delays = CONFIG_NANDSIM_DO_DELAYS;
-static unsigned long parts[CONFIG_NANDSIM_MAX_PARTS];
+#define NANDSIM_FIRST_ID_BYTE 0x98
+#define NANDSIM_SECOND_ID_BYTE 0x39
+#define NANDSIM_THIRD_ID_BYTE 0xFF /* No byte */
+#define NANDSIM_FOURTH_ID_BYTE 0xFF /* No byte */
+#define NANDSIM_ACCESS_DELAY 25
+#define NANDSIM_PROGRAMM_DELAY 200
+#define NANDSIM_ERASE_DELAY 2
+#define NANDSIM_OUTPUT_CYCLE 40
+#define NANDSIM_INPUT_CYCLE 50
+#define NANDSIM_BUS_WIDTH 8
+#define NANDSIM_DO_DELAYS 0
+
+static uint access_delay = NANDSIM_ACCESS_DELAY;
+static uint programm_delay = NANDSIM_PROGRAMM_DELAY;
+static uint erase_delay = NANDSIM_ERASE_DELAY;
+static uint output_cycle = NANDSIM_OUTPUT_CYCLE;
+static uint input_cycle = NANDSIM_INPUT_CYCLE;
+static uint bus_width = NANDSIM_BUS_WIDTH;
+static uint do_delays = NANDSIM_DO_DELAYS;
+static unsigned long parts[NANDSIM_MAX_PARTS];
static unsigned int parts_num;
static char *badblocks = NULL;
static char *weakblocks = NULL;
@@ -109,10 +85,10 @@ static char *cache_file = NULL;
static unsigned int bbt;
static unsigned int bch;
static u_char id_bytes[8] = {
- [0] = CONFIG_NANDSIM_FIRST_ID_BYTE,
- [1] = CONFIG_NANDSIM_SECOND_ID_BYTE,
- [2] = CONFIG_NANDSIM_THIRD_ID_BYTE,
- [3] = CONFIG_NANDSIM_FOURTH_ID_BYTE,
+ [0] = NANDSIM_FIRST_ID_BYTE,
+ [1] = NANDSIM_SECOND_ID_BYTE,
+ [2] = NANDSIM_THIRD_ID_BYTE,
+ [3] = NANDSIM_FOURTH_ID_BYTE,
[4 ... 7] = 0xFF,
};
static bool defaults = true;
@@ -304,8 +280,8 @@ struct nandsim {
unsigned int index;
unsigned int refcnt;
spinlock_t refcnt_lock;
- struct mtd_partition partitions[CONFIG_NANDSIM_MAX_PARTS];
bool destroying;
+ struct mtd_partition partitions[NANDSIM_MAX_PARTS];
unsigned int nbparts;
uint busw; /* flash chip bus width (8 or 16) */
--
2.8.3
[toc] | [prev] | [next] | [standalone]
| From | Daniel Walter <dwalter@sigma-star.at> |
|---|---|
| Date | 2016-08-31 09:40 +0200 |
| Subject | [PATCH 42/46] mtd: nandsim: Don't printk on ENOMEM |
| Message-ID | <sc8hR-7T2-61@gated-at.bofh.it> |
| In reply to | #1473080 |
From: Richard Weinberger <richard@nod.at>
Memory allocation failures are tabu, we don't talk
about them.
Signed-off-by: Richard Weinberger <richard@nod.at>
---
drivers/mtd/nand/nandsim.c | 37 +++++++++----------------------------
1 file changed, 9 insertions(+), 28 deletions(-)
diff --git a/drivers/mtd/nand/nandsim.c b/drivers/mtd/nand/nandsim.c
index 0905451..34b0c24 100644
--- a/drivers/mtd/nand/nandsim.c
+++ b/drivers/mtd/nand/nandsim.c
@@ -579,7 +579,6 @@ static int ns_ram_init(struct nandsim *ns, struct nandsim_params *nsparam)
data->pages = vmalloc(ns->geom.pgnum * sizeof(union ns_mem));
if (!data->pages) {
kfree(data);
- pr_err("unable to allocate page array\n");
return -ENOMEM;
}
for (i = 0; i < ns->geom.pgnum; i++) {
@@ -591,7 +590,6 @@ static int ns_ram_init(struct nandsim *ns, struct nandsim_params *nsparam)
if (!data->nand_pages_slab) {
vfree(data->pages);
kfree(data);
- pr_err("unable to create kmem_cache\n");
return -ENOMEM;
}
@@ -667,13 +665,11 @@ static int ns_cachefile_init(struct nandsim *ns, struct nandsim_params *nsparam)
data->pages_written = vzalloc(BITS_TO_LONGS(ns->geom.pgnum) *
sizeof(unsigned long));
if (!data->pages_written) {
- pr_err("unable to allocate pages written array\n");
err = -ENOMEM;
goto err_close;
}
data->file_buf = kmalloc(ns->geom.pgszoob, GFP_KERNEL);
if (!data->file_buf) {
- pr_err("unable to allocate file buf\n");
err = -ENOMEM;
goto err_free;
}
@@ -710,7 +706,6 @@ static int ns_file_init(struct nandsim *ns, struct nandsim_params *nsparam)
data->file_buf = kmalloc(ns->geom.pgszoob, GFP_KERNEL);
if (!data->file_buf) {
- pr_err("unable to allocate file buf\n");
ret = -ENOMEM;
goto out_put;
}
@@ -881,7 +876,6 @@ static int init_nandsim(struct mtd_info *mtd, struct nandsim_params *nsparam)
}
ns->partitions[i].name = get_partition_name(ns, i);
if (!ns->partitions[i].name) {
- pr_err("unable to allocate memory.\n");
ret = -ENOMEM;
goto err_names;
}
@@ -899,7 +893,6 @@ static int init_nandsim(struct mtd_info *mtd, struct nandsim_params *nsparam)
}
ns->partitions[i].name = get_partition_name(ns, i);
if (!ns->partitions[i].name) {
- pr_err("unable to allocate memory.\n");
ret = -ENOMEM;
goto err_names;
}
@@ -933,8 +926,6 @@ static int init_nandsim(struct mtd_info *mtd, struct nandsim_params *nsparam)
/* Allocate / initialize the internal buffer */
ns->buf.byte = kmalloc(ns->geom.pgszoob, GFP_KERNEL);
if (!ns->buf.byte) {
- pr_err("unable to allocate %u bytes for the internal buffer\n",
- ns->geom.pgszoob);
ret = -ENOMEM;
goto err_buf;
}
@@ -1057,7 +1048,6 @@ static int parse_weakblocks(struct nandsim_params *nsparam,
w += 1;
wb = kzalloc(sizeof(*wb), GFP_KERNEL);
if (!wb) {
- pr_err("unable to allocate memory.\n");
return -ENOMEM;
}
wb->erase_block_no = erase_block_no;
@@ -1114,10 +1104,9 @@ static int parse_weakpages(struct nandsim_params *nsparam,
if (*w == ',')
w += 1;
wp = kzalloc(sizeof(*wp), GFP_KERNEL);
- if (!wp) {
- pr_err("unable to allocate memory.\n");
+ if (!wp)
return -ENOMEM;
- }
+
wp->page_no = page_no;
wp->max_writes = max_writes;
list_add(&wp->list, nsparam->weak_pages);
@@ -1171,10 +1160,9 @@ static int parse_gravepages(struct nandsim_params *nsparam, unsigned char *grave
if (*g == ',')
g += 1;
gp = kzalloc(sizeof(*gp), GFP_KERNEL);
- if (!gp) {
- pr_err("unable to allocate memory.\n");
+ if (!gp)
return -ENOMEM;
- }
+
gp->page_no = page_no;
gp->max_reads = max_reads;
list_add(&gp->list, nsparam->grave_pages);
@@ -1236,15 +1224,11 @@ static int setup_wear_reporting(struct mtd_info *mtd)
ns->wear_eb_count = div_u64(mtd->size, mtd->erasesize);
mem = ns->wear_eb_count * sizeof(unsigned long);
- if (mem / sizeof(unsigned long) != ns->wear_eb_count) {
- pr_err("Too many erase blocks for wear reporting\n");
+ if (mem / sizeof(unsigned long) != ns->wear_eb_count)
return -ENOMEM;
- }
ns->erase_block_wear = kzalloc(mem, GFP_KERNEL);
- if (!ns->erase_block_wear) {
- pr_err("Too many erase blocks for wear reporting\n");
+ if (!ns->erase_block_wear)
return -ENOMEM;
- }
return 0;
}
@@ -1886,10 +1870,9 @@ static int ns_ram_prog_page(struct nandsim *ns, int num)
* again and deadlocks. This was seen in practice.
*/
mypage->byte = kmem_cache_alloc(data->nand_pages_slab, GFP_NOFS);
- if (mypage->byte == NULL) {
- pr_err("error allocating memory for page %d\n", ns->regs.row);
+ if (mypage->byte == NULL)
return -1;
- }
+
memset(mypage->byte, 0xFF, ns->geom.pgszoob);
}
@@ -2990,10 +2973,8 @@ struct mtd_info *ns_new_instance(struct nandsim_params *nsparam)
/* Allocate and initialize mtd_info, nand_chip and nandsim structures */
chip = kzalloc(sizeof(struct nand_chip) + sizeof(struct nandsim),
GFP_KERNEL);
- if (!chip) {
- pr_err("unable to allocate core structures.\n");
+ if (!chip)
return ERR_PTR(-ENOMEM);
- }
mutex_lock(&ns_mtd_mutex);
for (i = 0; i < NANDSIM_MAX_DEVICES; i++) {
--
2.8.3
[toc] | [prev] | [next] | [standalone]
| From | Daniel Walter <dwalter@sigma-star.at> |
|---|---|
| Date | 2016-08-31 09:40 +0200 |
| Subject | [PATCH 19/46] mtd: nandsim: UAPI v1 |
| Message-ID | <sc8hR-7T2-67@gated-at.bofh.it> |
| In reply to | #1473080 |
From: Richard Weinberger <richard@nod.at>
expose UAPI for nandsim
Signed-off-by: Richard Weinberger <richard@nod.at>
---
include/uapi/mtd/nandsim-user.h | 102 ++++++++++++++++++++++++++++++++++++++++
1 file changed, 102 insertions(+)
create mode 100644 include/uapi/mtd/nandsim-user.h
diff --git a/include/uapi/mtd/nandsim-user.h b/include/uapi/mtd/nandsim-user.h
new file mode 100644
index 0000000..14ab42a
--- /dev/null
+++ b/include/uapi/mtd/nandsim-user.h
@@ -0,0 +1,102 @@
+#ifndef __NANDSIM_USER_H__
+#define __NANDSIM_USER_H__
+
+#include <linux/types.h>
+
+#define NANDSIM_IOC_MAGIC 'n'
+
+#define NANDSIM_IOC_NEW_INSTANCE _IOW(NANDSIM_IOC_MAGIC, 0, struct ns_new_instance_req)
+#define NANDSIM_IOC_DESTROY_INSTANCE _IOW(NANDSIM_IOC_MAGIC, 1, struct ns_destroy_instance_req)
+
+#define NANDSIM_MAX_DEVICES 32
+#define NANDSIM_MAX_PARTS 32
+
+enum ns_backend_type {
+ NANDSIM_BACKEND_RAM = 0,
+ NANDSIM_BACKEND_CACHEFILE = 1,
+ NANDSIM_BACKEND_FILE = 2,
+ NANDSIM_BACKEND_MAX,
+};
+
+/**
+ * struct ns_new_instance_req - Create a new nandsim instance.
+ *
+ * @id_bytes: NAND ID of the simulated NAND chip
+ * @bus_width: bus width to emulate, either 8 or 16
+ * @bbt_mode: bad block table mode, 0 OOB, 1 BBT with marker in OOB,
+ * 2 BBT with marker in data area
+ * @no_oob: backing file contains no OOB data
+ * @bch_strength: instead of hamming ECC use BCH with given strength
+ * @parts_num: number of MTD partitions to create
+ * @parts: partition sizes in physical erase blocks, used then @parts_num > 0
+ * @backend: backend type, see @ns_backend_type
+ * @file_fd: file describtor of backend, only for @NANDSIM_BACKEND_CACHEFILE
+ * and @NANDSIM_BACKEND_FILE.
+ * @bitflips: maximum number of random bit flips per page
+ * @overridesize: specifies the NAND size overriding the ID bytes
+ * @access_delay: initial page access delay (microseconds)
+ * @program_delay: page programm delay (microseconds)
+ * @erase_delay: sector erase delay (milliseconds)
+ * @output_cycle: word output, from flash, time (nanoseconds)
+ * @input_cycle: word input, to flash, time (nanoseconds)
+ * @simelem_num: number of simulation elements appened to this
+ * data structure. see @ns_simelement_prop
+ *
+ * This struct is used with the @NANDSIM_IOC_NEW_INSTANCE ioctl command.
+ * It creates a new nandsim instance from the given parameter.
+ * The ioctl command returns in case of success the nandsim id of the new
+ * instance, in case of error a negative value.
+ *
+ * Not all fields in the struct have to be filled, if nandsim should
+ * use a default ignore the value, fill with 0.
+ * The only mandatory fields are @id_bytes and @bus_width.
+ * When @no_oob is non-zero @bch_strength cannot be used since
+ * @no_oob implies that no ECC is used.
+ */
+struct ns_new_instance_req {
+ __s8 id_bytes[8];
+
+ __s8 bus_width;
+ __s8 bbt_mode;
+ __s8 no_oob;
+ __s32 bch_strength;
+
+ __s8 parts_num;
+ __s32 parts[NANDSIM_MAX_PARTS];
+
+ __s8 backend;
+ __s32 file_fd;
+
+ __s32 bitflips;
+ __s32 overridesize;
+ __s32 access_delay;
+ __s32 program_delay;
+ __s32 erase_delay;
+ __s32 output_cycle;
+ __s32 input_cycle;
+
+ __s32 padding[4];
+
+ __s32 simelem_num;
+} __packed;
+
+enum {
+ NANDSIM_SIMELEM_BADBLOCK = 0,
+ NANDSIM_SIMELEM_WEAKBLOCK,
+ NANDSIM_SIMELEM_WEAKPAGE,
+ NANDSIM_SIMELEM_GRAVEPAGE,
+};
+
+struct ns_simelement_prop {
+ __s8 elem_type;
+ __s32 elem_id;
+ __s32 elem_attr;
+ __s8 padding[7];
+} __packed;
+
+struct ns_destroy_instance_req {
+ __s8 id;
+ __s8 padding[7];
+} __packed;
+
+#endif /* __NANDSIM_USER_H__ */
--
2.8.3
[toc] | [prev] | [next] | [standalone]
| From | Daniel Walter <dwalter@sigma-star.at> |
|---|---|
| Date | 2016-08-31 09:40 +0200 |
| Subject | [PATCH 20/46] mtd: nandsim: Implement preliminary constructor function |
| Message-ID | <sc8hR-7T2-73@gated-at.bofh.it> |
| In reply to | #1473080 |
From: Richard Weinberger <richard@nod.at>
This function will be used later by the ioctl() interface
for creating new nandsim instances.
Signed-off-by: Richard Weinberger <richard@nod.at>
---
drivers/mtd/nand/nandsim.c | 41 ++++++++++++++++++++++++++++++++++++++++-
include/linux/mtd/nandsim.h | 3 ++-
2 files changed, 42 insertions(+), 2 deletions(-)
diff --git a/drivers/mtd/nand/nandsim.c b/drivers/mtd/nand/nandsim.c
index 2e3c08e..344f5c4 100644
--- a/drivers/mtd/nand/nandsim.c
+++ b/drivers/mtd/nand/nandsim.c
@@ -2470,6 +2470,45 @@ static void ns_nand_read_buf(struct mtd_info *mtd, u_char *buf, int len)
return;
}
+static int ns_ctrl_new_instance(struct ns_new_instance_req *req)
+{
+ struct mtd_info *nsmtd;
+ struct nand_chip *chip;
+ struct nandsim *ns;
+ struct nandsim_params *nsparam = kzalloc(sizeof(*nsparam), GFP_KERNEL);
+
+ if (!nsparam)
+ return -ENOMEM;
+
+ memcpy(nsparam->id_bytes, req->id_bytes, sizeof(nsparam->id_bytes));
+ nsparam->bus_width = req->bus_width;
+ nsparam->file_fd = req->file_fd;
+
+ switch (req->backend) {
+ case NANDSIM_BACKEND_RAM:
+ nsparam->bops = &ns_ram_bops;
+ break;
+ case NANDSIM_BACKEND_FILE:
+ nsparam->bops = &ns_file_bops;
+ break;
+
+ default:
+ kfree(nsparam);
+ return -EINVAL;
+ }
+
+ nsmtd = ns_new_instance(nsparam);
+ kfree(nsparam);
+
+ if (IS_ERR(nsmtd))
+ return PTR_ERR(nsmtd);
+
+ chip = mtd_to_nand(nsmtd);
+ ns = nand_get_controller_data(chip);
+
+ return ns->index;
+}
+
static long ns_ctrl_ioctl(struct file *file, unsigned int cmd,
unsigned long arg)
{
@@ -2764,7 +2803,7 @@ static int __init ns_init_default(void)
nsparam->cache_file = cache_file;
nsparam->bbt = bbt;
nsparam->bch = bch;
- nsparam->id_bytes = id_bytes;
+ memcpy(nsparam->id_bytes, id_bytes, sizeof(nsparam->id_bytes));
if (!nsparam->cache_file)
nsparam->bops = &ns_ram_bops;
diff --git a/include/linux/mtd/nandsim.h b/include/linux/mtd/nandsim.h
index e3d2c9f..6e3b4a2 100644
--- a/include/linux/mtd/nandsim.h
+++ b/include/linux/mtd/nandsim.h
@@ -2,6 +2,7 @@
#define __LINUX_NANDSIM_H__
#include <linux/mtd/mtd.h>
+#include <mtd/nandsim-user.h>
struct nandsim_params {
unsigned int access_delay;
@@ -22,7 +23,7 @@ struct nandsim_params {
char *cache_file;
unsigned int bbt;
unsigned int bch;
- unsigned char *id_bytes;
+ unsigned char id_bytes[8];
unsigned int file_fd;
struct ns_backend_ops *bops;
};
--
2.8.3
[toc] | [prev] | [next] | [standalone]
| From | Daniel Walter <dwalter@sigma-star.at> |
|---|---|
| Date | 2016-08-31 09:40 +0200 |
| Subject | [PATCH 12/46] mtd: nandsim: Make debugfs logic multi instance capable |
| Message-ID | <sc8hR-7T2-71@gated-at.bofh.it> |
| In reply to | #1473080 |
From: Richard Weinberger <richard@nod.at>
Instead of creating our files in <debugfs>/nandsim/,
create one directory per instance.
Signed-off-by: Richard Weinberger <richard@nod.at>
---
drivers/mtd/nand/nandsim.c | 36 ++++++++++++++++++++++++++++++++++--
1 file changed, 34 insertions(+), 2 deletions(-)
diff --git a/drivers/mtd/nand/nandsim.c b/drivers/mtd/nand/nandsim.c
index ab4859d..057cc7a 100644
--- a/drivers/mtd/nand/nandsim.c
+++ b/drivers/mtd/nand/nandsim.c
@@ -328,6 +328,7 @@ union ns_mem {
* The structure which describes all the internal simulator data.
*/
struct nandsim {
+ unsigned int index;
struct mtd_partition partitions[CONFIG_NANDSIM_MAX_PARTS];
unsigned int nbparts;
@@ -483,6 +484,8 @@ struct grave_page {
/* MTD structure for NAND controller */
static struct mtd_info *ns_mtds[NS_MAX_DEVICES];
+static struct dentry *dfs_root;
+
static inline struct nandsim *chip_to_ns(struct nand_chip *chip)
{
return (struct nandsim *)(chip + 1);
@@ -560,6 +563,23 @@ static const struct file_operations dfs_fops = {
.release = single_release,
};
+static int nandsim_debugfs_init(void)
+{
+ if (!IS_ENABLED(CONFIG_DEBUG_FS))
+ return 0;
+
+ dfs_root = debugfs_create_dir("nandsim", NULL);
+ if (IS_ERR_OR_NULL(dfs_root)) {
+ int err = dfs_root ? -ENODEV : PTR_ERR(dfs_root);
+
+ NS_ERR("cannot create \"nandsim\" debugfs directory, err %d\n",
+ err);
+ return err;
+ }
+
+ return 0;
+}
+
/**
* nandsim_debugfs_create - initialize debugfs
* @dev: nandsim device description object
@@ -572,15 +592,21 @@ static int nandsim_debugfs_create(struct nandsim *dev)
struct nandsim_debug_info *dbg = &dev->dbg;
struct dentry *dent;
int err;
+ char *dirname;
if (!IS_ENABLED(CONFIG_DEBUG_FS))
return 0;
- dent = debugfs_create_dir("nandsim", NULL);
+ dirname = kasprintf(GFP_KERNEL, "nandsim%i", dev->index);
+ if (!dirname)
+ return -ENOMEM;
+
+ dent = debugfs_create_dir(dirname, dfs_root);
+ kfree(dirname);
if (IS_ERR_OR_NULL(dent)) {
int err = dent ? -ENODEV : PTR_ERR(dent);
- NS_ERR("cannot create \"nandsim\" debugfs directory, err %d\n",
+ NS_ERR("cannot create nandsim debugfs sub-directory, err %d\n",
err);
return err;
}
@@ -2336,6 +2362,7 @@ static int ns_new_instance(struct nandsim_params *nsparam)
nsmtd = ns_mtds[0] = nand_to_mtd(chip);
nand = chip_to_ns(chip);
nand_set_controller_data(chip, (void *)nand);
+ nand->index = 0;
INIT_LIST_HEAD(&nand->weak_blocks);
INIT_LIST_HEAD(&nand->grave_pages);
@@ -2557,6 +2584,10 @@ static int __init ns_init_module(void)
{
int ret;
+ ret = nandsim_debugfs_init();
+ if (ret)
+ return ret;
+
ret = ns_init_default();
if (ret)
return ret;
@@ -2569,6 +2600,7 @@ static void __exit ns_cleanup_module(void)
{
ns_cleanup_default();
misc_deregister(&nandsim_ctrl_cdev);
+ debugfs_remove_recursive(dfs_root);
}
module_exit(ns_cleanup_module);
--
2.8.3
[toc] | [prev] | [next] | [standalone]
| From | Daniel Walter <dwalter@sigma-star.at> |
|---|---|
| Date | 2016-08-31 09:40 +0200 |
| Subject | [PATCH 04/46] mtd: Don't unconditionally execute remove notifiers |
| Message-ID | <sc8hQ-7T2-39@gated-at.bofh.it> |
| In reply to | #1473080 |
From: Richard Weinberger <richard@nod.at>
Only call them when we're really removing the MTD.
Reviewed-by: Boris Brezillon <boris.brezillon@free-electrons.com>
Signed-off-by: Richard Weinberger <richard@nod.at>
---
drivers/mtd/mtdcore.c | 11 ++++++-----
1 file changed, 6 insertions(+), 5 deletions(-)
diff --git a/drivers/mtd/mtdcore.c b/drivers/mtd/mtdcore.c
index 36e5fb0..b8205ec 100644
--- a/drivers/mtd/mtdcore.c
+++ b/drivers/mtd/mtdcore.c
@@ -499,16 +499,17 @@ int del_mtd_device(struct mtd_info *mtd)
goto out_error;
}
- /* No need to get a refcount on the module containing
- the notifier, since we hold the mtd_table_mutex */
- list_for_each_entry(not, &mtd_notifiers, list)
- not->remove(mtd);
-
if (mtd->usecount) {
printk(KERN_NOTICE "Removing MTD device #%d (%s) with use count %d\n",
mtd->index, mtd->name, mtd->usecount);
ret = -EBUSY;
} else {
+ /* No need to get a refcount on the module containing
+ * the notifier, since we hold the mtd_table_mutex
+ */
+ list_for_each_entry(not, &mtd_notifiers, list)
+ not->remove(mtd);
+
device_unregister(&mtd->dev);
idr_remove(&mtd_idr, mtd->index);
--
2.8.3
[toc] | [prev] | [next] | [standalone]
| From | Daniel Walter <dwalter@sigma-star.at> |
|---|---|
| Date | 2016-08-31 09:40 +0200 |
| Subject | [PATCH 22/46] mtd: nandsim: Cleanup destroy handlers |
| Message-ID | <sc8hR-7T2-75@gated-at.bofh.it> |
| In reply to | #1473080 |
From: Richard Weinberger <richard@nod.at>
Make sure that we free stuff only after it has been
initialized.
Signed-off-by: Richard Weinberger <richard@nod.at>
---
drivers/mtd/nand/nandsim.c | 10 ++++++++++
1 file changed, 10 insertions(+)
diff --git a/drivers/mtd/nand/nandsim.c b/drivers/mtd/nand/nandsim.c
index f8b9e76..78c3ee4 100644
--- a/drivers/mtd/nand/nandsim.c
+++ b/drivers/mtd/nand/nandsim.c
@@ -770,6 +770,9 @@ static void ns_ram_destroy(struct nandsim *ns)
struct ns_ram_data *data = ns->backend_data;
int i;
+ if (!data)
+ return;
+
for (i = 0; i < ns->geom.pgnum; i++) {
if (data->pages[i].byte)
kmem_cache_free(data->nand_pages_slab,
@@ -784,15 +787,22 @@ static void ns_cachefile_destroy(struct nandsim *ns)
{
struct ns_cachefile_data *data = ns->backend_data;
+ if (!data)
+ return;
+
kfree(data->file_buf);
vfree(data->pages_written);
filp_close(data->cfile, NULL);
+ kfree(data);
}
static void ns_file_destroy(struct nandsim *ns)
{
struct ns_file_data *data = ns->backend_data;
+ if (!data)
+ return;
+
kfree(data->file_buf);
fput(data->file);
kfree(data);
--
2.8.3
[toc] | [prev] | [next] | [standalone]
| From | Daniel Walter <dwalter@sigma-star.at> |
|---|---|
| Date | 2016-08-31 09:40 +0200 |
| Subject | [PATCH 25/46] mtd: nandsim: Print backend name |
| Message-ID | <sc8hR-7T2-77@gated-at.bofh.it> |
| In reply to | #1473080 |
From: Richard Weinberger <richard@nod.at>
...useful to figure what backend is currently in use.
Signed-off-by: Richard Weinberger <richard@nod.at>
---
drivers/mtd/nand/nandsim.c | 4 ++++
include/linux/mtd/nandsim.h | 1 +
2 files changed, 5 insertions(+)
diff --git a/drivers/mtd/nand/nandsim.c b/drivers/mtd/nand/nandsim.c
index 47d8d41..838e5de 100644
--- a/drivers/mtd/nand/nandsim.c
+++ b/drivers/mtd/nand/nandsim.c
@@ -976,6 +976,7 @@ static int init_nandsim(struct mtd_info *mtd, struct nandsim_params *nsparam)
ns->bops = nsparam->bops;
+ NS_INFO("Using backend: %s\n", ns->bops->name);
if ((ret = ns->bops->init(ns, nsparam)) != 0) {
NS_ERR("Unable to initialize simulator backend: %i\n", ret);
return ret;
@@ -1880,6 +1881,7 @@ static struct ns_backend_ops ns_ram_bops = {
.read_page = ns_ram_read_page,
.init = ns_ram_init,
.destroy = ns_ram_destroy,
+ .name = "ram",
};
static struct ns_backend_ops ns_cachefile_bops = {
@@ -1888,6 +1890,7 @@ static struct ns_backend_ops ns_cachefile_bops = {
.read_page = ns_cachefile_read_page,
.init = ns_cachefile_init,
.destroy = ns_cachefile_destroy,
+ .name = "cache_file",
};
static struct ns_backend_ops ns_file_bops = {
@@ -1896,6 +1899,7 @@ static struct ns_backend_ops ns_file_bops = {
.read_page = ns_file_read_page,
.init = ns_file_init,
.destroy = ns_file_destroy,
+ .name = "file",
};
/*
diff --git a/include/linux/mtd/nandsim.h b/include/linux/mtd/nandsim.h
index a0ca0fb..d71a02f 100644
--- a/include/linux/mtd/nandsim.h
+++ b/include/linux/mtd/nandsim.h
@@ -72,6 +72,7 @@ struct ns_backend_ops {
void (*read_page)(struct nandsim *ns, int num);
int (*init)(struct nandsim *ns, struct nandsim_params *nsparam);
void (*destroy)(struct nandsim *ns);
+ char *name;
};
struct mtd_info *ns_new_instance(struct nandsim_params *nsparam);
--
2.8.3
[toc] | [prev] | [next] | [standalone]
| From | Daniel Walter <dwalter@sigma-star.at> |
|---|---|
| Date | 2016-08-31 09:40 +0200 |
| Subject | [PATCH 28/46] mtd: nandsim: Refine exports |
| Message-ID | <sc8hQ-7T2-41@gated-at.bofh.it> |
| In reply to | #1473080 |
From: Richard Weinberger <richard@nod.at>
Keep the file backend logic directly in nandsim such that
other users of only have to implement simple read/write
functions.
Signed-off-by: Richard Weinberger <richard@nod.at>
---
drivers/mtd/nand/nandsim.c | 101 +++++++++++++++++++++++++++++++++-----------
include/linux/mtd/nandsim.h | 33 ++++++---------
2 files changed, 88 insertions(+), 46 deletions(-)
diff --git a/drivers/mtd/nand/nandsim.c b/drivers/mtd/nand/nandsim.c
index f5aa0c4..f2ebf8b 100644
--- a/drivers/mtd/nand/nandsim.c
+++ b/drivers/mtd/nand/nandsim.c
@@ -302,6 +302,14 @@ struct nandsim_debug_info {
struct dentry *dfs_wear_report;
};
+/*
+ * A union to represent flash memory contents and flash buffer.
+ */
+union ns_mem {
+ u_char *byte; /* for byte access */
+ uint16_t *word; /* for 16-bit word access */
+};
+
struct ns_ram_data {
/* The simulated NAND flash pages array */
union ns_mem *pages;
@@ -350,7 +358,17 @@ struct nandsim {
/* Internal buffer of page + OOB size bytes */
union ns_mem buf;
struct nandsim_geom geom;
- struct nandsim_regs regs;
+
+ /* NAND flash internal registers */
+ struct {
+ unsigned int command; /* the command register */
+ u_char status; /* the status register */
+ uint row; /* the page number */
+ uint column; /* the offset within page */
+ uint count; /* internal counter */
+ uint num; /* number of bytes which must be processed */
+ uint off; /* fixed page offset */
+ } regs;
/* NAND flash lines state */
struct {
@@ -773,12 +791,6 @@ struct nandsim_geom *nandsim_get_geom(struct nandsim *ns)
}
EXPORT_SYMBOL_GPL(nandsim_get_geom);
-struct nandsim_regs *nandsim_get_regs(struct nandsim *ns)
-{
- return &ns->regs;
-}
-EXPORT_SYMBOL_GPL(nandsim_get_regs);
-
void nandsim_set_backend_data(struct nandsim *ns, void *data)
{
ns->backend_data = data;
@@ -791,12 +803,6 @@ void *nandsim_get_backend_data(struct nandsim *ns)
}
EXPORT_SYMBOL_GPL(nandsim_get_backend_data);
-union ns_mem *nandsim_get_buf(struct nandsim *ns)
-{
- return &ns->buf;
-}
-EXPORT_SYMBOL_GPL(nandsim_get_buf);
-
static void ns_ram_destroy(struct nandsim *ns)
{
struct ns_ram_data *data = ns->backend_data;
@@ -1706,9 +1712,10 @@ static void ns_cachefile_read_page(struct nandsim *ns, int num)
}
}
-static void ns_file_read_page(struct nandsim *ns, int num)
+void __ns_file_read_page(struct nandsim *ns, int num,
+ int (*read_fn)(struct nandsim *ns, char *addr,
+ unsigned long count, loff_t offset))
{
- struct ns_file_data *data = ns->backend_data;
loff_t pos;
ssize_t tx;
@@ -1734,12 +1741,26 @@ static void ns_file_read_page(struct nandsim *ns, int num)
}
pos = (loff_t)NS_RAW_OFFSET(ns) + ns->regs.off;
- tx = kernel_read(data->file, pos, ns->buf.byte, num);
+ tx = read_fn(ns, ns->buf.byte, num, pos);
if (tx == 0)
memset(ns->buf.byte, 0xff, num);
else if (tx != num)
NS_ERR("read_page: read error for page %d ret %ld\n", ns->regs.row, (long)tx);
}
+EXPORT_SYMBOL_GPL(__ns_file_read_page);
+
+static inline int do_kernel_read(struct nandsim *ns, char *addr,
+ unsigned long count, loff_t offset)
+{
+ struct ns_file_data *data = ns->backend_data;
+
+ return kernel_read(data->file, offset, addr, count);
+}
+
+static void ns_file_read_page(struct nandsim *ns, int num)
+{
+ __ns_file_read_page(ns, num, do_kernel_read);
+}
static void ns_ram_erase_sector(struct nandsim *ns)
{
@@ -1771,24 +1792,42 @@ static void ns_cachefile_erase_sector(struct nandsim *ns)
}
}
-static void ns_file_erase_sector(struct nandsim *ns)
+static inline ssize_t do_kernel_write(struct nandsim *ns, const char *addr,
+ size_t count, loff_t offset)
+{
+ struct ns_file_data *data = ns->backend_data;
+
+ return kernel_write(data->file, addr, count, offset);
+}
+
+
+void __ns_file_erase_sector(struct nandsim *ns, char *file_buf,
+ ssize_t (*write_fn)(struct nandsim *ns, const char *buf,
+ size_t count, loff_t pos))
{
int i;
loff_t pos;
ssize_t tx;
unsigned int pagesz = ns->no_oob ? ns->geom.pgsz : ns->geom.pgszoob;
- struct ns_file_data *data = ns->backend_data;
- memset(data->file_buf, 0xff, pagesz);
+ memset(file_buf, 0xff, pagesz);
for (i = 0; i < ns->geom.pgsec; i++) {
pos = (loff_t)(ns->regs.row + i) * pagesz;
- tx = kernel_write(data->file, data->file_buf, pagesz, pos);
+ tx = write_fn(ns, file_buf, pagesz, pos);
if (tx != pagesz) {
NS_ERR("prog_page: write error for page %d ret %ld\n", ns->regs.row, (long)tx);
}
}
}
+EXPORT_SYMBOL_GPL(__ns_file_erase_sector);
+
+static void ns_file_erase_sector(struct nandsim *ns)
+{
+ struct ns_file_data *data = ns->backend_data;
+
+ __ns_file_erase_sector(ns, data->file_buf, do_kernel_write);
+}
static int ns_ram_prog_page(struct nandsim *ns, int num)
{
@@ -1863,13 +1902,16 @@ static int ns_cachefile_prog_page(struct nandsim *ns, int num)
return 0;
}
-static int ns_file_prog_page(struct nandsim *ns, int num)
+int __ns_file_prog_page(struct nandsim *ns, int num, char *file_buf,
+ int (*read_fn)(struct nandsim *ns, char *addr,
+ unsigned long count, loff_t offset),
+ ssize_t (*write_fn)(struct nandsim *ns, const char *buf,
+ size_t count, loff_t pos))
{
int i;
loff_t off;
ssize_t tx;
u_char *pg_off;
- struct ns_file_data *data = ns->backend_data;
NS_DBG("prog_page: writing page %d\n", ns->regs.row);
@@ -1885,10 +1927,10 @@ static int ns_file_prog_page(struct nandsim *ns, int num)
num -= pg_write_end - ns->geom.pgsz;
}
- pg_off = data->file_buf + ns->regs.column + ns->regs.off;
+ pg_off = file_buf + ns->regs.column + ns->regs.off;
off = (loff_t)NS_RAW_OFFSET(ns) + ns->regs.off;
- tx = kernel_read(data->file, off, pg_off, num);
+ tx = read_fn(ns, pg_off, num, off);
if (tx == 0)
memset(pg_off, 0xff, num);
else if (tx != num) {
@@ -1899,7 +1941,7 @@ static int ns_file_prog_page(struct nandsim *ns, int num)
for (i = 0; i < num; i++)
pg_off[i] &= ns->buf.byte[i];
- tx = kernel_write(data->file, pg_off, num, off);
+ tx = write_fn(ns, pg_off, num, off);
if (tx != num) {
NS_ERR("prog_page: write error for page %d ret %ld\n", ns->regs.row, (long)tx);
return -1;
@@ -1907,6 +1949,15 @@ static int ns_file_prog_page(struct nandsim *ns, int num)
return 0;
}
+EXPORT_SYMBOL_GPL(__ns_file_prog_page);
+
+static int ns_file_prog_page(struct nandsim *ns, int num)
+{
+ struct ns_file_data *data = ns->backend_data;
+
+ return __ns_file_prog_page(ns, num, data->file_buf, do_kernel_read,
+ do_kernel_write);
+}
static struct ns_backend_ops ns_ram_bops = {
.erase_sector = ns_ram_erase_sector,
diff --git a/include/linux/mtd/nandsim.h b/include/linux/mtd/nandsim.h
index 05ac7e3..85d4d7e 100644
--- a/include/linux/mtd/nandsim.h
+++ b/include/linux/mtd/nandsim.h
@@ -47,25 +47,6 @@ struct nandsim_geom {
uint idbytes; /* the number ID bytes that this chip outputs */
};
-/* NAND flash internal registers */
-struct nandsim_regs {
- unsigned command; /* the command register */
- u_char status; /* the status register */
- uint row; /* the page number */
- uint column; /* the offset within page */
- uint count; /* internal counter */
- uint num; /* number of bytes which must be processed */
- uint off; /* fixed page offset */
-};
-
-/*
- * A union to represent flash memory contents and flash buffer.
- */
-union ns_mem {
- u_char *byte; /* for byte access */
- uint16_t *word; /* for 16-bit word access */
-};
-
struct nandsim;
struct ns_backend_ops {
void (*erase_sector)(struct nandsim *ns);
@@ -79,9 +60,19 @@ struct ns_backend_ops {
struct mtd_info *ns_new_instance(struct nandsim_params *nsparam);
int ns_destroy_instance(struct mtd_info *nsmtd);
struct nandsim_geom *nandsim_get_geom(struct nandsim *ns);
-struct nandsim_regs *nandsim_get_regs(struct nandsim *ns);
void nandsim_set_backend_data(struct nandsim *ns, void *data);
void *nandsim_get_backend_data(struct nandsim *ns);
-union ns_mem *nandsim_get_buf(struct nandsim *ns);
+void __ns_file_read_page(struct nandsim *ns, int num,
+ int (*read_fn)(struct nandsim *ns, char *addr,
+ unsigned long count, loff_t offset));
+
+int __ns_file_prog_page(struct nandsim *ns, int num, char *file_buf,
+ int (*read_fn)(struct nandsim *ns, char *addr,
+ unsigned long count, loff_t offset),
+ ssize_t (*write_fn)(struct nandsim *ns, const char *buf,
+ size_t count, loff_t pos));
+void __ns_file_erase_sector(struct nandsim *ns, char *file_buf,
+ ssize_t (*write_fn)(struct nandsim *ns, const char *buf,
+ size_t count, loff_t pos));
#endif /* __LINUX_NANDSIM_H__ */
--
2.8.3
[toc] | [prev] | [next] | [standalone]
| From | Daniel Walter <dwalter@sigma-star.at> |
|---|---|
| Date | 2016-08-31 09:40 +0200 |
| Subject | [PATCH 31/46] mtd: nandsim: Remove NS_RAW_OFFSET_OOB |
| Message-ID | <sc8hQ-7T2-47@gated-at.bofh.it> |
| In reply to | #1473080 |
From: Richard Weinberger <richard@nod.at> This helper macro has no users, kill it. Signed-off-by: Richard Weinberger <richard@nod.at> --- drivers/mtd/nand/nandsim.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/drivers/mtd/nand/nandsim.c b/drivers/mtd/nand/nandsim.c index 02fa039..fcc7441 100644 --- a/drivers/mtd/nand/nandsim.c +++ b/drivers/mtd/nand/nandsim.c @@ -198,9 +198,6 @@ MODULE_PARM_DESC(defaults, "Register a MTD during module load using default val #define NS_RAW_OFFSET(ns) \ (((ns)->regs.row * ((ns)->no_oob ? (ns)->geom.pgsz : (ns)->geom.pgszoob)) + (ns)->regs.column) -/* Calculate the OOB offset in flash RAM image by (row, column) address */ -#define NS_RAW_OFFSET_OOB(ns) (NS_RAW_OFFSET(ns) + ns->geom.pgsz) - /* After a command is input, the simulator goes to one of the following states */ #define STATE_CMD_READ0 0x00000001 /* read data from the beginning of page */ #define STATE_CMD_READ1 0x00000002 /* read data from the second half of page */ -- 2.8.3
[toc] | [prev] | [next] | [standalone]
| From | Daniel Walter <dwalter@sigma-star.at> |
|---|---|
| Date | 2016-08-31 09:40 +0200 |
| Subject | [PATCH 21/46] mtd: nandsim: Implement preliminary destructor function |
| Message-ID | <sc8hQ-7T2-49@gated-at.bofh.it> |
| In reply to | #1473080 |
From: Richard Weinberger <richard@nod.at>
This function will be used via ioctl() to remove nandsim instances.
Signed-off-by: Richard Weinberger <richard@nod.at>
---
drivers/mtd/nand/nandsim.c | 80 +++++++++++++++++++++++++++++++++++++++++++--
include/linux/mtd/nandsim.h | 2 +-
2 files changed, 78 insertions(+), 4 deletions(-)
diff --git a/drivers/mtd/nand/nandsim.c b/drivers/mtd/nand/nandsim.c
index 344f5c4..f8b9e76 100644
--- a/drivers/mtd/nand/nandsim.c
+++ b/drivers/mtd/nand/nandsim.c
@@ -39,6 +39,7 @@
#include <linux/mtd/nandsim.h>
#include <linux/delay.h>
#include <linux/list.h>
+#include <linux/spinlock.h>
#include <linux/random.h>
#include <linux/sched.h>
#include <linux/fs.h>
@@ -328,7 +329,10 @@ struct ns_file_data {
*/
struct nandsim {
unsigned int index;
+ unsigned int refcnt;
+ spinlock_t refcnt_lock;
struct mtd_partition partitions[CONFIG_NANDSIM_MAX_PARTS];
+ bool destroying;
unsigned int nbparts;
uint busw; /* flash chip bus width (8 or 16) */
@@ -2509,6 +2513,41 @@ static int ns_ctrl_new_instance(struct ns_new_instance_req *req)
return ns->index;
}
+static int ns_ctrl_destroy_instance(struct ns_destroy_instance_req *req)
+{
+ struct mtd_info *nsmtd;
+ int id = req->id, ret = 0;
+ struct nand_chip *chip;
+ struct nandsim *ns;
+
+ if (id < 0 || id >= NS_MAX_DEVICES)
+ return -EINVAL;
+
+ mutex_lock(&ns_mtd_mutex);
+ nsmtd = ns_mtds[id];
+ if (nsmtd) {
+ chip = mtd_to_nand(nsmtd);
+ ns = nand_get_controller_data(chip);
+ spin_lock(&ns->refcnt_lock);
+ if (ns->refcnt > 0) {
+ ret = -EBUSY;
+ spin_unlock(&ns->refcnt_lock);
+ goto out;
+ }
+ ns->destroying = true;
+ spin_unlock(&ns->refcnt_lock);
+ ret = ns_destroy_instance(nsmtd);
+ if (ret)
+ goto out;
+ ns_mtds[id] = NULL;
+ }
+
+out:
+ mutex_unlock(&ns_mtd_mutex);
+
+ return ret;
+}
+
static long ns_ctrl_ioctl(struct file *file, unsigned int cmd,
unsigned long arg)
{
@@ -2543,6 +2582,32 @@ static struct miscdevice nandsim_ctrl_cdev = {
.fops = &nansim_ctrl_fops,
};
+static void ns_put_device(struct mtd_info *mtd)
+{
+ struct nand_chip *chip = mtd_to_nand(mtd);
+ struct nandsim *ns = nand_get_controller_data(chip);
+
+ spin_lock(&ns->refcnt_lock);
+ ns->refcnt -= 1;
+ spin_unlock(&ns->refcnt_lock);
+}
+
+static int ns_get_device(struct mtd_info *mtd)
+{
+ int ret = 0;
+ struct nand_chip *chip = mtd_to_nand(mtd);
+ struct nandsim *ns = nand_get_controller_data(chip);
+
+ spin_lock(&ns->refcnt_lock);
+ if (ns->destroying)
+ ret = -EBUSY;
+ else
+ ns->refcnt += 1;
+ spin_unlock(&ns->refcnt_lock);
+
+ return ret;
+}
+
struct mtd_info *ns_new_instance(struct nandsim_params *nsparam)
{
struct nand_chip *chip;
@@ -2587,6 +2652,7 @@ struct mtd_info *ns_new_instance(struct nandsim_params *nsparam)
INIT_LIST_HEAD(&nand->grave_pages);
INIT_LIST_HEAD(&nand->weak_pages);
INIT_LIST_HEAD(&nand->weak_blocks);
+ spin_lock_init(&nand->refcnt_lock);
/*
* Register simulator's callbacks.
@@ -2637,6 +2703,8 @@ struct mtd_info *ns_new_instance(struct nandsim_params *nsparam)
}
nsmtd->owner = THIS_MODULE;
+ nsmtd->_get_device = ns_get_device;
+ nsmtd->_put_device = ns_put_device;
if ((retval = parse_weakblocks(nand, nsparam->weakblocks)) != 0)
goto error;
@@ -2750,11 +2818,15 @@ error:
}
EXPORT_SYMBOL_GPL(ns_new_instance);
-void ns_destroy_instance(struct mtd_info *nsmtd)
+int ns_destroy_instance(struct mtd_info *nsmtd)
{
+ int i, ret;
struct nand_chip *chip = mtd_to_nand(nsmtd);
struct nandsim *ns = nand_get_controller_data(chip);
- int i;
+
+ ret = __nand_release(nsmtd);
+ if (ret)
+ return ret;
nandsim_debugfs_remove(ns);
free_lists(ns);
@@ -2763,6 +2835,8 @@ void ns_destroy_instance(struct mtd_info *nsmtd)
for (i = 0;i < ARRAY_SIZE(ns->partitions); ++i)
kfree(ns->partitions[i].name);
kfree(mtd_to_nand(nsmtd)); /* Free other structures */
+
+ return 0;
}
EXPORT_SYMBOL_GPL(ns_destroy_instance);
@@ -2773,7 +2847,7 @@ static void ns_destroy_all(void)
mutex_lock(&ns_mtd_mutex);
for (i = 0; i < NS_MAX_DEVICES; i++)
if (ns_mtds[i])
- ns_destroy_instance(ns_mtds[i]);
+ WARN_ON(ns_destroy_instance(ns_mtds[i]) != 0);
mutex_unlock(&ns_mtd_mutex);
}
diff --git a/include/linux/mtd/nandsim.h b/include/linux/mtd/nandsim.h
index 6e3b4a2..a0ca0fb 100644
--- a/include/linux/mtd/nandsim.h
+++ b/include/linux/mtd/nandsim.h
@@ -75,7 +75,7 @@ struct ns_backend_ops {
};
struct mtd_info *ns_new_instance(struct nandsim_params *nsparam);
-void ns_destroy_instance(struct mtd_info *nsmtd);
+int ns_destroy_instance(struct mtd_info *nsmtd);
struct nandsim_geom *nandsim_get_geom(struct nandsim *ns);
struct nandsim_regs *nandsim_get_regs(struct nandsim *ns);
void nandsim_set_backend_data(struct nandsim *ns, void *data);
--
2.8.3
[toc] | [prev] | [next] | [standalone]
| From | Daniel Walter <dwalter@sigma-star.at> |
|---|---|
| Date | 2016-08-31 09:40 +0200 |
| Subject | [PATCH 26/46] mtd: nandsim: use the existing output macros |
| Message-ID | <sc8hR-7T2-85@gated-at.bofh.it> |
| In reply to | #1473080 |
From: Mathias Kresin <dev@kresin.me>
Without using the output macros, it isn't possible to suppress these
messages on the console by specifying an appropriate console log level.
Signed-off-by: Mathias Kresin <dev@kresin.me>
Signed-off-by: Richard Weinberger <richard@nod.at>
---
drivers/mtd/nand/nandsim.c | 28 ++++++++++++++--------------
1 file changed, 14 insertions(+), 14 deletions(-)
diff --git a/drivers/mtd/nand/nandsim.c b/drivers/mtd/nand/nandsim.c
index 838e5de..116b1d1 100644
--- a/drivers/mtd/nand/nandsim.c
+++ b/drivers/mtd/nand/nandsim.c
@@ -957,22 +957,22 @@ static int init_nandsim(struct mtd_info *mtd, struct nandsim_params *nsparam)
if (ns->busw == 16)
NS_WARN("16-bit flashes support wasn't tested\n");
- printk("flash size: %llu MiB\n",
+ NS_INFO("flash size: %llu MiB\n",
(unsigned long long)ns->geom.totsz >> 20);
- printk("page size: %u bytes\n", ns->geom.pgsz);
- printk("OOB area size: %u bytes\n", ns->geom.oobsz);
- printk("sector size: %u KiB\n", ns->geom.secsz >> 10);
- printk("pages number: %u\n", ns->geom.pgnum);
- printk("pages per sector: %u\n", ns->geom.pgsec);
- printk("bus width: %u\n", ns->busw);
- printk("bits in sector size: %u\n", ns->geom.secshift);
- printk("bits in page size: %u\n", ns->geom.pgshift);
- printk("bits in OOB size: %u\n", ffs(ns->geom.oobsz) - 1);
- printk("flash size with OOB: %llu KiB\n",
+ NS_INFO("page size: %u bytes\n", ns->geom.pgsz);
+ NS_INFO("OOB area size: %u bytes\n", ns->geom.oobsz);
+ NS_INFO("sector size: %u KiB\n", ns->geom.secsz >> 10);
+ NS_INFO("pages number: %u\n", ns->geom.pgnum);
+ NS_INFO("pages per sector: %u\n", ns->geom.pgsec);
+ NS_INFO("bus width: %u\n", ns->busw);
+ NS_INFO("bits in sector size: %u\n", ns->geom.secshift);
+ NS_INFO("bits in page size: %u\n", ns->geom.pgshift);
+ NS_INFO("bits in OOB size: %u\n", ffs(ns->geom.oobsz) - 1);
+ NS_INFO("flash size with OOB: %llu KiB\n",
(unsigned long long)ns->geom.totszoob >> 10);
- printk("page address bytes: %u\n", ns->geom.pgaddrbytes);
- printk("sector address bytes: %u\n", ns->geom.secaddrbytes);
- printk("options: %#x\n", ns->options);
+ NS_INFO("page address bytes: %u\n", ns->geom.pgaddrbytes);
+ NS_INFO("sector address bytes: %u\n", ns->geom.secaddrbytes);
+ NS_INFO("options: %#x\n", ns->options);
ns->bops = nsparam->bops;
--
2.8.3
[toc] | [prev] | [next] | [standalone]
| From | Daniel Walter <dwalter@sigma-star.at> |
|---|---|
| Date | 2016-08-31 09:40 +0200 |
| Subject | [PATCH 37/46] mtd: nandsim: Turn parts[] into a integer |
| Message-ID | <sc8hR-7T2-89@gated-at.bofh.it> |
| In reply to | #1473080 |
From: Richard Weinberger <richard@nod.at>
The parts array denotes how many erase blocks each partition
has. Therefore a plain integer can also do it.
If someone shows me a NAND with more than 2^32 erase blocks we can
turn it back into a long. ;)
Signed-off-by: Richard Weinberger <richard@nod.at>
---
drivers/mtd/nand/nandsim.c | 4 ++--
include/linux/mtd/nandsim.h | 2 +-
2 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/drivers/mtd/nand/nandsim.c b/drivers/mtd/nand/nandsim.c
index 0176271..584fc72 100644
--- a/drivers/mtd/nand/nandsim.c
+++ b/drivers/mtd/nand/nandsim.c
@@ -73,7 +73,7 @@ static uint output_cycle = NANDSIM_OUTPUT_CYCLE;
static uint input_cycle = NANDSIM_INPUT_CYCLE;
static uint bus_width = NANDSIM_BUS_WIDTH;
static uint do_delays = NANDSIM_DO_DELAYS;
-static unsigned long parts[NANDSIM_MAX_PARTS];
+static unsigned int parts[NANDSIM_MAX_PARTS];
static unsigned int parts_num;
static char *badblocks = NULL;
static char *weakblocks = NULL;
@@ -105,7 +105,7 @@ module_param(output_cycle, uint, 0400);
module_param(input_cycle, uint, 0400);
module_param(bus_width, uint, 0400);
module_param(do_delays, uint, 0400);
-module_param_array(parts, ulong, &parts_num, 0400);
+module_param_array(parts, uint, &parts_num, 0400);
module_param(badblocks, charp, 0400);
module_param(weakblocks, charp, 0400);
module_param(weakpages, charp, 0400);
diff --git a/include/linux/mtd/nandsim.h b/include/linux/mtd/nandsim.h
index 85d4d7e..61ff5dd 100644
--- a/include/linux/mtd/nandsim.h
+++ b/include/linux/mtd/nandsim.h
@@ -12,7 +12,7 @@ struct nandsim_params {
unsigned int input_cycle;
unsigned int bus_width;
unsigned int do_delays;
- unsigned long *parts;
+ unsigned int *parts;
unsigned int parts_num;
char *badblocks;
char *weakblocks;
--
2.8.3
[toc] | [prev] | [next] | [standalone]
| From | Daniel Walter <dwalter@sigma-star.at> |
|---|---|
| Date | 2016-08-31 09:40 +0200 |
| Subject | [PATCH 41/46] mtd: nandsim: Expose support for weakpages/blocks to userspace |
| Message-ID | <sc8hR-7T2-93@gated-at.bofh.it> |
| In reply to | #1473080 |
From: Richard Weinberger <richard@nod.at>
Signed-off-by: Richard Weinberger <richard@nod.at>
---
drivers/mtd/nand/nandsim.c | 338 ++++++++++++++++++++++++++++++++++++--------
include/linux/mtd/nandsim.h | 7 +-
2 files changed, 285 insertions(+), 60 deletions(-)
diff --git a/drivers/mtd/nand/nandsim.c b/drivers/mtd/nand/nandsim.c
index 222b2b8..0905451 100644
--- a/drivers/mtd/nand/nandsim.c
+++ b/drivers/mtd/nand/nandsim.c
@@ -322,9 +322,9 @@ struct nandsim {
struct ns_backend_ops *bops;
void *backend_data;
- struct list_head weak_blocks;
- struct list_head weak_pages;
- struct list_head grave_pages;
+ struct list_head *weak_blocks;
+ struct list_head *weak_pages;
+ struct list_head *grave_pages;
unsigned long *erase_block_wear;
unsigned int wear_eb_count;
@@ -387,6 +387,11 @@ static struct nandsim_operations {
STATE_DATAOUT, STATE_READY}},
};
+struct bad_block {
+ struct list_head list;
+ unsigned int erase_block_no;
+};
+
struct weak_block {
struct list_head list;
unsigned int erase_block_no;
@@ -957,16 +962,46 @@ static void free_nandsim(struct nandsim *ns)
kfree(ns->buf.byte);
}
-static int parse_badblocks(struct nandsim *ns, struct mtd_info *mtd,
+static int process_badblocks(struct nandsim_params *nsparam, struct nandsim *ns)
+{
+ loff_t offset;
+ struct bad_block *bb, *_bb;
+ struct mtd_info *nsmtd = ns_to_mtd(ns);
+
+ if (!nsparam->bad_blocks)
+ return 0;
+
+ list_for_each_entry_safe(bb, _bb, nsparam->bad_blocks, list) {
+ offset = (loff_t)bb->erase_block_no * ns->geom.secsz;
+ if (mtd_block_markbad(nsmtd, offset))
+ pr_err("invalid badblocks: %i:\n", bb->erase_block_no);
+
+ list_del(&bb->list);
+ kfree(bb);
+ }
+
+ kfree(nsparam->bad_blocks);
+ nsparam->bad_blocks = NULL;
+
+ return 0;
+}
+
+static int parse_badblocks(struct nandsim_params *nsparam,
unsigned char *badblocks)
{
char *w;
int zero_ok;
unsigned int erase_block_no;
- loff_t offset;
+ struct bad_block *bb;
+
+ nsparam->bad_blocks = kmalloc(sizeof(struct list_head), GFP_KERNEL);
+ if (!nsparam->bad_blocks)
+ return -ENOMEM;
+ INIT_LIST_HEAD(nsparam->bad_blocks);
if (!badblocks)
return 0;
+
w = badblocks;
do {
zero_ok = (*w == '0' ? 1 : 0);
@@ -975,18 +1010,21 @@ static int parse_badblocks(struct nandsim *ns, struct mtd_info *mtd,
pr_err("invalid badblocks.\n");
return -EINVAL;
}
- offset = (loff_t)erase_block_no * ns->geom.secsz;
- if (mtd_block_markbad(mtd, offset)) {
- pr_err("invalid badblocks.\n");
- return -EINVAL;
- }
+ bb = kzalloc(sizeof(*bb), GFP_KERNEL);
+ if (!bb)
+ return -ENOMEM;
+
+ bb->erase_block_no = erase_block_no;
+ list_add(&bb->list, nsparam->bad_blocks);
+
if (*w == ',')
w += 1;
} while (*w);
return 0;
}
-static int parse_weakblocks(struct nandsim *ns, unsigned char *weakblocks)
+static int parse_weakblocks(struct nandsim_params *nsparam,
+ unsigned char *weakblocks)
{
char *w;
int zero_ok;
@@ -994,8 +1032,14 @@ static int parse_weakblocks(struct nandsim *ns, unsigned char *weakblocks)
unsigned int max_erases;
struct weak_block *wb;
+ nsparam->weak_blocks = kmalloc(sizeof(struct list_head), GFP_KERNEL);
+ if (!nsparam->weak_blocks)
+ return -ENOMEM;
+
+ INIT_LIST_HEAD(nsparam->weak_blocks);
if (!weakblocks)
return 0;
+
w = weakblocks;
do {
zero_ok = (*w == '0' ? 1 : 0);
@@ -1018,7 +1062,7 @@ static int parse_weakblocks(struct nandsim *ns, unsigned char *weakblocks)
}
wb->erase_block_no = erase_block_no;
wb->max_erases = max_erases;
- list_add(&wb->list, &ns->weak_blocks);
+ list_add(&wb->list, nsparam->weak_blocks);
} while (*w);
return 0;
}
@@ -1027,7 +1071,7 @@ static int erase_error(struct nandsim *ns, unsigned int erase_block_no)
{
struct weak_block *wb;
- list_for_each_entry(wb, &ns->weak_blocks, list)
+ list_for_each_entry(wb, ns->weak_blocks, list)
if (wb->erase_block_no == erase_block_no) {
if (wb->erases_done >= wb->max_erases)
return 1;
@@ -1037,7 +1081,8 @@ static int erase_error(struct nandsim *ns, unsigned int erase_block_no)
return 0;
}
-static int parse_weakpages(struct nandsim *ns, unsigned char *weakpages)
+static int parse_weakpages(struct nandsim_params *nsparam,
+ unsigned char *weakpages)
{
char *w;
int zero_ok;
@@ -1045,8 +1090,14 @@ static int parse_weakpages(struct nandsim *ns, unsigned char *weakpages)
unsigned int max_writes;
struct weak_page *wp;
+ nsparam->weak_pages = kmalloc(sizeof(struct list_head), GFP_KERNEL);
+ if (!nsparam->weak_pages)
+ return -ENOMEM;
+
+ INIT_LIST_HEAD(nsparam->weak_pages);
if (!weakpages)
return 0;
+
w = weakpages;
do {
zero_ok = (*w == '0' ? 1 : 0);
@@ -1069,7 +1120,7 @@ static int parse_weakpages(struct nandsim *ns, unsigned char *weakpages)
}
wp->page_no = page_no;
wp->max_writes = max_writes;
- list_add(&wp->list, &ns->weak_pages);
+ list_add(&wp->list, nsparam->weak_pages);
} while (*w);
return 0;
}
@@ -1078,7 +1129,7 @@ static int write_error(struct nandsim *ns, unsigned int page_no)
{
struct weak_page *wp;
- list_for_each_entry(wp, &ns->weak_pages, list)
+ list_for_each_entry(wp, ns->weak_pages, list)
if (wp->page_no == page_no) {
if (wp->writes_done >= wp->max_writes)
return 1;
@@ -1088,7 +1139,7 @@ static int write_error(struct nandsim *ns, unsigned int page_no)
return 0;
}
-static int parse_gravepages(struct nandsim *ns, unsigned char *gravepages)
+static int parse_gravepages(struct nandsim_params *nsparam, unsigned char *gravepages)
{
char *g;
int zero_ok;
@@ -1096,8 +1147,14 @@ static int parse_gravepages(struct nandsim *ns, unsigned char *gravepages)
unsigned int max_reads;
struct grave_page *gp;
+ nsparam->grave_pages = kmalloc(sizeof(struct list_head), GFP_KERNEL);
+ if (!nsparam->grave_pages)
+ return -ENOMEM;
+
+ INIT_LIST_HEAD(nsparam->grave_pages);
if (!gravepages)
return 0;
+
g = gravepages;
do {
zero_ok = (*g == '0' ? 1 : 0);
@@ -1120,7 +1177,7 @@ static int parse_gravepages(struct nandsim *ns, unsigned char *gravepages)
}
gp->page_no = page_no;
gp->max_reads = max_reads;
- list_add(&gp->list, &ns->grave_pages);
+ list_add(&gp->list, nsparam->grave_pages);
} while (*g);
return 0;
}
@@ -1129,7 +1186,7 @@ static int read_error(struct nandsim *ns, unsigned int page_no)
{
struct grave_page *gp;
- list_for_each_entry(gp, &ns->grave_pages, list)
+ list_for_each_entry(gp, ns->grave_pages, list)
if (gp->page_no == page_no) {
if (gp->reads_done >= gp->max_reads)
return 1;
@@ -1142,17 +1199,31 @@ static int read_error(struct nandsim *ns, unsigned int page_no)
static void free_lists(struct nandsim *ns)
{
struct list_head *pos, *n;
- list_for_each_safe(pos, n, &ns->weak_blocks) {
- list_del(pos);
- kfree(list_entry(pos, struct weak_block, list));
+
+ if (ns->weak_blocks) {
+ list_for_each_safe(pos, n, ns->weak_blocks) {
+ list_del(pos);
+ kfree(list_entry(pos, struct weak_block, list));
+ }
+
+ kfree(ns->weak_blocks);
+ ns->weak_blocks = NULL;
}
- list_for_each_safe(pos, n, &ns->weak_pages) {
- list_del(pos);
- kfree(list_entry(pos, struct weak_page, list));
+ if (ns->weak_pages) {
+ list_for_each_safe(pos, n, ns->weak_pages) {
+ list_del(pos);
+ kfree(list_entry(pos, struct weak_page, list));
+ }
+ kfree(ns->weak_pages);
+ ns->weak_pages = NULL;
}
- list_for_each_safe(pos, n, &ns->grave_pages) {
- list_del(pos);
- kfree(list_entry(pos, struct grave_page, list));
+ if (ns->grave_pages) {
+ list_for_each_safe(pos, n, ns->grave_pages) {
+ list_del(pos);
+ kfree(list_entry(pos, struct grave_page, list));
+ }
+ kfree(ns->grave_pages);
+ ns->grave_pages = NULL;
}
kfree(ns->erase_block_wear);
}
@@ -2579,8 +2650,122 @@ static void ns_nand_read_buf(struct mtd_info *mtd, u_char *buf, int len)
return;
}
-static int ns_ctrl_new_instance(struct ns_new_instance_req *req)
+static void destroy_nsparam_lists(struct nandsim_params *nsparam)
+{
+ struct list_head *pos, *n;
+
+ if (nsparam->bad_blocks) {
+ list_for_each_safe(pos, n, nsparam->bad_blocks) {
+ list_del(pos);
+ kfree(list_entry(pos, struct bad_block, list));
+ }
+ }
+
+ if (nsparam->weak_blocks) {
+ list_for_each_safe(pos, n, nsparam->weak_blocks) {
+ list_del(pos);
+ kfree(list_entry(pos, struct weak_block, list));
+ }
+ }
+
+ if (nsparam->weak_pages) {
+ list_for_each_safe(pos, n, nsparam->weak_pages) {
+ list_del(pos);
+ kfree(list_entry(pos, struct weak_page, list));
+ }
+ }
+
+ if (nsparam->grave_pages) {
+ list_for_each_safe(pos, n, nsparam->grave_pages) {
+ list_del(pos);
+ kfree(list_entry(pos, struct grave_page, list));
+ }
+ }
+
+ kfree(nsparam->bad_blocks);
+ kfree(nsparam->weak_blocks);
+ kfree(nsparam->weak_pages);
+ kfree(nsparam->grave_pages);
+}
+
+static int process_element_params(struct nandsim_params *nsparam, int num,
+ void __user *elem_argp)
+{
+ int i, err;
+ struct ns_simelement_prop sep;
+
+ for (i = 0; i < num; i++) {
+ err = copy_from_user(&sep, elem_argp + (i * sizeof(sep)),
+ sizeof(sep));
+ if (err)
+ goto out_err;
+
+ err = -ENOMEM;
+
+ switch (sep.elem_type) {
+ case NANDSIM_SIMELEM_BADBLOCK:
+ {
+ struct bad_block *bb = kzalloc(sizeof(*bb), GFP_KERNEL);
+
+ if (!bb)
+ goto out_err;
+
+ bb->erase_block_no = sep.elem_id;
+ list_add(&bb->list, nsparam->bad_blocks);
+ }
+ break;
+ case NANDSIM_SIMELEM_WEAKBLOCK:
+ {
+ struct weak_block *wb = kzalloc(sizeof(*wb), GFP_KERNEL);
+
+ if (!wb)
+ goto out_err;
+
+ wb->erase_block_no = sep.elem_id;
+ wb->max_erases = sep.elem_attr;
+ list_add(&wb->list, nsparam->weak_blocks);
+ }
+ break;
+ case NANDSIM_SIMELEM_WEAKPAGE:
+ {
+ struct weak_page *wp = kzalloc(sizeof(*wp), GFP_KERNEL);
+
+ if (!wp)
+ goto out_err;
+
+ wp->page_no = sep.elem_id;
+ wp->max_writes = sep.elem_attr;
+ list_add(&wp->list, nsparam->weak_pages);
+ }
+ break;
+ case NANDSIM_SIMELEM_GRAVEPAGE:
+ {
+ struct grave_page *gp = kzalloc(sizeof(*gp), GFP_KERNEL);
+
+ if (!gp)
+ goto out_err;
+
+ gp->page_no = sep.elem_id;
+ gp->max_reads = sep.elem_attr;
+ list_add(&gp->list, nsparam->grave_pages);
+ }
+ break;
+ default:
+ err = -EINVAL;
+ goto out_err;
+ }
+ }
+
+ return 0;
+
+out_err:
+ destroy_nsparam_lists(nsparam);
+ return err;
+}
+
+static int ns_ctrl_new_instance(struct ns_new_instance_req *req, void __user *elem_argp)
{
+ int ret = -EINVAL;
struct mtd_info *nsmtd;
struct nand_chip *chip;
struct nandsim *ns;
@@ -2599,20 +2784,20 @@ static int ns_ctrl_new_instance(struct ns_new_instance_req *req)
nsparam->overridesize = req->overridesize;
if (req->bch_strength && req->no_oob)
- goto err_inval;
+ goto err;
if (req->access_delay && req->program_delay && req->erase_delay &&
req->output_cycle && req->input_cycle) {
if (req->access_delay > MAX_UDELAY_MS * 1000)
- goto err_inval;
+ goto err;
if (req->program_delay > MAX_UDELAY_MS * 1000)
- goto err_inval;
+ goto err;
if (req->erase_delay > 1000)
- goto err_inval;
+ goto err;
if (req->output_cycle > MAX_UDELAY_MS * 1000)
- goto err_inval;
+ goto err;
if (req->input_cycle > MAX_UDELAY_MS * 1000)
- goto err_inval;
+ goto err;
nsparam->access_delay = req->access_delay;
nsparam->program_delay = req->program_delay;
@@ -2623,7 +2808,7 @@ static int ns_ctrl_new_instance(struct ns_new_instance_req *req)
}
if (req->parts_num > NANDSIM_MAX_PARTS || req->parts_num < 0)
- goto err_inval;
+ goto err;
if (req->parts_num > 0) {
nsparam->parts_num = req->parts_num;
@@ -2644,7 +2829,37 @@ static int ns_ctrl_new_instance(struct ns_new_instance_req *req)
break;
default:
- goto err_inval;
+ goto err;
+ }
+
+ nsparam->bad_blocks = kmalloc(sizeof(struct list_head), GFP_KERNEL);
+ nsparam->weak_blocks = kmalloc(sizeof(struct list_head), GFP_KERNEL);
+ nsparam->weak_pages = kmalloc(sizeof(struct list_head), GFP_KERNEL);
+ nsparam->grave_pages = kmalloc(sizeof(struct list_head), GFP_KERNEL);
+
+ if (!nsparam->bad_blocks || !nsparam->weak_blocks ||
+ !nsparam->weak_pages || !nsparam->grave_pages) {
+ kfree(nsparam->bad_blocks);
+ kfree(nsparam->weak_blocks);
+ kfree(nsparam->weak_pages);
+ kfree(nsparam->grave_pages);
+
+ ret = -ENOMEM;
+ goto err;
+ }
+
+ INIT_LIST_HEAD(nsparam->bad_blocks);
+ INIT_LIST_HEAD(nsparam->weak_blocks);
+ INIT_LIST_HEAD(nsparam->weak_pages);
+ INIT_LIST_HEAD(nsparam->grave_pages);
+
+ if (req->simelem_num > 0) {
+ if (req->simelem_num > 1000)
+ goto err;
+
+ ret = process_element_params(nsparam, req->simelem_num, elem_argp);
+ if (ret)
+ goto err;
}
nsmtd = ns_new_instance(nsparam);
@@ -2658,9 +2873,10 @@ static int ns_ctrl_new_instance(struct ns_new_instance_req *req)
return ns->index;
-err_inval:
+err:
+ destroy_nsparam_lists(nsparam);
kfree(nsparam);
- return -EINVAL;
+ return ret;
}
static int ns_ctrl_destroy_instance(struct ns_destroy_instance_req *req)
@@ -2798,10 +3014,6 @@ struct mtd_info *ns_new_instance(struct nandsim_params *nsparam)
nand->index = i;
mutex_unlock(&ns_mtd_mutex);
- INIT_LIST_HEAD(&nand->weak_blocks);
- INIT_LIST_HEAD(&nand->grave_pages);
- INIT_LIST_HEAD(&nand->weak_pages);
- INIT_LIST_HEAD(&nand->weak_blocks);
spin_lock_init(&nand->refcnt_lock);
/*
@@ -2854,14 +3066,9 @@ struct mtd_info *ns_new_instance(struct nandsim_params *nsparam)
nsmtd->_get_device = ns_get_device;
nsmtd->_put_device = ns_put_device;
- if ((retval = parse_weakblocks(nand, nsparam->weakblocks)) != 0)
- goto err_lists;
-
- if ((retval = parse_weakpages(nand, nsparam->weakpages)) != 0)
- goto err_lists;
-
- if ((retval = parse_gravepages(nand, nsparam->gravepages)) != 0)
- goto err_lists;
+ nand->weak_blocks = nsparam->weak_blocks;
+ nand->weak_pages = nsparam->weak_pages;
+ nand->grave_pages = nsparam->grave_pages;
nand->do_delays = nsparam->do_delays;
nand->access_delay = nsparam->access_delay;
@@ -2960,7 +3167,7 @@ struct mtd_info *ns_new_instance(struct nandsim_params *nsparam)
if ((retval = chip->scan_bbt(nsmtd)) != 0)
goto err_nandsim;
- if ((retval = parse_badblocks(nand, nsmtd, nsparam->badblocks)) != 0)
+ if ((retval = process_badblocks(nsparam, nand)) != 0)
goto err_nandsim;
/* Register NAND partitions */
@@ -3021,6 +3228,7 @@ static void ns_destroy_all(void)
static int __init ns_init_default(void)
{
+ int ret;
struct mtd_info *nsmtd;
struct nandsim_params *nsparam = kzalloc(sizeof(*nsparam), GFP_KERNEL);
@@ -3036,11 +3244,6 @@ static int __init ns_init_default(void)
nsparam->do_delays = do_delays;
memcpy(nsparam->parts, parts, sizeof(nsparam->parts));
nsparam->parts_num = parts_num;
- nsparam->badblocks = badblocks;
- nsparam->weakblocks = weakblocks;
- nsparam->weakpages = weakpages;
- nsparam->bitflips = bitflips;
- nsparam->gravepages = gravepages;
nsparam->overridesize = overridesize;
nsparam->cache_file = cache_file;
nsparam->bbt = bbt;
@@ -3052,6 +3255,22 @@ static int __init ns_init_default(void)
else
nsparam->bops = &ns_cachefile_bops;
+ ret = parse_badblocks(nsparam, badblocks);
+ if (ret)
+ goto err_lists;
+
+ ret = parse_weakblocks(nsparam, weakblocks);
+ if (ret)
+ goto err_lists;
+
+ ret = parse_weakpages(nsparam, weakpages);
+ if (ret)
+ goto err_lists;
+
+ ret = parse_gravepages(nsparam, gravepages);
+ if (ret)
+ goto err_lists;
+
nsmtd = ns_new_instance(nsparam);
kfree(nsparam);
@@ -3059,6 +3278,11 @@ static int __init ns_init_default(void)
return PTR_ERR(nsmtd);
return 0;
+
+err_lists:
+ destroy_nsparam_lists(nsparam);
+ kfree(nsparam);
+ return ret;
}
static int __init ns_init_module(void)
diff --git a/include/linux/mtd/nandsim.h b/include/linux/mtd/nandsim.h
index 880c0b1..702e49d 100644
--- a/include/linux/mtd/nandsim.h
+++ b/include/linux/mtd/nandsim.h
@@ -14,9 +14,10 @@ struct nandsim_params {
bool do_delays;
unsigned int parts[NANDSIM_MAX_PARTS];
unsigned int parts_num;
- char *badblocks;
- char *weakblocks;
- char *weakpages;
+ struct list_head *bad_blocks;
+ struct list_head *weak_blocks;
+ struct list_head *weak_pages;
+ struct list_head *grave_pages;
unsigned int bitflips;
char *gravepages;
unsigned int overridesize;
--
2.8.3
[toc] | [prev] | [next] | [standalone]
| From | Daniel Walter <dwalter@sigma-star.at> |
|---|---|
| Date | 2016-08-31 09:40 +0200 |
| Subject | [PATCH 23/46] mtd: nandsim: Unify file backend init logic |
| Message-ID | <sc8hS-7T2-101@gated-at.bofh.it> |
| In reply to | #1473080 |
From: Richard Weinberger <richard@nod.at>
file and cache file backend do more or less the same,
so share some code.
Signed-off-by: Richard Weinberger <richard@nod.at>
---
drivers/mtd/nand/nandsim.c | 102 ++++++++++++++++++++++++++++++---------------
1 file changed, 68 insertions(+), 34 deletions(-)
diff --git a/drivers/mtd/nand/nandsim.c b/drivers/mtd/nand/nandsim.c
index 78c3ee4..f936157 100644
--- a/drivers/mtd/nand/nandsim.c
+++ b/drivers/mtd/nand/nandsim.c
@@ -312,6 +312,7 @@ struct ns_ram_data {
struct ns_cachefile_data {
struct file *cfile; /* Open file */
+ bool file_opened; /* False when we operate on an already opened file */
unsigned long *pages_written; /* Which pages have been written */
void *file_buf;
struct page *held_pages[NS_MAX_HELD_PAGES];
@@ -637,25 +638,70 @@ static int ns_ram_init(struct nandsim *ns, struct nandsim_params *nsparam)
return 0;
}
-static int ns_cachefile_init(struct nandsim *ns, struct nandsim_params *nsparam)
+static struct file *get_file_from_nsparam(struct nandsim_params *nsparam, bool *opened)
{
- struct file *cfile;
int err;
- struct ns_cachefile_data *data = kzalloc(sizeof(*data), GFP_KERNEL);
+ struct file *file;
+ struct inode *inode;
- cfile = filp_open(nsparam->cache_file, O_CREAT | O_RDWR | O_LARGEFILE, 0600);
- if (IS_ERR(cfile))
- return PTR_ERR(cfile);
- if (!(cfile->f_mode & FMODE_CAN_READ)) {
+ if (nsparam->cache_file) {
+ file = filp_open(nsparam->cache_file, O_CREAT | O_RDWR | O_LARGEFILE, 0600);
+ if (IS_ERR(file))
+ return file;
+
+ *opened = true;
+ } else {
+ file = fget(nsparam->file_fd);
+ if (!file)
+ return ERR_PTR(-EBADF);
+
+ *opened = false;
+ }
+
+ inode = file->f_mapping->host;
+ if (!S_ISREG(inode->i_mode) && !S_ISBLK(inode->i_mode)) {
+ NS_ERR("alloc_device: Backend file is not a regular file nor a block device\n");
+ err = -EINVAL;
+ goto out;
+ }
+
+ if (!(file->f_mode & FMODE_CAN_READ)) {
NS_ERR("alloc_device: cache file not readable\n");
err = -EINVAL;
- goto err_close;
+ goto out;
}
- if (!(cfile->f_mode & FMODE_CAN_WRITE)) {
+
+ if (!(file->f_mode & FMODE_CAN_WRITE)) {
NS_ERR("alloc_device: cache file not writeable\n");
err = -EINVAL;
- goto err_close;
+ goto out;
}
+
+ return file;
+
+out:
+ if (*opened)
+ filp_close(file, NULL);
+ else
+ fput(file);
+
+ return ERR_PTR(err);
+}
+
+static int ns_cachefile_init(struct nandsim *ns, struct nandsim_params *nsparam)
+{
+ int err;
+ struct ns_cachefile_data *data = kzalloc(sizeof(*data), GFP_KERNEL);
+
+ if (!data)
+ return -ENOMEM;
+
+ data->cfile = get_file_from_nsparam(nsparam, &data->file_opened);
+ if (IS_ERR(data->cfile)) {
+ err = PTR_ERR(data->cfile);
+ goto out;
+ }
+
data->pages_written = vzalloc(BITS_TO_LONGS(ns->geom.pgnum) *
sizeof(unsigned long));
if (!data->pages_written) {
@@ -669,7 +715,6 @@ static int ns_cachefile_init(struct nandsim *ns, struct nandsim_params *nsparam)
err = -ENOMEM;
goto err_free;
}
- data->cfile = cfile;
ns->backend_data = data;
@@ -678,15 +723,16 @@ static int ns_cachefile_init(struct nandsim *ns, struct nandsim_params *nsparam)
err_free:
vfree(data->pages_written);
err_close:
- filp_close(cfile, NULL);
+ filp_close(data->cfile, NULL);
+out:
+ kfree(data);
return err;
}
static int ns_file_init(struct nandsim *ns, struct nandsim_params *nsparam)
{
int ret;
- struct file *file;
- struct inode *inode;
+ bool dummy;
struct ns_file_data *data = kzalloc(sizeof(*data), GFP_KERNEL);
if (!data) {
@@ -694,27 +740,12 @@ static int ns_file_init(struct nandsim *ns, struct nandsim_params *nsparam)
goto out;
}
- file = fget(nsparam->file_fd);
- if (!file) {
- ret = -EBADF;
+ data->file = get_file_from_nsparam(nsparam, &dummy);
+ if (IS_ERR(data->file)) {
+ ret = PTR_ERR(data->file);
goto out_free;
}
- inode = file->f_mapping->host;
- if (!S_ISREG(inode->i_mode) && !S_ISBLK(inode->i_mode)) {
- NS_ERR("alloc_device: Backend file is not a regular file nor a block device\n");
- ret = -EINVAL;
- goto out_put;
- }
-
- if (!(file->f_mode & FMODE_WRITE)) {
- NS_ERR("alloc_device: Backend file is not writeable\n");
- ret = -EINVAL;
- goto out_put;
- }
-
- data->file = file;
-
data->file_buf = kmalloc(ns->geom.pgszoob, GFP_KERNEL);
if (!data->file_buf) {
NS_ERR("alloc_device: unable to allocate file buf\n");
@@ -728,7 +759,7 @@ static int ns_file_init(struct nandsim *ns, struct nandsim_params *nsparam)
return ret;
out_put:
- fput(file);
+ fput(data->file);
out_free:
kfree(data);
out:
@@ -792,7 +823,10 @@ static void ns_cachefile_destroy(struct nandsim *ns)
kfree(data->file_buf);
vfree(data->pages_written);
- filp_close(data->cfile, NULL);
+ if (data->file_opened)
+ filp_close(data->cfile, NULL);
+ else
+ fput(data->cfile);
kfree(data);
}
--
2.8.3
[toc] | [prev] | [next] | [standalone]
| From | Daniel Walter <dwalter@sigma-star.at> |
|---|---|
| Date | 2016-08-31 09:40 +0200 |
| Subject | [PATCH 35/46] mtd: nandsim: Make NANDSIM_MAX_DEVICES part of uapi |
| Message-ID | <sc8hS-7T2-103@gated-at.bofh.it> |
| In reply to | #1473080 |
From: Richard Weinberger <richard@nod.at>
...such that userspace very easy remove all nandsim instances.
Signed-off-by: Richard Weinberger <richard@nod.at>
---
drivers/mtd/nand/nandsim.c | 14 ++++++--------
1 file changed, 6 insertions(+), 8 deletions(-)
diff --git a/drivers/mtd/nand/nandsim.c b/drivers/mtd/nand/nandsim.c
index 812b97f..8bc8015 100644
--- a/drivers/mtd/nand/nandsim.c
+++ b/drivers/mtd/nand/nandsim.c
@@ -432,10 +432,8 @@ struct grave_page {
unsigned int reads_done;
};
-#define NS_MAX_DEVICES 32
-
/* MTD structure for NAND controller */
-static struct mtd_info *ns_mtds[NS_MAX_DEVICES];
+static struct mtd_info *ns_mtds[NANDSIM_MAX_DEVICES];
static DEFINE_MUTEX(ns_mtd_mutex);
static struct dentry *dfs_root;
@@ -2648,7 +2646,7 @@ static int ns_ctrl_destroy_instance(struct ns_destroy_instance_req *req)
struct nand_chip *chip;
struct nandsim *ns;
- if (id < 0 || id >= NS_MAX_DEVICES)
+ if (id < 0 || id >= NANDSIM_MAX_DEVICES)
return -EINVAL;
mutex_lock(&ns_mtd_mutex);
@@ -2758,13 +2756,13 @@ struct mtd_info *ns_new_instance(struct nandsim_params *nsparam)
}
mutex_lock(&ns_mtd_mutex);
- for (i = 0; i < NS_MAX_DEVICES; i++) {
+ for (i = 0; i < NANDSIM_MAX_DEVICES; i++) {
if (!ns_mtds[i])
break;
}
- if (i == NS_MAX_DEVICES) {
- pr_err("Cannot allocate more than %i instances!\n", NS_MAX_DEVICES);
+ if (i == NANDSIM_MAX_DEVICES) {
+ pr_err("Cannot allocate more than %i instances!\n", NANDSIM_MAX_DEVICES);
retval = -ENFILE;
mutex_unlock(&ns_mtd_mutex);
goto error;
@@ -2983,7 +2981,7 @@ static void ns_destroy_all(void)
int i;
mutex_lock(&ns_mtd_mutex);
- for (i = 0; i < NS_MAX_DEVICES; i++)
+ for (i = 0; i < NANDSIM_MAX_DEVICES; i++)
if (ns_mtds[i])
WARN_ON(ns_destroy_instance(ns_mtds[i]) != 0);
mutex_unlock(&ns_mtd_mutex);
--
2.8.3
[toc] | [prev] | [next] | [standalone]
Page 2 of 3 — ← Prev page 1 [2] 3 Next page →
Back to top | Article view | linux.kernel
csiph-web