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


Groups > linux.kernel > #1487952 > unrolled thread

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

Started byDaniel Walter <dwalter@sigma-star.at>
First post2016-09-21 11:50 +0200
Last post2016-09-21 12:00 +0200
Articles 20 on this page of 54 — 3 participants

Back to article view | Back to linux.kernel


Contents

  [PATCH v2 00/46] Nandsim facelift (part I of II) Daniel Walter <dwalter@sigma-star.at> - 2016-09-21 11:50 +0200
    [PATCH v2 13/46] mtd: nandsim: Add final logic for multiple instances Daniel Walter <dwalter@sigma-star.at> - 2016-09-21 11:50 +0200
    [PATCH v2 12/46] mtd: nandsim: Make debugfs logic multi instance capable Daniel Walter <dwalter@sigma-star.at> - 2016-09-21 11:50 +0200
    [PATCH v2 09/46] mtd: nandsim: Don't directly use module parameters Daniel Walter <dwalter@sigma-star.at> - 2016-09-21 11:50 +0200
    [PATCH v2 08/46] mtd: nandsim: Kill global nsmtd Daniel Walter <dwalter@sigma-star.at> - 2016-09-21 11:50 +0200
    [PATCH v2 04/46] mtd: Don't unconditionally execute remove notifiers Daniel Walter <dwalter@sigma-star.at> - 2016-09-21 11:50 +0200
    [PATCH v2 05/46] mtd: Don't print a scary message when trying to remove a busy MTD Daniel Walter <dwalter@sigma-star.at> - 2016-09-21 11:50 +0200
    [PATCH v2 02/46] mtd: nand: Provide nand_cleanup() function to free NAND related resources Daniel Walter <dwalter@sigma-star.at> - 2016-09-21 11:50 +0200
      Re: [PATCH v2 02/46] mtd: nand: Provide nand_cleanup() function to  free NAND related resources Boris Brezillon <boris.brezillon@free-electrons.com> - 2016-09-21 12:00 +0200
      Re: [PATCH v2 02/46] mtd: nand: Provide nand_cleanup() function to  free NAND related resources kbuild test robot <lkp@intel.com> - 2016-09-21 14:50 +0200
      Re: [PATCH v2 02/46] mtd: nand: Provide nand_cleanup() function to  free NAND related resources Boris Brezillon <boris.brezillon@free-electrons.com> - 2016-09-21 16:30 +0200
        Re: [PATCH v2 02/46] mtd: nand: Provide nand_cleanup() function to  free NAND related resources Daniel Walter <dwalter@sigma-star.at> - 2016-09-21 16:50 +0200
          Re: [PATCH v2 02/46] mtd: nand: Provide nand_cleanup() function to  free NAND related resources Boris Brezillon <boris.brezillon@free-electrons.com> - 2016-09-21 16:50 +0200
    [PATCH v2 01/46] mtdpart: Propagate _get/put_device() Daniel Walter <dwalter@sigma-star.at> - 2016-09-21 11:50 +0200
      Re: [PATCH v2 01/46] mtdpart: Propagate _get/put_device() Boris Brezillon <boris.brezillon@free-electrons.com> - 2016-09-21 12:20 +0200
    [PATCH v2 14/46] mtd: nandsim: Add simulator id to MTD parition name Daniel Walter <dwalter@sigma-star.at> - 2016-09-21 11:50 +0200
    [PATCH v2 07/46] mtd: nandsim: Begin with removal of global state Daniel Walter <dwalter@sigma-star.at> - 2016-09-21 11:50 +0200
    [PATCH v2 15/46] mtd: nandsim: Introduce backend operations Daniel Walter <dwalter@sigma-star.at> - 2016-09-21 11:50 +0200
    [PATCH v2 10/46] mtd: nandsim: Add helper functions for pointer magic Daniel Walter <dwalter@sigma-star.at> - 2016-09-21 11:50 +0200
    [PATCH v2 11/46] mtd: nandsim: Factor out nandsim parameters Daniel Walter <dwalter@sigma-star.at> - 2016-09-21 11:50 +0200
    [PATCH v2 03/46] mtd: Don't unconditionally unregister reboot notifier Daniel Walter <dwalter@sigma-star.at> - 2016-09-21 11:50 +0200
      Re: [PATCH v2 03/46] mtd: Don't unconditionally unregister reboot  notifier Boris Brezillon <boris.brezillon@free-electrons.com> - 2016-09-21 16:40 +0200
        Re: [PATCH v2 03/46] mtd: Don't unconditionally unregister reboot  notifier Daniel Walter <dwalter@sigma-star.at> - 2016-09-21 16:40 +0200
    [PATCH v2 24/46] mtd: nandsim: Wire up NANDSIM_MODE_CACHEFILE ioctl mode Daniel Walter <dwalter@sigma-star.at> - 2016-09-21 12:00 +0200
    [PATCH v2 38/46] mtd: nandsim: Expose partition creation logic to user space Daniel Walter <dwalter@sigma-star.at> - 2016-09-21 12:00 +0200
    [PATCH v2 31/46] mtd: nandsim: Remove NS_RAW_OFFSET_OOB Daniel Walter <dwalter@sigma-star.at> - 2016-09-21 12:00 +0200
    [PATCH v2 35/46] mtd: nandsim: Make NANDSIM_MAX_DEVICES part of uapi Daniel Walter <dwalter@sigma-star.at> - 2016-09-21 12:00 +0200
    [PATCH v2 40/46] mtd: nandsim: Expose BBT, delays, etc.. to userspace Daniel Walter <dwalter@sigma-star.at> - 2016-09-21 12:00 +0200
    [PATCH v2 22/46] mtd: nandsim: Cleanup destroy handlers Daniel Walter <dwalter@sigma-star.at> - 2016-09-21 12:00 +0200
    [PATCH v2 33/46] mtd: nandsim: Relax page size restrictions Daniel Walter <dwalter@sigma-star.at> - 2016-09-21 12:00 +0200
    [PATCH v2 32/46] mtd: nandsim: Remove NS_IS_INITIALIZED Daniel Walter <dwalter@sigma-star.at> - 2016-09-21 12:00 +0200
    [PATCH v2 45/46] mtd: nandsim: Always answer all 8 bytes from NAND_CMD_READID Daniel Walter <dwalter@sigma-star.at> - 2016-09-21 12:00 +0200
    [PATCH v2 17/46] mtd: nandsim: Allow external backends Daniel Walter <dwalter@sigma-star.at> - 2016-09-21 12:00 +0200
    [PATCH v2 44/46] mtd: nandsim: Wire up NANDSIM_IOC_DESTROY_INSTANCE Daniel Walter <dwalter@sigma-star.at> - 2016-09-21 12:00 +0200
    [PATCH v2 21/46] mtd: nandsim: Implement preliminary destructor function Daniel Walter <dwalter@sigma-star.at> - 2016-09-21 12:00 +0200
      Re: [PATCH v2 21/46] mtd: nandsim: Implement preliminary destructor  function kbuild test robot <lkp@intel.com> - 2016-09-21 15:00 +0200
    [PATCH v2 29/46] um: Add nandsim backend driver Daniel Walter <dwalter@sigma-star.at> - 2016-09-21 12:00 +0200
    [PATCH v2 39/46] mtd: nandsim: Rework init error paths Daniel Walter <dwalter@sigma-star.at> - 2016-09-21 12:00 +0200
    [PATCH v2 28/46] mtd: nandsim: Refine exports Daniel Walter <dwalter@sigma-star.at> - 2016-09-21 12:00 +0200
    [PATCH v2 26/46] mtd: nandsim: use the existing output macros Daniel Walter <dwalter@sigma-star.at> - 2016-09-21 12:00 +0200
    [PATCH v2 36/46] mtd: nandsim: Cleanup constants Daniel Walter <dwalter@sigma-star.at> - 2016-09-21 12:00 +0200
    [PATCH v2 16/46] mtd: nandsim: Print error when backend init failed Daniel Walter <dwalter@sigma-star.at> - 2016-09-21 12:00 +0200
    [PATCH v2 25/46] mtd: nandsim: Print backend name Daniel Walter <dwalter@sigma-star.at> - 2016-09-21 12:00 +0200
    [PATCH v2 23/46] mtd: nandsim: Unify file backend init logic Daniel Walter <dwalter@sigma-star.at> - 2016-09-21 12:00 +0200
    [PATCH v2 34/46] mtd: nandsim: Support bitflip and read error emulation in file backend Daniel Walter <dwalter@sigma-star.at> - 2016-09-21 12:00 +0200
    [PATCH v2 43/46] mtd: nandsim: Wire up NANDSIM_IOC_NEW_INSTANCE Daniel Walter <dwalter@sigma-star.at> - 2016-09-21 12:00 +0200
    [PATCH v2 41/46] mtd: nandsim: Expose support for weakpages/blocks to userspace Daniel Walter <dwalter@sigma-star.at> - 2016-09-21 12:00 +0200
    [PATCH v2 46/46] mtd/nandsim: Add ioctl for info Daniel Walter <dwalter@sigma-star.at> - 2016-09-21 12:00 +0200
    [PATCH v2 19/46] mtd: nandsim: UAPI v1 Daniel Walter <dwalter@sigma-star.at> - 2016-09-21 12:00 +0200
    [PATCH v2 20/46] mtd: nandsim: Implement preliminary constructor function Daniel Walter <dwalter@sigma-star.at> - 2016-09-21 12:00 +0200
    [PATCH v2 18/46] mtd: nandsim: Add basic support for a file backend Daniel Walter <dwalter@sigma-star.at> - 2016-09-21 12:00 +0200
    [PATCH v2 37/46] mtd: nandsim: Turn parts[] into a integer Daniel Walter <dwalter@sigma-star.at> - 2016-09-21 12:00 +0200
    [PATCH v2 27/46] mtd: nandsim: Add no_oob mode Daniel Walter <dwalter@sigma-star.at> - 2016-09-21 12:00 +0200
    [PATCH v2 42/46] mtd: nandsim: Don't printk on ENOMEM Daniel Walter <dwalter@sigma-star.at> - 2016-09-21 12:00 +0200

Page 2 of 3 — ← Prev page 1 [2] 3  Next page →


#1487968 — [PATCH v2 03/46] mtd: Don't unconditionally unregister reboot notifier

FromDaniel Walter <dwalter@sigma-star.at>
Date2016-09-21 11:50 +0200
Subject[PATCH v2 03/46] mtd: Don't unconditionally unregister reboot notifier
Message-ID<sjMkb-7il-39@gated-at.bofh.it>
In reply to#1487952
From: Richard Weinberger <richard@nod.at>

del_mtd_device() is allowed to fail.
i.e. when the MTD is busy.
Unregister the reboot notifier only when we're really
about to delete the MTD.

Signed-off-by: Richard Weinberger <richard@nod.at>
---
 drivers/mtd/mtdcore.c | 15 ++++++++++-----
 1 file changed, 10 insertions(+), 5 deletions(-)

diff --git a/drivers/mtd/mtdcore.c b/drivers/mtd/mtdcore.c
index e3936b8..36e5fb0 100644
--- a/drivers/mtd/mtdcore.c
+++ b/drivers/mtd/mtdcore.c
@@ -654,17 +654,22 @@ int mtd_device_unregister(struct mtd_info *master)
 {
 	int err;
 
-	if (master->_reboot)
-		unregister_reboot_notifier(&master->reboot_notifier);
-
 	err = del_mtd_partitions(master);
 	if (err)
 		return err;
 
 	if (!device_is_registered(&master->dev))
-		return 0;
+		goto unregister;
 
-	return del_mtd_device(master);
+	err = del_mtd_device(master);
+	if (err)
+		return err;
+
+unregister:
+	if (master->_reboot)
+		unregister_reboot_notifier(&master->reboot_notifier);
+
+	return 0;
 }
 EXPORT_SYMBOL_GPL(mtd_device_unregister);
 
-- 
2.8.3

[toc] | [prev] | [next] | [standalone]


#1488159 — Re: [PATCH v2 03/46] mtd: Don't unconditionally unregister reboot notifier

FromBoris Brezillon <boris.brezillon@free-electrons.com>
Date2016-09-21 16:40 +0200
SubjectRe: [PATCH v2 03/46] mtd: Don't unconditionally unregister reboot notifier
Message-ID<sjQQN-1KF-23@gated-at.bofh.it>
In reply to#1487968
On Wed, 21 Sep 2016 11:45:12 +0200
Daniel Walter <dwalter@sigma-star.at> wrote:

> From: Richard Weinberger <richard@nod.at>
> 
> del_mtd_device() is allowed to fail.
> i.e. when the MTD is busy.
> Unregister the reboot notifier only when we're really
> about to delete the MTD.
> 
> Signed-off-by: Richard Weinberger <richard@nod.at>
> ---
>  drivers/mtd/mtdcore.c | 15 ++++++++++-----
>  1 file changed, 10 insertions(+), 5 deletions(-)
> 
> diff --git a/drivers/mtd/mtdcore.c b/drivers/mtd/mtdcore.c
> index e3936b8..36e5fb0 100644
> --- a/drivers/mtd/mtdcore.c
> +++ b/drivers/mtd/mtdcore.c
> @@ -654,17 +654,22 @@ int mtd_device_unregister(struct mtd_info *master)
>  {
>  	int err;
>  
> -	if (master->_reboot)
> -		unregister_reboot_notifier(&master->reboot_notifier);
> -
>  	err = del_mtd_partitions(master);
>  	if (err)
>  		return err;
>  
>  	if (!device_is_registered(&master->dev))
> -		return 0;
> +		goto unregister;
>  
> -	return del_mtd_device(master);
> +	err = del_mtd_device(master);
> +	if (err)
> +		return err;
> +
> +unregister:
> +	if (master->_reboot)
> +		unregister_reboot_notifier(&master->reboot_notifier);
> +
> +	return 0;

How about:

	if (device_is_registered(&master->dev)) {
		err = del_mtd_device(master);
		if (err)
			return err;
	}

	if (master->_reboot)
		unregister_reboot_notifier(&master->reboot_notifier);

	return 0;

This way you get rid of the unregister label, which IMHO improves
readability.

>  }
>  EXPORT_SYMBOL_GPL(mtd_device_unregister);
>  

[toc] | [prev] | [next] | [standalone]


#1488163 — Re: [PATCH v2 03/46] mtd: Don't unconditionally unregister reboot notifier

FromDaniel Walter <dwalter@sigma-star.at>
Date2016-09-21 16:40 +0200
SubjectRe: [PATCH v2 03/46] mtd: Don't unconditionally unregister reboot notifier
Message-ID<sjQQO-1KF-47@gated-at.bofh.it>
In reply to#1488159
On 09/21/2016 04:31 PM, Boris Brezillon wrote:
> On Wed, 21 Sep 2016 11:45:12 +0200
> Daniel Walter <dwalter@sigma-star.at> wrote:
> 
>> From: Richard Weinberger <richard@nod.at>
>>
>> del_mtd_device() is allowed to fail.
>> i.e. when the MTD is busy.
>> Unregister the reboot notifier only when we're really
>> about to delete the MTD.
>>
>> Signed-off-by: Richard Weinberger <richard@nod.at>
>> ---
>>  drivers/mtd/mtdcore.c | 15 ++++++++++-----
>>  1 file changed, 10 insertions(+), 5 deletions(-)
>>
>> diff --git a/drivers/mtd/mtdcore.c b/drivers/mtd/mtdcore.c
>> index e3936b8..36e5fb0 100644
>> --- a/drivers/mtd/mtdcore.c
>> +++ b/drivers/mtd/mtdcore.c
>> @@ -654,17 +654,22 @@ int mtd_device_unregister(struct mtd_info *master)
>>  {
>>  	int err;
>>  
>> -	if (master->_reboot)
>> -		unregister_reboot_notifier(&master->reboot_notifier);
>> -
>>  	err = del_mtd_partitions(master);
>>  	if (err)
>>  		return err;
>>  
>>  	if (!device_is_registered(&master->dev))
>> -		return 0;
>> +		goto unregister;
>>  
>> -	return del_mtd_device(master);
>> +	err = del_mtd_device(master);
>> +	if (err)
>> +		return err;
>> +
>> +unregister:
>> +	if (master->_reboot)
>> +		unregister_reboot_notifier(&master->reboot_notifier);
>> +
>> +	return 0;
> 
> How about:
> 
> 	if (device_is_registered(&master->dev)) {
> 		err = del_mtd_device(master);
> 		if (err)
> 			return err;
> 	}
> 
> 	if (master->_reboot)
> 		unregister_reboot_notifier(&master->reboot_notifier);
> 
> 	return 0;
> 
> This way you get rid of the unregister label, which IMHO improves
> readability.

Agree, will fix this in v3 of the series.



-- 
sigma star gmbh | Eduard-Bodem-Gasse 6, 6020 Innsbruck, Austria
UID/VAT Nr: ATU 66964118 | FN: 374287y

[toc] | [prev] | [next] | [standalone]


#1487969 — [PATCH v2 24/46] mtd: nandsim: Wire up NANDSIM_MODE_CACHEFILE ioctl mode

FromDaniel Walter <dwalter@sigma-star.at>
Date2016-09-21 12:00 +0200
Subject[PATCH v2 24/46] mtd: nandsim: Wire up NANDSIM_MODE_CACHEFILE ioctl mode
Message-ID<sjMtP-7lX-1@gated-at.bofh.it>
In reply to#1487952
From: Richard Weinberger <richard@nod.at>

Allow the userspace control tool also to setup a cache file.
In contrast to the cache_file module parameter the ioctl() only
accepts a fd. So, userspace should hand in an fd pointing to
a temp file.

Signed-off-by: Richard Weinberger <richard@nod.at>
---
 drivers/mtd/nand/nandsim.c | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/drivers/mtd/nand/nandsim.c b/drivers/mtd/nand/nandsim.c
index 56a2904..0e8574e 100644
--- a/drivers/mtd/nand/nandsim.c
+++ b/drivers/mtd/nand/nandsim.c
@@ -2536,10 +2536,15 @@ static int ns_ctrl_new_instance(struct ns_new_instance_req *req)
 		case NANDSIM_BACKEND_RAM:
 			nsparam->bops = &ns_ram_bops;
 		break;
+
 		case NANDSIM_BACKEND_FILE:
 			nsparam->bops = &ns_file_bops;
 		break;
 
+		case NANDSIM_BACKEND_CACHEFILE:
+			nsparam->bops = &ns_cachefile_bops;
+		break;
+
 		default:
 			kfree(nsparam);
 			return -EINVAL;
-- 
2.8.3

[toc] | [prev] | [next] | [standalone]


#1487970 — [PATCH v2 38/46] mtd: nandsim: Expose partition creation logic to user space

FromDaniel Walter <dwalter@sigma-star.at>
Date2016-09-21 12:00 +0200
Subject[PATCH v2 38/46] mtd: nandsim: Expose partition creation logic to user space
Message-ID<sjMtP-7lX-3@gated-at.bofh.it>
In reply to#1487952
From: Richard Weinberger <richard@nod.at>

Signed-off-by: Richard Weinberger <richard@nod.at>
---
 drivers/mtd/nand/nandsim.c  | 12 +++++++++++-
 include/linux/mtd/nandsim.h |  2 +-
 2 files changed, 12 insertions(+), 2 deletions(-)

diff --git a/drivers/mtd/nand/nandsim.c b/drivers/mtd/nand/nandsim.c
index 615dde3..6b7570b 100644
--- a/drivers/mtd/nand/nandsim.c
+++ b/drivers/mtd/nand/nandsim.c
@@ -2585,6 +2585,16 @@ static int ns_ctrl_new_instance(struct ns_new_instance_req *req)
 	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;
+	}
+
+	if (req->parts_num > 0) {
+		nsparam->parts_num = req->parts_num;
+		memcpy(nsparam->parts, req->parts, sizeof(nsparam->parts));
+	}
+
 	switch (req->backend) {
 		case NANDSIM_BACKEND_RAM:
 			nsparam->bops = &ns_ram_bops;
@@ -2979,7 +2989,7 @@ static int __init ns_init_default(void)
 	nsparam->input_cycle = input_cycle;
 	nsparam->bus_width = bus_width;
 	nsparam->do_delays = do_delays;
-	nsparam->parts = parts;
+	memcpy(nsparam->parts, parts, sizeof(nsparam->parts));
 	nsparam->parts_num = parts_num;
 	nsparam->badblocks = badblocks;
 	nsparam->weakblocks = weakblocks;
diff --git a/include/linux/mtd/nandsim.h b/include/linux/mtd/nandsim.h
index 61ff5dd..07d32a9 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 int *parts;
+	unsigned int parts[NANDSIM_MAX_PARTS];
 	unsigned int parts_num;
 	char *badblocks;
 	char *weakblocks;
-- 
2.8.3

[toc] | [prev] | [next] | [standalone]


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

FromDaniel Walter <dwalter@sigma-star.at>
Date2016-09-21 12:00 +0200
Subject[PATCH v2 31/46] mtd: nandsim: Remove NS_RAW_OFFSET_OOB
Message-ID<sjMtP-7lX-5@gated-at.bofh.it>
In reply to#1487952
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 048beb0..915e3bb 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]


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

FromDaniel Walter <dwalter@sigma-star.at>
Date2016-09-21 12:00 +0200
Subject[PATCH v2 35/46] mtd: nandsim: Make NANDSIM_MAX_DEVICES part of uapi
Message-ID<sjMtP-7lX-7@gated-at.bofh.it>
In reply to#1487952
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 185ca4d..31a9f89 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;
@@ -2984,7 +2982,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]


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

FromDaniel Walter <dwalter@sigma-star.at>
Date2016-09-21 12:00 +0200
Subject[PATCH v2 40/46] mtd: nandsim: Expose BBT, delays, etc.. to userspace
Message-ID<sjMtP-7lX-9@gated-at.bofh.it>
In reply to#1487952
From: Richard Weinberger <richard@nod.at>

Allow userspace to define nandsim parameters like
delays, bitflips, ...

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 92f5efc..d1402df 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]


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

FromDaniel Walter <dwalter@sigma-star.at>
Date2016-09-21 12:00 +0200
Subject[PATCH v2 22/46] mtd: nandsim: Cleanup destroy handlers
Message-ID<sjMtP-7lX-21@gated-at.bofh.it>
In reply to#1487952
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 bac3fde..816d795 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]


#1487975 — [PATCH v2 33/46] mtd: nandsim: Relax page size restrictions

FromDaniel Walter <dwalter@sigma-star.at>
Date2016-09-21 12:00 +0200
Subject[PATCH v2 33/46] mtd: nandsim: Relax page size restrictions
Message-ID<sjMtP-7lX-11@gated-at.bofh.it>
In reply to#1487952
From: Richard Weinberger <richard@nod.at>

Allow any page size as long it is a power of two and less
than KMALLOC_MAX_SIZE.

Signed-off-by: Richard Weinberger <richard@nod.at>
---
 drivers/mtd/nand/nandsim.c | 26 +++++++++++++-------------
 1 file changed, 13 insertions(+), 13 deletions(-)

diff --git a/drivers/mtd/nand/nandsim.c b/drivers/mtd/nand/nandsim.c
index 971f7b4..8cfdfea 100644
--- a/drivers/mtd/nand/nandsim.c
+++ b/drivers/mtd/nand/nandsim.c
@@ -176,9 +176,6 @@ MODULE_PARM_DESC(bch,		 "Enable BCH ecc and set how many bits should "
 MODULE_PARM_DESC(defaults,	 "Register a MTD during module load using default values and module parametes. "
 				 "Set to N if you want to use the nandsimctl user space tool to setup nandsim.");
 
-/* The largest possible page size */
-#define NS_LARGEST_PAGE_SIZE	4096
-
 /* Busy-wait delay macros (microseconds, milliseconds) */
 #define NS_UDELAY(ns, us) \
 	do { if (ns->do_delays) udelay(us); } while (0)
@@ -247,10 +244,8 @@ MODULE_PARM_DESC(defaults,	 "Register a MTD during module load using default val
 
 #define OPT_ANY          0xFFFFFFFF /* any chip supports this operation */
 #define OPT_PAGE512      0x00000002 /* 512-byte  page chips */
-#define OPT_PAGE2048     0x00000008 /* 2048-byte page chips */
+#define OPT_LARGEPAGE    0x00000008 /* >= 2048-byte page chips */
 #define OPT_PAGE512_8BIT 0x00000040 /* 512-byte page chips with 8-bit bus width */
-#define OPT_PAGE4096     0x00000080 /* 4096-byte page chips */
-#define OPT_LARGEPAGE    (OPT_PAGE2048 | OPT_PAGE4096) /* 2048 & 4096-byte page chips */
 #define OPT_SMALLPAGE    (OPT_PAGE512) /* 512-byte page chips */
 
 /* Remove action bits from state */
@@ -858,13 +853,18 @@ static int init_nandsim(struct mtd_info *mtd, struct nandsim_params *nsparam)
 		ns->options |= OPT_PAGE512;
 		if (ns->busw == 8)
 			ns->options |= OPT_PAGE512_8BIT;
-	} else if (ns->geom.pgsz == 2048) {
-		ns->options |= OPT_PAGE2048;
-	} else if (ns->geom.pgsz == 4096) {
-		ns->options |= OPT_PAGE4096;
-	} else {
-		pr_err("unknown page size %u\n", ns->geom.pgsz);
-		return -EIO;
+	} else if (ns->geom.pgsz >= 2048) {
+		ns->options |= OPT_LARGEPAGE;
+	}
+
+	if (!is_power_of_2(ns->geom.pgsz)) {
+		pr_err("page size is not a power of two.\n");
+		return -EINVAL;
+	}
+
+	if (ns->geom.pgszoob > KMALLOC_MAX_SIZE) {
+		pr_err("page size plus oob too large: %u.\n", ns->geom.pgszoob);
+		return -EINVAL;
 	}
 
 	if (ns->options & OPT_SMALLPAGE) {
-- 
2.8.3

[toc] | [prev] | [next] | [standalone]


#1487976 — [PATCH v2 32/46] mtd: nandsim: Remove NS_IS_INITIALIZED

FromDaniel Walter <dwalter@sigma-star.at>
Date2016-09-21 12:00 +0200
Subject[PATCH v2 32/46] mtd: nandsim: Remove NS_IS_INITIALIZED
Message-ID<sjMtP-7lX-25@gated-at.bofh.it>
In reply to#1487952
From: Richard Weinberger <richard@nod.at>

init_nandsim() has exactly one caller, the construction
function. So, checking for this condition makes no sense.

Signed-off-by: Richard Weinberger <richard@nod.at>
---
 drivers/mtd/nand/nandsim.c | 8 --------
 1 file changed, 8 deletions(-)

diff --git a/drivers/mtd/nand/nandsim.c b/drivers/mtd/nand/nandsim.c
index 915e3bb..971f7b4 100644
--- a/drivers/mtd/nand/nandsim.c
+++ b/drivers/mtd/nand/nandsim.c
@@ -185,9 +185,6 @@ MODULE_PARM_DESC(defaults,	 "Register a MTD during module load using default val
 #define NS_MDELAY(ns, us) \
 	do { if (ns->do_delays) mdelay(us); } while (0)
 
-/* Is the nandsim structure initialized ? */
-#define NS_IS_INITIALIZED(ns) ((ns)->geom.totsz != 0)
-
 /* Good operation completion status */
 #define NS_STATUS_OK(ns) (NAND_STATUS_READY | (NAND_STATUS_WP * ((ns)->lines.wp == 0)))
 
@@ -839,11 +836,6 @@ static int init_nandsim(struct mtd_info *mtd, struct nandsim_params *nsparam)
 	uint64_t remains;
 	uint64_t next_offset;
 
-	if (NS_IS_INITIALIZED(ns)) {
-		pr_err("init_nandsim: nandsim is already initialized\n");
-		return -EIO;
-	}
-
 	/* Force mtd to not do delays */
 	chip->chip_delay = 0;
 
-- 
2.8.3

[toc] | [prev] | [next] | [standalone]


#1487978 — [PATCH v2 45/46] mtd: nandsim: Always answer all 8 bytes from NAND_CMD_READID

FromDaniel Walter <dwalter@sigma-star.at>
Date2016-09-21 12:00 +0200
Subject[PATCH v2 45/46] mtd: nandsim: Always answer all 8 bytes from NAND_CMD_READID
Message-ID<sjMtP-7lX-15@gated-at.bofh.it>
In reply to#1487952
From: Richard Weinberger <richard@nod.at>

nand base reads the full 8 byte NAND ID, no matter
how many id bytes we have configured.

So, instead of getting confused return all bytes
even when they are not configured (0xff).

Fixes error messages such as:
nandsim: unexpected data output cycle, state is STATE_READY return 0x0

Signed-off-by: Richard Weinberger <richard@nod.at>
---
 drivers/mtd/nand/nandsim.c | 15 ++-------------
 1 file changed, 2 insertions(+), 13 deletions(-)

diff --git a/drivers/mtd/nand/nandsim.c b/drivers/mtd/nand/nandsim.c
index 5d82a0a..b901155 100644
--- a/drivers/mtd/nand/nandsim.c
+++ b/drivers/mtd/nand/nandsim.c
@@ -56,8 +56,6 @@
 
 #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
@@ -87,9 +85,7 @@ static unsigned int bch;
 static u_char id_bytes[8] = {
 	[0] = NANDSIM_FIRST_ID_BYTE,
 	[1] = NANDSIM_SECOND_ID_BYTE,
-	[2] = NANDSIM_THIRD_ID_BYTE,
-	[3] = NANDSIM_FOURTH_ID_BYTE,
-	[4 ... 7] = 0xFF,
+	[2 ... 7] = 0xFF,
 };
 static bool defaults = true;
 
@@ -3064,14 +3060,7 @@ struct mtd_info *ns_new_instance(struct nandsim_params *nsparam)
 	 * Perform minimum nandsim structure initialization to handle
 	 * the initial ID read command correctly
 	 */
-	if (id_bytes[6] != 0xFF || id_bytes[7] != 0xFF)
-		nand->geom.idbytes = 8;
-	else if (id_bytes[4] != 0xFF || id_bytes[5] != 0xFF)
-		nand->geom.idbytes = 6;
-	else if (id_bytes[2] != 0xFF || id_bytes[3] != 0xFF)
-		nand->geom.idbytes = 4;
-	else
-		nand->geom.idbytes = 2;
+	nand->geom.idbytes = sizeof(id_bytes);
 	nand->regs.status = NS_STATUS_OK(nand);
 	nand->nxstate = STATE_UNKNOWN;
 	nand->options |= OPT_PAGE512; /* temporary value */
-- 
2.8.3

[toc] | [prev] | [next] | [standalone]


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

FromDaniel Walter <dwalter@sigma-star.at>
Date2016-09-21 12:00 +0200
Subject[PATCH v2 17/46] mtd: nandsim: Allow external backends
Message-ID<sjMtP-7lX-17@gated-at.bofh.it>
In reply to#1487952
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]


#1487980 — [PATCH v2 44/46] mtd: nandsim: Wire up NANDSIM_IOC_DESTROY_INSTANCE

FromDaniel Walter <dwalter@sigma-star.at>
Date2016-09-21 12:00 +0200
Subject[PATCH v2 44/46] mtd: nandsim: Wire up NANDSIM_IOC_DESTROY_INSTANCE
Message-ID<sjMtQ-7lX-31@gated-at.bofh.it>
In reply to#1487952
From: Richard Weinberger <richard@nod.at>

The logic for destroying nandsim instances now also ready.

Signed-off-by: Richard Weinberger <richard@nod.at>
---
 drivers/mtd/nand/nandsim.c | 13 +++++++++++++
 1 file changed, 13 insertions(+)

diff --git a/drivers/mtd/nand/nandsim.c b/drivers/mtd/nand/nandsim.c
index bb30763..5d82a0a 100644
--- a/drivers/mtd/nand/nandsim.c
+++ b/drivers/mtd/nand/nandsim.c
@@ -2922,6 +2922,19 @@ static long ns_ctrl_ioctl(struct file *file, unsigned int cmd,
 			ret = ns_ctrl_new_instance(&req, argp + sizeof(req));
 			break;
 		}
+		case NANDSIM_IOC_DESTROY_INSTANCE:
+		{
+			struct ns_destroy_instance_req req;
+
+			ret = copy_from_user(&req, argp, sizeof(struct ns_destroy_instance_req));
+			if (ret) {
+				ret = -EFAULT;
+				goto out;
+			}
+
+			ret = ns_ctrl_destroy_instance(&req);
+			break;
+		}
 
 		default:
 			ret = -ENOTTY;
-- 
2.8.3

[toc] | [prev] | [next] | [standalone]


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

FromDaniel Walter <dwalter@sigma-star.at>
Date2016-09-21 12:00 +0200
Subject[PATCH v2 21/46] mtd: nandsim: Implement preliminary destructor function
Message-ID<sjMtP-7lX-19@gated-at.bofh.it>
In reply to#1487952
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  | 81 +++++++++++++++++++++++++++++++++++++++++++--
 include/linux/mtd/nandsim.h |  2 +-
 2 files changed, 79 insertions(+), 4 deletions(-)

diff --git a/drivers/mtd/nand/nandsim.c b/drivers/mtd/nand/nandsim.c
index 344f5c4..bac3fde 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,16 @@ 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 = mtd_device_unregister(nsmtd);
+	if (ret)
+		return ret;
+	nand_cleanup(nsmtd);
 
 	nandsim_debugfs_remove(ns);
 	free_lists(ns);
@@ -2763,6 +2836,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 +2848,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]


#1488107 — Re: [PATCH v2 21/46] mtd: nandsim: Implement preliminary destructor function

Fromkbuild test robot <lkp@intel.com>
Date2016-09-21 15:00 +0200
SubjectRe: [PATCH v2 21/46] mtd: nandsim: Implement preliminary destructor function
Message-ID<sjPi2-Ff-3@gated-at.bofh.it>
In reply to#1487981

[Multipart message — attachments visible in raw view] — view raw

Hi Richard,

[auto build test ERROR on mtd/master]
[also build test ERROR on v4.8-rc7]
[cannot apply to next-20160921]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]
[Suggest to use git(>=2.9.0) format-patch --base=<commit> (or --base=auto for convenience) to record what (public, well-known) commit your patch series was built on]
[Check https://git-scm.com/docs/git-format-patch for more information]

url:    https://github.com/0day-ci/linux/commits/Daniel-Walter/Nandsim-facelift-part-I-of-II/20160921-182636
base:   git://git.infradead.org/linux-mtd.git master
config: i386-randconfig-s1-201638 (attached as .config)
compiler: gcc-6 (Debian 6.2.0-3) 6.2.0 20160901
reproduce:
        # save the attached .config to linux build tree
        make ARCH=i386 

All errors (new ones prefixed by >>):

>> ERROR: "nand_cleanup" [drivers/mtd/nand/nandsim.ko] undefined!

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation

[toc] | [prev] | [next] | [standalone]


#1487983 — [PATCH v2 29/46] um: Add nandsim backend driver

FromDaniel Walter <dwalter@sigma-star.at>
Date2016-09-21 12:00 +0200
Subject[PATCH v2 29/46] um: Add nandsim backend driver
Message-ID<sjMtQ-7lX-29@gated-at.bofh.it>
In reply to#1487952
From: Richard Weinberger <richard@nod.at>

Add a small UML driver to act as nandsim backend.
This allows us to use the nandsim MTD as root device
and boot from it.
e.g. ./linux mem=512M unand.backing_file=/home/rw/work/ubifs/mtd4.raw \
 unand.id_bytes=0x1c,0xd3,0x90,0xa6 unand.no_oob=y nandsim.defaults=n \
 ubi.mtd=0 rootfstype=ubifs root=ubi0:rootfs

Signed-off-by: Richard Weinberger <richard@nod.at>
---
 arch/um/Kconfig.um          |   6 ++
 arch/um/drivers/Makefile    |   2 +
 arch/um/drivers/nand_kern.c | 159 ++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 167 insertions(+)
 create mode 100644 arch/um/drivers/nand_kern.c

diff --git a/arch/um/Kconfig.um b/arch/um/Kconfig.um
index 4b2ed58..f7a1a17 100644
--- a/arch/um/Kconfig.um
+++ b/arch/um/Kconfig.um
@@ -44,6 +44,12 @@ config HOSTFS
           If you'd like to be able to work with files stored on the host,
           say Y or M here; otherwise say N.
 
+config UML_NANDSIM
+	tristate "UML nandsim backend"
+	help
+	  Use a file on the host directly as backend for nandsim.
+	  For more help, see modinfo unand.
+
 config MCONSOLE
 	bool "Management console"
 	depends on PROC_FS
diff --git a/arch/um/drivers/Makefile b/arch/um/drivers/Makefile
index e7582e1..08a806e 100644
--- a/arch/um/drivers/Makefile
+++ b/arch/um/drivers/Makefile
@@ -16,6 +16,7 @@ hostaudio-objs := hostaudio_kern.o
 ubd-objs := ubd_kern.o ubd_user.o
 port-objs := port_kern.o port_user.o
 harddog-objs := harddog_kern.o harddog_user.o
+unand-objs := nand_kern.o
 
 LDFLAGS_pcap.o := -r $(shell $(CC) $(KBUILD_CFLAGS) -print-file-name=libpcap.a)
 
@@ -59,6 +60,7 @@ obj-$(CONFIG_XTERM_CHAN) += xterm.o xterm_kern.o
 obj-$(CONFIG_UML_WATCHDOG) += harddog.o
 obj-$(CONFIG_BLK_DEV_COW_COMMON) += cow_user.o
 obj-$(CONFIG_UML_RANDOM) += random.o
+obj-$(CONFIG_UML_NANDSIM) += unand.o
 
 # pcap_user.o must be added explicitly.
 USER_OBJS := fd.o null.o pty.o tty.o xterm.o slip_common.o pcap_user.o vde_user.o
diff --git a/arch/um/drivers/nand_kern.c b/arch/um/drivers/nand_kern.c
new file mode 100644
index 0000000..399d9e6
--- /dev/null
+++ b/arch/um/drivers/nand_kern.c
@@ -0,0 +1,159 @@
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/nandsim.h>
+#include <init.h>
+#include <os.h>
+
+static u_char id_bytes[8] = {
+	[0 ... 7] = 0xFF,
+};
+static bool no_oob;
+static char *backing_file;
+static unsigned int bus_width;
+
+module_param_array(id_bytes, byte, NULL, 0400);
+module_param(no_oob, bool, 0400);
+module_param(backing_file, charp, 0400);
+module_param(bus_width, uint, 0400);
+
+MODULE_PARM_DESC(backing_file, "File to use as backing store");
+MODULE_PARM_DESC(id_bytes, "The ID bytes returned by NAND Flash 'read ID' command");
+MODULE_PARM_DESC(no_oob, "Set to use an image without OOB data, i.e created by nanddump");
+MODULE_PARM_DESC(bus_width, "Chip's bus width (8- or 16-bit)");
+
+struct ns_uml_data {
+	int fd;
+	void *file_buf;
+};
+
+/*
+ * We support only one instance so far, just to boot from MTD.
+ * If you need more MTDs, use nandsimctl(8).
+ */
+static struct mtd_info *nsmtd;
+
+static int file_read(struct nandsim *ns, char *addr, unsigned long count,
+		     loff_t offset)
+{
+	struct ns_uml_data *data = nandsim_get_backend_data(ns);
+
+	return os_pread_file(data->fd, addr, count, offset);
+}
+
+static ssize_t file_write(struct nandsim *ns, const char *addr, size_t count,
+			  loff_t offset)
+{
+	struct ns_uml_data *data = nandsim_get_backend_data(ns);
+
+	return os_pwrite_file(data->fd, addr, count, offset);
+}
+
+static void ns_uml_read_page(struct nandsim *ns, int num)
+{
+	__ns_file_read_page(ns, num, file_read);
+}
+
+static int ns_uml_prog_page(struct nandsim *ns, int num)
+{
+	struct ns_uml_data *data = nandsim_get_backend_data(ns);
+
+	return __ns_file_prog_page(ns, num, data->file_buf, file_read,
+				   file_write);
+}
+
+static void ns_uml_erase_sector(struct nandsim *ns)
+{
+	struct ns_uml_data *data = nandsim_get_backend_data(ns);
+
+	__ns_file_erase_sector(ns, data->file_buf, file_write);
+}
+
+static int ns_uml_init(struct nandsim *ns, struct nandsim_params *nsparam)
+{
+	struct ns_uml_data *data = kzalloc(sizeof(*data), GFP_KERNEL);
+
+	if (!data)
+		return -ENOMEM;
+
+	data->file_buf = kmalloc(nandsim_get_geom(ns)->pgszoob, GFP_KERNEL);
+	if (!data->file_buf) {
+		kfree(data);
+		return -ENOMEM;
+	}
+
+	data->fd = os_open_file(nsparam->cache_file, of_set_rw(OPENFLAGS(), 1, 1), 0);
+	if (data->fd < 0) {
+		printk(KERN_ERR "Unable to open %s: %i\n", nsparam->cache_file, data->fd);
+		kfree(data->file);
+		kfree(data);
+		return data->fd;
+	}
+
+	nandsim_set_backend_data(ns, data);
+
+	return 0;
+}
+
+static void ns_uml_destroy(struct nandsim *ns)
+{
+	struct ns_uml_data *data = nandsim_get_backend_data(ns);
+
+	if (!data)
+		return;
+
+	os_close_file(data->fd);
+	kfree(data->file_buf);
+	kfree(data);
+}
+
+static struct ns_backend_ops ns_uml_bops = {
+	.erase_sector = ns_uml_erase_sector,
+	.prog_page = ns_uml_prog_page,
+	.read_page = ns_uml_read_page,
+	.init = ns_uml_init,
+	.destroy = ns_uml_destroy,
+	.name = "uml",
+};
+
+static struct nandsim_params params = {
+	.bops = &ns_uml_bops,
+};
+
+static int __init uml_ns_init(void)
+{
+	struct mtd_info *ret;
+
+	if (!backing_file)
+		return 0;
+
+	params.cache_file = backing_file;
+	params.bus_width = bus_width;
+	params.no_oob = no_oob;
+	memcpy(params.id_bytes, id_bytes, sizeof(params.id_bytes));
+
+	ret = ns_new_instance(&params);
+	if (IS_ERR(ret))
+		return PTR_ERR(ret);
+
+	nsmtd = ret;
+
+	return 0;
+}
+late_initcall(uml_ns_init);
+
+static void __exit uml_ns_exit(void)
+{
+	/*
+	 * Since this driver is a singleton we can rely on module refcounting,
+	 * and assume that ns_destroy_instance() will succeed in any case.
+	 * If not, print a frindly warning. B-)
+	 */
+	WARN_ON(ns_destroy_instance(nsmtd) != 0);
+}
+module_exit(uml_ns_exit);
+
+MODULE_AUTHOR("Richard Weinberger");
+MODULE_DESCRIPTION("UML nandsim backend");
+MODULE_LICENSE("GPL");
+
-- 
2.8.3

[toc] | [prev] | [next] | [standalone]


#1487984 — [PATCH v2 39/46] mtd: nandsim: Rework init error paths

FromDaniel Walter <dwalter@sigma-star.at>
Date2016-09-21 12:00 +0200
Subject[PATCH v2 39/46] mtd: nandsim: Rework init error paths
Message-ID<sjMtQ-7lX-33@gated-at.bofh.it>
In reply to#1487952
From: Richard Weinberger <richard@nod.at>

Signed-off-by: Richard Weinberger <richard@nod.at>
---
 drivers/mtd/nand/nandsim.c | 97 +++++++++++++++++++++++++++-------------------
 1 file changed, 57 insertions(+), 40 deletions(-)

diff --git a/drivers/mtd/nand/nandsim.c b/drivers/mtd/nand/nandsim.c
index 6b7570b..92f5efc 100644
--- a/drivers/mtd/nand/nandsim.c
+++ b/drivers/mtd/nand/nandsim.c
@@ -871,12 +871,14 @@ static int init_nandsim(struct mtd_info *mtd, struct nandsim_params *nsparam)
 
 		if (!part_sz || part_sz > remains) {
 			pr_err("bad partition size.\n");
-			return -EINVAL;
+			ret = -EINVAL;
+			goto err_names;
 		}
 		ns->partitions[i].name = get_partition_name(ns, i);
 		if (!ns->partitions[i].name) {
 			pr_err("unable to allocate memory.\n");
-			return -ENOMEM;
+			ret = -ENOMEM;
+			goto err_names;
 		}
 		ns->partitions[i].offset = next_offset;
 		ns->partitions[i].size   = part_sz;
@@ -887,12 +889,14 @@ static int init_nandsim(struct mtd_info *mtd, struct nandsim_params *nsparam)
 	if (remains) {
 		if (nsparam->parts_num + 1 > ARRAY_SIZE(ns->partitions)) {
 			pr_err("too many partitions.\n");
-			return -EINVAL;
+			ret = -EINVAL;
+			goto err_names;
 		}
 		ns->partitions[i].name = get_partition_name(ns, i);
 		if (!ns->partitions[i].name) {
 			pr_err("unable to allocate memory.\n");
-			return -ENOMEM;
+			ret = -ENOMEM;
+			goto err_names;
 		}
 		ns->partitions[i].offset = next_offset;
 		ns->partitions[i].size   = remains;
@@ -921,22 +925,24 @@ static int init_nandsim(struct mtd_info *mtd, struct nandsim_params *nsparam)
 
 	ns->bops = nsparam->bops;
 
-	pr_info("Using backend: %s\n", ns->bops->name);
-	if ((ret = ns->bops->init(ns, nsparam)) != 0) {
-		pr_err("Unable to initialize simulator backend: %i\n", ret);
-		return ret;
-	}
-
 	/* 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);
-		return -ENOMEM;
+		ret = -ENOMEM;
+		goto err_buf;
 	}
 	memset(ns->buf.byte, 0xFF, ns->geom.pgszoob);
 
 	return 0;
+
+err_buf:
+	kfree(ns->buf.byte);
+err_names:
+	for (i = 0; i < ARRAY_SIZE(ns->partitions); i++)
+		kfree(ns->partitions[i].name);
+	return ret;
 }
 
 /*
@@ -944,8 +950,11 @@ static int init_nandsim(struct mtd_info *mtd, struct nandsim_params *nsparam)
  */
 static void free_nandsim(struct nandsim *ns)
 {
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(ns->partitions); i++)
+		kfree(ns->partitions[i].name);
 	kfree(ns->buf.byte);
-	ns->bops->destroy(ns);
 }
 
 static int parse_badblocks(struct nandsim *ns, struct mtd_info *mtd,
@@ -2751,7 +2760,7 @@ struct mtd_info *ns_new_instance(struct nandsim_params *nsparam)
 		pr_err("Cannot allocate more than %i instances!\n", NANDSIM_MAX_DEVICES);
 		retval = -ENFILE;
 		mutex_unlock(&ns_mtd_mutex);
-		goto error;
+		goto err_chip;
 	}
 
 	nsmtd = ns_mtds[i] = nand_to_mtd(chip);
@@ -2789,7 +2798,7 @@ struct mtd_info *ns_new_instance(struct nandsim_params *nsparam)
 	default:
 		pr_err("bbt has to be 0..2\n");
 		retval = -EINVAL;
-		goto error;
+		goto err_mtds;
 	}
 	/*
 	 * Perform minimum nandsim structure initialization to handle
@@ -2817,13 +2826,13 @@ struct mtd_info *ns_new_instance(struct nandsim_params *nsparam)
 	nsmtd->_put_device = ns_put_device;
 
 	if ((retval = parse_weakblocks(nand, nsparam->weakblocks)) != 0)
-		goto error;
+		goto err_lists;
 
 	if ((retval = parse_weakpages(nand, nsparam->weakpages)) != 0)
-		goto error;
+		goto err_lists;
 
 	if ((retval = parse_gravepages(nand, nsparam->gravepages)) != 0)
-		goto error;
+		goto err_lists;
 
 	nand->do_delays = nsparam->do_delays;
 	nand->access_delay = nsparam->access_delay;
@@ -2838,14 +2847,14 @@ struct mtd_info *ns_new_instance(struct nandsim_params *nsparam)
 		pr_err("cannot scan NAND Simulator device\n");
 		if (retval > 0)
 			retval = -ENXIO;
-		goto error;
+		goto err_lists;
 	}
 
 	if (nsparam->no_oob) {
 		if (nsparam->bch) {
 			pr_err("Cannot use ECC without OOB\n");
 			retval = -EINVAL;
-			goto error;
+			goto err_lists;
 		}
 
 		chip->ecc.mode = NAND_ECC_NONE;
@@ -2855,7 +2864,7 @@ struct mtd_info *ns_new_instance(struct nandsim_params *nsparam)
 		if (!mtd_nand_has_bch()) {
 			pr_err("BCH ECC support is disabled\n");
 			retval = -EINVAL;
-			goto error;
+			goto err_lists;
 		}
 		/* use 512-byte ecc blocks */
 		eccsteps = nsmtd->writesize/512;
@@ -2864,12 +2873,12 @@ struct mtd_info *ns_new_instance(struct nandsim_params *nsparam)
 		if ((nsmtd->oobsize < 64) || !eccsteps) {
 			pr_err("bch not available on small page devices\n");
 			retval = -EINVAL;
-			goto error;
+			goto err_lists;
 		}
 		if ((eccbytes*eccsteps+2) > nsmtd->oobsize) {
 			pr_err("invalid bch value %u\n", nsparam->bch);
 			retval = -EINVAL;
-			goto error;
+			goto err_lists;
 		}
 		chip->ecc.mode = NAND_ECC_SOFT;
 		chip->ecc.algo = NAND_ECC_BCH;
@@ -2887,7 +2896,7 @@ struct mtd_info *ns_new_instance(struct nandsim_params *nsparam)
 		pr_err("can't register NAND Simulator\n");
 		if (retval > 0)
 			retval = -ENXIO;
-		goto error;
+		goto err_lists;
 	}
 
 	if (nsparam->overridesize) {
@@ -2895,7 +2904,7 @@ struct mtd_info *ns_new_instance(struct nandsim_params *nsparam)
 		if (new_size >> nsparam->overridesize != nsmtd->erasesize) {
 			pr_err("overridesize is too big\n");
 			retval = -EINVAL;
-			goto err_exit;
+			goto err_nand;
 		}
 		/* N.B. This relies on nand_scan not doing anything with the size before we change it */
 		nsmtd->size = new_size;
@@ -2905,35 +2914,45 @@ struct mtd_info *ns_new_instance(struct nandsim_params *nsparam)
 	}
 
 	if ((retval = setup_wear_reporting(nsmtd)) != 0)
-		goto err_exit;
+		goto err_nand;
 
 	if ((retval = nandsim_debugfs_create(nand)) != 0)
-		goto err_exit;
+		goto err_nand;
 
 	if ((retval = init_nandsim(nsmtd, nsparam)) != 0)
-		goto err_exit;
+		goto err_debugfs;
+
+	pr_info("Using backend: %s\n", nand->bops->name);
+	if ((retval = nand->bops->init(nand, nsparam)) != 0) {
+		pr_err("Unable to initialize simulator backend: %i\n", retval);
+		goto err_nandsim;
+	}
 
 	if ((retval = chip->scan_bbt(nsmtd)) != 0)
-		goto err_exit;
+		goto err_nandsim;
 
 	if ((retval = parse_badblocks(nand, nsmtd, nsparam->badblocks)) != 0)
-		goto err_exit;
+		goto err_nandsim;
 
 	/* Register NAND partitions */
 	retval = mtd_device_register(nsmtd, &nand->partitions[0],
 				     nand->nbparts);
 	if (retval != 0)
-		goto err_exit;
+		goto err_nandsim;
 
 	return nsmtd;
 
-err_exit:
+err_nandsim:
 	free_nandsim(nand);
+err_debugfs:
+	nandsim_debugfs_remove(nand);
+err_nand:
 	nand_release(nsmtd);
-	for (i = 0;i < ARRAY_SIZE(nand->partitions); ++i)
-		kfree(nand->partitions[i].name);
-error:
+err_lists:
 	free_lists(nand);
+err_mtds:
+	ns_mtds[nand->index] = NULL;
+err_chip:
 	kfree(chip);
 
 	return ERR_PTR(retval);
@@ -2942,7 +2961,7 @@ EXPORT_SYMBOL_GPL(ns_new_instance);
 
 int ns_destroy_instance(struct mtd_info *nsmtd)
 {
-	int i, ret;
+	int ret;
 	struct nand_chip *chip = mtd_to_nand(nsmtd);
 	struct nandsim *ns = nand_get_controller_data(chip);
 
@@ -2952,12 +2971,10 @@ int ns_destroy_instance(struct mtd_info *nsmtd)
 	nand_cleanup(nsmtd);
 
 	nandsim_debugfs_remove(ns);
+	ns->bops->destroy(ns);
+	free_nandsim(ns);
 	free_lists(ns);
-	free_nandsim(ns);    /* Free nandsim private resources */
-	nand_release(nsmtd); /* Unregister driver */
-	for (i = 0;i < ARRAY_SIZE(ns->partitions); ++i)
-		kfree(ns->partitions[i].name);
-	kfree(mtd_to_nand(nsmtd));        /* Free other structures */
+	kfree(chip);
 
 	return 0;
 }
-- 
2.8.3

[toc] | [prev] | [next] | [standalone]


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

FromDaniel Walter <dwalter@sigma-star.at>
Date2016-09-21 12:00 +0200
Subject[PATCH v2 28/46] mtd: nandsim: Refine exports
Message-ID<sjMtQ-7lX-35@gated-at.bofh.it>
In reply to#1487952
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 c93d946..cf2694f 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]


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

FromDaniel Walter <dwalter@sigma-star.at>
Date2016-09-21 12:00 +0200
Subject[PATCH v2 26/46] mtd: nandsim: use the existing output macros
Message-ID<sjMtQ-7lX-39@gated-at.bofh.it>
In reply to#1487952
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 f8e5687..7a95802 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]


Page 2 of 3 — ← Prev page 1 [2] 3  Next page →

Back to top | Article view | linux.kernel


csiph-web