From 8ce7ad780d80d7df119a1985606a7ae9fe6b00ff Mon Sep 17 00:00:00 2001 From: Helge Deller Date: Sun, 4 Mar 2018 20:56:22 +0100 Subject: [PATCH 01/15] parisc/stifb: Use fb_memset() to avoid sparse warning Signed-off-by: Helge Deller --- drivers/video/fbdev/stifb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/video/fbdev/stifb.c b/drivers/video/fbdev/stifb.c index 6ded5c198998..3c2e4cabc08f 100644 --- a/drivers/video/fbdev/stifb.c +++ b/drivers/video/fbdev/stifb.c @@ -527,7 +527,7 @@ rattlerSetupPlanes(struct stifb_info *fb) fb->id = saved_id; for (y = 0; y < fb->info.var.yres; ++y) - memset(fb->info.screen_base + y * fb->info.fix.line_length, + fb_memset(fb->info.screen_base + y * fb->info.fix.line_length, 0xff, fb->info.var.xres * fb->info.var.bits_per_pixel/8); CRX24_SET_OVLY_MASK(fb); From c92826ef5a23422d36fb3dbe685e9215119eadc7 Mon Sep 17 00:00:00 2001 From: Helge Deller Date: Sun, 4 Mar 2018 20:57:30 +0100 Subject: [PATCH 02/15] parisc/parport_gsc: Use NULL to avoid sparse warning Signed-off-by: Helge Deller --- drivers/parport/parport_gsc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/parport/parport_gsc.c b/drivers/parport/parport_gsc.c index 5f710aaaf3da..190c0a7a1c52 100644 --- a/drivers/parport/parport_gsc.c +++ b/drivers/parport/parport_gsc.c @@ -256,7 +256,7 @@ struct parport *parport_gsc_probe_port(unsigned long base, } priv->ctr = 0xc; priv->ctr_writable = 0xff; - priv->dma_buf = 0; + priv->dma_buf = NULL; priv->dma_handle = 0; p->base = base; p->base_hi = base_hi; From 2d76978d53afb93de46ae54f722e0e24e9b2a39b Mon Sep 17 00:00:00 2001 From: Helge Deller Date: Sun, 4 Mar 2018 20:58:39 +0100 Subject: [PATCH 03/15] parisc/led: Fix sparse warnings Annotate user buffer and use NULL to avoid sparse warnings. Signed-off-by: Helge Deller --- drivers/parisc/led.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/parisc/led.c b/drivers/parisc/led.c index ff1a332d76e4..0c6e8b44b4ed 100644 --- a/drivers/parisc/led.c +++ b/drivers/parisc/led.c @@ -176,7 +176,7 @@ static int led_proc_open(struct inode *inode, struct file *file) } -static ssize_t led_proc_write(struct file *file, const char *buf, +static ssize_t led_proc_write(struct file *file, const char __user *buf, size_t count, loff_t *pos) { void *data = PDE_DATA(file_inode(file)); @@ -250,7 +250,7 @@ static int __init led_create_procfs(void) if (led_type == -1) return -1; - proc_pdc_root = proc_mkdir("pdc", 0); + proc_pdc_root = proc_mkdir("pdc", NULL); if (!proc_pdc_root) return -1; if (!lcd_no_led_support) From 3a67ca192c2b1c67b6bbe940f4746200eb427fae Mon Sep 17 00:00:00 2001 From: Helge Deller Date: Sun, 4 Mar 2018 21:00:39 +0100 Subject: [PATCH 04/15] parisc/gscps2: Fix sparse warnings Signed-off-by: Helge Deller --- drivers/input/serio/gscps2.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/drivers/input/serio/gscps2.c b/drivers/input/serio/gscps2.c index aa9f29b875de..49d8d53e50b7 100644 --- a/drivers/input/serio/gscps2.c +++ b/drivers/input/serio/gscps2.c @@ -91,7 +91,7 @@ struct gscps2port { struct parisc_device *padev; struct serio *port; spinlock_t lock; - char *addr; + char __iomem *addr; u8 act, append; /* position in buffer[] */ struct { u8 data; @@ -114,7 +114,7 @@ struct gscps2port { * wait_TBE() - wait for Transmit Buffer Empty */ -static int wait_TBE(char *addr) +static int wait_TBE(char __iomem *addr) { int timeout = 25000; /* device is expected to react within 250 msec */ while (gscps2_readb_status(addr) & GSC_STAT_TBNE) { @@ -146,14 +146,14 @@ static void gscps2_flush(struct gscps2port *ps2port) static inline int gscps2_writeb_output(struct gscps2port *ps2port, u8 data) { unsigned long flags; - char *addr = ps2port->addr; + char __iomem *addr = ps2port->addr; if (!wait_TBE(addr)) { printk(KERN_DEBUG PFX "timeout - could not write byte %#x\n", data); return 0; } - while (gscps2_readb_status(ps2port->addr) & GSC_STAT_RBNE) + while (gscps2_readb_status(addr) & GSC_STAT_RBNE) /* wait */; spin_lock_irqsave(&ps2port->lock, flags); @@ -200,13 +200,12 @@ static void gscps2_enable(struct gscps2port *ps2port, int enable) static void gscps2_reset(struct gscps2port *ps2port) { - char *addr = ps2port->addr; unsigned long flags; /* reset the interface */ spin_lock_irqsave(&ps2port->lock, flags); gscps2_flush(ps2port); - writeb(0xff, addr+GSC_RESET); + writeb(0xff, ps2port->addr + GSC_RESET); gscps2_flush(ps2port); spin_unlock_irqrestore(&ps2port->lock, flags); } From 184b922cb632371aa63a1d0ae5d9d9ea6434552d Mon Sep 17 00:00:00 2001 From: Helge Deller Date: Sun, 4 Mar 2018 21:10:09 +0100 Subject: [PATCH 05/15] parisc: Force to various endian types for sparse Signed-off-by: Helge Deller --- arch/parisc/include/asm/io.h | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/arch/parisc/include/asm/io.h b/arch/parisc/include/asm/io.h index 27c62baa9c4e..afe493b23d04 100644 --- a/arch/parisc/include/asm/io.h +++ b/arch/parisc/include/asm/io.h @@ -183,15 +183,15 @@ static inline unsigned char readb(const volatile void __iomem *addr) } static inline unsigned short readw(const volatile void __iomem *addr) { - return le16_to_cpu(__raw_readw(addr)); + return le16_to_cpu((__le16 __force) __raw_readw(addr)); } static inline unsigned int readl(const volatile void __iomem *addr) { - return le32_to_cpu(__raw_readl(addr)); + return le32_to_cpu((__le32 __force) __raw_readl(addr)); } static inline unsigned long long readq(const volatile void __iomem *addr) { - return le64_to_cpu(__raw_readq(addr)); + return le64_to_cpu((__le64 __force) __raw_readq(addr)); } static inline void writeb(unsigned char b, volatile void __iomem *addr) @@ -200,15 +200,15 @@ static inline void writeb(unsigned char b, volatile void __iomem *addr) } static inline void writew(unsigned short w, volatile void __iomem *addr) { - __raw_writew(cpu_to_le16(w), addr); + __raw_writew((__u16 __force) cpu_to_le16(w), addr); } static inline void writel(unsigned int l, volatile void __iomem *addr) { - __raw_writel(cpu_to_le32(l), addr); + __raw_writel((__u32 __force) cpu_to_le32(l), addr); } static inline void writeq(unsigned long long q, volatile void __iomem *addr) { - __raw_writeq(cpu_to_le64(q), addr); + __raw_writeq((__u64 __force) cpu_to_le64(q), addr); } #define readb readb From d5b59a71204b0a9a55eda633347b1214642bead3 Mon Sep 17 00:00:00 2001 From: Helge Deller Date: Tue, 26 Sep 2017 00:21:27 +0200 Subject: [PATCH 06/15] parisc: Convert MAP_TYPE to cover 4 bits on parisc On parisc we want to be as much as possible compatible to the major architectures like x86. Those architectures have MAP_TYPE defined as 0x0f which covers MAP_SHARED and MAP_PRIVATE and leaves two more bits unused. In contrast, on parisc we have MAP_TYPE defined to 0x03 which covers MAP_SHARED and MAP_PRIVATE only. But we don't have the 2 bits free as x86. Usually that's not a problem, but during the discussions for pmem+dax support the idea came up to use the two remaining bits of MAP_TYPE (on x86 and others) for the new MAP_DIRECT and MAP_SYNC flags. One requirement is, that an old kernel should correctly handle MAP_DIRECT and MAP_SYNC and fail on those if set. This only works if MAP_TYPE has 4 bits. Even though the pmem+dax people now choosed another solution via MAP_SHARED_VALIDATE, let's still proceed to be more compatible to x86 by adding two more bits for future usage. Signed-off-by: Helge Deller Signed-off-by: John David Anglin --- arch/parisc/include/uapi/asm/mman.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/parisc/include/uapi/asm/mman.h b/arch/parisc/include/uapi/asm/mman.h index 80510ba44c08..a056a642bb31 100644 --- a/arch/parisc/include/uapi/asm/mman.h +++ b/arch/parisc/include/uapi/asm/mman.h @@ -13,7 +13,7 @@ #define MAP_SHARED 0x01 /* Share changes */ #define MAP_PRIVATE 0x02 /* Changes are private */ #define MAP_SHARED_VALIDATE 0x03 /* share + validate extension flags */ -#define MAP_TYPE 0x03 /* Mask for type of mapping */ +#define MAP_TYPE 0x2b /* Mask for type of mapping, includes bits 0x08 and 0x20 */ #define MAP_FIXED 0x04 /* Interpret addr exactly */ #define MAP_ANONYMOUS 0x10 /* don't use a file */ From b86db40e1ecc910c73b6bed8368816d9ae378fb6 Mon Sep 17 00:00:00 2001 From: Helge Deller Date: Sun, 4 Mar 2018 22:26:11 +0100 Subject: [PATCH 07/15] parisc: Move various functions and strings to init section Signed-off-by: Helge Deller --- arch/parisc/kernel/drivers.c | 22 +++++++++++----------- arch/parisc/kernel/hardware.c | 12 ++++++------ 2 files changed, 17 insertions(+), 17 deletions(-) diff --git a/arch/parisc/kernel/drivers.c b/arch/parisc/kernel/drivers.c index 29b99b8964aa..d4256145b74c 100644 --- a/arch/parisc/kernel/drivers.c +++ b/arch/parisc/kernel/drivers.c @@ -135,7 +135,7 @@ static int parisc_driver_probe(struct device *dev) return rc; } -static int parisc_driver_remove(struct device *dev) +static int __exit parisc_driver_remove(struct device *dev) { struct parisc_device *pa_dev = to_parisc_device(dev); struct parisc_driver *pa_drv = to_parisc_driver(dev->driver); @@ -205,7 +205,7 @@ static int match_and_count(struct device * dev, void * data) * Use by IOMMU support to "guess" the right size IOPdir. * Formula is something like memsize/(num_iommu * entry_size). */ -int count_parisc_driver(struct parisc_driver *driver) +int __init count_parisc_driver(struct parisc_driver *driver) { struct match_count m = { .driver = driver, @@ -268,7 +268,7 @@ static struct parisc_device *find_device_by_addr(unsigned long hpa) * Walks up the device tree looking for a device of the specified type. * If it finds it, it returns it. If not, it returns NULL. */ -const struct parisc_device * +const struct parisc_device * __init find_pa_parent_type(const struct parisc_device *padev, int type) { const struct device *dev = &padev->dev; @@ -397,7 +397,7 @@ static void setup_bus_id(struct parisc_device *padev) dev_set_name(&padev->dev, name); } -struct parisc_device * create_tree_node(char id, struct device *parent) +struct parisc_device * __init create_tree_node(char id, struct device *parent) { struct parisc_device *dev = kzalloc(sizeof(*dev), GFP_KERNEL); if (!dev) @@ -471,7 +471,7 @@ static struct parisc_device *create_parisc_device(struct hardware_path *modpath) return alloc_tree_node(parent, modpath->mod); } -struct parisc_device * +struct parisc_device * __init alloc_pa_dev(unsigned long hpa, struct hardware_path *mod_path) { int status; @@ -609,7 +609,7 @@ struct bus_type parisc_bus_type = { .uevent = parisc_uevent, .dev_groups = parisc_device_groups, .probe = parisc_driver_probe, - .remove = parisc_driver_remove, + .remove = __exit_p(parisc_driver_remove), }; /** @@ -619,7 +619,7 @@ struct bus_type parisc_bus_type = { * Search the driver list for a driver that is willing to manage * this device. */ -int register_parisc_device(struct parisc_device *dev) +int __init register_parisc_device(struct parisc_device *dev) { if (!dev) return 0; @@ -791,7 +791,7 @@ EXPORT_SYMBOL(device_to_hwpath); static void walk_native_bus(unsigned long io_io_low, unsigned long io_io_high, struct device *parent); -void walk_lower_bus(struct parisc_device *dev) +static void walk_lower_bus(struct parisc_device *dev) { unsigned long io_io_low, io_io_high; @@ -857,7 +857,7 @@ static void walk_native_bus(unsigned long io_io_low, unsigned long io_io_high, * PDC doesn't tell us about all devices in the system. This routine * finds devices connected to the central bus. */ -void walk_central_bus(void) +void __init walk_central_bus(void) { walk_native_bus(CENTRAL_BUS_ADDR, CENTRAL_BUS_ADDR + (MAX_NATIVE_DEVICES * NATIVE_DEVICE_OFFSET), @@ -886,7 +886,7 @@ static void print_parisc_device(struct parisc_device *dev) /** * init_parisc_bus - Some preparation to be done before inventory */ -void init_parisc_bus(void) +void __init init_parisc_bus(void) { if (bus_register(&parisc_bus_type)) panic("Could not register PA-RISC bus type\n"); @@ -908,7 +908,7 @@ static int print_one_device(struct device * dev, void * data) /** * print_parisc_devices - Print out a list of devices found in this system */ -void print_parisc_devices(void) +void __init print_parisc_devices(void) { for_each_padev(print_one_device, NULL); } diff --git a/arch/parisc/kernel/hardware.c b/arch/parisc/kernel/hardware.c index af3bc359dc70..a2058953a53f 100644 --- a/arch/parisc/kernel/hardware.c +++ b/arch/parisc/kernel/hardware.c @@ -41,7 +41,7 @@ * are guessed. If you know the correct name, please let us know. */ -static struct hp_hardware hp_hardware_list[] = { +static struct hp_hardware hp_hardware_list[] __initdata = { {HPHW_NPROC,0x01,0x4,0x0,"Indigo (840, 930)"}, {HPHW_NPROC,0x8,0x4,0x01,"Firefox(825,925)"}, {HPHW_NPROC,0xA,0x4,0x01,"Top Gun (835,834,935,635)"}, @@ -1238,7 +1238,7 @@ static struct hp_cpu_type_mask { unsigned short model; unsigned short mask; enum cpu_type cpu; -} hp_cpu_type_mask_list[] = { +} hp_cpu_type_mask_list[] __initdata = { { 0x0000, 0x0ff0, pcx }, /* 0x0000 - 0x000f */ { 0x0048, 0x0ff0, pcxl }, /* 0x0040 - 0x004f */ @@ -1325,17 +1325,17 @@ const char * const cpu_name_version[][2] = { [pcxt] = { "PA7100 (PCX-T)", "1.1b" }, [pcxt_] = { "PA7200 (PCX-T')", "1.1c" }, [pcxl] = { "PA7100LC (PCX-L)", "1.1d" }, - [pcxl2] = { "PA7300LC (PCX-L2)", "1.1e" }, + [pcxl2] = { "PA7300LC (PCX-L2)","1.1e" }, [pcxu] = { "PA8000 (PCX-U)", "2.0" }, [pcxu_] = { "PA8200 (PCX-U+)", "2.0" }, [pcxw] = { "PA8500 (PCX-W)", "2.0" }, [pcxw_] = { "PA8600 (PCX-W+)", "2.0" }, [pcxw2] = { "PA8700 (PCX-W2)", "2.0" }, [mako] = { "PA8800 (Mako)", "2.0" }, - [mako2] = { "PA8900 (Shortfin)", "2.0" } + [mako2] = { "PA8900 (Shortfin)","2.0" } }; -const char *parisc_hardware_description(struct parisc_device_id *id) +const char * __init parisc_hardware_description(struct parisc_device_id *id) { struct hp_hardware *listptr; @@ -1373,7 +1373,7 @@ const char *parisc_hardware_description(struct parisc_device_id *id) /* Interpret hversion (ret[0]) from PDC_MODEL(4)/PDC_MODEL_INFO(0) */ -enum cpu_type +enum cpu_type __init parisc_get_cpu_type(unsigned long hversion) { struct hp_cpu_type_mask *ptr; From acc2a51add8efac2c8925eb981792c0f11c88dfb Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Tue, 6 Mar 2018 13:06:19 +0300 Subject: [PATCH 08/15] parisc: Silence uninitialized variable warning in dbl_to_sgl_fcnvff() Smatch warns that is_tiny can be used uninitialized: arch/parisc/math-emu/fcnvff.c:297 dbl_to_sgl_fcnvff() error: uninitialized symbol 'is_tiny'. This code is very old so that suggests the bug doesn't have a huge affect in real life. But I've read the code and it seems like a reasonable warning. Either way it should be harmless to initialize it to false and silence the static checker warning. Signed-off-by: Dan Carpenter Signed-off-by: Helge Deller --- arch/parisc/math-emu/fcnvff.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/parisc/math-emu/fcnvff.c b/arch/parisc/math-emu/fcnvff.c index 76c063f7d17c..f9357d9d4cb1 100644 --- a/arch/parisc/math-emu/fcnvff.c +++ b/arch/parisc/math-emu/fcnvff.c @@ -148,7 +148,7 @@ dbl_to_sgl_fcnvff( register int src_exponent, dest_exponent, dest_mantissa; register boolean inexact = FALSE, guardbit = FALSE, stickybit = FALSE; register boolean lsb_odd = FALSE; - boolean is_tiny; + boolean is_tiny = FALSE; Dbl_copyfromptr(srcptr,srcp1,srcp2); src_exponent = Dbl_exponent(srcp1); From 2a3f53d5530c02d7bc7c78b11e6a2c24dc767e9c Mon Sep 17 00:00:00 2001 From: Helge Deller Date: Tue, 13 Mar 2018 20:56:16 +0100 Subject: [PATCH 09/15] parisc/Kconfig: SMP kernels boot on all machines I'm not aware of any machines which won't be able to run our SMP kernel. Refine the Kconfig help text. Signed-off-by: Helge Deller --- arch/parisc/Kconfig | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/arch/parisc/Kconfig b/arch/parisc/Kconfig index 9792d8cf4f56..7e0bb9836b58 100644 --- a/arch/parisc/Kconfig +++ b/arch/parisc/Kconfig @@ -276,10 +276,8 @@ config SMP than one CPU, say Y. If you say N here, the kernel will run on uni- and multiprocessor - machines, but will use only one CPU of a multiprocessor machine. If - you say Y here, the kernel will run on many, but not all, - uniprocessor machines. On a uniprocessor machine, the kernel - will run faster if you say N here. + machines, but will use only one CPU of a multiprocessor machine. + On a uniprocessor machine, the kernel will run faster if you say N. See also and the SMP-HOWTO available at . From 24002d59376e2d19a2a523fe88d5b32e691a43af Mon Sep 17 00:00:00 2001 From: Helge Deller Date: Sat, 24 Mar 2018 20:49:39 +0100 Subject: [PATCH 10/15] parisc: machine_power_off() should call pm_power_off() Signed-off-by: Helge Deller Tested-by: Matt Turner --- arch/parisc/kernel/process.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/arch/parisc/kernel/process.c b/arch/parisc/kernel/process.c index 6975a0627078..bbe46571ff96 100644 --- a/arch/parisc/kernel/process.c +++ b/arch/parisc/kernel/process.c @@ -138,6 +138,10 @@ void machine_power_off(void) pdc_soft_power_button(0); pdc_chassis_send_status(PDC_CHASSIS_DIRECT_SHUTDOWN); + + /* ipmi_poweroff may have been installed. */ + if (pm_power_off) + pm_power_off(); /* It seems we have no way to power the system off via * software. The user has to press the button himself. */ @@ -151,7 +155,7 @@ void machine_power_off(void) for (;;); } -void (*pm_power_off)(void) = machine_power_off; +void (*pm_power_off)(void); EXPORT_SYMBOL(pm_power_off); void flush_thread(void) From c14b302c44f61dce219e1f4026d3c9248e81fbd2 Mon Sep 17 00:00:00 2001 From: Helge Deller Date: Sat, 24 Mar 2018 21:00:14 +0100 Subject: [PATCH 11/15] parisc: Directly call machine_power_off() in power button driver Signed-off-by: Helge Deller Tested-by: Matt Turner --- drivers/parisc/power.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/parisc/power.c b/drivers/parisc/power.c index e2a3112f1c98..ebaf6867b457 100644 --- a/drivers/parisc/power.c +++ b/drivers/parisc/power.c @@ -95,8 +95,7 @@ static void process_shutdown(void) /* send kill signal */ if (kill_cad_pid(SIGINT, 1)) { /* just in case killing init process failed */ - if (pm_power_off) - pm_power_off(); + machine_power_off(); } } } From d5654e156bc4d68a87bbaa6d7e020baceddf6e68 Mon Sep 17 00:00:00 2001 From: Helge Deller Date: Sat, 24 Mar 2018 21:18:25 +0100 Subject: [PATCH 12/15] parisc: Fix HPMC handler by increasing size to multiple of 16 bytes Make sure that the HPMC (High Priority Machine Check) handler is 16-byte aligned and that it's length in the IVT is a multiple of 16 bytes. Otherwise PDC may decide not to call the HPMC crash handler. Signed-off-by: Helge Deller Cc: stable@vger.kernel.org --- arch/parisc/kernel/hpmc.S | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/arch/parisc/kernel/hpmc.S b/arch/parisc/kernel/hpmc.S index 8d072c44f300..781c3b9a3e46 100644 --- a/arch/parisc/kernel/hpmc.S +++ b/arch/parisc/kernel/hpmc.S @@ -84,6 +84,7 @@ END(hpmc_pim_data) .text .import intr_save, code + .align 16 ENTRY_CFI(os_hpmc) .os_hpmc: @@ -300,12 +301,15 @@ os_hpmc_6: b . nop + .align 16 /* make function length multiple of 16 bytes */ ENDPROC_CFI(os_hpmc) .os_hpmc_end: __INITRODATA +.globl os_hpmc_size .align 4 - .export os_hpmc_size + .type os_hpmc_size, @object + .size os_hpmc_size, 4 os_hpmc_size: .word .os_hpmc_end-.os_hpmc From b845f66f78bf42a4ce98e5cfe0e94fab41dd0742 Mon Sep 17 00:00:00 2001 From: Helge Deller Date: Sun, 25 Mar 2018 14:04:22 +0200 Subject: [PATCH 13/15] parisc/pci: Switch LBA PCI bus from Hard Fail to Soft Fail mode Carlo Pisani noticed that his C3600 workstation behaved unstable during heavy I/O on the PCI bus with a VIA VT6421 IDE/SATA PCI card. To avoid such instability, this patch switches the LBA PCI bus from Hard Fail mode into Soft Fail mode. In this mode the bus will return -1UL for timed out MMIO transactions, which is exactly how the x86 (and most other architectures) PCI busses behave. This patch is based on a proposal by Grant Grundler and Kyle McMartin 10 years ago: https://www.spinics.net/lists/linux-parisc/msg01027.html Cc: Carlo Pisani Cc: Kyle McMartin Reviewed-by: Grant Grundler Signed-off-by: Helge Deller --- drivers/parisc/lba_pci.c | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/drivers/parisc/lba_pci.c b/drivers/parisc/lba_pci.c index 41b740aed3a3..69bd98421eb1 100644 --- a/drivers/parisc/lba_pci.c +++ b/drivers/parisc/lba_pci.c @@ -1403,9 +1403,27 @@ lba_hw_init(struct lba_device *d) WRITE_REG32(stat, d->hba.base_addr + LBA_ERROR_CONFIG); } - /* Set HF mode as the default (vs. -1 mode). */ + + /* + * Hard Fail vs. Soft Fail on PCI "Master Abort". + * + * "Master Abort" means the MMIO transaction timed out - usually due to + * the device not responding to an MMIO read. We would like HF to be + * enabled to find driver problems, though it means the system will + * crash with a HPMC. + * + * In SoftFail mode "~0L" is returned as a result of a timeout on the + * pci bus. This is like how PCI busses on x86 and most other + * architectures behave. In order to increase compatibility with + * existing (x86) PCI hardware and existing Linux drivers we enable + * Soft Faul mode on PA-RISC now too. + */ stat = READ_REG32(d->hba.base_addr + LBA_STAT_CTL); +#if defined(ENABLE_HARDFAIL) WRITE_REG32(stat | HF_ENABLE, d->hba.base_addr + LBA_STAT_CTL); +#else + WRITE_REG32(stat & ~HF_ENABLE, d->hba.base_addr + LBA_STAT_CTL); +#endif /* ** Writing a zero to STAT_CTL.rf (bit 0) will clear reset signal From a77ab0e7ce232a62adac3d85b9ae66d0f48385ac Mon Sep 17 00:00:00 2001 From: Helge Deller Date: Sun, 25 Mar 2018 18:52:58 +0200 Subject: [PATCH 14/15] parisc: Add code generator for Qemu/SeaBIOS machine info Qemu now supports emulating PA-RISC machines. For that a forked version of SeaBIOS available at https://github.com/hdeller/seabios-hppa is used which requires some information about the emulated machine. This patch adds code to generate a header file with the necessary information for SeaBIOS. The information is extracted from the firmware the current kernel is running on. Tested on a B160L workstation. Signed-off-by: Helge Deller --- arch/parisc/kernel/drivers.c | 171 +++++++++++++++++++++++++++++++++++ 1 file changed, 171 insertions(+) diff --git a/arch/parisc/kernel/drivers.c b/arch/parisc/kernel/drivers.c index d4256145b74c..6afb595e0d86 100644 --- a/arch/parisc/kernel/drivers.c +++ b/arch/parisc/kernel/drivers.c @@ -895,6 +895,171 @@ void __init init_parisc_bus(void) get_device(&root); } +static __init void qemu_header(void) +{ + int num; + unsigned long *p; + + pr_info("--- cut here ---\n"); + pr_info("/* AUTO-GENERATED HEADER FILE FOR SEABIOS FIRMWARE */\n"); + pr_cont("/* generated with Linux kernel */\n"); + pr_cont("/* search for PARISC_QEMU_MACHINE_HEADER in Linux */\n\n"); + + pr_info("#define PARISC_MODEL \"%s\"\n\n", + boot_cpu_data.pdc.sys_model_name); + + pr_info("#define PARISC_PDC_MODEL 0x%lx, 0x%lx, 0x%lx, " + "0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx\n\n", + #define p ((unsigned long *)&boot_cpu_data.pdc.model) + p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7], p[8]); + #undef p + + pr_info("#define PARISC_PDC_VERSION 0x%04lx\n\n", + boot_cpu_data.pdc.versions); + + pr_info("#define PARISC_PDC_CPUID 0x%04lx\n\n", + boot_cpu_data.pdc.cpuid); + + pr_info("#define PARISC_PDC_CAPABILITIES 0x%04lx\n\n", + boot_cpu_data.pdc.capabilities); + + pr_info("#define PARISC_PDC_ENTRY_ORG 0x%04lx\n\n", +#ifdef CONFIG_64BIT + (unsigned long)(PAGE0->mem_pdc_hi) << 32 | +#endif + (unsigned long)PAGE0->mem_pdc); + + pr_info("#define PARISC_PDC_CACHE_INFO"); + p = (unsigned long *) &cache_info; + for (num = 0; num < sizeof(cache_info); num += sizeof(unsigned long)) { + if (((num % 5) == 0)) { + pr_cont(" \\\n"); + pr_info("\t"); + } + pr_cont("%s0x%04lx", + num?", ":"", *p++); + } + pr_cont("\n\n"); +} + +static __init int qemu_print_hpa(struct device *lin_dev, void *data) +{ + struct parisc_device *dev = to_parisc_device(lin_dev); + unsigned long hpa = dev->hpa.start; + + pr_cont("\t{\t.hpa = 0x%08lx,\\\n", hpa); + pr_cont("\t\t.iodc = &iodc_data_hpa_%08lx,\\\n", hpa); + pr_cont("\t\t.mod_info = &mod_info_hpa_%08lx,\\\n", hpa); + pr_cont("\t\t.mod_path = &mod_path_hpa_%08lx,\\\n", hpa); + pr_cont("\t\t.num_addr = HPA_%08lx_num_addr,\\\n", hpa); + pr_cont("\t\t.add_addr = { HPA_%08lx_add_addr } },\\\n", hpa); + return 0; +} + + +static __init void qemu_footer(void) +{ + pr_info("\n\n#define PARISC_DEVICE_LIST \\\n"); + for_each_padev(qemu_print_hpa, NULL); + pr_cont("\t{ 0, }\n"); + pr_info("--- cut here ---\n"); +} + +/* print iodc data of the various hpa modules for qemu inclusion */ +static __init int qemu_print_iodc_data(struct device *lin_dev, void *data) +{ + struct parisc_device *dev = to_parisc_device(lin_dev); + unsigned long count; + unsigned long hpa = dev->hpa.start; + int status; + struct pdc_iodc iodc_data; + + int mod_index; + struct pdc_system_map_mod_info pdc_mod_info; + struct pdc_module_path mod_path; + + status = pdc_iodc_read(&count, hpa, 0, + &iodc_data, sizeof(iodc_data)); + if (status != PDC_OK) { + pr_info("No IODC data for hpa 0x%08lx\n", hpa); + return 0; + } + + pr_info("\n"); + + pr_info("#define HPA_%08lx_DESCRIPTION \"%s\"\n", + hpa, parisc_hardware_description(&dev->id)); + + mod_index = 0; + do { + status = pdc_system_map_find_mods(&pdc_mod_info, + &mod_path, mod_index++); + } while (status == PDC_OK && pdc_mod_info.mod_addr != hpa); + + pr_info("static struct pdc_system_map_mod_info" + " mod_info_hpa_%08lx = {\n", hpa); + #define DO(member) \ + pr_cont("\t." #member " = 0x%x,\n", \ + (unsigned int)pdc_mod_info.member) + DO(mod_addr); + DO(mod_pgs); + DO(add_addrs); + pr_cont("};\n"); + #undef DO + pr_info("static struct pdc_module_path " + "mod_path_hpa_%08lx = {\n", hpa); + pr_cont("\t.path = { "); + pr_cont(".flags = 0x%x, ", mod_path.path.flags); + pr_cont(".bc = { 0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x }, ", + (unsigned char)mod_path.path.bc[0], + (unsigned char)mod_path.path.bc[1], + (unsigned char)mod_path.path.bc[2], + (unsigned char)mod_path.path.bc[3], + (unsigned char)mod_path.path.bc[4], + (unsigned char)mod_path.path.bc[5]); + pr_cont(".mod = 0x%x ", mod_path.path.mod); + pr_cont(" },\n"); + pr_cont("\t.layers = { 0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x }\n", + mod_path.layers[0], mod_path.layers[1], mod_path.layers[2], + mod_path.layers[3], mod_path.layers[4], mod_path.layers[5]); + pr_cont("};\n"); + + pr_info("static struct pdc_iodc iodc_data_hpa_%08lx = {\n", hpa); + #define DO(member) \ + pr_cont("\t." #member " = 0x%04lx,\n", \ + (unsigned long)iodc_data.member) + DO(hversion_model); + DO(hversion); + DO(spa); + DO(type); + DO(sversion_rev); + DO(sversion_model); + DO(sversion_opt); + DO(rev); + DO(dep); + DO(features); + DO(checksum); + DO(length); + #undef DO + pr_cont("\t/* pad: 0x%04x, 0x%04x */\n", + iodc_data.pad[0], iodc_data.pad[1]); + pr_cont("};\n"); + + pr_info("#define HPA_%08lx_num_addr %d\n", hpa, dev->num_addrs); + pr_info("#define HPA_%08lx_add_addr ", hpa); + count = 0; + if (dev->num_addrs == 0) + pr_cont("0"); + while (count < dev->num_addrs) { + pr_cont("0x%08lx, ", dev->addr[count]); + count++; + } + pr_cont("\n\n"); + + return 0; +} + + static int print_one_device(struct device * dev, void * data) { @@ -911,4 +1076,10 @@ static int print_one_device(struct device * dev, void * data) void __init print_parisc_devices(void) { for_each_padev(print_one_device, NULL); + #define PARISC_QEMU_MACHINE_HEADER 0 + if (PARISC_QEMU_MACHINE_HEADER) { + qemu_header(); + for_each_padev(qemu_print_iodc_data, NULL); + qemu_footer(); + } } From 615b2665fd20c327b631ff1e79426775de748094 Mon Sep 17 00:00:00 2001 From: Helge Deller Date: Sun, 25 Mar 2018 23:53:22 +0200 Subject: [PATCH 15/15] parisc: Fix out of array access in match_pci_device() As found by the ubsan checker, the value of the 'index' variable can be out of range for the bc[] array: UBSAN: Undefined behaviour in arch/parisc/kernel/drivers.c:655:21 index 6 is out of range for type 'char [6]' Backtrace: [<104fa850>] __ubsan_handle_out_of_bounds+0x68/0x80 [<1019d83c>] check_parent+0xc0/0x170 [<1019d91c>] descend_children+0x30/0x6c [<1059e164>] device_for_each_child+0x60/0x98 [<1019cd54>] parse_tree_node+0x40/0x54 [<1019d86c>] check_parent+0xf0/0x170 [<1019d91c>] descend_children+0x30/0x6c [<1059e164>] device_for_each_child+0x60/0x98 [<1019d938>] descend_children+0x4c/0x6c [<1059e164>] device_for_each_child+0x60/0x98 [<1019cd54>] parse_tree_node+0x40/0x54 [<1019cffc>] hwpath_to_device+0xa4/0xc4 Signed-off-by: Helge Deller Cc: stable@vger.kernel.org --- arch/parisc/kernel/drivers.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/arch/parisc/kernel/drivers.c b/arch/parisc/kernel/drivers.c index 6afb595e0d86..3b8507f71050 100644 --- a/arch/parisc/kernel/drivers.c +++ b/arch/parisc/kernel/drivers.c @@ -651,6 +651,10 @@ static int match_pci_device(struct device *dev, int index, (modpath->mod == PCI_FUNC(devfn))); } + /* index might be out of bounds for bc[] */ + if (index >= 6) + return 0; + id = PCI_SLOT(pdev->devfn) | (PCI_FUNC(pdev->devfn) << 5); return (modpath->bc[index] == id); }