#include <linux/module.h>
#include <linux/slab.h>
#include <linux/sched.h>
+#include <linux/smp_lock.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/compatmac.h>
if (!mtd)
return;
- device_create(mtd_class, NULL, MKDEV(MTD_CHAR_MAJOR, mtd->index*2), "mtd%d", mtd->index);
+ device_create(mtd_class, NULL, MKDEV(MTD_CHAR_MAJOR, mtd->index*2),
+ NULL, "mtd%d", mtd->index);
- device_create(mtd_class, NULL,
- MKDEV(MTD_CHAR_MAJOR, mtd->index*2+1), "mtd%dro", mtd->index);
+ device_create(mtd_class, NULL, MKDEV(MTD_CHAR_MAJOR, mtd->index*2+1),
+ NULL, "mtd%dro", mtd->index);
}
static void mtd_notify_remove(struct mtd_info* mtd)
{
int minor = iminor(inode);
int devnum = minor >> 1;
+ int ret = 0;
struct mtd_info *mtd;
struct mtd_file_info *mfi;
return -ENODEV;
/* You can't open the RO devices RW */
- if ((file->f_mode & 2) && (minor & 1))
+ if ((file->f_mode & FMODE_WRITE) && (minor & 1))
return -EACCES;
+ lock_kernel();
mtd = get_mtd_device(NULL, devnum);
- if (IS_ERR(mtd))
- return PTR_ERR(mtd);
+ if (IS_ERR(mtd)) {
+ ret = PTR_ERR(mtd);
+ goto out;
+ }
if (MTD_ABSENT == mtd->type) {
put_mtd_device(mtd);
- return -ENODEV;
+ ret = -ENODEV;
+ goto out;
}
/* You can't open it RW if it's not a writeable device */
- if ((file->f_mode & 2) && !(mtd->flags & MTD_WRITEABLE)) {
+ if ((file->f_mode & FMODE_WRITE) && !(mtd->flags & MTD_WRITEABLE)) {
put_mtd_device(mtd);
- return -EACCES;
+ ret = -EACCES;
+ goto out;
}
mfi = kzalloc(sizeof(*mfi), GFP_KERNEL);
if (!mfi) {
put_mtd_device(mtd);
- return -ENOMEM;
+ ret = -ENOMEM;
+ goto out;
}
mfi->mtd = mtd;
file->private_data = mfi;
- return 0;
+out:
+ unlock_kernel();
+ return ret;
} /* mtd_open */
/*====================================================================*/
DEBUG(MTD_DEBUG_LEVEL0, "MTD_close\n");
/* Only sync if opened RW */
- if ((file->f_mode & 2) && mtd->sync)
+ if ((file->f_mode & FMODE_WRITE) && mtd->sync)
mtd->sync(mtd);
put_mtd_device(mtd);
wake_up((wait_queue_head_t *)instr->priv);
}
-#if defined(CONFIG_MTD_OTP) || defined(CONFIG_MTD_ONENAND_OTP)
+#ifdef CONFIG_HAVE_MTD_OTP
static int otp_select_filemode(struct mtd_file_info *mfi, int mode)
{
struct mtd_info *mtd = mfi->mtd;
case MEMGETREGIONINFO:
{
- struct region_info_user ur;
+ uint32_t ur_idx;
+ struct mtd_erase_region_info *kr;
+ struct region_info_user *ur = (struct region_info_user *) argp;
- if (copy_from_user(&ur, argp, sizeof(struct region_info_user)))
+ if (get_user(ur_idx, &(ur->regionindex)))
return -EFAULT;
- if (ur.regionindex >= mtd->numeraseregions)
- return -EINVAL;
- if (copy_to_user(argp, &(mtd->eraseregions[ur.regionindex]),
- sizeof(struct mtd_erase_region_info)))
+ kr = &(mtd->eraseregions[ur_idx]);
+
+ if (put_user(kr->offset, &(ur->offset))
+ || put_user(kr->erasesize, &(ur->erasesize))
+ || put_user(kr->numblocks, &(ur->numblocks)))
return -EFAULT;
+
break;
}
{
struct erase_info *erase;
- if(!(file->f_mode & 2))
+ if(!(file->f_mode & FMODE_WRITE))
return -EPERM;
erase=kzalloc(sizeof(struct erase_info),GFP_KERNEL);
if (!erase)
ret = -ENOMEM;
else {
+ struct erase_info_user einfo;
+
wait_queue_head_t waitq;
DECLARE_WAITQUEUE(wait, current);
init_waitqueue_head(&waitq);
- if (copy_from_user(&erase->addr, argp,
+ if (copy_from_user(&einfo, argp,
sizeof(struct erase_info_user))) {
kfree(erase);
return -EFAULT;
}
+ erase->addr = einfo.start;
+ erase->len = einfo.length;
erase->mtd = mtd;
erase->callback = mtdchar_erase_callback;
erase->priv = (unsigned long)&waitq;
struct mtd_oob_buf __user *user_buf = argp;
uint32_t retlen;
- if(!(file->f_mode & 2))
+ if(!(file->f_mode & FMODE_WRITE))
return -EPERM;
if (copy_from_user(&buf, argp, sizeof(struct mtd_oob_buf)))
case MEMLOCK:
{
- struct erase_info_user info;
+ struct erase_info_user einfo;
- if (copy_from_user(&info, argp, sizeof(info)))
+ if (copy_from_user(&einfo, argp, sizeof(einfo)))
return -EFAULT;
if (!mtd->lock)
ret = -EOPNOTSUPP;
else
- ret = mtd->lock(mtd, info.start, info.length);
+ ret = mtd->lock(mtd, einfo.start, einfo.length);
break;
}
case MEMUNLOCK:
{
- struct erase_info_user info;
+ struct erase_info_user einfo;
- if (copy_from_user(&info, argp, sizeof(info)))
+ if (copy_from_user(&einfo, argp, sizeof(einfo)))
return -EFAULT;
if (!mtd->unlock)
ret = -EOPNOTSUPP;
else
- ret = mtd->unlock(mtd, info.start, info.length);
+ ret = mtd->unlock(mtd, einfo.start, einfo.length);
break;
}
break;
}
-#if defined(CONFIG_MTD_OTP) || defined(CONFIG_MTD_ONENAND_OTP)
+#ifdef CONFIG_HAVE_MTD_OTP
case OTPSELECT:
{
int mode;
case OTPLOCK:
{
- struct otp_info info;
+ struct otp_info oinfo;
if (mfi->mode != MTD_MODE_OTP_USER)
return -EINVAL;
- if (copy_from_user(&info, argp, sizeof(info)))
+ if (copy_from_user(&oinfo, argp, sizeof(oinfo)))
return -EFAULT;
if (!mtd->lock_user_prot_reg)
return -EOPNOTSUPP;
- ret = mtd->lock_user_prot_reg(mtd, info.start, info.length);
+ ret = mtd->lock_user_prot_reg(mtd, oinfo.start, oinfo.length);
break;
}
#endif