Re-use nvram module
Subsystems (10)
v9 cover Re-use nvram module
The "generic" NVRAM module, drivers/char/generic_nvram.c, implements a /dev/nvram misc device. This module is used only by 32-bit PowerPC platforms.
The RTC "CMOS" NVRAM module, drivers/char/nvram.c, also implements a /dev/nvram misc device. This module is now used only by x86 and m68k thanks to commit 3ba9faedc180 ("char: nvram: disable on ARM").
The "generic" module cannot be used by x86 or m68k platforms because it cannot co-exist with the "CMOS" module. One reason for that is the CONFIG_GENERIC_NVRAM kludge in drivers/char/Makefile. Another reason is that automatically loading the appropriate module would be impossible because only one module can provide the char-major-10-144 alias.
A multi-platform kernel binary needs a single, generic module. With this patch series, drivers/char/nvram.c becomes more generic and some of the arch-specific code gets moved under arch/. The nvram module is then usable by all m68k, powerpc and x86 platforms.
This allows for removal of drivers/char/generic_nvram.c as well as a duplicate in arch/powerpc/kernel/nvram_64.c. By reducing the number of /dev/nvram char misc device implementations, the number of bugs and inconsistencies is also reduced.
This approach reduces inconsistencies between PPC32 and PPC64 and also between PPC_PMAC and MAC. A uniform API has benefits for userspace.
For example, some error codes for some ioctl calls become consistent across PowerPC platforms. The uniform API can potentially benefit any bootloader that works across the various platforms having XPRAM (e.g. Emile).
This patch series was tested on Atari, Mac, PowerMac (both 32-bit and 64-bit) and ThinkPad hardware. AFAIK, it has not yet been tested on pSeries or CHRP.
I think there are two possible merge strategies for this patch series. The char misc maintainer could take the entire series. Alternatively, the m68k maintainer could take patches 1 thru 16 (though some of these have nothing to do with m68k) and after those patches reach mainline the powerpc maintainer could take 17 thru 22.
Changed since v8:
- Replaced defined(CONFIG_NVRAM) with IS_REACHABLE(CONFIG_NVRAM) as
suggested by James Bottomley.
- Changed #ifdef to if as suggested by Christophe Leroy.
- Expanded the fbdev patch to include controlfb.c and platinumfb.c.
- Added kernel-doc comment to describe struct nvram_ops.
- Moved the HAVE_ARCH_NVRAM_OPS symbol to common code as suggested
by Christoph Hellwig.
- Abandoned conversion of powerpc drivers to arch_nvram_ops, as discussed
with Arnd Bergmann.
- Dropped patch 6 ("x86/thinkpad_acpi: Use arch_nvram_ops methods").
- Dropped patch 17 ("powerpc: Implement arch_nvram_ops.get_size() ...").
- Dropped patch 20 ("powerpc, fbdev: Use arch_nvram_ops methods ...").
- Dropped patch 25 ("powerpc: Remove pmac_xpram_{read,write} functions").
- Added portable static functions to nvram.h which wrap both arch_nvram_ops
and ppc_md method calls.
- Re-ordered and revised patches to resolve conflicts with existing extern
definitions in nvram.h and elsewhere.
- Rebased on v5.0-rc2.
- Added patch 14 ("macintosh/via-cuda: Don't rely on Cuda to end a transfer").
Changed since v7:
- Rebased.
- Dropped patch 9/26, "char/nvram: Use generic fixed_size_llseek()"
because generic_file_llseek_size() was adopted in commit b808b1d632f6.
- Reordered the m68k and powerpc patches to simplify the merge strategy.
- Addressed some trivial checkpatch.pl complaints.
- Improved some commit log entries.
- Changed the CONFIG_NVRAM default to better approximate the present code.
In particular, the CONFIG_GENERIC_NVRAM default and use of "select NVRAM".
- Added more tested-by tags.
For older change logs, please refer to,
https://lore.kernel.org/lkml/[email protected]/
Finn Thain (22):
scsi/atari_scsi: Don't select CONFIG_NVRAM
m68k/atari: Move Atari-specific code out of drivers/char/nvram.c char/nvram: Re-order functions to remove forward declarations and
#ifdefs
nvram: Replace nvram_* function exports with static functions
m68k/atari: Implement arch_nvram_ops struct
powerpc: Replace nvram_* extern declarations with standard header
char/nvram: Adopt arch_nvram_ops
char/nvram: Allow the set_checksum and initialize ioctls to be omitted
char/nvram: Implement NVRAM read/write methods
m68k/atari: Implement arch_nvram_ops methods and enable
CONFIG_HAVE_ARCH_NVRAM_OPS
m68k/mac: Adopt naming and calling conventions for PRAM routines
m68k/mac: Use macros for RTC accesses not magic numbers
m68k/mac: Fix PRAM accessors
macintosh/via-cuda: Don't rely on Cuda to end a transfer
m68k: Dispatch nvram_ops calls to Atari or Mac functions
char/nvram: Add "devname:nvram" module alias
powerpc: Define missing ppc_md.nvram_size for CHRP and PowerMac
powerpc: Implement nvram ioctls
powerpc, fbdev: Use NV_CMODE and NV_VMODE only when CONFIG_PPC32 &&
CONFIG_PPC_PMAC && CONFIG_NVRAM powerpc: Enable HAVE_ARCH_NVRAM_OPS and disable GENERIC_NVRAM char/generic_nvram: Remove as unused
powerpc: Adopt nvram module for PPC64
arch/Kconfig | 3 + arch/m68k/Kconfig.machine | 2 + arch/m68k/atari/Makefile | 2 + arch/m68k/atari/nvram.c | 272 +++++++++ arch/m68k/include/asm/atarihw.h | 6 + arch/m68k/include/asm/macintosh.h | 4 + arch/m68k/kernel/setup_mm.c | 82 ++- arch/m68k/mac/misc.c | 174 ++++-- arch/powerpc/Kconfig | 6 +- arch/powerpc/include/asm/nvram.h | 9 - arch/powerpc/kernel/nvram_64.c | 158 +---- arch/powerpc/kernel/setup_32.c | 36 +- arch/powerpc/platforms/chrp/Makefile | 2 +- arch/powerpc/platforms/chrp/nvram.c | 14 +- arch/powerpc/platforms/chrp/setup.c | 2 +- arch/powerpc/platforms/powermac/Makefile | 2 - arch/powerpc/platforms/powermac/nvram.c | 9 + arch/powerpc/platforms/powermac/setup.c | 3 +- arch/powerpc/platforms/powermac/time.c | 2 +- arch/powerpc/platforms/pseries/nvram.c | 2 - drivers/char/Kconfig | 19 +- drivers/char/Makefile | 6 +- drivers/char/generic_nvram.c | 159 ----- drivers/char/nvram.c | 673 ++++++++------------- drivers/macintosh/via-cuda.c | 8 +- drivers/scsi/Kconfig | 6 +- drivers/scsi/atari_scsi.c | 10 +- drivers/video/fbdev/Kconfig | 2 +- drivers/video/fbdev/controlfb.c | 42 +- drivers/video/fbdev/imsttfb.c | 23 +- drivers/video/fbdev/matrox/matroxfb_base.c | 7 +- drivers/video/fbdev/platinumfb.c | 21 +- drivers/video/fbdev/valkyriefb.c | 30 +- include/linux/nvram.h | 133 +++- include/uapi/linux/pmu.h | 2 + 35 files changed, 966 insertions(+), 965 deletions(-) create mode 100644 arch/m68k/atari/nvram.c delete mode 100644 drivers/char/generic_nvram.c
Signature · 1 line
2.19.2
PATCH v9 1/22 scsi/atari_scsi: Don't select CONFIG_NVRAM
On powerpc, setting CONFIG_NVRAM=n builds a kernel with no NVRAM support. Setting CONFIG_NVRAM=m enables the /dev/nvram misc device module without enabling NVRAM support in drivers. Setting CONFIG_NVRAM=y enables the misc device (built-in) and also enables NVRAM support in drivers.
m68k shares the valkyriefb driver with powerpc, and since that driver uses NVRAM, it is affected by CONFIG_ATARI_SCSI, because of the use of "select NVRAM". We can avoid the "select" here, but drivers still have to interpret the CONFIG_NVRAM symbol consistently regardless of platform.
In this patch and the subsequent fbdev driver patch, the convention is adopted across all relevant platforms whereby NVRAM functionality gets enabled in a given device driver when the nvram misc device is built-in or when both drivers are modules.
---
This patch temporarily disables CONFIG_NVRAM on Atari, to prevent build failures when bisecting the rest of this patch series. It gets enabled again with the introduction of CONFIG_HAVE_ARCH_NVRAM_OPS, once the nvram_* global functions have been moved to an ops struct.
Changed since v8:
- Replaced defined(CONFIG_NVRAM) with IS_REACHABLE(CONFIG_NVRAM) as
suggested by James Bottomley.
- Changed #ifdef to if as suggested by Christophe Leroy.
--- drivers/char/Kconfig | 5 +---- drivers/scsi/Kconfig | 6 +++--- drivers/scsi/atari_scsi.c | 2 +- 3 files changed, 5 insertions(+), 8 deletions(-)
drivers/char/Kconfig +1 -4
@@ -244,7 +244,7 @@ source "drivers/char/hw_random/Kconfig" config NVRAM tristate "/dev/nvram support" - depends on ATARI || X86 || GENERIC_NVRAM + depends on X86 || GENERIC_NVRAM ---help--- If you say Y here and create a character special file /dev/nvram with major number 10 and minor number 144 using mknod ("man mknod"),
@@ -262,9 +262,6 @@ config NVRAM should NEVER idly tamper with it. See Ralf Brown's interrupt list for a guide to the use of CMOS bytes by your BIOS. - On Atari machines, /dev/nvram is always configured and does not need - to be selected. - To compile this driver as a module, choose M here: the module will be called nvram.
drivers/scsi/Kconfig +3 -3
@@ -1369,14 +1369,14 @@ config ATARI_SCSI tristate "Atari native SCSI support" depends on ATARI && SCSI select SCSI_SPI_ATTRS - select NVRAM ---help--- If you have an Atari with built-in NCR5380 SCSI controller (TT, Falcon, ...) say Y to get it supported. Of course also, if you have a compatible SCSI controller (e.g. for Medusa). - To compile this driver as a module, choose M here: the - module will be called atari_scsi. + To compile this driver as a module, choose M here: the module will + be called atari_scsi. If you also enable NVRAM support, the SCSI + host's ID is taken from the setting in TT RTC NVRAM. This driver supports both styles of NCR integration into the system: the TT style (separate DMA), and the Falcon style (via
drivers/scsi/atari_scsi.c +1 -1
@@ -757,7 +757,7 @@ static int __init atari_scsi_probe(struct platform_device *pdev)if (setup_hostid >=0 ) { atari_scsi_template.this_id = setup_hostid &7 ; - }else { + }else if (IS_REACHABLE (CONFIG_NVRAM )) {/* Test if a host id is set in the NVRam */ if (ATARIHW_PRESENT (TT_CLK ) &&nvram_check_checksum ()) {unsigned char b =nvram_read_byte (16 );
Signature · 1 line
2.19.2
PATCH v9 2/22 m68k/atari: Move Atari-specific code out of drivers/char/nvram.c
In reply to Finn ThainMove the m68k-specific code out of the driver to make the driver generic.
I've used 'SPDX-License-Identifier: GPL-2.0+' for the new file because the old file is covered by MODULE_LICENSE("GPL").
---
Changed since v8:
- Fixed an old bug by adding a missing new line character.
Changed since v7:
- Added SPDX-License-Identifier.
--- arch/m68k/atari/Makefile | 2 + arch/m68k/atari/nvram.c | 243 +++++++++++++++++++++++++++++++++ drivers/char/nvram.c | 280 +++++---------------------------------- 3 files changed, 280 insertions(+), 245 deletions(-) create mode 100644 arch/m68k/atari/nvram.c
arch/m68k/atari/Makefile +2 -0
@@ -6,3 +6,5 @@ obj-y := config.o time.o debug.o ataints.o stdma.o \ atasound.o stram.o obj-$(CONFIG_ATARI_KBD_CORE) += atakeyb.o + +obj-$(CONFIG_NVRAM:m=y) += nvram.o
arch/m68k/atari/nvram.c new file +243 -0
243 lines not on this page · raw message
drivers/char/nvram.c +35 -245
350 lines not on this page · raw message
Signature · 1 line
2.19.2
PATCH v9 3/22 char/nvram: Re-order functions to remove forward declarations and #ifdefs
In reply to Finn ThainAlso give functions more sensible names: nvram_misc_* for misc device ops, nvram_proc_* for proc file ops and nvram_module_* for init and exit functions. This prevents name collisions with nvram.h helper functions and improves readability.
--- drivers/char/nvram.c | 167 +++++++++++++++++++------------------------ 1 file changed, 72 insertions(+), 95 deletions(-)
drivers/char/nvram.c +72 -95
@@ -55,11 +55,6 @@ static int nvram_open_mode; /* special open modes */#define NVRAM_WRITE 1/* opened for writing (exclusive) */ #define NVRAM_EXCL 2/* opened with O_EXCL */ -#ifdef CONFIG_PROC_FS -static void pc_nvram_proc_read (unsigned char *contents,struct seq_file *seq, -void *offset); -#endif -/* * These functions are provided to be called internally or by other parts of * the kernel. It's up to the caller to ensure correct checksum before reading
@@ -171,14 +166,14 @@ void nvram_set_checksum(void)* The are the file operation function for user access to /dev/nvram */ -static loff_t nvram_llseek (struct file *file,loff_t offset,int origin) +static loff_t nvram_misc_llseek (struct file *file,loff_t offset,int origin) {return generic_file_llseek_size (file, offset, origin,MAX_LFS_FILESIZE ,NVRAM_BYTES ); } -static ssize_t nvram_read (struct file *file,char __user *buf, -size_t count,loff_t *ppos) +static ssize_t nvram_misc_read (struct file *file,char __user *buf, +size_t count,loff_t *ppos) {unsigned char contents[NVRAM_BYTES ];unsigned i = *ppos;
@@ -206,8 +201,8 @@ static ssize_t nvram_read(struct file *file, char __user *buf,return -EIO ; } -static ssize_t nvram_write (struct file *file,const char __user *buf, -size_t count,loff_t *ppos) +static ssize_t nvram_misc_write (struct file *file,const char __user *buf, +size_t count,loff_t *ppos) {unsigned char contents[NVRAM_BYTES ];unsigned i = *ppos;
@@ -245,8 +240,8 @@ static ssize_t nvram_write(struct file *file, const char __user *buf,return -EIO ; } -static long nvram_ioctl (struct file *file,unsigned int cmd, -unsigned long arg) +static long nvram_misc_ioctl (struct file *file,unsigned int cmd, +unsigned long arg) {int i;
@@ -286,7 +281,7 @@ static long nvram_ioctl(struct file *file, unsigned int cmd, } } -static int nvram_open (struct inode *inode,struct file *file) +static int nvram_misc_open (struct inode *inode,struct file *file) {spin_lock (&nvram_state_lock);
@@ -308,7 +303,7 @@ static int nvram_open(struct inode *inode, struct file *file)return 0 ; } -static int nvram_release (struct inode *inode,struct file *file) +static int nvram_misc_release (struct inode *inode,struct file *file) {spin_lock (&nvram_state_lock);
@@ -325,87 +320,6 @@ static int nvram_release(struct inode *inode, struct file *file)return 0 ; } -#ifndef CONFIG_PROC_FS -static int nvram_add_proc_fs (void ) -{ -return 0 ; -} - -#else - -static int nvram_proc_read (struct seq_file *seq,void *offset) -{ -unsigned char contents[NVRAM_BYTES ]; -int i =0 ; - -spin_lock_irq (&rtc_lock); -for (i =0 ; i <NVRAM_BYTES ; ++i) - contents[i] =__nvram_read_byte (i); -spin_unlock_irq (&rtc_lock); - -pc_nvram_proc_read (contents, seq, offset); - -return 0 ; -} - -static int nvram_add_proc_fs (void ) -{ -if (!proc_create_single ("driver/nvram" ,0 ,NULL , nvram_proc_read)) -return -ENOMEM ; -return 0 ; -} - -#endif /* CONFIG_PROC_FS */ - -static const struct file_operations nvram_fops = { - .owner =THIS_MODULE , - .llseek = nvram_llseek, - .read = nvram_read, - .write = nvram_write, - .unlocked_ioctl = nvram_ioctl, - .open = nvram_open, - .release = nvram_release, -}; - -static struct miscdevice nvram_dev = { -NVRAM_MINOR , -"nvram" , - &nvram_fops -}; - -static int __init nvram_init (void ) -{ -int ret; - - ret =misc_register (&nvram_dev); -if (ret) { -printk (KERN_ERR "nvram: can't misc_register on minor=%d\n" , -NVRAM_MINOR ); - goto out; - } - ret =nvram_add_proc_fs (); -if (ret) { -printk (KERN_ERR "nvram: can't create /proc/driver/nvram\n" ); - goto outmisc; - } - ret =0 ; -printk (KERN_INFO "Non-volatile memory driver v" NVRAM_VERSION "\n" ); -out: -return ret; -outmisc: -misc_deregister (&nvram_dev); - goto out; -} - -static void __exit nvram_cleanup_module(void) -{ -remove_proc_entry ("driver/nvram" ,NULL ); -misc_deregister (&nvram_dev); -} - -module_init (nvram_init); -module_exit (nvram_cleanup_module); -#ifdef CONFIG_PROC_FS static const char * const floppy_types[] = {
@@ -483,7 +397,70 @@ static void pc_nvram_proc_read(unsigned char *nvram, struct seq_file *seq,return ; } +static int nvram_proc_read (struct seq_file *seq,void *offset) +{ +unsigned char contents[NVRAM_BYTES ]; +int i =0 ; + +spin_lock_irq (&rtc_lock); +for (i =0 ; i <NVRAM_BYTES ; ++i) + contents[i] =__nvram_read_byte (i); +spin_unlock_irq (&rtc_lock); + +pc_nvram_proc_read (contents, seq, offset); + +return 0 ; +}#endif /* CONFIG_PROC_FS */ +static const struct file_operations nvram_misc_fops = { + .owner =THIS_MODULE , + .llseek = nvram_misc_llseek, + .read = nvram_misc_read, + .write = nvram_misc_write, + .unlocked_ioctl = nvram_misc_ioctl, + .open = nvram_misc_open, + .release = nvram_misc_release, +}; + +static struct miscdevice nvram_misc = { +NVRAM_MINOR , +"nvram" , + &nvram_misc_fops, +}; + +static int __init nvram_module_init (void ) +{ +int ret; + + ret =misc_register (&nvram_misc); +if (ret) { +pr_err ("nvram: can't misc_register on minor=%d\n" ,NVRAM_MINOR ); +return ret; + } + +#ifdef CONFIG_PROC_FS +if (!proc_create_single ("driver/nvram" ,0 ,NULL , nvram_proc_read)) { +pr_err ("nvram: can't create /proc/driver/nvram\n" ); +misc_deregister (&nvram_misc); +return -ENOMEM ; + } +#endif + +pr_info ("Non-volatile memory driver v" NVRAM_VERSION "\n" ); +return 0 ; +} + +static void __exit nvram_module_exit(void) +{ +#ifdef CONFIG_PROC_FS +remove_proc_entry ("driver/nvram" ,NULL ); +#endif +misc_deregister (&nvram_misc); +} + +module_init (nvram_module_init); +module_exit (nvram_module_exit); +MODULE_LICENSE ("GPL" );MODULE_ALIAS_MISCDEV (NVRAM_MINOR );
Signature · 1 line
2.19.2
PATCH v9 4/22 nvram: Replace nvram_* function exports with static functions
In reply to Finn ThainReplace nvram_* functions with static functions in nvram.h. These will become wrappers for struct nvram_ops method calls.
This patch effectively disables existing NVRAM functionality so as to allow the rest of the series to be bisected without build failures. That functionality is gradually re-implemented in subsequent patches.
Replace the sole validate-checksum-and-read-byte sequence with a call to nvram_read() which will gain the same semantics in subsequent patches.
Remove unused exports.
--- arch/m68k/atari/nvram.c | 39 +++------------------------------------ drivers/char/nvram.c | 27 +++++---------------------- drivers/scsi/atari_scsi.c | 8 +++++--- include/linux/nvram.h | 32 +++++++++++++++++++++++++------- 4 files changed, 38 insertions(+), 68 deletions(-)
arch/m68k/atari/nvram.c +3 -36
@@ -34,38 +34,17 @@* periodic 11 min sync from kernel/time/ntp.c vs. this driver.) */ -unsigned char __nvram_read_byte (int i) +static unsigned char __nvram_read_byte (int i) {return CMOS_READ (NVRAM_FIRST_BYTE + i); } -unsigned char nvram_read_byte (int i) -{ -unsigned long flags; -unsigned char c; - -spin_lock_irqsave (&rtc_lock, flags); - c =__nvram_read_byte (i); -spin_unlock_irqrestore (&rtc_lock, flags); -return c; -} -EXPORT_SYMBOL (nvram_read_byte); -/* This races nicely with trying to read with checksum checking */ -void __nvram_write_byte (unsigned char c,int i) +static void __nvram_write_byte (unsigned char c,int i) {CMOS_WRITE (c,NVRAM_FIRST_BYTE + i); } -void nvram_write_byte (unsigned char c,int i) -{ -unsigned long flags; - -spin_lock_irqsave (&rtc_lock, flags); -__nvram_write_byte (c, i); -spin_unlock_irqrestore (&rtc_lock, flags); -} -/* On Ataris, the checksum is over all bytes except the checksum bytes * themselves; these are at the very end. */
@@ -73,7 +52,7 @@ void nvram_write_byte(unsigned char c, int i)#define ATARI_CKS_RANGE_END 47#define ATARI_CKS_LOC 48 -int __nvram_check_checksum (void ) +static int __nvram_check_checksum (void ) {int i;unsigned char sum =0 ;
@@ -84,18 +63,6 @@ int __nvram_check_checksum(void) (__nvram_read_byte (ATARI_CKS_LOC +1 ) == (sum &0xff )); } -int nvram_check_checksum (void ) -{ -unsigned long flags; -int rv; - -spin_lock_irqsave (&rtc_lock, flags); - rv =__nvram_check_checksum (); -spin_unlock_irqrestore (&rtc_lock, flags); -return rv; -} -EXPORT_SYMBOL (nvram_check_checksum); -static void __nvram_set_checksum (void ) {int i;
drivers/char/nvram.c +5 -22
@@ -74,13 +74,12 @@ static int nvram_open_mode; /* special open modes */* periodic 11 min sync from kernel/time/ntp.c vs. this driver.) */ -unsigned char __nvram_read_byte (int i) +static unsigned char __nvram_read_byte (int i) {return CMOS_READ (NVRAM_FIRST_BYTE + i); } -EXPORT_SYMBOL (__nvram_read_byte); -unsigned char nvram_read_byte (int i) +static unsigned char pc_nvram_read_byte (int i) {unsigned long flags;unsigned char c;
@@ -90,16 +89,14 @@ unsigned char nvram_read_byte(int i)spin_unlock_irqrestore (&rtc_lock, flags);return c; } -EXPORT_SYMBOL (nvram_read_byte);/* This races nicely with trying to read with checksum checking (nvram_read) */ -void __nvram_write_byte (unsigned char c,int i) +static void __nvram_write_byte (unsigned char c,int i) {CMOS_WRITE (c,NVRAM_FIRST_BYTE + i); } -EXPORT_SYMBOL (__nvram_write_byte); -void nvram_write_byte (unsigned char c,int i) +static void pc_nvram_write_byte (unsigned char c,int i) {unsigned long flags;
@@ -107,14 +104,13 @@ void nvram_write_byte(unsigned char c, int i)__nvram_write_byte (c, i);spin_unlock_irqrestore (&rtc_lock, flags); } -EXPORT_SYMBOL (nvram_write_byte);/* On PCs, the checksum is built only over bytes 2..31 */ #define PC_CKS_RANGE_START 2#define PC_CKS_RANGE_END 31#define PC_CKS_LOC 32 -int __nvram_check_checksum (void ) +static int __nvram_check_checksum (void ) {int i;unsigned short sum =0 ;
@@ -126,19 +122,6 @@ int __nvram_check_checksum(void)__nvram_read_byte (PC_CKS_LOC +1 );return (sum &0xffff ) == expect; } -EXPORT_SYMBOL (__nvram_check_checksum); - -int nvram_check_checksum (void ) -{ -unsigned long flags; -int rv; - -spin_lock_irqsave (&rtc_lock, flags); - rv =__nvram_check_checksum (); -spin_unlock_irqrestore (&rtc_lock, flags); -return rv; -} -EXPORT_SYMBOL (nvram_check_checksum);static void __nvram_set_checksum (void ) {
drivers/scsi/atari_scsi.c +5 -3
@@ -759,13 +759,15 @@ static int __init atari_scsi_probe(struct platform_device *pdev) atari_scsi_template.this_id = setup_hostid &7 ; }else if (IS_REACHABLE (CONFIG_NVRAM )) {/* Test if a host id is set in the NVRam */ -if (ATARIHW_PRESENT (TT_CLK ) &&nvram_check_checksum ()) { -unsigned char b =nvram_read_byte (16 ); +if (ATARIHW_PRESENT (TT_CLK )) { +unsigned char b; +loff_t offset =16 ; +ssize_t count =nvram_read (&b,1 , &offset);/* Arbitration enabled? (for TOS) * If yes, use configured host ID */ -if (b &0x80 ) +if ((count ==1 ) && (b &0x80 )) atari_scsi_template.this_id = b &7 ; } }
include/linux/nvram.h +25 -7
@@ -2,13 +2,31 @@#ifndef _LINUX_NVRAM_H#define _LINUX_NVRAM_H +#include <linux/errno.h> #include <uapi/linux/nvram.h> -/* __foo is foo without grabbing the rtc_lock - get it yourself */ -extern unsigned char __nvram_read_byte (int i); -extern unsigned char nvram_read_byte (int i); -extern void __nvram_write_byte (unsigned char c,int i); -extern void nvram_write_byte (unsigned char c,int i); -extern int __nvram_check_checksum (void ); -extern int nvram_check_checksum (void ); +static inline ssize_t nvram_get_size (void ) +{ +return -ENODEV ; +} + +static inline unsigned char nvram_read_byte (int addr) +{ +return 0xFF ; +} + +static inline void nvram_write_byte (unsigned char val,int addr) +{ +} + +static inline ssize_t nvram_read (char *buf,size_t count,loff_t *ppos) +{ +return -ENODEV ; +} + +static inline ssize_t nvram_write (char *buf,size_t count,loff_t *ppos) +{ +return -ENODEV ; +} +#endif /* _LINUX_NVRAM_H */
Signature · 1 line
2.19.2
PATCH v9 5/22 m68k/atari: Implement arch_nvram_ops struct
In reply to Finn ThainBy implementing an arch_nvram_ops struct, a platform can re-use the drivers/char/nvram.c module without needing any arch-specific code in that module. Atari does so here.
---
Changed since v8:
- Added static inline wrapper functions to nvram.h.
- Removed excess whitespace.
- Renamed functions to avoid collisions with nvram.h wrapper functions.
- Moved nvram_check_checksum() changes to the preceding patch.
--- arch/m68k/atari/nvram.c | 49 +++++++++++++++++++++++++++++++++++++++++ include/linux/nvram.h | 14 ++++++++++++ 2 files changed, 63 insertions(+)
arch/m68k/atari/nvram.c +49 -0
@@ -74,6 +74,55 @@ static void __nvram_set_checksum(void)__nvram_write_byte (sum,ATARI_CKS_LOC +1 ); } +static ssize_t atari_nvram_read (char *buf,size_t count,loff_t *ppos) +{ +char *p = buf; +loff_t i; + +spin_lock_irq (&rtc_lock); +if (!__nvram_check_checksum ()) { +spin_unlock_irq (&rtc_lock); +return -EIO ; + } +for (i = *ppos; count >0 && i <NVRAM_BYTES ; --count, ++i, ++p) + *p =__nvram_read_byte (i); +spin_unlock_irq (&rtc_lock); + + *ppos = i; +return p - buf; +} + +static ssize_t atari_nvram_write (char *buf,size_t count,loff_t *ppos) +{ +char *p = buf; +loff_t i; + +spin_lock_irq (&rtc_lock); +if (!__nvram_check_checksum ()) { +spin_unlock_irq (&rtc_lock); +return -EIO ; + } +for (i = *ppos; count >0 && i <NVRAM_BYTES ; --count, ++i, ++p) +__nvram_write_byte (*p, i); +__nvram_set_checksum (); +spin_unlock_irq (&rtc_lock); + + *ppos = i; +return p - buf; +} + +static ssize_t atari_nvram_get_size (void ) +{ +return NVRAM_BYTES ; +} + +const struct nvram_ops arch_nvram_ops = { + .read = atari_nvram_read, + .write = atari_nvram_write, + .get_size = atari_nvram_get_size, +}; +EXPORT_SYMBOL (arch_nvram_ops); + #ifdef CONFIG_PROC_FS static struct { unsigned char val;
include/linux/nvram.h +14 -0
@@ -5,8 +5,18 @@#include <linux/errno.h> #include <uapi/linux/nvram.h> +struct nvram_ops { +ssize_t (*get_size)(void ); +ssize_t (*read)(char *,size_t ,loff_t *); +ssize_t (*write)(char *,size_t ,loff_t *); +}; + +extern const struct nvram_ops arch_nvram_ops; +static inline ssize_t nvram_get_size (void ) { +if (arch_nvram_ops.get_size) +return arch_nvram_ops.get_size ();return -ENODEV ; }
@@ -21,11 +31,15 @@ static inline void nvram_write_byte(unsigned char val, int addr)static inline ssize_t nvram_read (char *buf,size_t count,loff_t *ppos) { +if (arch_nvram_ops.read) +return arch_nvram_ops.read (buf, count, ppos);return -ENODEV ; }static inline ssize_t nvram_write (char *buf,size_t count,loff_t *ppos) { +if (arch_nvram_ops.write) +return arch_nvram_ops.write (buf, count, ppos);return -ENODEV ; }
Signature · 1 line
2.19.2
PATCH v9 6/22 powerpc: Replace nvram_* extern declarations with standard header
In reply to Finn ThainRemove the nvram_read_byte() and nvram_write_byte() declarations in powerpc/include/asm/nvram.h and use the cross-platform static functions in linux/nvram.h instead.
---
Changed since v8:
- Added nvram_read_byte() and nvram_write_byte() functions to avoid a
potential build failure during 'git bisect'.
- Brought forward some powerpc cleanup to avoid naming collisions withnvram.h functions.
- Replaced the ppc_md.nvram_* method wrappers with the ones in nvram.h.
--- arch/powerpc/include/asm/nvram.h | 6 ------ arch/powerpc/kernel/setup_32.c | 25 +--------------------- drivers/char/generic_nvram.c | 1 + drivers/video/fbdev/matrox/matroxfb_base.c | 2 +- include/linux/nvram.h | 3 +++ 5 files changed, 6 insertions(+), 31 deletions(-)
arch/powerpc/include/asm/nvram.h +0 -6
@@ -98,10 +98,4 @@ extern int nvram_write_os_partition(struct nvram_os_partition *part,unsigned int err_type, unsigned int error_log_cnt); -/* Determine NVRAM size */ -extern ssize_t nvram_get_size (void ); - -/* Normal access to NVRAM */ -extern unsigned char nvram_read_byte (int i); -extern void nvram_write_byte (unsigned char c,int i);#endif /* _ASM_POWERPC_NVRAM_H */
arch/powerpc/kernel/setup_32.c +1 -24
@@ -17,6 +17,7 @@#include <linux/console.h> #include <linux/memblock.h> #include <linux/export.h> +#include <linux/nvram.h> #include <asm/io.h> #include <asm/prom.h>
@@ -149,30 +150,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) -return ppc_md.nvram_read_val (addr); -return 0xff ; -} -EXPORT_SYMBOL (nvram_read_byte); - -void nvram_write_byte (unsigned char val,int addr) -{ -if (ppc_md.nvram_write_val) - ppc_md.nvram_write_val (addr, val); -} -EXPORT_SYMBOL (nvram_write_byte); - -ssize_t nvram_get_size (void ) -{ -if (ppc_md.nvram_size) -return ppc_md.nvram_size (); -return -1 ; -} -EXPORT_SYMBOL (nvram_get_size); -void nvram_sync (void ) {if (ppc_md.nvram_sync)
drivers/char/generic_nvram.c +1 -0
@@ -20,6 +20,7 @@#include <linux/fcntl.h> #include <linux/init.h> #include <linux/mutex.h> +#include <linux/nvram.h> #include <linux/pagemap.h> #include <linux/uaccess.h> #include <asm/nvram.h>
drivers/video/fbdev/matrox/matroxfb_base.c +1 -1
@@ -111,12 +111,12 @@#include "matroxfb_g450.h" #include <linux/matroxfb.h> #include <linux/interrupt.h> +#include <linux/nvram.h> #include <linux/slab.h> #include <linux/uaccess.h> #ifdef CONFIG_PPC_PMAC #include <asm/machdep.h> -unsigned char nvram_read_byte (int );static int default_vmode =VMODE_NVRAM ;static int default_cmode =CMODE_NVRAM ;#endif
include/linux/nvram.h +3 -0
@@ -15,8 +15,11 @@ extern const struct nvram_ops arch_nvram_ops;static inline ssize_t nvram_get_size (void ) { +#ifdef CONFIG_PPC +#else if (arch_nvram_ops.get_size)return arch_nvram_ops.get_size (); +#endif return -ENODEV ; }
Signature · 1 line
2.19.2
PATCH v9 7/22 char/nvram: Adopt arch_nvram_ops
In reply to Finn ThainNVRAMs on different platforms and architectures have different attributes and access methods. E.g. some platforms have byte-at-a-time accessor functions while others have byte-range accessor functions. Some have checksum functionality while others do not. By calling ops struct methods via the common wrapper functions, the nvram module and other drivers can make use of the available NVRAM functionality in a portable way.
---
It might be nice if the NVRAM Kconfig symbol depended only on HAVE_ARCH_NVRAM_OPS and all the x86 code here were moved to arch/x86. This driver would then be more "generic". However, that x86 code would have to be built-in when used by thinkpad_acpi or else a new module would have to be added to arch/x86 too. Better to avoid that bloat because most x86 platforms won't benefit.
Changed since v8:
- Added kernel-doc comment describing the nvram_ops methods.
- Renamed static nvram_* functions to avoid name collisions.
- Converted arch_nvram_ops method calls to nvram.h wrapper function calls.
--- drivers/char/nvram.c | 30 ++++++++++++++++++++++++------ include/linux/nvram.h | 32 ++++++++++++++++++++++++++++++++ 2 files changed, 56 insertions(+), 6 deletions(-)
drivers/char/nvram.c +24 -6
@@ -52,9 +52,11 @@ static DEFINE_MUTEX(nvram_mutex);static DEFINE_SPINLOCK (nvram_state_lock);static int nvram_open_cnt;/* #times opened */ static int nvram_open_mode;/* special open modes */ +static ssize_t nvram_size;#define NVRAM_WRITE 1/* opened for writing (exclusive) */ #define NVRAM_EXCL 2/* opened with O_EXCL */ +#ifdef CONFIG_X86 /* * These functions are provided to be called internally or by other parts of * the kernel. It's up to the caller to ensure correct checksum before reading
@@ -145,6 +147,19 @@ void nvram_set_checksum(void) }#endif /* 0 */ +static ssize_t pc_nvram_get_size (void ) +{ +return NVRAM_BYTES ; +} + +const struct nvram_ops arch_nvram_ops = { + .read_byte = pc_nvram_read_byte, + .write_byte = pc_nvram_write_byte, + .get_size = pc_nvram_get_size, +}; +EXPORT_SYMBOL (arch_nvram_ops); +#endif /* CONFIG_X86 */ +/* * The are the file operation function for user access to /dev/nvram */
@@ -152,7 +167,7 @@ void nvram_set_checksum(void)static loff_t nvram_misc_llseek (struct file *file,loff_t offset,int origin) {return generic_file_llseek_size (file, offset, origin,MAX_LFS_FILESIZE , -NVRAM_BYTES ); + nvram_size); } static ssize_t nvram_misc_read(struct file *file, char __user *buf,
@@ -303,8 +318,7 @@ static int nvram_misc_release(struct inode *inode, struct file *file)return 0 ; } -#ifdef CONFIG_PROC_FS - +#if defined(CONFIG_X86 ) && defined(CONFIG_PROC_FS )static const char *const floppy_types[] = {"none" ,"5.25'' 360k" ,"5.25'' 1.2M" ,"3.5'' 720k" ,"3.5'' 1.44M" , "3.5'' 2.88M", "3.5'' 2.88M"
@@ -394,7 +408,7 @@ static int nvram_proc_read(struct seq_file *seq, void *offset)return 0 ; } -#endif /* CONFIG_PROC_FS */ +#endif /* CONFIG_X86 && CONFIG_PROC_FS */ static const struct file_operations nvram_misc_fops = { .owner =THIS_MODULE ,
@@ -416,13 +430,17 @@ static int __init nvram_module_init(void) {int ret; + nvram_size =nvram_get_size (); +if (nvram_size <0 ) +return nvram_size; + ret =misc_register (&nvram_misc);if (ret) {pr_err ("nvram: can't misc_register on minor=%d\n" ,NVRAM_MINOR );return ret; } -#ifdef CONFIG_PROC_FS +#if defined(CONFIG_X86 ) && defined(CONFIG_PROC_FS )if (!proc_create_single ("driver/nvram" ,0 ,NULL , nvram_proc_read)) {pr_err ("nvram: can't create /proc/driver/nvram\n" );misc_deregister (&nvram_misc);
@@ -436,7 +454,7 @@ static int __init nvram_module_init(void) static void __exit nvram_module_exit(void) { -#ifdef CONFIG_PROC_FS +#if defined(CONFIG_X86 ) && defined(CONFIG_PROC_FS )remove_proc_entry ("driver/nvram" ,NULL );#endif misc_deregister (&nvram_misc);
include/linux/nvram.h +32 -0
@@ -5,8 +5,30 @@#include <linux/errno.h> #include <uapi/linux/nvram.h> +/** +* struct nvram_ops - NVRAM functionality made available to drivers +* @read: validate checksum (if any) then load a range of bytes from NVRAM +* @write: store a range of bytes to NVRAM then update checksum (if any) +* @read_byte: load a single byte from NVRAM +* @write_byte: store a single byte to NVRAM +* @get_size: return the fixed number of bytes in the NVRAM +* +* Architectures which provide an nvram ops struct need not implement all +* of these methods. If the NVRAM hardware can be accessed only one byte +* at a time then it may be sufficient to provide .read_byte and .write_byte. +* If the NVRAM has a checksum (and it is to be checked) the .read and +* .write methods can be used to implement that efficiently. +* +* Portable drivers may use the wrapper functions defined here. +* The nvram_read() and nvram_write() functions call the .read and .write +* methods when available and fall back on the .read_byte and .write_byte +* methods otherwise. +*/ +struct nvram_ops {ssize_t (*get_size)(void ); +unsigned char (*read_byte)(int ); +void (*write_byte)(unsigned char ,int );ssize_t (*read)(char *,size_t ,loff_t *);ssize_t (*write)(char *,size_t ,loff_t *); };
@@ -25,11 +47,21 @@ static inline ssize_t nvram_get_size(void)static inline unsigned char nvram_read_byte (int addr) { +#ifdef CONFIG_PPC +#else +if (arch_nvram_ops.read_byte) +return arch_nvram_ops.read_byte (addr); +#endif return 0xFF ; }static inline void nvram_write_byte (unsigned char val,int addr) { +#ifdef CONFIG_PPC +#else +if (arch_nvram_ops.write_byte) + arch_nvram_ops.write_byte (val, addr); +#endif }static inline ssize_t nvram_read (char *buf,size_t count,loff_t *ppos)
Signature · 1 line
2.19.2
PATCH v9 8/22 char/nvram: Allow the set_checksum and initialize ioctls to be omitted
In reply to Finn ThainThe drivers/char/nvram.c module has previously supported only RTC "CMOS" NVRAM, for which it provides appropriate checksum ioctls. Make these ioctls optional so the module can be re-used with other kinds of NVRAM.
The ops struct methods that implement the ioctls now return error codes so that a multi-platform kernel binary can do the right thing when running on hardware without a suitable NVRAM.
---
Changed since v8:
- Renamed nvram_* functions to avoid name collisions.
--- drivers/char/nvram.c | 70 ++++++++++++++++++++++++------------------- include/linux/nvram.h | 2 ++ 2 files changed, 42 insertions(+), 30 deletions(-)
drivers/char/nvram.c +40 -30
@@ -136,16 +136,25 @@ static void __nvram_set_checksum(void)__nvram_write_byte (sum &0xff ,PC_CKS_LOC +1 ); } -#if 0 -void nvram_set_checksum (void ) +static long pc_nvram_set_checksum (void ) { -unsigned long flags; +spin_lock_irq (&rtc_lock); +__nvram_set_checksum (); +spin_unlock_irq (&rtc_lock); +return 0 ; +} -spin_lock_irqsave (&rtc_lock, flags); +static long pc_nvram_initialize (void ) +{ +ssize_t i; + +spin_lock_irq (&rtc_lock); +for (i =0 ; i <NVRAM_BYTES ; ++i) +__nvram_write_byte (0 , i);__nvram_set_checksum (); -spin_unlock_irqrestore (&rtc_lock, flags); +spin_unlock_irq (&rtc_lock); +return 0 ; } -#endif /* 0 */ static ssize_t pc_nvram_get_size (void ) {
@@ -156,6 +165,8 @@ const struct nvram_ops arch_nvram_ops = { .read_byte = pc_nvram_read_byte, .write_byte = pc_nvram_write_byte, .get_size = pc_nvram_get_size, + .set_checksum = pc_nvram_set_checksum, + .initialize = pc_nvram_initialize, };EXPORT_SYMBOL (arch_nvram_ops);#endif /* CONFIG_X86 */
@@ -241,51 +252,50 @@ static ssize_t nvram_misc_write(struct file *file, const char __user *buf,static long nvram_misc_ioctl (struct file *file,unsigned int cmd,unsigned long arg) { -int i; +long ret = -ENOTTY ;switch (cmd) { -case NVRAM_INIT :/* initialize NVRAM contents and checksum */ if (!capable (CAP_SYS_ADMIN ))return -EACCES ; -mutex_lock (&nvram_mutex); -spin_lock_irq (&rtc_lock); - -for (i =0 ; i <NVRAM_BYTES ; ++i) -__nvram_write_byte (0 , i); -__nvram_set_checksum (); - -spin_unlock_irq (&rtc_lock); -mutex_unlock (&nvram_mutex); -return 0 ; - +if (arch_nvram_ops.initialize !=NULL ) { +mutex_lock (&nvram_mutex); + ret = arch_nvram_ops.initialize (); +mutex_unlock (&nvram_mutex); + } +break ;case NVRAM_SETCKS :/* just set checksum, contents unchanged (maybe useful after * checksum garbaged somehow...) */ if (!capable (CAP_SYS_ADMIN ))return -EACCES ; -mutex_lock (&nvram_mutex); -spin_lock_irq (&rtc_lock); -__nvram_set_checksum (); -spin_unlock_irq (&rtc_lock); -mutex_unlock (&nvram_mutex); -return 0 ; - -default : -return -ENOTTY ; +if (arch_nvram_ops.set_checksum !=NULL ) { +mutex_lock (&nvram_mutex); + ret = arch_nvram_ops.set_checksum (); +mutex_unlock (&nvram_mutex); + } +break ; } +return ret; }static int nvram_misc_open (struct inode *inode,struct file *file) {spin_lock (&nvram_state_lock); +/* Prevent multiple readers/writers if desired. */ if ((nvram_open_cnt && (file->f_flags &O_EXCL )) || - (nvram_open_mode &NVRAM_EXCL ) || - ((file->f_mode &FMODE_WRITE ) && (nvram_open_mode &NVRAM_WRITE ))) { + (nvram_open_mode &NVRAM_EXCL )) { +spin_unlock (&nvram_state_lock); +return -EBUSY ; + } + +/* Prevent multiple writers if the set_checksum ioctl is implemented. */ +if ((arch_nvram_ops.set_checksum !=NULL ) && + (file->f_mode &FMODE_WRITE ) && (nvram_open_mode &NVRAM_WRITE )) {spin_unlock (&nvram_state_lock);return -EBUSY ; }
include/linux/nvram.h +2 -0
@@ -31,6 +31,8 @@ struct nvram_ops {void (*write_byte)(unsigned char ,int );ssize_t (*read)(char *,size_t ,loff_t *);ssize_t (*write)(char *,size_t ,loff_t *); +long (*initialize)(void ); +long (*set_checksum)(void ); };extern const struct nvram_ops arch_nvram_ops;
Signature · 1 line
2.19.2
PATCH v9 9/22 char/nvram: Implement NVRAM read/write methods
In reply to Finn ThainRefactor the RTC "CMOS" NVRAM functions so that they can be used as arch_nvram_ops methods. Checksumming logic is moved from the misc device operations to the nvram read/write operations. This makes the misc device implementation more generic.
This preserves the locking mechanism such that "read if checksum valid" and "write and update checksum" remain atomic operations.
Some platforms implement byte-range read/write methods which are similar to file_operations struct methods. Other platforms provide only byte-at-a-time methods. The former are more efficient but may be unavailable so fall back on the latter methods when necessary.
---
Changed since v8:
- Renamed nvram_* functions to avoid name collisions.
- Added nvram_read_bytes() and nvram_write_bytes() helpers for use by
those platforms which access NVRAM only one-byte-at-a-time.
Changed since v7:
- Adopted memdup_user(), like arch/powerpc/kernel/nvram_64.c.
--- drivers/char/nvram.c | 120 ++++++++++++++++++++++++++---------------- include/linux/nvram.h | 32 ++++++++++- 2 files changed, 104 insertions(+), 48 deletions(-)
drivers/char/nvram.c +74 -46
@@ -41,6 +41,7 @@#include <linux/init.h> #include <linux/proc_fs.h> #include <linux/seq_file.h> +#include <linux/slab.h> #include <linux/spinlock.h> #include <linux/io.h> #include <linux/uaccess.h>
@@ -161,7 +162,46 @@ static ssize_t pc_nvram_get_size(void)return NVRAM_BYTES ; } +static ssize_t pc_nvram_read (char *buf,size_t count,loff_t *ppos) +{ +char *p = buf; +loff_t i; + +spin_lock_irq (&rtc_lock); +if (!__nvram_check_checksum ()) { +spin_unlock_irq (&rtc_lock); +return -EIO ; + } +for (i = *ppos; count >0 && i <NVRAM_BYTES ; --count, ++i, ++p) + *p =__nvram_read_byte (i); +spin_unlock_irq (&rtc_lock); + + *ppos = i; +return p - buf; +} + +static ssize_t pc_nvram_write (char *buf,size_t count,loff_t *ppos) +{ +char *p = buf; +loff_t i; + +spin_lock_irq (&rtc_lock); +if (!__nvram_check_checksum ()) { +spin_unlock_irq (&rtc_lock); +return -EIO ; + } +for (i = *ppos; count >0 && i <NVRAM_BYTES ; --count, ++i, ++p) +__nvram_write_byte (*p, i); +__nvram_set_checksum (); +spin_unlock_irq (&rtc_lock); + + *ppos = i; +return p - buf; +} +const struct nvram_ops arch_nvram_ops = { + .read = pc_nvram_read, + .write = pc_nvram_write, .read_byte = pc_nvram_read_byte, .write_byte = pc_nvram_write_byte, .get_size = pc_nvram_get_size,
@@ -184,69 +224,57 @@ static loff_t nvram_misc_llseek(struct file *file, loff_t offset, int origin)static ssize_t nvram_misc_read (struct file *file,char __user *buf,size_t count,loff_t *ppos) { -unsigned char contents[NVRAM_BYTES ]; -unsigned i = *ppos; -unsigned char *tmp; - -spin_lock_irq (&rtc_lock); +char *tmp; +ssize_t ret; -if (!__nvram_check_checksum ()) - goto checksum_err; -for (tmp = contents; count-- >0 && i <NVRAM_BYTES ; ++i, ++tmp) - *tmp =__nvram_read_byte (i); +if (!access_ok (buf, count)) +return -EFAULT ; +if (*ppos >= nvram_size) +return 0 ; -spin_unlock_irq (&rtc_lock); + count =min_t (size_t, count, nvram_size - *ppos); + count =min_t (size_t, count,PAGE_SIZE ); -if (copy_to_user (buf, contents, tmp - contents)) -return -EFAULT ; + tmp =kmalloc (count,GFP_KERNEL ); +if (!tmp) +return -ENOMEM ; - *ppos = i; + ret =nvram_read (tmp, count, ppos); +if (ret <=0 ) + goto out; -return tmp - contents; +if (copy_to_user (buf, tmp, ret)) { + *ppos -= ret; + ret = -EFAULT ; + } -checksum_err: -spin_unlock_irq (&rtc_lock); -return -EIO ; +out: +kfree (tmp); +return ret; }static ssize_t nvram_misc_write (struct file *file,const char __user *buf,size_t count,loff_t *ppos) { -unsigned char contents[NVRAM_BYTES ]; -unsigned i = *ppos; -unsigned char *tmp; - -if (i >=NVRAM_BYTES ) -return 0 ;/* Past EOF */ - -if (count >NVRAM_BYTES - i) - count =NVRAM_BYTES - i; -if (count >NVRAM_BYTES ) -return -EFAULT ;/* Can't happen, but prove it to gcc */ +char *tmp; +ssize_t ret; -if (copy_from_user (contents, buf, count)) +if (!access_ok (buf, count))return -EFAULT ; +if (*ppos >= nvram_size) +return 0 ; -spin_lock_irq (&rtc_lock); - -if (!__nvram_check_checksum ()) - goto checksum_err; - -for (tmp = contents; count--; ++i, ++tmp) -__nvram_write_byte (*tmp, i); + count =min_t (size_t, count, nvram_size - *ppos); + count =min_t (size_t, count,PAGE_SIZE ); -__nvram_set_checksum (); - -spin_unlock_irq (&rtc_lock); + tmp =memdup_user (buf, count); +if (IS_ERR (tmp)) +return PTR_ERR (tmp); - *ppos = i; - -return tmp - contents; - -checksum_err: -spin_unlock_irq (&rtc_lock); -return -EIO ; + ret =nvram_write (tmp, count, ppos); +kfree (tmp); +return ret; } static long nvram_misc_ioctl(struct file *file, unsigned int cmd,
include/linux/nvram.h +30 -2
@@ -66,18 +66,46 @@ static inline void nvram_write_byte(unsigned char val, int addr)#endif } +static inline ssize_t nvram_read_bytes (char *buf,size_t count,loff_t *ppos) +{ +ssize_t nvram_size =nvram_get_size (); +loff_t i; +char *p = buf; + +if (nvram_size <0 ) +return nvram_size; +for (i = *ppos; count >0 && i < nvram_size; ++i, ++p, --count) + *p =nvram_read_byte (i); + *ppos = i; +return p - buf; +} + +static inline ssize_t nvram_write_bytes (char *buf,size_t count,loff_t *ppos) +{ +ssize_t nvram_size =nvram_get_size (); +loff_t i; +char *p = buf; + +if (nvram_size <0 ) +return nvram_size; +for (i = *ppos; count >0 && i < nvram_size; ++i, ++p, --count) +nvram_write_byte (*p, i); + *ppos = i; +return p - buf; +} +static inline ssize_t nvram_read (char *buf,size_t count,loff_t *ppos) {if (arch_nvram_ops.read)return arch_nvram_ops.read (buf, count, ppos); -return -ENODEV ; +return nvram_read_bytes (buf, count, ppos); }static inline ssize_t nvram_write (char *buf,size_t count,loff_t *ppos) {if (arch_nvram_ops.write)return arch_nvram_ops.write (buf, count, ppos); -return -ENODEV ; +return nvram_write_bytes (buf, count, ppos); }#endif /* _LINUX_NVRAM_H */
Signature · 1 line
2.19.2
PATCH v9 10/22 m68k/atari: Implement arch_nvram_ops methods and enable CONFIG_HAVE_ARCH_NVRAM_OPS
In reply to Finn ThainAtari RTC NVRAM uses a checksum so implement the remaining arch_nvram_ops methods for the set_checksum and initialize ioctls. Enable CONFIG_HAVE_ARCH_NVRAM_OPS.
---
Changed since v8:
- Moved the HAVE_ARCH_NVRAM_OPS symbol to common code as suggested by
Christoph Hellwig.
- Renamed functions to avoid name collisions with nvram.h.
Changed since v7:
- Changed the default for CONFIG_NVRAM, because "select NVRAM" was
removed from ATARI_SCSI in patch 1.
--- arch/Kconfig | 3 +++ arch/m68k/Kconfig.machine | 1 + arch/m68k/atari/nvram.c | 24 ++++++++++++++++++++++++ drivers/char/Kconfig | 3 ++- 4 files changed, 30 insertions(+), 1 deletion(-)
arch/Kconfig +3 -0
@@ -701,6 +701,9 @@ config HAVE_ARCH_HASH file which provides platform-specific implementations of some functions in <linux/hash.h> or fs/namei.c. +config HAVE_ARCH_NVRAM_OPS + bool + config ISA_BUS_API def_bool ISA
arch/m68k/Kconfig.machine +1 -0
@@ -16,6 +16,7 @@ config ATARI bool "Atari support" depends on MMU select MMU_MOTOROLA if MMU + select HAVE_ARCH_NVRAM_OPS help This option enables support for the 68000-based Atari series of computers (including the TT, Falcon and Medusa). If you plan to use
arch/m68k/atari/nvram.c +24 -0
@@ -74,6 +74,26 @@ static void __nvram_set_checksum(void)__nvram_write_byte (sum,ATARI_CKS_LOC +1 ); } +static long atari_nvram_set_checksum (void ) +{ +spin_lock_irq (&rtc_lock); +__nvram_set_checksum (); +spin_unlock_irq (&rtc_lock); +return 0 ; +} + +static long atari_nvram_initialize (void ) +{ +loff_t i; + +spin_lock_irq (&rtc_lock); +for (i =0 ; i <NVRAM_BYTES ; ++i) +__nvram_write_byte (0 , i); +__nvram_set_checksum (); +spin_unlock_irq (&rtc_lock); +return 0 ; +} +static ssize_t atari_nvram_read (char *buf,size_t count,loff_t *ppos) {char *p = buf;
@@ -113,6 +133,8 @@ static ssize_t atari_nvram_write(char *buf, size_t count, loff_t *ppos)static ssize_t atari_nvram_get_size (void ) { +if (!MACH_IS_ATARI ) +return -ENODEV ;return NVRAM_BYTES ; }
@@ -120,6 +142,8 @@ const struct nvram_ops arch_nvram_ops = { .read = atari_nvram_read, .write = atari_nvram_write, .get_size = atari_nvram_get_size, + .set_checksum = atari_nvram_set_checksum, + .initialize = atari_nvram_initialize, };EXPORT_SYMBOL (arch_nvram_ops);
drivers/char/Kconfig +2 -1
@@ -244,7 +244,8 @@ source "drivers/char/hw_random/Kconfig" config NVRAM tristate "/dev/nvram support" - depends on X86 || GENERIC_NVRAM + depends on X86 || GENERIC_NVRAM || HAVE_ARCH_NVRAM_OPS + default M68K ---help--- If you say Y here and create a character special file /dev/nvram with major number 10 and minor number 144 using mknod ("man mknod"),
Signature · 1 line
2.19.2
PATCH v9 11/22 m68k/mac: Adopt naming and calling conventions for PRAM routines
In reply to Finn ThainAdopt the existing *_read_byte and *_write_byte naming convention. Rename via_pram_readbyte and via_pram_writebyte to avoid confusion. Adjust calling conventions of mac_pram_* functions to match the struct nvram_ops methods.
---
Changed since v7:
- Removed some gratuitous function pointers.
--- arch/m68k/mac/misc.c | 61 +++++++++++++++++--------------------------- 1 file changed, 23 insertions(+), 38 deletions(-)
arch/m68k/mac/misc.c +23 -38
@@ -37,7 +37,7 @@static void (*rom_reset)(void );#ifdef CONFIG_ADB_CUDA -static __u8 cuda_read_pram (int offset) +static unsigned char cuda_pram_read_byte (int offset) {struct adb_request req;
@@ -49,7 +49,7 @@ static __u8 cuda_read_pram(int offset)return req.reply[3 ]; } -static void cuda_write_pram (int offset,__u8 data) +static void cuda_pram_write_byte (unsigned char data,int offset) {struct adb_request req;
@@ -62,7 +62,7 @@ static void cuda_write_pram(int offset, __u8 data)#endif /* CONFIG_ADB_CUDA */ #ifdef CONFIG_ADB_PMU -static __u8 pmu_read_pram (int offset) +static unsigned char pmu_pram_read_byte (int offset) {struct adb_request req;
@@ -74,7 +74,7 @@ static __u8 pmu_read_pram(int offset)return req.reply[3 ]; } -static void pmu_write_pram (int offset,__u8 data) +static void pmu_pram_write_byte (unsigned char data,int offset) {struct adb_request req;
@@ -93,7 +93,7 @@ static void pmu_write_pram(int offset, __u8 data)* the RTC should be enabled. */ -static __u8 via_pram_readbyte (void ) +static __u8 via_rtc_recv (void ) {int i, reg;__u8 data;
@@ -120,7 +120,7 @@ static __u8 via_pram_readbyte(void)return data; } -static void via_pram_writebyte (__u8 data) +static void via_rtc_send (__u8 data) {int i, reg, bit;
@@ -157,17 +157,17 @@ static void via_pram_command(int command, __u8 *data) via1[vBufB] = (via1[vBufB] | VIA1B_vRTCClk) & ~VIA1B_vRTCEnb;if (command &0xFF00 ) {/* extended (two-byte) command */ -via_pram_writebyte ((command &0xFF00 ) >>8 ); -via_pram_writebyte (command &0xFF ); +via_rtc_send ((command &0xFF00 ) >>8 ); +via_rtc_send (command &0xFF ); is_read = command &0x8000 ; }else {/* one-byte command */ -via_pram_writebyte (command); +via_rtc_send (command); is_read = command &0x80 ; }if (is_read) { - *data =via_pram_readbyte (); + *data =via_rtc_recv (); }else { -via_pram_writebyte (*data); +via_rtc_send (*data); }/* All done, disable the RTC */
@@ -177,12 +177,12 @@ static void via_pram_command(int command, __u8 *data)local_irq_restore (flags); } -static __u8 via_read_pram (int offset) +static unsigned char via_pram_read_byte (int offset) {return 0 ; } -static void via_write_pram (int offset,__u8 data) +static void via_pram_write_byte (unsigned char data,int offset) { }
@@ -326,63 +326,48 @@ static void cuda_shutdown(void)*------------------------------------------------------------------- */ -void mac_pram_read (int offset,__u8 *buffer,int len) +unsigned char mac_pram_read_byte (int addr) { -__u8 (*func)(int); -int i; -switch (macintosh_config->adb_type) {case MAC_ADB_IOP :case MAC_ADB_II :case MAC_ADB_PB1 : - func = via_read_pram; -break ; +return via_pram_read_byte (addr);#ifdef CONFIG_ADB_CUDA case MAC_ADB_EGRET :case MAC_ADB_CUDA : - func = cuda_read_pram; -break ; +return cuda_pram_read_byte (addr);#endif #ifdef CONFIG_ADB_PMU case MAC_ADB_PB2 : - func = pmu_read_pram; -break ; +return pmu_pram_read_byte (addr);#endif default : -return ; - } -for (i =0 ; i < len ; i++) { - buffer[i] = (*func)(offset++); +return 0xFF ; } } -void mac_pram_write (int offset,__u8 *buffer,int len) +void mac_pram_write_byte (unsigned char val,int addr) { -void (*func)(int ,__u8 ); -int i; -switch (macintosh_config->adb_type) {case MAC_ADB_IOP :case MAC_ADB_II :case MAC_ADB_PB1 : - func = via_write_pram; +via_pram_write_byte (val, addr);break ;#ifdef CONFIG_ADB_CUDA case MAC_ADB_EGRET :case MAC_ADB_CUDA : - func = cuda_write_pram; +cuda_pram_write_byte (val, addr);break ;#endif #ifdef CONFIG_ADB_PMU case MAC_ADB_PB2 : - func = pmu_write_pram; +pmu_pram_write_byte (val, addr);break ;#endif default : -return ; - } -for (i =0 ; i < len ; i++) { - (*func)(offset++, buffer[i]); +break ; } }
Signature · 1 line
2.19.2
PATCH v9 12/22 m68k/mac: Use macros for RTC accesses not magic numbers
In reply to Finn ThainThis is intended to improve code style and not affect code behaviour.
--- arch/m68k/mac/misc.c | 59 ++++++++++++++++++++++++++++++-------------- 1 file changed, 41 insertions(+), 18 deletions(-)
arch/m68k/mac/misc.c +41 -18
@@ -136,6 +136,21 @@ static void via_rtc_send(__u8 data) } } +/* +* These values can be found in Inside Macintosh vol. III ch. 2 +* which has a description of the RTC chip in the original Mac. +*/ + +#define RTC_FLG_READ BIT(7) +#define RTC_FLG_WRITE_PROTECT BIT(7) +#define RTC_CMD_READ (r) (RTC_FLG_READ | (r << 2)) +#define RTC_CMD_WRITE (r) (r << 2) +#define RTC_REG_SECONDS_0 0 +#define RTC_REG_SECONDS_1 1 +#define RTC_REG_SECONDS_2 2 +#define RTC_REG_SECONDS_3 3 +#define RTC_REG_WRITE_PROTECT 13 +/* * Execute a VIA PRAM/RTC command. For read commands * data should point to a one-byte buffer for the
@@ -145,13 +160,17 @@ static void via_rtc_send(__u8 data)* This function disables all interrupts while running. */ -static void via_pram_command (int command,__u8 *data) +static void via_rtc_command (int command,__u8 *data) {unsigned long flags;int is_read;local_irq_save (flags); +/* The least significant bits must be 0b01 according to Inside Mac */ + + command = (command & ~3 ) |1 ; +/* Enable the RTC and make sure the strobe line is high */ via1[vBufB] = (via1[vBufB] | VIA1B_vRTCClk) & ~VIA1B_vRTCEnb;
@@ -159,10 +178,10 @@ static void via_pram_command(int command, __u8 *data)if (command &0xFF00 ) {/* extended (two-byte) command */ via_rtc_send ((command &0xFF00 ) >>8 );via_rtc_send (command &0xFF ); - is_read = command &0x8000 ; + is_read = command & (RTC_FLG_READ <<8 ); }else {/* one-byte command */ via_rtc_send (command); - is_read = command &0x80 ; + is_read = command &RTC_FLG_READ ; }if (is_read) { *data =via_rtc_recv ();
@@ -201,10 +220,10 @@ static time64_t via_read_time(void) } result, last_result;int count =1 ; -via_pram_command (0x81 , &last_result.cdata[3 ]); -via_pram_command (0x85 , &last_result.cdata[2 ]); -via_pram_command (0x89 , &last_result.cdata[1 ]); -via_pram_command (0x8D , &last_result.cdata[0 ]); +via_rtc_command (RTC_CMD_READ (RTC_REG_SECONDS_0 ), &last_result.cdata[3 ]); +via_rtc_command (RTC_CMD_READ (RTC_REG_SECONDS_1 ), &last_result.cdata[2 ]); +via_rtc_command (RTC_CMD_READ (RTC_REG_SECONDS_2 ), &last_result.cdata[1 ]); +via_rtc_command (RTC_CMD_READ (RTC_REG_SECONDS_3 ), &last_result.cdata[0 ]);/* * The NetBSD guys say to loop until you get the same reading
@@ -212,10 +231,14 @@ static time64_t via_read_time(void)*/ while (1 ) { -via_pram_command (0x81 , &result.cdata[3 ]); -via_pram_command (0x85 , &result.cdata[2 ]); -via_pram_command (0x89 , &result.cdata[1 ]); -via_pram_command (0x8D , &result.cdata[0 ]); +via_rtc_command (RTC_CMD_READ (RTC_REG_SECONDS_0 ), + &result.cdata[3 ]); +via_rtc_command (RTC_CMD_READ (RTC_REG_SECONDS_1 ), + &result.cdata[2 ]); +via_rtc_command (RTC_CMD_READ (RTC_REG_SECONDS_2 ), + &result.cdata[1 ]); +via_rtc_command (RTC_CMD_READ (RTC_REG_SECONDS_3 ), + &result.cdata[0 ]);if (result.idata == last_result.idata)return (time64_t )result.idata -RTC_OFFSET ;
@@ -254,18 +277,18 @@ static void via_set_rtc_time(struct rtc_time *tm)/* Clear the write protect bit */ temp =0x55 ; -via_pram_command (0x35 , &temp); +via_rtc_command (RTC_CMD_WRITE (RTC_REG_WRITE_PROTECT ), &temp); data.idata =lower_32_bits (time +RTC_OFFSET ); -via_pram_command (0x01 , &data.cdata[3 ]); -via_pram_command (0x05 , &data.cdata[2 ]); -via_pram_command (0x09 , &data.cdata[1 ]); -via_pram_command (0x0D , &data.cdata[0 ]); +via_rtc_command (RTC_CMD_WRITE (RTC_REG_SECONDS_0 ), &data.cdata[3 ]); +via_rtc_command (RTC_CMD_WRITE (RTC_REG_SECONDS_1 ), &data.cdata[2 ]); +via_rtc_command (RTC_CMD_WRITE (RTC_REG_SECONDS_2 ), &data.cdata[1 ]); +via_rtc_command (RTC_CMD_WRITE (RTC_REG_SECONDS_3 ), &data.cdata[0 ]);/* Set the write protect bit */ - temp =0xD5 ; -via_pram_command (0x35 , &temp); + temp =0x55 |RTC_FLG_WRITE_PROTECT ; +via_rtc_command (RTC_CMD_WRITE (RTC_REG_WRITE_PROTECT ), &temp); }static void via_shutdown (void )
Signature · 1 line
2.19.2
PATCH v9 13/22 m68k/mac: Fix PRAM accessors
In reply to Finn ThainPMU-based m68k Macs pre-date PowerMac-style NVRAM. Use the appropriate PMU commands. Also implement the missing XPRAM accessors for VIA-based Macs.
---
Changed since v7:
- Revised PMU response decoding due to via-pmu68k driver replacement.
--- arch/m68k/mac/misc.c | 43 ++++++++++++++++++++++++++++++---------- include/uapi/linux/pmu.h | 2 ++ 2 files changed, 35 insertions(+), 10 deletions(-)
arch/m68k/mac/misc.c +33 -10
@@ -66,23 +66,22 @@ static unsigned char pmu_pram_read_byte(int offset) {struct adb_request req; -if (pmu_request (&req,NULL ,3 ,PMU_READ_NVRAM , - (offset >>8 ) &0xFF , offset &0xFF ) <0 ) +if (pmu_request (&req,NULL ,3 ,PMU_READ_XPRAM , + offset &0xFF ,1 ) <0 )return 0 ; -while (!req.complete) -pmu_poll (); -return req.reply[3 ]; +pmu_wait_complete (&req); + +return req.reply[0 ]; }static void pmu_pram_write_byte (unsigned char data,int offset) {struct adb_request req; -if (pmu_request (&req,NULL ,4 ,PMU_WRITE_NVRAM , - (offset >>8 ) &0xFF , offset &0xFF , data) <0 ) +if (pmu_request (&req,NULL ,4 ,PMU_WRITE_XPRAM , + offset &0xFF ,1 , data) <0 )return ; -while (!req.complete) -pmu_poll (); +pmu_wait_complete (&req); }#endif /* CONFIG_ADB_PMU */
@@ -151,6 +150,16 @@ static void via_rtc_send(__u8 data)#define RTC_REG_SECONDS_3 3#define RTC_REG_WRITE_PROTECT 13 +/* +* Inside Mac has no information about two-byte RTC commands but +* the MAME/MESS source code has the essentials. +*/ + +#define RTC_REG_XPRAM 14 +#define RTC_CMD_XPRAM_READ (RTC_CMD_READ(RTC_REG_XPRAM) << 8) +#define RTC_CMD_XPRAM_WRITE (RTC_CMD_WRITE(RTC_REG_XPRAM) << 8) +#define RTC_CMD_XPRAM_ARG (a) (((a & 0xE0) << 3) | ((a & 0x1F) << 2)) +/* * Execute a VIA PRAM/RTC command. For read commands * data should point to a one-byte buffer for the
@@ -198,11 +207,25 @@ static void via_rtc_command(int command, __u8 *data)static unsigned char via_pram_read_byte (int offset) { -return 0 ; +unsigned char temp; + +via_rtc_command (RTC_CMD_XPRAM_READ |RTC_CMD_XPRAM_ARG (offset), &temp); + +return temp; }static void via_pram_write_byte (unsigned char data,int offset) { +unsigned char temp; + + temp =0x55 ; +via_rtc_command (RTC_CMD_WRITE (RTC_REG_WRITE_PROTECT ), &temp); + + temp = data; +via_rtc_command (RTC_CMD_XPRAM_WRITE |RTC_CMD_XPRAM_ARG (offset), &temp); + + temp =0x55 |RTC_FLG_WRITE_PROTECT ; +via_rtc_command (RTC_CMD_WRITE (RTC_REG_WRITE_PROTECT ), &temp); }/*
include/uapi/linux/pmu.h +2 -0
@@ -19,7 +19,9 @@#define PMU_POWER_CTRL 0x11/* control power of some devices */ #define PMU_ADB_CMD 0x20/* send ADB packet */ #define PMU_ADB_POLL_OFF 0x21/* disable ADB auto-poll */ +#define PMU_WRITE_XPRAM 0x32/* write eXtended Parameter RAM */ #define PMU_WRITE_NVRAM 0x33/* write non-volatile RAM */ +#define PMU_READ_XPRAM 0x3a/* read eXtended Parameter RAM */ #define PMU_READ_NVRAM 0x3b/* read non-volatile RAM */ #define PMU_SET_RTC 0x30/* set real-time clock */ #define PMU_READ_RTC 0x38/* read real-time clock */
Signature · 1 line
2.19.2
PATCH v9 14/22 macintosh/via-cuda: Don't rely on Cuda to end a transfer
In reply to Finn ThainCertain Cuda transfers have to be ended by the driver. According to Apple's open source Cuda driver, as found in mkLinux and XNU, this applies to any "open ended request such as PRAM read". This fixes an infinite polling loop in cuda_pram_read_byte().
--- drivers/macintosh/via-cuda.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-)
drivers/macintosh/via-cuda.c +5 -3
@@ -569,6 +569,7 @@ cuda_interrupt(int irq, void *arg)unsigned char ibuf[16 ];int ibuf_len =0 ;int complete =0 ; +bool full;spin_lock_irqsave (&cuda_lock, flags);
@@ -656,12 +657,13 @@ cuda_interrupt(int irq, void *arg)break ;case reading: -if (reading_reply ?ARRAY_FULL (current_req->reply, reply_ptr) - :ARRAY_FULL (cuda_rbuf, reply_ptr)) + full = reading_reply ?ARRAY_FULL (current_req->reply, reply_ptr) + :ARRAY_FULL (cuda_rbuf, reply_ptr); +if (full) (void )in_8 (&via[SR ]);else *reply_ptr++ =in_8 (&via[SR ]); -if (!TREQ_asserted (status)) { +if (!TREQ_asserted (status) || full) {if (mcu_is_egret)assert_TACK ();/* that's all folks */
Signature · 1 line
2.19.2
PATCH v9 15/22 m68k: Dispatch nvram_ops calls to Atari or Mac functions
In reply to Finn ThainA multi-platform kernel binary has to decide at run-time how to dispatch the arch_nvram_ops calls. Add a platform-independent arch_nvram_ops struct for this, to replace the atari-specific one.
Enable CONFIG_HAVE_ARCH_NVRAM_OPS for Macs.
---
Changed since v8:
- Adopted nvram_read_bytes() and nvram_write_bytes() where possible.
--- arch/m68k/Kconfig.machine | 1 + arch/m68k/atari/nvram.c | 21 ++------ arch/m68k/include/asm/atarihw.h | 6 +++ arch/m68k/include/asm/macintosh.h | 4 ++ arch/m68k/kernel/setup_mm.c | 82 ++++++++++++++++++++++++++++++- arch/m68k/mac/misc.c | 11 +++++ 6 files changed, 108 insertions(+), 17 deletions(-)
arch/m68k/Kconfig.machine +1 -0
@@ -27,6 +27,7 @@ config MAC bool "Macintosh support" depends on MMU select MMU_MOTOROLA if MMU + select HAVE_ARCH_NVRAM_OPS help This option enables support for the Apple Macintosh series of computers (yes, there is experimental support now, at least for part
arch/m68k/atari/nvram.c +5 -16
@@ -74,7 +74,7 @@ static void __nvram_set_checksum(void)__nvram_write_byte (sum,ATARI_CKS_LOC +1 ); } -static long atari_nvram_set_checksum (void ) +long atari_nvram_set_checksum (void ) {spin_lock_irq (&rtc_lock);__nvram_set_checksum ();
@@ -82,7 +82,7 @@ static long atari_nvram_set_checksum(void)return 0 ; } -static long atari_nvram_initialize (void ) +long atari_nvram_initialize (void ) {loff_t i;
@@ -94,7 +94,7 @@ static long atari_nvram_initialize(void)return 0 ; } -static ssize_t atari_nvram_read (char *buf,size_t count,loff_t *ppos) +ssize_t atari_nvram_read (char *buf,size_t count,loff_t *ppos) {char *p = buf;loff_t i;
@@ -112,7 +112,7 @@ static ssize_t atari_nvram_read(char *buf, size_t count, loff_t *ppos)return p - buf; } -static ssize_t atari_nvram_write (char *buf,size_t count,loff_t *ppos) +ssize_t atari_nvram_write (char *buf,size_t count,loff_t *ppos) {char *p = buf;loff_t i;
@@ -131,22 +131,11 @@ static ssize_t atari_nvram_write(char *buf, size_t count, loff_t *ppos)return p - buf; } -static ssize_t atari_nvram_get_size (void ) +ssize_t atari_nvram_get_size (void ) { -if (!MACH_IS_ATARI ) -return -ENODEV ;return NVRAM_BYTES ; } -const struct nvram_ops arch_nvram_ops = { - .read = atari_nvram_read, - .write = atari_nvram_write, - .get_size = atari_nvram_get_size, - .set_checksum = atari_nvram_set_checksum, - .initialize = atari_nvram_initialize, -}; -EXPORT_SYMBOL (arch_nvram_ops); - #ifdef CONFIG_PROC_FS static struct { unsigned char val;
arch/m68k/include/asm/atarihw.h +6 -0
@@ -33,6 +33,12 @@ extern int atari_dont_touch_floppy_select;extern int atari_SCC_reset_done; +extern ssize_t atari_nvram_read (char *,size_t ,loff_t *); +extern ssize_t atari_nvram_write (char *,size_t ,loff_t *); +extern ssize_t atari_nvram_get_size (void ); +extern long atari_nvram_set_checksum (void ); +extern long atari_nvram_initialize (void ); +/* convenience macros for testing machine type */ #define MACH_IS_ST ((atari_mch_cookie >> 16) == ATARI_MCH_ST)#define MACH_IS_STE ((atari_mch_cookie >> 16) == ATARI_MCH_STE && \
arch/m68k/include/asm/macintosh.h +4 -0
@@ -19,6 +19,10 @@ extern void mac_init_IRQ(void);extern void mac_irq_enable (struct irq_data *data);extern void mac_irq_disable (struct irq_data *data); +extern unsigned char mac_pram_read_byte (int ); +extern void mac_pram_write_byte (unsigned char ,int ); +extern ssize_t mac_pram_get_size (void ); +/* * Macintosh Table */
arch/m68k/kernel/setup_mm.c +81 -1
103 lines not on this page · raw message
arch/m68k/mac/misc.c +11 -0
@@ -36,6 +36,7 @@static void (*rom_reset)(void ); +#if IS_ENABLED(CONFIG_NVRAM) #ifdef CONFIG_ADB_CUDA static unsigned char cuda_pram_read_byte(int offset) {
@@ -84,6 +85,7 @@ static void pmu_pram_write_byte(unsigned char data, int offset)pmu_wait_complete (&req); }#endif /* CONFIG_ADB_PMU */ +#endif /* CONFIG_NVRAM */ /* * VIA PRAM/RTC access routines
@@ -205,6 +207,7 @@ static void via_rtc_command(int command, __u8 *data)local_irq_restore (flags); } +#if IS_ENABLED (CONFIG_NVRAM )static unsigned char via_pram_read_byte (int offset) {unsigned char temp;
@@ -227,6 +230,7 @@ static void via_pram_write_byte(unsigned char data, int offset) temp =0x55 |RTC_FLG_WRITE_PROTECT ; via_rtc_command(RTC_CMD_WRITE(RTC_REG_WRITE_PROTECT), &temp); } +#endif /* CONFIG_NVRAM */ /* * Return the current time in seconds since January 1, 1904.
@@ -372,6 +376,7 @@ static void cuda_shutdown(void)*------------------------------------------------------------------- */ +#if IS_ENABLED (CONFIG_NVRAM )unsigned char mac_pram_read_byte (int addr) {switch (macintosh_config->adb_type) {
@@ -417,6 +422,12 @@ void mac_pram_write_byte(unsigned char val, int addr) } } +ssize_t mac_pram_get_size (void ) +{ +return 256 ; +} +#endif /* CONFIG_NVRAM */ +void mac_poweroff (void ) {if (oss_present) {
Signature · 1 line
2.19.2
Greg Kroah-Hartman
maintainerRe: [PATCH v9 15/22] m68k: Dispatch nvram_ops calls to Atari or Mac functions
Quoted 4 lines · Finn Thain
A multi-platform kernel binary has to decide at run-time how to dispatch the
arch_nvram_opscalls. Add a platform-independentarch_nvram_opsstruct for this, to replace the atari-specific one.
Quoted 8 lines
Enable
CONFIG_HAVE_ARCH_NVRAM_OPSfor Macs.Tested-by Stan Johnson <[email protected]>Signed-off-by Finn Thain <[email protected]>---
Changed since v8:
- Adoptednvram_read_bytes()andnvram_write_bytes()where possible.
This patch fails to apply to my tree, what did you make it against?
I tried against 5.0-rc1 :(
Can you rebase this series against the char-misc-next branch of my char-misc.git tree and resend so that I can apply the whole series?
thanks,
greg k-h
Greg Kroah-Hartman
maintainerRe: [PATCH v9 15/22] m68k: Dispatch nvram_ops calls to Atari or Mac functions
Quoted 14 lines · Greg Kroah-Hartman
Quoted 4 lines · Finn Thain
A multi-platform kernel binary has to decide at run-time how to dispatch the
arch_nvram_opscalls. Add a platform-independentarch_nvram_opsstruct for this, to replace the atari-specific one.Quoted 8 lines
Enable
CONFIG_HAVE_ARCH_NVRAM_OPSfor Macs.Tested-by Stan Johnson <[email protected]>Signed-off-by Finn Thain <[email protected]>---
Changed since v8:
- Adoptednvram_read_bytes()andnvram_write_bytes()where possible.
Quoted 6 lines
This patch fails to apply to my tree, what did you make it against?
I tried against 5.0-rc1 :(
Can you rebase this series against the char-misc-next branch of my char-misc.git tree and resend so that I can apply the whole series?
Oops, nope, my fault, I missed some patches in this series, nevermind...
greg k-h
PATCH v9 16/22 char/nvram: Add "devname:nvram" module alias
In reply to Finn Thain--- drivers/char/nvram.c | 1 + 1 file changed, 1 insertion(+)
drivers/char/nvram.c +1 -0
@@ -503,3 +503,4 @@ module_exit(nvram_module_exit);MODULE_LICENSE ("GPL" );MODULE_ALIAS_MISCDEV (NVRAM_MINOR ); +MODULE_ALIAS ("devname:nvram" );
Signature · 1 line
2.19.2
PATCH v9 17/22 powerpc: Define missing ppc_md.nvram_size for CHRP and PowerMac
In reply to Finn ThainAdd the nvram_size() function to those PowerPC platforms that don't already have one: CHRP and PowerMac. This means that the ppc_md.nvram_size() function can be called by nvram_get_size().
Since we are addressing CHRP inconsistencies here, rename chrp_nvram_read and chrp_nvram_write, which break the naming convention used across powerpc platforms for NVRAM accessor functions.
---
Changed since v8:
- Renamed functions to correspond with ppc_md member names.
--- arch/powerpc/platforms/chrp/nvram.c | 14 ++++++++++---- arch/powerpc/platforms/powermac/nvram.c | 9 +++++++++ 2 files changed, 19 insertions(+), 4 deletions(-)
arch/powerpc/platforms/chrp/nvram.c +10 -4
@@ -24,7 +24,7 @@ static unsigned int nvram_size;static unsigned char nvram_buf[4 ];static DEFINE_SPINLOCK (nvram_lock); -static unsigned char chrp_nvram_read (int addr) +static unsigned char chrp_nvram_read_val (int addr) {unsigned int done;unsigned long flags;
@@ -46,7 +46,7 @@ static unsigned char chrp_nvram_read(int addr)return ret; } -static void chrp_nvram_write (int addr,unsigned char val) +static void chrp_nvram_write_val (int addr,unsigned char val) {unsigned int done;unsigned long flags;
@@ -64,6 +64,11 @@ static void chrp_nvram_write(int addr, unsigned char val)spin_unlock_irqrestore (&nvram_lock, flags); } +static ssize_t chrp_nvram_size (void ) +{ +return nvram_size; +} +void __init chrp_nvram_init (void ) {struct device_node *nvram;
@@ -85,8 +90,9 @@ void __init chrp_nvram_init(void)printk (KERN_INFO "CHRP nvram contains %u bytes\n" , nvram_size);of_node_put (nvram); - ppc_md.nvram_read_val = chrp_nvram_read; - ppc_md.nvram_write_val = chrp_nvram_write; + ppc_md.nvram_read_val = chrp_nvram_read_val; + ppc_md.nvram_write_val = chrp_nvram_write_val; + ppc_md.nvram_size = chrp_nvram_size;return ; }
arch/powerpc/platforms/powermac/nvram.c +9 -0
@@ -147,6 +147,11 @@ static ssize_t core99_nvram_size(void)static volatile unsigned char __iomem *nvram_addr;static int nvram_mult; +static ssize_t ppc32_nvram_size (void ) +{ +return NVRAM_SIZE ; +} +static unsigned char direct_nvram_read_byte (int addr) {return in_8 (&nvram_data[(addr & (NVRAM_SIZE -1 )) * nvram_mult]);
@@ -590,21 +595,25 @@ int __init pmac_nvram_init(void) nvram_mult =1 ; ppc_md.nvram_read_val = direct_nvram_read_byte; ppc_md.nvram_write_val = direct_nvram_write_byte; + ppc_md.nvram_size = ppc32_nvram_size; }else if (nvram_naddrs ==1 ) { nvram_data =ioremap (r1.start, s1); nvram_mult = (s1 +NVRAM_SIZE -1 ) /NVRAM_SIZE ; ppc_md.nvram_read_val = direct_nvram_read_byte; ppc_md.nvram_write_val = direct_nvram_write_byte; + ppc_md.nvram_size = ppc32_nvram_size; }else if (nvram_naddrs ==2 ) { nvram_addr =ioremap (r1.start, s1); nvram_data =ioremap (r2.start, s2); ppc_md.nvram_read_val = indirect_nvram_read_byte; ppc_md.nvram_write_val = indirect_nvram_write_byte; + ppc_md.nvram_size = ppc32_nvram_size; }else if (nvram_naddrs ==0 && sys_ctrler ==SYS_CTRLER_PMU ) {#ifdef CONFIG_ADB_PMU nvram_naddrs =-1 ; ppc_md.nvram_read_val = pmu_nvram_read_byte; ppc_md.nvram_write_val = pmu_nvram_write_byte; + ppc_md.nvram_size = ppc32_nvram_size;#endif /* CONFIG_ADB_PMU */ }else {printk (KERN_ERR "Incompatible type of NVRAM\n" );
Signature · 1 line
2.19.2
PATCH v9 18/22 powerpc: Implement nvram ioctls
In reply to Finn ThainAdd the powerpc-specific ioctls to the nvram module. This allows the nvram module to replace the generic_nvram module.
---
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 may be better to return an error (which is what PPC64 does).
Changed since v8:
- Changed #else to fully specified #elif conditional.
- Changed arch_nvram_ops method calls to ppc_md method calls.
--- drivers/char/nvram.c | 38 ++++++++++++++++++++++++++++++++++++++ include/linux/nvram.h | 2 ++ 2 files changed, 40 insertions(+)
drivers/char/nvram.c +38 -0
@@ -48,6 +48,9 @@#include <linux/mutex.h> #include <linux/pagemap.h> +#ifdef CONFIG_PPC +#include <asm/nvram.h> +#endif static DEFINE_MUTEX (nvram_mutex);static DEFINE_SPINLOCK (nvram_state_lock);
@@ -283,6 +286,38 @@ 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 +if (machine_is (powermac)) { +int part, offset; + +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 ; + } +#endif +break ; +case IOC_NVRAM_SYNC : +if (ppc_md.nvram_sync !=NULL ) { +mutex_lock (&nvram_mutex); + ppc_md.nvram_sync (); +mutex_unlock (&nvram_mutex); + } + ret =0 ; +break ; +#elif defined(CONFIG_X86 ) || defined(CONFIG_M68K )case NVRAM_INIT :/* initialize NVRAM contents and checksum */ if (!capable (CAP_SYS_ADMIN ))
@@ -306,6 +341,7 @@ static long nvram_misc_ioctl(struct file *file, unsigned int cmd, mutex_unlock(&nvram_mutex); }break ; +#endif /* CONFIG_X86 || CONFIG_M68K */ }return ret; }
@@ -321,12 +357,14 @@ static int nvram_misc_open(struct inode *inode, struct file *file)return -EBUSY ; } +#if defined(CONFIG_X86 ) || defined(CONFIG_M68K )/* Prevent multiple writers if the set_checksum ioctl is implemented. */ if ((arch_nvram_ops.set_checksum !=NULL ) && (file->f_mode &FMODE_WRITE ) && (nvram_open_mode &NVRAM_WRITE )) {spin_unlock (&nvram_state_lock);return -EBUSY ; } +#endif if (file->f_flags &O_EXCL ) nvram_open_mode |=NVRAM_EXCL ;
include/linux/nvram.h +2 -0
@@ -31,8 +31,10 @@ struct nvram_ops {void (*write_byte)(unsigned char ,int );ssize_t (*read)(char *,size_t ,loff_t *);ssize_t (*write)(char *,size_t ,loff_t *); +#if defined(CONFIG_X86 ) || defined(CONFIG_M68K )long (*initialize)(void );long (*set_checksum)(void ); +#endif };extern const struct nvram_ops arch_nvram_ops;
Signature · 1 line
2.19.2
PATCH v9 19/22 powerpc, fbdev: Use NV_CMODE and NV_VMODE only when CONFIG_PPC32 && CONFIG_PPC_PMAC && CONFIG_NVRAM
In reply to Finn ThainThis patch addresses inconsistencies in Mac framebuffer drivers and their use of Kconfig symbols relating to NVRAM, so PPC64 can use CONFIG_NVRAM.
The defined(CONFIG_NVRAM) condition is replaced with the weaker IS_REACHABLE(CONFIG_NVRAM) condition, like atari_scsi.
Macintosh framebuffer drivers use default settings for color mode and video mode that are found in NVRAM. On PCI Macs, MacOS stores display settings in the Name Registry (NR) partition in NVRAM*. On NuBus Macs, there is no NR partition and MacOS stores display mode settings in PRAM**.
Early-model Macs are the ones most likely to benefit from these settings, since they are more likely to have a fixed-frequency monitor connected to the built-in framebuffer device. Moreover, a single NV_CMODE value and a single NV_VMODE value provide for only one display.
The NV_CMODE and NV_VMODE constants are apparently offsets into the NR partition for Old World machines. This also suggests that these defaults are not useful on later models. The NR partition seems to be optional on New World machines. CONFIG_NVRAM cannot be enabled on PPC64 at present.
It is safe to say that NVRAM support in PowerMac fbdev drivers is only applicable to CONFIG_PPC32 so make this condition explicit. This means matroxfb driver won't crash on PPC64 when CONFIG_NVRAM becomes available there.
For imsttfb, add the missing CONFIG_NVRAM test to prevent a build failure, since PPC64 does not implement nvram_read_byte(). Also add a missing machine_is(powermac) check. Change the inconsistent dependency on CONFIG_PPC and the matching #ifdef tests to CONFIG_PPC_PMAC.
For valkyriefb, to improve clarity and consistency with the other PowerMac fbdev drivers, test for CONFIG_PPC_PMAC instead of !CONFIG_MAC. Remove a bogus comment regarding PRAM.
* See GetPreferredConfiguration and SavePreferredConfiguration in "Designing PCI Cards and Drivers for Power Macintosh Computers".
** See SetDefaultMode and GetDefaultMode in "Designing Cards and Drivers for the Macintosh Family".
---
Changed since v8:
- Replaced defined(CONFIG_NVRAM) with IS_REACHABLE(CONFIG_NVRAM) as
suggested by James Bottomley.
- Changed #ifdef to if as suggested by Christophe Leroy.
- Expanded the patch to include controlfb.c and platinumfb.c due to the
conversion from '#if defined(CONFIG_NVRAM)' to
'if (IS_REACHABLE(CONFIG_NVRAM))'.
--- drivers/video/fbdev/Kconfig | 2 +- drivers/video/fbdev/controlfb.c | 42 ++++++++-------------- drivers/video/fbdev/imsttfb.c | 23 ++++++------ drivers/video/fbdev/matrox/matroxfb_base.c | 5 +-- drivers/video/fbdev/platinumfb.c | 21 +++++------ drivers/video/fbdev/valkyriefb.c | 30 ++++++---------- 6 files changed, 48 insertions(+), 75 deletions(-)
drivers/video/fbdev/Kconfig +1 -1
@@ -536,7 +536,7 @@ config FB_IMSTT bool "IMS Twin Turbo display support" depends on (FB = y) && PCI select FB_CFB_IMAGEBLIT - select FB_MACMODES if PPC + select FB_MACMODES if PPC_PMAC help The IMS Twin Turbo is a PCI-based frame buffer card bundled with many Macintosh and compatible computers.
drivers/video/fbdev/controlfb.c +15 -27
50 lines not on this page · raw message
drivers/video/fbdev/imsttfb.c +11 -12
@@ -30,9 +30,8 @@#include <asm/io.h> #include <linux/uaccess.h> -#if defined(CONFIG_PPC ) +#if defined(CONFIG_PPC_PMAC )#include <linux/nvram.h> -#include <asm/prom.h> #include "macmodes.h" #endif
@@ -327,14 +326,13 @@ enum { TVP = 1 }; -#define USE_NV_MODES 1#define INIT_BPP 8#define INIT_XRES 640#define INIT_YRES 480static int inverse =0 ;static char fontname[40 ]__initdata = {0 }; -#if defined(CONFIG_PPC ) +#if defined(CONFIG_PPC_PMAC )static signed char init_vmode =-1 , init_cmode =-1 ;#endif
@@ -1390,8 +1388,8 @@ static void init_imstt(struct fb_info *info) } } -#if USE_NV_MODES && defined(CONFIG_PPC32 ) - { +#if defined(CONFIG_PPC_PMAC ) && defined(CONFIG_PPC32 ) +if (IS_REACHABLE (CONFIG_NVRAM ) &&machine_is (powermac)) {int vmode = init_vmode, cmode = init_cmode;if (vmode ==-1 ) {
@@ -1409,12 +1407,13 @@ static void init_imstt(struct fb_info *info) info->var.yres = info->var.yres_virtual =INIT_YRES ; info->var.bits_per_pixel = INIT_BPP; } - } -#else - info->var.xres = info->var.xres_virtual =INIT_XRES ; - info->var.yres = info->var.yres_virtual =INIT_YRES ; - info->var.bits_per_pixel =INIT_BPP ; + } else#endif + { + info->var.xres = info->var.xres_virtual =INIT_XRES ; + info->var.yres = info->var.yres_virtual =INIT_YRES ; + info->var.bits_per_pixel =INIT_BPP ; + }if ((info->var.xres * info->var.yres) * (info->var.bits_per_pixel >>3 ) > info->fix.smem_len || !(compute_imstt_regvals (par, info->var.xres, info->var.yres))) {
@@ -1565,7 +1564,7 @@ imsttfb_setup(char *options) inverse =1 ;fb_invert_cmaps (); } -#if defined(CONFIG_PPC ) +#if defined(CONFIG_PPC_PMAC ) else if (!strncmp(this_opt, "vmode:", 6)) {int vmode =simple_strtoul (this_opt+6 ,NULL ,0 );if (vmode >0 && vmode <=VMODE_MAX )
drivers/video/fbdev/matrox/matroxfb_base.c +3 -2
@@ -1872,10 +1872,11 @@ static int initMatrox2(struct matrox_fb_info *minfo, struct board *b)#ifndef MODULE if (machine_is (powermac)) {struct fb_var_screeninfo var; +if (default_vmode <=0 || default_vmode >VMODE_MAX ) default_vmode =VMODE_640_480_60 ; -#ifdef CONFIG_NVRAM -if (default_cmode ==CMODE_NVRAM ) +#if defined(CONFIG_PPC32 ) +if (IS_REACHABLE (CONFIG_NVRAM ) && default_cmode ==CMODE_NVRAM ) default_cmode =nvram_read_byte (NV_CMODE );#endif if (default_cmode <CMODE_8 || default_cmode >CMODE_32 )
drivers/video/fbdev/platinumfb.c +8 -13
@@ -345,23 +345,18 @@ static int platinum_init_fb(struct fb_info *info) sense =read_platinum_sense (pinfo);printk (KERN_INFO "platinumfb: Monitor sense value = 0x%x, " , sense); -if (default_vmode ==VMODE_NVRAM ) { -#ifdef CONFIG_NVRAM + +if (IS_REACHABLE (CONFIG_NVRAM ) && default_vmode ==VMODE_NVRAM ) default_vmode =nvram_read_byte (NV_VMODE ); -if (default_vmode <=0 || default_vmode >VMODE_MAX || - !platinum_reg_init[default_vmode-1]) -#endif - default_vmode =VMODE_CHOOSE ; - } -if (default_vmode ==VMODE_CHOOSE ) { +if (default_vmode <=0 || default_vmode >VMODE_MAX || + !platinum_reg_init[default_vmode -1 ]) { default_vmode =mac_map_monitor_sense (sense); +if (!platinum_reg_init[default_vmode -1 ]) + default_vmode =VMODE_640_480_60 ; } -if (default_vmode <=0 || default_vmode >VMODE_MAX ) - default_vmode =VMODE_640_480_60 ; -#ifdef CONFIG_NVRAM -if (default_cmode ==CMODE_NVRAM ) + +if (IS_REACHABLE (CONFIG_NVRAM ) && default_cmode ==CMODE_NVRAM ) default_cmode =nvram_read_byte (NV_CMODE ); -#endif if (default_cmode <CMODE_8 || default_cmode >CMODE_32 ) default_cmode =CMODE_8 ;/*
drivers/video/fbdev/valkyriefb.c +10 -20
@@ -63,15 +63,8 @@#include "macmodes.h" #include "valkyriefb.h" -#ifdef CONFIG_MAC -/* We don't yet have functions to read the PRAM... perhaps we can -adapt them from the PPC code? */ -static int default_vmode =VMODE_CHOOSE ; -static int default_cmode =CMODE_8 ; -#else static int default_vmode =VMODE_NVRAM ;static int default_cmode =CMODE_NVRAM ; -#endif struct fb_par_valkyrie {int vmode, cmode;
@@ -283,24 +276,21 @@ static void __init valkyrie_choose_mode(struct fb_info_valkyrie *p)printk (KERN_INFO "Monitor sense value = 0x%x\n" , p->sense);/* Try to pick a video mode out of NVRAM if we have one. */ -#if !defined(CONFIG_MAC ) && defined(CONFIG_NVRAM ) -if (default_vmode ==VMODE_NVRAM ) { +#ifdef CONFIG_PPC_PMAC +if (IS_REACHABLE (CONFIG_NVRAM ) && default_vmode ==VMODE_NVRAM ) default_vmode =nvram_read_byte (NV_VMODE ); -if (default_vmode <=0 - || default_vmode >VMODE_MAX - || !valkyrie_reg_init[default_vmode -1 ]) - default_vmode =VMODE_CHOOSE ; - }#endif -if (default_vmode ==VMODE_CHOOSE ) +if (default_vmode <=0 || default_vmode >VMODE_MAX || + !valkyrie_reg_init[default_vmode -1 ]) { default_vmode =mac_map_monitor_sense (p->sense); -if (!valkyrie_reg_init[default_vmode -1 ]) - default_vmode =VMODE_640_480_67 ; -#if !defined(CONFIG_MAC ) && defined(CONFIG_NVRAM ) -if (default_cmode ==CMODE_NVRAM ) +if (!valkyrie_reg_init[default_vmode -1 ]) + default_vmode =VMODE_640_480_67 ; + } + +#ifdef CONFIG_PPC_PMAC +if (IS_REACHABLE (CONFIG_NVRAM ) && default_cmode ==CMODE_NVRAM ) default_cmode =nvram_read_byte (NV_CMODE );#endif -/* * Reduce the pixel size if we don't have enough VRAM or bandwidth. */
Signature · 1 line
2.19.2
PATCH v9 20/22 powerpc: Enable HAVE_ARCH_NVRAM_OPS and disable GENERIC_NVRAM
In reply to Finn ThainSwitch PPC32 kernels from the generic_nvram module to the nvram module.
Also fix a theoretical bug where CHRP omits the chrp_nvram_init() call when CONFIG_NVRAM_MODULE=m.
---
The change in the name of the module is visible to userspace. The module that implements /dev/nvram on PowerPC now has suitable aliases, i.e. MODULE_ALIAS_MISCDEV(NVRAM_MINOR); MODULE_ALIAS("devname:nvram");
so that the device special file can be automatically created and the module automatically loaded when needed. Previously this was not the case.
Changed since v8:
- Moved the HAVE_ARCH_NVRAM_OPS symbol to common code as suggested by
Christoph Hellwig.
- Changed arch_nvram_ops method calls to ppc_md method calls.
- Removed the now unused nvram_sync() export.
Changed since v7:
- Improved Kconfig help text for CONFIG_NVRAM.
- Changed the default for CONFIG_NVRAM, which used to be "n". This is to
reduce the risk that CONFIG_GENERIC_NVRAM=y accidentally gets changed to CONFIG_NVRAM=n.
--- arch/powerpc/Kconfig | 6 +----- arch/powerpc/include/asm/nvram.h | 3 --- arch/powerpc/kernel/setup_32.c | 11 ----------- arch/powerpc/platforms/chrp/Makefile | 2 +- arch/powerpc/platforms/chrp/setup.c | 2 +- arch/powerpc/platforms/powermac/setup.c | 3 +-- drivers/char/Kconfig | 19 +++++++++---------- include/linux/nvram.h | 20 ++++++++++++++++++++ 8 files changed, 33 insertions(+), 33 deletions(-)
arch/powerpc/Kconfig +1 -5
@@ -178,6 +178,7 @@ config PPC select HAVE_ARCH_KGDB select HAVE_ARCH_MMAP_RND_BITS select HAVE_ARCH_MMAP_RND_COMPAT_BITS if COMPAT + select HAVE_ARCH_NVRAM_OPS if PPC32 select HAVE_ARCH_SECCOMP_FILTER select HAVE_ARCH_TRACEHOOK select HAVE_CBPF_JIT if !PPC64
@@ -274,11 +275,6 @@ config SYSVIPC_COMPAT depends on COMPAT && SYSVIPC default y -# All PPC32s use generic nvram driver through ppc_md -config GENERIC_NVRAM - bool - default y if PPC32 - config SCHED_OMIT_FRAME_POINTER bool default y
arch/powerpc/include/asm/nvram.h +0 -3
@@ -78,9 +78,6 @@ extern int pmac_get_partition(int partition);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);
arch/powerpc/kernel/setup_32.c +0 -11
@@ -148,17 +148,6 @@ static int __init ppc_setup_l3cr(char *str) }__setup ("l3cr=" , ppc_setup_l3cr); -#ifdef CONFIG_GENERIC_NVRAM - -void nvram_sync (void ) -{ -if (ppc_md.nvram_sync) - ppc_md.nvram_sync (); -} -EXPORT_SYMBOL (nvram_sync); - -#endif /* CONFIG_NVRAM */ -static int __init ppc_init (void ) {/* clear the progress line */
arch/powerpc/platforms/chrp/Makefile +1 -1
@@ -1,3 +1,3 @@ obj-y += setup.o time.o pegasos_eth.o pci.o obj-$(CONFIG_SMP) += smp.o -obj-$(CONFIG_NVRAM) += nvram.o +obj-$(CONFIG_NVRAM:m=y) += nvram.o
arch/powerpc/platforms/chrp/setup.c +1 -1
@@ -550,7 +550,7 @@ static void __init chrp_init_IRQ(void)static void __init chrp_init2 (void ) { -#ifdef CONFIG_NVRAM +#if IS_ENABLED (CONFIG_NVRAM )chrp_nvram_init ();#endif
arch/powerpc/platforms/powermac/setup.c +1 -2
@@ -316,8 +316,7 @@ static void __init pmac_setup_arch(void)find_via_pmu ();smu_init (); -#if defined(CONFIG_NVRAM ) || defined(CONFIG_NVRAM_MODULE ) || \ - defined(CONFIG_PPC64 ) +#if IS_ENABLED (CONFIG_NVRAM ) || defined(CONFIG_PPC64 )pmac_nvram_init ();#endif #ifdef CONFIG_PPC32
drivers/char/Kconfig +9 -10
@@ -244,25 +244,24 @@ source "drivers/char/hw_random/Kconfig" config NVRAM tristate "/dev/nvram support" - depends on X86 || GENERIC_NVRAM || HAVE_ARCH_NVRAM_OPS - default M68K + depends on X86 || HAVE_ARCH_NVRAM_OPS + default M68K || PPC ---help--- If you say Y here and create a character special file /dev/nvram with major number 10 and minor number 144 using mknod ("man mknod"), - you get read and write access to the extra bytes of non-volatile - memory in the real time clock (RTC), which is contained in every PC - and most Ataris. The actual number of bytes varies, depending on the - nvram in the system, but is usually 114 (128-14 for the RTC). - - This memory is conventionally called "CMOS RAM" on PCs and "NVRAM" - on Ataris. /dev/nvram may be used to view settings there, or to - change them (with some utility). It could also be used to frequently + you get read and write access to the non-volatile memory. + + /dev/nvram may be used to view settings in NVRAM or to change them + (with some utility). It could also be used to frequently save a few bits of very important data that may not be lost over power-off and for which writing to disk is too insecure. Note however that most NVRAM space in a PC belongs to the BIOS and you should NEVER idly tamper with it. See Ralf Brown's interrupt list for a guide to the use of CMOS bytes by your BIOS. + This memory is conventionally called "NVRAM" on PowerPC machines, + "CMOS RAM" on PCs, "NVRAM" on Ataris and "PRAM" on Macintoshes. + To compile this driver as a module, choose M here: the module will be called nvram.
include/linux/nvram.h +20 -0
@@ -5,6 +5,10 @@#include <linux/errno.h> #include <uapi/linux/nvram.h> +#ifdef CONFIG_PPC +#include <asm/machdep.h> +#endif +/** * struct nvram_ops - NVRAM functionality made available to drivers * @read: validate checksum (if any) then load a range of bytes from NVRAM
@@ -42,6 +46,8 @@ extern const struct nvram_ops arch_nvram_ops;static inline ssize_t nvram_get_size (void ) {#ifdef CONFIG_PPC +if (ppc_md.nvram_size) +return ppc_md.nvram_size ();#else if (arch_nvram_ops.get_size)return arch_nvram_ops.get_size ();
@@ -52,6 +58,8 @@ static inline ssize_t nvram_get_size(void)static inline unsigned char nvram_read_byte (int addr) {#ifdef CONFIG_PPC +if (ppc_md.nvram_read_val) +return ppc_md.nvram_read_val (addr);#else if (arch_nvram_ops.read_byte)return arch_nvram_ops.read_byte (addr);
@@ -62,6 +70,8 @@ static inline unsigned char nvram_read_byte(int addr)static inline void nvram_write_byte (unsigned char val,int addr) {#ifdef CONFIG_PPC +if (ppc_md.nvram_write_val) + ppc_md.nvram_write_val (addr, val);#else if (arch_nvram_ops.write_byte) arch_nvram_ops.write_byte (val, addr);
@@ -98,15 +108,25 @@ static inline ssize_t nvram_write_bytes(char *buf, size_t count, loff_t *ppos)static inline ssize_t nvram_read (char *buf,size_t count,loff_t *ppos) { +#ifdef CONFIG_PPC +if (ppc_md.nvram_read) +return ppc_md.nvram_read (buf, count, ppos); +#else if (arch_nvram_ops.read)return arch_nvram_ops.read (buf, count, ppos); +#endif return nvram_read_bytes (buf, count, ppos); }static inline ssize_t nvram_write (char *buf,size_t count,loff_t *ppos) { +#ifdef CONFIG_PPC +if (ppc_md.nvram_write) +return ppc_md.nvram_write (buf, count, ppos); +#else if (arch_nvram_ops.write)return arch_nvram_ops.write (buf, count, ppos); +#endif return nvram_write_bytes (buf, count, ppos); }
Signature · 1 line
2.19.2
PATCH v9 21/22 char/generic_nvram: Remove as unused
In reply to Finn Thain--- drivers/char/Makefile | 6 +- drivers/char/generic_nvram.c | 160 ----------------------------------- 2 files changed, 1 insertion(+), 165 deletions(-) delete mode 100644 drivers/char/generic_nvram.c
drivers/char/Makefile +1 -5
@@ -26,11 +26,7 @@ obj-$(CONFIG_RTC) += rtc.o obj-$(CONFIG_HPET) += hpet.o obj-$(CONFIG_EFI_RTC) += efirtc.o obj-$(CONFIG_XILINX_HWICAP) += xilinx_hwicap/ -ifeq ($(CONFIG_GENERIC_NVRAM),y) - obj-$(CONFIG_NVRAM) += generic_nvram.o -else - obj-$(CONFIG_NVRAM) += nvram.o -endif +obj-$(CONFIG_NVRAM) += nvram.o obj-$(CONFIG_TOSHIBA) += toshiba.o obj-$(CONFIG_DS1620) += ds1620.o obj-$(CONFIG_HW_RANDOM) += hw_random/
drivers/char/generic_nvram.c deleted +0 -160
160 lines not on this page · raw message
Signature · 1 line
2.19.2
PATCH v9 22/22 powerpc: Adopt nvram module for PPC64
In reply to Finn ThainAdopt nvram module to reduce code duplication. This means CONFIG_NVRAM becomes available to PPC64 builds. Previously it was only available to PPC32 builds because it depended on CONFIG_GENERIC_NVRAM.
The IOC_NVRAM_GET_OFFSET ioctl as implemented on PPC64 validates the offset returned by pmac_get_partition(). Do the same in the nvram module.
Note that the old PPC32 generic_nvram module lacked this test. So when CONFIG_PPC32 && CONFIG_PPC_PMAC, the IOC_NVRAM_GET_OFFSET ioctl would have returned 0 (always). But when CONFIG_PPC64 && CONFIG_PPC_PMAC, the IOC_NVRAM_GET_OFFSET ioctl would have returned -1 (which is -EPERM) when the requested partition was not found.
With this patch, the result is now -EINVAL on both PPC32 and PPC64 when the requested PowerMac NVRAM partition is not found. This is a userspace- visible change, in the non-existent partition case, which would be in an error path for an IOC_NVRAM_GET_OFFSET ioctl syscall.
---
BTW, the IOC_NVRAM_SYNC ioctl call returns an error on PPC64. This patch retains this behaviour though it might be better to actually perform a sync since both PPC64 and PPC32 do implement ppc_md.nvram_sync() for Core99.
Changed since v8:
- Dropped the arch_nvram_ops struct in favour of equivalent ppc_md
method calls. Regardless of the actual implementation, the presence of this functionality is indicated by CONFIG_HAVE_ARCH_NVRAM_OPS=y.
Changed since v7:
- Dropped pointless comment edit.
--- arch/powerpc/Kconfig | 2 +- arch/powerpc/kernel/nvram_64.c | 158 +---------------------- arch/powerpc/platforms/powermac/Makefile | 2 - arch/powerpc/platforms/powermac/setup.c | 2 +- arch/powerpc/platforms/powermac/time.c | 2 +- arch/powerpc/platforms/pseries/nvram.c | 2 - drivers/char/nvram.c | 4 + 7 files changed, 9 insertions(+), 163 deletions(-)
arch/powerpc/Kconfig +1 -1
@@ -178,7 +178,7 @@ config PPC select HAVE_ARCH_KGDB select HAVE_ARCH_MMAP_RND_BITS select HAVE_ARCH_MMAP_RND_COMPAT_BITS if COMPAT - select HAVE_ARCH_NVRAM_OPS if PPC32 + select HAVE_ARCH_NVRAM_OPS select HAVE_ARCH_SECCOMP_FILTER select HAVE_ARCH_TRACEHOOK select HAVE_CBPF_JIT if !PPC64
arch/powerpc/kernel/nvram_64.c +2 -156
179 lines not on this page · raw message
arch/powerpc/platforms/powermac/Makefile +0 -2
@@ -15,7 +15,5 @@ obj-$(CONFIG_PMAC_BACKLIGHT) += backlight.o # need this to be a bool. Cheat here and pretend CONFIG_NVRAM=m is really # CONFIG_NVRAM=y obj-$(CONFIG_NVRAM:m=y) += nvram.o -# ppc64 pmac doesn't define CONFIG_NVRAM but needs nvram stuff -obj-$(CONFIG_PPC64) += nvram.o obj-$(CONFIG_PPC32) += bootx_init.o obj-$(CONFIG_SMP) += smp.o
arch/powerpc/platforms/powermac/setup.c +1 -1
@@ -316,7 +316,7 @@ static void __init pmac_setup_arch(void)find_via_pmu ();smu_init (); -#if IS_ENABLED (CONFIG_NVRAM ) || defined(CONFIG_PPC64 ) +#if IS_ENABLED (CONFIG_NVRAM )pmac_nvram_init ();#endif #ifdef CONFIG_PPC32
arch/powerpc/platforms/powermac/time.c +1 -1
@@ -68,7 +68,7 @@long __init pmac_time_init (void ) {s32 delta =0 ; -#ifdef CONFIG_NVRAM +#if defined(CONFIG_NVRAM ) && defined(CONFIG_PPC32 )int dst; delta = ((s32 )pmac_xpram_read (PMAC_XPRAM_MACHINE_LOC +0x9 )) <<16 ;
arch/powerpc/platforms/pseries/nvram.c +0 -2
@@ -7,8 +7,6 @@* 2 of the License, or (at your option) any later version. * * /dev/nvram driver for PPC64 -* -* This perhaps should live in drivers/char */
drivers/char/nvram.c +4 -0
@@ -302,6 +302,8 @@ static long nvram_misc_ioctl(struct file *file, unsigned int cmd,if (part < pmac_nvram_OF || part > pmac_nvram_NR)return -EINVAL ; offset =pmac_get_partition (part); +if (offset <0 ) +return -EINVAL ;if (copy_to_user ((void __user *)arg, &offset,sizeof (offset)) !=0 )return -EFAULT ;
@@ -309,6 +311,7 @@ static long nvram_misc_ioctl(struct file *file, unsigned int cmd, }#endif break ; +#ifdef CONFIG_PPC32 case IOC_NVRAM_SYNC :if (ppc_md.nvram_sync !=NULL ) {mutex_lock (&nvram_mutex);
@@ -317,6 +320,7 @@ static long nvram_misc_ioctl(struct file *file, unsigned int cmd, } ret =0 ;break ; +#endif #elif defined(CONFIG_X86) || defined(CONFIG_M68K)case NVRAM_INIT :/* initialize NVRAM contents and checksum */
Signature · 1 line
2.19.2
Greg Kroah-Hartman
maintainerQuoted 36 lines · Finn Thain
The "generic" NVRAM module,
drivers/char/generic_nvram.c, implements a/dev/nvrammisc device. This module is used only by 32-bit PowerPC platforms.The RTC "CMOS" NVRAM module,
drivers/char/nvram.c, also implements a/dev/nvrammisc device. This module is now used only by x86 and m68k thanks to commit3ba9faedc180("char: nvram: disable on ARM").The "generic" module cannot be used by x86 or m68k platforms because it cannot co-exist with the "CMOS" module. One reason for that is the
CONFIG_GENERIC_NVRAMkludge indrivers/char/Makefile. Another reason is that automatically loading the appropriate module would be impossible because only one module can provide the char-major-10-144 alias.A multi-platform kernel binary needs a single, generic module. With this patch series,
drivers/char/nvram.cbecomes more generic and some of the arch-specific code gets moved underarch/. The nvram module is then usable by all m68k, powerpc and x86 platforms.This allows for removal of
drivers/char/generic_nvram.cas well as a duplicate inarch/powerpc/kernel/nvram_64.c. By reducing the number of/dev/nvramchar misc device implementations, the number of bugs and inconsistencies is also reduced.This approach reduces inconsistencies between PPC32 and PPC64 and also between
PPC_PMACand MAC. A uniform API has benefits for userspace.For example, some error codes for some ioctl calls become consistent across PowerPC platforms. The uniform API can potentially benefit any bootloader that works across the various platforms having XPRAM (e.g. Emile).
This patch series was tested on Atari, Mac, PowerMac (both 32-bit and 64-bit) and ThinkPad hardware. AFAIK, it has not yet been tested on pSeries or CHRP.
Quoted 5 lines
I think there are two possible merge strategies for this patch series. The char misc maintainer could take the entire series. Alternatively, the m68k maintainer could take patches 1 thru 16 (though some of these have nothing to do with m68k) and after those patches reach mainline the powerpc maintainer could take 17 thru 22.
I just took the whole series, thanks for doing this, looks good.
greg k-h
Quoted 37 lines · Greg Kroah-Hartman
Quoted 36 lines · Finn Thain
The "generic" NVRAM module,
drivers/char/generic_nvram.c, implements a/dev/nvrammisc device. This module is used only by 32-bit PowerPC platforms.The RTC "CMOS" NVRAM module,
drivers/char/nvram.c, also implements a/dev/nvrammisc device. This module is now used only by x86 and m68k thanks to commit3ba9faedc180("char: nvram: disable on ARM").The "generic" module cannot be used by x86 or m68k platforms because it cannot co-exist with the "CMOS" module. One reason for that is the
CONFIG_GENERIC_NVRAMkludge indrivers/char/Makefile. Another reason is that automatically loading the appropriate module would be impossible because only one module can provide the char-major-10-144 alias.A multi-platform kernel binary needs a single, generic module. With this patch series,
drivers/char/nvram.cbecomes more generic and some of the arch-specific code gets moved underarch/. The nvram module is then usable by all m68k, powerpc and x86 platforms.This allows for removal of
drivers/char/generic_nvram.cas well as a duplicate inarch/powerpc/kernel/nvram_64.c. By reducing the number of/dev/nvramchar misc device implementations, the number of bugs and inconsistencies is also reduced.This approach reduces inconsistencies between PPC32 and PPC64 and also between
PPC_PMACand MAC. A uniform API has benefits for userspace.For example, some error codes for some ioctl calls become consistent across PowerPC platforms. The uniform API can potentially benefit any bootloader that works across the various platforms having XPRAM (e.g. Emile).
This patch series was tested on Atari, Mac, PowerMac (both 32-bit and 64-bit) and ThinkPad hardware. AFAIK, it has not yet been tested on pSeries or CHRP.
Quoted 8 lines
Quoted 5 lines
I think there are two possible merge strategies for this patch series. The char misc maintainer could take the entire series. Alternatively, the m68k maintainer could take patches 1 thru 16 (though some of these have nothing to do with m68k) and after those patches reach mainline the powerpc maintainer could take 17 thru 22.
I just took the whole series, thanks for doing this, looks good.
Thanks, Greg.
I haven't seen any acks from powerpc maintainers yet...
Quoted 2 lines
greg k-h