devfs & mtd: add MEMERASE ioctl support
To make that, we need to shift mtd_erase before mtd_ioctl. ubi-utils need that, especially ubiformat. Signed-off-by: Wolfram Sang <w.sang@pengutronix.de> Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
This commit is contained in:
parent
68e00c165c
commit
8c98a5dfb7
|
@ -73,7 +73,37 @@ static ssize_t mtd_write(struct cdev* cdev, const void *buf, size_t _count,
|
||||||
|
|
||||||
return ret ? ret : _count;
|
return ret ? ret : _count;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
static int mtd_erase(struct cdev *cdev, size_t count, loff_t offset)
|
||||||
|
{
|
||||||
|
struct mtd_info *mtd = cdev->priv;
|
||||||
|
struct erase_info erase;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
memset(&erase, 0, sizeof(erase));
|
||||||
|
erase.mtd = mtd;
|
||||||
|
erase.addr = offset;
|
||||||
|
erase.len = mtd->erasesize;
|
||||||
|
|
||||||
|
while (count > 0) {
|
||||||
|
dev_dbg(cdev->dev, "erase %d %d\n", erase.addr, erase.len);
|
||||||
|
|
||||||
|
ret = mtd_block_isbad(mtd, erase.addr);
|
||||||
|
if (ret > 0) {
|
||||||
|
printf("Skipping bad block at 0x%08x\n", erase.addr);
|
||||||
|
} else {
|
||||||
|
ret = mtd->erase(mtd, &erase);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
erase.addr += mtd->erasesize;
|
||||||
|
count -= count > mtd->erasesize ? mtd->erasesize : count;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif /* CONFIG_MTD_WRITE */
|
||||||
|
|
||||||
int mtd_ioctl(struct cdev *cdev, int request, void *buf)
|
int mtd_ioctl(struct cdev *cdev, int request, void *buf)
|
||||||
{
|
{
|
||||||
|
@ -84,6 +114,7 @@ int mtd_ioctl(struct cdev *cdev, int request, void *buf)
|
||||||
struct mtd_ecc_stats *ecc = buf;
|
struct mtd_ecc_stats *ecc = buf;
|
||||||
#endif
|
#endif
|
||||||
struct region_info_user *reg = buf;
|
struct region_info_user *reg = buf;
|
||||||
|
struct erase_info_user *ei = buf;
|
||||||
loff_t *offset = buf;
|
loff_t *offset = buf;
|
||||||
|
|
||||||
switch (request) {
|
switch (request) {
|
||||||
|
@ -96,6 +127,9 @@ int mtd_ioctl(struct cdev *cdev, int request, void *buf)
|
||||||
dev_dbg(cdev->dev, "MEMSETBADBLOCK: 0x%08llx\n", *offset);
|
dev_dbg(cdev->dev, "MEMSETBADBLOCK: 0x%08llx\n", *offset);
|
||||||
ret = mtd->block_markbad(mtd, *offset);
|
ret = mtd->block_markbad(mtd, *offset);
|
||||||
break;
|
break;
|
||||||
|
case MEMERASE:
|
||||||
|
ret = mtd_erase(cdev, ei->length, ei->start + cdev->offset);
|
||||||
|
break;
|
||||||
#endif
|
#endif
|
||||||
case MEMGETINFO:
|
case MEMGETINFO:
|
||||||
user->type = mtd->type;
|
user->type = mtd->type;
|
||||||
|
@ -133,38 +167,6 @@ int mtd_ioctl(struct cdev *cdev, int request, void *buf)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_MTD_WRITE
|
|
||||||
static int mtd_erase(struct cdev *cdev, size_t count, loff_t offset)
|
|
||||||
{
|
|
||||||
struct mtd_info *mtd = cdev->priv;
|
|
||||||
struct erase_info erase;
|
|
||||||
int ret;
|
|
||||||
|
|
||||||
memset(&erase, 0, sizeof(erase));
|
|
||||||
erase.mtd = mtd;
|
|
||||||
erase.addr = offset;
|
|
||||||
erase.len = mtd->erasesize;
|
|
||||||
|
|
||||||
while (count > 0) {
|
|
||||||
dev_dbg(cdev->dev, "erase %d %d\n", erase.addr, erase.len);
|
|
||||||
|
|
||||||
ret = mtd_block_isbad(mtd, erase.addr);
|
|
||||||
if (ret > 0) {
|
|
||||||
printf("Skipping bad block at 0x%08x\n", erase.addr);
|
|
||||||
} else {
|
|
||||||
ret = mtd->erase(mtd, &erase);
|
|
||||||
if (ret)
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
erase.addr += mtd->erasesize;
|
|
||||||
count -= count > mtd->erasesize ? mtd->erasesize : count;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static struct file_operations mtd_ops = {
|
static struct file_operations mtd_ops = {
|
||||||
.read = mtd_read,
|
.read = mtd_read,
|
||||||
#ifdef CONFIG_MTD_WRITE
|
#ifdef CONFIG_MTD_WRITE
|
||||||
|
|
|
@ -152,13 +152,14 @@ static int partition_ioctl(struct cdev *cdev, int request, void *buf)
|
||||||
break;
|
break;
|
||||||
#if (defined(CONFIG_NAND_ECC_HW) || defined(CONFIG_NAND_ECC_SOFT))
|
#if (defined(CONFIG_NAND_ECC_HW) || defined(CONFIG_NAND_ECC_SOFT))
|
||||||
case ECCGETSTATS:
|
case ECCGETSTATS:
|
||||||
|
#endif
|
||||||
|
case MEMERASE:
|
||||||
if (!cdev->ops->ioctl) {
|
if (!cdev->ops->ioctl) {
|
||||||
ret = -EINVAL;
|
ret = -EINVAL;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
ret = cdev->ops->ioctl(cdev, request, buf);
|
ret = cdev->ops->ioctl(cdev, request, buf);
|
||||||
break;
|
break;
|
||||||
#endif
|
|
||||||
#ifdef CONFIG_PARTITION
|
#ifdef CONFIG_PARTITION
|
||||||
case MEMGETREGIONINFO:
|
case MEMGETREGIONINFO:
|
||||||
if (cdev->mtd) {
|
if (cdev->mtd) {
|
||||||
|
|
Loading…
Reference in New Issue