On Mon, 31 Dec 2018, Arnd Bergmann wrote: > On Sun, Dec 30, 2018 at 8:25 AM Finn Thain <fth...@telegraphics.com.au> wrote: > > > > On Sat, 29 Dec 2018, Arnd Bergmann wrote: > > > > > > --- a/drivers/char/nvram.c > > > > +++ b/drivers/char/nvram.c > > > > @@ -48,6 +48,10 @@ > > > > #include <linux/mutex.h> > > > > #include <linux/pagemap.h> > > > > > > > > +#ifdef CONFIG_PPC > > > > +#include <asm/nvram.h> > > > > +#include <asm/machdep.h> > > > > +#endif > > > > > > > > static DEFINE_MUTEX(nvram_mutex); > > > > static DEFINE_SPINLOCK(nvram_state_lock); > > > > @@ -331,6 +335,37 @@ static long nvram_misc_ioctl(struct file *file, > > > > unsigned int cmd, > > > > long ret = -ENOTTY; > > > > > > > > switch (cmd) { > > > > +#ifdef CONFIG_PPC > > > > + case OBSOLETE_PMAC_NVRAM_GET_OFFSET: > > > > + pr_warn("nvram: Using obsolete PMAC_NVRAM_GET_OFFSET > > > > ioctl\n"); > > > > + /* fall through */ > > > > + case IOC_NVRAM_GET_OFFSET: > > > > + ret = -EINVAL; > > > > +#ifdef CONFIG_PPC_PMAC > > > > > > I think it would make be nicer here to keep the ppc bits in arch/ppc, > > > and instead add a .ioctl() callback to nvram_ops. > > > > > > > The problem with having an nvram_ops.ioctl() method is the code in the > > !PPC branch. That code would get duplicated because it's needed by > > both X86 and M68K, to implement the checksum ioctls. > > I was thinking you'd just have a common ioctl function that falls back > to the .ioctl callback for any unhandled commands like > > switch (cmd) { > case NVRAM_INIT: > ... > break; > case ...: > break; > default: > if (ops->ioctl) > return ops->ioctl(...); > return -EINVAL; > } > > Would that work? >
There are no ioctls common to all architectures. So your example becomes, static long nvram_misc_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { if (ops->ioctl) return ops->ioctl(file, cmd, arg); return -ENOTTY; } And then my objection is the same: m68k and x86 now have to duplicate their common ops->ioctl() implementation. Here's a compromise that avoids some code duplication. switch (cmd) { #if defined(CONFIG_X86) || defined(CONFIG_M68K) case NVRAM_INIT: ... break; case NVRAM_SETCKS: ... break; #endif default: if (ops->ioctl) return ops->ioctl(...); return -EINVAL; } But PPC64 and PPC32 also need to share their ops->ioctl() implementation. It's not clear to me where that code would go. Personally, I prefer the present patch series, or something similar, with it's symmetry between nvram.c and nvram.h: static long nvram_misc_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { long ret = -ENOTTY; switch (cmd) { #if defined(CONFIG_PPC) case OBSOLETE_PMAC_NVRAM_GET_OFFSET: ... case IOC_NVRAM_GET_OFFSET: ... break; case IOC_NVRAM_SYNC: ... break; #elif defined(CONFIG_X86) || defined(CONFIG_M68K) case NVRAM_INIT: ... break; case NVRAM_SETCKS: ... break; #endif } return ret; } ... versus the struct definition in nvram.h, struct nvram_ops { ssize_t (*read)(char *, size_t, loff_t *); ssize_t (*write)(char *, size_t, loff_t *); unsigned char (*read_byte)(int); void (*write_byte)(unsigned char, int); ssize_t (*get_size)(void); #if defined(CONFIG_PPC) long (*sync)(void); int (*get_partition)(int); #elif defined(CONFIG_X86) || defined(CONFIG_M68K) long (*set_checksum)(void); long (*initialize)(void); #endif }; Which of these alternatives do you prefer? Is there a better way? -- > Arnd >