From: Finn Thain <hidden> Date: 2015-05-31 01:18:47
The generic NVRAM module, drivers/char/generic_nvram, implements a
/dev/nvram misc device. It is used only by 32-bit PowerPC platforms and
isn't generic enough to be more widely used.
The RTC NVRAM module, drivers/char/nvram, also implements a /dev/nvram
misc device. It is used by x86, ARM and m68k.
The former module cannot be used on x86, ARM or m68k because it
cannot co-exist with the latter module, partly due to the Kconfig logic.
It is possible to modify the modules so that one kernel binary could
have either, neither or both. However, automatically loading the
appropriate module is then impossible; if both provide the
char-major-10-144 alias then the wrong module will end up being loaded.
Hence a multi-platform kernel binary needs a single generic nvram module
with alias char-major-10-144.
Therefore, drivers/char/nvram.c should be made more generic and the
arch-specific code therein should be moved to a more appropriate
place under arch/. Also, drivers/char/generic_nvram.c should be removed
to reduce code duplication.
In this patch series, Atari-specific code is moved from the nvram module
to arch/m68k/atari. More arch-specific code in the nvram module could
be moved, probably to arch/x86, but it is difficult to determine just
what code is relevant to ARM platforms and what code is x86-only.
In addressing code duplication, this patch series removes three
inconsistent /dev/nvram misc device implementations. One of these,
drivers/macintosh/nvram.c is entirely unused already. The other two,
drivers/char/generic_nvram.c and the misc device implementation in
arch/powerpc/kernel/nvram_64.c, are replaced by drivers/char/nvram.c.
A benefit of this work is better consistency -- between PPC32 and PPC64
as well as between PPC_PMAC and MAC. This new uniformity does have
implications for userspace, that is, some error codes for some ioctl calls
become consistent on all PowerPC platforms.
The drivers/char/nvram module becomes sufficiently generic to be useful
to other platforms and architectures, besides those with "CMOS" RTC. At the
end of this patch series the module is adopted by the m68k Mac port, which
already has PRAM access functions but lacks the /dev/nvram misc device.
This patch series has been compile-tested for arm, m68k, powerpc and x86.
The nvram and thinkpad_acpi modules were regression tested on a ThinkPad T43.
The /dev/nvram functionality was also regression tested on a G3 PowerMac.
The nvram module was also tested on a PowerBook 520 and Quadra 650.
Note that my testing doesn't cover PPC64 or Atari.
---
arch/m68k/Kconfig | 3
arch/m68k/atari/Makefile | 2
arch/m68k/atari/nvram.c | 304 ++++++++++++
arch/m68k/include/asm/atarihw.h | 6
arch/m68k/include/asm/macintosh.h | 4
arch/m68k/kernel/setup_mm.c | 89 +++
arch/m68k/mac/misc.c | 157 ++++--
arch/powerpc/Kconfig | 5
arch/powerpc/include/asm/nvram.h | 9
arch/powerpc/kernel/nvram_64.c | 203 +-------
arch/powerpc/kernel/setup_32.c | 27 -
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 | 5
arch/powerpc/platforms/powermac/nvram.c | 11
arch/powerpc/platforms/powermac/setup.c | 3
drivers/char/Kconfig | 13
drivers/char/Makefile | 6
drivers/char/generic_nvram.c | 174 ------
drivers/char/nvram.c | 731 ++++++++++++-----------------
drivers/macintosh/nvram.c | 130 -----
drivers/platform/x86/thinkpad_acpi.c | 20
drivers/scsi/Kconfig | 6
drivers/scsi/atari_scsi.c | 16
drivers/video/fbdev/controlfb.c | 4
drivers/video/fbdev/imsttfb.c | 7
drivers/video/fbdev/matrox/matroxfb_base.c | 4
drivers/video/fbdev/platinumfb.c | 4
drivers/video/fbdev/valkyriefb.c | 4
include/linux/nvram.h | 23
include/uapi/linux/pmu.h | 2
32 files changed, 950 insertions(+), 1040 deletions(-)
From: Finn Thain <hidden> Date: 2015-05-31 01:17:08
Implement arch_nvram_ops and adjust calling conventions of mac_pram_*
functions to match the ops struct methods. Rename via_pram_readbyte and
via_pram_writebyte to avoid confusion and follow the existing
nvram_*_read_byte and nvram_*_write_byte naming convention.
Enable CONFIG_HAVE_ARCH_NVRAM_OPS on Macs.
Signed-off-by: Finn Thain <redacted>
---
The arch_nvram_ops struct can only be defined once, of course, so the
Mac and Atari ops structs are mutually exclusive. The final patch will
allow the two implementations to co-exist in a multi-platform kernel binary.
---
arch/m68k/Kconfig | 2
arch/m68k/mac/misc.c | 120 +++++++++++++++++++++++++++++++--------------------
2 files changed, 76 insertions(+), 46 deletions(-)
Index: linux/arch/m68k/Kconfig
===================================================================
From: Finn Thain <hidden> Date: 2015-05-31 01:17:23
Also 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 makes them distict from nvram_ops members.
Signed-off-by: Finn Thain <redacted>
---
drivers/char/nvram.c | 194 ++++++++++++++++++++++-----------------------------
1 file changed, 86 insertions(+), 108 deletions(-)
Index: linux/drivers/char/nvram.c
===================================================================
@@ -54,11 +54,6 @@ static int nvram_open_mode; /* special o#define NVRAM_WRITE 1 /* opened for writing (exclusive) */#define NVRAM_EXCL 2 /* opened with O_EXCL */-#ifdef CONFIG_PROC_FS-staticvoidpc_nvram_proc_read(unsignedchar*contents,structseq_file*seq,-void*offset);-#endif-/**Thesefunctionsareprovidedtobecalledinternallyorbyotherpartsof*thekernel.It'suptothecallertoensurecorrectchecksumbeforereading
From: Finn Thain <hidden> Date: 2015-05-31 01:17:50
Adopt nvram module to reduce code duplication.
The IOC_NVRAM_GET_OFFSET ioctl as implemented on PPC64 validates the offset
returned by pmac_get_partition(). Add this test to 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 -ENOENT 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.
Signed-off-by: Finn Thain <redacted>
---
BTW, the IOC_NVRAM_SYNC ioctl call returns -EINVAL on PPC64. This patch
retains this behaviour though it might be better to actually perform a sync.
Both PPC64 and PPC32 kernels implement ppc_md.nvram_sync() for Core99,
but on PPC64 the ioctl is unimplemented (unlike PPC32).
---
arch/powerpc/Kconfig | 3
arch/powerpc/kernel/nvram_64.c | 203 ++++---------------------------
arch/powerpc/platforms/powermac/Makefile | 5
arch/powerpc/platforms/powermac/nvram.c | 2
arch/powerpc/platforms/powermac/setup.c | 2
drivers/char/nvram.c | 2
6 files changed, 38 insertions(+), 179 deletions(-)
Index: linux/arch/powerpc/Kconfig
===================================================================
@@ -177,10 +177,9 @@ config SYSVIPC_COMPATdepends onCOMPAT&&SYSVIPCdefaulty-# All PPC32s use generic nvram driver through ppc_mdconfigHAVE_ARCH_NVRAM_OPSbool-defaultyifPPC32+defaultyconfigSCHED_OMIT_FRAME_POINTERbool
@@ -9,11 +9,6 @@ obj-y += pic.o setup.o time.o featuresleep.olow_i2c.ocache.opfunc_core.o\pfunc_base.oudbg_scc.oudbg_adb.oobj-$(CONFIG_PMAC_BACKLIGHT)+=backlight.o-# CONFIG_NVRAM is an arch. independent tristate symbol, for pmac32 we really-# need this to be a bool. Cheat here and pretend CONFIG_NVRAM=m is really-# CONFIG_NVRAM=yobj-$(CONFIG_NVRAM:m=y) += nvram.o-# ppc64 pmac doesn't define CONFIG_NVRAM but needs nvram stuff-obj-$(CONFIG_PPC64)+=nvram.oobj-$(CONFIG_PPC32)+=bootx_init.oobj-$(CONFIG_SMP)+=smp.o
@@ -235,21 +235,7 @@ EXPORT_SYMBOL(arch_nvram_ops);staticloff_tnvram_misc_llseek(structfile*file,loff_toffset,intorigin){-switch(origin){-case0:-/* nothing to do */-break;-case1:-offset+=file->f_pos;-break;-case2:-offset+=NVRAM_BYTES;-break;-default:-return-EINVAL;-}--return(offset>=0)?(file->f_pos=offset):-EINVAL;+returnfixed_size_llseek(file,offset,origin,nvram_size);}staticssize_tnvram_misc_read(structfile*file,char__user*buf,
From: Finn Thain <hidden> Date: 2015-05-31 01:18:02
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".
Adopt the powerpc convention on m68k to avoid surprises.
Signed-off-by: Finn Thain <redacted>
---
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.
The removal of "select NVRAM" may mean that some kernel configs (such
as Debian/m68k) may need tweaking.
---
drivers/char/Kconfig | 5 +----
drivers/scsi/Kconfig | 6 +++---
drivers/scsi/atari_scsi.c | 8 ++++----
3 files changed, 8 insertions(+), 11 deletions(-)
Index: linux/drivers/char/Kconfig
===================================================================
@@ -875,9 +875,10 @@ static int __init atari_scsi_probe(strucif(ATARIHW_PRESENT(TT_SCSI)&&setup_sg_tablesize>=0)atari_scsi_template.sg_tablesize=setup_sg_tablesize;-if(setup_hostid>=0){+if(setup_hostid>=0)atari_scsi_template.this_id=setup_hostid&7;-}else{+#ifdef CONFIG_NVRAM+else/* Test if a host id is set in the NVRam */if(ATARIHW_PRESENT(TT_CLK)&&nvram_check_checksum()){unsignedcharb=nvram_read_byte(14);
@@ -888,8 +889,7 @@ static int __init atari_scsi_probe(strucif(b&0x80)atari_scsi_template.this_id=b&7;}-}-+#endif#ifdef REAL_DMA/* If running on a Falcon and if there's TT-Ram (i.e., more than one
From: Finn Thain <hidden> Date: 2015-05-31 01:18:10
Move the m68k-specific code elsewhere to make the driver generic.
Change the vmode calculation from logical OR to bitwise OR, since it is
obviously wrong.
Signed-off-by: Finn Thain <redacted>
---
BTW, I didn't change the SCSI ID location in NVRAM. This code says 16
whereas atari_scsi says 14. Which one is correct?
---
arch/m68k/atari/Makefile | 2
arch/m68k/atari/nvram.c | 255 ++++++++++++++++++++++++++++++++++++++++++
drivers/char/nvram.c | 280 +++++------------------------------------------
3 files changed, 292 insertions(+), 245 deletions(-)
Index: linux/arch/m68k/atari/nvram.c
===================================================================
@@ -0,0 +1,255 @@+/*+*CMOS/NV-RAMdriverforAtari.Adaptedfromdrivers/char/nvram.c.+*Copyright(C)1997RomanHodek<Roman.Hodek@informatik.uni-erlangen.de>+*ideabyandwithhelpfromRichardJelinek<rj@suse.de>+*Portionscopyright(c)2001,2002SunMicrosystems(thockin@sun.com)+*FurthercontributionsfromCesarBarros,ErikGilling,TimHockinand+*WimVanSebroeck.+*/++#include<linux/errno.h>+#include<linux/init.h>+#include<linux/mc146818rtc.h>+#include<linux/module.h>+#include<linux/nvram.h>+#include<linux/proc_fs.h>+#include<linux/seq_file.h>+#include<linux/spinlock.h>+#include<linux/types.h>+#include<asm/atarihw.h>+#include<asm/atariints.h>++#define NVRAM_BYTES 50++/* It is worth noting that these functions all access bytes of general+*purposememoryintheNVRAM-thatistosay,theyalladdthe+*NVRAM_FIRST_BYTEoffset.PassthemoffsetsintoNVRAMasifyoudidnot+*knowabouttheRTCcruft.+*/++/* Note that *all* calls to CMOS_READ and CMOS_WRITE must be done with+*rtc_lockheld.Duetotheindex-port/data-portdesignoftheRTC,we+*don'twanttwodifferentthingstryingtogettoitatonce.(e.g.the+*periodic11minsyncfromkernel/time/ntp.cvs.thisdriver.)+*/++unsignedchar__nvram_read_byte(inti)+{+returnCMOS_READ(NVRAM_FIRST_BYTE+i);+}++unsignedcharnvram_read_byte(inti)+{+unsignedlongflags;+unsignedcharc;++spin_lock_irqsave(&rtc_lock,flags);+c=__nvram_read_byte(i);+spin_unlock_irqrestore(&rtc_lock,flags);+returnc;+}+EXPORT_SYMBOL(nvram_read_byte);++/* This races nicely with trying to read with checksum checking */+void__nvram_write_byte(unsignedcharc,inti)+{+CMOS_WRITE(c,NVRAM_FIRST_BYTE+i);+}++voidnvram_write_byte(unsignedcharc,inti)+{+unsignedlongflags;++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;theseareattheveryend.+*/+#define ATARI_CKS_RANGE_START 0+#define ATARI_CKS_RANGE_END 47+#define ATARI_CKS_LOC 48++int__nvram_check_checksum(void)+{+inti;+unsignedcharsum=0;++for(i=ATARI_CKS_RANGE_START;i<=ATARI_CKS_RANGE_END;++i)+sum+=__nvram_read_byte(i);+return(__nvram_read_byte(ATARI_CKS_LOC)==(~sum&0xff))&&+(__nvram_read_byte(ATARI_CKS_LOC+1)==(sum&0xff));+}++intnvram_check_checksum(void)+{+unsignedlongflags;+intrv;++spin_lock_irqsave(&rtc_lock,flags);+rv=__nvram_check_checksum();+spin_unlock_irqrestore(&rtc_lock,flags);+returnrv;+}+EXPORT_SYMBOL(nvram_check_checksum);++staticvoid__nvram_set_checksum(void)+{+inti;+unsignedcharsum=0;++for(i=ATARI_CKS_RANGE_START;i<=ATARI_CKS_RANGE_END;++i)+sum+=__nvram_read_byte(i);+__nvram_write_byte(~sum,ATARI_CKS_LOC);+__nvram_write_byte(sum,ATARI_CKS_LOC+1);+}++#ifdef CONFIG_PROC_FS+staticstruct{+unsignedcharval;+char*name;+}boot_prefs[]={+{0x80,"TOS"},+{0x40,"ASV"},+{0x20,"NetBSD (?)"},+{0x10,"Linux"},+{0x00,"unspecified"},+};++staticchar*languages[]={+"English (US)",+"German",+"French",+"English (UK)",+"Spanish",+"Italian",+"6 (undefined)",+"Swiss (French)",+"Swiss (German)",+};++staticchar*dateformat[]={+"MM%cDD%cYY",+"DD%cMM%cYY",+"YY%cMM%cDD",+"YY%cDD%cMM",+"4 (undefined)",+"5 (undefined)",+"6 (undefined)",+"7 (undefined)",+};++staticchar*colors[]={+"2","4","16","256","65536","??","??","??"+};++staticvoidatari_nvram_proc_read(unsignedchar*nvram,structseq_file*seq,+void*offset)+{+intchecksum;+inti;+unsignedvmode;++spin_lock_irq(&rtc_lock);+checksum=__nvram_check_checksum();+spin_unlock_irq(&rtc_lock);++seq_printf(seq,"Checksum status : %svalid\n",checksum?"":"not ");++seq_puts(seq,"Boot preference : ");+for(i=ARRAY_SIZE(boot_prefs)-1;i>=0;--i)+if(nvram[1]==boot_prefs[i].val){+seq_printf(seq,"%s\n",boot_prefs[i].name);+break;+}+if(i<0)+seq_printf(seq,"0x%02x (undefined)\n",nvram[1]);++seq_printf(seq,"SCSI arbitration : %s\n",+(nvram[16]&0x80)?"on":"off");+seq_puts(seq,"SCSI host ID : ");+if(nvram[16]&0x80)+seq_printf(seq,"%d\n",nvram[16]&7);+else+seq_puts(seq,"n/a\n");++if(!MACH_IS_FALCON)+return;++seq_puts(seq,"OS language : ");+if(nvram[6]<ARRAY_SIZE(languages))+seq_printf(seq,"%s\n",languages[nvram[6]]);+else+seq_printf(seq,"%u (undefined)\n",nvram[6]);+seq_puts(seq,"Keyboard language: ");+if(nvram[7]<ARRAY_SIZE(languages))+seq_printf(seq,"%s\n",languages[nvram[7]]);+else+seq_printf(seq,"%u (undefined)\n",nvram[7]);+seq_puts(seq,"Date format : ");+seq_printf(seq,dateformat[nvram[8]&7],+nvram[9]?nvram[9]:'/',nvram[9]?nvram[9]:'/');+seq_printf(seq,", %dh clock\n",nvram[8]&16?24:12);+seq_puts(seq,"Boot delay : ");+if(nvram[10]==0)+seq_puts(seq,"default");+else+seq_printf(seq,"%ds%s\n",nvram[10],+nvram[10]<8?", no memory test":"");++vmode=(nvram[14]<<8)|nvram[15];+seq_printf(seq,+"Video mode : %s colors, %d columns, %s %s monitor\n",+colors[vmode&7],vmode&8?80:40,+vmode&16?"VGA":"TV",vmode&32?"PAL":"NTSC");+seq_printf(seq,+" %soverscan, compat. mode %s%s\n",+vmode&64?"":"no ",vmode&128?"on":"off",+vmode&256?+(vmode&16?", line doubling":", half screen"):"");+}++staticintnvram_proc_read(structseq_file*seq,void*offset)+{+unsignedcharcontents[NVRAM_BYTES];+inti;++spin_lock_irq(&rtc_lock);+for(i=0;i<NVRAM_BYTES;++i)+contents[i]=__nvram_read_byte(i);+spin_unlock_irq(&rtc_lock);++atari_nvram_proc_read(contents,seq,offset);++return0;+}++staticintnvram_proc_open(structinode*inode,structfile*file)+{+returnsingle_open(file,nvram_proc_read,NULL);+}++staticconststructfile_operationsnvram_proc_fops={+.owner=THIS_MODULE,+.open=nvram_proc_open,+.read=seq_read,+.llseek=seq_lseek,+.release=single_release,+};++staticint__initatari_nvram_init(void)+{+if(!(MACH_IS_ATARI&&ATARIHW_PRESENT(TT_CLK)))+return-ENODEV;++if(!proc_create("driver/nvram",0,NULL,&nvram_proc_fops)){+pr_err("nvram: can't create /proc/driver/nvram\n");+return-ENOMEM;+}++return0;+}+device_initcall(atari_nvram_init);+#endif /* CONFIG_PROC_FS */
@@ -39,64 +32,6 @@#include<linux/module.h>#include<linux/nvram.h>--#define PC 1-#define ATARI 2--/* select machine configuration */-#if defined(CONFIG_ATARI)-# define MACH ATARI-#elif defined(__i386__) || defined(__x86_64__) || defined(__arm__) /* and ?? */-# define MACH PC-#else-# error Cannot build nvram driver for this machine configuration.-#endif--#if MACH == PC--/* RTC in a PC */-#define CHECK_DRIVER_INIT() 1--/* 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-#define NVRAM_BYTES (128-NVRAM_FIRST_BYTE)--#define mach_check_checksum pc_check_checksum-#define mach_set_checksum pc_set_checksum-#define mach_proc_infos pc_proc_infos--#endif--#if MACH == ATARI--/* Special parameters for RTC in Atari machines */-#include<asm/atarihw.h>-#include<asm/atariints.h>-#define RTC_PORT(x) (TT_RTC_BAS + 2*(x))-#define CHECK_DRIVER_INIT() (MACH_IS_ATARI && ATARIHW_PRESENT(TT_CLK))--#define NVRAM_BYTES 50--/* On Ataris, the checksum is over all bytes except the checksum bytes-*themselves;theseareattheveryend*/-#define ATARI_CKS_RANGE_START 0-#define ATARI_CKS_RANGE_END 47-#define ATARI_CKS_LOC 48--#define mach_check_checksum atari_check_checksum-#define mach_set_checksum atari_set_checksum-#define mach_proc_infos atari_proc_infos--#endif--/* Note that *all* calls to CMOS_READ and CMOS_WRITE must be done with-*rtc_lockheld.Duetotheindex-port/data-portdesignoftheRTC,we-*don'twanttwodifferentthingstryingtogettoitatonce.(e.g.the-*periodic11minsyncfromkernel/time/ntp.cvs.thisdriver.)-*/-#include<linux/types.h>#include<linux/errno.h>#include<linux/miscdevice.h>
@@ -119,12 +54,9 @@ static int nvram_open_mode; /* special o#define NVRAM_WRITE 1 /* opened for writing (exclusive) */#define NVRAM_EXCL 2 /* opened with O_EXCL */-staticintmach_check_checksum(void);-staticvoidmach_set_checksum(void);-#ifdef CONFIG_PROC_FS-staticvoidmach_proc_infos(unsignedchar*contents,structseq_file*seq,-void*offset);+staticvoidpc_nvram_proc_read(unsignedchar*contents,structseq_file*seq,+void*offset);#endif/*
@@ -138,6 +70,14 @@ static void mach_proc_infos(unsigned cha*knowabouttheRTCcruft.*/+#define NVRAM_BYTES (128 - NVRAM_FIRST_BYTE)++/* Note that *all* calls to CMOS_READ and CMOS_WRITE must be done with+*rtc_lockheld.Duetotheindex-port/data-portdesignoftheRTC,we+*don'twanttwodifferentthingstryingtogettoitatonce.(e.g.the+*periodic11minsyncfromkernel/time/ntp.cvs.thisdriver.)+*/+unsignedchar__nvram_read_byte(inti){returnCMOS_READ(NVRAM_FIRST_BYTE+i);
@@ -173,9 +113,22 @@ void nvram_write_byte(unsigned char c, i}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){-returnmach_check_checksum();+inti;+unsignedshortsum=0;+unsignedshortexpect;++for(i=PC_CKS_RANGE_START;i<=PC_CKS_RANGE_END;++i)+sum+=__nvram_read_byte(i);+expect=__nvram_read_byte(PC_CKS_LOC)<<8|+__nvram_read_byte(PC_CKS_LOC+1);+return(sum&0xffff)==expect;}EXPORT_SYMBOL(__nvram_check_checksum);
@@ -396,7 +355,7 @@ static int nvram_proc_read(struct seq_ficontents[i]=__nvram_read_byte(i);spin_unlock_irq(&rtc_lock);-mach_proc_infos(contents,seq,offset);+pc_nvram_proc_read(contents,seq,offset);return0;}
@@ -443,10 +402,6 @@ static int __init nvram_init(void){intret;-/* First test whether the driver should init at all */-if(!CHECK_DRIVER_INIT())-return-ENODEV;-ret=misc_register(&nvram_dev);if(ret){printk(KERN_ERR"nvram: can't misc_register on minor=%d\n",
From: Finn Thain <hidden> Date: 2015-05-31 01:18:19
Switch 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.
As before, when CONFIG_PPC && !CONFIG_PPC_PMAC, the IOC_NVRAM_GET_OFFSET
ioctl is unimplemented. For the nvram module, unimplemented ioctls return
-ENOTTY. Whereas, for the superseded generic_nvram module they would
return -EINVAL.
Signed-off-by: Finn Thain <redacted>
---
This ioctl change is visible to userspace code but only in an error path.
I didn't find any userspace code that uses the IOC_NVRAM_GET_OFFSET ioctl.
The change in the name of the module is also visible. 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.
---
arch/powerpc/Kconfig | 2 +-
arch/powerpc/kernel/setup_32.c | 2 +-
arch/powerpc/platforms/chrp/Makefile | 2 +-
arch/powerpc/platforms/chrp/setup.c | 2 +-
arch/powerpc/platforms/powermac/setup.c | 3 +--
drivers/char/Kconfig | 10 ++++++----
6 files changed, 11 insertions(+), 10 deletions(-)
Index: linux/arch/powerpc/Kconfig
===================================================================
@@ -178,7 +178,7 @@ config SYSVIPC_COMPATdefaulty# All PPC32s use generic nvram driver through ppc_md-configGENERIC_NVRAM+configHAVE_ARCH_NVRAM_OPSbooldefaultyifPPC32
From: Finn Thain <hidden> Date: 2015-05-31 01:18:26
Refactor 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 also
preserves the locking semantics such that "read if checksum valid" and
"write and update checksum" remain atomic operations.
PPC64 implements byte-range read/write methods which are similar to
file_operations struct methods. Other platforms provide only
byte-at-a-time functions. So the misc device prefers the former but
will fall back on the latter.
Signed-off-by: Finn Thain <redacted>
---
drivers/char/nvram.c | 162 +++++++++++++++++++++++++++++++++++----------------
1 file changed, 114 insertions(+), 48 deletions(-)
Index: linux/drivers/char/nvram.c
===================================================================
@@ -215,69 +255,95 @@ static loff_t nvram_misc_llseek(struct fstaticssize_tnvram_misc_read(structfile*file,char__user*buf,size_tcount,loff_t*ppos){-unsignedcharcontents[NVRAM_BYTES];-unsignedi=*ppos;-unsignedchar*tmp;--spin_lock_irq(&rtc_lock);+loff_ti;+char__user*p=buf;-if(!__nvram_check_checksum())-gotochecksum_err;--for(tmp=contents;count-->0&&i<NVRAM_BYTES;++i,++tmp)-*tmp=__nvram_read_byte(i);--spin_unlock_irq(&rtc_lock);--if(copy_to_user(buf,contents,tmp-contents))+if(!access_ok(VERIFY_WRITE,buf,count))return-EFAULT;+if(*ppos>=nvram_size)+return0;-*ppos=i;--returntmp-contents;+/* If the arch provided a byte range read op, use it. Otherwise+*fallbackonthebyte-at-a-timeaccessor.+*/+if(arch_nvram_ops.read!=NULL){+char*tmp;+ssize_tret;++count=min_t(size_t,count,nvram_size-*ppos);+count=min_t(size_t,count,PAGE_SIZE);++tmp=kmalloc(count,GFP_KERNEL);+if(!tmp)+return-ENOMEM;++ret=arch_nvram_ops.read(tmp,count,ppos);+if(ret<=0)+gotoout;++if(copy_to_user(buf,tmp,ret)){+*ppos-=ret;+ret=-EFAULT;+}++out:+kfree(tmp);+returnret;+}-checksum_err:-spin_unlock_irq(&rtc_lock);-return-EIO;+for(i=*ppos;count>0&&i<nvram_size;++i,++p,--count)+if(__put_user(arch_nvram_ops.read_byte(i),p))+return-EFAULT;+*ppos=i;+returnp-buf;}staticssize_tnvram_misc_write(structfile*file,constchar__user*buf,size_tcount,loff_t*ppos){-unsignedcharcontents[NVRAM_BYTES];-unsignedi=*ppos;-unsignedchar*tmp;--if(i>=NVRAM_BYTES)-return0;/* 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 */+loff_ti;+constchar__user*p=buf;-if(copy_from_user(contents,buf,count))+if(!access_ok(VERIFY_READ,buf,count))return-EFAULT;+if(*ppos>=nvram_size)+return0;-spin_lock_irq(&rtc_lock);--if(!__nvram_check_checksum())-gotochecksum_err;--for(tmp=contents;count--;++i,++tmp)-__nvram_write_byte(*tmp,i);--__nvram_set_checksum();+/* If the arch provided a byte range write op, use it. Otherwise+*fallbackonthebyte-at-a-timeaccessor.+*/+if(arch_nvram_ops.write!=NULL){+char*tmp;+ssize_tret;++count=min_t(size_t,count,nvram_size-*ppos);+count=min_t(size_t,count,PAGE_SIZE);++tmp=kmalloc(count,GFP_KERNEL);+if(!tmp)+return-ENOMEM;++if(copy_from_user(tmp,buf,count)){+ret=-EFAULT;+gotoout;+}++ret=arch_nvram_ops.write(tmp,count,ppos);++out:+kfree(tmp);+returnret;+}-spin_unlock_irq(&rtc_lock);+for(i=*ppos;count>0&&i<nvram_size;++i,++p,--count){+charc;+if(__get_user(c,p))+return-EFAULT;+arch_nvram_ops.write_byte(c,i);+}*ppos=i;--returntmp-contents;--checksum_err:-spin_unlock_irq(&rtc_lock);-return-EIO;+returnp-buf;}staticlongnvram_misc_ioctl(structfile*file,unsignedintcmd,
From: Finn Thain <hidden> Date: 2015-05-31 01:18:35
Atari RTC NVRAM has a checksum so implement the remaining arch_nvram_ops
methods for the set_checksum and initialize ioctls. Enable
CONFIG_HAVE_ARCH_NVRAM_OPS.
Signed-off-by: Finn Thain <redacted>
---
This re-enables the nvram module for Atari.
---
arch/m68k/Kconfig | 3 +++
arch/m68k/atari/nvram.c | 24 ++++++++++++++++++++++++
drivers/char/Kconfig | 2 +-
3 files changed, 28 insertions(+), 1 deletion(-)
Index: linux/arch/m68k/atari/nvram.c
===================================================================
From: Finn Thain <hidden> Date: 2015-05-31 01:18:57
Add the powerpc-specific sync() method to struct nvram_ops and implement
the corresponding ioctl in the nvram module. This allows the nvram module
to replace the generic_nvram module.
Signed-off-by: Finn Thain <redacted>
---
On PPC32, the IOC_NVRAM_SYNC ioctl call always returns 0, even for those
platforms that don't implement ppc_md.nvram_sync. This patch retains
that quirk. It might be better to return failure (which is what PPC64 does).
---
arch/powerpc/include/asm/nvram.h | 3 ---
arch/powerpc/kernel/setup_32.c | 6 +++---
drivers/char/generic_nvram.c | 2 +-
drivers/char/nvram.c | 38 ++++++++++++++++++++++++++++++++++++++
include/linux/nvram.h | 4 ++++
5 files changed, 46 insertions(+), 7 deletions(-)
Index: linux/drivers/char/nvram.c
===================================================================
@@ -374,6 +410,7 @@ static int nvram_misc_open(struct inodereturn-EBUSY;}+#ifndef CONFIG_PPC/* Prevent multiple writers if the set_checksum ioctl is implemented. */if((arch_nvram_ops.set_checksum!=NULL)&&(file->f_mode&FMODE_WRITE)&&
@@ -381,6 +418,7 @@ static int nvram_misc_open(struct inodespin_unlock(&nvram_state_lock);return-EBUSY;}+#endifif(file->f_flags&O_EXCL)nvram_open_mode|=NVRAM_EXCL;
From: Finn Thain <hidden> Date: 2015-05-31 01:20:21
Make use of arch_nvram_ops in the thinkpad_acpi driver so that the
nvram_* function exports can be removed.
This patch series was tested on a ThinkPad T43.
Signed-off-by: Finn Thain <redacted>
---
drivers/platform/x86/thinkpad_acpi.c | 20 ++++++++++----------
1 file changed, 10 insertions(+), 10 deletions(-)
Index: linux/drivers/platform/x86/thinkpad_acpi.c
===================================================================
From: Finn Thain <hidden> Date: 2015-05-31 01:20:28
Implement arch_nvram_ops for PPC32 and make use of it in the generic_nvram
misc device module so that the nvram_* function exports can be removed.
Signed-off-by: Finn Thain <redacted>
---
arch/powerpc/include/asm/nvram.h | 3 ---
arch/powerpc/kernel/setup_32.c | 10 +++++++---
drivers/char/generic_nvram.c | 24 ++++++++++++------------
3 files changed, 19 insertions(+), 18 deletions(-)
Index: linux/arch/powerpc/include/asm/nvram.h
===================================================================
From: Finn Thain <hidden> Date: 2015-05-31 01:20:31
The drivers/char/nvram module has previously only supported 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 suitable NVRAM.
Signed-off-by: Finn Thain <redacted>
---
drivers/char/nvram.c | 61 ++++++++++++++++++++++++++++----------------------
include/linux/nvram.h | 2 +
2 files changed, 37 insertions(+), 26 deletions(-)
Index: linux/drivers/char/nvram.c
===================================================================
@@ -272,26 +283,19 @@ checksum_err:staticlongnvram_misc_ioctl(structfile*file,unsignedintcmd,unsignedlongarg){-inti;+longret=-ENOTTY;switch(cmd){-caseNVRAM_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);+if(arch_nvram_ops.initialize!=NULL)+ret=arch_nvram_ops.initialize();mutex_unlock(&nvram_mutex);-return0;-+break;caseNVRAM_SETCKS:/* just set checksum, contents unchanged (maybe useful after*checksumgarbagedsomehow...)*/
@@ -299,24 +303,29 @@ static long nvram_misc_ioctl(struct filereturn-EACCES;mutex_lock(&nvram_mutex);-spin_lock_irq(&rtc_lock);-__nvram_set_checksum();-spin_unlock_irq(&rtc_lock);+if(arch_nvram_ops.set_checksum!=NULL)+ret=arch_nvram_ops.set_checksum();mutex_unlock(&nvram_mutex);-return0;--default:-return-ENOTTY;+break;}+returnret;}staticintnvram_misc_open(structinode*inode,structfile*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;}
From: Finn Thain <hidden> Date: 2015-05-31 01:20:52
Make use of arch_nvram_ops in device drivers so that the nvram_*
function exports can be removed.
Since they are no longer global symbols, rename the PPC32 nvram_* functions
appropriately.
Add the missing CONFIG_NVRAM test to imsttfb to avoid a build failure.
Signed-off-by: Finn Thain <redacted>
---
arch/powerpc/kernel/setup_32.c | 8 ++++----
drivers/char/generic_nvram.c | 4 ++--
drivers/video/fbdev/controlfb.c | 4 ++--
drivers/video/fbdev/imsttfb.c | 7 +++----
drivers/video/fbdev/matrox/matroxfb_base.c | 2 +-
drivers/video/fbdev/platinumfb.c | 4 ++--
drivers/video/fbdev/valkyriefb.c | 4 ++--
7 files changed, 16 insertions(+), 17 deletions(-)
Index: linux/arch/powerpc/kernel/setup_32.c
===================================================================
@@ -415,7 +415,7 @@ static int __init init_control(struct fb/* Try to pick a video mode out of NVRAM if we have one. */#ifdef CONFIG_NVRAMif(default_cmode==CMODE_NVRAM){-cmode=nvram_read_byte(NV_CMODE);+cmode=arch_nvram_ops.read_byte(NV_CMODE);if(cmode<CMODE_8||cmode>CMODE_32)cmode=CMODE_8;}else
@@ -423,7 +423,7 @@ static int __init init_control(struct fbcmode=default_cmode;#ifdef CONFIG_NVRAMif(default_vmode==VMODE_NVRAM){-vmode=nvram_read_byte(NV_VMODE);+vmode=arch_nvram_ops.read_byte(NV_VMODE);if(vmode<1||vmode>VMODE_MAX||control_mac_modes[vmode-1].m[full]<cmode){sense=read_control_sense(p);
@@ -349,7 +349,7 @@ static int platinum_init_fb(struct fb_inprintk(KERN_INFO"platinumfb: Monitor sense value = 0x%x, ",sense);if(default_vmode==VMODE_NVRAM){#ifdef CONFIG_NVRAM-default_vmode=nvram_read_byte(NV_VMODE);+default_vmode=arch_nvram_ops.read_byte(NV_VMODE);if(default_vmode<=0||default_vmode>VMODE_MAX||!platinum_reg_init[default_vmode-1])#endif
@@ -362,7 +362,7 @@ static int platinum_init_fb(struct fb_indefault_vmode=VMODE_640_480_60;#ifdef CONFIG_NVRAMif(default_cmode==CMODE_NVRAM)-default_cmode=nvram_read_byte(NV_CMODE);+default_cmode=arch_nvram_ops.read_byte(NV_CMODE);#endifif(default_cmode<CMODE_8||default_cmode>CMODE_32)default_cmode=CMODE_8;
@@ -287,7 +287,7 @@ static void __init valkyrie_choose_mode(/* 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){-default_vmode=nvram_read_byte(NV_VMODE);+default_vmode=arch_nvram_ops.read_byte(NV_VMODE);if(default_vmode<=0||default_vmode>VMODE_MAX||!valkyrie_reg_init[default_vmode-1])
From: Finn Thain <hidden> Date: 2015-05-31 01:20:59
Drivers now use the arch_nvram_ops calls so remove the function exports and
prototypes. nvram_check_checksum() is unused so remove it.
Signed-off-by: Finn Thain <redacted>
---
arch/m68k/atari/nvram.c | 6 +++---
drivers/char/nvram.c | 27 +++++----------------------
include/linux/nvram.h | 8 --------
3 files changed, 8 insertions(+), 33 deletions(-)
Index: linux/drivers/char/nvram.c
===================================================================
@@ -98,16 +97,14 @@ unsigned char nvram_read_byte(int i)spin_unlock_irqrestore(&rtc_lock,flags);returnc;}-EXPORT_SYMBOL(nvram_read_byte);/* This races nicely with trying to read with checksum checking (nvram_read) */-void__nvram_write_byte(unsignedcharc,inti)+staticvoid__nvram_write_byte(unsignedcharc,inti){CMOS_WRITE(c,NVRAM_FIRST_BYTE+i);}-EXPORT_SYMBOL(__nvram_write_byte);-voidnvram_write_byte(unsignedcharc,inti)+staticvoidnvram_write_byte(unsignedcharc,inti){unsignedlongflags;
@@ -115,14 +112,13 @@ void nvram_write_byte(unsigned char c, 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)+staticint__nvram_check_checksum(void){inti;unsignedshortsum=0;
@@ -134,19 +130,6 @@ int __nvram_check_checksum(void)__nvram_read_byte(PC_CKS_LOC+1);return(sum&0xffff)==expect;}-EXPORT_SYMBOL(__nvram_check_checksum);--intnvram_check_checksum(void)-{-unsignedlongflags;-intrv;--spin_lock_irqsave(&rtc_lock,flags);-rv=__nvram_check_checksum();-spin_unlock_irqrestore(&rtc_lock,flags);-returnrv;-}-EXPORT_SYMBOL(nvram_check_checksum);staticvoid__nvram_set_checksum(void){
@@ -3,14 +3,6 @@#include<uapi/linux/nvram.h>-/* __foo is foo without grabbing the rtc_lock - get it yourself */-externunsignedchar__nvram_read_byte(inti);-externunsignedcharnvram_read_byte(inti);-externvoid__nvram_write_byte(unsignedcharc,inti);-externvoidnvram_write_byte(unsignedcharc,inti);-externint__nvram_check_checksum(void);-externintnvram_check_checksum(void);-structnvram_ops{ssize_t(*read)(char*,size_t,loff_t*);ssize_t(*write)(char*,size_t,loff_t*);
@@ -33,13 +33,13 @@*periodic11minsyncfromkernel/time/ntp.cvs.thisdriver.)*/-unsignedchar__nvram_read_byte(inti)+staticunsignedchar__nvram_read_byte(inti){returnCMOS_READ(NVRAM_FIRST_BYTE+i);}/* This races nicely with trying to read with checksum checking */-void__nvram_write_byte(unsignedcharc,inti)+staticvoid__nvram_write_byte(unsignedcharc,inti){CMOS_WRITE(c,NVRAM_FIRST_BYTE+i);}
From: Finn Thain <hidden> Date: 2015-05-31 01:21:09
Different platforms and architectures offer different NVRAM sizes and
access methods. E.g. PPC32 has byte-at-a-time read/write functions whereas
PPC64 has byte-range read/write functions. Adopt the nvram_ops struct so
the nvram module can call such functions as are defined by the various
platforms and architectures.
Signed-off-by: Finn Thain <redacted>
---
The #ifdefs here restrict the procfs and checksumming code to those
architectures with PC-style RTC NVRAM. There may be a better place for
that code but it's an open question. See https://lkml.org/lkml/2015/2/3/22
The procfs code here, if irrelevant to ARM platforms, could be moved to
arch/x86 (like the earlier patch does for m68k code) and the nvram ops
could implemented and exported by the rtc-cmos driver instead. This
would eliminate these #ifdefs.
---
drivers/char/nvram.c | 30 +++++++++++++++++++++++++++---
include/linux/nvram.h | 2 ++
2 files changed, 29 insertions(+), 3 deletions(-)
Index: linux/drivers/char/nvram.c
===================================================================
@@ -51,9 +51,12 @@ static DEFINE_MUTEX(nvram_mutex);staticDEFINE_SPINLOCK(nvram_state_lock);staticintnvram_open_cnt;/* #times opened */staticintnvram_open_mode;/* special open modes */+staticssize_tnvram_size;#define NVRAM_WRITE 1 /* opened for writing (exclusive) */#define NVRAM_EXCL 2 /* opened with O_EXCL */+#if defined(CONFIG_X86) || defined(CONFIG_ARM)+/**Thesefunctionsareprovidedtobecalledinternallyorbyotherpartsof*thekernel.It'suptothecallertoensurecorrectchecksumbeforereading
@@ -295,11 +298,31 @@ static void via_pram_command(int command#if IS_ENABLED(CONFIG_NVRAM)staticunsignedcharvia_pram_read_byte(intoffset){-return0;+unsignedchartemp;+intaddr=((offset&0xE0)<<3)|((offset&0x1F)<<2);++/* Use RTC command 0x38 for XPRAM access, as per MESS source code */+via_pram_command(addr|0x3800|0x8001,&temp);++returntemp;}staticvoidvia_pram_write_byte(unsignedchardata,intoffset){+unsignedchartemp;+intaddr=((offset&0xE0)<<3)|((offset&0x1F)<<2);++/* Clear the write protect bit */+temp=0x55;+via_pram_command(0x34|0x01,&temp);++/* Write the byte to XPRAM */+temp=data;+via_pram_command(0x3800|0x0001|addr,&temp);++/* Set the write protect bit */+temp=0xD5;+via_pram_command(0x34|0x01,&temp);}#endif /* CONFIG_NVRAM */
From: Finn Thain <hidden> Date: 2015-05-31 01:21:30
Add 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 used to implement arch_nvram_ops.get_size()
Since we are addressing inconsistencies here, also rename chrp_nvram_read
and chrp_nvram_write, which break the naming convention used across
PowerPC platforms for NVRAM accessor functions.
Signed-off-by: Finn Thain <redacted>
---
arch/powerpc/platforms/chrp/nvram.c | 14 ++++++++++----
arch/powerpc/platforms/powermac/nvram.c | 9 +++++++++
2 files changed, 19 insertions(+), 4 deletions(-)
Index: linux/arch/powerpc/platforms/chrp/nvram.c
===================================================================
@@ -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;}elseif(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;}elseif(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;}elseif(nvram_naddrs==0&&sys_ctrler==SYS_CTRLER_PMU){#ifdef CONFIG_ADB_PMUnvram_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");
From: Finn Thain <hidden> Date: 2015-05-31 01:21:38
By implementing an arch_nvram_ops struct, any platform can re-use the
drivers/char/nvram module without needing any arch-specific code
in that module. Atari does so here.
Atari has one user of nvram_check_checksum() whereas the other platforms
(i.e. x86 and ARM platforms) have none at all. Replace this
validate-checksum-and-read-byte sequence with the equivalent
rtc_nvram_ops.read() call and remove the now unused functions.
Signed-off-by: Finn Thain <redacted>
---
The advantage of the new ops struct over the old global nvram_* functions
is that the misc device module can be shared by different platforms
without requiring every platform to implement every nvram_* function.
E.g. only RTC "CMOS" NVRAMs have a checksum and only PowerPC platforms
have a "sync" ioctl.
---
arch/m68k/atari/nvram.c | 89 ++++++++++++++++++++++++++++------------------
drivers/scsi/atari_scsi.c | 8 ++--
include/linux/nvram.h | 9 ++++
3 files changed, 70 insertions(+), 36 deletions(-)
Index: linux/arch/m68k/atari/nvram.c
===================================================================
@@ -38,33 +38,12 @@ unsigned char __nvram_read_byte(int i)returnCMOS_READ(NVRAM_FIRST_BYTE+i);}-unsignedcharnvram_read_byte(inti)-{-unsignedlongflags;-unsignedcharc;--spin_lock_irqsave(&rtc_lock,flags);-c=__nvram_read_byte(i);-spin_unlock_irqrestore(&rtc_lock,flags);-returnc;-}-EXPORT_SYMBOL(nvram_read_byte);-/* This races nicely with trying to read with checksum checking */void__nvram_write_byte(unsignedcharc,inti){CMOS_WRITE(c,NVRAM_FIRST_BYTE+i);}-voidnvram_write_byte(unsignedcharc,inti)-{-unsignedlongflags;--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;theseareattheveryend.*/
@@ -83,18 +62,6 @@ int __nvram_check_checksum(void)(__nvram_read_byte(ATARI_CKS_LOC+1)==(sum&0xff));}-intnvram_check_checksum(void)-{-unsignedlongflags;-intrv;--spin_lock_irqsave(&rtc_lock,flags);-rv=__nvram_check_checksum();-spin_unlock_irqrestore(&rtc_lock,flags);-returnrv;-}-EXPORT_SYMBOL(nvram_check_checksum);-staticvoid__nvram_set_checksum(void){inti;
@@ -880,13 +880,15 @@ static int __init atari_scsi_probe(struc#ifdef CONFIG_NVRAMelse/* Test if a host id is set in the NVRam */-if(ATARIHW_PRESENT(TT_CLK)&&nvram_check_checksum()){-unsignedcharb=nvram_read_byte(14);+if(ATARIHW_PRESENT(TT_CLK)){+unsignedcharb;+loff_toffset=14;+ssize_tcount=arch_nvram_ops.read(&b,1,&offset);/* Arbitration enabled? (for TOS)*Ifyes,useconfiguredhostID*/-if(b&0x80)+if((count==1)&&(b&0x80))atari_scsi_template.this_id=b&7;}#endif
From: Finn Thain <hidden> Date: 2015-05-31 01:21:43
The nvram_read_byte() and nvram_write_byte() definitions in asm/nvram.h
duplicate those in linux/nvram.h. Get rid of the former to prepare for
adoption of struct arch_nvram_ops (which is defined in linux/nvram.h for
general use).
Signed-off-by: Finn Thain <redacted>
---
arch/powerpc/include/asm/nvram.h | 3 ---
arch/powerpc/kernel/setup_32.c | 1 +
drivers/char/generic_nvram.c | 4 +++-
drivers/video/fbdev/matrox/matroxfb_base.c | 2 +-
4 files changed, 5 insertions(+), 5 deletions(-)
Index: linux/arch/powerpc/include/asm/nvram.h
===================================================================
From: Henrique de Moraes Holschuh <hmh@hmh.eng.br> Date: 2015-05-31 04:11:32
On Sun, 31 May 2015, Finn Thain wrote:
Make use of arch_nvram_ops in the thinkpad_acpi driver so that the
nvram_* function exports can be removed.
This patch series was tested on a ThinkPad T43.
Can you describe how you did the testing? A specific procedure is required
to test the hotkey NVRAM polling codepaths (which will read several NVRAM
bytes @10Hz by default) in a T43...
Signed-off-by: Finn Thain <redacted>
The patch looks correct, so I don't expect any problems.
Provided that your test procedure did enable hotkey NVRAM polling in the T43
and your hotkeys all still worked fine, you have my Acked-by.
@@ -6794,13 +6794,13 @@ static void tpacpi_volume_checkpoint_nvrif(unlikely(!acpi_ec_read(TP_EC_AUDIO,&lec)))gotounlock;lec&=ec_mask;-b_nvram=nvram_read_byte(TP_NVRAM_ADDR_MIXER);+b_nvram=arch_nvram_ops.read_byte(TP_NVRAM_ADDR_MIXER);if(lec!=(b_nvram&ec_mask)){/* NVRAM needs update */b_nvram&=~ec_mask;b_nvram|=lec;-nvram_write_byte(b_nvram,TP_NVRAM_ADDR_MIXER);+arch_nvram_ops.write_byte(b_nvram,TP_NVRAM_ADDR_MIXER);dbg_printk(TPACPI_DBG_MIXER,"updated NVRAM mixer status to 0x%02x (0x%02x)\n",(unsignedint)lec,(unsignedint)b_nvram);
--
"One disk to rule them all, One disk to find them. One disk to bring
them all and in the darkness grind them. In the Land of Redmond
where the shadows lie." -- The Silicon Valley Tarot
Henrique Holschuh
From: Finn Thain <hidden> Date: 2015-05-31 06:16:10
On Sun, 31 May 2015, Henrique de Moraes Holschuh wrote:
On Sun, 31 May 2015, Finn Thain wrote:
quoted
Make use of arch_nvram_ops in the thinkpad_acpi driver so that the
nvram_* function exports can be removed.
This patch series was tested on a ThinkPad T43.
Can you describe how you did the testing? A specific procedure is
required to test the hotkey NVRAM polling codepaths (which will read
several NVRAM bytes @10Hz by default) in a T43...
quoted
Signed-off-by: Finn Thain <redacted>
The patch looks correct, so I don't expect any problems.
Provided that your test procedure did enable hotkey NVRAM polling in the
T43 and your hotkeys all still worked fine, you have my Acked-by.
The procedure I used was this,
1. $ xev
2. # rmmod thinkpad_acpi
3. Press <Access IBM> key and confirm that xev does not report any
events.
4. # modprobe thinkpad_acpi
5. Press <Access IBM> key and confirm that xev now reports the key press
events.
Is this sufficient?
Regards,
Finn
From: Henrique de Moraes Holschuh <hmh@hmh.eng.br> Date: 2015-05-31 14:34:36
On Sun, 31 May 2015, Finn Thain wrote:
On Sun, 31 May 2015, Henrique de Moraes Holschuh wrote:
quoted
On Sun, 31 May 2015, Finn Thain wrote:
quoted
Make use of arch_nvram_ops in the thinkpad_acpi driver so that the
nvram_* function exports can be removed.
This patch series was tested on a ThinkPad T43.
Can you describe how you did the testing? A specific procedure is
required to test the hotkey NVRAM polling codepaths (which will read
several NVRAM bytes @10Hz by default) in a T43...
quoted
Signed-off-by: Finn Thain <redacted>
The patch looks correct, so I don't expect any problems.
Provided that your test procedure did enable hotkey NVRAM polling in the
T43 and your hotkeys all still worked fine, you have my Acked-by.
The procedure I used was this,
1. $ xev
2. # rmmod thinkpad_acpi
3. Press <Access IBM> key and confirm that xev does not report any
events.
4. # modprobe thinkpad_acpi
5. Press <Access IBM> key and confirm that xev now reports the key press
events.
Is this sufficient?
No. Please try:
modprobe thinkpad_acpi
echo 0xfb88c0 > /sys/devices/platform/thinkpad_acpi/hotkey_source_mask
test the hotkeys. Please test several of them, as not all of them are
available through NVRAM polling... at least Fn+SPACE, Fn+F1..FN+F12
Please test the brightness keys. In the T43 we use "direct EC mode", which
depends on the NVRAM to sync with the SMBIOS firmware.
to reset the driver to normal mode, it is enough to do this:
echo 0 > /sys/devices/platform/thinkpad_acpi/hotkey_source_mask
--
"One disk to rule them all, One disk to find them. One disk to bring
them all and in the darkness grind them. In the Land of Redmond
where the shadows lie." -- The Silicon Valley Tarot
Henrique Holschuh
On Sun, May 31, 2015 at 3:01 AM, Finn Thain [off-list ref] wrote:
Signed-off-by: Finn Thain <redacted>
Removal seems to be forgotten by full-history-linux
commit 17c6f4635bea74e110ab3558d408c9cd218c568a
Author: Benjamin Herrenschmidt [off-list ref]
Date: Fri Feb 6 14:20:56 2004 +1100
ppc32: Rework nvram management
move drivers/macintosh/nvram.c to drivers/char/generic_nvram.c,
update platform hooks,
fix powermac nvram driver for newer machines
Acked-by: Geert Uytterhoeven <geert@linux-m68k.org>
Gr{oetje,eeting}s,
Geert
--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org
In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
-- Linus Torvalds
Hi Finn,
On Sun, May 31, 2015 at 3:01 AM, Finn Thain [off-list ref] wrote:
A multi-platform kernel binary needs to decide at run-time how to dispatch
the arch_nvram_ops calls. Add platform-independent arch_nvram_ops, for use
when multiple platform-specific NVRAM ops implementations are needed.
Can't you just fill in the mach specific pointers in the generic structure,
and be done with it?
If you handle this right, I think you can do without the temporary "def_bool
(ATARI && !MAC) || (MAC && !ATARI)" in "[RFC 22/24] m68k/mac: Adopt nvram
module", too.
Thanks!
Gr{oetje,eeting}s,
Geert
--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org
In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
-- Linus Torvalds
We could eliminate the Atari and Mac definitions of arch_nvram_ops, and
define the struct only in arch/m68k/kernel/setup_mm.c -- at the cost of
some bloat (see below).
Isn't this handled already by the nvram core, based on the available
operations in nvram_ops?
A multi-platform kernel can't set inappropriate ops to NULL at run-time,
because the struct is const. (Maybe we can on m68k? That doesn't mean it
is good style.)
There isn't any nvram core as such. The nvram misc device is just one of
many callers of the functions in the ops struct.
(The read_byte and write_byte loops above that also appear in the misc
device are different in that latter loops involve userspace. So I have not
factored them out. If it were possible to refactor, the shared code would
have to go into include/linux/nvram.h.)
Same for the other nvram abstractions in this file.
Again, a multi-platform kernel needs them. E.g. a kernel eith CONFIG_ATARI
&& CONFIG_MAC has to support checksummed Atari NVRAM. If you boot it on a
Mac, you need the m68k_nvram_set_checksum() and m68k_nvram_initialize()
stubs.
Whereas, a single-platform kernel, having CONFIG_MAC && !CONFIG_ATARI, you
don't define the .set_checksum and .initialize ops at all. (Like any PPC32
kernel, BTW.)
Can't you just fill in the mach specific pointers in the generic
structure, and be done with it?
Not at compile-time. Hence the mach-independent functions, i.e. the
wrapper functions that dispatch to the mach-specific functions.
The wrappers and stubs only add bloat in a single-platform kernel binary.
I avoided this by use of the #ifdefs you objected to above.
I suppose we could instead do, in arch/m68k/kernel/setup_mm.c, something
like the following.
+
+#if IS_ENABLED(CONFIG_NVRAM)
+#ifdef CONFIG_MAC
+static unsigned char m68k_nvram_read_byte(int addr)
+{
+ if (MACH_IS_MAC)
+ return mac_pram_read_byte(addr);
+ return 0xff;
+}
+
+static void m68k_nvram_write_byte(unsigned char val, int addr)
+{
+ if (MACH_IS_MAC)
+ mac_pram_write_byte(val, addr);
+}
+#endif
+
+#ifdef CONFIG_ATARI
+static ssize_t m68k_nvram_read(char *buf, size_t count, loff_t *ppos)
+{
+ if (MACH_IS_ATARI)
+ return atari_nvram_read(buf, count, ppos);
+ else if (MACH_IS_MAC) {
+ ssize_t size = mac_pram_get_size();
+ char *p = buf;
+ loff_t i;
+
+ for (i = *ppos; count > 0 && i < size; --count, ++i, ++p)
+ *p = mac_pram_read_byte(i);
+
+ *ppos = i;
+ return p - buf;
+ }
+ return -EINVAL;
+}
+
+static ssize_t m68k_nvram_write(char *buf, size_t count, loff_t *ppos)
+{
+ if (MACH_IS_ATARI)
+ return atari_nvram_write(buf, count, ppos);
+ else if (MACH_IS_MAC) {
+ ssize_t size = mac_pram_get_size();
+ char *p = buf;
+ loff_t i;
+
+ for (i = *ppos; count > 0 && i < size; --count, ++i, ++p)
+ mac_pram_write_byte(*p, i);
+
+ *ppos = i;
+ return p - buf;
+ }
+ return -EINVAL;
+}
+
+static long m68k_nvram_set_checksum(void)
+{
+ if (MACH_IS_ATARI)
+ return atari_nvram_set_checksum();
+ return -EINVAL;
+}
+
+static long m68k_nvram_initialize(void)
+{
+ if (MACH_IS_ATARI)
+ return atari_nvram_initialize();
+ return -EINVAL;
+}
+#endif
+
+const struct nvram_ops arch_nvram_ops = {
+ .get_size = m68k_nvram_get_size,
+#ifdef CONFIG_MAC
+ .read_byte = m68k_nvram_read_byte,
+ .write_byte = m68k_nvram_write_byte,
+#endif
+#ifdef CONFIG_ATARI
+ .read = m68k_nvram_read,
+ .write = m68k_nvram_write,
+ .set_checksum = m68k_nvram_set_checksum,
+ .initialize = m68k_nvram_initialize,
+#endif
+};
+EXPORT_SYMBOL(arch_nvram_ops);
+#endif /* CONFIG_NVRAM */
This would eliminate the conditional ops struct definitions in
arch/m68k/atari/nvram.c and in arch/m68k/mac/misc.c, and still avoid stubs
in single-platform kernels. OTOH, it does mean a single-platform kernel
binary gets pointless wrapper functions.
Is this better than the original submission?
If you handle this right, I think you can do without the temporary
"def_bool (ATARI && !MAC) || (MAC && !ATARI)" in "[RFC 22/24] m68k/mac:
Adopt nvram module", too.
From: Henrique de Moraes Holschuh <hmh@hmh.eng.br> Date: 2015-06-02 10:09:37
Test results were sent to me privately, and they are correct, so...
Acked-by: Henrique de Moraes Holschuh <hmh@hmh.eng.br>
On Sun, May 31, 2015, at 11:34, Henrique de Moraes Holschuh wrote:
On Sun, 31 May 2015, Finn Thain wrote:
quoted
On Sun, 31 May 2015, Henrique de Moraes Holschuh wrote:
quoted
On Sun, 31 May 2015, Finn Thain wrote:
quoted
Make use of arch_nvram_ops in the thinkpad_acpi driver so that the
nvram_* function exports can be removed.
This patch series was tested on a ThinkPad T43.
Can you describe how you did the testing? A specific procedure is
required to test the hotkey NVRAM polling codepaths (which will read
several NVRAM bytes @10Hz by default) in a T43...
quoted
Signed-off-by: Finn Thain <redacted>
The patch looks correct, so I don't expect any problems.
Provided that your test procedure did enable hotkey NVRAM polling in the
T43 and your hotkeys all still worked fine, you have my Acked-by.
The procedure I used was this,
1. $ xev
2. # rmmod thinkpad_acpi
3. Press <Access IBM> key and confirm that xev does not report any
events.
4. # modprobe thinkpad_acpi
5. Press <Access IBM> key and confirm that xev now reports the key press
events.
Is this sufficient?
No. Please try:
modprobe thinkpad_acpi
echo 0xfb88c0 > /sys/devices/platform/thinkpad_acpi/hotkey_source_mask
test the hotkeys. Please test several of them, as not all of them are
available through NVRAM polling... at least Fn+SPACE, Fn+F1..FN+F12
Please test the brightness keys. In the T43 we use "direct EC mode",
which
depends on the NVRAM to sync with the SMBIOS firmware.
to reset the driver to normal mode, it is enough to do this:
echo 0 > /sys/devices/platform/thinkpad_acpi/hotkey_source_mask
--
"One disk to rule them all, One disk to find them. One disk to bring
them all and in the darkness grind them. In the Land of Redmond
where the shadows lie." -- The Silicon Valley Tarot
Henrique Holschuh
From: Darren Hart <dvhart@infradead.org> Date: 2015-06-03 03:34:21
On Tue, Jun 02, 2015 at 07:09:28AM -0300, Henrique de Moraes Holschuh wrote:
Test results were sent to me privately, and they are correct, so...
Finn, unless there is some compelling reason not to - like they are MBs worth of
data, please submit these to the list in the future so we have them for
reference.
Acked-by: Henrique de Moraes Holschuh <hmh@hmh.eng.br>
I'm fine with the changes, but they need to be submitted with the other changes
as this one change cannot compile independently in my tree.
Finn, please work with whomever is pulling the series to include this in their
pull request.
Reviewed-by: Darren Hart <redacted>
--
Darren Hart
Intel Open Source Technology Center
From: Finn Thain <hidden> Date: 2015-06-03 07:38:30
On Tue, 2 Jun 2015, Darren Hart wrote:
On Tue, Jun 02, 2015 at 07:09:28AM -0300, Henrique de Moraes Holschuh
wrote:
quoted
Test results were sent to me privately, and they are correct, so...
Finn, unless there is some compelling reason not to - like they are MBs
worth of data, please submit these to the list in the future so we have
them for reference.
Sure. Those results were just confirmation that this patch series doesn't
affect input events read directly from
/dev/input/by-path/platform-thinkpad_acpi-event
given the the hotkey_source_mask settings discussed in this thread.
quoted
Acked-by: Henrique de Moraes Holschuh <hmh@hmh.eng.br>
I'm fine with the changes, but they need to be submitted with the other
changes as this one change cannot compile independently in my tree.
Finn, please work with whomever is pulling the series to include this in
their pull request.
From: Henrique de Moraes Holschuh <hmh@hmh.eng.br> Date: 2015-06-03 10:37:19
On Wed, Jun 3, 2015, at 00:34, Darren Hart wrote:
On Tue, Jun 02, 2015 at 07:09:28AM -0300, Henrique de Moraes Holschuh
wrote:
quoted
Test results were sent to me privately, and they are correct, so...
Finn, unless there is some compelling reason not to - like they are MBs
worth of
data, please submit these to the list in the future so we have them for
reference.
After I told him which exact bitmask to use on a T43 to test
hotkey_source_mask, his test results can be summarized as "I could see
no difference in behavior", which is *exactly* what I expected to
happen.
If anything went wrong with the thinkpad-acpi NVRAM code, you'd notice a
very large change in behavior (typical: hotkeys don't work, less
typical: random hotkey keypresses, hotkey press bursts, low responsivity
of hotkeys).
quoted
Acked-by: Henrique de Moraes Holschuh <hmh@hmh.eng.br>
I'm fine with the changes, but they need to be submitted with the other
changes
as this one change cannot compile independently in my tree.
Finn, please work with whomever is pulling the series to include this in
their
pull request.
Reviewed-by: Darren Hart <redacted>
--
"One disk to rule them all, One disk to find them. One disk to bring
them all and in the darkness grind them. In the Land of Redmond
where the shadows lie." -- The Silicon Valley Tarot
Henrique Holschuh
From: Darren Hart <dvhart@infradead.org> Date: 2015-06-04 05:14:22
On Wed, Jun 03, 2015 at 07:37:13AM -0300, Henrique de Moraes Holschuh wrote:
On Wed, Jun 3, 2015, at 00:34, Darren Hart wrote:
quoted
On Tue, Jun 02, 2015 at 07:09:28AM -0300, Henrique de Moraes Holschuh
wrote:
quoted
Test results were sent to me privately, and they are correct, so...
Finn, unless there is some compelling reason not to - like they are MBs
worth of
data, please submit these to the list in the future so we have them for
reference.
After I told him which exact bitmask to use on a T43 to test
hotkey_source_mask, his test results can be summarized as "I could see
no difference in behavior", which is *exactly* what I expected to
happen.
If anything went wrong with the thinkpad-acpi NVRAM code, you'd notice a
very large change in behavior (typical: hotkeys don't work, less
typical: random hotkey keypresses, hotkey press bursts, low responsivity
of hotkeys).
Perfect, thanks for the update so we have it recorded here on the list.
--
Darren Hart
Intel Open Source Technology Center