Add the powerpc-specific sync() method to struct nvram_ops and implement
the corresponding ioctl in the nvram module. This allows the nvram module
to replace the generic_nvram module.

Signed-off-by: Finn Thain <fth...@telegraphics.com.au>

---

On PPC32, the IOC_NVRAM_SYNC ioctl call always returns 0, even for those
platforms that don't implement ppc_md.nvram_sync. This patch retains
that quirk. It might be better to return failure (which is what PPC64 does).

Changed since v1:
- Don't bother acquiring the mutex for unimplemented ioctls.

---
 arch/powerpc/include/asm/nvram.h |    3 ---
 arch/powerpc/kernel/setup_32.c   |    6 +++---
 drivers/char/generic_nvram.c     |    2 +-
 drivers/char/nvram.c             |   39 +++++++++++++++++++++++++++++++++++++++
 include/linux/nvram.h            |    4 ++++
 5 files changed, 47 insertions(+), 7 deletions(-)

Index: linux/drivers/char/nvram.c
===================================================================
--- linux.orig/drivers/char/nvram.c     2015-07-25 17:45:37.000000000 +1000
+++ linux/drivers/char/nvram.c  2015-07-25 17:45:42.000000000 +1000
@@ -48,6 +48,11 @@
 #include <linux/mutex.h>
 
 
+#ifdef CONFIG_PPC
+#include <asm/nvram.h>
+#include <asm/machdep.h>
+#endif
+
 static DEFINE_MUTEX(nvram_mutex);
 static DEFINE_SPINLOCK(nvram_state_lock);
 static int nvram_open_cnt;     /* #times opened */
@@ -338,6 +343,37 @@ static long nvram_misc_ioctl(struct file
        long ret = -ENOTTY;
 
        switch (cmd) {
+#ifdef CONFIG_PPC
+#ifdef CONFIG_PPC_PMAC
+       case OBSOLETE_PMAC_NVRAM_GET_OFFSET:
+               pr_warn("nvram: Using obsolete PMAC_NVRAM_GET_OFFSET ioctl\n");
+               /* fall through */
+       case IOC_NVRAM_GET_OFFSET: {
+               int part, offset;
+
+               if (!machine_is(powermac))
+                       return -EINVAL;
+               if (copy_from_user(&part,
+                                  (void __user *)arg, sizeof(part)) != 0)
+                       return -EFAULT;
+               if (part < pmac_nvram_OF || part > pmac_nvram_NR)
+                       return -EINVAL;
+               offset = pmac_get_partition(part);
+               if (copy_to_user((void __user *)arg,
+                                &offset, sizeof(offset)) != 0)
+                       return -EFAULT;
+               ret = 0;
+               break;
+       }
+#endif
+       case IOC_NVRAM_SYNC:
+               if (arch_nvram_ops.sync != NULL) {
+                       mutex_lock(&nvram_mutex);
+                       ret = arch_nvram_ops.sync();
+                       mutex_unlock(&nvram_mutex);
+               }
+               break;
+#else /* !CONFIG_PPC */
        case NVRAM_INIT:
                /* initialize NVRAM contents and checksum */
                if (!capable(CAP_SYS_ADMIN))
@@ -361,6 +397,7 @@ static long nvram_misc_ioctl(struct file
                        mutex_unlock(&nvram_mutex);
                }
                break;
+#endif /* CONFIG_PPC */
        }
        return ret;
 }
@@ -376,6 +413,7 @@ static int nvram_misc_open(struct inode
                return -EBUSY;
        }
 
+#ifndef CONFIG_PPC
        /* Prevent multiple writers if the set_checksum ioctl is implemented. */
        if ((arch_nvram_ops.set_checksum != NULL) &&
            (file->f_mode & FMODE_WRITE) &&
@@ -383,6 +421,7 @@ static int nvram_misc_open(struct inode
                spin_unlock(&nvram_state_lock);
                return -EBUSY;
        }
+#endif
 
        if (file->f_flags & O_EXCL)
                nvram_open_mode |= NVRAM_EXCL;
Index: linux/include/linux/nvram.h
===================================================================
--- linux.orig/include/linux/nvram.h    2015-07-25 17:45:33.000000000 +1000
+++ linux/include/linux/nvram.h 2015-07-25 17:45:42.000000000 +1000
@@ -17,8 +17,12 @@ struct nvram_ops {
        unsigned char   (*read_byte)(int);
        void            (*write_byte)(unsigned char, int);
        ssize_t         (*get_size)(void);
+#ifdef CONFIG_PPC
+       long            (*sync)(void);
+#else
        long            (*set_checksum)(void);
        long            (*initialize)(void);
+#endif
 };
 
 extern const struct nvram_ops arch_nvram_ops;
Index: linux/arch/powerpc/include/asm/nvram.h
===================================================================
--- linux.orig/arch/powerpc/include/asm/nvram.h 2015-07-25 17:45:41.000000000 
+1000
+++ linux/arch/powerpc/include/asm/nvram.h      2015-07-25 17:45:42.000000000 
+1000
@@ -78,9 +78,6 @@ extern int    pmac_get_partition(int partit
 extern u8      pmac_xpram_read(int xpaddr);
 extern void    pmac_xpram_write(int xpaddr, u8 data);
 
-/* Synchronize NVRAM */
-extern void    nvram_sync(void);
-
 /* Initialize NVRAM OS partition */
 extern int __init nvram_init_os_partition(struct nvram_os_partition *part);
 
Index: linux/arch/powerpc/kernel/setup_32.c
===================================================================
--- linux.orig/arch/powerpc/kernel/setup_32.c   2015-07-25 17:45:41.000000000 
+1000
+++ linux/arch/powerpc/kernel/setup_32.c        2015-07-25 17:45:42.000000000 
+1000
@@ -170,7 +170,6 @@ __setup("l3cr=", ppc_setup_l3cr);
 
 #ifdef CONFIG_GENERIC_NVRAM
 
-/* Generic nvram hooks used by drivers/char/gen_nvram.c */
 unsigned char nvram_read_byte(int addr)
 {
        if (ppc_md.nvram_read_val)
@@ -193,15 +192,16 @@ static ssize_t ppc_nvram_get_size(void)
        return -ENODEV;
 }
 
-void nvram_sync(void)
+static long ppc_nvram_sync(void)
 {
        if (ppc_md.nvram_sync)
                ppc_md.nvram_sync();
+       return 0;
 }
-EXPORT_SYMBOL(nvram_sync);
 
 const struct nvram_ops arch_nvram_ops = {
        .get_size       = ppc_nvram_get_size,
+       .sync           = ppc_nvram_sync,
 };
 EXPORT_SYMBOL(arch_nvram_ops);
 
Index: linux/drivers/char/generic_nvram.c
===================================================================
--- linux.orig/drivers/char/generic_nvram.c     2015-07-25 17:45:41.000000000 
+1000
+++ linux/drivers/char/generic_nvram.c  2015-07-25 17:45:42.000000000 +1000
@@ -111,7 +111,7 @@ static int nvram_ioctl(struct file *file
        }
 #endif /* CONFIG_PPC_PMAC */
        case IOC_NVRAM_SYNC:
-               nvram_sync();
+               arch_nvram_ops.sync();
                break;
        default:
                return -EINVAL;


_______________________________________________
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev

Reply via email to