9
0
Fork 0

mtd: Update internal API to support 64-bit device size

MTD internal API presently uses 32-bit values to represent device
size. This patch updates them to 64-bits but leaves the external API
unchanged.

In general, changing from 32-bit to 64-bit values cause little
or no changes to the majority of the code with the following
exceptions:
  - printk message formats;
  - division and modulus of 64-bit values (mtd_div_by_wb,
    mtd_div_by_eb may be used in some of such cases).

Was tested on phyFLEX i.MX6.

Signed-off-by: Dmitry Lavnikevich <d.lavnikevich@sam-solutions.com>
Signed-off-by: Grigory Milev <g.milev@sam-solutions.com>
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
This commit is contained in:
Dmitry Lavnikevich 2014-03-10 14:39:49 +03:00 committed by Sascha Hauer
parent cf1b29a850
commit 1ee640765a
10 changed files with 39 additions and 20 deletions

View File

@ -277,7 +277,7 @@ static int do_nandtest(int argc, char *argv[])
} }
if (length + flash_offset > meminfo.size) { if (length + flash_offset > meminfo.size) {
printf("Length 0x%08llx + offset 0x%08llx exceeds " printf("Length 0x%08llx + offset 0x%08llx exceeds "
"device size 0x%08x\n", length, "device size 0x%08llx\n", length,
flash_offset, meminfo.size); flash_offset, meminfo.size);
goto err; goto err;
} }

View File

@ -42,10 +42,11 @@
#define PART_ADD_DEVNAME (1 << 0) #define PART_ADD_DEVNAME (1 << 0)
static int mtd_part_do_parse_one(char *devname, const char *partstr, static int mtd_part_do_parse_one(char *devname, const char *partstr,
char **endp, unsigned long *offset, char **endp, loff_t *offset,
off_t devsize, size_t *retsize, unsigned int pflags) loff_t devsize, size_t *retsize,
unsigned int pflags)
{ {
ulong size; loff_t size;
char *end; char *end;
char buf[PATH_MAX] = {}; char buf[PATH_MAX] = {};
unsigned long flags = 0; unsigned long flags = 0;
@ -114,8 +115,8 @@ static int do_addpart(int argc, char *argv[])
{ {
char *devname; char *devname;
char *endp; char *endp;
unsigned long offset = 0; loff_t offset = 0;
off_t devsize; loff_t devsize;
struct stat s; struct stat s;
int opt; int opt;
unsigned int flags = PART_ADD_DEVNAME; unsigned int flags = PART_ADD_DEVNAME;

View File

@ -401,7 +401,7 @@ int add_mtd_device(struct mtd_info *mtd, char *devname, int device_id)
mtd->cdev.mtd = mtd; mtd->cdev.mtd = mtd;
if (IS_ENABLED(CONFIG_PARAMETER)) { if (IS_ENABLED(CONFIG_PARAMETER)) {
dev_add_param_int_ro(&mtd->class_dev, "size", mtd->size, "%u"); dev_add_param_int_ro(&mtd->class_dev, "size", mtd->size, "%llu");
dev_add_param_int_ro(&mtd->class_dev, "erasesize", mtd->erasesize, "%u"); dev_add_param_int_ro(&mtd->class_dev, "erasesize", mtd->erasesize, "%u");
dev_add_param_int_ro(&mtd->class_dev, "writesize", mtd->oobsize, "%u"); dev_add_param_int_ro(&mtd->class_dev, "writesize", mtd->oobsize, "%u");
dev_add_param_int_ro(&mtd->class_dev, "oobsize", mtd->oobsize, "%u"); dev_add_param_int_ro(&mtd->class_dev, "oobsize", mtd->oobsize, "%u");

View File

@ -268,8 +268,9 @@ static int erase_sector(struct m25p *flash, u32 offset, u32 command)
static int m25p80_erase(struct mtd_info *mtd, struct erase_info *instr) static int m25p80_erase(struct mtd_info *mtd, struct erase_info *instr)
{ {
struct m25p *flash = mtd_to_m25p(mtd); struct m25p *flash = mtd_to_m25p(mtd);
u32 addr, len; u32 addr;
uint32_t rem; uint32_t rem;
uint64_t len;
dev_dbg(&flash->spi->dev, "%s at 0x%llx, len %lld\n", dev_dbg(&flash->spi->dev, "%s at 0x%llx, len %lld\n",
__func__, (long long)instr->addr, __func__, (long long)instr->addr,
@ -897,7 +898,7 @@ static int m25p_probe(struct device_d *dev)
flash->mtd.type = MTD_NORFLASH; flash->mtd.type = MTD_NORFLASH;
flash->mtd.writesize = 1; flash->mtd.writesize = 1;
flash->mtd.flags = MTD_CAP_NORFLASH; flash->mtd.flags = MTD_CAP_NORFLASH;
flash->mtd.size = info->sector_size * info->n_sectors; flash->mtd.size = (uint64_t)info->sector_size * info->n_sectors;
flash->mtd.erase = m25p80_erase; flash->mtd.erase = m25p80_erase;
flash->mtd.read = m25p80_read; flash->mtd.read = m25p80_read;

View File

@ -625,7 +625,7 @@ add_dataflash_otp(struct spi_device *spi, char *name,
device = &priv->mtd; device = &priv->mtd;
device->name = (pdata && pdata->name) ? pdata->name : "dataflash"; device->name = (pdata && pdata->name) ? pdata->name : "dataflash";
device->size = nr_pages * pagesize; device->size = nr_pages * (uint64_t)pagesize;
device->erasesize = pagesize; device->erasesize = pagesize;
device->writesize = pagesize; device->writesize = pagesize;
device->type = MTD_DATAFLASH; device->type = MTD_DATAFLASH;

View File

@ -78,7 +78,7 @@ static int add_mtdoob_device(struct mtd_info *mtd, char *devname, void **priv)
mtdoob = xzalloc(sizeof(*mtdoob)); mtdoob = xzalloc(sizeof(*mtdoob));
mtdoob->cdev.ops = &mtd_ops_oob; mtdoob->cdev.ops = &mtd_ops_oob;
mtdoob->cdev.size = (mtd->size / mtd->writesize) * mtd->oobsize; mtdoob->cdev.size = mtd_div_by_wb(mtd->size, mtd) * mtd->oobsize;
mtdoob->cdev.name = asprintf("%s_oob%d", devname, mtd->class_dev.id); mtdoob->cdev.name = asprintf("%s_oob%d", devname, mtd->class_dev.id);
mtdoob->cdev.priv = mtdoob; mtdoob->cdev.priv = mtdoob;
mtdoob->cdev.dev = &mtd->class_dev; mtdoob->cdev.dev = &mtd->class_dev;

View File

@ -293,7 +293,7 @@ static int add_mtdraw_device(struct mtd_info *mtd, char *devname, void **priv)
mtdraw->mtd = mtd; mtdraw->mtd = mtd;
mtdraw->cdev.ops = (struct file_operations *)&mtd_raw_fops; mtdraw->cdev.ops = (struct file_operations *)&mtd_raw_fops;
mtdraw->cdev.size = mtd->size / mtd->writesize * mtdraw->cdev.size = mtd_div_by_wb(mtd->size, mtd) *
(mtd->writesize + mtd->oobsize); (mtd->writesize + mtd->oobsize);
mtdraw->cdev.name = asprintf("%s.raw", mtd->cdev.name); mtdraw->cdev.name = asprintf("%s.raw", mtd->cdev.name);
mtdraw->cdev.priv = mtdraw; mtdraw->cdev.priv = mtdraw;

View File

@ -9,6 +9,8 @@
#ifndef DOXYGEN_SHOULD_SKIP_THIS #ifndef DOXYGEN_SHOULD_SKIP_THIS
#include <asm-generic/div64.h>
struct erase_info_user { struct erase_info_user {
uint32_t start; uint32_t start;
uint32_t length; uint32_t length;
@ -73,7 +75,7 @@ enum {
struct mtd_info_user { struct mtd_info_user {
uint8_t type; uint8_t type;
uint32_t flags; uint32_t flags;
uint32_t size; // Total size of the MTD uint64_t size; /* Total size of the MTD */
uint32_t erasesize; uint32_t erasesize;
uint32_t writesize; uint32_t writesize;
uint32_t oobsize; // Amount of OOB data per block (e.g. 16) uint32_t oobsize; // Amount of OOB data per block (e.g. 16)
@ -173,6 +175,14 @@ enum mtd_file_modes {
MTD_MODE_RAW, MTD_MODE_RAW,
}; };
static inline uint32_t mtd_user_div_by_eb(uint64_t sz,
struct mtd_info_user *mtd_user)
{
do_div(sz, mtd_user->erasesize);
return sz;
}
#endif /* DOXYGEN_SHOULD_SKIP_THIS */ #endif /* DOXYGEN_SHOULD_SKIP_THIS */
#endif /* __MTD_ABI_H__ */ #endif /* __MTD_ABI_H__ */

View File

@ -86,7 +86,7 @@ struct mtd_oob_ops {
struct mtd_info { struct mtd_info {
u_char type; u_char type;
u_int32_t flags; u_int32_t flags;
u_int32_t size; // Total size of the MTD u_int64_t size; /* Total size of the MTD */
/* "Major" erase size for the device. Naïve users may take this /* "Major" erase size for the device. Naïve users may take this
* to be the only erase size available, or may use the more detailed * to be the only erase size available, or may use the more detailed
@ -219,7 +219,7 @@ struct mtd_info {
int p_allow_erasebad; int p_allow_erasebad;
struct mtd_info *master; struct mtd_info *master;
uint32_t master_offset; loff_t master_offset;
}; };
int mtd_erase(struct mtd_info *mtd, struct erase_info *instr); int mtd_erase(struct mtd_info *mtd, struct erase_info *instr);
@ -256,6 +256,13 @@ static inline uint32_t mtd_mod_by_eb(uint64_t sz, struct mtd_info *mtd)
{ {
return do_div(sz, mtd->erasesize); return do_div(sz, mtd->erasesize);
} }
static inline uint32_t mtd_div_by_wb(uint64_t sz, struct mtd_info *mtd)
{
do_div(sz, mtd->writesize);
return sz;
}
/* Kernel-side ioctl definitions */ /* Kernel-side ioctl definitions */
extern int add_mtd_device(struct mtd_info *mtd, char *devname, int device_id); extern int add_mtd_device(struct mtd_info *mtd, char *devname, int device_id);

View File

@ -195,7 +195,7 @@ int libmtd_read(const struct mtd_dev_info *mtd, int fd, int eb, int offs,
void *buf, int len) void *buf, int len)
{ {
int ret, rd = 0; int ret, rd = 0;
off_t seek; loff_t seek;
ret = mtd_valid_erase_block(mtd, eb); ret = mtd_valid_erase_block(mtd, eb);
if (ret) if (ret)
@ -209,7 +209,7 @@ int libmtd_read(const struct mtd_dev_info *mtd, int fd, int eb, int offs,
} }
/* Seek to the beginning of the eraseblock */ /* Seek to the beginning of the eraseblock */
seek = (off_t)eb * mtd->eb_size + offs; seek = (loff_t)eb * mtd->eb_size + offs;
if (lseek(fd, seek, SEEK_SET) != seek) if (lseek(fd, seek, SEEK_SET) != seek)
return sys_errmsg("cannot seek %s to offset %llu", return sys_errmsg("cannot seek %s to offset %llu",
mtd->node, (unsigned long long)seek); mtd->node, (unsigned long long)seek);
@ -229,7 +229,7 @@ int libmtd_write(const struct mtd_dev_info *mtd, int fd, int eb, int offs,
void *buf, int len) void *buf, int len)
{ {
int ret; int ret;
off_t seek; loff_t seek;
ret = mtd_valid_erase_block(mtd, eb); ret = mtd_valid_erase_block(mtd, eb);
if (ret) if (ret)
@ -255,7 +255,7 @@ int libmtd_write(const struct mtd_dev_info *mtd, int fd, int eb, int offs,
} }
/* Seek to the beginning of the eraseblock */ /* Seek to the beginning of the eraseblock */
seek = (off_t)eb * mtd->eb_size + offs; seek = (loff_t)eb * mtd->eb_size + offs;
if (lseek(fd, seek, SEEK_SET) != seek) if (lseek(fd, seek, SEEK_SET) != seek)
return sys_errmsg("cannot seek %s to offset %llu", return sys_errmsg("cannot seek %s to offset %llu",
mtd->node, (unsigned long long)seek); mtd->node, (unsigned long long)seek);
@ -326,7 +326,7 @@ int mtd_get_dev_info(const char *node, struct mtd_dev_info *mtd)
goto out_close; goto out_close;
} }
mtd->eb_cnt = ui.size / ui.erasesize; mtd->eb_cnt = mtd_user_div_by_eb(ui.size, &ui);
switch(mtd->type) { switch(mtd->type) {
case MTD_ABSENT: case MTD_ABSENT: