Commit 33caf82a authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'work.misc' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs

Pull misc vfs updates from Al Viro:
 "All kinds of stuff.  That probably should've been 5 or 6 separate
  branches, but by the time I'd realized how large and mixed that bag
  had become it had been too close to -final to play with rebasing.

  Some fs/namei.c cleanups there, memdup_user_nul() introduction and
  switching open-coded instances, burying long-dead code, whack-a-mole
  of various kinds, several new helpers for ->llseek(), assorted
  cleanups and fixes from various people, etc.

  One piece probably deserves special mention - Neil's
  lookup_one_len_unlocked().  Similar to lookup_one_len(), but gets
  called without ->i_mutex and tries to avoid ever taking it.  That, of
  course, means that it's not useful for any directory modifications,
  but things like getting inode attributes in nfds readdirplus are fine
  with that.  I really should've asked for moratorium on lookup-related
  changes this cycle, but since I hadn't done that early enough...  I
  *am* asking for that for the coming cycle, though - I'm going to try
  and get conversion of i_mutex to rwsem with ->lookup() done under lock
  taken shared.

  There will be a patch closer to the end of the window, along the lines
  of the one Linus had posted last May - mechanical conversion of
  ->i_mutex accesses to inode_lock()/inode_unlock()/inode_trylock()/
  inode_is_locked()/inode_lock_nested().  To quote Linus back then:

    -----
    |    This is an automated patch using
    |
    |        sed 's/mutex_lock(&\(.*\)->i_mutex)/inode_lock(\1)/'
    |        sed 's/mutex_unlock(&\(.*\)->i_mutex)/inode_unlock(\1)/'
    |        sed 's/mutex_lock_nested(&\(.*\)->i_mutex,[     ]*I_MUTEX_\([A-Z0-9_]*\))/inode_lock_nested(\1, I_MUTEX_\2)/'
    |        sed 's/mutex_is_locked(&\(.*\)->i_mutex)/inode_is_locked(\1)/'
    |        sed 's/mutex_trylock(&\(.*\)->i_mutex)/inode_trylock(\1)/'
    |
    |    with a very few manual fixups
    -----

  I'm going to send that once the ->i_mutex-affecting stuff in -next
  gets mostly merged (or when Linus says he's about to stop taking
  merges)"

* 'work.misc' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs: (63 commits)
  nfsd: don't hold i_mutex over userspace upcalls
  fs:affs:Replace time_t with time64_t
  fs/9p: use fscache mutex rather than spinlock
  proc: add a reschedule point in proc_readfd_common()
  logfs: constify logfs_block_ops structures
  fcntl: allow to set O_DIRECT flag on pipe
  fs: __generic_file_splice_read retry lookup on AOP_TRUNCATED_PAGE
  fs: xattr: Use kvfree()
  [s390] page_to_phys() always returns a multiple of PAGE_SIZE
  nbd: use ->compat_ioctl()
  fs: use block_device name vsprintf helper
  lib/vsprintf: add %*pg format specifier
  fs: use gendisk->disk_name where possible
  poll: plug an unused argument to do_poll
  amdkfd: don't open-code memdup_user()
  cdrom: don't open-code memdup_user()
  rsxx: don't open-code memdup_user()
  mtip32xx: don't open-code memdup_user()
  [um] mconsole: don't open-code memdup_user_nul()
  [um] hostaudio: don't open-code memdup_user()
  ...
parents ca9706a2 bbddca8e
......@@ -250,6 +250,12 @@ dentry names:
Passed by reference.
block_device names:
%pg sda, sda1 or loop0p1
For printing name of block_device pointers.
struct va_format:
%pV
......
......@@ -168,12 +168,6 @@ static inline int bad_user_access_length(void)
#define __copy_to_user_inatomic __copy_to_user
#define __copy_from_user_inatomic __copy_from_user
#define copy_to_user_ret(to, from, n, retval) ({ if (copy_to_user(to, from, n))\
return retval; })
#define copy_from_user_ret(to, from, n, retval) ({ if (copy_from_user(to, from, n))\
return retval; })
static inline unsigned long __must_check
copy_from_user(void *to, const void __user *from, unsigned long n)
{
......
......@@ -135,10 +135,6 @@ extern int __get_user_bad(void);
#define __copy_to_user_inatomic __copy_to_user
#define __copy_from_user_inatomic __copy_from_user
#define copy_to_user_ret(to,from,n,retval) ({ if (copy_to_user(to,from,n)) return retval; })
#define copy_from_user_ret(to,from,n,retval) ({ if (copy_from_user(to,from,n)) return retval; })
/*
* Copy a null terminated string from userspace.
*/
......
......@@ -22,7 +22,6 @@
static DEFINE_MUTEX(pvc_mutex);
static char pvc_lines[PVC_NLINES][PVC_LINELEN+1];
static int pvc_linedata[PVC_NLINES];
static struct proc_dir_entry *pvc_display_dir;
static char *pvc_linename[PVC_NLINES] = {"line1", "line2"};
#define DISPLAY_DIR_NAME "display"
static int scroll_dir, scroll_interval;
......@@ -169,22 +168,17 @@ void pvc_proc_timerfunc(unsigned long data)
static void pvc_proc_cleanup(void)
{
int i;
for (i = 0; i < PVC_NLINES; i++)
remove_proc_entry(pvc_linename[i], pvc_display_dir);
remove_proc_entry("scroll", pvc_display_dir);
remove_proc_entry(DISPLAY_DIR_NAME, NULL);
remove_proc_subtree(DISPLAY_DIR_NAME, NULL);
del_timer_sync(&timer);
}
static int __init pvc_proc_init(void)
{
struct proc_dir_entry *proc_entry;
struct proc_dir_entry *dir, *proc_entry;
int i;
pvc_display_dir = proc_mkdir(DISPLAY_DIR_NAME, NULL);
if (pvc_display_dir == NULL)
dir = proc_mkdir(DISPLAY_DIR_NAME, NULL);
if (dir == NULL)
goto error;
for (i = 0; i < PVC_NLINES; i++) {
......@@ -192,12 +186,12 @@ static int __init pvc_proc_init(void)
pvc_linedata[i] = i;
}
for (i = 0; i < PVC_NLINES; i++) {
proc_entry = proc_create_data(pvc_linename[i], 0644, pvc_display_dir,
proc_entry = proc_create_data(pvc_linename[i], 0644, dir,
&pvc_line_proc_fops, &pvc_linedata[i]);
if (proc_entry == NULL)
goto error;
}
proc_entry = proc_create("scroll", 0644, pvc_display_dir,
proc_entry = proc_create("scroll", 0644, dir,
&pvc_scroll_proc_fops);
if (proc_entry == NULL)
goto error;
......
......@@ -110,21 +110,6 @@ extern int fixup_exception(struct pt_regs *regs);
#define __put_user(x, ptr) __put_user_nocheck((x), (ptr), sizeof(*(ptr)))
#define __get_user(x, ptr) __get_user_nocheck((x), (ptr), sizeof(*(ptr)))
/*
* The "xxx_ret" versions return constant specified in third argument, if
* something bad happens. These macros can be optimized for the
* case of just returning from the function xxx_ret is used.
*/
#define put_user_ret(x, ptr, ret) \
({ if (put_user((x), (ptr))) return (ret); })
#define get_user_ret(x, ptr, ret) \
({ if (get_user((x), (ptr))) return (ret); })
#define __put_user_ret(x, ptr, ret) \
({ if (__put_user((x), (ptr))) return (ret); })
#define __get_user_ret(x, ptr, ret) \
({ if (__get_user((x), (ptr))) return (ret); })
struct __large_struct { unsigned long buf[100]; };
#define __m(x) (*(struct __large_struct *)(x))
......
......@@ -274,21 +274,6 @@ do { \
__gu_err; \
})
#ifndef __powerpc64__
#define __get_user64_nocheck(x, ptr, size) \
({ \
long __gu_err; \
long long __gu_val; \
__typeof__(*(ptr)) __user *__gu_addr = (ptr); \
__chk_user_ptr(ptr); \
if (!is_kernel_addr((unsigned long)__gu_addr)) \
might_fault(); \
__get_user_size(__gu_val, __gu_addr, (size), __gu_err); \
(x) = (__force __typeof__(*(ptr)))__gu_val; \
__gu_err; \
})
#endif /* __powerpc64__ */
#define __get_user_check(x, ptr, size) \
({ \
long __gu_err = -EFAULT; \
......
......@@ -27,6 +27,7 @@
#include <linux/slab.h>
#include <linux/spinlock.h>
#include <linux/kmsg_dump.h>
#include <linux/pagemap.h>
#include <linux/pstore.h>
#include <linux/zlib.h>
#include <asm/uaccess.h>
......@@ -733,24 +734,10 @@ static void oops_to_nvram(struct kmsg_dumper *dumper,
static loff_t dev_nvram_llseek(struct file *file, loff_t offset, int origin)
{
int size;
if (ppc_md.nvram_size == NULL)
return -ENODEV;
size = ppc_md.nvram_size();
switch (origin) {
case 1:
offset += file->f_pos;
break;
case 2:
offset += size;
break;
}
if (offset < 0)
return -EINVAL;
file->f_pos = offset;
return file->f_pos;
return generic_file_llseek_size(file, offset, origin, MAX_LFS_FILESIZE,
ppc_md.nvram_size());
}
......
......@@ -366,8 +366,7 @@ static void *s390_dma_alloc(struct device *dev, size_t size,
pa = page_to_phys(page);
memset((void *) pa, 0, size);
map = s390_dma_map_pages(dev, page, pa % PAGE_SIZE,
size, DMA_BIDIRECTIONAL, NULL);
map = s390_dma_map_pages(dev, page, 0, size, DMA_BIDIRECTIONAL, NULL);
if (dma_mapping_error(dev, map)) {
free_pages(pa, get_order(size));
return NULL;
......
......@@ -205,31 +205,6 @@ int __put_user_bad(void);
__gu_ret; \
})
#define __get_user_check_ret(x, addr, size, type, retval) ({ \
register unsigned long __gu_val __asm__ ("l1"); \
if (__access_ok(addr, size)) { \
switch (size) { \
case 1: \
__get_user_asm_ret(__gu_val, ub, addr, retval); \
break; \
case 2: \
__get_user_asm_ret(__gu_val, uh, addr, retval); \
break; \
case 4: \
__get_user_asm_ret(__gu_val, , addr, retval); \
break; \
case 8: \
__get_user_asm_ret(__gu_val, d, addr, retval); \
break; \
default: \
if (__get_user_bad()) \
return retval; \
} \
x = (__force type) __gu_val; \
} else \
return retval; \
})
#define __get_user_nocheck(x, addr, size, type) ({ \
register int __gu_ret; \
register unsigned long __gu_val; \
......@@ -247,20 +222,6 @@ int __put_user_bad(void);
__gu_ret; \
})
#define __get_user_nocheck_ret(x, addr, size, type, retval) ({ \
register unsigned long __gu_val __asm__ ("l1"); \
switch (size) { \
case 1: __get_user_asm_ret(__gu_val, ub, addr, retval); break; \
case 2: __get_user_asm_ret(__gu_val, uh, addr, retval); break; \
case 4: __get_user_asm_ret(__gu_val, , addr, retval); break; \
case 8: __get_user_asm_ret(__gu_val, d, addr, retval); break; \
default: \
if (__get_user_bad()) \
return retval; \
} \
x = (__force type) __gu_val; \
})
#define __get_user_asm(x, size, addr, ret) \
__asm__ __volatile__( \
"/* Get user asm, inline. */\n" \
......@@ -281,32 +242,6 @@ __asm__ __volatile__( \
: "=&r" (ret), "=&r" (x) : "m" (*__m(addr)), \
"i" (-EFAULT))
#define __get_user_asm_ret(x, size, addr, retval) \
if (__builtin_constant_p(retval) && retval == -EFAULT) \
__asm__ __volatile__( \
"/* Get user asm ret, inline. */\n" \
"1:\t" "ld"#size " %1, %0\n\n\t" \
".section __ex_table,#alloc\n\t" \
".align 4\n\t" \
".word 1b,__ret_efault\n\n\t" \
".previous\n\t" \
: "=&r" (x) : "m" (*__m(addr))); \
else \
__asm__ __volatile__( \
"/* Get user asm ret, inline. */\n" \
"1:\t" "ld"#size " %1, %0\n\n\t" \
".section .fixup,#alloc,#execinstr\n\t" \
".align 4\n" \
"3:\n\t" \
"ret\n\t" \
" restore %%g0, %2, %%o0\n\n\t" \
".previous\n\t" \
".section __ex_table,#alloc\n\t" \
".align 4\n\t" \
".word 1b, 3b\n\n\t" \
".previous\n\t" \
: "=&r" (x) : "m" (*__m(addr)), "i" (retval))
int __get_user_bad(void);
unsigned long __copy_user(void __user *to, const void __user *from, unsigned long size);
......
......@@ -179,20 +179,6 @@ int __put_user_bad(void);
__gu_ret; \
})
#define __get_user_nocheck_ret(data, addr, size, type, retval) ({ \
register unsigned long __gu_val __asm__ ("l1"); \
switch (size) { \
case 1: __get_user_asm_ret(__gu_val, ub, addr, retval); break; \
case 2: __get_user_asm_ret(__gu_val, uh, addr, retval); break; \
case 4: __get_user_asm_ret(__gu_val, uw, addr, retval); break; \
case 8: __get_user_asm_ret(__gu_val, x, addr, retval); break; \
default: \
if (__get_user_bad()) \
return retval; \
} \
data = (__force type) __gu_val; \
})
#define __get_user_asm(x, size, addr, ret) \
__asm__ __volatile__( \
"/* Get user asm, inline. */\n" \
......@@ -214,32 +200,6 @@ __asm__ __volatile__( \
: "=r" (ret), "=r" (x) : "r" (__m(addr)), \
"i" (-EFAULT))
#define __get_user_asm_ret(x, size, addr, retval) \
if (__builtin_constant_p(retval) && retval == -EFAULT) \
__asm__ __volatile__( \
"/* Get user asm ret, inline. */\n" \
"1:\t" "ld"#size "a [%1] %%asi, %0\n\n\t" \
".section __ex_table,\"a\"\n\t" \
".align 4\n\t" \
".word 1b,__ret_efault\n\n\t" \
".previous\n\t" \
: "=r" (x) : "r" (__m(addr))); \
else \
__asm__ __volatile__( \
"/* Get user asm ret, inline. */\n" \
"1:\t" "ld"#size "a [%1] %%asi, %0\n\n\t" \
".section .fixup,#alloc,#execinstr\n\t" \
".align 4\n" \
"3:\n\t" \
"ret\n\t" \
" restore %%g0, %2, %%o0\n\n\t" \
".previous\n\t" \
".section __ex_table,\"a\"\n\t" \
".align 4\n\t" \
".word 1b, 3b\n\n\t" \
".previous\n\t" \
: "=r" (x) : "r" (__m(addr)), "i" (retval))
int __get_user_bad(void);
unsigned long __must_check ___copy_from_user(void *to,
......
......@@ -1033,25 +1033,9 @@ static ssize_t mdesc_read(struct file *file, char __user *buf,
static loff_t mdesc_llseek(struct file *file, loff_t offset, int whence)
{
struct mdesc_handle *hp;
switch (whence) {
case SEEK_CUR:
offset += file->f_pos;
break;
case SEEK_SET:
break;
default:
return -EINVAL;
}
hp = file->private_data;
if (offset > hp->handle_size)
return -EINVAL;
else
file->f_pos = offset;
struct mdesc_handle *hp = file->private_data;
return offset;
return no_seek_end_llseek_size(file, offset, whence, hp->handle_size);
}
/* mdesc_close() - /dev/mdesc is being closed, release the reference to
......
......@@ -105,13 +105,9 @@ static ssize_t hostaudio_write(struct file *file, const char __user *buffer,
printk(KERN_DEBUG "hostaudio: write called, count = %d\n", count);
#endif
kbuf = kmalloc(count, GFP_KERNEL);
if (kbuf == NULL)
return -ENOMEM;
err = -EFAULT;
if (copy_from_user(kbuf, buffer, count))
goto out;
kbuf = memdup_user(buffer, count);
if (IS_ERR(kbuf))
return PTR_ERR(kbuf);
err = os_write_file(state->fd, kbuf, count);
if (err < 0)
......
......@@ -748,19 +748,11 @@ static ssize_t mconsole_proc_write(struct file *file,
{
char *buf;
buf = kmalloc(count + 1, GFP_KERNEL);
if (buf == NULL)
return -ENOMEM;
if (copy_from_user(buf, buffer, count)) {
count = -EFAULT;
goto out;
}
buf[count] = '\0';
buf = memdup_user_nul(buffer, count);
if (IS_ERR(buf))
return PTR_ERR(buf);
mconsole_notify(notify_socket, MCONSOLE_USER_NOTIFY, buf, count);
out:
kfree(buf);
return count;
}
......
......@@ -58,28 +58,6 @@ static void cpuid_smp_cpuid(void *cmd_block)
&cmd->eax, &cmd->ebx, &cmd->ecx, &cmd->edx);
}
static loff_t cpuid_seek(struct file *file, loff_t offset, int orig)
{
loff_t ret;
struct inode *inode = file->f_mapping->host;
mutex_lock(&inode->i_mutex);
switch (orig) {
case 0:
file->f_pos = offset;
ret = file->f_pos;
break;
case 1:
file->f_pos += offset;
ret = file->f_pos;
break;
default:
ret = -EINVAL;
}
mutex_unlock(&inode->i_mutex);
return ret;
}
static ssize_t cpuid_read(struct file *file, char __user *buf,
size_t count, loff_t *ppos)
{
......@@ -132,7 +110,7 @@ static int cpuid_open(struct inode *inode, struct file *file)
*/
static const struct file_operations cpuid_fops = {
.owner = THIS_MODULE,
.llseek = cpuid_seek,
.llseek = no_seek_end_llseek,
.read = cpuid_read,
.open = cpuid_open,
};
......
......@@ -45,28 +45,6 @@
static struct class *msr_class;
static loff_t msr_seek(struct file *file, loff_t offset, int orig)
{
loff_t ret;
struct inode *inode = file_inode(file);
mutex_lock(&inode->i_mutex);
switch (orig) {
case SEEK_SET:
file->f_pos = offset;
ret = file->f_pos;
break;
case SEEK_CUR:
file->f_pos += offset;
ret = file->f_pos;
break;
default:
ret = -EINVAL;
}
mutex_unlock(&inode->i_mutex);
return ret;
}
static ssize_t msr_read(struct file *file, char __user *buf,
size_t count, loff_t *ppos)
{
......@@ -194,7 +172,7 @@ static int msr_open(struct inode *inode, struct file *file)
*/
static const struct file_operations msr_fops = {
.owner = THIS_MODULE,
.llseek = msr_seek,
.llseek = no_seek_end_llseek,
.read = msr_read,
.write = msr_write,
.open = msr_open,
......
......@@ -227,16 +227,12 @@ static ssize_t proc_read_simdisk(struct file *file, char __user *buf,
static ssize_t proc_write_simdisk(struct file *file, const char __user *buf,
size_t count, loff_t *ppos)
{
char *tmp = kmalloc(count + 1, GFP_KERNEL);
char *tmp = memdup_user_nul(buf, count);
struct simdisk *dev = PDE_DATA(file_inode(file));
int err;
if (tmp == NULL)
return -ENOMEM;
if (copy_from_user(tmp, buf, count)) {
err = -EFAULT;
goto out_free;
}
if (IS_ERR(tmp))
return PTR_ERR(tmp);
err = simdisk_detach(dev);
if (err != 0)
......@@ -244,8 +240,6 @@ static ssize_t proc_write_simdisk(struct file *file, const char __user *buf,
if (count > 0 && tmp[count - 1] == '\n')
tmp[count - 1] = 0;
else
tmp[count] = 0;
if (tmp[0])
err = simdisk_attach(dev, tmp);
......
......@@ -514,14 +514,9 @@ cciss_proc_write(struct file *file, const char __user *buf,
if (!buf || length > PAGE_SIZE - 1)
return -EINVAL;
buffer = (char *)__get_free_page(GFP_KERNEL);
if (!buffer)
return -ENOMEM;
err = -EFAULT;
if (copy_from_user(buffer, buf, length))
goto out;
buffer[length] = '\0';
buffer = memdup_user_nul(buf, length);
if (IS_ERR(buffer))
return PTR_ERR(buffer);
#ifdef CONFIG_CISS_SCSI_TAPE
if (strncmp(ENGAGE_SCSI, buffer, sizeof ENGAGE_SCSI - 1) == 0) {
......@@ -537,8 +532,7 @@ cciss_proc_write(struct file *file, const char __user *buf,
/* might be nice to have "disengage" too, but it's not
safely possible. (only 1 module use count, lock issues.) */
out:
free_page((unsigned long)buffer);
kfree(buffer);
return err;
}
......
......@@ -2029,13 +2029,10 @@ static int exec_drive_taskfile(struct driver_data *dd,
}
if (taskout) {
outbuf = kzalloc(taskout, GFP_KERNEL);
if (outbuf == NULL) {
err = -ENOMEM;
goto abort;
}
if (copy_from_user(outbuf, buf + outtotal, taskout)) {
err = -EFAULT;
outbuf = memdup_user(buf + outtotal, taskout);
if (IS_ERR(outbuf)) {
err = PTR_ERR(outbuf);
outbuf = NULL;
goto abort;
}
outbuf_dma = pci_map_single(dd->pdev,
......@@ -2050,14 +2047,10 @@ static int exec_drive_taskfile(struct driver_data *dd,
}
if (taskin) {
inbuf = kzalloc(taskin, GFP_KERNEL);
if (inbuf == NULL) {
err = -ENOMEM;
goto abort;
}
if (copy_from_user(inbuf, buf + intotal, taskin)) {
err = -EFAULT;
inbuf = memdup_user(buf + intotal, taskin);
if (IS_ERR(inbuf)) {
err = PTR_ERR(inbuf);
inbuf = NULL;
goto abort;
}
inbuf_dma = pci_map_single(dd->pdev,
......
......@@ -827,6 +827,7 @@ static const struct block_device_operations nbd_fops =
{
.owner = THIS_MODULE,
.ioctl = nbd_ioctl,
.compat_ioctl = nbd_ioctl,
};
#if IS_ENABLED(CONFIG_DEBUG_FS)
......
......@@ -203,14 +203,11 @@ static ssize_t rsxx_cram_write(struct file *fp, const char __user *ubuf,
char *buf;
ssize_t st;
buf = kzalloc(cnt, GFP_KERNEL);
if (!buf)
return -ENOMEM;
buf = memdup_user(ubuf, cnt);
if (IS_ERR(buf))
return PTR_ERR(buf);
st = copy_from_user(buf, ubuf, cnt);
if (!st)
st = rsxx_creg_write(card, CREG_ADD_CRAM + (u32)*ppos, cnt,
buf, 1);
st = rsxx_creg_write(card, CREG_ADD_CRAM + (u32)*ppos, cnt, buf, 1);
kfree(buf);
if (st)
return st;
......
......@@ -3186,15 +3186,11 @@ static noinline int mmc_ioctl_dvd_read_struct(struct cdrom_device_info *cdi,
if (!CDROM_CAN(CDC_DVD))
return -ENOSYS;
s = kmalloc(size, GFP_KERNEL);
if (!s)
return -ENOMEM;
s = memdup_user(arg, size);
if (IS_ERR(s))
return PTR_ERR(s);
cd_dbg(CD_DO_IOCTL, "entering DVD_READ_STRUCT\n");
if (copy_from_user(s, arg, size)) {
kfree(s);
return -EFAULT;
}
ret = dvd_read_struct(cdi, s, cgc);
if (ret)
......
......@@ -20,6 +20,7 @@
#include <linux/fcntl.h>
#include <linux/init.h>
#include <linux/mutex.h>
#include <linux/pagemap.h>
#include <asm/uaccess.h>
#include <asm/nvram.h>
#ifdef CONFIG_PPC_PMAC
......@@ -33,24 +34,8 @@ static ssize_t nvram_len;
static loff_t nvram_llseek(struct file *file, loff_t offset, int origin)
{
switch (origin) {
case 0:
break;
case 1:
offset += file->f_pos;
break;
case 2:
offset += nvram_len;
break;
default:
offset = -1;
}
if (offset < 0)
return -EINVAL;
file->f_pos = offset;
return file->f_pos;
return generic_file_llseek_size(file, offset, origin,
MAX_LFS_FILESIZE, nvram_len);
}
static ssize_t read_nvram(struct file *file, char __user *buf,
......
......@@ -26,6 +26,7 @@
#include <linux/uio.h>
#include <linux/mutex.h>
#include <linux/slab.h>
#include <linux/pagemap.h>
#include <asm/io.h>
#include <asm/uaccess.h>
#include <asm/pgtable.h>
......@@ -451,31 +452,8 @@ mbcs_sram_write(struct file * fp, const char __user *buf, size_t len, loff_t * o
static loff_t mbcs_sram_llseek(struct file * filp, loff_t off, int whence)
{
loff_t newpos;
switch (whence) {
case SEEK_SET:
newpos = off;
break;
case SEEK_CUR:
newpos = filp->f_pos + off;
break;
case SEEK_END:
newpos = MBCS_SRAM_SIZE + off;
break;
default: /* can't happen */
return -EINVAL;
}