* [PATCH 1/2] mtd: nand: omap: Do not use global variables
@ 2014-10-01 14:59 Rostislav Lisovy
2014-10-01 14:59 ` [PATCH 2/2] mtd: nand: omap: Synchronize access to the ECC engine Rostislav Lisovy
2014-10-02 6:44 ` [PATCH 1/2] mtd: nand: omap: Do not use global variables Roger Quadros
0 siblings, 2 replies; 4+ messages in thread
From: Rostislav Lisovy @ 2014-10-01 14:59 UTC (permalink / raw)
To: David Woodhouse, Brian Norris, pekon gupta, Tony Lindgren,
Roger Quadros, linux-mtd, linux-kernel
Cc: michal.vokac, lisovy, Rostislav Lisovy, sojkam1
Since the commit 97a288ba2cfa ("ARM: omap2+: gpmc-nand: Use
dynamic platform_device_alloc()") gpmc-nand driver supports
multiple NAND flash devices connected to the single controller.
Remove global variable to make the code thread-safe.
Signed-off-by: Rostislav Lisovy <lisovy@merica.cz>
---
drivers/mtd/nand/omap2.c | 4 +---
1 file changed, 1 insertion(+), 3 deletions(-)
diff --git a/drivers/mtd/nand/omap2.c b/drivers/mtd/nand/omap2.c
index 5967b38..24d5c6a 100644
--- a/drivers/mtd/nand/omap2.c
+++ b/drivers/mtd/nand/omap2.c
@@ -146,8 +146,6 @@ static u_char bch8_vector[] = {0xf3, 0xdb, 0x14, 0x16, 0x8b, 0xd2, 0xbe, 0xcc,
static u_char bch4_vector[] = {0x00, 0x6b, 0x31, 0xdd, 0x41, 0xbc, 0x10};
#endif
-/* oob info generated runtime depending on ecc algorithm and layout selected */
-static struct nand_ecclayout omap_oobinfo;
struct omap_nand_info {
struct nand_hw_control controller;
@@ -1794,7 +1792,7 @@ static int omap_nand_probe(struct platform_device *pdev)
}
/* populate MTD interface based on ECC scheme */
- ecclayout = &omap_oobinfo;
+ ecclayout = kzalloc(sizeof(*ecclayout), GFP_KERNEL);
switch (info->ecc_opt) {
case OMAP_ECC_HAM1_CODE_SW:
nand_chip->ecc.mode = NAND_ECC_SOFT;
--
1.9.1
^ permalink raw reply related [flat|nested] 4+ messages in thread* [PATCH 2/2] mtd: nand: omap: Synchronize access to the ECC engine 2014-10-01 14:59 [PATCH 1/2] mtd: nand: omap: Do not use global variables Rostislav Lisovy @ 2014-10-01 14:59 ` Rostislav Lisovy 2014-10-02 7:12 ` Roger Quadros 2014-10-02 6:44 ` [PATCH 1/2] mtd: nand: omap: Do not use global variables Roger Quadros 1 sibling, 1 reply; 4+ messages in thread From: Rostislav Lisovy @ 2014-10-01 14:59 UTC (permalink / raw) To: David Woodhouse, Brian Norris, pekon gupta, Tony Lindgren, Roger Quadros, linux-mtd, linux-kernel Cc: michal.vokac, lisovy, Rostislav Lisovy, sojkam1 The AM335x Technical Reference Manual (spruh73j.pdf) says "Because the ECC engine includes only one accumulation context, it can be allocated to only one chip-select at a time ... " (7.1.3.3.12.3). Since the commit 97a288ba2cfa ("ARM: omap2+: gpmc-nand: Use dynamic platform_device_alloc()") gpmc-nand driver supports multiple NAND flash devices connected to the single controller. Use spinlocks to restrict access to the ECC engine for single read/write operation at a time. Tested with custom AM335x board using 2x NAND flash chips. Signed-off-by: Rostislav Lisovy <lisovy@merica.cz> --- drivers/mtd/nand/omap2.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/mtd/nand/omap2.c b/drivers/mtd/nand/omap2.c index 24d5c6a..8761a5b 100644 --- a/drivers/mtd/nand/omap2.c +++ b/drivers/mtd/nand/omap2.c @@ -24,6 +24,7 @@ #include <linux/slab.h> #include <linux/of.h> #include <linux/of_device.h> +#include <linux/spinlock.h> #include <linux/mtd/nand_bch.h> #include <linux/platform_data/elm.h> @@ -146,6 +147,7 @@ static u_char bch8_vector[] = {0xf3, 0xdb, 0x14, 0x16, 0x8b, 0xd2, 0xbe, 0xcc, static u_char bch4_vector[] = {0x00, 0x6b, 0x31, 0xdd, 0x41, 0xbc, 0x10}; #endif +static DEFINE_SPINLOCK(omap_eccengine_lock); struct omap_nand_info { struct nand_hw_control controller; @@ -1518,6 +1520,7 @@ static int omap_write_page_bch(struct mtd_info *mtd, struct nand_chip *chip, uint8_t *ecc_calc = chip->buffers->ecccalc; uint32_t *eccpos = chip->ecc.layout->eccpos; + spin_lock(&omap_eccengine_lock); /* Enable GPMC ecc engine */ chip->ecc.hwctl(mtd, NAND_ECC_WRITE); @@ -1526,6 +1529,7 @@ static int omap_write_page_bch(struct mtd_info *mtd, struct nand_chip *chip, /* Update ecc vector from GPMC result registers */ chip->ecc.calculate(mtd, buf, &ecc_calc[0]); + spin_unlock(&omap_eccengine_lock); for (i = 0; i < chip->ecc.total; i++) chip->oob_poi[eccpos[i]] = ecc_calc[i]; @@ -1561,6 +1565,7 @@ static int omap_read_page_bch(struct mtd_info *mtd, struct nand_chip *chip, int stat; unsigned int max_bitflips = 0; + spin_lock(&omap_eccengine_lock); /* Enable GPMC ecc engine */ chip->ecc.hwctl(mtd, NAND_ECC_READ); @@ -1573,6 +1578,7 @@ static int omap_read_page_bch(struct mtd_info *mtd, struct nand_chip *chip, /* Calculate ecc bytes */ chip->ecc.calculate(mtd, buf, ecc_calc); + spin_unlock(&omap_eccengine_lock); memcpy(ecc_code, &chip->oob_poi[eccpos[0]], chip->ecc.total); -- 1.9.1 ^ permalink raw reply related [flat|nested] 4+ messages in thread
* Re: [PATCH 2/2] mtd: nand: omap: Synchronize access to the ECC engine 2014-10-01 14:59 ` [PATCH 2/2] mtd: nand: omap: Synchronize access to the ECC engine Rostislav Lisovy @ 2014-10-02 7:12 ` Roger Quadros 0 siblings, 0 replies; 4+ messages in thread From: Roger Quadros @ 2014-10-02 7:12 UTC (permalink / raw) To: Rostislav Lisovy, David Woodhouse, Brian Norris, pekon, Tony Lindgren, linux-mtd, linux-kernel Cc: michal.vokac, Rostislav Lisovy, sojkam1 On 10/01/2014 05:59 PM, Rostislav Lisovy wrote: > The AM335x Technical Reference Manual (spruh73j.pdf) says > "Because the ECC engine includes only one accumulation context, > it can be allocated to only one chip-select at a time ... " > (7.1.3.3.12.3). Since the commit 97a288ba2cfa ("ARM: omap2+: > gpmc-nand: Use dynamic platform_device_alloc()") gpmc-nand > driver supports multiple NAND flash devices connected to > the single controller. Use spinlocks to restrict access > to the ECC engine for single read/write operation at a time. > > Tested with custom AM335x board using 2x NAND flash chips. > > Signed-off-by: Rostislav Lisovy <lisovy@merica.cz> > --- > drivers/mtd/nand/omap2.c | 6 ++++++ > 1 file changed, 6 insertions(+) > > diff --git a/drivers/mtd/nand/omap2.c b/drivers/mtd/nand/omap2.c > index 24d5c6a..8761a5b 100644 > --- a/drivers/mtd/nand/omap2.c > +++ b/drivers/mtd/nand/omap2.c > @@ -24,6 +24,7 @@ > #include <linux/slab.h> > #include <linux/of.h> > #include <linux/of_device.h> > +#include <linux/spinlock.h> > > #include <linux/mtd/nand_bch.h> > #include <linux/platform_data/elm.h> > @@ -146,6 +147,7 @@ static u_char bch8_vector[] = {0xf3, 0xdb, 0x14, 0x16, 0x8b, 0xd2, 0xbe, 0xcc, > static u_char bch4_vector[] = {0x00, 0x6b, 0x31, 0xdd, 0x41, 0xbc, 0x10}; > #endif > > +static DEFINE_SPINLOCK(omap_eccengine_lock); > > struct omap_nand_info { > struct nand_hw_control controller; > @@ -1518,6 +1520,7 @@ static int omap_write_page_bch(struct mtd_info *mtd, struct nand_chip *chip, > uint8_t *ecc_calc = chip->buffers->ecccalc; > uint32_t *eccpos = chip->ecc.layout->eccpos; > > + spin_lock(&omap_eccengine_lock); > /* Enable GPMC ecc engine */ > chip->ecc.hwctl(mtd, NAND_ECC_WRITE); > > @@ -1526,6 +1529,7 @@ static int omap_write_page_bch(struct mtd_info *mtd, struct nand_chip *chip, > > /* Update ecc vector from GPMC result registers */ > chip->ecc.calculate(mtd, buf, &ecc_calc[0]); > + spin_unlock(&omap_eccengine_lock); > > for (i = 0; i < chip->ecc.total; i++) > chip->oob_poi[eccpos[i]] = ecc_calc[i]; > @@ -1561,6 +1565,7 @@ static int omap_read_page_bch(struct mtd_info *mtd, struct nand_chip *chip, > int stat; > unsigned int max_bitflips = 0; > > + spin_lock(&omap_eccengine_lock); > /* Enable GPMC ecc engine */ > chip->ecc.hwctl(mtd, NAND_ECC_READ); > > @@ -1573,6 +1578,7 @@ static int omap_read_page_bch(struct mtd_info *mtd, struct nand_chip *chip, > > /* Calculate ecc bytes */ > chip->ecc.calculate(mtd, buf, ecc_calc); > + spin_unlock(&omap_eccengine_lock); > > memcpy(ecc_code, &chip->oob_poi[eccpos[0]], chip->ecc.total); > > The access to the BCH/ELM engine is still not serialized for ecc->read_subpage and ecc->write_subpage() in case of OMAP_ECC_BCH4_CODE_HW OMAP_ECC_BCH8_CODE_HW OMAP_ECC_BCH16_CODE_HW What about serializing access to BCH engine for read/write_page() and read/write_subpage() in case of OMAP_ECC_BCH4_CODE_HW_DETECTION_SW OMAP_ECC_BCH8_CODE_HW_DETECTION_SW and finally we should also serialize access to ECC engine for read/write_page() and read/write_subpage() in case of OMAP_ECC_HAM1_CODE_HW cheers, -roger ^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH 1/2] mtd: nand: omap: Do not use global variables 2014-10-01 14:59 [PATCH 1/2] mtd: nand: omap: Do not use global variables Rostislav Lisovy 2014-10-01 14:59 ` [PATCH 2/2] mtd: nand: omap: Synchronize access to the ECC engine Rostislav Lisovy @ 2014-10-02 6:44 ` Roger Quadros 1 sibling, 0 replies; 4+ messages in thread From: Roger Quadros @ 2014-10-02 6:44 UTC (permalink / raw) To: Rostislav Lisovy, David Woodhouse, Brian Norris, pekon, Tony Lindgren, linux-mtd, linux-kernel Cc: michal.vokac, Rostislav Lisovy, sojkam1 Hi, On 10/01/2014 05:59 PM, Rostislav Lisovy wrote: > Since the commit 97a288ba2cfa ("ARM: omap2+: gpmc-nand: Use > dynamic platform_device_alloc()") gpmc-nand driver supports > multiple NAND flash devices connected to the single controller. > Remove global variable to make the code thread-safe. > > Signed-off-by: Rostislav Lisovy <lisovy@merica.cz> > --- > drivers/mtd/nand/omap2.c | 4 +--- > 1 file changed, 1 insertion(+), 3 deletions(-) > > diff --git a/drivers/mtd/nand/omap2.c b/drivers/mtd/nand/omap2.c > index 5967b38..24d5c6a 100644 > --- a/drivers/mtd/nand/omap2.c > +++ b/drivers/mtd/nand/omap2.c > @@ -146,8 +146,6 @@ static u_char bch8_vector[] = {0xf3, 0xdb, 0x14, 0x16, 0x8b, 0xd2, 0xbe, 0xcc, > static u_char bch4_vector[] = {0x00, 0x6b, 0x31, 0xdd, 0x41, 0xbc, 0x10}; > #endif > > -/* oob info generated runtime depending on ecc algorithm and layout selected */ > -static struct nand_ecclayout omap_oobinfo; > > struct omap_nand_info { > struct nand_hw_control controller; > @@ -1794,7 +1792,7 @@ static int omap_nand_probe(struct platform_device *pdev) > } > > /* populate MTD interface based on ECC scheme */ > - ecclayout = &omap_oobinfo; > + ecclayout = kzalloc(sizeof(*ecclayout), GFP_KERNEL); We should free this in failure path or omap_nand_remove(), or use devm_kzalloc(). How about making "struct nand_ecclayout" a part of omap_nand_info, so that it gets allocated without a separate devm_kzalloc() call? > switch (info->ecc_opt) { > case OMAP_ECC_HAM1_CODE_SW: > nand_chip->ecc.mode = NAND_ECC_SOFT; > cheers, -roger ^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2014-10-02 7:12 UTC | newest] Thread overview: 4+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2014-10-01 14:59 [PATCH 1/2] mtd: nand: omap: Do not use global variables Rostislav Lisovy 2014-10-01 14:59 ` [PATCH 2/2] mtd: nand: omap: Synchronize access to the ECC engine Rostislav Lisovy 2014-10-02 7:12 ` Roger Quadros 2014-10-02 6:44 ` [PATCH 1/2] mtd: nand: omap: Do not use global variables Roger Quadros
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).