Message ID | 1589542063-6703-1-git-send-email-yangyicong@hisilicon.com |
---|---|
State | Superseded |
Delegated to: | Ambarus Tudor |
Headers | show |
Series | mtd:spi-nor: Fix an issue of releasing resources during read/write | expand |
A friendly ping... Thanks. On 2020/5/15 19:27, Yicong Yang wrote: > From: Xiang Chen <chenxiang66@hisilicon.com> > > If rmmod the driver during read or write, the driver will release the > resources which are used during read or write, so it is possible to > refer to NULL pointer. > > Use the testcase "mtd_debug read /dev/mtd0 0xc00000 0x400000 dest_file & > sleep 0.5;rmmod spi_hisi_sfc_v3xx.ko", the issue can be reproduced in > hisi_sfc_v3xx driver. > > To avoid the issue, fill the interface _get_device and _put_device of > mtd_info to grab the reference to the spi controller driver module, so > the request of rmmod the driver is rejected before read/write is finished. > > Signed-off-by: Xiang Chen <chenxiang66@hisilicon.com> > Signed-off-by: Yicong Yang <yangyicong@hisilicon.com> > --- > The patch has been tested with hisi_sfc_v3xx controller. May someone > could test it on a spi-nor-controller device as we don't have one > aside. > > drivers/mtd/spi-nor/core.c | 33 +++++++++++++++++++++++++++++++++ > 1 file changed, 33 insertions(+) > > diff --git a/drivers/mtd/spi-nor/core.c b/drivers/mtd/spi-nor/core.c > index cc68ea8..05370cb 100644 > --- a/drivers/mtd/spi-nor/core.c > +++ b/drivers/mtd/spi-nor/core.c > @@ -2977,6 +2977,37 @@ static void spi_nor_resume(struct mtd_info *mtd) > dev_err(dev, "resume() failed\n"); > } > > +static int spi_nor_get_device(struct mtd_info *mtd) > +{ > + struct mtd_info *master = mtd_get_master(mtd); > + struct spi_nor *nor = mtd_to_spi_nor(master); > + struct device *dev; > + > + if (nor->spimem) > + dev = nor->spimem->spi->controller->dev.parent; > + else > + dev = nor->dev; > + > + if (!try_module_get(dev->driver->owner)) > + return -ENODEV; > + > + return 0; > +} > + > +static void spi_nor_put_device(struct mtd_info *mtd) > +{ > + struct mtd_info *master = mtd_get_master(mtd); > + struct spi_nor *nor = mtd_to_spi_nor(master); > + struct device *dev; > + > + if (nor->spimem) > + dev = nor->spimem->spi->controller->dev.parent; > + else > + dev = nor->dev; > + > + module_put(dev->driver->owner); > +} > + > void spi_nor_restore(struct spi_nor *nor) > { > /* restore the addressing mode */ > @@ -3151,6 +3182,8 @@ int spi_nor_scan(struct spi_nor *nor, const char *name, > mtd->_erase = spi_nor_erase; > mtd->_read = spi_nor_read; > mtd->_resume = spi_nor_resume; > + mtd->_get_device = spi_nor_get_device; > + mtd->_put_device = spi_nor_put_device; > > if (nor->params->locking_ops) { > mtd->_lock = spi_nor_lock; > -- > 2.8.1 > > . >
diff --git a/drivers/mtd/spi-nor/core.c b/drivers/mtd/spi-nor/core.c index cc68ea8..05370cb 100644 --- a/drivers/mtd/spi-nor/core.c +++ b/drivers/mtd/spi-nor/core.c @@ -2977,6 +2977,37 @@ static void spi_nor_resume(struct mtd_info *mtd) dev_err(dev, "resume() failed\n"); } +static int spi_nor_get_device(struct mtd_info *mtd) +{ + struct mtd_info *master = mtd_get_master(mtd); + struct spi_nor *nor = mtd_to_spi_nor(master); + struct device *dev; + + if (nor->spimem) + dev = nor->spimem->spi->controller->dev.parent; + else + dev = nor->dev; + + if (!try_module_get(dev->driver->owner)) + return -ENODEV; + + return 0; +} + +static void spi_nor_put_device(struct mtd_info *mtd) +{ + struct mtd_info *master = mtd_get_master(mtd); + struct spi_nor *nor = mtd_to_spi_nor(master); + struct device *dev; + + if (nor->spimem) + dev = nor->spimem->spi->controller->dev.parent; + else + dev = nor->dev; + + module_put(dev->driver->owner); +} + void spi_nor_restore(struct spi_nor *nor) { /* restore the addressing mode */ @@ -3151,6 +3182,8 @@ int spi_nor_scan(struct spi_nor *nor, const char *name, mtd->_erase = spi_nor_erase; mtd->_read = spi_nor_read; mtd->_resume = spi_nor_resume; + mtd->_get_device = spi_nor_get_device; + mtd->_put_device = spi_nor_put_device; if (nor->params->locking_ops) { mtd->_lock = spi_nor_lock;