From e71d47dc2a6c9a1ec83f015c7c3dd87b635ffcda Mon Sep 17 00:00:00 2001 From: Helge Deller Date: Sat, 12 Aug 2023 23:21:08 +0200 Subject: parisc: lasi: Register LASI power-off feature as sys_off_handler Prefer the Linux kernel sys_off_handler functionality over a home-grown implementation. Signed-off-by: Helge Deller --- drivers/parisc/lasi.c | 28 +++++++++++----------------- 1 file changed, 11 insertions(+), 17 deletions(-) (limited to 'drivers') diff --git a/drivers/parisc/lasi.c b/drivers/parisc/lasi.c index 6ef621adb63a..d7331823255f 100644 --- a/drivers/parisc/lasi.c +++ b/drivers/parisc/lasi.c @@ -17,6 +17,7 @@ #include #include #include +#include #include #include @@ -145,23 +146,19 @@ static void __init lasi_led_init(unsigned long lasi_hpa) * 1 to PWR_ON_L in the Power Control Register * */ - -static unsigned long lasi_power_off_hpa __read_mostly; - -static void lasi_power_off(void) +static int lasi_power_off(struct sys_off_data *data) { - unsigned long datareg; + struct gsc_asic *lasi = data->cb_data; - /* calculate addr of the Power Control Register */ - datareg = lasi_power_off_hpa + 0x0000C000; + /* Power down the machine via Power Control Register */ + gsc_writel(0x02, lasi->hpa + 0x0000C000); - /* Power down the machine */ - gsc_writel(0x02, datareg); + /* might not be reached: */ + return NOTIFY_DONE; } static int __init lasi_init_chip(struct parisc_device *dev) { - extern void (*chassis_power_off)(void); struct gsc_asic *lasi; int ret; @@ -212,13 +209,10 @@ static int __init lasi_init_chip(struct parisc_device *dev) gsc_fixup_irqs(dev, lasi, lasi_choose_irq); - /* initialize the power off function */ - /* FIXME: Record the LASI HPA for the power off function. This should - * ensure that only the first LASI (the one controlling the power off) - * should set the HPA here */ - lasi_power_off_hpa = lasi->hpa; - chassis_power_off = lasi_power_off; - + /* register the LASI power off function */ + register_sys_off_handler(SYS_OFF_MODE_POWER_OFF, + SYS_OFF_PRIO_DEFAULT, lasi_power_off, lasi); + return ret; } -- cgit v1.2.3 From 8f01caf0c5c14b2dc086c766cf5321fbcdc40bd1 Mon Sep 17 00:00:00 2001 From: Helge Deller Date: Mon, 21 Aug 2023 17:29:18 +0200 Subject: parisc: Avoid ioremap() for same addresss in iosapic_register() The LBA has already called ioremap() to get it's virtual address, which can be used for the IOSAPIC as well. Avoid calling ioremap() again and just reuse the correct iomem address for the IOSAPIC. Signed-off-by: Helge Deller --- arch/parisc/include/asm/ropes.h | 2 +- drivers/parisc/iosapic.c | 4 ++-- drivers/parisc/lba_pci.c | 3 ++- 3 files changed, 5 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/arch/parisc/include/asm/ropes.h b/arch/parisc/include/asm/ropes.h index 8e51c775c80a..fd96706c7234 100644 --- a/arch/parisc/include/asm/ropes.h +++ b/arch/parisc/include/asm/ropes.h @@ -252,7 +252,7 @@ static inline int agp_mode_mercury(void __iomem *hpa) { ** fixup_irq is to initialize PCI IRQ line support and ** virtualize pcidev->irq value. To be called by pci_fixup_bus(). */ -extern void *iosapic_register(unsigned long hpa); +extern void *iosapic_register(unsigned long hpa, void __iomem *vaddr); extern int iosapic_fixup_irq(void *obj, struct pci_dev *pcidev); #define LBA_FUNC_ID 0x0000 /* function id */ diff --git a/drivers/parisc/iosapic.c b/drivers/parisc/iosapic.c index bcc1dae00780..27478e9f4e84 100644 --- a/drivers/parisc/iosapic.c +++ b/drivers/parisc/iosapic.c @@ -890,7 +890,7 @@ iosapic_rd_version(struct iosapic_info *isi) ** o allocate and initialize isi_vector[] ** o allocate irq region */ -void *iosapic_register(unsigned long hpa) +void *iosapic_register(unsigned long hpa, void __iomem *vaddr) { struct iosapic_info *isi = NULL; struct irt_entry *irte = irt_cell; @@ -919,7 +919,7 @@ void *iosapic_register(unsigned long hpa) return NULL; } - isi->addr = ioremap(hpa, 4096); + isi->addr = vaddr; isi->isi_hpa = hpa; isi->isi_version = iosapic_rd_version(isi); isi->isi_num_vectors = IOSAPIC_IRDT_MAX_ENTRY(isi->isi_version) + 1; diff --git a/drivers/parisc/lba_pci.c b/drivers/parisc/lba_pci.c index 702bfd64e6e1..9e22b117fb3a 100644 --- a/drivers/parisc/lba_pci.c +++ b/drivers/parisc/lba_pci.c @@ -1535,7 +1535,8 @@ lba_driver_probe(struct parisc_device *dev) } /* Tell I/O SAPIC driver we have a IRQ handler/region. */ - tmp_obj = iosapic_register(dev->hpa.start + LBA_IOSAPIC_BASE); + tmp_obj = iosapic_register(dev->hpa.start + LBA_IOSAPIC_BASE, + addr + LBA_IOSAPIC_BASE); /* NOTE: PCI devices (e.g. 103c:1005 graphics card) which don't ** have an IRT entry will get NULL back from iosapic code. -- cgit v1.2.3 From 358ad816e52d4253b38c2f312e6b1cbd89e0dbf7 Mon Sep 17 00:00:00 2001 From: Helge Deller Date: Fri, 25 Aug 2023 17:46:39 +0200 Subject: parisc: led: Reduce CPU overhead for disk & lan LED computation Older PA-RISC machines have LEDs which show the disk- and LAN-activity. The computation is done in software and takes quite some time, e.g. on a J6500 this may take up to 60% time of one CPU if the machine is loaded via network traffic. Since most people don't care about the LEDs, start with LEDs disabled and just show a CPU heartbeat LED. The disk and LAN LEDs can be turned on manually via /proc/pdc/led. Signed-off-by: Helge Deller Cc: --- drivers/parisc/led.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/parisc/led.c b/drivers/parisc/led.c index 8bdc5e043831..3737c1021f88 100644 --- a/drivers/parisc/led.c +++ b/drivers/parisc/led.c @@ -56,8 +56,8 @@ static int led_type __read_mostly = -1; static unsigned char lastleds; /* LED state from most recent update */ static unsigned int led_heartbeat __read_mostly = 1; -static unsigned int led_diskio __read_mostly = 1; -static unsigned int led_lanrxtx __read_mostly = 1; +static unsigned int led_diskio __read_mostly; +static unsigned int led_lanrxtx __read_mostly; static char lcd_text[32] __read_mostly; static char lcd_text_default[32] __read_mostly; static int lcd_no_led_support __read_mostly = 0; /* KittyHawk doesn't support LED on its LCD */ -- cgit v1.2.3 From 59bf860a97c152efff6b357009bb2016caa46552 Mon Sep 17 00:00:00 2001 From: Helge Deller Date: Sun, 27 Aug 2023 08:37:01 +0200 Subject: parisc: Makefile: Adjust order in which drivers should be loaded This is the order in which the drivers are initialized in setup.c. The order is important when the drivers are convertet to use the initcall_*() startup framework. Signed-off-by: Helge Deller --- drivers/parisc/Makefile | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/parisc/Makefile b/drivers/parisc/Makefile index 99fa6a89e0b9..69860a60bb7a 100644 --- a/drivers/parisc/Makefile +++ b/drivers/parisc/Makefile @@ -1,25 +1,27 @@ # SPDX-License-Identifier: GPL-2.0 # -# Makefile for most of the non-PCI devices in PA-RISC machines +# Makefile PCI and non-PCI devices in PA-RISC machines +# +# Keep the order below, e.g. +# - ccio before any potential subdevices +# - gsc is required before lasi and wax +# - asp and wax before the EISA adapters for the IRQ regions +# - EISA must come before PCI to be sure it gets IRQ region # -# I/O SAPIC is also on IA64 platforms. -# The two could be merged into a common source some day. obj-$(CONFIG_IOSAPIC) += iosapic.o obj-$(CONFIG_IOMMU_SBA) += sba_iommu.o obj-$(CONFIG_PCI_LBA) += lba_pci.o obj-$(CONFIG_IOMMU_CCIO) += ccio-dma.o obj-$(CONFIG_GSC) += gsc.o - -obj-$(CONFIG_HPPB) += hppb.o -obj-$(CONFIG_GSC_DINO) += dino.o obj-$(CONFIG_GSC_LASI) += lasi.o asp.o obj-$(CONFIG_GSC_WAX) += wax.o obj-$(CONFIG_EISA) += eisa.o eisa_enumerator.o eisa_eeprom.o +obj-$(CONFIG_HPPB) += hppb.o +obj-$(CONFIG_GSC_DINO) += dino.o obj-$(CONFIG_SUPERIO) += superio.o obj-$(CONFIG_CHASSIS_LCD_LED) += led.o obj-$(CONFIG_PDC_STABLE) += pdc_stable.o obj-y += power.o - -- cgit v1.2.3 From 07c34e9fdcda868ef33c234e403b88dfb4aa6d8c Mon Sep 17 00:00:00 2001 From: Helge Deller Date: Sun, 27 Aug 2023 08:43:52 +0200 Subject: parisc: dino: Convert dino PCI bus driver to use arch_initcall() Signed-off-by: Helge Deller --- arch/parisc/include/asm/processor.h | 1 - arch/parisc/kernel/setup.c | 4 ---- drivers/parisc/dino.c | 6 +++--- 3 files changed, 3 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/arch/parisc/include/asm/processor.h b/arch/parisc/include/asm/processor.h index e132b2819fc9..275456ea7758 100644 --- a/arch/parisc/include/asm/processor.h +++ b/arch/parisc/include/asm/processor.h @@ -317,7 +317,6 @@ extern void gsc_init(void); extern void processor_init(void); extern void ccio_init(void); extern void hppb_init(void); -extern void dino_init(void); extern void iosapic_init(void); extern void lba_init(void); extern void sba_init(void); diff --git a/arch/parisc/kernel/setup.c b/arch/parisc/kernel/setup.c index 3e95b5417a50..e993ce617166 100644 --- a/arch/parisc/kernel/setup.c +++ b/arch/parisc/kernel/setup.c @@ -311,10 +311,6 @@ static int __init parisc_init(void) hppb_init(); #endif -#if defined(CONFIG_GSC_DINO) - dino_init(); -#endif - #ifdef CONFIG_CHASSIS_LCD_LED register_led_regions(); /* register LED port info in procfs */ #endif diff --git a/drivers/parisc/dino.c b/drivers/parisc/dino.c index f89f9fb4c84b..01a50a051296 100644 --- a/drivers/parisc/dino.c +++ b/drivers/parisc/dino.c @@ -1084,8 +1084,8 @@ static struct parisc_driver dino_driver __refdata = { * This is the only routine which is NOT static. * Must be called exactly once before pci_init(). */ -void __init dino_init(void) +static int __init dino_init(void) { - register_parisc_driver(&dino_driver); + return register_parisc_driver(&dino_driver); } - +arch_initcall(dino_init); -- cgit v1.2.3 From 49663185d050ddb4b2bc3297c04c976078c4911f Mon Sep 17 00:00:00 2001 From: Helge Deller Date: Sun, 27 Aug 2023 08:56:16 +0200 Subject: parisc: hppb: Convert HP PB bus driver to use arch_initcall() Signed-off-by: Helge Deller --- arch/parisc/include/asm/processor.h | 1 - arch/parisc/kernel/setup.c | 4 ---- drivers/parisc/hppb.c | 7 ++++--- 3 files changed, 4 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/arch/parisc/include/asm/processor.h b/arch/parisc/include/asm/processor.h index 275456ea7758..e0386767c0a4 100644 --- a/arch/parisc/include/asm/processor.h +++ b/arch/parisc/include/asm/processor.h @@ -316,7 +316,6 @@ extern int show_cpuinfo (struct seq_file *m, void *v); extern void gsc_init(void); extern void processor_init(void); extern void ccio_init(void); -extern void hppb_init(void); extern void iosapic_init(void); extern void lba_init(void); extern void sba_init(void); diff --git a/arch/parisc/kernel/setup.c b/arch/parisc/kernel/setup.c index e993ce617166..795486f0a1ea 100644 --- a/arch/parisc/kernel/setup.c +++ b/arch/parisc/kernel/setup.c @@ -307,10 +307,6 @@ static int __init parisc_init(void) parisc_eisa_init(); #endif -#if defined(CONFIG_HPPB) - hppb_init(); -#endif - #ifdef CONFIG_CHASSIS_LCD_LED register_led_regions(); /* register LED port info in procfs */ #endif diff --git a/drivers/parisc/hppb.c b/drivers/parisc/hppb.c index e60e68664654..0f9d80384e3d 100644 --- a/drivers/parisc/hppb.c +++ b/drivers/parisc/hppb.c @@ -96,9 +96,10 @@ static struct parisc_driver hppb_driver __refdata = { /** * hppb_init - HP-PB bus initialization procedure. * - * Register this driver. + * Register this driver. */ -void __init hppb_init(void) +static int __init hppb_init(void) { - register_parisc_driver(&hppb_driver); + return register_parisc_driver(&hppb_driver); } +arch_initcall(hppb_init); -- cgit v1.2.3 From 5f4f870a445790c8ff781a4b9a3e233769d26835 Mon Sep 17 00:00:00 2001 From: Helge Deller Date: Sun, 27 Aug 2023 08:59:34 +0200 Subject: parisc: eisa: Convert HP EISA bus driver to use arch_initcall() Signed-off-by: Helge Deller --- arch/parisc/include/asm/processor.h | 1 - arch/parisc/kernel/setup.c | 3 --- drivers/parisc/eisa.c | 5 +++-- 3 files changed, 3 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/arch/parisc/include/asm/processor.h b/arch/parisc/include/asm/processor.h index e0386767c0a4..b3db85b71e8b 100644 --- a/arch/parisc/include/asm/processor.h +++ b/arch/parisc/include/asm/processor.h @@ -319,7 +319,6 @@ extern void ccio_init(void); extern void iosapic_init(void); extern void lba_init(void); extern void sba_init(void); -extern void parisc_eisa_init(void); struct parisc_device; struct resource; extern void sba_distributed_lmmio(struct parisc_device *, struct resource *); diff --git a/arch/parisc/kernel/setup.c b/arch/parisc/kernel/setup.c index 795486f0a1ea..733a9010f370 100644 --- a/arch/parisc/kernel/setup.c +++ b/arch/parisc/kernel/setup.c @@ -303,9 +303,6 @@ static int __init parisc_init(void) #if defined(CONFIG_GSC_LASI) || defined(CONFIG_GSC_WAX) gsc_init(); #endif -#ifdef CONFIG_EISA - parisc_eisa_init(); -#endif #ifdef CONFIG_CHASSIS_LCD_LED register_led_regions(); /* register LED port info in procfs */ diff --git a/drivers/parisc/eisa.c b/drivers/parisc/eisa.c index 45e487388c6e..9eab974e6baf 100644 --- a/drivers/parisc/eisa.c +++ b/drivers/parisc/eisa.c @@ -400,10 +400,11 @@ static struct parisc_driver eisa_driver __refdata = { .probe = eisa_probe, }; -void __init parisc_eisa_init(void) +static int __init parisc_eisa_init(void) { - register_parisc_driver(&eisa_driver); + return register_parisc_driver(&eisa_driver); } +arch_initcall(parisc_eisa_init); static unsigned int eisa_irq_configured; -- cgit v1.2.3 From 63c1ce56abddec2cec046cdbe6260bca09bf89a1 Mon Sep 17 00:00:00 2001 From: Helge Deller Date: Sun, 27 Aug 2023 09:10:20 +0200 Subject: parisc: ccio: Convert CCIO driver to use arch_initcall() Signed-off-by: Helge Deller --- arch/parisc/include/asm/processor.h | 1 - arch/parisc/kernel/setup.c | 10 ---------- drivers/parisc/ccio-dma.c | 14 +++----------- 3 files changed, 3 insertions(+), 22 deletions(-) (limited to 'drivers') diff --git a/arch/parisc/include/asm/processor.h b/arch/parisc/include/asm/processor.h index b3db85b71e8b..215f4d03ba2a 100644 --- a/arch/parisc/include/asm/processor.h +++ b/arch/parisc/include/asm/processor.h @@ -315,7 +315,6 @@ extern int show_cpuinfo (struct seq_file *m, void *v); /* driver code in driver/parisc */ extern void gsc_init(void); extern void processor_init(void); -extern void ccio_init(void); extern void iosapic_init(void); extern void lba_init(void); extern void sba_init(void); diff --git a/arch/parisc/kernel/setup.c b/arch/parisc/kernel/setup.c index 733a9010f370..86771ba893b6 100644 --- a/arch/parisc/kernel/setup.c +++ b/arch/parisc/kernel/setup.c @@ -290,16 +290,6 @@ static int __init parisc_init(void) lba_init(); #endif - /* CCIO before any potential subdevices */ -#if defined(CONFIG_IOMMU_CCIO) - ccio_init(); -#endif - - /* - * Need to register Asp & Wax before the EISA adapters for the IRQ - * regions. EISA must come before PCI to be sure it gets IRQ region - * 0. - */ #if defined(CONFIG_GSC_LASI) || defined(CONFIG_GSC_WAX) gsc_init(); #endif diff --git a/drivers/parisc/ccio-dma.c b/drivers/parisc/ccio-dma.c index 9bf652bd002c..bd9285628b42 100644 --- a/drivers/parisc/ccio-dma.c +++ b/drivers/parisc/ccio-dma.c @@ -8,18 +8,10 @@ ** (c) Copyright 2000 Ryan Bradetich ** (c) Copyright 2000 Hewlett-Packard Company ** -** -** ** "Real Mode" operation refers to U2/Uturn chip operation. ** U2/Uturn were designed to perform coherency checks w/o using ** the I/O MMU - basically what x86 does. ** -** Philipp Rumpf has a "Real Mode" driver for PCX-W machines at: -** CVSROOT=:pserver:anonymous@198.186.203.37:/cvsroot/linux-parisc -** cvs -z3 co linux/arch/parisc/kernel/dma-rm.c -** -** I've rewritten his code to work under TPG's tree. See ccio-rm-dma.c. -** ** Drawbacks of using Real Mode are: ** o outbound DMA is slower - U2 won't prefetch data (GSC+ XQL signal). ** o Inbound DMA less efficient - U2 can't use DMA_FAST attribute. @@ -1582,8 +1574,8 @@ static int __init ccio_probe(struct parisc_device *dev) * * Register this driver. */ -void __init ccio_init(void) +static int __init ccio_init(void) { - register_parisc_driver(&ccio_driver); + return register_parisc_driver(&ccio_driver); } - +arch_initcall(ccio_init); -- cgit v1.2.3 From ba8723b1edf9dbd4c10a739375a60506fd00652b Mon Sep 17 00:00:00 2001 From: Helge Deller Date: Sun, 27 Aug 2023 09:14:42 +0200 Subject: parisc: gsc: Convert GSC bus driver to use arch_initcall() This conversion includes LASI, ASP and WAX drivers for now. Signed-off-by: Helge Deller --- arch/parisc/include/asm/processor.h | 1 - arch/parisc/kernel/setup.c | 4 ---- drivers/parisc/gsc.c | 4 +++- 3 files changed, 3 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/arch/parisc/include/asm/processor.h b/arch/parisc/include/asm/processor.h index 215f4d03ba2a..44e9a03fd778 100644 --- a/arch/parisc/include/asm/processor.h +++ b/arch/parisc/include/asm/processor.h @@ -313,7 +313,6 @@ extern void collect_boot_cpu_data(void); extern int show_cpuinfo (struct seq_file *m, void *v); /* driver code in driver/parisc */ -extern void gsc_init(void); extern void processor_init(void); extern void iosapic_init(void); extern void lba_init(void); diff --git a/arch/parisc/kernel/setup.c b/arch/parisc/kernel/setup.c index 86771ba893b6..444357815c2d 100644 --- a/arch/parisc/kernel/setup.c +++ b/arch/parisc/kernel/setup.c @@ -290,10 +290,6 @@ static int __init parisc_init(void) lba_init(); #endif -#if defined(CONFIG_GSC_LASI) || defined(CONFIG_GSC_WAX) - gsc_init(); -#endif - #ifdef CONFIG_CHASSIS_LCD_LED register_led_regions(); /* register LED port info in procfs */ #endif diff --git a/drivers/parisc/gsc.c b/drivers/parisc/gsc.c index ec175ae99873..f6a8f26d8c40 100644 --- a/drivers/parisc/gsc.c +++ b/drivers/parisc/gsc.c @@ -263,7 +263,7 @@ extern struct parisc_driver lasi_driver; extern struct parisc_driver asp_driver; extern struct parisc_driver wax_driver; -void __init gsc_init(void) +static int __init gsc_init(void) { #ifdef CONFIG_GSC_LASI register_parisc_driver(&lasi_driver); @@ -272,4 +272,6 @@ void __init gsc_init(void) #ifdef CONFIG_GSC_WAX register_parisc_driver(&wax_driver); #endif + return 0; } +arch_initcall(gsc_init); -- cgit v1.2.3 From df3f93596c8ffb97482bb6d90f4933d7417605aa Mon Sep 17 00:00:00 2001 From: Helge Deller Date: Sun, 27 Aug 2023 09:25:48 +0200 Subject: parisc: lba: Convert LBA PCI bus driver to use arch_initcall() Signed-off-by: Helge Deller --- arch/parisc/include/asm/processor.h | 1 - arch/parisc/kernel/setup.c | 3 --- drivers/parisc/lba_pci.c | 5 +++-- 3 files changed, 3 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/arch/parisc/include/asm/processor.h b/arch/parisc/include/asm/processor.h index 44e9a03fd778..c6a526b6353c 100644 --- a/arch/parisc/include/asm/processor.h +++ b/arch/parisc/include/asm/processor.h @@ -315,7 +315,6 @@ extern int show_cpuinfo (struct seq_file *m, void *v); /* driver code in driver/parisc */ extern void processor_init(void); extern void iosapic_init(void); -extern void lba_init(void); extern void sba_init(void); struct parisc_device; struct resource; diff --git a/arch/parisc/kernel/setup.c b/arch/parisc/kernel/setup.c index 444357815c2d..3b8ba550f029 100644 --- a/arch/parisc/kernel/setup.c +++ b/arch/parisc/kernel/setup.c @@ -286,9 +286,6 @@ static int __init parisc_init(void) #if defined(CONFIG_IOMMU_SBA) sba_init(); #endif -#if defined(CONFIG_PCI_LBA) - lba_init(); -#endif #ifdef CONFIG_CHASSIS_LCD_LED register_led_regions(); /* register LED port info in procfs */ diff --git a/drivers/parisc/lba_pci.c b/drivers/parisc/lba_pci.c index 9e22b117fb3a..3fc3765fddaa 100644 --- a/drivers/parisc/lba_pci.c +++ b/drivers/parisc/lba_pci.c @@ -1682,10 +1682,11 @@ static struct parisc_driver lba_driver __refdata = { ** One time initialization to let the world know the LBA was found. ** Must be called exactly once before pci_init(). */ -void __init lba_init(void) +static int __init lba_init(void) { - register_parisc_driver(&lba_driver); + return register_parisc_driver(&lba_driver); } +arch_initcall(lba_init); /* ** Initialize the IBASE/IMASK registers for LBA (Elroy). -- cgit v1.2.3 From 3b425dd2aeb8c876805a4cc29d84a6c455b43530 Mon Sep 17 00:00:00 2001 From: Helge Deller Date: Sun, 27 Aug 2023 09:36:23 +0200 Subject: parisc: led: Move register_led_regions() to late_initcall() Signed-off-by: Helge Deller --- arch/parisc/include/asm/led.h | 3 --- arch/parisc/kernel/setup.c | 5 ----- drivers/parisc/led.c | 4 +++- 3 files changed, 3 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/arch/parisc/include/asm/led.h b/arch/parisc/include/asm/led.h index 6de13d08a388..d1a016e33198 100644 --- a/arch/parisc/include/asm/led.h +++ b/arch/parisc/include/asm/led.h @@ -27,9 +27,6 @@ /* register_led_driver() */ int __init register_led_driver(int model, unsigned long cmd_reg, unsigned long data_reg); -/* registers the LED regions for procfs */ -void __init register_led_regions(void); - #ifdef CONFIG_CHASSIS_LCD_LED /* writes a string to the LCD display (if possible on this h/w) */ int lcd_print(const char *str); diff --git a/arch/parisc/kernel/setup.c b/arch/parisc/kernel/setup.c index 3b8ba550f029..ef642a2ade96 100644 --- a/arch/parisc/kernel/setup.c +++ b/arch/parisc/kernel/setup.c @@ -286,11 +286,6 @@ static int __init parisc_init(void) #if defined(CONFIG_IOMMU_SBA) sba_init(); #endif - -#ifdef CONFIG_CHASSIS_LCD_LED - register_led_regions(); /* register LED port info in procfs */ -#endif - return 0; } arch_initcall(parisc_init); diff --git a/drivers/parisc/led.c b/drivers/parisc/led.c index 3737c1021f88..38cd14530ff2 100644 --- a/drivers/parisc/led.c +++ b/drivers/parisc/led.c @@ -613,7 +613,7 @@ int __init register_led_driver(int model, unsigned long cmd_reg, unsigned long d ** */ -void __init register_led_regions(void) +static int __init register_led_regions(void) { switch (lcd_info.model) { case DISPLAY_MODEL_LCD: @@ -625,7 +625,9 @@ void __init register_led_regions(void) request_mem_region((unsigned long)LED_DATA_REG, 1, "led_data"); break; } + return 0; } +late_initcall(register_led_regions); /* -- cgit v1.2.3 From 53861a915afeb445126588da266fc5031d1c8eaa Mon Sep 17 00:00:00 2001 From: Helge Deller Date: Sun, 27 Aug 2023 09:38:32 +0200 Subject: parisc: sba_iommu: Convert SBA IOMMU driver to use arch_initcall() Signed-off-by: Helge Deller --- arch/parisc/include/asm/processor.h | 1 - arch/parisc/kernel/setup.c | 3 --- drivers/parisc/sba_iommu.c | 5 +++-- 3 files changed, 3 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/arch/parisc/include/asm/processor.h b/arch/parisc/include/asm/processor.h index c6a526b6353c..eb0ecd9b5621 100644 --- a/arch/parisc/include/asm/processor.h +++ b/arch/parisc/include/asm/processor.h @@ -315,7 +315,6 @@ extern int show_cpuinfo (struct seq_file *m, void *v); /* driver code in driver/parisc */ extern void processor_init(void); extern void iosapic_init(void); -extern void sba_init(void); struct parisc_device; struct resource; extern void sba_distributed_lmmio(struct parisc_device *, struct resource *); diff --git a/arch/parisc/kernel/setup.c b/arch/parisc/kernel/setup.c index ef642a2ade96..84a1dce6c757 100644 --- a/arch/parisc/kernel/setup.c +++ b/arch/parisc/kernel/setup.c @@ -282,9 +282,6 @@ static int __init parisc_init(void) /* These are in a non-obvious order, will fix when we have an iotree */ #if defined(CONFIG_IOSAPIC) iosapic_init(); -#endif -#if defined(CONFIG_IOMMU_SBA) - sba_init(); #endif return 0; } diff --git a/drivers/parisc/sba_iommu.c b/drivers/parisc/sba_iommu.c index 8b1dcd537020..33da29d65f30 100644 --- a/drivers/parisc/sba_iommu.c +++ b/drivers/parisc/sba_iommu.c @@ -1994,10 +1994,11 @@ static int __init sba_driver_callback(struct parisc_device *dev) ** This is the only routine which is NOT static. ** Must be called exactly once before pci_init(). */ -void __init sba_init(void) +static int __init sba_init(void) { - register_parisc_driver(&sba_driver); + return register_parisc_driver(&sba_driver); } +arch_initcall(sba_init); /** -- cgit v1.2.3 From 9c2ca106c9fecea2f1564ccc276b3db1f2ab25e8 Mon Sep 17 00:00:00 2001 From: Helge Deller Date: Sun, 27 Aug 2023 10:33:07 +0200 Subject: parisc: iosapic: Convert I/O Sapic driver to use arch_initcall() Signed-off-by: Helge Deller --- arch/parisc/include/asm/processor.h | 1 - arch/parisc/kernel/setup.c | 5 ----- drivers/parisc/iosapic.c | 8 ++++---- 3 files changed, 4 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/arch/parisc/include/asm/processor.h b/arch/parisc/include/asm/processor.h index eb0ecd9b5621..d77c43d32974 100644 --- a/arch/parisc/include/asm/processor.h +++ b/arch/parisc/include/asm/processor.h @@ -314,7 +314,6 @@ extern int show_cpuinfo (struct seq_file *m, void *v); /* driver code in driver/parisc */ extern void processor_init(void); -extern void iosapic_init(void); struct parisc_device; struct resource; extern void sba_distributed_lmmio(struct parisc_device *, struct resource *); diff --git a/arch/parisc/kernel/setup.c b/arch/parisc/kernel/setup.c index 84a1dce6c757..fc4134be1742 100644 --- a/arch/parisc/kernel/setup.c +++ b/arch/parisc/kernel/setup.c @@ -278,11 +278,6 @@ static int __init parisc_init(void) apply_alternatives_all(); parisc_setup_cache_timing(); - - /* These are in a non-obvious order, will fix when we have an iotree */ -#if defined(CONFIG_IOSAPIC) - iosapic_init(); -#endif return 0; } arch_initcall(parisc_init); diff --git a/drivers/parisc/iosapic.c b/drivers/parisc/iosapic.c index 27478e9f4e84..a7df764f1a72 100644 --- a/drivers/parisc/iosapic.c +++ b/drivers/parisc/iosapic.c @@ -348,13 +348,10 @@ iosapic_load_irt(unsigned long cell_num, struct irt_entry **irt) } - -void __init iosapic_init(void) +static int __init iosapic_init(void) { unsigned long cell = 0; - DBG("iosapic_init()\n"); - #ifdef __LP64__ if (is_pdc_pat()) { int status; @@ -371,7 +368,10 @@ void __init iosapic_init(void) irt_num_entry = iosapic_load_irt(cell, &irt_cell); if (irt_num_entry == 0) irt_cell = NULL; /* old PDC w/o iosapic */ + + return 0; } +arch_initcall(iosapic_init); /* -- cgit v1.2.3 From ac65d9c90e4cccab2c939b2648e015c93ba3711b Mon Sep 17 00:00:00 2001 From: Helge Deller Date: Sun, 27 Aug 2023 10:43:18 +0200 Subject: parisc: wax: Initialize wax driver via arch_initcall() Signed-off-by: Helge Deller --- drivers/parisc/gsc.c | 4 ---- drivers/parisc/wax.c | 12 +++++++++--- 2 files changed, 9 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/parisc/gsc.c b/drivers/parisc/gsc.c index f6a8f26d8c40..95112176c546 100644 --- a/drivers/parisc/gsc.c +++ b/drivers/parisc/gsc.c @@ -261,16 +261,12 @@ int gsc_common_setup(struct parisc_device *parent, struct gsc_asic *gsc_asic) extern struct parisc_driver lasi_driver; extern struct parisc_driver asp_driver; -extern struct parisc_driver wax_driver; static int __init gsc_init(void) { #ifdef CONFIG_GSC_LASI register_parisc_driver(&lasi_driver); register_parisc_driver(&asp_driver); -#endif -#ifdef CONFIG_GSC_WAX - register_parisc_driver(&wax_driver); #endif return 0; } diff --git a/drivers/parisc/wax.c b/drivers/parisc/wax.c index 73a2b01f8d9c..834dbe9a767b 100644 --- a/drivers/parisc/wax.c +++ b/drivers/parisc/wax.c @@ -4,7 +4,7 @@ * * (c) Copyright 2000 The Puffin Group Inc. * - * by Helge Deller + * (c) 2000-2023 by Helge Deller */ #include @@ -121,14 +121,20 @@ static int __init wax_init_chip(struct parisc_device *dev) } static const struct parisc_device_id wax_tbl[] __initconst = { - { HPHW_BA, HVERSION_REV_ANY_ID, HVERSION_ANY_ID, 0x0008e }, + { HPHW_BA, HVERSION_REV_ANY_ID, HVERSION_ANY_ID, 0x0008e }, { 0, } }; MODULE_DEVICE_TABLE(parisc, wax_tbl); -struct parisc_driver wax_driver __refdata = { +static struct parisc_driver wax_driver __refdata = { .name = "wax", .id_table = wax_tbl, .probe = wax_init_chip, }; + +static int __init wax_init(void) +{ + return register_parisc_driver(&wax_driver); +} +arch_initcall(wax_init); -- cgit v1.2.3 From ff0e833e98ee382e718a0a8a9433a3568fede4ab Mon Sep 17 00:00:00 2001 From: Helge Deller Date: Sun, 27 Aug 2023 10:49:20 +0200 Subject: parisc: asp: Initialize asp driver via arch_initcall() Signed-off-by: Helge Deller --- drivers/parisc/asp.c | 11 +++++++++-- drivers/parisc/gsc.c | 2 -- 2 files changed, 9 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/parisc/asp.c b/drivers/parisc/asp.c index f55018e5cc7c..32af8f095781 100644 --- a/drivers/parisc/asp.c +++ b/drivers/parisc/asp.c @@ -4,7 +4,7 @@ * * (c) Copyright 2000 The Puffin Group Inc. * - * by Helge Deller + * (c) 2000-2023 by Helge Deller */ #include @@ -118,9 +118,16 @@ static const struct parisc_device_id asp_tbl[] __initconst = { { HPHW_BA, HVERSION_REV_ANY_ID, HVERSION_ANY_ID, 0x00070 }, { 0, } }; +MODULE_DEVICE_TABLE(parisc, asp_tbl); -struct parisc_driver asp_driver __refdata = { +static struct parisc_driver asp_driver __refdata = { .name = "asp", .id_table = asp_tbl, .probe = asp_init_chip, }; + +static int __init asp_init(void) +{ + return register_parisc_driver(&asp_driver); +} +arch_initcall(asp_init); diff --git a/drivers/parisc/gsc.c b/drivers/parisc/gsc.c index 95112176c546..5643c46a4255 100644 --- a/drivers/parisc/gsc.c +++ b/drivers/parisc/gsc.c @@ -260,13 +260,11 @@ int gsc_common_setup(struct parisc_device *parent, struct gsc_asic *gsc_asic) } extern struct parisc_driver lasi_driver; -extern struct parisc_driver asp_driver; static int __init gsc_init(void) { #ifdef CONFIG_GSC_LASI register_parisc_driver(&lasi_driver); - register_parisc_driver(&asp_driver); #endif return 0; } -- cgit v1.2.3 From d75ef5994db384856f1590ecac2ad38ebcde1a4a Mon Sep 17 00:00:00 2001 From: Helge Deller Date: Sun, 27 Aug 2023 11:03:20 +0200 Subject: parisc: lasi: Initialize LASI driver via arch_initcall() Move initialization code for LASI out of the GSC driver. Since ASP and WAX have been moved in previous commits, the GSC driver is now just a driver which provides library functions for LASI, ASP and WAX and as such doesn't need an own initialization function any longer. Signed-off-by: Helge Deller --- drivers/parisc/gsc.c | 11 ----------- drivers/parisc/lasi.c | 9 ++++++++- 2 files changed, 8 insertions(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/parisc/gsc.c b/drivers/parisc/gsc.c index 5643c46a4255..a0daaa548bc3 100644 --- a/drivers/parisc/gsc.c +++ b/drivers/parisc/gsc.c @@ -258,14 +258,3 @@ int gsc_common_setup(struct parisc_device *parent, struct gsc_asic *gsc_asic) return 0; } - -extern struct parisc_driver lasi_driver; - -static int __init gsc_init(void) -{ -#ifdef CONFIG_GSC_LASI - register_parisc_driver(&lasi_driver); -#endif - return 0; -} -arch_initcall(gsc_init); diff --git a/drivers/parisc/lasi.c b/drivers/parisc/lasi.c index d7331823255f..73c93e9cfa51 100644 --- a/drivers/parisc/lasi.c +++ b/drivers/parisc/lasi.c @@ -220,9 +220,16 @@ static struct parisc_device_id lasi_tbl[] __initdata = { { HPHW_BA, HVERSION_REV_ANY_ID, HVERSION_ANY_ID, 0x00081 }, { 0, } }; +MODULE_DEVICE_TABLE(parisc, lasi_tbl); -struct parisc_driver lasi_driver __refdata = { +static struct parisc_driver lasi_driver __refdata = { .name = "lasi", .id_table = lasi_tbl, .probe = lasi_init_chip, }; + +static int __init lasi_init(void) +{ + return register_parisc_driver(&lasi_driver); +} +arch_initcall(lasi_init); -- cgit v1.2.3 From 789e527adfc335681ea4c3e347e8b500753d4fde Mon Sep 17 00:00:00 2001 From: Helge Deller Date: Sun, 27 Aug 2023 13:50:00 +0200 Subject: parisc: led: Rewrite LED/LCD driver to utilizize Linux LED subsystem Rewrite the whole driver and drop the own code to calculate load average, disk and LAN load. Switch instead to use the in-kernel LED subsystem, which gives us quite some advantages, e.g. - existing triggers for heartbeat and disk/lan activity can be used - users can configre the LEDs at will to any existing trigger via /sys/class/leds - less overhead since we don't need to run own timers - fully integrated in Linux and as such cleaner code. Note that the driver now depends on CONFIG_LEDS_CLASS which has to be built-in and not as module. Signed-off-by: Helge Deller --- arch/parisc/include/asm/led.h | 9 +- arch/parisc/kernel/setup.c | 5 - drivers/parisc/Kconfig | 3 +- drivers/parisc/led.c | 903 ++++++++++++++++-------------------------- 4 files changed, 343 insertions(+), 577 deletions(-) (limited to 'drivers') diff --git a/arch/parisc/include/asm/led.h b/arch/parisc/include/asm/led.h index 3409c883f1bb..0aea47eff48d 100644 --- a/arch/parisc/include/asm/led.h +++ b/arch/parisc/include/asm/led.h @@ -25,16 +25,13 @@ #define LED_CMD_REG_NONE 0 /* NULL == no addr for the cmd register */ /* register_led_driver() */ -int __init register_led_driver(int model, unsigned long cmd_reg, unsigned long data_reg); +int register_led_driver(int model, unsigned long cmd_reg, unsigned long data_reg); #ifdef CONFIG_CHASSIS_LCD_LED /* writes a string to the LCD display (if possible on this h/w) */ -int lcd_print(const char *str); +void lcd_print(const char *str); #else -#define lcd_print(str) +#define lcd_print(str) do { } while (0) #endif -/* main LED initialization function (uses PDC) */ -int __init led_init(void); - #endif /* LED_H */ diff --git a/arch/parisc/kernel/setup.c b/arch/parisc/kernel/setup.c index fc4134be1742..2f434f2da185 100644 --- a/arch/parisc/kernel/setup.c +++ b/arch/parisc/kernel/setup.c @@ -143,11 +143,6 @@ void __init setup_arch(char **cmdline_p) parisc_cache_init(); paging_init(); -#ifdef CONFIG_CHASSIS_LCD_LED - /* initialize the LCD/LED after boot_cpu_data is available ! */ - led_init(); /* LCD/LED initialization */ -#endif - #ifdef CONFIG_PA11 dma_ops_init(); #endif diff --git a/drivers/parisc/Kconfig b/drivers/parisc/Kconfig index 2fc3222d2634..9cbcf15527b6 100644 --- a/drivers/parisc/Kconfig +++ b/drivers/parisc/Kconfig @@ -100,8 +100,9 @@ config SUPERIO config CHASSIS_LCD_LED bool "Chassis LCD and LED support" + depends on LEDS_CLASS=y default y - select VM_EVENT_COUNTERS + select LEDS_TRIGGERS help Say Y here if you want to enable support for the Heartbeat, Disk/Network activities LEDs on some PA-RISC machines, diff --git a/drivers/parisc/led.c b/drivers/parisc/led.c index 38cd14530ff2..1f75d2416001 100644 --- a/drivers/parisc/led.c +++ b/drivers/parisc/led.c @@ -1,77 +1,46 @@ // SPDX-License-Identifier: GPL-2.0-or-later /* - * Chassis LCD/LED driver for HP-PARISC workstations + * Chassis LCD/LED driver for HP-PARISC workstations * - * (c) Copyright 2000 Red Hat Software - * (c) Copyright 2000 Helge Deller - * (c) Copyright 2001-2009 Helge Deller - * (c) Copyright 2001 Randolph Chung + * (c) Copyright 2000 Red Hat Software + * (c) Copyright 2000 Helge Deller + * (c) Copyright 2001 Randolph Chung + * (c) Copyright 2000-2023 Helge Deller * - * TODO: - * - speed-up calculations with inlined assembler - * - interface to write to second row of LCD from /proc (if technically possible) + * The control of the LEDs and LCDs on PARISC machines has to be done + * completely in software. * - * Changes: - * - Audit copy_from_user in led_proc_write. - * Daniele Bellucci - * - Switch from using a tasklet to a work queue, so the led_LCD_driver - * can sleep. - * David Pye + * The LEDs can be configured at runtime in /sys/class/leds/ */ #include -#include /* for offsetof() */ #include #include #include #include #include #include -#include -#include -#include -#include -#include #include -#include -#include -#include -#include -#include -#include +#include +#include +#include + #include #include #include #include /* HZ */ #include #include -#include - -/* The control of the LEDs and LCDs on PARISC-machines have to be done - completely in software. The necessary calculations are done in a work queue - task which is scheduled regularly, and since the calculations may consume a - relatively large amount of CPU time, some of the calculations can be - turned off with the following variables (controlled via procfs) */ -static int led_type __read_mostly = -1; -static unsigned char lastleds; /* LED state from most recent update */ -static unsigned int led_heartbeat __read_mostly = 1; -static unsigned int led_diskio __read_mostly; -static unsigned int led_lanrxtx __read_mostly; -static char lcd_text[32] __read_mostly; -static char lcd_text_default[32] __read_mostly; -static int lcd_no_led_support __read_mostly = 0; /* KittyHawk doesn't support LED on its LCD */ +#define LED_HAS_LCD 1 +#define LED_HAS_LED 2 - -static struct workqueue_struct *led_wq; -static void led_work_func(struct work_struct *); -static DECLARE_DELAYED_WORK(led_task, led_work_func); - -#if 0 -#define DPRINTK(x) printk x -#else -#define DPRINTK(x) -#endif +static unsigned char led_type; /* bitmask of LED_HAS_XXX */ +static unsigned char lastleds; /* LED state from most recent update */ +static unsigned char lcd_new_text; +static unsigned char lcd_text[20]; +static unsigned char lcd_text_default[20]; +static unsigned char lcd_no_led_support; /* KittyHawk doesn't support LED on its LCD */ struct lcd_block { unsigned char command; /* stores the command byte */ @@ -80,7 +49,7 @@ struct lcd_block { }; /* Structure returned by PDC_RETURN_CHASSIS_INFO */ -/* NOTE: we use unsigned long:16 two times, since the following member +/* NOTE: we use unsigned long:16 two times, since the following member lcd_cmd_reg_addr needs to be 64bit aligned on 64bit PA2.0-machines */ struct pdc_chassis_lcd_info_ret_block { unsigned long model:16; /* DISPLAY_MODEL_XXXX */ @@ -100,15 +69,15 @@ struct pdc_chassis_lcd_info_ret_block { /* LCD_CMD and LCD_DATA for KittyHawk machines */ -#define KITTYHAWK_LCD_CMD F_EXTEND(0xf0190000UL) /* 64bit-ready */ -#define KITTYHAWK_LCD_DATA (KITTYHAWK_LCD_CMD+1) +#define KITTYHAWK_LCD_CMD F_EXTEND(0xf0190000UL) +#define KITTYHAWK_LCD_DATA (KITTYHAWK_LCD_CMD + 1) -/* lcd_info is pre-initialized to the values needed to program KittyHawk LCD's +/* lcd_info is pre-initialized to the values needed to program KittyHawk LCD's * HP seems to have used Sharp/Hitachi HD44780 LCDs most of the time. */ static struct pdc_chassis_lcd_info_ret_block -lcd_info __attribute__((aligned(8))) __read_mostly = +lcd_info __attribute__((aligned(8))) = { - .model = DISPLAY_MODEL_LCD, + .model = DISPLAY_MODEL_NONE, .lcd_width = 16, .lcd_cmd_reg_addr = KITTYHAWK_LCD_CMD, .lcd_data_reg_addr = KITTYHAWK_LCD_DATA, @@ -117,165 +86,65 @@ lcd_info __attribute__((aligned(8))) __read_mostly = .reset_cmd2 = 0xc0, }; - /* direct access to some of the lcd_info variables */ -#define LCD_CMD_REG lcd_info.lcd_cmd_reg_addr -#define LCD_DATA_REG lcd_info.lcd_data_reg_addr +#define LCD_CMD_REG lcd_info.lcd_cmd_reg_addr +#define LCD_DATA_REG lcd_info.lcd_data_reg_addr #define LED_DATA_REG lcd_info.lcd_cmd_reg_addr /* LASI & ASP only */ -#define LED_HASLCD 1 -#define LED_NOLCD 0 - -/* The workqueue must be created at init-time */ -static int start_task(void) -{ - /* Display the default text now */ - if (led_type == LED_HASLCD) lcd_print( lcd_text_default ); - - /* KittyHawk has no LED support on its LCD */ - if (lcd_no_led_support) return 0; - - /* Create the work queue and queue the LED task */ - led_wq = create_singlethread_workqueue("led_wq"); - if (!led_wq) - return -ENOMEM; - - queue_delayed_work(led_wq, &led_task, 0); - - return 0; -} - -device_initcall(start_task); - /* ptr to LCD/LED-specific function */ -static void (*led_func_ptr) (unsigned char) __read_mostly; - -#ifdef CONFIG_PROC_FS -static int led_proc_show(struct seq_file *m, void *v) -{ - switch ((long)m->private) - { - case LED_NOLCD: - seq_printf(m, "Heartbeat: %d\n", led_heartbeat); - seq_printf(m, "Disk IO: %d\n", led_diskio); - seq_printf(m, "LAN Rx/Tx: %d\n", led_lanrxtx); - break; - case LED_HASLCD: - seq_printf(m, "%s\n", lcd_text); - break; - default: - return 0; - } - return 0; -} - -static int led_proc_open(struct inode *inode, struct file *file) -{ - return single_open(file, led_proc_show, pde_data(inode)); -} +static void (*led_func_ptr) (unsigned char); -static ssize_t led_proc_write(struct file *file, const char __user *buf, - size_t count, loff_t *pos) +static void lcd_print_now(void) { - void *data = pde_data(file_inode(file)); - char *cur, lbuf[32]; - int d; - - if (!capable(CAP_SYS_ADMIN)) - return -EACCES; - - if (count >= sizeof(lbuf)) - count = sizeof(lbuf)-1; - - if (copy_from_user(lbuf, buf, count)) - return -EFAULT; - lbuf[count] = 0; - - cur = lbuf; - - switch ((long)data) - { - case LED_NOLCD: - d = *cur++ - '0'; - if (d != 0 && d != 1) goto parse_error; - led_heartbeat = d; - - if (*cur++ != ' ') goto parse_error; + int i; + char *str = lcd_text; - d = *cur++ - '0'; - if (d != 0 && d != 1) goto parse_error; - led_diskio = d; + if (lcd_info.model != DISPLAY_MODEL_LCD) + return; - if (*cur++ != ' ') goto parse_error; + if (!lcd_new_text) + return; + lcd_new_text = 0; - d = *cur++ - '0'; - if (d != 0 && d != 1) goto parse_error; - led_lanrxtx = d; + /* Set LCD Cursor to 1st character */ + gsc_writeb(lcd_info.reset_cmd1, LCD_CMD_REG); + udelay(lcd_info.min_cmd_delay); - break; - case LED_HASLCD: - if (*cur && cur[strlen(cur)-1] == '\n') - cur[strlen(cur)-1] = 0; - if (*cur == 0) - cur = lcd_text_default; - lcd_print(cur); - break; - default: - return 0; + /* Print the string */ + for (i = 0; i < lcd_info.lcd_width; i++) { + gsc_writeb(*str ? *str++ : ' ', LCD_DATA_REG); + udelay(lcd_info.min_cmd_delay); } - - return count; - -parse_error: - if ((long)data == LED_NOLCD) - printk(KERN_CRIT "Parse error: expect \"n n n\" (n == 0 or 1) for heartbeat,\ndisk io and lan tx/rx indicators\n"); - return -EINVAL; } -static const struct proc_ops led_proc_ops = { - .proc_open = led_proc_open, - .proc_read = seq_read, - .proc_lseek = seq_lseek, - .proc_release = single_release, - .proc_write = led_proc_write, -}; - -static int __init led_create_procfs(void) +/** + * lcd_print() + * + * @str: string to show on the LCD. If NULL, print current string again. + * + * Displays the given string on the LCD-Display of newer machines. + */ +void lcd_print(const char *str) { - struct proc_dir_entry *proc_pdc_root = NULL; - struct proc_dir_entry *ent; - - if (led_type == -1) return -1; - - proc_pdc_root = proc_mkdir("pdc", NULL); - if (!proc_pdc_root) return -1; - - if (!lcd_no_led_support) - { - ent = proc_create_data("led", 0644, proc_pdc_root, - &led_proc_ops, (void *)LED_NOLCD); /* LED */ - if (!ent) return -1; - } - - if (led_type == LED_HASLCD) - { - ent = proc_create_data("lcd", 0644, proc_pdc_root, - &led_proc_ops, (void *)LED_HASLCD); /* LCD */ - if (!ent) return -1; - } + /* copy display string to buffer for procfs */ + if (str) + strscpy(lcd_text, str, sizeof(lcd_text)); + lcd_new_text = 1; - return 0; + /* print now if LCD without any LEDs */ + if (led_type == LED_HAS_LCD) + lcd_print_now(); } -#endif -/* - ** - ** led_ASP_driver() - ** - */ #define LED_DATA 0x01 /* data to shift (0:on 1:off) */ #define LED_STROBE 0x02 /* strobe to clock data */ + +/** + * led_ASP_driver() - LED driver for the ASP controller chip + * + * @leds: bitmap representing the LED status + */ static void led_ASP_driver(unsigned char leds) { int i; @@ -290,11 +159,10 @@ static void led_ASP_driver(unsigned char leds) } } - -/* - ** - ** led_LASI_driver() - ** +/** + * led_LASI_driver() - LED driver for the LASI controller chip + * + * @leds: bitmap representing the LED status */ static void led_LASI_driver(unsigned char leds) { @@ -302,397 +170,298 @@ static void led_LASI_driver(unsigned char leds) gsc_writeb( leds, LED_DATA_REG ); } - -/* - ** - ** led_LCD_driver() - ** +/** + * led_LCD_driver() - LED & LCD driver for LCD chips + * + * @leds: bitmap representing the LED status */ static void led_LCD_driver(unsigned char leds) { - static int i; - static unsigned char mask[4] = { LED_HEARTBEAT, LED_DISK_IO, + static const unsigned char mask[4] = { + LED_HEARTBEAT, LED_DISK_IO, LED_LAN_RCV, LED_LAN_TX }; - - static struct lcd_block * blockp[4] = { + + static struct lcd_block * const blockp[4] = { &lcd_info.heartbeat, &lcd_info.disk_io, &lcd_info.lan_rcv, &lcd_info.lan_tx }; + static unsigned char latest_leds; + int i; - /* Convert min_cmd_delay to milliseconds */ - unsigned int msec_cmd_delay = 1 + (lcd_info.min_cmd_delay / 1000); - - for (i=0; i<4; ++i) - { - if ((leds & mask[i]) != (lastleds & mask[i])) - { - gsc_writeb( blockp[i]->command, LCD_CMD_REG ); - msleep(msec_cmd_delay); - - gsc_writeb( leds & mask[i] ? blockp[i]->on : - blockp[i]->off, LCD_DATA_REG ); - msleep(msec_cmd_delay); - } + for (i = 0; i < 4; ++i) { + if ((leds & mask[i]) == (latest_leds & mask[i])) + continue; + + gsc_writeb( blockp[i]->command, LCD_CMD_REG ); + udelay(lcd_info.min_cmd_delay); + + gsc_writeb( leds & mask[i] ? blockp[i]->on : + blockp[i]->off, LCD_DATA_REG ); + udelay(lcd_info.min_cmd_delay); } + latest_leds = leds; + + lcd_print_now(); } -/* - ** - ** led_get_net_activity() - ** - ** calculate if there was TX- or RX-throughput on the network interfaces - ** (analog to dev_get_info() from net/core/dev.c) - ** +/** + * lcd_system_halt() + * + * @nb: pointer to the notifier_block structure + * @event: the event (SYS_RESTART, SYS_HALT or SYS_POWER_OFF) + * @buf: pointer to a buffer (not used) + * + * Called by the reboot notifier chain at shutdown. Stops all + * LED/LCD activities. */ -static __inline__ int led_get_net_activity(void) -{ -#ifndef CONFIG_NET - return 0; -#else - static u64 rx_total_last, tx_total_last; - u64 rx_total, tx_total; - struct net_device *dev; - int retval; - - rx_total = tx_total = 0; - - /* we are running as a workqueue task, so we can use an RCU lookup */ - rcu_read_lock(); - for_each_netdev_rcu(&init_net, dev) { - const struct rtnl_link_stats64 *stats; - struct rtnl_link_stats64 temp; - struct in_device *in_dev = __in_dev_get_rcu(dev); - if (!in_dev || !in_dev->ifa_list) - continue; - if (ipv4_is_loopback(in_dev->ifa_list->ifa_local)) - continue; - stats = dev_get_stats(dev, &temp); - rx_total += stats->rx_packets; - tx_total += stats->tx_packets; - } - rcu_read_unlock(); - - retval = 0; +static int lcd_system_halt(struct notifier_block *nb, unsigned long event, void *buf) +{ + const char *txt; - if (rx_total != rx_total_last) { - rx_total_last = rx_total; - retval |= LED_LAN_RCV; + switch (event) { + case SYS_RESTART: txt = "SYSTEM RESTART"; + break; + case SYS_HALT: txt = "SYSTEM HALT"; + break; + case SYS_POWER_OFF: txt = "SYSTEM POWER OFF"; + break; + default: return NOTIFY_DONE; } - if (tx_total != tx_total_last) { - tx_total_last = tx_total; - retval |= LED_LAN_TX; - } + lcd_print(txt); - return retval; -#endif + return NOTIFY_OK; } +static struct notifier_block lcd_system_halt_notifier = { + .notifier_call = lcd_system_halt, +}; -/* - ** - ** led_get_diskio_activity() - ** - ** calculate if there was disk-io in the system - ** - */ -static __inline__ int led_get_diskio_activity(void) -{ - static unsigned long last_pgpgin, last_pgpgout; - unsigned long events[NR_VM_EVENT_ITEMS]; - int changed; - - all_vm_events(events); - - /* Just use a very simple calculation here. Do not care about overflow, - since we only want to know if there was activity or not. */ - changed = (events[PGPGIN] != last_pgpgin) || - (events[PGPGOUT] != last_pgpgout); - last_pgpgin = events[PGPGIN]; - last_pgpgout = events[PGPGOUT]; - - return (changed ? LED_DISK_IO : 0); -} - +static void set_led(struct led_classdev *led_cdev, enum led_brightness brightness); +struct hppa_led { + struct led_classdev led_cdev; + unsigned char led_bit; +}; +#define to_hppa_led(d) container_of(d, struct hppa_led, led_cdev) -/* - ** led_work_func() - ** - ** manages when and which chassis LCD/LED gets updated +typedef void (*set_handler)(struct led_classdev *, enum led_brightness); +struct led_type { + const char *name; + set_handler handler; + const char *default_trigger; +}; - TODO: - - display load average (older machines like 715/64 have 4 "free" LED's for that) - - optimizations - */ +#define NUM_LEDS_PER_BOARD 8 +struct hppa_drvdata { + struct hppa_led leds[NUM_LEDS_PER_BOARD]; +}; -#define HEARTBEAT_LEN (HZ*10/100) -#define HEARTBEAT_2ND_RANGE_START (HZ*28/100) -#define HEARTBEAT_2ND_RANGE_END (HEARTBEAT_2ND_RANGE_START + HEARTBEAT_LEN) +static void set_led(struct led_classdev *led_cdev, enum led_brightness brightness) +{ + struct hppa_led *p = to_hppa_led(led_cdev); + unsigned char led_bit = p->led_bit; -#define LED_UPDATE_INTERVAL (1 + (HZ*19/1000)) + if (brightness == LED_OFF) + lastleds &= ~led_bit; + else + lastleds |= led_bit; -static void led_work_func (struct work_struct *unused) -{ - static unsigned long last_jiffies; - static unsigned long count_HZ; /* counter in range 0..HZ */ - unsigned char currentleds = 0; /* stores current value of the LEDs */ + if (led_func_ptr) + led_func_ptr(lastleds); +} - /* exit if not initialized */ - if (!led_func_ptr) - return; - /* increment the heartbeat timekeeper */ - count_HZ += jiffies - last_jiffies; - last_jiffies = jiffies; - if (count_HZ >= HZ) - count_HZ = 0; +static int hppa_led_generic_probe(struct platform_device *pdev, + struct led_type *types) +{ + struct hppa_drvdata *p; + int i, err; - if (likely(led_heartbeat)) - { - /* flash heartbeat-LED like a real heart - * (2 x short then a long delay) - */ - if (count_HZ < HEARTBEAT_LEN || - (count_HZ >= HEARTBEAT_2ND_RANGE_START && - count_HZ < HEARTBEAT_2ND_RANGE_END)) - currentleds |= LED_HEARTBEAT; - } + p = devm_kzalloc(&pdev->dev, sizeof(*p), GFP_KERNEL); + if (!p) + return -ENOMEM; - if (likely(led_lanrxtx)) currentleds |= led_get_net_activity(); - if (likely(led_diskio)) currentleds |= led_get_diskio_activity(); - - /* blink LEDs if we got an Oops (HPMC) */ - if (unlikely(oops_in_progress)) { - if (boot_cpu_data.cpu_type >= pcxl2) { - /* newer machines don't have loadavg. LEDs, so we - * let all LEDs blink twice per second instead */ - currentleds = (count_HZ <= (HZ/2)) ? 0 : 0xff; - } else { - /* old machines: blink loadavg. LEDs twice per second */ - if (count_HZ <= (HZ/2)) - currentleds &= ~(LED4|LED5|LED6|LED7); - else - currentleds |= (LED4|LED5|LED6|LED7); + for (i = 0; i < NUM_LEDS_PER_BOARD; i++) { + struct led_classdev *lp = &p->leds[i].led_cdev; + + p->leds[i].led_bit = BIT(i); + lp->name = types[i].name; + lp->brightness = LED_FULL; + lp->brightness_set = types[i].handler; + lp->default_trigger = types[i].default_trigger; + err = led_classdev_register(&pdev->dev, lp); + if (err) { + dev_err(&pdev->dev, "Could not register %s LED\n", + lp->name); + for (i--; i >= 0; i--) + led_classdev_unregister(&p->leds[i].led_cdev); + return err; } } - if (currentleds != lastleds) - { - led_func_ptr(currentleds); /* Update the LCD/LEDs */ - lastleds = currentleds; - } + platform_set_drvdata(pdev, p); - queue_delayed_work(led_wq, &led_task, LED_UPDATE_INTERVAL); + return 0; } -/* - ** led_halt() - ** - ** called by the reboot notifier chain at shutdown and stops all - ** LED/LCD activities. - ** - */ +static int platform_led_remove(struct platform_device *pdev) +{ + struct hppa_drvdata *p = platform_get_drvdata(pdev); + int i; -static int led_halt(struct notifier_block *, unsigned long, void *); + for (i = 0; i < NUM_LEDS_PER_BOARD; i++) + led_classdev_unregister(&p->leds[i].led_cdev); -static struct notifier_block led_notifier = { - .notifier_call = led_halt, + return 0; +} + +static struct led_type mainboard_led_types[NUM_LEDS_PER_BOARD] = { + { + .name = "platform-lan-tx", + .handler = set_led, + .default_trigger = "tx", + }, + { + .name = "platform-lan-rx", + .handler = set_led, + .default_trigger = "rx", + }, + { + .name = "platform-disk", + .handler = set_led, + .default_trigger = "disk-activity", + }, + { + .name = "platform-heartbeat", + .handler = set_led, + .default_trigger = "heartbeat", + }, + { + .name = "platform-LED4", + .handler = set_led, + .default_trigger = "panic", + }, + { + .name = "platform-LED5", + .handler = set_led, + .default_trigger = "panic", + }, + { + .name = "platform-LED6", + .handler = set_led, + .default_trigger = "panic", + }, + { + .name = "platform-LED7", + .handler = set_led, + .default_trigger = "panic", + }, }; -static int notifier_disabled = 0; -static int led_halt(struct notifier_block *nb, unsigned long event, void *buf) +static int platform_led_probe(struct platform_device *pdev) { - char *txt; + return hppa_led_generic_probe(pdev, mainboard_led_types); +} - if (notifier_disabled) - return NOTIFY_OK; +MODULE_ALIAS("platform:platform-leds"); - notifier_disabled = 1; - switch (event) { - case SYS_RESTART: txt = "SYSTEM RESTART"; - break; - case SYS_HALT: txt = "SYSTEM HALT"; - break; - case SYS_POWER_OFF: txt = "SYSTEM POWER OFF"; - break; - default: return NOTIFY_DONE; - } - - /* Cancel the work item and delete the queue */ - if (led_wq) { - cancel_delayed_work_sync(&led_task); - destroy_workqueue(led_wq); - led_wq = NULL; - } - - if (lcd_info.model == DISPLAY_MODEL_LCD) - lcd_print(txt); - else - if (led_func_ptr) - led_func_ptr(0xff); /* turn all LEDs ON */ - - return NOTIFY_OK; -} +static struct platform_driver hppa_mainboard_led_driver = { + .probe = platform_led_probe, + .remove = platform_led_remove, + .driver = { + .name = "platform-leds", + }, +}; -/* - ** register_led_driver() - ** - ** registers an external LED or LCD for usage by this driver. - ** currently only LCD-, LASI- and ASP-style LCD/LED's are supported. - ** - */ +static struct platform_driver * const drivers[] = { + &hppa_mainboard_led_driver, +}; + +static struct platform_device platform_leds = { + .name = "platform-leds", +}; +/** + * register_led_driver() + * + * @model: model type, one of the DISPLAY_MODEL_XXXX values + * @cmd_reg: physical address of cmd register for the LED/LCD + * @data_reg: physical address of data register for the LED/LCD + * + * Registers a chassis LED or LCD which should be driven by this driver. + * Only PDC-based, LASI- or ASP-style LEDs and LCDs are supported. + */ int __init register_led_driver(int model, unsigned long cmd_reg, unsigned long data_reg) { - static int initialized; - - if (initialized || !data_reg) + if (led_func_ptr || !data_reg) return 1; - + + /* No LEDs when running in QEMU */ + if (running_on_qemu) + return 1; + lcd_info.model = model; /* store the values */ LCD_CMD_REG = (cmd_reg == LED_CMD_REG_NONE) ? 0 : cmd_reg; switch (lcd_info.model) { case DISPLAY_MODEL_LCD: LCD_DATA_REG = data_reg; - printk(KERN_INFO "LCD display at %lx,%lx registered\n", + pr_info("led: LCD display at %#lx and %#lx\n", LCD_CMD_REG , LCD_DATA_REG); led_func_ptr = led_LCD_driver; - led_type = LED_HASLCD; + if (lcd_no_led_support) + led_type = LED_HAS_LCD; + else + led_type = LED_HAS_LCD | LED_HAS_LED; break; case DISPLAY_MODEL_LASI: - /* Skip to register LED in QEMU */ - if (running_on_qemu) - return 1; LED_DATA_REG = data_reg; led_func_ptr = led_LASI_driver; - printk(KERN_INFO "LED display at %lx registered\n", LED_DATA_REG); - led_type = LED_NOLCD; + pr_info("led: LED display at %#lx\n", LED_DATA_REG); + led_type = LED_HAS_LED; break; case DISPLAY_MODEL_OLD_ASP: LED_DATA_REG = data_reg; led_func_ptr = led_ASP_driver; - printk(KERN_INFO "LED (ASP-style) display at %lx registered\n", + pr_info("led: LED (ASP-style) display at %#lx\n", LED_DATA_REG); - led_type = LED_NOLCD; + led_type = LED_HAS_LED; break; default: - printk(KERN_ERR "%s: Wrong LCD/LED model %d !\n", - __func__, lcd_info.model); + pr_err("led: Unknown LCD/LED model type %d\n", lcd_info.model); return 1; } - - /* mark the LCD/LED driver now as initialized and - * register to the reboot notifier chain */ - initialized++; - register_reboot_notifier(&led_notifier); - - /* Ensure the work is queued */ - if (led_wq) { - queue_delayed_work(led_wq, &led_task, 0); - } - return 0; -} + platform_register_drivers(drivers, ARRAY_SIZE(drivers)); -/* - ** register_led_regions() - ** - ** register_led_regions() registers the LCD/LED regions for /procfs. - ** At bootup - where the initialisation of the LCD/LED normally happens - - ** not all internal structures of request_region() are properly set up, - ** so that we delay the led-registration until after busdevices_init() - ** has been executed. - ** - */ - -static int __init register_led_regions(void) -{ - switch (lcd_info.model) { - case DISPLAY_MODEL_LCD: - request_mem_region((unsigned long)LCD_CMD_REG, 1, "lcd_cmd"); - request_mem_region((unsigned long)LCD_DATA_REG, 1, "lcd_data"); - break; - case DISPLAY_MODEL_LASI: - case DISPLAY_MODEL_OLD_ASP: - request_mem_region((unsigned long)LED_DATA_REG, 1, "led_data"); - break; - } - return 0; -} -late_initcall(register_led_regions); - - -/* - ** - ** lcd_print() - ** - ** Displays the given string on the LCD-Display of newer machines. - ** lcd_print() disables/enables the timer-based led work queue to - ** avoid a race condition while writing the CMD/DATA register pair. - ** - */ -int lcd_print( const char *str ) -{ - int i; - - if (!led_func_ptr || lcd_info.model != DISPLAY_MODEL_LCD) - return 0; - - /* temporarily disable the led work task */ - if (led_wq) - cancel_delayed_work_sync(&led_task); - - /* copy display string to buffer for procfs */ - strscpy(lcd_text, str, sizeof(lcd_text)); - - /* Set LCD Cursor to 1st character */ - gsc_writeb(lcd_info.reset_cmd1, LCD_CMD_REG); - udelay(lcd_info.min_cmd_delay); - - /* Print the string */ - for (i=0; i < lcd_info.lcd_width; i++) { - if (str && *str) - gsc_writeb(*str++, LCD_DATA_REG); - else - gsc_writeb(' ', LCD_DATA_REG); - udelay(lcd_info.min_cmd_delay); - } - - /* re-queue the work */ - if (led_wq) { - queue_delayed_work(led_wq, &led_task, 0); - } - - return lcd_info.lcd_width; + return register_reboot_notifier(&lcd_system_halt_notifier); } -/* - ** led_init() - ** - ** led_init() is called very early in the bootup-process from setup.c - ** and asks the PDC for an usable chassis LCD or LED. - ** If the PDC doesn't return any info, then the LED - ** is detected by lasi.c or asp.c and registered with the - ** above functions lasi_led_init() or asp_led_init(). - ** KittyHawk machines have often a buggy PDC, so that - ** we explicitly check for those machines here. +/** + * early_led_init() + * + * early_led_init() is called early in the bootup-process and asks the + * PDC for an usable chassis LCD or LED. If the PDC doesn't return any + * info, then a LED might be detected by the LASI or ASP drivers later. + * KittyHawk machines have often a buggy PDC, so that we explicitly check + * for those machines here. */ - -int __init led_init(void) +static int __init early_led_init(void) { struct pdc_chassis_info chassis_info; int ret; snprintf(lcd_text_default, sizeof(lcd_text_default), "Linux %s", init_utsname()->release); + strcpy(lcd_text, lcd_text_default); + lcd_new_text = 1; /* Work around the buggy PDC of KittyHawk-machines */ switch (CPU_HVERSION) { @@ -701,82 +470,86 @@ int __init led_init(void) case 0x582: /* KittyHawk DC3 100 (K400) */ case 0x583: /* KittyHawk DC3 120 (K410) */ case 0x58B: /* KittyHawk DC2 100 (K200) */ - printk(KERN_INFO "%s: KittyHawk-Machine (hversion 0x%x) found, " - "LED detection skipped.\n", __FILE__, CPU_HVERSION); + pr_info("LCD on KittyHawk-Machine found.\n"); + lcd_info.model = DISPLAY_MODEL_LCD; + /* KittyHawk has no LED support on its LCD, so skip LED detection */ lcd_no_led_support = 1; goto found; /* use the preinitialized values of lcd_info */ } /* initialize the struct, so that we can check for valid return values */ - lcd_info.model = DISPLAY_MODEL_NONE; chassis_info.actcnt = chassis_info.maxcnt = 0; ret = pdc_chassis_info(&chassis_info, &lcd_info, sizeof(lcd_info)); - if (ret == PDC_OK) { - DPRINTK((KERN_INFO "%s: chassis info: model=%d (%s), " - "lcd_width=%d, cmd_delay=%u,\n" - "%s: sizecnt=%d, actcnt=%ld, maxcnt=%ld\n", - __FILE__, lcd_info.model, - (lcd_info.model==DISPLAY_MODEL_LCD) ? "LCD" : - (lcd_info.model==DISPLAY_MODEL_LASI) ? "LED" : "unknown", - lcd_info.lcd_width, lcd_info.min_cmd_delay, - __FILE__, sizeof(lcd_info), - chassis_info.actcnt, chassis_info.maxcnt)); - DPRINTK((KERN_INFO "%s: cmd=%p, data=%p, reset1=%x, reset2=%x, act_enable=%d\n", - __FILE__, lcd_info.lcd_cmd_reg_addr, - lcd_info.lcd_data_reg_addr, lcd_info.reset_cmd1, - lcd_info.reset_cmd2, lcd_info.act_enable )); - - /* check the results. Some machines have a buggy PDC */ - if (chassis_info.actcnt <= 0 || chassis_info.actcnt != chassis_info.maxcnt) - goto not_found; + if (ret != PDC_OK) { +not_found: + lcd_info.model = DISPLAY_MODEL_NONE; + return 1; + } - switch (lcd_info.model) { - case DISPLAY_MODEL_LCD: /* LCD display */ - if (chassis_info.actcnt < - offsetof(struct pdc_chassis_lcd_info_ret_block, _pad)-1) - goto not_found; - if (!lcd_info.act_enable) { - DPRINTK((KERN_INFO "PDC prohibited usage of the LCD.\n")); - goto not_found; - } - break; - - case DISPLAY_MODEL_NONE: /* no LED or LCD available */ - printk(KERN_INFO "PDC reported no LCD or LED.\n"); + /* check the results. Some machines have a buggy PDC */ + if (chassis_info.actcnt <= 0 || chassis_info.actcnt != chassis_info.maxcnt) + goto not_found; + + switch (lcd_info.model) { + case DISPLAY_MODEL_LCD: /* LCD display */ + if (chassis_info.actcnt < + offsetof(struct pdc_chassis_lcd_info_ret_block, _pad)-1) goto not_found; + if (!lcd_info.act_enable) { + /* PDC tells LCD should not be used. */ + goto not_found; + } + break; - case DISPLAY_MODEL_LASI: /* Lasi style 8 bit LED display */ - if (chassis_info.actcnt != 8 && chassis_info.actcnt != 32) - goto not_found; - break; + case DISPLAY_MODEL_NONE: /* no LED or LCD available */ + goto not_found; - default: - printk(KERN_WARNING "PDC reported unknown LCD/LED model %d\n", - lcd_info.model); + case DISPLAY_MODEL_LASI: /* Lasi style 8 bit LED display */ + if (chassis_info.actcnt != 8 && chassis_info.actcnt != 32) goto not_found; - } /* switch() */ - -found: - /* register the LCD/LED driver */ - register_led_driver(lcd_info.model, LCD_CMD_REG, LCD_DATA_REG); - return 0; + break; - } else { /* if() */ - DPRINTK((KERN_INFO "pdc_chassis_info call failed with retval = %d\n", ret)); + default: + pr_warn("PDC reported unknown LCD/LED model %d\n", + lcd_info.model); + goto not_found; } -not_found: - lcd_info.model = DISPLAY_MODEL_NONE; - return 1; +found: + /* register the LCD/LED driver */ + return register_led_driver(lcd_info.model, LCD_CMD_REG, LCD_DATA_REG); } +arch_initcall(early_led_init); -static void __exit led_exit(void) +/** + * register_led_regions() + * + * Register_led_regions() registers the LCD/LED regions for /procfs. + * At bootup - where the initialisation of the LCD/LED often happens + * not all internal structures of request_region() are properly set up, + * so that we delay the led-registration until after busdevices_init() + * has been executed. + */ +static void __init register_led_regions(void) { - unregister_reboot_notifier(&led_notifier); - return; + switch (lcd_info.model) { + case DISPLAY_MODEL_LCD: + request_mem_region((unsigned long)LCD_CMD_REG, 1, "lcd_cmd"); + request_mem_region((unsigned long)LCD_DATA_REG, 1, "lcd_data"); + break; + case DISPLAY_MODEL_LASI: + case DISPLAY_MODEL_OLD_ASP: + request_mem_region((unsigned long)LED_DATA_REG, 1, "led_data"); + break; + } } -#ifdef CONFIG_PROC_FS -module_init(led_create_procfs) -#endif +static int __init startup_leds(void) +{ + if (platform_device_register(&platform_leds)) + printk(KERN_INFO "LED: failed to register LEDs\n"); + register_led_regions(); + return 0; +} +device_initcall(startup_leds); -- cgit v1.2.3 From 77e0ddf097d6d4ceaf898e088b133b99e0a97fa0 Mon Sep 17 00:00:00 2001 From: Helge Deller Date: Mon, 28 Aug 2023 17:29:46 +0200 Subject: parisc: ccio-dma: Create private runway procfs root entry Create an own procfs "runway" root entry for the CCIO driver. No need to share it with the sba_iommu driver, as only one of those busses can be active in one machine anyway. Signed-off-by: Helge Deller Reported-by: kernel test robot Fixes: 547259580dfa ("parisc: Move proc_mckinley_root and proc_runway_root to sba_iommu") Cc: # v6.5 --- arch/parisc/include/asm/runway.h | 3 --- drivers/parisc/ccio-dma.c | 11 +++++++---- drivers/parisc/sba_iommu.c | 2 +- 3 files changed, 8 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/arch/parisc/include/asm/runway.h b/arch/parisc/include/asm/runway.h index 5cf061376ddb..2837f0223d6d 100644 --- a/arch/parisc/include/asm/runway.h +++ b/arch/parisc/include/asm/runway.h @@ -2,9 +2,6 @@ #ifndef ASM_PARISC_RUNWAY_H #define ASM_PARISC_RUNWAY_H -/* declared in arch/parisc/kernel/setup.c */ -extern struct proc_dir_entry * proc_runway_root; - #define RUNWAY_STATUS 0x10 #define RUNWAY_DEBUG 0x40 diff --git a/drivers/parisc/ccio-dma.c b/drivers/parisc/ccio-dma.c index bd9285628b42..509a4072d50a 100644 --- a/drivers/parisc/ccio-dma.c +++ b/drivers/parisc/ccio-dma.c @@ -63,8 +63,6 @@ #undef CCIO_COLLECT_STATS #endif -#include /* for proc_runway_root */ - #ifdef DEBUG_CCIO_INIT #define DBG_INIT(x...) printk(x) #else @@ -1559,10 +1557,15 @@ static int __init ccio_probe(struct parisc_device *dev) #ifdef CONFIG_PROC_FS if (ioc_count == 0) { - proc_create_single(MODULE_NAME, 0, proc_runway_root, + struct proc_dir_entry *runway; + + runway = proc_mkdir("bus/runway", NULL); + if (runway) { + proc_create_single(MODULE_NAME, 0, runway, ccio_proc_info); - proc_create_single(MODULE_NAME"-bitmap", 0, proc_runway_root, + proc_create_single(MODULE_NAME"-bitmap", 0, runway, ccio_proc_bitmap_info); + } } #endif ioc_count++; diff --git a/drivers/parisc/sba_iommu.c b/drivers/parisc/sba_iommu.c index 33da29d65f30..f6b510675318 100644 --- a/drivers/parisc/sba_iommu.c +++ b/drivers/parisc/sba_iommu.c @@ -121,7 +121,7 @@ module_param(sba_reserve_agpgart, int, 0444); MODULE_PARM_DESC(sba_reserve_agpgart, "Reserve half of IO pdir as AGPGART"); #endif -struct proc_dir_entry *proc_runway_root __ro_after_init; +static struct proc_dir_entry *proc_runway_root __ro_after_init; struct proc_dir_entry *proc_mckinley_root __ro_after_init; /************************************ -- cgit v1.2.3