mtd: nand: fix drivers abusing mtd->priv
The ->priv field of the mtd_info object attached to a nand_chip device should point to the nand_chip device. The pxa and cafe drivers are assigning this field their own private structure, which works fine as long as the nand_chip field is the first one in the driver private struct but seems a bit fragile. Fix that by setting mtd->priv to point the nand_chip field and assigning chip->priv to the private structure head. Signed-off-by: Boris Brezillon <boris.brezillon@free-electrons.com> Signed-off-by: Brian Norris <computersforpeace@gmail.com>
This commit is contained in:
parent
064f462632
commit
1d8d8b5c85
|
@ -101,7 +101,8 @@ static const char *part_probes[] = { "cmdlinepart", "RedBoot", NULL };
|
||||||
|
|
||||||
static int cafe_device_ready(struct mtd_info *mtd)
|
static int cafe_device_ready(struct mtd_info *mtd)
|
||||||
{
|
{
|
||||||
struct cafe_priv *cafe = mtd->priv;
|
struct nand_chip *chip = mtd->priv;
|
||||||
|
struct cafe_priv *cafe = chip->priv;
|
||||||
int result = !!(cafe_readl(cafe, NAND_STATUS) & 0x40000000);
|
int result = !!(cafe_readl(cafe, NAND_STATUS) & 0x40000000);
|
||||||
uint32_t irqs = cafe_readl(cafe, NAND_IRQ);
|
uint32_t irqs = cafe_readl(cafe, NAND_IRQ);
|
||||||
|
|
||||||
|
@ -117,7 +118,8 @@ static int cafe_device_ready(struct mtd_info *mtd)
|
||||||
|
|
||||||
static void cafe_write_buf(struct mtd_info *mtd, const uint8_t *buf, int len)
|
static void cafe_write_buf(struct mtd_info *mtd, const uint8_t *buf, int len)
|
||||||
{
|
{
|
||||||
struct cafe_priv *cafe = mtd->priv;
|
struct nand_chip *chip = mtd->priv;
|
||||||
|
struct cafe_priv *cafe = chip->priv;
|
||||||
|
|
||||||
if (usedma)
|
if (usedma)
|
||||||
memcpy(cafe->dmabuf + cafe->datalen, buf, len);
|
memcpy(cafe->dmabuf + cafe->datalen, buf, len);
|
||||||
|
@ -132,7 +134,8 @@ static void cafe_write_buf(struct mtd_info *mtd, const uint8_t *buf, int len)
|
||||||
|
|
||||||
static void cafe_read_buf(struct mtd_info *mtd, uint8_t *buf, int len)
|
static void cafe_read_buf(struct mtd_info *mtd, uint8_t *buf, int len)
|
||||||
{
|
{
|
||||||
struct cafe_priv *cafe = mtd->priv;
|
struct nand_chip *chip = mtd->priv;
|
||||||
|
struct cafe_priv *cafe = chip->priv;
|
||||||
|
|
||||||
if (usedma)
|
if (usedma)
|
||||||
memcpy(buf, cafe->dmabuf + cafe->datalen, len);
|
memcpy(buf, cafe->dmabuf + cafe->datalen, len);
|
||||||
|
@ -146,7 +149,8 @@ static void cafe_read_buf(struct mtd_info *mtd, uint8_t *buf, int len)
|
||||||
|
|
||||||
static uint8_t cafe_read_byte(struct mtd_info *mtd)
|
static uint8_t cafe_read_byte(struct mtd_info *mtd)
|
||||||
{
|
{
|
||||||
struct cafe_priv *cafe = mtd->priv;
|
struct nand_chip *chip = mtd->priv;
|
||||||
|
struct cafe_priv *cafe = chip->priv;
|
||||||
uint8_t d;
|
uint8_t d;
|
||||||
|
|
||||||
cafe_read_buf(mtd, &d, 1);
|
cafe_read_buf(mtd, &d, 1);
|
||||||
|
@ -158,7 +162,8 @@ static uint8_t cafe_read_byte(struct mtd_info *mtd)
|
||||||
static void cafe_nand_cmdfunc(struct mtd_info *mtd, unsigned command,
|
static void cafe_nand_cmdfunc(struct mtd_info *mtd, unsigned command,
|
||||||
int column, int page_addr)
|
int column, int page_addr)
|
||||||
{
|
{
|
||||||
struct cafe_priv *cafe = mtd->priv;
|
struct nand_chip *chip = mtd->priv;
|
||||||
|
struct cafe_priv *cafe = chip->priv;
|
||||||
int adrbytes = 0;
|
int adrbytes = 0;
|
||||||
uint32_t ctl1;
|
uint32_t ctl1;
|
||||||
uint32_t doneint = 0x80000000;
|
uint32_t doneint = 0x80000000;
|
||||||
|
@ -313,7 +318,8 @@ static void cafe_nand_cmdfunc(struct mtd_info *mtd, unsigned command,
|
||||||
|
|
||||||
static void cafe_select_chip(struct mtd_info *mtd, int chipnr)
|
static void cafe_select_chip(struct mtd_info *mtd, int chipnr)
|
||||||
{
|
{
|
||||||
struct cafe_priv *cafe = mtd->priv;
|
struct nand_chip *chip = mtd->priv;
|
||||||
|
struct cafe_priv *cafe = chip->priv;
|
||||||
|
|
||||||
cafe_dev_dbg(&cafe->pdev->dev, "select_chip %d\n", chipnr);
|
cafe_dev_dbg(&cafe->pdev->dev, "select_chip %d\n", chipnr);
|
||||||
|
|
||||||
|
@ -328,7 +334,8 @@ static void cafe_select_chip(struct mtd_info *mtd, int chipnr)
|
||||||
static irqreturn_t cafe_nand_interrupt(int irq, void *id)
|
static irqreturn_t cafe_nand_interrupt(int irq, void *id)
|
||||||
{
|
{
|
||||||
struct mtd_info *mtd = id;
|
struct mtd_info *mtd = id;
|
||||||
struct cafe_priv *cafe = mtd->priv;
|
struct nand_chip *chip = mtd->priv;
|
||||||
|
struct cafe_priv *cafe = chip->priv;
|
||||||
uint32_t irqs = cafe_readl(cafe, NAND_IRQ);
|
uint32_t irqs = cafe_readl(cafe, NAND_IRQ);
|
||||||
cafe_writel(cafe, irqs & ~0x90000000, NAND_IRQ);
|
cafe_writel(cafe, irqs & ~0x90000000, NAND_IRQ);
|
||||||
if (!irqs)
|
if (!irqs)
|
||||||
|
@ -377,7 +384,7 @@ static int cafe_nand_read_oob(struct mtd_info *mtd, struct nand_chip *chip,
|
||||||
static int cafe_nand_read_page(struct mtd_info *mtd, struct nand_chip *chip,
|
static int cafe_nand_read_page(struct mtd_info *mtd, struct nand_chip *chip,
|
||||||
uint8_t *buf, int oob_required, int page)
|
uint8_t *buf, int oob_required, int page)
|
||||||
{
|
{
|
||||||
struct cafe_priv *cafe = mtd->priv;
|
struct cafe_priv *cafe = chip->priv;
|
||||||
unsigned int max_bitflips = 0;
|
unsigned int max_bitflips = 0;
|
||||||
|
|
||||||
cafe_dev_dbg(&cafe->pdev->dev, "ECC result %08x SYN1,2 %08x\n",
|
cafe_dev_dbg(&cafe->pdev->dev, "ECC result %08x SYN1,2 %08x\n",
|
||||||
|
@ -519,7 +526,7 @@ static int cafe_nand_write_page_lowlevel(struct mtd_info *mtd,
|
||||||
const uint8_t *buf, int oob_required,
|
const uint8_t *buf, int oob_required,
|
||||||
int page)
|
int page)
|
||||||
{
|
{
|
||||||
struct cafe_priv *cafe = mtd->priv;
|
struct cafe_priv *cafe = chip->priv;
|
||||||
|
|
||||||
chip->write_buf(mtd, buf, mtd->writesize);
|
chip->write_buf(mtd, buf, mtd->writesize);
|
||||||
chip->write_buf(mtd, chip->oob_poi, mtd->oobsize);
|
chip->write_buf(mtd, chip->oob_poi, mtd->oobsize);
|
||||||
|
@ -604,7 +611,8 @@ static int cafe_nand_probe(struct pci_dev *pdev,
|
||||||
cafe = (void *)(&mtd[1]);
|
cafe = (void *)(&mtd[1]);
|
||||||
|
|
||||||
mtd->dev.parent = &pdev->dev;
|
mtd->dev.parent = &pdev->dev;
|
||||||
mtd->priv = cafe;
|
mtd->priv = &cafe->nand;
|
||||||
|
cafe->nand.priv = cafe;
|
||||||
|
|
||||||
cafe->pdev = pdev;
|
cafe->pdev = pdev;
|
||||||
cafe->mmio = pci_iomap(pdev, 0, 0);
|
cafe->mmio = pci_iomap(pdev, 0, 0);
|
||||||
|
@ -792,7 +800,8 @@ static int cafe_nand_probe(struct pci_dev *pdev,
|
||||||
static void cafe_nand_remove(struct pci_dev *pdev)
|
static void cafe_nand_remove(struct pci_dev *pdev)
|
||||||
{
|
{
|
||||||
struct mtd_info *mtd = pci_get_drvdata(pdev);
|
struct mtd_info *mtd = pci_get_drvdata(pdev);
|
||||||
struct cafe_priv *cafe = mtd->priv;
|
struct nand_chip *chip = mtd->priv;
|
||||||
|
struct cafe_priv *cafe = chip->priv;
|
||||||
|
|
||||||
/* Disable NAND IRQ in global IRQ mask register */
|
/* Disable NAND IRQ in global IRQ mask register */
|
||||||
cafe_writel(cafe, ~1 & cafe_readl(cafe, GLOBAL_IRQ_MASK), GLOBAL_IRQ_MASK);
|
cafe_writel(cafe, ~1 & cafe_readl(cafe, GLOBAL_IRQ_MASK), GLOBAL_IRQ_MASK);
|
||||||
|
@ -819,7 +828,8 @@ static int cafe_nand_resume(struct pci_dev *pdev)
|
||||||
{
|
{
|
||||||
uint32_t ctrl;
|
uint32_t ctrl;
|
||||||
struct mtd_info *mtd = pci_get_drvdata(pdev);
|
struct mtd_info *mtd = pci_get_drvdata(pdev);
|
||||||
struct cafe_priv *cafe = mtd->priv;
|
struct nand_chip *chip = mtd->priv;
|
||||||
|
struct cafe_priv *cafe = chip->priv;
|
||||||
|
|
||||||
/* Start off by resetting the NAND controller completely */
|
/* Start off by resetting the NAND controller completely */
|
||||||
cafe_writel(cafe, 1, NAND_RESET);
|
cafe_writel(cafe, 1, NAND_RESET);
|
||||||
|
|
|
@ -1113,7 +1113,8 @@ static int prepare_set_command(struct pxa3xx_nand_info *info, int command,
|
||||||
static void nand_cmdfunc(struct mtd_info *mtd, unsigned command,
|
static void nand_cmdfunc(struct mtd_info *mtd, unsigned command,
|
||||||
int column, int page_addr)
|
int column, int page_addr)
|
||||||
{
|
{
|
||||||
struct pxa3xx_nand_host *host = mtd->priv;
|
struct nand_chip *chip = mtd->priv;
|
||||||
|
struct pxa3xx_nand_host *host = chip->priv;
|
||||||
struct pxa3xx_nand_info *info = host->info_data;
|
struct pxa3xx_nand_info *info = host->info_data;
|
||||||
int exec_cmd;
|
int exec_cmd;
|
||||||
|
|
||||||
|
@ -1161,7 +1162,8 @@ static void nand_cmdfunc_extended(struct mtd_info *mtd,
|
||||||
const unsigned command,
|
const unsigned command,
|
||||||
int column, int page_addr)
|
int column, int page_addr)
|
||||||
{
|
{
|
||||||
struct pxa3xx_nand_host *host = mtd->priv;
|
struct nand_chip *chip = mtd->priv;
|
||||||
|
struct pxa3xx_nand_host *host = chip->priv;
|
||||||
struct pxa3xx_nand_info *info = host->info_data;
|
struct pxa3xx_nand_info *info = host->info_data;
|
||||||
int exec_cmd, ext_cmd_type;
|
int exec_cmd, ext_cmd_type;
|
||||||
|
|
||||||
|
@ -1281,7 +1283,7 @@ static int pxa3xx_nand_read_page_hwecc(struct mtd_info *mtd,
|
||||||
struct nand_chip *chip, uint8_t *buf, int oob_required,
|
struct nand_chip *chip, uint8_t *buf, int oob_required,
|
||||||
int page)
|
int page)
|
||||||
{
|
{
|
||||||
struct pxa3xx_nand_host *host = mtd->priv;
|
struct pxa3xx_nand_host *host = chip->priv;
|
||||||
struct pxa3xx_nand_info *info = host->info_data;
|
struct pxa3xx_nand_info *info = host->info_data;
|
||||||
|
|
||||||
chip->read_buf(mtd, buf, mtd->writesize);
|
chip->read_buf(mtd, buf, mtd->writesize);
|
||||||
|
@ -1307,7 +1309,8 @@ static int pxa3xx_nand_read_page_hwecc(struct mtd_info *mtd,
|
||||||
|
|
||||||
static uint8_t pxa3xx_nand_read_byte(struct mtd_info *mtd)
|
static uint8_t pxa3xx_nand_read_byte(struct mtd_info *mtd)
|
||||||
{
|
{
|
||||||
struct pxa3xx_nand_host *host = mtd->priv;
|
struct nand_chip *chip = mtd->priv;
|
||||||
|
struct pxa3xx_nand_host *host = chip->priv;
|
||||||
struct pxa3xx_nand_info *info = host->info_data;
|
struct pxa3xx_nand_info *info = host->info_data;
|
||||||
char retval = 0xFF;
|
char retval = 0xFF;
|
||||||
|
|
||||||
|
@ -1320,7 +1323,8 @@ static uint8_t pxa3xx_nand_read_byte(struct mtd_info *mtd)
|
||||||
|
|
||||||
static u16 pxa3xx_nand_read_word(struct mtd_info *mtd)
|
static u16 pxa3xx_nand_read_word(struct mtd_info *mtd)
|
||||||
{
|
{
|
||||||
struct pxa3xx_nand_host *host = mtd->priv;
|
struct nand_chip *chip = mtd->priv;
|
||||||
|
struct pxa3xx_nand_host *host = chip->priv;
|
||||||
struct pxa3xx_nand_info *info = host->info_data;
|
struct pxa3xx_nand_info *info = host->info_data;
|
||||||
u16 retval = 0xFFFF;
|
u16 retval = 0xFFFF;
|
||||||
|
|
||||||
|
@ -1333,7 +1337,8 @@ static u16 pxa3xx_nand_read_word(struct mtd_info *mtd)
|
||||||
|
|
||||||
static void pxa3xx_nand_read_buf(struct mtd_info *mtd, uint8_t *buf, int len)
|
static void pxa3xx_nand_read_buf(struct mtd_info *mtd, uint8_t *buf, int len)
|
||||||
{
|
{
|
||||||
struct pxa3xx_nand_host *host = mtd->priv;
|
struct nand_chip *chip = mtd->priv;
|
||||||
|
struct pxa3xx_nand_host *host = chip->priv;
|
||||||
struct pxa3xx_nand_info *info = host->info_data;
|
struct pxa3xx_nand_info *info = host->info_data;
|
||||||
int real_len = min_t(size_t, len, info->buf_count - info->buf_start);
|
int real_len = min_t(size_t, len, info->buf_count - info->buf_start);
|
||||||
|
|
||||||
|
@ -1344,7 +1349,8 @@ static void pxa3xx_nand_read_buf(struct mtd_info *mtd, uint8_t *buf, int len)
|
||||||
static void pxa3xx_nand_write_buf(struct mtd_info *mtd,
|
static void pxa3xx_nand_write_buf(struct mtd_info *mtd,
|
||||||
const uint8_t *buf, int len)
|
const uint8_t *buf, int len)
|
||||||
{
|
{
|
||||||
struct pxa3xx_nand_host *host = mtd->priv;
|
struct nand_chip *chip = mtd->priv;
|
||||||
|
struct pxa3xx_nand_host *host = chip->priv;
|
||||||
struct pxa3xx_nand_info *info = host->info_data;
|
struct pxa3xx_nand_info *info = host->info_data;
|
||||||
int real_len = min_t(size_t, len, info->buf_count - info->buf_start);
|
int real_len = min_t(size_t, len, info->buf_count - info->buf_start);
|
||||||
|
|
||||||
|
@ -1359,7 +1365,8 @@ static void pxa3xx_nand_select_chip(struct mtd_info *mtd, int chip)
|
||||||
|
|
||||||
static int pxa3xx_nand_waitfunc(struct mtd_info *mtd, struct nand_chip *this)
|
static int pxa3xx_nand_waitfunc(struct mtd_info *mtd, struct nand_chip *this)
|
||||||
{
|
{
|
||||||
struct pxa3xx_nand_host *host = mtd->priv;
|
struct nand_chip *chip = mtd->priv;
|
||||||
|
struct pxa3xx_nand_host *host = chip->priv;
|
||||||
struct pxa3xx_nand_info *info = host->info_data;
|
struct pxa3xx_nand_info *info = host->info_data;
|
||||||
|
|
||||||
if (info->need_wait) {
|
if (info->need_wait) {
|
||||||
|
@ -1565,11 +1572,11 @@ static int pxa_ecc_init(struct pxa3xx_nand_info *info,
|
||||||
|
|
||||||
static int pxa3xx_nand_scan(struct mtd_info *mtd)
|
static int pxa3xx_nand_scan(struct mtd_info *mtd)
|
||||||
{
|
{
|
||||||
struct pxa3xx_nand_host *host = mtd->priv;
|
struct nand_chip *chip = mtd->priv;
|
||||||
|
struct pxa3xx_nand_host *host = chip->priv;
|
||||||
struct pxa3xx_nand_info *info = host->info_data;
|
struct pxa3xx_nand_info *info = host->info_data;
|
||||||
struct platform_device *pdev = info->pdev;
|
struct platform_device *pdev = info->pdev;
|
||||||
struct pxa3xx_nand_platform_data *pdata = dev_get_platdata(&pdev->dev);
|
struct pxa3xx_nand_platform_data *pdata = dev_get_platdata(&pdev->dev);
|
||||||
struct nand_chip *chip = mtd->priv;
|
|
||||||
int ret;
|
int ret;
|
||||||
uint16_t ecc_strength, ecc_step;
|
uint16_t ecc_strength, ecc_step;
|
||||||
|
|
||||||
|
@ -1701,11 +1708,12 @@ static int alloc_nand_resource(struct platform_device *pdev)
|
||||||
host->mtd = mtd;
|
host->mtd = mtd;
|
||||||
host->cs = cs;
|
host->cs = cs;
|
||||||
host->info_data = info;
|
host->info_data = info;
|
||||||
mtd->priv = host;
|
mtd->priv = chip;
|
||||||
mtd->dev.parent = &pdev->dev;
|
mtd->dev.parent = &pdev->dev;
|
||||||
/* FIXME: all chips use the same device tree partitions */
|
/* FIXME: all chips use the same device tree partitions */
|
||||||
nand_set_flash_node(chip, np);
|
nand_set_flash_node(chip, np);
|
||||||
|
|
||||||
|
chip->priv = host;
|
||||||
chip->ecc.read_page = pxa3xx_nand_read_page_hwecc;
|
chip->ecc.read_page = pxa3xx_nand_read_page_hwecc;
|
||||||
chip->ecc.write_page = pxa3xx_nand_write_page_hwecc;
|
chip->ecc.write_page = pxa3xx_nand_write_page_hwecc;
|
||||||
chip->controller = &info->controller;
|
chip->controller = &info->controller;
|
||||||
|
|
Loading…
Reference in New Issue