Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > linux.kernel > #1473080 > unrolled thread

[PATCH 00/46] Nandsim facelift (part I of II)

Started byDaniel Walter <dwalter@sigma-star.at>
First post2016-08-31 09:30 +0200
Last post2016-08-31 09:40 +0200
Articles 20 on this page of 45 — 1 participant

Back to article view | Back to linux.kernel


Contents

  [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 →


#1473109 — [PATCH 08/46] mtd: nandsim: Kill global nsmtd

FromDaniel Walter <dwalter@sigma-star.at>
Date2016-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]


#1473110 — [PATCH 40/46] mtd: nandsim: Expose BBT, delays, etc.. to userspace

FromDaniel Walter <dwalter@sigma-star.at>
Date2016-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]


#1473111 — [PATCH 17/46] mtd: nandsim: Allow external backends

FromDaniel Walter <dwalter@sigma-star.at>
Date2016-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]


#1473112 — [PATCH 46/46] mtd/nandsim: Add ioctl for info

FromDaniel Walter <dwalter@sigma-star.at>
Date2016-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]


#1473113 — [PATCH 36/46] mtd: nandsim: Cleanup constants

FromDaniel Walter <dwalter@sigma-star.at>
Date2016-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]


#1473114 — [PATCH 42/46] mtd: nandsim: Don't printk on ENOMEM

FromDaniel Walter <dwalter@sigma-star.at>
Date2016-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]


#1473115 — [PATCH 19/46] mtd: nandsim: UAPI v1

FromDaniel Walter <dwalter@sigma-star.at>
Date2016-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]


#1473116 — [PATCH 20/46] mtd: nandsim: Implement preliminary constructor function

FromDaniel Walter <dwalter@sigma-star.at>
Date2016-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]


#1473117 — [PATCH 12/46] mtd: nandsim: Make debugfs logic multi instance capable

FromDaniel Walter <dwalter@sigma-star.at>
Date2016-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]


#1473118 — [PATCH 04/46] mtd: Don't unconditionally execute remove notifiers

FromDaniel Walter <dwalter@sigma-star.at>
Date2016-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]


#1473119 — [PATCH 22/46] mtd: nandsim: Cleanup destroy handlers

FromDaniel Walter <dwalter@sigma-star.at>
Date2016-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]


#1473120 — [PATCH 25/46] mtd: nandsim: Print backend name

FromDaniel Walter <dwalter@sigma-star.at>
Date2016-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]


#1473121 — [PATCH 28/46] mtd: nandsim: Refine exports

FromDaniel Walter <dwalter@sigma-star.at>
Date2016-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]


#1473122 — [PATCH 31/46] mtd: nandsim: Remove NS_RAW_OFFSET_OOB

FromDaniel Walter <dwalter@sigma-star.at>
Date2016-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]


#1473123 — [PATCH 21/46] mtd: nandsim: Implement preliminary destructor function

FromDaniel Walter <dwalter@sigma-star.at>
Date2016-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]


#1473125 — [PATCH 26/46] mtd: nandsim: use the existing output macros

FromDaniel Walter <dwalter@sigma-star.at>
Date2016-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]


#1473126 — [PATCH 37/46] mtd: nandsim: Turn parts[] into a integer

FromDaniel Walter <dwalter@sigma-star.at>
Date2016-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]


#1473127 — [PATCH 41/46] mtd: nandsim: Expose support for weakpages/blocks to userspace

FromDaniel Walter <dwalter@sigma-star.at>
Date2016-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]


#1473129 — [PATCH 23/46] mtd: nandsim: Unify file backend init logic

FromDaniel Walter <dwalter@sigma-star.at>
Date2016-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]


#1473130 — [PATCH 35/46] mtd: nandsim: Make NANDSIM_MAX_DEVICES part of uapi

FromDaniel Walter <dwalter@sigma-star.at>
Date2016-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