Patchwork mtdchar: handle chips that have user otp but no factory otp

login
register
mail settings
Submitter Uwe Kleine-König
Date Feb. 18, 2013, 10:19 a.m.
Message ID <1361182768-31919-1-git-send-email-u.kleine-koenig@pengutronix.de>
Download mbox | patch
Permalink /patch/221191/
State New
Headers show

Comments

Uwe Kleine-König - Feb. 18, 2013, 10:19 a.m.
Before this patch mtd_read_fact_prot_reg was used to check availability
for both MTD_OTP_FACTORY and MTD_OTP_USER access. This made accessing
user otp for chips that don't have a factory otp area impossible. So use
the right wrapper depending on the intended area to be accessed.

Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
---
Hello,

I'm currently working on accessing the user otp area of MT29F2G nand
flash that doesn't have a factory otp. Reading and writing are not ready
yet, but this change is an obvious prerequisite.

Best regards
Uwe

 drivers/mtd/mtdchar.c |   30 +++++++++++++++++++-----------
 1 file changed, 19 insertions(+), 11 deletions(-)
Artem Bityutskiy - March 2, 2013, 3:41 p.m.
On Mon, 2013-02-18 at 11:19 +0100, Uwe Kleine-König wrote:
> Before this patch mtd_read_fact_prot_reg was used to check availability
> for both MTD_OTP_FACTORY and MTD_OTP_USER access. This made accessing
> user otp for chips that don't have a factory otp area impossible. So use
> the right wrapper depending on the intended area to be accessed.
> 
> Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
> ---
> Hello,
> 
> I'm currently working on accessing the user otp area of MT29F2G nand
> flash that doesn't have a factory otp. Reading and writing are not ready
> yet, but this change is an obvious prerequisite.
> 
> Best regards
> Uwe
> 
>  drivers/mtd/mtdchar.c |   30 +++++++++++++++++++-----------
>  1 file changed, 19 insertions(+), 11 deletions(-)
> 
> diff --git a/drivers/mtd/mtdchar.c b/drivers/mtd/mtdchar.c
> index a6e7451..1f4034a 100644
> --- a/drivers/mtd/mtdchar.c
> +++ b/drivers/mtd/mtdchar.c
> @@ -371,26 +371,34 @@ static int otp_select_filemode(struct mtd_file_info *mfi, int mode)
>  	struct mtd_info *mtd = mfi->mtd;
>  	size_t retlen;
>  	int ret = 0;
> -
> -	/*
> -	 * Make a fake call to mtd_read_fact_prot_reg() to check if OTP
> -	 * operations are supported.
> -	 */
> -	if (mtd_read_fact_prot_reg(mtd, -1, 0, &retlen, NULL) == -EOPNOTSUPP)
> -		return -EOPNOTSUPP;
> +	int (*func)(struct mtd_info *, loff_t, size_t, size_t *, u_char *) =
> +		NULL;
> +	enum mtd_file_modes outmode = MTD_FILE_MODE_NORMAL;

In this particular case when we only have 2 modes I'd prefer to not
introduce a function pointer variable but directly call the function.
>  
>  	switch (mode) {
>  	case MTD_OTP_FACTORY:
> -		mfi->mode = MTD_FILE_MODE_OTP_FACTORY;
> +		outmode = MTD_FILE_MODE_OTP_FACTORY;
> +		func = mtd_read_fact_prot_reg;
>  		break;
>  	case MTD_OTP_USER:
> -		mfi->mode = MTD_FILE_MODE_OTP_USER;
> +		outmode = MTD_FILE_MODE_OTP_USER;
> +		func = mtd_read_user_prot_reg;
>  		break;
> -	default:
> -		ret = -EINVAL;
>  	case MTD_OTP_OFF:
>  		break;
> +	default:
> +		ret = -EINVAL;

Probably in this case you need to 'return -EINVAL', otherwise you modify
'mfi->mode' below which is an unexpected side-effect of '-EINVAL'.
>  	}
> +
> +	/*
> +	 * Make a fake call to mtd_read_fact_prot_reg() or
> +	 * mtd_read_user_prot_reg() to check if OTP operations are supported.
> +	 */
> +	if (func && func(mtd, -1, 0, &retlen, NULL) == -EOPNOTSUPP)
> +		return -EOPNOTSUPP;
> +
> +	mfi->mode = outmode;
> +
>  	return ret;
>  }
>  #else
Uwe Kleine-König - March 2, 2013, 9:08 p.m.
Hello,

On Sat, Mar 02, 2013 at 05:41:24PM +0200, Artem Bityutskiy wrote:
> On Mon, 2013-02-18 at 11:19 +0100, Uwe Kleine-König wrote:
> > Before this patch mtd_read_fact_prot_reg was used to check availability
> > for both MTD_OTP_FACTORY and MTD_OTP_USER access. This made accessing
> > user otp for chips that don't have a factory otp area impossible. So use
> > the right wrapper depending on the intended area to be accessed.
> > 
> > Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
> > ---
> > Hello,
> > 
> > I'm currently working on accessing the user otp area of MT29F2G nand
> > flash that doesn't have a factory otp. Reading and writing are not ready
> > yet, but this change is an obvious prerequisite.
> > 
> > Best regards
> > Uwe
> > 
> >  drivers/mtd/mtdchar.c |   30 +++++++++++++++++++-----------
> >  1 file changed, 19 insertions(+), 11 deletions(-)
> > 
> > diff --git a/drivers/mtd/mtdchar.c b/drivers/mtd/mtdchar.c
> > index a6e7451..1f4034a 100644
> > --- a/drivers/mtd/mtdchar.c
> > +++ b/drivers/mtd/mtdchar.c
> > @@ -371,26 +371,34 @@ static int otp_select_filemode(struct mtd_file_info *mfi, int mode)
> >  	struct mtd_info *mtd = mfi->mtd;
> >  	size_t retlen;
> >  	int ret = 0;
> > -
> > -	/*
> > -	 * Make a fake call to mtd_read_fact_prot_reg() to check if OTP
> > -	 * operations are supported.
> > -	 */
> > -	if (mtd_read_fact_prot_reg(mtd, -1, 0, &retlen, NULL) == -EOPNOTSUPP)
> > -		return -EOPNOTSUPP;
> > +	int (*func)(struct mtd_info *, loff_t, size_t, size_t *, u_char *) =
> > +		NULL;
> > +	enum mtd_file_modes outmode = MTD_FILE_MODE_NORMAL;
> 
> In this particular case when we only have 2 modes I'd prefer to not
> introduce a function pointer variable but directly call the function.
I choosed the function pointer to reduce code duplication. Do function
pointer have a bad characteristic that I don't know? But actually I
don't care much and can resend without the function pointer.
> >  
> >  	switch (mode) {
> >  	case MTD_OTP_FACTORY:
> > -		mfi->mode = MTD_FILE_MODE_OTP_FACTORY;
> > +		outmode = MTD_FILE_MODE_OTP_FACTORY;
> > +		func = mtd_read_fact_prot_reg;
> >  		break;
> >  	case MTD_OTP_USER:
> > -		mfi->mode = MTD_FILE_MODE_OTP_USER;
> > +		outmode = MTD_FILE_MODE_OTP_USER;
> > +		func = mtd_read_user_prot_reg;
> >  		break;
> > -	default:
> > -		ret = -EINVAL;
> >  	case MTD_OTP_OFF:
> >  		break;
> > +	default:
> > +		ret = -EINVAL;
> 
> Probably in this case you need to 'return -EINVAL', otherwise you modify
> 'mfi->mode' below which is an unexpected side-effect of '-EINVAL'.
I don't remember, but I think I convinced myself that it doesn't hurt.
Still it's less surprising to not modify mfi, so OK.

Uwe

> >  	}
> > +
> > +	/*
> > +	 * Make a fake call to mtd_read_fact_prot_reg() or
> > +	 * mtd_read_user_prot_reg() to check if OTP operations are supported.
> > +	 */
> > +	if (func && func(mtd, -1, 0, &retlen, NULL) == -EOPNOTSUPP)
> > +		return -EOPNOTSUPP;
> > +
> > +	mfi->mode = outmode;
> > +
> >  	return ret;
> >  }
> >  #else
> 
> -- 
> Best Regards,
> Artem Bityutskiy
> 
>

Patch

diff --git a/drivers/mtd/mtdchar.c b/drivers/mtd/mtdchar.c
index a6e7451..1f4034a 100644
--- a/drivers/mtd/mtdchar.c
+++ b/drivers/mtd/mtdchar.c
@@ -371,26 +371,34 @@  static int otp_select_filemode(struct mtd_file_info *mfi, int mode)
 	struct mtd_info *mtd = mfi->mtd;
 	size_t retlen;
 	int ret = 0;
-
-	/*
-	 * Make a fake call to mtd_read_fact_prot_reg() to check if OTP
-	 * operations are supported.
-	 */
-	if (mtd_read_fact_prot_reg(mtd, -1, 0, &retlen, NULL) == -EOPNOTSUPP)
-		return -EOPNOTSUPP;
+	int (*func)(struct mtd_info *, loff_t, size_t, size_t *, u_char *) =
+		NULL;
+	enum mtd_file_modes outmode = MTD_FILE_MODE_NORMAL;
 
 	switch (mode) {
 	case MTD_OTP_FACTORY:
-		mfi->mode = MTD_FILE_MODE_OTP_FACTORY;
+		outmode = MTD_FILE_MODE_OTP_FACTORY;
+		func = mtd_read_fact_prot_reg;
 		break;
 	case MTD_OTP_USER:
-		mfi->mode = MTD_FILE_MODE_OTP_USER;
+		outmode = MTD_FILE_MODE_OTP_USER;
+		func = mtd_read_user_prot_reg;
 		break;
-	default:
-		ret = -EINVAL;
 	case MTD_OTP_OFF:
 		break;
+	default:
+		ret = -EINVAL;
 	}
+
+	/*
+	 * Make a fake call to mtd_read_fact_prot_reg() or
+	 * mtd_read_user_prot_reg() to check if OTP operations are supported.
+	 */
+	if (func && func(mtd, -1, 0, &retlen, NULL) == -EOPNOTSUPP)
+		return -EOPNOTSUPP;
+
+	mfi->mode = outmode;
+
 	return ret;
 }
 #else