From 54632c05e0a12f2cf3358a3720d7ccd8ae55b700 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Mon, 6 Jun 2005 15:07:19 -0700 Subject: [PATCH] --- yaml --- r: 1860 b: refs/heads/master c: fa04ae5c09f3dfedbc923c2954a9a26a573833f1 h: refs/heads/master v: v3 --- [refs] | 2 +- trunk/arch/ppc/kernel/misc.S | 6 +- trunk/drivers/char/mxser.c | 38 ++++--- trunk/fs/binfmt_flat.c | 6 +- trunk/fs/namei.c | 153 ++++++++++++--------------- trunk/include/asm-h8300/kmap_types.h | 6 +- trunk/include/asm-h8300/mman.h | 3 - trunk/mm/filemap.c | 8 +- trunk/net/core/ethtool.c | 2 +- 9 files changed, 103 insertions(+), 121 deletions(-) diff --git a/[refs] b/[refs] index 9e30c5286c96..10ce2d52dcda 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: 8f5bb0438b86d1a5393176ceeec2836fd469edf8 +refs/heads/master: fa04ae5c09f3dfedbc923c2954a9a26a573833f1 diff --git a/trunk/arch/ppc/kernel/misc.S b/trunk/arch/ppc/kernel/misc.S index 7329ef177a18..e4f1615ec13f 100644 --- a/trunk/arch/ppc/kernel/misc.S +++ b/trunk/arch/ppc/kernel/misc.S @@ -619,7 +619,7 @@ _GLOBAL(flush_instruction_cache) _GLOBAL(flush_icache_range) BEGIN_FTR_SECTION blr /* for 601, do nothing */ -END_FTR_SECTION_IFCLR(CPU_FTR_SPLIT_ID_CACHE) +END_FTR_SECTION_IFSET(PPC_FEATURE_UNIFIED_CACHE) li r5,L1_CACHE_LINE_SIZE-1 andc r3,r3,r5 subf r4,r3,r4 @@ -736,7 +736,7 @@ _GLOBAL(flush_dcache_all) _GLOBAL(__flush_dcache_icache) BEGIN_FTR_SECTION blr /* for 601, do nothing */ -END_FTR_SECTION_IFCLR(CPU_FTR_SPLIT_ID_CACHE) +END_FTR_SECTION_IFSET(PPC_FEATURE_UNIFIED_CACHE) rlwinm r3,r3,0,0,19 /* Get page base address */ li r4,4096/L1_CACHE_LINE_SIZE /* Number of lines in a page */ mtctr r4 @@ -764,7 +764,7 @@ END_FTR_SECTION_IFCLR(CPU_FTR_SPLIT_ID_CACHE) _GLOBAL(__flush_dcache_icache_phys) BEGIN_FTR_SECTION blr /* for 601, do nothing */ -END_FTR_SECTION_IFCLR(CPU_FTR_SPLIT_ID_CACHE) +END_FTR_SECTION_IFSET(PPC_FEATURE_UNIFIED_CACHE) mfmsr r10 rlwinm r0,r10,0,28,26 /* clear DR */ mtmsr r0 diff --git a/trunk/drivers/char/mxser.c b/trunk/drivers/char/mxser.c index f022f0944434..7a245068e3e5 100644 --- a/trunk/drivers/char/mxser.c +++ b/trunk/drivers/char/mxser.c @@ -1995,6 +1995,9 @@ static void mxser_receive_chars(struct mxser_struct *info, int *status) unsigned char ch, gdl; int ignored = 0; int cnt = 0; + unsigned char *cp; + char *fp; + int count; int recv_room; int max = 256; unsigned long flags; @@ -2008,6 +2011,10 @@ static void mxser_receive_chars(struct mxser_struct *info, int *status) //return; } + cp = tty->flip.char_buf; + fp = tty->flip.flag_buf; + count = 0; + // following add by Victor Yu. 09-02-2002 if (info->IsMoxaMustChipFlag != MOXA_OTHER_UART) { @@ -2034,10 +2041,12 @@ static void mxser_receive_chars(struct mxser_struct *info, int *status) } while (gdl--) { ch = inb(info->base + UART_RX); - tty_insert_flip_char(tty, ch, 0); + count++; + *cp++ = ch; + *fp++ = 0; cnt++; /* - if((cnt>=HI_WATER) && (info->stop_rx==0)){ + if((count>=HI_WATER) && (info->stop_rx==0)){ mxser_stoprx(tty); info->stop_rx=1; break; @@ -2052,7 +2061,7 @@ static void mxser_receive_chars(struct mxser_struct *info, int *status) if (max-- < 0) break; /* - if((cnt>=HI_WATER) && (info->stop_rx==0)){ + if((count>=HI_WATER) && (info->stop_rx==0)){ mxser_stoprx(tty); info->stop_rx=1; break; @@ -2069,33 +2078,36 @@ static void mxser_receive_chars(struct mxser_struct *info, int *status) if (++ignored > 100) break; } else { - char flag = 0; + count++; if (*status & UART_LSR_SPECIAL) { if (*status & UART_LSR_BI) { - flag = TTY_BREAK; + *fp++ = TTY_BREAK; /* added by casper 1/11/2000 */ info->icount.brk++; + /* */ if (info->flags & ASYNC_SAK) do_SAK(tty); } else if (*status & UART_LSR_PE) { - flag = TTY_PARITY; + *fp++ = TTY_PARITY; /* added by casper 1/11/2000 */ info->icount.parity++; /* */ } else if (*status & UART_LSR_FE) { - flag = TTY_FRAME; + *fp++ = TTY_FRAME; /* added by casper 1/11/2000 */ info->icount.frame++; /* */ } else if (*status & UART_LSR_OE) { - flag = TTY_OVERRUN; + *fp++ = TTY_OVERRUN; /* added by casper 1/11/2000 */ info->icount.overrun++; /* */ - } - } - tty_insert_flip_char(tty, ch, flag); + } else + *fp++ = 0; + } else + *fp++ = 0; + *cp++ = ch; cnt++; if (cnt >= recv_room) { if (!info->ldisc_stop_rx) { @@ -2120,13 +2132,13 @@ static void mxser_receive_chars(struct mxser_struct *info, int *status) // above add by Victor Yu. 09-02-2002 } while (*status & UART_LSR_DR); -end_intr: // add by Victor Yu. 09-02-2002 + end_intr: // add by Victor Yu. 09-02-2002 mxvar_log.rxcnt[info->port] += cnt; info->mon_data.rxcnt += cnt; info->mon_data.up_rxcnt += cnt; spin_unlock_irqrestore(&info->slock, flags); - + tty_flip_buffer_push(tty); } diff --git a/trunk/fs/binfmt_flat.c b/trunk/fs/binfmt_flat.c index c8998dc66882..f0cd67d9d31b 100644 --- a/trunk/fs/binfmt_flat.c +++ b/trunk/fs/binfmt_flat.c @@ -520,7 +520,7 @@ static int load_flat_file(struct linux_binprm * bprm, DBG_FLT("BINFMT_FLAT: ROM mapping of file (we hope)\n"); down_write(¤t->mm->mmap_sem); - textpos = do_mmap(bprm->file, 0, text_len, PROT_READ|PROT_EXEC, MAP_SHARED, 0); + textpos = do_mmap(bprm->file, 0, text_len, PROT_READ|PROT_EXEC, 0, 0); up_write(¤t->mm->mmap_sem); if (!textpos || textpos >= (unsigned long) -4096) { if (!textpos) @@ -532,7 +532,7 @@ static int load_flat_file(struct linux_binprm * bprm, down_write(¤t->mm->mmap_sem); realdatastart = do_mmap(0, 0, data_len + extra + MAX_SHARED_LIBS * sizeof(unsigned long), - PROT_READ|PROT_WRITE|PROT_EXEC, MAP_PRIVATE, 0); + PROT_READ|PROT_WRITE|PROT_EXEC, 0, 0); up_write(¤t->mm->mmap_sem); if (realdatastart == 0 || realdatastart >= (unsigned long)-4096) { @@ -574,7 +574,7 @@ static int load_flat_file(struct linux_binprm * bprm, down_write(¤t->mm->mmap_sem); textpos = do_mmap(0, 0, text_len + data_len + extra + MAX_SHARED_LIBS * sizeof(unsigned long), - PROT_READ | PROT_EXEC | PROT_WRITE, MAP_PRIVATE, 0); + PROT_READ | PROT_EXEC | PROT_WRITE, 0, 0); up_write(¤t->mm->mmap_sem); if (!textpos || textpos >= (unsigned long) -4096) { if (!textpos) diff --git a/trunk/fs/namei.c b/trunk/fs/namei.c index a7f7f44119b3..dd78f01b6de8 100644 --- a/trunk/fs/namei.c +++ b/trunk/fs/namei.c @@ -493,21 +493,12 @@ static inline int __vfs_follow_link(struct nameidata *nd, const char *link) return PTR_ERR(link); } -struct path { - struct vfsmount *mnt; - struct dentry *dentry; -}; - -static inline int __do_follow_link(struct path *path, struct nameidata *nd) +static inline int __do_follow_link(struct dentry *dentry, struct nameidata *nd) { int error; - struct dentry *dentry = path->dentry; - touch_atime(path->mnt, dentry); + touch_atime(nd->mnt, dentry); nd_set_link(nd, NULL); - - if (path->mnt == nd->mnt) - mntget(path->mnt); error = dentry->d_inode->i_op->follow_link(dentry, nd); if (!error) { char *s = nd_get_link(nd); @@ -516,8 +507,6 @@ static inline int __do_follow_link(struct path *path, struct nameidata *nd) if (dentry->d_inode->i_op->put_link) dentry->d_inode->i_op->put_link(dentry, nd); } - dput(dentry); - mntput(path->mnt); return error; } @@ -529,7 +518,7 @@ static inline int __do_follow_link(struct path *path, struct nameidata *nd) * Without that kind of total limit, nasty chains of consecutive * symlinks can cause almost arbitrarily long lookups. */ -static inline int do_follow_link(struct path *path, struct nameidata *nd) +static inline int do_follow_link(struct dentry *dentry, struct nameidata *nd) { int err = -ELOOP; if (current->link_count >= MAX_NESTED_LINKS) @@ -538,20 +527,17 @@ static inline int do_follow_link(struct path *path, struct nameidata *nd) goto loop; BUG_ON(nd->depth >= MAX_NESTED_LINKS); cond_resched(); - err = security_inode_follow_link(path->dentry, nd); + err = security_inode_follow_link(dentry, nd); if (err) goto loop; current->link_count++; current->total_link_count++; nd->depth++; - err = __do_follow_link(path, nd); + err = __do_follow_link(dentry, nd); current->link_count--; nd->depth--; return err; loop: - dput(path->dentry); - if (path->mnt != nd->mnt) - mntput(path->mnt); path_release(nd); return err; } @@ -579,91 +565,87 @@ int follow_up(struct vfsmount **mnt, struct dentry **dentry) /* no need for dcache_lock, as serialization is taken care in * namespace.c */ -static int __follow_mount(struct path *path) +static int follow_mount(struct vfsmount **mnt, struct dentry **dentry) { int res = 0; - while (d_mountpoint(path->dentry)) { - struct vfsmount *mounted = lookup_mnt(path->mnt, path->dentry); - if (!mounted) - break; - dput(path->dentry); - if (res) - mntput(path->mnt); - path->mnt = mounted; - path->dentry = dget(mounted->mnt_root); - res = 1; - } - return res; -} - -static void follow_mount(struct vfsmount **mnt, struct dentry **dentry) -{ while (d_mountpoint(*dentry)) { struct vfsmount *mounted = lookup_mnt(*mnt, *dentry); if (!mounted) break; - dput(*dentry); mntput(*mnt); *mnt = mounted; + dput(*dentry); *dentry = dget(mounted->mnt_root); + res = 1; } + return res; } /* no need for dcache_lock, as serialization is taken care in * namespace.c */ -int follow_down(struct vfsmount **mnt, struct dentry **dentry) +static inline int __follow_down(struct vfsmount **mnt, struct dentry **dentry) { struct vfsmount *mounted; mounted = lookup_mnt(*mnt, *dentry); if (mounted) { - dput(*dentry); mntput(*mnt); *mnt = mounted; + dput(*dentry); *dentry = dget(mounted->mnt_root); return 1; } return 0; } -static inline void follow_dotdot(struct nameidata *nd) +int follow_down(struct vfsmount **mnt, struct dentry **dentry) +{ + return __follow_down(mnt,dentry); +} + +static inline void follow_dotdot(struct vfsmount **mnt, struct dentry **dentry) { while(1) { struct vfsmount *parent; - struct dentry *old = nd->dentry; + struct dentry *old = *dentry; read_lock(¤t->fs->lock); - if (nd->dentry == current->fs->root && - nd->mnt == current->fs->rootmnt) { + if (*dentry == current->fs->root && + *mnt == current->fs->rootmnt) { read_unlock(¤t->fs->lock); break; } read_unlock(¤t->fs->lock); spin_lock(&dcache_lock); - if (nd->dentry != nd->mnt->mnt_root) { - nd->dentry = dget(nd->dentry->d_parent); + if (*dentry != (*mnt)->mnt_root) { + *dentry = dget((*dentry)->d_parent); spin_unlock(&dcache_lock); dput(old); break; } spin_unlock(&dcache_lock); spin_lock(&vfsmount_lock); - parent = nd->mnt->mnt_parent; - if (parent == nd->mnt) { + parent = (*mnt)->mnt_parent; + if (parent == *mnt) { spin_unlock(&vfsmount_lock); break; } mntget(parent); - nd->dentry = dget(nd->mnt->mnt_mountpoint); + *dentry = dget((*mnt)->mnt_mountpoint); spin_unlock(&vfsmount_lock); dput(old); - mntput(nd->mnt); - nd->mnt = parent; + mntput(*mnt); + *mnt = parent; } - follow_mount(&nd->mnt, &nd->dentry); + follow_mount(mnt, dentry); } +struct path { + struct vfsmount *mnt; + struct dentry *dentry; +}; + /* * It's more convoluted than I'd like it to be, but... it's still fairly * small and for now I'd prefer to have fast path as straight as possible. @@ -682,7 +664,6 @@ static int do_lookup(struct nameidata *nd, struct qstr *name, done: path->mnt = mnt; path->dentry = dentry; - __follow_mount(path); return 0; need_lookup: @@ -770,7 +751,7 @@ static fastcall int __link_path_walk(const char * name, struct nameidata *nd) case 2: if (this.name[1] != '.') break; - follow_dotdot(nd); + follow_dotdot(&nd->mnt, &nd->dentry); inode = nd->dentry->d_inode; /* fallthrough */ case 1: @@ -790,6 +771,8 @@ static fastcall int __link_path_walk(const char * name, struct nameidata *nd) err = do_lookup(nd, &this, &next); if (err) break; + /* Check mountpoints.. */ + follow_mount(&next.mnt, &next.dentry); err = -ENOENT; inode = next.dentry->d_inode; @@ -800,7 +783,10 @@ static fastcall int __link_path_walk(const char * name, struct nameidata *nd) goto out_dput; if (inode->i_op->follow_link) { - err = do_follow_link(&next, nd); + mntget(next.mnt); + err = do_follow_link(next.dentry, nd); + dput(next.dentry); + mntput(next.mnt); if (err) goto return_err; err = -ENOENT; @@ -812,8 +798,6 @@ static fastcall int __link_path_walk(const char * name, struct nameidata *nd) break; } else { dput(nd->dentry); - if (nd->mnt != next.mnt) - mntput(nd->mnt); nd->mnt = next.mnt; nd->dentry = next.dentry; } @@ -835,7 +819,7 @@ static fastcall int __link_path_walk(const char * name, struct nameidata *nd) case 2: if (this.name[1] != '.') break; - follow_dotdot(nd); + follow_dotdot(&nd->mnt, &nd->dentry); inode = nd->dentry->d_inode; /* fallthrough */ case 1: @@ -849,17 +833,19 @@ static fastcall int __link_path_walk(const char * name, struct nameidata *nd) err = do_lookup(nd, &this, &next); if (err) break; + follow_mount(&next.mnt, &next.dentry); inode = next.dentry->d_inode; if ((lookup_flags & LOOKUP_FOLLOW) && inode && inode->i_op && inode->i_op->follow_link) { - err = do_follow_link(&next, nd); + mntget(next.mnt); + err = do_follow_link(next.dentry, nd); + dput(next.dentry); + mntput(next.mnt); if (err) goto return_err; inode = nd->dentry->d_inode; } else { dput(nd->dentry); - if (nd->mnt != next.mnt) - mntput(nd->mnt); nd->mnt = next.mnt; nd->dentry = next.dentry; } @@ -899,8 +885,6 @@ static fastcall int __link_path_walk(const char * name, struct nameidata *nd) return 0; out_dput: dput(next.dentry); - if (nd->mnt != next.mnt) - mntput(next.mnt); break; } path_release(nd); @@ -1414,7 +1398,7 @@ int may_open(struct nameidata *nd, int acc_mode, int flag) int open_namei(const char * pathname, int flag, int mode, struct nameidata *nd) { int acc_mode, error = 0; - struct path path; + struct dentry *dentry; struct dentry *dir; int count = 0; @@ -1458,24 +1442,23 @@ int open_namei(const char * pathname, int flag, int mode, struct nameidata *nd) dir = nd->dentry; nd->flags &= ~LOOKUP_PARENT; down(&dir->d_inode->i_sem); - path.dentry = __lookup_hash(&nd->last, nd->dentry, nd); - path.mnt = nd->mnt; + dentry = __lookup_hash(&nd->last, nd->dentry, nd); do_last: - error = PTR_ERR(path.dentry); - if (IS_ERR(path.dentry)) { + error = PTR_ERR(dentry); + if (IS_ERR(dentry)) { up(&dir->d_inode->i_sem); goto exit; } /* Negative dentry, just create the file */ - if (!path.dentry->d_inode) { + if (!dentry->d_inode) { if (!IS_POSIXACL(dir->d_inode)) mode &= ~current->fs->umask; - error = vfs_create(dir->d_inode, path.dentry, mode, nd); + error = vfs_create(dir->d_inode, dentry, mode, nd); up(&dir->d_inode->i_sem); dput(nd->dentry); - nd->dentry = path.dentry; + nd->dentry = dentry; if (error) goto exit; /* Don't check for write permission, don't truncate */ @@ -1493,24 +1476,22 @@ int open_namei(const char * pathname, int flag, int mode, struct nameidata *nd) if (flag & O_EXCL) goto exit_dput; - if (__follow_mount(&path)) { + if (d_mountpoint(dentry)) { error = -ELOOP; if (flag & O_NOFOLLOW) goto exit_dput; + while (__follow_down(&nd->mnt,&dentry) && d_mountpoint(dentry)); } error = -ENOENT; - if (!path.dentry->d_inode) + if (!dentry->d_inode) goto exit_dput; - if (path.dentry->d_inode->i_op && path.dentry->d_inode->i_op->follow_link) + if (dentry->d_inode->i_op && dentry->d_inode->i_op->follow_link) goto do_link; dput(nd->dentry); - nd->dentry = path.dentry; - if (nd->mnt != path.mnt) - mntput(nd->mnt); - nd->mnt = path.mnt; + nd->dentry = dentry; error = -EISDIR; - if (path.dentry->d_inode && S_ISDIR(path.dentry->d_inode->i_mode)) + if (dentry->d_inode && S_ISDIR(dentry->d_inode->i_mode)) goto exit; ok: error = may_open(nd, acc_mode, flag); @@ -1519,9 +1500,7 @@ int open_namei(const char * pathname, int flag, int mode, struct nameidata *nd) return 0; exit_dput: - dput(path.dentry); - if (nd->mnt != path.mnt) - mntput(path.mnt); + dput(dentry); exit: path_release(nd); return error; @@ -1541,15 +1520,18 @@ int open_namei(const char * pathname, int flag, int mode, struct nameidata *nd) * are done. Procfs-like symlinks just set LAST_BIND. */ nd->flags |= LOOKUP_PARENT; - error = security_inode_follow_link(path.dentry, nd); + error = security_inode_follow_link(dentry, nd); if (error) goto exit_dput; - error = __do_follow_link(&path, nd); + error = __do_follow_link(dentry, nd); + dput(dentry); if (error) return error; nd->flags &= ~LOOKUP_PARENT; - if (nd->last_type == LAST_BIND) + if (nd->last_type == LAST_BIND) { + dentry = nd->dentry; goto ok; + } error = -EISDIR; if (nd->last_type != LAST_NORM) goto exit; @@ -1564,8 +1546,7 @@ int open_namei(const char * pathname, int flag, int mode, struct nameidata *nd) } dir = nd->dentry; down(&dir->d_inode->i_sem); - path.dentry = __lookup_hash(&nd->last, nd->dentry, nd); - path.mnt = nd->mnt; + dentry = __lookup_hash(&nd->last, nd->dentry, nd); putname(nd->last.name); goto do_last; } diff --git a/trunk/include/asm-h8300/kmap_types.h b/trunk/include/asm-h8300/kmap_types.h index 1ec8a3427120..82431edeb2a1 100644 --- a/trunk/include/asm-h8300/kmap_types.h +++ b/trunk/include/asm-h8300/kmap_types.h @@ -1,5 +1,5 @@ -#ifndef _ASM_H8300_KMAP_TYPES_H -#define _ASM_H8300_KMAP_TYPES_H +#ifndef _ASM_KMAP_TYPES_H +#define _ASM_KMAP_TYPES_H enum km_type { KM_BOUNCE_READ, @@ -13,8 +13,6 @@ enum km_type { KM_PTE1, KM_IRQ0, KM_IRQ1, - KM_SOFTIRQ0, - KM_SOFTIRQ1, KM_TYPE_NR }; diff --git a/trunk/include/asm-h8300/mman.h b/trunk/include/asm-h8300/mman.h index 63f727a59850..abe08856c84f 100644 --- a/trunk/include/asm-h8300/mman.h +++ b/trunk/include/asm-h8300/mman.h @@ -4,7 +4,6 @@ #define PROT_READ 0x1 /* page can be read */ #define PROT_WRITE 0x2 /* page can be written */ #define PROT_EXEC 0x4 /* page can be executed */ -#define PROT_SEM 0x8 /* page may be used for atomic ops */ #define PROT_NONE 0x0 /* page can not be accessed */ #define PROT_GROWSDOWN 0x01000000 /* mprotect flag: extend change to start of growsdown vma */ #define PROT_GROWSUP 0x02000000 /* mprotect flag: extend change to end of growsup vma */ @@ -20,8 +19,6 @@ #define MAP_EXECUTABLE 0x1000 /* mark it as an executable */ #define MAP_LOCKED 0x2000 /* pages are locked */ #define MAP_NORESERVE 0x4000 /* don't check for reservations */ -#define MAP_POPULATE 0x8000 /* populate (prefault) pagetables */ -#define MAP_NONBLOCK 0x10000 /* do not block on IO */ #define MS_ASYNC 1 /* sync memory asynchronously */ #define MS_INVALIDATE 2 /* invalidate the caches */ diff --git a/trunk/mm/filemap.c b/trunk/mm/filemap.c index 4a2fee2cb62b..1d33fec7bac6 100644 --- a/trunk/mm/filemap.c +++ b/trunk/mm/filemap.c @@ -1968,7 +1968,6 @@ generic_file_buffered_write(struct kiocb *iocb, const struct iovec *iov, do { unsigned long index; unsigned long offset; - unsigned long maxlen; size_t copied; offset = (pos & (PAGE_CACHE_SIZE -1)); /* Within page */ @@ -1983,10 +1982,7 @@ generic_file_buffered_write(struct kiocb *iocb, const struct iovec *iov, * same page as we're writing to, without it being marked * up-to-date. */ - maxlen = cur_iov->iov_len - iov_base; - if (maxlen > bytes) - maxlen = bytes; - fault_in_pages_readable(buf, maxlen); + fault_in_pages_readable(buf, bytes); page = __grab_cache_page(mapping,index,&cached_page,&lru_pvec); if (!page) { @@ -2028,8 +2024,6 @@ generic_file_buffered_write(struct kiocb *iocb, const struct iovec *iov, filemap_set_next_iovec(&cur_iov, &iov_base, status); buf = cur_iov->iov_base + iov_base; - } else { - iov_base += status; } } } diff --git a/trunk/net/core/ethtool.c b/trunk/net/core/ethtool.c index 8ec484894d68..a3eeb88e1c81 100644 --- a/trunk/net/core/ethtool.c +++ b/trunk/net/core/ethtool.c @@ -356,7 +356,7 @@ static int ethtool_set_coalesce(struct net_device *dev, void __user *useraddr) { struct ethtool_coalesce coalesce; - if (!dev->ethtool_ops->get_coalesce) + if (!dev->ethtool_ops->set_coalesce) return -EOPNOTSUPP; if (copy_from_user(&coalesce, useraddr, sizeof(coalesce)))