From 24587380f61d20e36662fbd4d938431e33e3eda2 Mon Sep 17 00:00:00 2001 From: Helge Deller <deller@gmx.de> Date: Fri, 4 Aug 2017 20:07:41 +0200 Subject: parisc: Add MADV_HWPOISON and MADV_SOFT_OFFLINE Add the missing MADV_HWPOISON (100) and MADV_SOFT_OFFLINE (101) defines which are needed for an upcoming patch which adds page-deallocation for parisc. Signed-off-by: Helge Deller <deller@gmx.de> --- arch/parisc/include/uapi/asm/mman.h | 3 +++ tools/arch/parisc/include/uapi/asm/mman.h | 2 -- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/arch/parisc/include/uapi/asm/mman.h b/arch/parisc/include/uapi/asm/mman.h index 5979745815a5..2e7b8c2431a3 100644 --- a/arch/parisc/include/uapi/asm/mman.h +++ b/arch/parisc/include/uapi/asm/mman.h @@ -60,6 +60,9 @@ overrides the coredump filter bits */ #define MADV_DODUMP 70 /* Clear the MADV_NODUMP flag */ +#define MADV_HWPOISON 100 /* poison a page for testing */ +#define MADV_SOFT_OFFLINE 101 /* soft offline page for testing */ + /* compatibility flags */ #define MAP_FILE 0 #define MAP_VARIABLE 0 diff --git a/tools/arch/parisc/include/uapi/asm/mman.h b/tools/arch/parisc/include/uapi/asm/mman.h index 03d8d5b7ae7f..286c0bd74573 100644 --- a/tools/arch/parisc/include/uapi/asm/mman.h +++ b/tools/arch/parisc/include/uapi/asm/mman.h @@ -36,9 +36,7 @@ #define PROT_READ 0x1 #define PROT_SEM 0x8 #define PROT_WRITE 0x2 -/* MADV_HWPOISON is undefined on parisc, fix it for perf */ #define MADV_HWPOISON 100 -/* MADV_SOFT_OFFLINE is undefined on parisc, fix it for perf */ #define MADV_SOFT_OFFLINE 101 /* MAP_32BIT is undefined on parisc, fix it for perf */ #define MAP_32BIT 0 -- cgit v1.2.3-70-g09d2 From 8a5aa00e6b9630d36d7681b38062a3d48d8b6ee6 Mon Sep 17 00:00:00 2001 From: Helge Deller <deller@gmx.de> Date: Fri, 4 Aug 2017 19:12:39 +0200 Subject: parisc: PDT/firmware: Add support to read PDT on older PAT-machines Older machines with a PAT firmware (e.g. the rp5470) return their Page Deallocation Table (PDT) info per cell via the PDC_PAT_MEM_PD_INFO PDC call. This patch adds the necessary structures and wrappers to call firmware. Signed-off-by: Helge Deller <deller@gmx.de> --- arch/parisc/include/asm/pdcpat.h | 14 ++++++++++++ arch/parisc/kernel/firmware.c | 47 +++++++++++++++++++++++++++++++++------- 2 files changed, 53 insertions(+), 8 deletions(-) diff --git a/arch/parisc/include/asm/pdcpat.h b/arch/parisc/include/asm/pdcpat.h index e3c0586260d8..a468a172ee33 100644 --- a/arch/parisc/include/asm/pdcpat.h +++ b/arch/parisc/include/asm/pdcpat.h @@ -223,6 +223,18 @@ struct pdc_pat_mem_retinfo { /* PDC_PAT_MEM/PDC_PAT_MEM_PD_INFO (return info) */ unsigned long clear_time; /* last PDT clear time (since Jan 1970) */ }; +struct pdc_pat_mem_cell_pdt_retinfo { /* PDC_PAT_MEM/PDC_PAT_MEM_CELL_INFO */ + u64 reserved:32; + u64 cs:1; /* clear status: cleared since the last call? */ + u64 current_pdt_entries:15; + u64 ic:1; /* interleaving had to be changed ? */ + u64 max_pdt_entries:15; + unsigned long good_mem; + unsigned long first_dbe_loc; /* first location of double bit error */ + unsigned long clear_time; /* last PDT clear time (since Jan 1970) */ +}; + + struct pdc_pat_mem_read_pd_retinfo { /* PDC_PAT_MEM/PDC_PAT_MEM_PD_READ */ unsigned long actual_count_bytes; unsigned long pdt_entries; @@ -325,6 +337,8 @@ extern int pdc_pat_io_pci_cfg_read(unsigned long pci_addr, int pci_size, u32 *va extern int pdc_pat_io_pci_cfg_write(unsigned long pci_addr, int pci_size, u32 val); extern int pdc_pat_mem_pdt_info(struct pdc_pat_mem_retinfo *rinfo); +extern int pdc_pat_mem_pdt_cell_info(struct pdc_pat_mem_cell_pdt_retinfo *rinfo, + unsigned long cell); extern int pdc_pat_mem_read_cell_pdt(struct pdc_pat_mem_read_pd_retinfo *pret, unsigned long *pdt_entries_ptr, unsigned long max_entries); extern int pdc_pat_mem_read_pd_pdt(struct pdc_pat_mem_read_pd_retinfo *pret, diff --git a/arch/parisc/kernel/firmware.c b/arch/parisc/kernel/firmware.c index f622a311d04a..be9a2e89e90f 100644 --- a/arch/parisc/kernel/firmware.c +++ b/arch/parisc/kernel/firmware.c @@ -142,8 +142,8 @@ static void convert_to_wide(unsigned long *addr) int i; unsigned int *p = (unsigned int *)addr; - if(unlikely(parisc_narrow_firmware)) { - for(i = 31; i >= 0; --i) + if (unlikely(parisc_narrow_firmware)) { + for (i = (NUM_PDC_RESULT-1); i >= 0; --i) addr[i] = p[i]; } #endif @@ -979,16 +979,22 @@ int pdc_mem_pdt_read_entries(struct pdc_mem_read_pdt *pret, spin_lock_irqsave(&pdc_lock, flags); retval = mem_pdc_call(PDC_MEM, PDC_MEM_READ_PDT, __pa(pdc_result), - __pa(pdc_result2)); + __pa(pdt_entries_ptr)); if (retval == PDC_OK) { convert_to_wide(pdc_result); memcpy(pret, pdc_result, sizeof(*pret)); - convert_to_wide(pdc_result2); - memcpy(pdt_entries_ptr, pdc_result2, - pret->pdt_entries * sizeof(*pdt_entries_ptr)); } spin_unlock_irqrestore(&pdc_lock, flags); +#ifdef CONFIG_64BIT + /* + * 64-bit kernels should not call this PDT function in narrow mode. + * The pdt_entries_ptr array above will now contain 32-bit values + */ + if (WARN_ON_ONCE((retval == PDC_OK) && parisc_narrow_firmware)) + return PDC_ERROR; +#endif + return retval; } @@ -1439,6 +1445,29 @@ int pdc_pat_mem_pdt_info(struct pdc_pat_mem_retinfo *rinfo) return retval; } +/** + * pdc_pat_mem_pdt_cell_info - Retrieve information about page deallocation + * table of a cell + * @rinfo: memory pdt information + * @cell: cell number + * + */ +int pdc_pat_mem_pdt_cell_info(struct pdc_pat_mem_cell_pdt_retinfo *rinfo, + unsigned long cell) +{ + int retval; + unsigned long flags; + + spin_lock_irqsave(&pdc_lock, flags); + retval = mem_pdc_call(PDC_PAT_MEM, PDC_PAT_MEM_CELL_INFO, + __pa(&pdc_result), cell); + if (retval == PDC_OK) + memcpy(rinfo, &pdc_result, sizeof(*rinfo)); + spin_unlock_irqrestore(&pdc_lock, flags); + + return retval; +} + /** * pdc_pat_mem_read_cell_pdt - Read PDT entries from (old) PAT firmware * @pret: array of PDT entries @@ -1455,14 +1484,14 @@ int pdc_pat_mem_read_cell_pdt(struct pdc_pat_mem_read_pd_retinfo *pret, spin_lock_irqsave(&pdc_lock, flags); /* PDC_PAT_MEM_CELL_READ is available on early PAT machines only */ retval = mem_pdc_call(PDC_PAT_MEM, PDC_PAT_MEM_CELL_READ, - __pa(&pdc_result), parisc_cell_num, __pa(&pdc_result2)); + __pa(&pdc_result), parisc_cell_num, + __pa(pdt_entries_ptr)); if (retval == PDC_OK) { /* build up return value as for PDC_PAT_MEM_PD_READ */ entries = min(pdc_result[0], max_entries); pret->pdt_entries = entries; pret->actual_count_bytes = entries * sizeof(unsigned long); - memcpy(pdt_entries_ptr, &pdc_result2, pret->actual_count_bytes); } spin_unlock_irqrestore(&pdc_lock, flags); @@ -1474,6 +1503,8 @@ int pdc_pat_mem_read_cell_pdt(struct pdc_pat_mem_read_pd_retinfo *pret, * pdc_pat_mem_read_pd_pdt - Read PDT entries from (newer) PAT firmware * @pret: array of PDT entries * @pdt_entries_ptr: ptr to hold number of PDT entries + * @count: number of bytes to read + * @offset: offset to start (in bytes) * */ int pdc_pat_mem_read_pd_pdt(struct pdc_pat_mem_read_pd_retinfo *pret, -- cgit v1.2.3-70-g09d2 From 54ac8fcbd6e6777929235ac767467991005d2df3 Mon Sep 17 00:00:00 2001 From: Helge Deller <deller@gmx.de> Date: Fri, 4 Aug 2017 19:23:53 +0200 Subject: parisc: PDT: Add full support for memory failure via Page Deallocation Table (PDT) This patch adds full support to read PDT info on all machine types. At bootup the PDT is read and bad memory excluded from usage via memblock_reserve(). Later in the boot process a kernel thread is started (kpdtd) which regularily checks firmare for new reported bad memory and tries to soft offline pages in case of correctable errors and to kill processes and exclude such memory in case of uncorrectable errors via memory_failure(). Signed-off-by: Helge Deller <deller@gmx.de> --- arch/parisc/Kconfig | 1 + arch/parisc/kernel/pdt.c | 280 ++++++++++++++++++++++++++++++++++++++++------- 2 files changed, 240 insertions(+), 41 deletions(-) diff --git a/arch/parisc/Kconfig b/arch/parisc/Kconfig index dda1f558ef35..7d2faf711d31 100644 --- a/arch/parisc/Kconfig +++ b/arch/parisc/Kconfig @@ -9,6 +9,7 @@ config PARISC select ARCH_WANT_FRAME_POINTERS select ARCH_HAS_ELF_RANDOMIZE select ARCH_HAS_STRICT_KERNEL_RWX + select ARCH_SUPPORTS_MEMORY_FAILURE select RTC_CLASS select RTC_DRV_GENERIC select INIT_ALL_POSSIBLE diff --git a/arch/parisc/kernel/pdt.c b/arch/parisc/kernel/pdt.c index d02874ecb94d..05730a83895c 100644 --- a/arch/parisc/kernel/pdt.c +++ b/arch/parisc/kernel/pdt.c @@ -1,19 +1,20 @@ /* * Page Deallocation Table (PDT) support * - * The Page Deallocation Table (PDT) holds a table with pointers to bad - * memory (broken RAM modules) which is maintained by firmware. + * The Page Deallocation Table (PDT) is maintained by firmware and holds a + * list of memory addresses in which memory errors were detected. + * The list contains both single-bit (correctable) and double-bit + * (uncorrectable) errors. * * Copyright 2017 by Helge Deller <deller@gmx.de> * - * TODO: - * - check regularily for new bad memory - * - add userspace interface with procfs or sysfs - * - increase number of PDT entries dynamically + * possible future enhancements: + * - add userspace interface via procfs or sysfs to clear PDT */ #include <linux/memblock.h> #include <linux/seq_file.h> +#include <linux/kthread.h> #include <asm/pdc.h> #include <asm/pdcpat.h> @@ -24,11 +25,16 @@ enum pdt_access_type { PDT_NONE, PDT_PDC, PDT_PAT_NEW, - PDT_PAT_OLD + PDT_PAT_CELL }; static enum pdt_access_type pdt_type; +/* PDT poll interval: 1 minute if errors, 5 minutes if everything OK. */ +#define PDT_POLL_INTERVAL_DEFAULT (5*60*HZ) +#define PDT_POLL_INTERVAL_SHORT (1*60*HZ) +static unsigned long pdt_poll_interval = PDT_POLL_INTERVAL_DEFAULT; + /* global PDT status information */ static struct pdc_mem_retinfo pdt_status; @@ -36,6 +42,21 @@ static struct pdc_mem_retinfo pdt_status; #define MAX_PDT_ENTRIES (MAX_PDT_TABLE_SIZE / sizeof(unsigned long)) static unsigned long pdt_entry[MAX_PDT_ENTRIES] __page_aligned_bss; +/* + * Constants for the pdt_entry format: + * A pdt_entry holds the physical address in bits 0-57, bits 58-61 are + * reserved, bit 62 is the perm bit and bit 63 is the error_type bit. + * The perm bit indicates whether the error have been verified as a permanent + * error (value of 1) or has not been verified, and may be transient (value + * of 0). The error_type bit indicates whether the error is a single bit error + * (value of 1) or a multiple bit error. + * On non-PAT machines phys_addr is encoded in bits 0-59 and error_type in bit + * 63. Those machines don't provide the perm bit. + */ + +#define PDT_ADDR_PHYS_MASK (pdt_type != PDT_PDC ? ~0x3f : ~0x0f) +#define PDT_ADDR_PERM_ERR (pdt_type != PDT_PDC ? 2UL : 0UL) +#define PDT_ADDR_SINGLE_ERR 1UL /* report PDT entries via /proc/meminfo */ void arch_report_meminfo(struct seq_file *m) @@ -49,6 +70,68 @@ void arch_report_meminfo(struct seq_file *m) pdt_status.pdt_entries); } +static int get_info_pat_new(void) +{ + struct pdc_pat_mem_retinfo pat_rinfo; + int ret; + + /* newer PAT machines like C8000 report info for all cells */ + if (is_pdc_pat()) + ret = pdc_pat_mem_pdt_info(&pat_rinfo); + else + return PDC_BAD_PROC; + + pdt_status.pdt_size = pat_rinfo.max_pdt_entries; + pdt_status.pdt_entries = pat_rinfo.current_pdt_entries; + pdt_status.pdt_status = 0; + pdt_status.first_dbe_loc = pat_rinfo.first_dbe_loc; + pdt_status.good_mem = pat_rinfo.good_mem; + + return ret; +} + +static int get_info_pat_cell(void) +{ + struct pdc_pat_mem_cell_pdt_retinfo cell_rinfo; + int ret; + + /* older PAT machines like rp5470 report cell info only */ + if (is_pdc_pat()) + ret = pdc_pat_mem_pdt_cell_info(&cell_rinfo, parisc_cell_num); + else + return PDC_BAD_PROC; + + pdt_status.pdt_size = cell_rinfo.max_pdt_entries; + pdt_status.pdt_entries = cell_rinfo.current_pdt_entries; + pdt_status.pdt_status = 0; + pdt_status.first_dbe_loc = cell_rinfo.first_dbe_loc; + pdt_status.good_mem = cell_rinfo.good_mem; + + return ret; +} + +static void report_mem_err(unsigned long pde) +{ + struct pdc_pat_mem_phys_mem_location loc; + unsigned long addr; + char dimm_txt[32]; + + addr = pde & PDT_ADDR_PHYS_MASK; + + /* show DIMM slot description on PAT machines */ + if (is_pdc_pat()) { + pdc_pat_mem_get_dimm_phys_location(&loc, addr); + sprintf(dimm_txt, "DIMM slot %02x, ", loc.dimm_slot); + } else + dimm_txt[0] = 0; + + pr_warn("PDT: BAD MEMORY at 0x%08lx, %s%s%s-bit error.\n", + addr, dimm_txt, + pde & PDT_ADDR_PERM_ERR ? "permanent ":"", + pde & PDT_ADDR_SINGLE_ERR ? "single":"multi"); +} + + /* * pdc_pdt_init() * @@ -63,18 +146,17 @@ void __init pdc_pdt_init(void) unsigned long entries; struct pdc_mem_read_pdt pdt_read_ret; - if (is_pdc_pat()) { - struct pdc_pat_mem_retinfo pat_rinfo; + pdt_type = PDT_PAT_NEW; + ret = get_info_pat_new(); - pdt_type = PDT_PAT_NEW; - ret = pdc_pat_mem_pdt_info(&pat_rinfo); - pdt_status.pdt_size = pat_rinfo.max_pdt_entries; - pdt_status.pdt_entries = pat_rinfo.current_pdt_entries; - pdt_status.pdt_status = 0; - pdt_status.first_dbe_loc = pat_rinfo.first_dbe_loc; - pdt_status.good_mem = pat_rinfo.good_mem; - } else { + if (ret != PDC_OK) { + pdt_type = PDT_PAT_CELL; + ret = get_info_pat_cell(); + } + + if (ret != PDC_OK) { pdt_type = PDT_PDC; + /* non-PAT machines provide the standard PDC call */ ret = pdc_mem_pdt_info(&pdt_status); } @@ -86,13 +168,17 @@ void __init pdc_pdt_init(void) } entries = pdt_status.pdt_entries; - WARN_ON(entries > MAX_PDT_ENTRIES); + if (WARN_ON(entries > MAX_PDT_ENTRIES)) + entries = pdt_status.pdt_entries = MAX_PDT_ENTRIES; - pr_info("PDT: size %lu, entries %lu, status %lu, dbe_loc 0x%lx," - " good_mem %lu\n", + pr_info("PDT: type %s, size %lu, entries %lu, status %lu, dbe_loc 0x%lx," + " good_mem %lu MB\n", + pdt_type == PDT_PDC ? __stringify(PDT_PDC) : + pdt_type == PDT_PAT_CELL ? __stringify(PDT_PAT_CELL) + : __stringify(PDT_PAT_NEW), pdt_status.pdt_size, pdt_status.pdt_entries, pdt_status.pdt_status, pdt_status.first_dbe_loc, - pdt_status.good_mem); + pdt_status.good_mem / 1024 / 1024); if (entries == 0) { pr_info("PDT: Firmware reports all memory OK.\n"); @@ -112,15 +198,12 @@ void __init pdc_pdt_init(void) #ifdef CONFIG_64BIT struct pdc_pat_mem_read_pd_retinfo pat_pret; - /* try old obsolete PAT firmware function first */ - pdt_type = PDT_PAT_OLD; - ret = pdc_pat_mem_read_cell_pdt(&pat_pret, pdt_entry, - MAX_PDT_ENTRIES); - if (ret != PDC_OK) { - pdt_type = PDT_PAT_NEW; + if (pdt_type == PDT_PAT_CELL) + ret = pdc_pat_mem_read_cell_pdt(&pat_pret, pdt_entry, + MAX_PDT_ENTRIES); + else ret = pdc_pat_mem_read_pd_pdt(&pat_pret, pdt_entry, MAX_PDT_TABLE_SIZE, 0); - } #else ret = PDC_BAD_PROC; #endif @@ -128,27 +211,142 @@ void __init pdc_pdt_init(void) if (ret != PDC_OK) { pdt_type = PDT_NONE; - pr_debug("PDT type %d, retval = %d\n", pdt_type, ret); + pr_warn("PDT: Get PDT entries failed with %d\n", ret); return; } for (i = 0; i < pdt_status.pdt_entries; i++) { - struct pdc_pat_mem_phys_mem_location loc; + report_mem_err(pdt_entry[i]); + + /* mark memory page bad */ + memblock_reserve(pdt_entry[i] & PAGE_MASK, PAGE_SIZE); + } +} - /* get DIMM slot number */ - loc.dimm_slot = 0xff; + +/* + * This is the PDT kernel thread main loop. + */ + +static int pdt_mainloop(void *unused) +{ + struct pdc_mem_read_pdt pdt_read_ret; + struct pdc_pat_mem_read_pd_retinfo pat_pret __maybe_unused; + unsigned long old_num_entries; + unsigned long *bad_mem_ptr; + int num, ret; + + for (;;) { + set_current_state(TASK_INTERRUPTIBLE); + + old_num_entries = pdt_status.pdt_entries; + + schedule_timeout(pdt_poll_interval); + if (kthread_should_stop()) + break; + + /* Do we have new PDT entries? */ + switch (pdt_type) { + case PDT_PAT_NEW: + ret = get_info_pat_new(); + break; + case PDT_PAT_CELL: + ret = get_info_pat_cell(); + break; + default: + ret = pdc_mem_pdt_info(&pdt_status); + break; + } + + if (ret != PDC_OK) { + pr_warn("PDT: unexpected failure %d\n", ret); + return -EINVAL; + } + + /* if no new PDT entries, just wait again */ + num = pdt_status.pdt_entries - old_num_entries; + if (num <= 0) + continue; + + /* decrease poll interval in case we found memory errors */ + if (pdt_status.pdt_entries && + pdt_poll_interval == PDT_POLL_INTERVAL_DEFAULT) + pdt_poll_interval = PDT_POLL_INTERVAL_SHORT; + + /* limit entries to get */ + if (num > MAX_PDT_ENTRIES) { + num = MAX_PDT_ENTRIES; + pdt_status.pdt_entries = old_num_entries + num; + } + + /* get new entries */ + switch (pdt_type) { #ifdef CONFIG_64BIT - pdc_pat_mem_get_dimm_phys_location(&loc, pdt_entry[i]); + case PDT_PAT_CELL: + if (pdt_status.pdt_entries > MAX_PDT_ENTRIES) { + pr_crit("PDT: too many entries.\n"); + return -ENOMEM; + } + ret = pdc_pat_mem_read_cell_pdt(&pat_pret, pdt_entry, + MAX_PDT_ENTRIES); + bad_mem_ptr = &pdt_entry[old_num_entries]; + break; + case PDT_PAT_NEW: + ret = pdc_pat_mem_read_pd_pdt(&pat_pret, + pdt_entry, + num * sizeof(unsigned long), + old_num_entries * sizeof(unsigned long)); + bad_mem_ptr = &pdt_entry[0]; + break; #endif + default: + ret = pdc_mem_pdt_read_entries(&pdt_read_ret, + pdt_entry); + bad_mem_ptr = &pdt_entry[old_num_entries]; + break; + } - pr_warn("PDT: BAD PAGE #%d at 0x%08lx, " - "DIMM slot %02x (error_type = %lu)\n", - i, - pdt_entry[i] & PAGE_MASK, - loc.dimm_slot, - pdt_entry[i] & 1); + /* report and mark memory broken */ + while (num--) { + unsigned long pde = *bad_mem_ptr++; - /* mark memory page bad */ - memblock_reserve(pdt_entry[i] & PAGE_MASK, PAGE_SIZE); + report_mem_err(pde); + +#ifdef CONFIG_MEMORY_FAILURE + if ((pde & PDT_ADDR_PERM_ERR) || + ((pde & PDT_ADDR_SINGLE_ERR) == 0)) + memory_failure(pde >> PAGE_SHIFT, 0, 0); + else + soft_offline_page( + pfn_to_page(pde >> PAGE_SHIFT), 0); +#else + pr_crit("PDT: memory error at 0x%lx ignored.\n" + "Rebuild kernel with CONFIG_MEMORY_FAILURE=y " + "for real handling.\n", + pde & PDT_ADDR_PHYS_MASK); +#endif + + } } + + return 0; } + + +static int __init pdt_initcall(void) +{ + struct task_struct *kpdtd_task; + + if (pdt_type == PDT_NONE) + return -ENODEV; + + kpdtd_task = kthread_create(pdt_mainloop, NULL, "kpdtd"); + if (IS_ERR(kpdtd_task)) + return PTR_ERR(kpdtd_task); + + wake_up_process(kpdtd_task); + + return 0; +} + +late_initcall(pdt_initcall); -- cgit v1.2.3-70-g09d2 From 76cffeb6ccace1ae487e58d8d72b4519861a9d9e Mon Sep 17 00:00:00 2001 From: Helge Deller <deller@gmx.de> Date: Fri, 4 Aug 2017 23:54:19 +0200 Subject: parisc: Static initialization of spinlocks in perf and unwind code While testing UBSAN I saw this BUG: BUG: spinlock bad magic on CPU#0, swapper/0 in unwind code. Let's avoid that by static initialization. Signed-off-by: Helge Deller <deller@gmx.de> --- arch/parisc/kernel/perf.c | 4 +--- arch/parisc/kernel/unwind.c | 4 +--- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/arch/parisc/kernel/perf.c b/arch/parisc/kernel/perf.c index 6017a5af2e6e..0813359049ae 100644 --- a/arch/parisc/kernel/perf.c +++ b/arch/parisc/kernel/perf.c @@ -69,7 +69,7 @@ struct rdr_tbl_ent { static int perf_processor_interface __read_mostly = UNKNOWN_INTF; static int perf_enabled __read_mostly; -static spinlock_t perf_lock; +static DEFINE_SPINLOCK(perf_lock); struct parisc_device *cpu_device __read_mostly; /* RDRs to write for PCX-W */ @@ -533,8 +533,6 @@ static int __init perf_init(void) /* Patch the images to match the system */ perf_patch_images(); - spin_lock_init(&perf_lock); - /* TODO: this only lets us access the first cpu.. what to do for SMP? */ cpu_device = per_cpu(cpu_data, 0).dev; printk("Performance monitoring counters enabled for %s\n", diff --git a/arch/parisc/kernel/unwind.c b/arch/parisc/kernel/unwind.c index 1b73690477c5..48dc7d4d20bb 100644 --- a/arch/parisc/kernel/unwind.c +++ b/arch/parisc/kernel/unwind.c @@ -34,7 +34,7 @@ extern struct unwind_table_entry __start___unwind[]; extern struct unwind_table_entry __stop___unwind[]; -static spinlock_t unwind_lock; +static DEFINE_SPINLOCK(unwind_lock); /* * the kernel unwind block is not dynamically allocated so that * we can call unwind_init as early in the bootup process as @@ -181,8 +181,6 @@ int __init unwind_init(void) start = (long)&__start___unwind[0]; stop = (long)&__stop___unwind[0]; - spin_lock_init(&unwind_lock); - printk("unwind_init: start = 0x%lx, end = 0x%lx, entries = %lu\n", start, stop, (stop - start) / sizeof(struct unwind_table_entry)); -- cgit v1.2.3-70-g09d2 From da3dc73ef6dcb226a2a97ac70c53026b7d16d77e Mon Sep 17 00:00:00 2001 From: Helge Deller <deller@gmx.de> Date: Mon, 7 Aug 2017 23:26:45 +0200 Subject: parisc: Drop exception_data struct Signed-off-by: Helge Deller <deller@gmx.de> --- arch/parisc/lib/memcpy.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/arch/parisc/lib/memcpy.c b/arch/parisc/lib/memcpy.c index 99115cd9e790..865a7f796c7f 100644 --- a/arch/parisc/lib/memcpy.c +++ b/arch/parisc/lib/memcpy.c @@ -27,8 +27,6 @@ #include <linux/compiler.h> #include <linux/uaccess.h> -DECLARE_PER_CPU(struct exception_data, exception_data); - #define get_user_space() (uaccess_kernel() ? 0 : mfsp(3)) #define get_kernel_space() (0) -- cgit v1.2.3-70-g09d2 From 8b5bdd850dcc12b2d1c1e1a8418c0c31da56e69b Mon Sep 17 00:00:00 2001 From: Helge Deller <deller@gmx.de> Date: Mon, 7 Aug 2017 23:28:39 +0200 Subject: parisc: Static initialization of pcxl_res_lock spinlock Signed-off-by: Helge Deller <deller@gmx.de> --- arch/parisc/kernel/pci-dma.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/arch/parisc/kernel/pci-dma.c b/arch/parisc/kernel/pci-dma.c index 5f0067a62738..bd4c0a7471d3 100644 --- a/arch/parisc/kernel/pci-dma.c +++ b/arch/parisc/kernel/pci-dma.c @@ -41,7 +41,7 @@ static unsigned long pcxl_used_bytes __read_mostly = 0; static unsigned long pcxl_used_pages __read_mostly = 0; extern unsigned long pcxl_dma_start; /* Start of pcxl dma mapping area */ -static spinlock_t pcxl_res_lock; +static DEFINE_SPINLOCK(pcxl_res_lock); static char *pcxl_res_map; static int pcxl_res_hint; static int pcxl_res_size; @@ -390,7 +390,6 @@ pcxl_dma_init(void) if (pcxl_dma_start == 0) return 0; - spin_lock_init(&pcxl_res_lock); pcxl_res_size = PCXL_DMA_MAP_SIZE >> (PAGE_SHIFT + 3); pcxl_res_hint = 0; pcxl_res_map = (char *)__get_free_pages(GFP_KERNEL, -- cgit v1.2.3-70-g09d2 From 42593e70004d13baf9f1587aed13911cac01cfd9 Mon Sep 17 00:00:00 2001 From: Helge Deller <deller@gmx.de> Date: Fri, 4 Aug 2017 21:32:41 +0200 Subject: parisc: Drop MADV_SPACEAVAIL, MADV_VPS_PURGE and MADV_VPS_INHERIT Those aren't used or implemented anywhere in Linux. Furthermore, MADV_SPACEAVAIL seems to be a HP-UX related flag which is implemented as null operation in HP-UX. And since we don't support running HP-UX binaries there is no need to keep it. Signed-off-by: Helge Deller <deller@gmx.de> --- arch/parisc/include/uapi/asm/mman.h | 3 --- 1 file changed, 3 deletions(-) diff --git a/arch/parisc/include/uapi/asm/mman.h b/arch/parisc/include/uapi/asm/mman.h index 2e7b8c2431a3..9a9c2fe4be50 100644 --- a/arch/parisc/include/uapi/asm/mman.h +++ b/arch/parisc/include/uapi/asm/mman.h @@ -40,9 +40,6 @@ #define MADV_SEQUENTIAL 2 /* expect sequential page references */ #define MADV_WILLNEED 3 /* will need these pages */ #define MADV_DONTNEED 4 /* don't need these pages */ -#define MADV_SPACEAVAIL 5 /* insure that resources are reserved */ -#define MADV_VPS_PURGE 6 /* Purge pages from VM page cache */ -#define MADV_VPS_INHERIT 7 /* Inherit parents page size */ /* common/generic parameters */ #define MADV_FREE 8 /* free pages only if memory pressure */ -- cgit v1.2.3-70-g09d2 From d2883fa1a6fcb065362f27f410114dc6b7084655 Mon Sep 17 00:00:00 2001 From: John David Anglin <dave.anglin@bell.net> Date: Wed, 26 Jul 2017 20:02:52 +0200 Subject: parisc: Optimize switch_mm We only need to switch contexts when prev != next, and we don't need to disable interrupts to do the check. Signed-off-by: John David Anglin <dave.anglin@bell.net> Signed-off-by: Helge Deller <deller@gmx.de> --- arch/parisc/include/asm/mmu_context.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/arch/parisc/include/asm/mmu_context.h b/arch/parisc/include/asm/mmu_context.h index a81226257878..e4a657094058 100644 --- a/arch/parisc/include/asm/mmu_context.h +++ b/arch/parisc/include/asm/mmu_context.h @@ -63,6 +63,9 @@ static inline void switch_mm(struct mm_struct *prev, { unsigned long flags; + if (prev == next) + return; + local_irq_save(flags); switch_mm_irqs_off(prev, next, tsk); local_irq_restore(flags); -- cgit v1.2.3-70-g09d2 From 1ed4714fba25a3730369567b081549ee1da49124 Mon Sep 17 00:00:00 2001 From: Helge Deller <deller@gmx.de> Date: Thu, 10 Aug 2017 19:20:47 +0200 Subject: parisc/random: Add machine specific randomness Add some machine-specific information like values of cr16 cycle counter, machine-specific software ID and machine model to the random generator. Signed-off-by: Helge Deller <deller@gmx.de> --- arch/parisc/kernel/processor.c | 24 +++++++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/arch/parisc/kernel/processor.c b/arch/parisc/kernel/processor.c index 0ab32779dfa7..6b6fe8d62893 100644 --- a/arch/parisc/kernel/processor.c +++ b/arch/parisc/kernel/processor.c @@ -30,6 +30,7 @@ #include <linux/mm.h> #include <linux/module.h> #include <linux/seq_file.h> +#include <linux/random.h> #include <linux/slab.h> #include <linux/cpu.h> #include <asm/param.h> @@ -237,28 +238,45 @@ static int processor_probe(struct parisc_device *dev) */ void __init collect_boot_cpu_data(void) { + unsigned long cr16_seed; + memset(&boot_cpu_data, 0, sizeof(boot_cpu_data)); + cr16_seed = get_cycles(); + add_device_randomness(&cr16_seed, sizeof(cr16_seed)); + boot_cpu_data.cpu_hz = 100 * PAGE0->mem_10msec; /* Hz of this PARISC */ /* get CPU-Model Information... */ #define p ((unsigned long *)&boot_cpu_data.pdc.model) - if (pdc_model_info(&boot_cpu_data.pdc.model) == PDC_OK) + if (pdc_model_info(&boot_cpu_data.pdc.model) == PDC_OK) { printk(KERN_INFO "model %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx\n", p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7], p[8]); + + add_device_randomness(&boot_cpu_data.pdc.model, + sizeof(boot_cpu_data.pdc.model)); + } #undef p - if (pdc_model_versions(&boot_cpu_data.pdc.versions, 0) == PDC_OK) + if (pdc_model_versions(&boot_cpu_data.pdc.versions, 0) == PDC_OK) { printk(KERN_INFO "vers %08lx\n", boot_cpu_data.pdc.versions); - if (pdc_model_cpuid(&boot_cpu_data.pdc.cpuid) == PDC_OK) + add_device_randomness(&boot_cpu_data.pdc.versions, + sizeof(boot_cpu_data.pdc.versions)); + } + + if (pdc_model_cpuid(&boot_cpu_data.pdc.cpuid) == PDC_OK) { printk(KERN_INFO "CPUID vers %ld rev %ld (0x%08lx)\n", (boot_cpu_data.pdc.cpuid >> 5) & 127, boot_cpu_data.pdc.cpuid & 31, boot_cpu_data.pdc.cpuid); + add_device_randomness(&boot_cpu_data.pdc.cpuid, + sizeof(boot_cpu_data.pdc.cpuid)); + } + if (pdc_model_capabilities(&boot_cpu_data.pdc.capabilities) == PDC_OK) printk(KERN_INFO "capabilities 0x%lx\n", boot_cpu_data.pdc.capabilities); -- cgit v1.2.3-70-g09d2 From e35a2ce692821563583fa8b11ddf4acb24e54580 Mon Sep 17 00:00:00 2001 From: Helge Deller <deller@gmx.de> Date: Fri, 4 Aug 2017 23:46:16 +0200 Subject: parisc: Enable UBSAN support Signed-off-by: Helge Deller <deller@gmx.de> --- arch/parisc/Kconfig | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/parisc/Kconfig b/arch/parisc/Kconfig index 7d2faf711d31..9db4b4f2f8f5 100644 --- a/arch/parisc/Kconfig +++ b/arch/parisc/Kconfig @@ -9,6 +9,8 @@ config PARISC select ARCH_WANT_FRAME_POINTERS select ARCH_HAS_ELF_RANDOMIZE select ARCH_HAS_STRICT_KERNEL_RWX + select ARCH_HAS_UBSAN_SANITIZE_ALL + select ARCH_WANTS_UBSAN_NO_NULL select ARCH_SUPPORTS_MEMORY_FAILURE select RTC_CLASS select RTC_DRV_GENERIC -- cgit v1.2.3-70-g09d2 From 2f3c7b8137ef6a3f90850d7cb5dbd05d8940403a Mon Sep 17 00:00:00 2001 From: Helge Deller <deller@gmx.de> Date: Sun, 20 Aug 2017 10:52:22 +0200 Subject: parisc: Add core code for self-extracting kernel Signed-off-by: Helge Deller <deller@gmx.de> --- arch/parisc/boot/.gitignore | 2 + arch/parisc/boot/Makefile | 26 +++ arch/parisc/boot/compressed/.gitignore | 3 + arch/parisc/boot/compressed/Makefile | 86 +++++++++ arch/parisc/boot/compressed/head.S | 85 +++++++++ arch/parisc/boot/compressed/misc.c | 301 ++++++++++++++++++++++++++++++ arch/parisc/boot/compressed/vmlinux.lds.S | 101 ++++++++++ arch/parisc/boot/compressed/vmlinux.scr | 10 + arch/parisc/boot/install.sh | 65 +++++++ 9 files changed, 679 insertions(+) create mode 100644 arch/parisc/boot/.gitignore create mode 100644 arch/parisc/boot/Makefile create mode 100644 arch/parisc/boot/compressed/.gitignore create mode 100644 arch/parisc/boot/compressed/Makefile create mode 100644 arch/parisc/boot/compressed/head.S create mode 100644 arch/parisc/boot/compressed/misc.c create mode 100644 arch/parisc/boot/compressed/vmlinux.lds.S create mode 100644 arch/parisc/boot/compressed/vmlinux.scr create mode 100644 arch/parisc/boot/install.sh diff --git a/arch/parisc/boot/.gitignore b/arch/parisc/boot/.gitignore new file mode 100644 index 000000000000..017d5912ad2d --- /dev/null +++ b/arch/parisc/boot/.gitignore @@ -0,0 +1,2 @@ +image +bzImage diff --git a/arch/parisc/boot/Makefile b/arch/parisc/boot/Makefile new file mode 100644 index 000000000000..cad68a584884 --- /dev/null +++ b/arch/parisc/boot/Makefile @@ -0,0 +1,26 @@ +# +# Makefile for the linux parisc-specific parts of the boot image creator. +# + +COMPILE_VERSION := __linux_compile_version_id__`hostname | \ + tr -c '[0-9A-Za-z]' '_'`__`date | \ + tr -c '[0-9A-Za-z]' '_'`_t + +ccflags-y := -DCOMPILE_VERSION=$(COMPILE_VERSION) -gstabs -I. + +targets := image +targets += bzImage +subdir- := compressed + +$(obj)/image: vmlinux FORCE + $(call if_changed,objcopy) + +$(obj)/bzImage: $(obj)/compressed/vmlinux FORCE + $(call if_changed,objcopy) + +$(obj)/compressed/vmlinux: FORCE + $(Q)$(MAKE) $(build)=$(obj)/compressed $@ + +install: $(CONFIGURE) $(obj)/bzImage + sh -x $(srctree)/$(obj)/install.sh $(KERNELRELEASE) $(obj)/bzImage \ + System.map "$(INSTALL_PATH)" diff --git a/arch/parisc/boot/compressed/.gitignore b/arch/parisc/boot/compressed/.gitignore new file mode 100644 index 000000000000..ae06b9b4c02f --- /dev/null +++ b/arch/parisc/boot/compressed/.gitignore @@ -0,0 +1,3 @@ +sizes.h +vmlinux +vmlinux.lds diff --git a/arch/parisc/boot/compressed/Makefile b/arch/parisc/boot/compressed/Makefile new file mode 100644 index 000000000000..5450a11c9d10 --- /dev/null +++ b/arch/parisc/boot/compressed/Makefile @@ -0,0 +1,86 @@ +# +# linux/arch/parisc/boot/compressed/Makefile +# +# create a compressed self-extracting vmlinux image from the original vmlinux +# + +KCOV_INSTRUMENT := n +GCOV_PROFILE := n +UBSAN_SANITIZE := n + +targets := vmlinux.lds vmlinux vmlinux.bin vmlinux.bin.gz vmlinux.bin.bz2 +targets += vmlinux.bin.xz vmlinux.bin.lzma vmlinux.bin.lzo vmlinux.bin.lz4 +targets += misc.o piggy.o sizes.h head.o real2.o firmware.o + +KBUILD_CFLAGS := -D__KERNEL__ -O2 -DBOOTLOADER +KBUILD_CFLAGS += -DDISABLE_BRANCH_PROFILING +KBUILD_CFLAGS += $(cflags-y) -fno-delete-null-pointer-checks +KBUILD_CFLAGS += -fno-PIE -mno-space-regs -mdisable-fpregs +ifndef CONFIG_64BIT +KBUILD_CFLAGS += -mfast-indirect-calls +endif + +OBJECTS += $(obj)/head.o $(obj)/real2.o $(obj)/firmware.o $(obj)/misc.o $(obj)/piggy.o + +# LDFLAGS_vmlinux := -X --whole-archive -e startup -T +LDFLAGS_vmlinux := -X -e startup --as-needed -T +$(obj)/vmlinux: $(obj)/vmlinux.lds $(OBJECTS) $(LIBGCC) + $(call if_changed,ld) + +sed-sizes := -e 's/^\([0-9a-fA-F]*\) . \(__bss_start\|_end\|parisc_kernel_start\)$$/\#define SZ\2 0x\1/p' + +quiet_cmd_sizes = GEN $@ + cmd_sizes = $(NM) $< | sed -n $(sed-sizes) > $@ + +$(obj)/sizes.h: vmlinux + $(call if_changed,sizes) + +AFLAGS_head.o += -I$(objtree)/$(obj) -DBOOTLOADER +$(obj)/head.o: $(obj)/sizes.h + +CFLAGS_misc.o += -I$(objtree)/$(obj) +$(obj)/misc.o: $(obj)/sizes.h + +$(obj)/firmware.o: $(obj)/firmware.c +$(obj)/firmware.c: $(srctree)/arch/$(SRCARCH)/kernel/firmware.c + $(call cmd,shipped) + +AFLAGS_real2.o += -DBOOTLOADER +$(obj)/real2.o: $(obj)/real2.S +$(obj)/real2.S: $(srctree)/arch/$(SRCARCH)/kernel/real2.S + $(call cmd,shipped) + +$(obj)/misc.o: $(obj)/sizes.h + +CPPFLAGS_vmlinux.lds += -I$(objtree)/$(obj) -DBOOTLOADER +$(obj)/vmlinux.lds: $(obj)/sizes.h + +OBJCOPYFLAGS_vmlinux.bin := -O binary -R .comment -S +$(obj)/vmlinux.bin: vmlinux + $(call if_changed,objcopy) + +vmlinux.bin.all-y := $(obj)/vmlinux.bin + +suffix-$(CONFIG_KERNEL_GZIP) := gz +suffix-$(CONFIG_KERNEL_BZIP2) := bz2 +suffix-$(CONFIG_KERNEL_LZ4) := lz4 +suffix-$(CONFIG_KERNEL_LZMA) := lzma +suffix-$(CONFIG_KERNEL_LZO) := lzo +suffix-$(CONFIG_KERNEL_XZ) := xz + +$(obj)/vmlinux.bin.gz: $(vmlinux.bin.all-y) + $(call if_changed,gzip) +$(obj)/vmlinux.bin.bz2: $(vmlinux.bin.all-y) + $(call if_changed,bzip2) +$(obj)/vmlinux.bin.lz4: $(vmlinux.bin.all-y) + $(call if_changed,lz4) +$(obj)/vmlinux.bin.lzma: $(vmlinux.bin.all-y) + $(call if_changed,lzma) +$(obj)/vmlinux.bin.lzo: $(vmlinux.bin.all-y) + $(call if_changed,lzo) +$(obj)/vmlinux.bin.xz: $(vmlinux.bin.all-y) + $(call if_changed,xzkern) + +LDFLAGS_piggy.o := -r --format binary --oformat $(LD_BFD) -T +$(obj)/piggy.o: $(obj)/vmlinux.scr $(obj)/vmlinux.bin.$(suffix-y) + $(call if_changed,ld) diff --git a/arch/parisc/boot/compressed/head.S b/arch/parisc/boot/compressed/head.S new file mode 100644 index 000000000000..5aba20fa48aa --- /dev/null +++ b/arch/parisc/boot/compressed/head.S @@ -0,0 +1,85 @@ +/* + * Startup glue code to uncompress the kernel + * + * (C) 2017 Helge Deller <deller@gmx.de> + */ + +#include <linux/init.h> +#include <linux/linkage.h> +#include <asm/asm-offsets.h> +#include <asm/page.h> +#include <asm/psw.h> +#include <asm/pdc.h> +#include <asm/assembly.h> +#include "sizes.h" + +#define BOOTADDR(x) (x) + +#ifndef CONFIG_64BIT + .import $global$ /* forward declaration */ +#endif /*!CONFIG_64BIT*/ + + __HEAD + +ENTRY(startup) + .level LEVEL + +#define PSW_W_SM 0x200 +#define PSW_W_BIT 36 + + ;! nuke the W bit, saving original value + .level 2.0 + rsm PSW_W_SM, %r1 + + .level 1.1 + extrw,u %r1, PSW_W_BIT-32, 1, %r1 + copy %r1, %arg0 + + /* Make sure sr4-sr7 are set to zero for the kernel address space */ + mtsp %r0,%sr4 + mtsp %r0,%sr5 + mtsp %r0,%sr6 + mtsp %r0,%sr7 + + /* Clear BSS */ + + .import _bss,data + .import _ebss,data + + load32 BOOTADDR(_bss),%r3 + load32 BOOTADDR(_ebss),%r4 + ldo FRAME_SIZE(%r4),%sp /* stack at end of bss */ +$bss_loop: + cmpb,<<,n %r3,%r4,$bss_loop + stw,ma %r0,4(%r3) + + /* Initialize the global data pointer */ + loadgp + + /* arg0..arg4 were set by palo. */ + copy %arg1, %r6 /* command line */ + copy %arg2, %r7 /* rd-start */ + copy %arg3, %r8 /* rd-end */ + load32 BOOTADDR(decompress_kernel),%r3 + +#ifdef CONFIG_64BIT + .level LEVEL + ssm PSW_W_SM, %r0 /* set W-bit */ + depdi 0, 31, 32, %r3 +#endif + load32 BOOTADDR(startup_continue), %r2 + bv,n 0(%r3) + +startup_continue: +#ifdef CONFIG_64BIT + .level LEVEL + rsm PSW_W_SM, %r0 /* clear W-bit */ +#endif + + load32 KERNEL_BINARY_TEXT_START, %arg0 /* free mem */ + copy %r6, %arg1 /* command line */ + copy %r7, %arg2 /* rd-start */ + copy %r8, %arg3 /* rd-end */ + + bv,n 0(%ret0) +END(startup) diff --git a/arch/parisc/boot/compressed/misc.c b/arch/parisc/boot/compressed/misc.c new file mode 100644 index 000000000000..13a4bf9ac4da --- /dev/null +++ b/arch/parisc/boot/compressed/misc.c @@ -0,0 +1,301 @@ +/* + * Definitions and wrapper functions for kernel decompressor + * + * (C) 2017 Helge Deller <deller@gmx.de> + */ + +#include <linux/uaccess.h> +#include <asm/unaligned.h> +#include <asm/page.h> +#include "sizes.h" + +/* + * gzip declarations + */ +#define STATIC static + +#undef memmove +#define memmove memmove +#define memzero(s, n) memset((s), 0, (n)) + +#define malloc malloc_gzip +#define free free_gzip + +/* Symbols defined by linker scripts */ +extern char input_data[]; +extern int input_len; +extern __le32 output_len; /* at unaligned address, little-endian */ +extern char _text, _end; +extern char _bss, _ebss; +extern char _startcode_end; +extern void startup_continue(void *entry, unsigned long cmdline, + unsigned long rd_start, unsigned long rd_end) __noreturn; + +void error(char *m) __noreturn; + +static unsigned long free_mem_ptr; +static unsigned long free_mem_end_ptr; + +#ifdef CONFIG_KERNEL_GZIP +#include "../../../../lib/decompress_inflate.c" +#endif + +#ifdef CONFIG_KERNEL_BZIP2 +#include "../../../../lib/decompress_bunzip2.c" +#endif + +#ifdef CONFIG_KERNEL_LZ4 +#include "../../../../lib/decompress_unlz4.c" +#endif + +#ifdef CONFIG_KERNEL_LZMA +#include "../../../../lib/decompress_unlzma.c" +#endif + +#ifdef CONFIG_KERNEL_LZO +#include "../../../../lib/decompress_unlzo.c" +#endif + +#ifdef CONFIG_KERNEL_XZ +#include "../../../../lib/decompress_unxz.c" +#endif + +void *memmove(void *dest, const void *src, size_t n) +{ + const char *s = src; + char *d = dest; + + if (d <= s) { + while (n--) + *d++ = *s++; + } else { + d += n; + s += n; + while (n--) + *--d = *--s; + } + return dest; +} + +void *memset(void *s, int c, size_t count) +{ + char *xs = (char *)s; + + while (count--) + *xs++ = c; + return s; +} + +void *memcpy(void *d, const void *s, size_t len) +{ + char *dest = (char *)d; + const char *source = (const char *)s; + + while (len--) + *dest++ = *source++; + return d; +} + +size_t strlen(const char *s) +{ + const char *sc; + + for (sc = s; *sc != '\0'; ++sc) + ; + return sc - s; +} + +char *strchr(const char *s, int c) +{ + while (*s) { + if (*s == (char)c) + return (char *)s; + ++s; + } + return NULL; +} + +int puts(const char *s) +{ + const char *nuline = s; + + while ((nuline = strchr(s, '\n')) != NULL) { + if (nuline != s) + pdc_iodc_print(s, nuline - s); + pdc_iodc_print("\r\n", 2); + s = nuline + 1; + } + if (*s != '\0') + pdc_iodc_print(s, strlen(s)); + + return 0; +} + +static int putchar(int c) +{ + char buf[2]; + + buf[0] = c; + buf[1] = '\0'; + puts(buf); + return c; +} + +void __noreturn error(char *x) +{ + puts("\n\n"); + puts(x); + puts("\n\n -- System halted"); + while (1) /* wait forever */ + ; +} + +static int print_hex(unsigned long num) +{ + const char hex[] = "0123456789abcdef"; + char str[40]; + int i = sizeof(str)-1; + + str[i--] = '\0'; + do { + str[i--] = hex[num & 0x0f]; + num >>= 4; + } while (num); + + str[i--] = 'x'; + str[i] = '0'; + puts(&str[i]); + + return 0; +} + +int printf(const char *fmt, ...) +{ + va_list args; + int i = 0; + + va_start(args, fmt); + + while (fmt[i]) { + if (fmt[i] != '%') { +put: + putchar(fmt[i++]); + continue; + } + + if (fmt[++i] == '%') + goto put; + ++i; + print_hex(va_arg(args, unsigned long)); + } + + va_end(args); + return 0; +} + +/* helper functions for libgcc */ +void abort(void) +{ + error("aborted."); +} + +#undef malloc +void *malloc(size_t size) +{ + return malloc_gzip(size); +} + +#undef free +void free(void *ptr) +{ + return free_gzip(ptr); +} + + +static void flush_data_cache(char *start, unsigned long length) +{ + char *end = start + length; + + do { + asm volatile("fdc 0(%0)" : : "r" (start)); + asm volatile("fic 0(%%sr0,%0)" : : "r" (start)); + start += 16; + } while (start < end); + asm volatile("fdc 0(%0)" : : "r" (end)); + + asm ("sync"); +} + +unsigned long decompress_kernel(unsigned int started_wide, + unsigned int command_line, + const unsigned int rd_start, + const unsigned int rd_end) +{ + char *output; + unsigned long len, len_all; + +#ifdef CONFIG_64BIT + parisc_narrow_firmware = 0; +#endif + + set_firmware_width_unlocked(); + + putchar('U'); /* if you get this p and no more, string storage */ + /* in $GLOBAL$ is wrong or %dp is wrong */ + puts("ncompressing ...\n"); + + output = (char *) KERNEL_BINARY_TEXT_START; + len_all = __pa(SZ_end) - __pa(SZparisc_kernel_start); + + if ((unsigned long) &_startcode_end > (unsigned long) output) + error("Bootcode overlaps kernel code"); + + len = get_unaligned_le32(&output_len); + if (len > len_all) + error("Output len too big."); + else + memset(&output[len], 0, len_all - len); + + /* + * Initialize free_mem_ptr and free_mem_end_ptr. + */ + free_mem_ptr = (unsigned long) &_ebss; + free_mem_ptr += 2*1024*1024; /* leave 2 MB for stack */ + + /* Limit memory for bootoader to 1GB */ + #define ARTIFICIAL_LIMIT (1*1024*1024*1024) + free_mem_end_ptr = PAGE0->imm_max_mem; + if (free_mem_end_ptr > ARTIFICIAL_LIMIT) + free_mem_end_ptr = ARTIFICIAL_LIMIT; + +#ifdef CONFIG_BLK_DEV_INITRD + /* if we have ramdisk this is at end of memory */ + if (rd_start && rd_start < free_mem_end_ptr) + free_mem_end_ptr = rd_start; +#endif + +#ifdef DEBUG + printf("startcode_end = %x\n", &_startcode_end); + printf("commandline = %x\n", command_line); + printf("rd_start = %x\n", rd_start); + printf("rd_end = %x\n", rd_end); + + printf("free_ptr = %x\n", free_mem_ptr); + printf("free_ptr_end = %x\n", free_mem_end_ptr); + + printf("input_data = %x\n", input_data); + printf("input_len = %x\n", input_len); + printf("output = %x\n", output); + printf("output_len = %x\n", len); + printf("output_max = %x\n", len_all); +#endif + + __decompress(input_data, input_len, NULL, NULL, + output, 0, NULL, error); + + flush_data_cache(output, len); + + printf("Booting kernel ...\n\n"); + + return (unsigned long) output; +} diff --git a/arch/parisc/boot/compressed/vmlinux.lds.S b/arch/parisc/boot/compressed/vmlinux.lds.S new file mode 100644 index 000000000000..a4ce3314e78e --- /dev/null +++ b/arch/parisc/boot/compressed/vmlinux.lds.S @@ -0,0 +1,101 @@ +#include <asm-generic/vmlinux.lds.h> +#include <asm/page.h> +#include "sizes.h" + +#ifndef CONFIG_64BIT +OUTPUT_FORMAT("elf32-hppa-linux") +OUTPUT_ARCH(hppa) +#else +OUTPUT_FORMAT("elf64-hppa-linux") +OUTPUT_ARCH(hppa:hppa2.0w) +#endif + +ENTRY(startup) + +SECTIONS +{ + /* palo loads at 0x60000 */ + /* loaded kernel will move to 0x10000 */ + . = 0xe0000; /* should not overwrite palo code */ + + .head.text : { + _head = . ; + HEAD_TEXT + _ehead = . ; + } + + /* keep __gp below 0x1000000 */ +#ifdef CONFIG_64BIT + . = ALIGN(16); + /* Linkage tables */ + .opd : { + *(.opd) + } PROVIDE (__gp = .); + .plt : { + *(.plt) + } + .dlt : { + *(.dlt) + } +#endif + _startcode_end = .; + + /* bootloader code and data starts behind area of extracted kernel */ + . = (SZ_end - SZparisc_kernel_start + KERNEL_BINARY_TEXT_START); + + /* align on next page boundary */ + . = ALIGN(4096); + .text : { + _text = .; /* Text */ + *(.text) + *(.text.*) + _etext = . ; + } + . = ALIGN(8); + .data : { + _data = . ; + *(.data) + *(.data.*) + _edata = . ; + } + . = ALIGN(8); + .rodata : { + _rodata = . ; + *(.rodata) /* read-only data */ + *(.rodata.*) + _erodata = . ; + } + . = ALIGN(8); + .rodata.compressed : { + *(.rodata.compressed) + } + . = ALIGN(8); + .bss : { + _bss = . ; + *(.bss) + *(.bss.*) + *(COMMON) + . = ALIGN(4096); + _ebss = .; + } + + STABS_DEBUG + .note 0 : { *(.note) } + + /* Sections to be discarded */ + DISCARDS + /DISCARD/ : { +#ifdef CONFIG_64BIT + /* temporary hack until binutils is fixed to not emit these + * for static binaries + */ + *(.PARISC.unwind) /* no unwind data */ + *(.interp) + *(.dynsym) + *(.dynstr) + *(.dynamic) + *(.hash) + *(.gnu.hash) +#endif + } +} diff --git a/arch/parisc/boot/compressed/vmlinux.scr b/arch/parisc/boot/compressed/vmlinux.scr new file mode 100644 index 000000000000..dac2d142bcfa --- /dev/null +++ b/arch/parisc/boot/compressed/vmlinux.scr @@ -0,0 +1,10 @@ +SECTIONS +{ + .rodata.compressed : { + input_len = .; + LONG(input_data_end - input_data) input_data = .; + *(.data) + output_len = . - 4; /* can be at unaligned address */ + input_data_end = .; + } +} diff --git a/arch/parisc/boot/install.sh b/arch/parisc/boot/install.sh new file mode 100644 index 000000000000..8f7c365fad83 --- /dev/null +++ b/arch/parisc/boot/install.sh @@ -0,0 +1,65 @@ +#!/bin/sh +# +# arch/parisc/install.sh, derived from arch/i386/boot/install.sh +# +# This file is subject to the terms and conditions of the GNU General Public +# License. See the file "COPYING" in the main directory of this archive +# for more details. +# +# Copyright (C) 1995 by Linus Torvalds +# +# Adapted from code in arch/i386/boot/Makefile by H. Peter Anvin +# +# "make install" script for i386 architecture +# +# Arguments: +# $1 - kernel version +# $2 - kernel image file +# $3 - kernel map file +# $4 - default install path (blank if root directory) +# + +verify () { + if [ ! -f "$1" ]; then + echo "" 1>&2 + echo " *** Missing file: $1" 1>&2 + echo ' *** You need to run "make" before "make install".' 1>&2 + echo "" 1>&2 + exit 1 + fi +} + +# Make sure the files actually exist + +verify "$2" +verify "$3" + +# User may have a custom install script + +if [ -n "${INSTALLKERNEL}" ]; then + if [ -x ~/bin/${INSTALLKERNEL} ]; then exec ~/bin/${INSTALLKERNEL} "$@"; fi + if [ -x /sbin/${INSTALLKERNEL} ]; then exec /sbin/${INSTALLKERNEL} "$@"; fi +fi + +# Default install + +if [ "$(basename $2)" = "zImage" ]; then +# Compressed install + echo "Installing compressed kernel" + base=vmlinuz +else +# Normal install + echo "Installing normal kernel" + base=vmlinux +fi + +if [ -f $4/$base-$1 ]; then + mv $4/$base-$1 $4/$base-$1.old +fi +cat $2 > $4/$base-$1 + +# Install system map file +if [ -f $4/System.map-$1 ]; then + mv $4/System.map-$1 $4/System.map-$1.old +fi +cp $3 $4/System.map-$1 -- cgit v1.2.3-70-g09d2 From f5213b2c40f5749e6b9b8f737ea946495ed0a438 Mon Sep 17 00:00:00 2001 From: Helge Deller <deller@gmx.de> Date: Sun, 20 Aug 2017 10:52:22 +0200 Subject: parisc: Make existing core files reuseable for bootloader Signed-off-by: Helge Deller <deller@gmx.de> --- arch/parisc/include/asm/page.h | 4 ++++ arch/parisc/include/asm/pdc.h | 2 ++ arch/parisc/kernel/firmware.c | 15 ++++++++++++++- arch/parisc/kernel/real2.S | 4 ++++ 4 files changed, 24 insertions(+), 1 deletion(-) diff --git a/arch/parisc/include/asm/page.h b/arch/parisc/include/asm/page.h index 80e742a1c162..bfed09d80bae 100644 --- a/arch/parisc/include/asm/page.h +++ b/arch/parisc/include/asm/page.h @@ -116,11 +116,15 @@ extern int npmem_ranges; /* This governs the relationship between virtual and physical addresses. * If you alter it, make sure to take care of our various fixed mapping * segments in fixmap.h */ +#if defined(BOOTLOADER) +#define __PAGE_OFFSET (0) /* bootloader uses physical addresses */ +#else #ifdef CONFIG_64BIT #define __PAGE_OFFSET (0x40000000) /* 1GB */ #else #define __PAGE_OFFSET (0x10000000) /* 256MB */ #endif +#endif /* BOOTLOADER */ #define PAGE_OFFSET ((unsigned long)__PAGE_OFFSET) diff --git a/arch/parisc/include/asm/pdc.h b/arch/parisc/include/asm/pdc.h index 7569627a032b..26b4455baa83 100644 --- a/arch/parisc/include/asm/pdc.h +++ b/arch/parisc/include/asm/pdc.h @@ -5,6 +5,8 @@ #if !defined(__ASSEMBLY__) +extern int parisc_narrow_firmware; + extern int pdc_type; extern unsigned long parisc_cell_num; /* cell number the CPU runs on (PAT) */ extern unsigned long parisc_cell_loc; /* cell location of CPU (PAT) */ diff --git a/arch/parisc/kernel/firmware.c b/arch/parisc/kernel/firmware.c index be9a2e89e90f..ab80e5c6f651 100644 --- a/arch/parisc/kernel/firmware.c +++ b/arch/parisc/kernel/firmware.c @@ -69,7 +69,15 @@ #include <asm/pdcpat.h> #include <asm/processor.h> /* for boot_cpu_data */ +#if defined(BOOTLOADER) +# undef spin_lock_irqsave +# define spin_lock_irqsave(a, b) { b = 1; } +# undef spin_unlock_irqrestore +# define spin_unlock_irqrestore(a, b) +#else static DEFINE_SPINLOCK(pdc_lock); +#endif + extern unsigned long pdc_result[NUM_PDC_RESULT]; extern unsigned long pdc_result2[NUM_PDC_RESULT]; @@ -186,6 +194,8 @@ void set_firmware_width(void) } #endif /*CONFIG_64BIT*/ + +#if !defined(BOOTLOADER) /** * pdc_emergency_unlock - Unlock the linux pdc lock * @@ -1149,6 +1159,8 @@ void pdc_io_reset_devices(void) spin_unlock_irqrestore(&pdc_lock, flags); } +#endif /* defined(BOOTLOADER) */ + /* locked by pdc_console_lock */ static int __attribute__((aligned(8))) iodc_retbuf[32]; static char __attribute__((aligned(64))) iodc_dbuf[4096]; @@ -1193,6 +1205,7 @@ print: return i; } +#if !defined(BOOTLOADER) /** * pdc_iodc_getc - Read a character (non-blocking) from the PDC console. * @@ -1555,6 +1568,7 @@ int pdc_pat_mem_get_dimm_phys_location( return retval; } #endif /* CONFIG_64BIT */ +#endif /* defined(BOOTLOADER) */ /***************** 32-bit real-mode calls ***********/ @@ -1664,4 +1678,3 @@ long real64_call(unsigned long fn, ...) } #endif /* CONFIG_64BIT */ - diff --git a/arch/parisc/kernel/real2.S b/arch/parisc/kernel/real2.S index 1db58e546230..cc9963421a19 100644 --- a/arch/parisc/kernel/real2.S +++ b/arch/parisc/kernel/real2.S @@ -162,6 +162,7 @@ ENDPROC_CFI(restore_control_regs) .text .align 128 ENTRY_CFI(rfi_virt2real) +#if !defined(BOOTLOADER) /* switch to real mode... */ rsm PSW_SM_I,%r0 load32 PA(rfi_v2r_1), %r1 @@ -191,6 +192,7 @@ ENTRY_CFI(rfi_virt2real) nop rfi_v2r_1: tophys_r1 %r2 +#endif /* defined(BOOTLOADER) */ bv 0(%r2) nop ENDPROC_CFI(rfi_virt2real) @@ -198,6 +200,7 @@ ENDPROC_CFI(rfi_virt2real) .text .align 128 ENTRY_CFI(rfi_real2virt) +#if !defined(BOOTLOADER) rsm PSW_SM_I,%r0 load32 (rfi_r2v_1), %r1 nop @@ -226,6 +229,7 @@ ENTRY_CFI(rfi_real2virt) nop rfi_r2v_1: tovirt_r1 %r2 +#endif /* defined(BOOTLOADER) */ bv 0(%r2) nop ENDPROC_CFI(rfi_real2virt) -- cgit v1.2.3-70-g09d2 From b6adc16e08e0ee8bbc9cccf7af3882b6e1cb30c2 Mon Sep 17 00:00:00 2001 From: Helge Deller <deller@gmx.de> Date: Sun, 20 Aug 2017 10:52:22 +0200 Subject: parisc: Wire up support for self-extracting kernel Signed-off-by: Helge Deller <deller@gmx.de> --- arch/parisc/Kconfig | 6 ++++++ arch/parisc/Makefile | 16 +++++++++++++--- 2 files changed, 19 insertions(+), 3 deletions(-) diff --git a/arch/parisc/Kconfig b/arch/parisc/Kconfig index 9db4b4f2f8f5..13648519bd41 100644 --- a/arch/parisc/Kconfig +++ b/arch/parisc/Kconfig @@ -20,6 +20,12 @@ config PARISC select BUG select BUILDTIME_EXTABLE_SORT select HAVE_PERF_EVENTS + select HAVE_KERNEL_BZIP2 + select HAVE_KERNEL_GZIP + select HAVE_KERNEL_LZ4 + select HAVE_KERNEL_LZMA + select HAVE_KERNEL_LZO + select HAVE_KERNEL_XZ select GENERIC_ATOMIC64 if !64BIT select GENERIC_IRQ_PROBE select GENERIC_PCI_IOMAP diff --git a/arch/parisc/Makefile b/arch/parisc/Makefile index 75cb451b1f03..58fae5d2449d 100644 --- a/arch/parisc/Makefile +++ b/arch/parisc/Makefile @@ -24,15 +24,20 @@ KBUILD_DEFCONFIG := default_defconfig NM = sh $(srctree)/arch/parisc/nm CHECKFLAGS += -D__hppa__=1 LIBGCC = $(shell $(CC) $(KBUILD_CFLAGS) -print-libgcc-file-name) +export LIBGCC ifdef CONFIG_64BIT UTS_MACHINE := parisc64 CHECKFLAGS += -D__LP64__=1 -m64 CC_ARCHES = hppa64 +LD_BFD := elf64-hppa-linux else # 32-bit CC_ARCHES = hppa hppa2.0 hppa1.1 +LD_BFD := elf32-hppa-linux endif +export LD_BFD + ifneq ($(SUBARCH),$(UTS_MACHINE)) ifeq ($(CROSS_COMPILE),) CC_SUFFIXES = linux linux-gnu unknown-linux-gnu @@ -88,6 +93,8 @@ libs-y += arch/parisc/lib/ $(LIBGCC) drivers-$(CONFIG_OPROFILE) += arch/parisc/oprofile/ +boot := arch/parisc/boot + PALO := $(shell if (which palo 2>&1); then : ; \ elif [ -x /sbin/palo ]; then echo /sbin/palo; \ fi) @@ -116,11 +123,14 @@ INSTALL_TARGETS = zinstall install PHONY += bzImage $(BOOT_TARGETS) $(INSTALL_TARGETS) -bzImage zImage: vmlinuz +zImage: vmlinuz Image: vmlinux -vmlinuz: vmlinux - @gzip -cf -9 $< > $@ +bzImage: vmlinux + $(Q)$(MAKE) $(build)=$(boot) $(boot)/$@ + +vmlinuz: bzImage + $(OBJCOPY) $(boot)/bzImage $@ install: $(CONFIG_SHELL) $(src)/arch/parisc/install.sh \ -- cgit v1.2.3-70-g09d2 From c8dbaa2261197a648673cc14a280fe7dac73ca5d Mon Sep 17 00:00:00 2001 From: Helge Deller <deller@gmx.de> Date: Mon, 21 Aug 2017 21:52:05 +0200 Subject: parisc/harmony: Fix section mismatches Signed-off-by: Helge Deller <deller@gmx.de> --- sound/parisc/harmony.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/sound/parisc/harmony.c b/sound/parisc/harmony.c index 5911eb35c2a3..5e04c2b4fbc1 100644 --- a/sound/parisc/harmony.c +++ b/sound/parisc/harmony.c @@ -66,7 +66,7 @@ module_param(id, charp, 0444); MODULE_PARM_DESC(id, "ID string for Harmony driver."); -static struct parisc_device_id snd_harmony_devtable[] = { +static const struct parisc_device_id snd_harmony_devtable[] __initconst = { /* bushmaster / flounder */ { HPHW_FIO, HVERSION_REV_ANY_ID, HVERSION_ANY_ID, 0x0007A }, /* 712 / 715 */ @@ -960,7 +960,7 @@ free_and_ret: return err; } -static int +static int __init snd_harmony_probe(struct parisc_device *padev) { int err; @@ -1000,18 +1000,18 @@ free_and_ret: return err; } -static int +static int __exit snd_harmony_remove(struct parisc_device *padev) { snd_card_free(parisc_get_drvdata(padev)); return 0; } -static struct parisc_driver snd_harmony_driver = { +static struct parisc_driver snd_harmony_driver __refdata = { .name = "harmony", .id_table = snd_harmony_devtable, .probe = snd_harmony_probe, - .remove = snd_harmony_remove, + .remove = __exit_p(snd_harmony_remove), }; static int __init -- cgit v1.2.3-70-g09d2 From 6aaf7934cfcd3884c852ad88559c228a53b413f7 Mon Sep 17 00:00:00 2001 From: Helge Deller <deller@gmx.de> Date: Mon, 21 Aug 2017 21:54:23 +0200 Subject: parisc/sticore: Fix section mismatches Signed-off-by: Helge Deller <deller@gmx.de> --- drivers/video/console/sticore.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/drivers/video/console/sticore.c b/drivers/video/console/sticore.c index 7da1ad03acb5..d1d3796773aa 100644 --- a/drivers/video/console/sticore.c +++ b/drivers/video/console/sticore.c @@ -281,7 +281,7 @@ static void sti_rom_copy(unsigned long base, unsigned long count, void *dest) static char default_sti_path[21] __read_mostly; #ifndef MODULE -static int sti_setup(char *str) +static int __init sti_setup(char *str) { if (str) strlcpy (default_sti_path, str, sizeof (default_sti_path)); @@ -941,7 +941,7 @@ static void sticore_check_for_default_sti(struct sti_struct *sti, char *path) * in the additional address field addr[1] while on * older Systems the PDC stores it in page0->proc_sti */ -static int sticore_pa_init(struct parisc_device *dev) +static int __init sticore_pa_init(struct parisc_device *dev) { char pa_path[21]; struct sti_struct *sti = NULL; @@ -1009,7 +1009,7 @@ static int sticore_pci_init(struct pci_dev *pd, const struct pci_device_id *ent) } -static void sticore_pci_remove(struct pci_dev *pd) +static void __exit sticore_pci_remove(struct pci_dev *pd) { BUG(); } @@ -1029,7 +1029,7 @@ static struct pci_driver pci_sti_driver = { .name = "sti", .id_table = sti_pci_tbl, .probe = sticore_pci_init, - .remove = sticore_pci_remove, + .remove = __exit_p(sticore_pci_remove), }; static struct parisc_device_id sti_pa_tbl[] = { @@ -1037,8 +1037,9 @@ static struct parisc_device_id sti_pa_tbl[] = { { HPHW_FIO, HVERSION_REV_ANY_ID, HVERSION_ANY_ID, 0x00085 }, { 0, } }; +MODULE_DEVICE_TABLE(parisc, sti_pa_tbl); -static struct parisc_driver pa_sti_driver = { +static struct parisc_driver pa_sti_driver __refdata = { .name = "sti", .id_table = sti_pa_tbl, .probe = sticore_pa_init, -- cgit v1.2.3-70-g09d2 From fc72b7a3a0d893576afb19b4f38c1d6160e9753b Mon Sep 17 00:00:00 2001 From: Helge Deller <deller@gmx.de> Date: Mon, 21 Aug 2017 21:55:11 +0200 Subject: parisc/mux: Fix section mismatches Signed-off-by: Helge Deller <deller@gmx.de> --- drivers/tty/serial/mux.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/tty/serial/mux.c b/drivers/tty/serial/mux.c index 8a4be4b73723..6f14d2a547c4 100644 --- a/drivers/tty/serial/mux.c +++ b/drivers/tty/serial/mux.c @@ -503,7 +503,7 @@ static int __init mux_probe(struct parisc_device *dev) return 0; } -static int mux_remove(struct parisc_device *dev) +static int __exit mux_remove(struct parisc_device *dev) { int i, j; int port_count = (long)dev_get_drvdata(&dev->dev); @@ -536,13 +536,13 @@ static int mux_remove(struct parisc_device *dev) * This table only contains the parisc_device_id of known builtin mux * devices. All other mux cards will be detected by the generic mux_tbl. */ -static struct parisc_device_id builtin_mux_tbl[] = { +static const struct parisc_device_id builtin_mux_tbl[] __initconst = { { HPHW_A_DIRECT, HVERSION_REV_ANY_ID, 0x15, 0x0000D }, /* All K-class */ { HPHW_A_DIRECT, HVERSION_REV_ANY_ID, 0x44, 0x0000D }, /* E35, E45, and E55 */ { 0, } }; -static struct parisc_device_id mux_tbl[] = { +static const struct parisc_device_id mux_tbl[] __initconst = { { HPHW_A_DIRECT, HVERSION_REV_ANY_ID, HVERSION_ANY_ID, 0x0000D }, { 0, } }; @@ -550,18 +550,18 @@ static struct parisc_device_id mux_tbl[] = { MODULE_DEVICE_TABLE(parisc, builtin_mux_tbl); MODULE_DEVICE_TABLE(parisc, mux_tbl); -static struct parisc_driver builtin_serial_mux_driver = { +static struct parisc_driver builtin_serial_mux_driver __refdata = { .name = "builtin_serial_mux", .id_table = builtin_mux_tbl, .probe = mux_probe, - .remove = mux_remove, + .remove = __exit_p(mux_remove), }; -static struct parisc_driver serial_mux_driver = { +static struct parisc_driver serial_mux_driver __refdata = { .name = "serial_mux", .id_table = mux_tbl, .probe = mux_probe, - .remove = mux_remove, + .remove = __exit_p(mux_remove), }; /** -- cgit v1.2.3-70-g09d2 From 9e466f101e19f0836e8040a7bf4cde2205534963 Mon Sep 17 00:00:00 2001 From: Helge Deller <deller@gmx.de> Date: Mon, 21 Aug 2017 21:56:08 +0200 Subject: parisc/8250_gsc: Fix section mismatches Signed-off-by: Helge Deller <deller@gmx.de> --- drivers/tty/serial/8250/8250_gsc.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/tty/serial/8250/8250_gsc.c b/drivers/tty/serial/8250/8250_gsc.c index 63306de4390d..df2931e1e086 100644 --- a/drivers/tty/serial/8250/8250_gsc.c +++ b/drivers/tty/serial/8250/8250_gsc.c @@ -80,7 +80,7 @@ static int __init serial_init_chip(struct parisc_device *dev) return 0; } -static struct parisc_device_id serial_tbl[] = { +static const struct parisc_device_id serial_tbl[] __initconst = { { HPHW_FIO, HVERSION_REV_ANY_ID, HVERSION_ANY_ID, 0x00075 }, { HPHW_FIO, HVERSION_REV_ANY_ID, HVERSION_ANY_ID, 0x0008c }, { HPHW_FIO, HVERSION_REV_ANY_ID, HVERSION_ANY_ID, 0x0008d }, @@ -94,7 +94,7 @@ static struct parisc_device_id serial_tbl[] = { * which only knows about Lasi and then a second which will find all the * other serial ports. HPUX ignores this problem. */ -static struct parisc_device_id lasi_tbl[] = { +static const struct parisc_device_id lasi_tbl[] __initconst = { { HPHW_FIO, HVERSION_REV_ANY_ID, 0x03B, 0x0008C }, /* C1xx/C1xxL */ { HPHW_FIO, HVERSION_REV_ANY_ID, 0x03C, 0x0008C }, /* B132L */ { HPHW_FIO, HVERSION_REV_ANY_ID, 0x03D, 0x0008C }, /* B160L */ @@ -110,13 +110,13 @@ static struct parisc_device_id lasi_tbl[] = { MODULE_DEVICE_TABLE(parisc, serial_tbl); -static struct parisc_driver lasi_driver = { +static struct parisc_driver lasi_driver __refdata = { .name = "serial_1", .id_table = lasi_tbl, .probe = serial_init_chip, }; -static struct parisc_driver serial_driver = { +static struct parisc_driver serial_driver __refdata = { .name = "serial", .id_table = serial_tbl, .probe = serial_init_chip, -- cgit v1.2.3-70-g09d2 From 5898aa13ab4899d3a12e069f8716f83dd44567eb Mon Sep 17 00:00:00 2001 From: Helge Deller <deller@gmx.de> Date: Mon, 21 Aug 2017 21:56:59 +0200 Subject: parisc/scsi/zalon: Fix section mismatches Signed-off-by: Helge Deller <deller@gmx.de> --- drivers/scsi/zalon.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/scsi/zalon.c b/drivers/scsi/zalon.c index b2cf1faa819d..4722660958f8 100644 --- a/drivers/scsi/zalon.c +++ b/drivers/scsi/zalon.c @@ -160,14 +160,14 @@ zalon_probe(struct parisc_device *dev) return error; } -static struct parisc_device_id zalon_tbl[] = { +static const struct parisc_device_id zalon_tbl[] __initconst = { { HPHW_A_DMA, HVERSION_REV_ANY_ID, HVERSION_ANY_ID, 0x00089 }, { 0, } }; MODULE_DEVICE_TABLE(parisc, zalon_tbl); -static int zalon_remove(struct parisc_device *dev) +static int __exit zalon_remove(struct parisc_device *dev) { struct Scsi_Host *host = dev_get_drvdata(&dev->dev); @@ -178,11 +178,11 @@ static int zalon_remove(struct parisc_device *dev) return 0; } -static struct parisc_driver zalon_driver = { +static struct parisc_driver zalon_driver __refdata = { .name = "zalon", .id_table = zalon_tbl, .probe = zalon_probe, - .remove = zalon_remove, + .remove = __exit_p(zalon_remove), }; static int __init zalon7xx_init(void) -- cgit v1.2.3-70-g09d2 From 6ade2a0be9ee20bfd7a884436ce73df9a69d1d8c Mon Sep 17 00:00:00 2001 From: Helge Deller <deller@gmx.de> Date: Mon, 21 Aug 2017 21:57:39 +0200 Subject: parisc/scsi/lasi700: Fix section mismatches Signed-off-by: Helge Deller <deller@gmx.de> --- drivers/scsi/lasi700.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/scsi/lasi700.c b/drivers/scsi/lasi700.c index 5c4ded997265..dc839279bbd9 100644 --- a/drivers/scsi/lasi700.c +++ b/drivers/scsi/lasi700.c @@ -81,7 +81,7 @@ MODULE_LICENSE("GPL"); #define LASI710_CLOCK 40 #define LASI_SCSI_CORE_OFFSET 0x100 -static struct parisc_device_id lasi700_ids[] = { +static const struct parisc_device_id lasi700_ids[] __initconst = { LASI700_ID_TABLE, LASI710_ID_TABLE, { 0 } @@ -164,11 +164,11 @@ lasi700_driver_remove(struct parisc_device *dev) return 0; } -static struct parisc_driver lasi700_driver = { +static struct parisc_driver lasi700_driver __refdata = { .name = "lasi_scsi", .id_table = lasi700_ids, .probe = lasi700_probe, - .remove = lasi700_driver_remove, + .remove = __exit_p(lasi700_driver_remove), }; static int __init -- cgit v1.2.3-70-g09d2 From f0973443bef706b6bccc8a1b99a19b8e389bf9cd Mon Sep 17 00:00:00 2001 From: Helge Deller <deller@gmx.de> Date: Mon, 21 Aug 2017 21:58:19 +0200 Subject: parisc/parport_gsc: Fix section mismatches Signed-off-by: Helge Deller <deller@gmx.de> --- drivers/parport/parport_gsc.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/parport/parport_gsc.c b/drivers/parport/parport_gsc.c index 3858b87fd0bb..5f710aaaf3da 100644 --- a/drivers/parport/parport_gsc.c +++ b/drivers/parport/parport_gsc.c @@ -346,7 +346,7 @@ struct parport *parport_gsc_probe_port(unsigned long base, static int parport_count; -static int parport_init_chip(struct parisc_device *dev) +static int __init parport_init_chip(struct parisc_device *dev) { struct parport *p; unsigned long port; @@ -381,7 +381,7 @@ static int parport_init_chip(struct parisc_device *dev) return 0; } -static int parport_remove_chip(struct parisc_device *dev) +static int __exit parport_remove_chip(struct parisc_device *dev) { struct parport *p = dev_get_drvdata(&dev->dev); if (p) { @@ -403,18 +403,18 @@ static int parport_remove_chip(struct parisc_device *dev) return 0; } -static struct parisc_device_id parport_tbl[] = { +static const struct parisc_device_id parport_tbl[] __initconst = { { HPHW_FIO, HVERSION_REV_ANY_ID, HVERSION_ANY_ID, 0x74 }, { 0, } }; MODULE_DEVICE_TABLE(parisc, parport_tbl); -static struct parisc_driver parport_driver = { +static struct parisc_driver parport_driver __refdata = { .name = "Parallel", .id_table = parport_tbl, .probe = parport_init_chip, - .remove = parport_remove_chip, + .remove = __exit_p(parport_remove_chip), }; int parport_gsc_init(void) -- cgit v1.2.3-70-g09d2 From cfe4fbfb23b3280e9a4d1c3b8438c1558a6a614d Mon Sep 17 00:00:00 2001 From: Helge Deller <deller@gmx.de> Date: Mon, 21 Aug 2017 22:02:19 +0200 Subject: parisc: Fix section mismatches in parisc core drivers Signed-off-by: Helge Deller <deller@gmx.de> --- drivers/parisc/asp.c | 4 ++-- drivers/parisc/ccio-dma.c | 4 ++-- drivers/parisc/ccio-rm-dma.c | 6 +++--- drivers/parisc/dino.c | 4 ++-- drivers/parisc/eisa.c | 4 ++-- drivers/parisc/hppb.c | 6 +++--- drivers/parisc/lasi.c | 4 ++-- drivers/parisc/lba_pci.c | 4 ++-- drivers/parisc/sba_iommu.c | 6 +++--- drivers/parisc/superio.c | 4 ++-- drivers/parisc/wax.c | 4 ++-- 11 files changed, 25 insertions(+), 25 deletions(-) diff --git a/drivers/parisc/asp.c b/drivers/parisc/asp.c index 6a1ab2512a53..3163b6752d3d 100644 --- a/drivers/parisc/asp.c +++ b/drivers/parisc/asp.c @@ -118,12 +118,12 @@ static int __init asp_init_chip(struct parisc_device *dev) return ret; } -static struct parisc_device_id asp_tbl[] = { +static const struct parisc_device_id asp_tbl[] __initconst = { { HPHW_BA, HVERSION_REV_ANY_ID, HVERSION_ANY_ID, 0x00070 }, { 0, } }; -struct parisc_driver asp_driver = { +struct parisc_driver asp_driver __refdata = { .name = "asp", .id_table = asp_tbl, .probe = asp_init_chip, diff --git a/drivers/parisc/ccio-dma.c b/drivers/parisc/ccio-dma.c index 6aa1e7f6672f..acba1f56af3e 100644 --- a/drivers/parisc/ccio-dma.c +++ b/drivers/parisc/ccio-dma.c @@ -1241,7 +1241,7 @@ ccio_get_iotlb_size(struct parisc_device *dev) #endif /* 0 */ /* We *can't* support JAVA (T600). Venture there at your own risk. */ -static const struct parisc_device_id ccio_tbl[] = { +static const struct parisc_device_id ccio_tbl[] __initconst = { { HPHW_IOA, HVERSION_REV_ANY_ID, U2_IOA_RUNWAY, 0xb }, /* U2 */ { HPHW_IOA, HVERSION_REV_ANY_ID, UTURN_IOA_RUNWAY, 0xb }, /* UTurn */ { 0, } @@ -1249,7 +1249,7 @@ static const struct parisc_device_id ccio_tbl[] = { static int ccio_probe(struct parisc_device *dev); -static struct parisc_driver ccio_driver = { +static struct parisc_driver ccio_driver __refdata = { .name = "ccio", .id_table = ccio_tbl, .probe = ccio_probe, diff --git a/drivers/parisc/ccio-rm-dma.c b/drivers/parisc/ccio-rm-dma.c index 1bf988010855..df7932af48b7 100644 --- a/drivers/parisc/ccio-rm-dma.c +++ b/drivers/parisc/ccio-rm-dma.c @@ -163,7 +163,7 @@ static struct pci_dma_ops ccio_ops = { ** If so, initialize the chip and tell other partners in crime they ** have work to do. */ -static int +static int __init ccio_probe(struct parisc_device *dev) { printk(KERN_INFO "%s found %s at 0x%lx\n", MODULE_NAME, @@ -184,13 +184,13 @@ ccio_probe(struct parisc_device *dev) return 0; } -static struct parisc_device_id ccio_tbl[] = { +static const struct parisc_device_id ccio_tbl[] __initconst = { { HPHW_BCPORT, HVERSION_REV_ANY_ID, U2_BC_GSC, 0xc }, { HPHW_BCPORT, HVERSION_REV_ANY_ID, UTURN_BC_GSC, 0xc }, { 0, } }; -static struct parisc_driver ccio_driver = { +static struct parisc_driver ccio_driver __refdata = { .name = "U2/Uturn", .id_table = ccio_tbl, .probe = ccio_probe, diff --git a/drivers/parisc/dino.c b/drivers/parisc/dino.c index ed92c1254cff..0b3fb99d9b89 100644 --- a/drivers/parisc/dino.c +++ b/drivers/parisc/dino.c @@ -1022,7 +1022,7 @@ static int __init dino_probe(struct parisc_device *dev) * and 725 firmware misreport it as 0x08080 for no adequately explained * reason. */ -static struct parisc_device_id dino_tbl[] = { +static const struct parisc_device_id dino_tbl[] __initconst = { { HPHW_A_DMA, HVERSION_REV_ANY_ID, 0x004, 0x0009D },/* Card-mode Dino */ { HPHW_A_DMA, HVERSION_REV_ANY_ID, HVERSION_ANY_ID, 0x08080 }, /* XXX */ { HPHW_BRIDGE, HVERSION_REV_ANY_ID, 0x680, 0xa }, /* Bridge-mode Dino */ @@ -1031,7 +1031,7 @@ static struct parisc_device_id dino_tbl[] = { { 0, } }; -static struct parisc_driver dino_driver = { +static struct parisc_driver dino_driver __refdata = { .name = "dino", .id_table = dino_tbl, .probe = dino_probe, diff --git a/drivers/parisc/eisa.c b/drivers/parisc/eisa.c index 7e2f6d5a6aaf..9ff434f354bd 100644 --- a/drivers/parisc/eisa.c +++ b/drivers/parisc/eisa.c @@ -393,7 +393,7 @@ error_release: return result; } -static const struct parisc_device_id eisa_tbl[] = { +static const struct parisc_device_id eisa_tbl[] __initconst = { { HPHW_BA, HVERSION_REV_ANY_ID, HVERSION_ANY_ID, 0x00076 }, /* Mongoose */ { HPHW_BA, HVERSION_REV_ANY_ID, HVERSION_ANY_ID, 0x00090 }, /* Wax EISA */ { 0, } @@ -401,7 +401,7 @@ static const struct parisc_device_id eisa_tbl[] = { MODULE_DEVICE_TABLE(parisc, eisa_tbl); -static struct parisc_driver eisa_driver = { +static struct parisc_driver eisa_driver __refdata = { .name = "eisa_ba", .id_table = eisa_tbl, .probe = eisa_probe, diff --git a/drivers/parisc/hppb.c b/drivers/parisc/hppb.c index 898208e4f302..ebc7b617e5d0 100644 --- a/drivers/parisc/hppb.c +++ b/drivers/parisc/hppb.c @@ -45,7 +45,7 @@ static struct hppb_card hppb_card_head = { * (return 1). If so, initialize the chip and tell other partners in crime * they have work to do. */ -static int hppb_probe(struct parisc_device *dev) +static int __init hppb_probe(struct parisc_device *dev) { int status; struct hppb_card *card = &hppb_card_head; @@ -81,7 +81,7 @@ static int hppb_probe(struct parisc_device *dev) return 0; } -static struct parisc_device_id hppb_tbl[] = { +static const struct parisc_device_id hppb_tbl[] __initconst = { { HPHW_BCPORT, HVERSION_REV_ANY_ID, 0x500, 0xc }, /* E25 and K */ { HPHW_BCPORT, 0x0, 0x501, 0xc }, /* E35 */ { HPHW_BCPORT, 0x0, 0x502, 0xc }, /* E45 */ @@ -89,7 +89,7 @@ static struct parisc_device_id hppb_tbl[] = { { 0, } }; -static struct parisc_driver hppb_driver = { +static struct parisc_driver hppb_driver __refdata = { .name = "gecko_boa", .id_table = hppb_tbl, .probe = hppb_probe, diff --git a/drivers/parisc/lasi.c b/drivers/parisc/lasi.c index e65727ca9fc0..4c9225431500 100644 --- a/drivers/parisc/lasi.c +++ b/drivers/parisc/lasi.c @@ -227,12 +227,12 @@ static int __init lasi_init_chip(struct parisc_device *dev) return ret; } -static struct parisc_device_id lasi_tbl[] = { +static struct parisc_device_id lasi_tbl[] __initdata = { { HPHW_BA, HVERSION_REV_ANY_ID, HVERSION_ANY_ID, 0x00081 }, { 0, } }; -struct parisc_driver lasi_driver = { +struct parisc_driver lasi_driver __refdata = { .name = "lasi", .id_table = lasi_tbl, .probe = lasi_init_chip, diff --git a/drivers/parisc/lba_pci.c b/drivers/parisc/lba_pci.c index bc286cbbbc9b..0cc6d5cc5d66 100644 --- a/drivers/parisc/lba_pci.c +++ b/drivers/parisc/lba_pci.c @@ -1613,14 +1613,14 @@ lba_driver_probe(struct parisc_device *dev) return 0; } -static struct parisc_device_id lba_tbl[] = { +static const struct parisc_device_id lba_tbl[] __initconst = { { HPHW_BRIDGE, HVERSION_REV_ANY_ID, ELROY_HVERS, 0xa }, { HPHW_BRIDGE, HVERSION_REV_ANY_ID, MERCURY_HVERS, 0xa }, { HPHW_BRIDGE, HVERSION_REV_ANY_ID, QUICKSILVER_HVERS, 0xa }, { 0, } }; -static struct parisc_driver lba_driver = { +static struct parisc_driver lba_driver __refdata = { .name = MODULE_NAME, .id_table = lba_tbl, .probe = lba_driver_probe, diff --git a/drivers/parisc/sba_iommu.c b/drivers/parisc/sba_iommu.c index 4086f79d58d5..0a9c762a70fa 100644 --- a/drivers/parisc/sba_iommu.c +++ b/drivers/parisc/sba_iommu.c @@ -1905,7 +1905,7 @@ static const struct file_operations sba_proc_bitmap_fops = { }; #endif /* CONFIG_PROC_FS */ -static struct parisc_device_id sba_tbl[] = { +static const struct parisc_device_id sba_tbl[] __initconst = { { HPHW_IOA, HVERSION_REV_ANY_ID, ASTRO_RUNWAY_PORT, 0xb }, { HPHW_BCPORT, HVERSION_REV_ANY_ID, IKE_MERCED_PORT, 0xc }, { HPHW_BCPORT, HVERSION_REV_ANY_ID, REO_MERCED_PORT, 0xc }, @@ -1916,7 +1916,7 @@ static struct parisc_device_id sba_tbl[] = { static int sba_driver_callback(struct parisc_device *); -static struct parisc_driver sba_driver = { +static struct parisc_driver sba_driver __refdata = { .name = MODULE_NAME, .id_table = sba_tbl, .probe = sba_driver_callback, @@ -1927,7 +1927,7 @@ static struct parisc_driver sba_driver = { ** If so, initialize the chip and tell other partners in crime they ** have work to do. */ -static int sba_driver_callback(struct parisc_device *dev) +static int __init sba_driver_callback(struct parisc_device *dev) { struct sba_device *sba_dev; u32 func_class; diff --git a/drivers/parisc/superio.c b/drivers/parisc/superio.c index deeaed544222..0441777fc777 100644 --- a/drivers/parisc/superio.c +++ b/drivers/parisc/superio.c @@ -482,14 +482,14 @@ superio_probe(struct pci_dev *dev, const struct pci_device_id *id) return -ENODEV; } -static const struct pci_device_id superio_tbl[] = { +static const struct pci_device_id superio_tbl[] __initconst = { { PCI_DEVICE(PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_87560_LIO) }, { PCI_DEVICE(PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_87560_USB) }, { PCI_DEVICE(PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_87415) }, { 0, } }; -static struct pci_driver superio_driver = { +static struct pci_driver superio_driver __refdata = { .name = SUPERIO, .id_table = superio_tbl, .probe = superio_probe, diff --git a/drivers/parisc/wax.c b/drivers/parisc/wax.c index da9d5ad1353c..6a3e40702b3b 100644 --- a/drivers/parisc/wax.c +++ b/drivers/parisc/wax.c @@ -125,14 +125,14 @@ static int __init wax_init_chip(struct parisc_device *dev) return ret; } -static struct parisc_device_id wax_tbl[] = { +static const struct parisc_device_id wax_tbl[] __initconst = { { HPHW_BA, HVERSION_REV_ANY_ID, HVERSION_ANY_ID, 0x0008e }, { 0, } }; MODULE_DEVICE_TABLE(parisc, wax_tbl); -struct parisc_driver wax_driver = { +struct parisc_driver wax_driver __refdata = { .name = "wax", .id_table = wax_tbl, .probe = wax_init_chip, -- cgit v1.2.3-70-g09d2 From c1bebd070008e5cca8ab6a0d183068b9f51f6f50 Mon Sep 17 00:00:00 2001 From: Helge Deller <deller@gmx.de> Date: Mon, 21 Aug 2017 22:03:39 +0200 Subject: parisc/serio: Fix section mismatches in gscps2 and hp_sdc drivers Signed-off-by: Helge Deller <deller@gmx.de> --- drivers/input/serio/gscps2.c | 10 +++++----- drivers/input/serio/hp_sdc.c | 4 ++-- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/input/serio/gscps2.c b/drivers/input/serio/gscps2.c index ecba666afadb..aa9f29b875de 100644 --- a/drivers/input/serio/gscps2.c +++ b/drivers/input/serio/gscps2.c @@ -325,7 +325,7 @@ static void gscps2_close(struct serio *port) * @return: success/error report */ -static int gscps2_probe(struct parisc_device *dev) +static int __init gscps2_probe(struct parisc_device *dev) { struct gscps2port *ps2port; struct serio *serio; @@ -412,7 +412,7 @@ fail_nomem: * @return: success/error report */ -static int gscps2_remove(struct parisc_device *dev) +static int __exit gscps2_remove(struct parisc_device *dev) { struct gscps2port *ps2port = dev_get_drvdata(&dev->dev); @@ -430,7 +430,7 @@ static int gscps2_remove(struct parisc_device *dev) } -static struct parisc_device_id gscps2_device_tbl[] = { +static const struct parisc_device_id gscps2_device_tbl[] __initconst = { { HPHW_FIO, HVERSION_REV_ANY_ID, HVERSION_ANY_ID, 0x00084 }, /* LASI PS/2 */ #ifdef DINO_TESTED { HPHW_FIO, HVERSION_REV_ANY_ID, HVERSION_ANY_ID, 0x00096 }, /* DINO PS/2 */ @@ -439,11 +439,11 @@ static struct parisc_device_id gscps2_device_tbl[] = { }; MODULE_DEVICE_TABLE(parisc, gscps2_device_tbl); -static struct parisc_driver parisc_ps2_driver = { +static struct parisc_driver parisc_ps2_driver __refdata = { .name = "gsc_ps2", .id_table = gscps2_device_tbl, .probe = gscps2_probe, - .remove = gscps2_remove, + .remove = __exit_p(gscps2_remove), }; static int __init gscps2_init(void) diff --git a/drivers/input/serio/hp_sdc.c b/drivers/input/serio/hp_sdc.c index 1bfdae4b0d99..8eef6849d066 100644 --- a/drivers/input/serio/hp_sdc.c +++ b/drivers/input/serio/hp_sdc.c @@ -805,7 +805,7 @@ static void hp_sdc_kicker(unsigned long data) #if defined(__hppa__) -static const struct parisc_device_id hp_sdc_tbl[] = { +static const struct parisc_device_id hp_sdc_tbl[] __initconst = { { .hw_type = HPHW_FIO, .hversion_rev = HVERSION_REV_ANY_ID, @@ -820,7 +820,7 @@ MODULE_DEVICE_TABLE(parisc, hp_sdc_tbl); static int __init hp_sdc_init_hppa(struct parisc_device *d); static struct delayed_work moduleloader_work; -static struct parisc_driver hp_sdc_driver = { +static struct parisc_driver hp_sdc_driver __refdata = { .name = "hp_sdc", .id_table = hp_sdc_tbl, .probe = hp_sdc_init_hppa, -- cgit v1.2.3-70-g09d2 From 117c02394a29768573c4c4ea86b61d83970c8391 Mon Sep 17 00:00:00 2001 From: Helge Deller <deller@gmx.de> Date: Mon, 21 Aug 2017 22:05:51 +0200 Subject: parisc/net/lasi_82596: Fix section mismatches Signed-off-by: Helge Deller <deller@gmx.de> --- drivers/net/ethernet/i825xx/lasi_82596.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/net/ethernet/i825xx/lasi_82596.c b/drivers/net/ethernet/i825xx/lasi_82596.c index d787fdd5db7b..aa22e108f09b 100644 --- a/drivers/net/ethernet/i825xx/lasi_82596.c +++ b/drivers/net/ethernet/i825xx/lasi_82596.c @@ -149,7 +149,7 @@ static void mpu_port(struct net_device *dev, int c, dma_addr_t x) #define LAN_PROM_ADDR 0xF0810000 -static int +static int __init lan_init_chip(struct parisc_device *dev) { struct net_device *netdevice; @@ -194,7 +194,7 @@ lan_init_chip(struct parisc_device *dev) return retval; } -static int lan_remove_chip(struct parisc_device *pdev) +static int __exit lan_remove_chip(struct parisc_device *pdev) { struct net_device *dev = parisc_get_drvdata(pdev); struct i596_private *lp = netdev_priv(dev); @@ -206,7 +206,7 @@ static int lan_remove_chip(struct parisc_device *pdev) return 0; } -static struct parisc_device_id lan_tbl[] = { +static const struct parisc_device_id lan_tbl[] __initconst = { { HPHW_FIO, HVERSION_REV_ANY_ID, HVERSION_ANY_ID, 0x0008a }, { HPHW_FIO, HVERSION_REV_ANY_ID, HVERSION_ANY_ID, 0x00072 }, { 0, } @@ -214,11 +214,11 @@ static struct parisc_device_id lan_tbl[] = { MODULE_DEVICE_TABLE(parisc, lan_tbl); -static struct parisc_driver lan_driver = { +static struct parisc_driver lan_driver __refdata = { .name = "lasi_82596", .id_table = lan_tbl, .probe = lan_init_chip, - .remove = lan_remove_chip, + .remove = __exit_p(lan_remove_chip), }; static int lasi_82596_init(void) -- cgit v1.2.3-70-g09d2 From 98c77c7945241d2268712ac7e8edf7c99d3ad53e Mon Sep 17 00:00:00 2001 From: Helge Deller <deller@gmx.de> Date: Mon, 21 Aug 2017 22:06:45 +0200 Subject: parisc/input/hilkbd: Fix section mismatches Signed-off-by: Helge Deller <deller@gmx.de> --- drivers/input/keyboard/hilkbd.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/input/keyboard/hilkbd.c b/drivers/input/keyboard/hilkbd.c index 198dc07a1be5..a4e404aaf64b 100644 --- a/drivers/input/keyboard/hilkbd.c +++ b/drivers/input/keyboard/hilkbd.c @@ -299,7 +299,7 @@ static void hil_keyb_exit(void) } #if defined(CONFIG_PARISC) -static int hil_probe_chip(struct parisc_device *dev) +static int __init hil_probe_chip(struct parisc_device *dev) { /* Only allow one HIL keyboard */ if (hil_dev.dev) @@ -320,14 +320,14 @@ static int hil_probe_chip(struct parisc_device *dev) return hil_keyb_init(); } -static int hil_remove_chip(struct parisc_device *dev) +static int __exit hil_remove_chip(struct parisc_device *dev) { hil_keyb_exit(); return 0; } -static struct parisc_device_id hil_tbl[] = { +static const struct parisc_device_id hil_tbl[] __initconst = { { HPHW_FIO, HVERSION_REV_ANY_ID, HVERSION_ANY_ID, 0x00073 }, { 0, } }; @@ -337,11 +337,11 @@ static struct parisc_device_id hil_tbl[] = { MODULE_DEVICE_TABLE(parisc, hil_tbl); #endif -static struct parisc_driver hil_driver = { +static struct parisc_driver hil_driver __refdata = { .name = "hil", .id_table = hil_tbl, .probe = hil_probe_chip, - .remove = hil_remove_chip, + .remove = __exit_p(hil_remove_chip), }; static int __init hil_init(void) -- cgit v1.2.3-70-g09d2 From 0618cdfaeb0733e82d296d9db746b0fe0f07fefe Mon Sep 17 00:00:00 2001 From: Helge Deller <deller@gmx.de> Date: Mon, 21 Aug 2017 22:07:54 +0200 Subject: parisc/ipmi_si_intf: Fix section mismatches on parisc platform Additionally add a MODULE_DEVICE_TABLE entry so that udev can load the driver automatically. Signed-off-by: Helge Deller <deller@gmx.de> --- drivers/char/ipmi/ipmi_si_intf.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/drivers/char/ipmi/ipmi_si_intf.c b/drivers/char/ipmi/ipmi_si_intf.c index 985973855005..36f47e8d06a3 100644 --- a/drivers/char/ipmi/ipmi_si_intf.c +++ b/drivers/char/ipmi/ipmi_si_intf.c @@ -2812,7 +2812,7 @@ static struct platform_driver ipmi_driver = { }; #ifdef CONFIG_PARISC -static int ipmi_parisc_probe(struct parisc_device *dev) +static int __init ipmi_parisc_probe(struct parisc_device *dev) { struct smi_info *info; int rv; @@ -2850,22 +2850,24 @@ static int ipmi_parisc_probe(struct parisc_device *dev) return 0; } -static int ipmi_parisc_remove(struct parisc_device *dev) +static int __exit ipmi_parisc_remove(struct parisc_device *dev) { cleanup_one_si(dev_get_drvdata(&dev->dev)); return 0; } -static const struct parisc_device_id ipmi_parisc_tbl[] = { +static const struct parisc_device_id ipmi_parisc_tbl[] __initconst = { { HPHW_MC, HVERSION_REV_ANY_ID, 0x004, 0xC0 }, { 0, } }; -static struct parisc_driver ipmi_parisc_driver = { +MODULE_DEVICE_TABLE(parisc, ipmi_parisc_tbl); + +static struct parisc_driver ipmi_parisc_driver __refdata = { .name = "ipmi", .id_table = ipmi_parisc_tbl, .probe = ipmi_parisc_probe, - .remove = ipmi_parisc_remove, + .remove = __exit_p(ipmi_parisc_remove), }; #endif /* CONFIG_PARISC */ -- cgit v1.2.3-70-g09d2 From 6c706b93b078ca0a802f6987b81899f4650a7810 Mon Sep 17 00:00:00 2001 From: Helge Deller <deller@gmx.de> Date: Mon, 21 Aug 2017 22:09:30 +0200 Subject: parisc/core: Fix section mismatches Signed-off-by: Helge Deller <deller@gmx.de> --- arch/parisc/kernel/processor.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/arch/parisc/kernel/processor.c b/arch/parisc/kernel/processor.c index 6b6fe8d62893..a778bd3c107c 100644 --- a/arch/parisc/kernel/processor.c +++ b/arch/parisc/kernel/processor.c @@ -90,7 +90,7 @@ init_percpu_prof(unsigned long cpunum) * (return 1). If so, initialize the chip and tell other partners in crime * they have work to do. */ -static int processor_probe(struct parisc_device *dev) +static int __init processor_probe(struct parisc_device *dev) { unsigned long txn_addr; unsigned long cpuid; @@ -432,12 +432,12 @@ show_cpuinfo (struct seq_file *m, void *v) return 0; } -static const struct parisc_device_id processor_tbl[] = { +static const struct parisc_device_id processor_tbl[] __initconst = { { HPHW_NPROC, HVERSION_REV_ANY_ID, HVERSION_ANY_ID, SVERSION_ANY_ID }, { 0, } }; -static struct parisc_driver cpu_driver = { +static struct parisc_driver cpu_driver __refdata = { .name = "CPU", .id_table = processor_tbl, .probe = processor_probe -- cgit v1.2.3-70-g09d2 From d81f734462d439291531266c4004ab97e9a033cc Mon Sep 17 00:00:00 2001 From: Helge Deller <deller@gmx.de> Date: Wed, 16 Aug 2017 18:53:16 +0200 Subject: parisc: Fix up devices below a PCI-PCI MegaRAID controller bridge A MegaRAID PCI card in my rp5470 acts as PCI-PCI bridge. Resource allocation for PCI devices behind such a bridge is quite incomplete, so that syslog reports those warnings: LBA 0:10: PCI host bridge to bus 0000:50 pci_bus 0000:50: root bus resource [io 0x80000-0x8ffff] (bus address [0x0000-0xffff]) pci_bus 0000:50: root bus resource [mem 0xffffffff94000000-0xffffffff95ffffff] (bus address [0x94000000-0x95ffffff]) pci_bus 0000:50: root bus resource [bus 50-57] pci 0000:50:00.0: [8086:0964] type 01 class 0x060400 pci 0000:50:00.1: [8086:1960] type 00 class 0x0e0001 pci 0000:50:00.1: reg 0x10: [mem 0x00000000-0x003fffff pref] pci 0000:50:00.1: reg 0x30: [mem 0x00000000-0x00007fff pref] pci 0000:50:00.0: Changing bridge control from 0x00000000 to 0x00000023 pci_bus 0000:51: busn_res: can not insert [bus 51-ff] under [bus 50-57] (conflicts with (null) [bus 50-57]) pci 0000:50:00.0: PCI bridge to [bus 51-ff] pci 0000:50:00.0: bridge window [io 0x80000-0x80fff] pci 0000:50:00.0: bridge window [mem 0x00000000-0x000fffff] pci 0000:50:00.0: bridge window [mem 0x00000000-0x000fffff pref] pci 0000:50:00.0: can't claim BAR 14 [mem 0x00000000-0x000fffff]: no compatible bridge window pci 0000:50:00.0: can't claim BAR 15 [mem 0x00000000-0x000fffff pref]: no compatible bridge window pci 0000:50:00.0: can't claim BAR 16 [??? 0x00000000 flags 0x0]: no compatible bridge window pci_bus 0000:51: busn_res: [bus 51-ff] end is updated to 51 pci 0000:50:00.0: BAR 16: [??? 0x00000000 flags 0x20000000] has bogus alignment pci 0000:50:00.1: BAR 0: assigned [mem 0xffffffff94000000-0xffffffff943fffff pref] pci 0000:50:00.0: BAR 14: assigned [mem 0xffffffff94400000-0xffffffff944fffff] pci 0000:50:00.0: BAR 15: assigned [mem 0xffffffff94500000-0xffffffff945fffff pref] pci 0000:50:00.1: BAR 6: assigned [mem 0xffffffff94600000-0xffffffff94607fff pref] pci 0000:50:00.0: PCI bridge to [bus 51] pci 0000:50:00.0: bridge window [io 0x80000-0x80fff] pci 0000:50:00.0: bridge window [mem 0xffffffff94400000-0xffffffff944fffff] pci 0000:50:00.0: bridge window [mem 0xffffffff94500000-0xffffffff945fffff pref] The patch below tries to improve the resource allocation. Output is now: LBA 0:10: PCI host bridge to bus 0000:50 pci_bus 0000:50: root bus resource [io 0x80000-0x8ffff] (bus address [0x0000-0xffff]) pci_bus 0000:50: root bus resource [mem 0xffffffff94000000-0xffffffff95ffffff] (bus address [0x94000000-0x95ffffff]) pci_bus 0000:50: root bus resource [bus 50-57] pci 0000:50:00.0: Changing bridge control from 0x00000000 to 0x00000023 pci 0000:50:00.0: PCI bridge to [bus 51-ff] pci 0000:50:00.1: BAR 0: assigned [mem 0xffffffff94000000-0xffffffff943fffff pref] pci 0000:50:00.1: BAR 6: assigned [mem 0xffffffff94400000-0xffffffff94407fff pref] pci 0000:50:00.0: PCI bridge to [bus 51] pci 0000:50:00.0: bridge window [io 0x80000-0x80fff] Signed-off-by: Helge Deller <deller@gmx.de> --- drivers/parisc/lba_pci.c | 42 +++++++++++++++++++++++++++++++++++++++--- 1 file changed, 39 insertions(+), 3 deletions(-) diff --git a/drivers/parisc/lba_pci.c b/drivers/parisc/lba_pci.c index 0cc6d5cc5d66..a25fed52f7e9 100644 --- a/drivers/parisc/lba_pci.c +++ b/drivers/parisc/lba_pci.c @@ -667,6 +667,42 @@ extend_lmmio_len(unsigned long start, unsigned long end, unsigned long lba_len) #define truncate_pat_collision(r,n) (0) #endif +static void pcibios_allocate_bridge_resources(struct pci_dev *dev) +{ + int idx; + struct resource *r; + + for (idx = PCI_BRIDGE_RESOURCES; idx < PCI_NUM_RESOURCES; idx++) { + r = &dev->resource[idx]; + if (!r->flags) + continue; + if (r->parent) /* Already allocated */ + continue; + if (!r->start || pci_claim_bridge_resource(dev, idx) < 0) { + /* + * Something is wrong with the region. + * Invalidate the resource to prevent + * child resource allocations in this + * range. + */ + r->start = r->end = 0; + r->flags = 0; + } + } +} + +static void pcibios_allocate_bus_resources(struct pci_bus *bus) +{ + struct pci_bus *child; + + /* Depth-First Search on bus tree */ + if (bus->self) + pcibios_allocate_bridge_resources(bus->self); + list_for_each_entry(child, &bus->children, node) + pcibios_allocate_bus_resources(child); +} + + /* ** The algorithm is generic code. ** But it needs to access local data structures to get the IRQ base. @@ -693,11 +729,11 @@ lba_fixup_bus(struct pci_bus *bus) ** pci_alloc_primary_bus() mangles this. */ if (bus->parent) { - int i; /* PCI-PCI Bridge */ pci_read_bridge_bases(bus); - for (i = PCI_BRIDGE_RESOURCES; i < PCI_NUM_RESOURCES; i++) - pci_claim_bridge_resource(bus->self, i); + + /* check and allocate bridge resources */ + pcibios_allocate_bus_resources(bus); } else { /* Host-PCI Bridge */ int err; -- cgit v1.2.3-70-g09d2 From fd46cd55fbc5a8e8c180ee04a30cda26c84569d2 Mon Sep 17 00:00:00 2001 From: Helge Deller <deller@gmx.de> Date: Wed, 23 Aug 2017 21:52:05 +0200 Subject: printk-formats.txt: Add examples for %pF and %pS usage Signed-off-by: Helge Deller <deller@gmx.de> Signed-off-by: Petr Mladek <pmladek@suse.com> Reviewed-by: Sergey Senozhatsky <sergey.senozhatsky@gmail.com> Acked-by: Steven Rostedt (VMware) <rostedt@goodmis.org> --- Documentation/printk-formats.txt | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/Documentation/printk-formats.txt b/Documentation/printk-formats.txt index 074670b98bac..361789df51ec 100644 --- a/Documentation/printk-formats.txt +++ b/Documentation/printk-formats.txt @@ -75,6 +75,16 @@ used when printing stack backtraces. The specifier takes into consideration the effect of compiler optimisations which may occur when tail-call``s are used and marked with the noreturn GCC attribute. +Examples:: + + printk("Going to call: %pF\n", gettimeofday); + printk("Going to call: %pF\n", p->func); + printk("%s: called from %pS\n", __func__, (void *)_RET_IP_); + printk("%s: called from %pS\n", __func__, + (void *)__builtin_return_address(0)); + printk("Faulted at %pS\n", (void *)regs->ip); + printk(" %s%pB\n", (reliable ? "" : "? "), (void *)*stack); + Kernel Pointers =============== -- cgit v1.2.3-70-g09d2