From 5d9dae73e3962e58da22b29e4eb1d1dd2f6fc013 Mon Sep 17 00:00:00 2001 From: Wan Ahmad Zainie Date: Tue, 14 Mar 2017 15:45:21 -0500 Subject: [PATCH 001/110] usb: dwc3: call _DSM for core soft reset The issue is, if core soft reset is issued while Intel Apollo Lake USB mux is in Host role mode, it takes close to 7 minutes before we are able to switch USB mux from Host mode to Device mode. This is due to RTL bug. The workaround is to let BIOS issue the core soft reset via _DSM method. It will ensure that USB mux is in Device role mode before issuing core soft reset, and will inform the driver whether the reset is success within the timeout value, or the timeout is exceeded. commit cd78b8067c6e ("usb: dwc3: call _DSM for core soft reset") originated from http://git.yoctoproject.org/cgit/cgit.cgi/linux-yocto-4.1/ Signed-off-by: Wan Ahmad Zainie [akash.mankar@ni.com: changed the way has_dsm_for_softreset property is set in dwc3-pci.c and read in core.c] Signed-off-by: Akash Mankar Signed-off-by: Brad Mouring Acked-by: Gratian Crisan Acked-by: Brandon Streiff Natinst-ReviewBoard-ID: 178124 [gratian: fixed merge conflicts, mainly due to dwc3_soft_reset removal] Signed-off-by: Gratian Crisan [bstreiff: fixed merge conflicts due to property refactor by 1a7b12f69a94 ("usb: dwc3: pci: Supply device properties via driver data")] [gratian: fix merge conflict with f580170f135a ("usb: dwc3: Add splitdisable quirk for Hisilicon Kirin Soc")] Signed-off-by: Gratian Crisan --- drivers/usb/dwc3/core.c | 40 +++++++++++++++++++++++++++++++++++++ drivers/usb/dwc3/core.h | 3 +++ drivers/usb/dwc3/dwc3-pci.c | 1 + 3 files changed, 44 insertions(+) diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c index 841daec70b6ef..245e366deeebe 100644 --- a/drivers/usb/dwc3/core.c +++ b/drivers/usb/dwc3/core.c @@ -230,6 +230,38 @@ u32 dwc3_core_fifo_space(struct dwc3_ep *dep, u8 type) return DWC3_GDBGFIFOSPACE_SPACE_AVAILABLE(reg); } +/** + * WORKAROUND: We let BIOS issues the core soft reset to Device + * controller for Intel Apollo Lake, via _DSM method. + * + * The issue is, if core soft reset is issued while Intel Apollo Lake + * USB mux is in Host role mode, it takes close to 7 minutes before + * we are able to switch USB mux from Host mode to Device mode. + */ +static int dwc3_pci_dsm_soft_reset(struct device *dev) +{ + int ret = -ETIMEDOUT; + union acpi_object *obj; + guid_t guid; + + WARN_ON(guid_parse("732b85d5-b7a7-4a1b-9ba0-4bbd00ffd511", &guid)); + + obj = acpi_evaluate_dsm(ACPI_HANDLE(dev), + &guid, + 1, 6, NULL); + if (!obj) { + dev_err(dev, "failed to evaluate _DSM\n"); + return -EIO; + } + + if (obj->type == ACPI_TYPE_INTEGER) + ret = (obj->integer.value == 0) ? 0 : -ETIMEDOUT; + dev_dbg(dev, "dwc3_pci_dsm_soft_reset() ret= %d\n", ret); + + ACPI_FREE(obj); + return ret; +} + /** * dwc3_core_soft_reset - Issues core soft reset and PHY reset * @dwc: pointer to our context structure @@ -260,6 +292,11 @@ static int dwc3_core_soft_reset(struct dwc3 *dwc) if (dwc->current_dr_role == DWC3_GCTL_PRTCAP_HOST) return 0; + if (dwc->has_dsm_for_softreset) { + dev_dbg(dwc->dev, "calling dwc3_pci_dsm_soft_reset()"); + return dwc3_pci_dsm_soft_reset(dwc->dev); + } + reg = dwc3_readl(dwc->regs, DWC3_DCTL); reg |= DWC3_DCTL_CSFTRST; dwc3_writel(dwc->regs, DWC3_DCTL, reg); @@ -1358,6 +1395,9 @@ static void dwc3_get_properties(struct dwc3 *dwc) dwc->dis_split_quirk = device_property_read_bool(dev, "snps,dis-split-quirk"); + dwc->has_dsm_for_softreset = device_property_read_bool(dev, + "snps,has_dsm_for_softreset"); + dwc->lpm_nyet_threshold = lpm_nyet_threshold; dwc->tx_de_emphasis = tx_de_emphasis; diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h index 2f95f08ca5119..c1afd98e4bd0d 100644 --- a/drivers/usb/dwc3/core.h +++ b/drivers/usb/dwc3/core.h @@ -1058,6 +1058,7 @@ struct dwc3_scratchpad_array { * 3 - Reserved * @dis_metastability_quirk: set to disable metastability quirk. * @dis_split_quirk: set to disable split boundary. + * @has_dsm_for_softreset: set if we want to use BIOS to do core soft reset * @imod_interval: set the interrupt moderation interval in 250ns * increments or 0 to disable. */ @@ -1253,6 +1254,8 @@ struct dwc3 { unsigned dis_split_quirk:1; + unsigned has_dsm_for_softreset:1; + u16 imod_interval; }; diff --git a/drivers/usb/dwc3/dwc3-pci.c b/drivers/usb/dwc3/dwc3-pci.c index bae6a70664c80..34e3b5f6589a0 100644 --- a/drivers/usb/dwc3/dwc3-pci.c +++ b/drivers/usb/dwc3/dwc3-pci.c @@ -111,6 +111,7 @@ static int dwc3_byt_enable_ulpi_refclock(struct pci_dev *pci) static const struct property_entry dwc3_pci_intel_properties[] = { PROPERTY_ENTRY_STRING("dr_mode", "peripheral"), + PROPERTY_ENTRY_BOOL("snps,has_dsm_for_softreset"), PROPERTY_ENTRY_BOOL("linux,sysdev_is_parent"), {} }; From 42ed058652985eaf0c301d89c73a4bbd4fd77e92 Mon Sep 17 00:00:00 2001 From: Richard Tollerton Date: Wed, 4 Apr 2012 20:13:05 -0400 Subject: [PATCH 002/110] ftrace: ni: add raw marker support for trace tool Signed-off-by: Richard Tollerton [gratian: fix conflict with fa32e8557b47 ("tracing: Add new trace_marker_raw"); rename NI specific implementation until we can replace it] Signed-off-by: Gratian Crisan [bstreiff: fixups due to struct member renames in 13292494379f ("tracing: Make struct ring_buffer less ambiguous")] Signed-off-by: Brandon Streiff [gratian: update for 22c36b182634 ("tracing: make tracing_init_dentry() returns an integer instead of a d_entry pointer")] Signed-off-by: Gratian Crisan --- kernel/trace/trace.c | 91 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 91 insertions(+) diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c index 6bf160b478ff2..96abae0eb4149 100644 --- a/kernel/trace/trace.c +++ b/kernel/trace/trace.c @@ -6795,6 +6795,88 @@ tracing_mark_raw_write(struct file *filp, const char __user *ubuf, return written; } +/* + * rtollert: tracing_ni_ett_raw_write exists as part of LabVIEW RT's support of + * the Execution Trace Toolkit. LabVIEW RT logs its own events through this + * interface, so that they are stored in ftrace's ring buffers. Basically + * tracing_ni_ett_raw_write is the same as tracing_mark_write, except all the + * text processing code is ripped out for improved performance. + * + * These events will show up as BPRINT ftrace events, with ip and fmt set to + * the fourcc 'lvrt'. The event data is generally a binary blob that is + * processed later by LabVIEW RT (and ultimately the ETT). That data is not + * meant to be parsed by third parties and is not documented (sorry). + * + * I'm a little embarrassed of this implementation, so this code goes out of + * its way to scream "HACK!": The hardcoded settings for ip and fmt; the + * name of the marker file (trace_ni_ett_marker), etc. + * + * Eventually I'd like to see a solution which would allow multiple programs + * to each write to their own marker files, with dynamically allocated IDs, + * without overloading BPRINT events, etc. However a lot of that is contingent + * on if it's even a good idea to allow binary blobs to be logged to ftrace. + * (a worthwhile discussion!) + */ +static ssize_t +tracing_ni_ett_raw_write(struct file *filp, const char __user *ubuf, + size_t cnt, loff_t *fpos) +{ + struct trace_event_call *call = &event_bprint; + struct ring_buffer_event *event; + struct trace_array *tr = &global_trace; + struct trace_buffer *buffer = tr->array_buffer.buffer; + struct trace_array_cpu *data; + int cpu, size, pc; + struct bprint_entry *entry; + unsigned long irq_flags; + int disable; + + const unsigned int ip = 0x6c767274; /* "lvrt" */ + const char *fmt = "lvrt"; /* to avoid dereferencing NULL */ + + if (tracing_disabled || tracing_selftest_running) + return -EINVAL; + + pc = preempt_count(); + preempt_disable_notrace(); + cpu = raw_smp_processor_id(); + data = per_cpu_ptr(tr->array_buffer.data, cpu); + disable = atomic_inc_return(&data->disabled); + if (unlikely(disable != 1)) + goto out; + pause_graph_tracing(); + raw_local_irq_save(irq_flags); + + size = sizeof(*entry) + cnt; + event = trace_buffer_lock_reserve(buffer, TRACE_BPRINT, size, + irq_flags, pc); + if (!event) + goto out_unlock; + entry = ring_buffer_event_data(event); + entry->ip = ip; + entry->fmt = fmt; + + if (cnt) { + if (copy_from_user(&(entry->buf[0]), ubuf, cnt)) { + cnt = -EFAULT; + goto error_and_trace; + } + } + if (call_filter_check_discard(call, entry, buffer, event)) + goto out_unlock; + error_and_trace: + __buffer_unlock_commit(buffer, event); + ftrace_trace_stack(&global_trace, buffer, irq_flags, 6, pc, NULL); + out_unlock: + raw_local_irq_restore(irq_flags); + unpause_graph_tracing(); + out: + atomic_dec_return(&data->disabled); + preempt_enable_notrace(); + + return cnt; +} + static int tracing_clock_show(struct seq_file *m, void *v) { struct trace_array *tr = m->private; @@ -7201,6 +7283,12 @@ static const struct file_operations tracing_mark_raw_fops = { .release = tracing_release_generic_tr, }; +static const struct file_operations tracing_ni_ett_raw_fops = { + .open = tracing_open_generic, + .write = tracing_ni_ett_raw_write, + .llseek = generic_file_llseek, +}; + static const struct file_operations trace_clock_fops = { .open = tracing_clock_open, .read = seq_read, @@ -9178,6 +9266,9 @@ static __init int tracer_init_tracefs(void) trace_create_file("README", 0444, NULL, NULL, &tracing_readme_fops); + trace_create_file("trace_ni_ett_marker", 0220, NULL, + NULL, &tracing_ni_ett_raw_fops); + trace_create_file("saved_cmdlines", 0444, NULL, NULL, &tracing_saved_cmdlines_fops); From dcd249848dbb1ca249f97fdc88042d049e53284c Mon Sep 17 00:00:00 2001 From: Ben Shelton Date: Tue, 1 Apr 2014 11:31:31 -0500 Subject: [PATCH 003/110] shared: Adding mcopy syscall for Zynq and x64 Signed-off-by: Ben Shelton Acked-by: Scot Salmon Acked-by: Terry Wilcox Natinst-ReviewBoard-ID: 69848 [gratian: convert to new syscall table format for arm] Signed-off-by: Gratian Crisan [bstreiff: update the number for this painful out-of-tree syscall] Signed-off-by: Brandon Streiff [gratian: update due to new syscall introduced by ecb8ac8b1f14 ("mm/madvise: introduce process_madvise() syscall: an external memory hinting AP")] Signed-off-by: Gratian Crisan --- arch/arm/tools/syscall.tbl | 1 + arch/x86/entry/syscalls/syscall_64.tbl | 1 + include/linux/syscalls.h | 3 +++ include/uapi/asm-generic/unistd.h | 5 +++- kernel/ksysfs.c | 14 +++++++++++ mm/maccess.c | 32 ++++++++++++++++++++++++++ 6 files changed, 55 insertions(+), 1 deletion(-) diff --git a/arch/arm/tools/syscall.tbl b/arch/arm/tools/syscall.tbl index d056a548358ea..22bb327704781 100644 --- a/arch/arm/tools/syscall.tbl +++ b/arch/arm/tools/syscall.tbl @@ -454,3 +454,4 @@ 438 common pidfd_getfd sys_pidfd_getfd 439 common faccessat2 sys_faccessat2 440 common process_madvise sys_process_madvise +441 common mcopy sys_mcopy diff --git a/arch/x86/entry/syscalls/syscall_64.tbl b/arch/x86/entry/syscalls/syscall_64.tbl index 379819244b91d..f8aa93f2c3da9 100644 --- a/arch/x86/entry/syscalls/syscall_64.tbl +++ b/arch/x86/entry/syscalls/syscall_64.tbl @@ -362,6 +362,7 @@ 438 common pidfd_getfd sys_pidfd_getfd 439 common faccessat2 sys_faccessat2 440 common process_madvise sys_process_madvise +441 common mcopy sys_mcopy # # Due to a historical design error, certain syscalls are numbered differently diff --git a/include/linux/syscalls.h b/include/linux/syscalls.h index 37bea07c12f21..d032bbdafa9c1 100644 --- a/include/linux/syscalls.h +++ b/include/linux/syscalls.h @@ -866,6 +866,9 @@ asmlinkage long sys_execve(const char __user *filename, /* mm/fadvise.c */ asmlinkage long sys_fadvise64_64(int fd, loff_t offset, loff_t len, int advice); +/* mm/maccess.c */ +asmlinkage long sys_mcopy(void * __user dest, void * __user src, size_t len); + /* mm/, CONFIG_MMU only */ asmlinkage long sys_swapon(const char __user *specialfile, int swap_flags); asmlinkage long sys_swapoff(const char __user *specialfile); diff --git a/include/uapi/asm-generic/unistd.h b/include/uapi/asm-generic/unistd.h index 2056318988f77..62b67ee07ad7d 100644 --- a/include/uapi/asm-generic/unistd.h +++ b/include/uapi/asm-generic/unistd.h @@ -860,8 +860,11 @@ __SYSCALL(__NR_faccessat2, sys_faccessat2) #define __NR_process_madvise 440 __SYSCALL(__NR_process_madvise, sys_process_madvise) +#define __NR_mcopy 441 +__SYSCALL(__NR_mcopy, sys_mcopy) + #undef __NR_syscalls -#define __NR_syscalls 441 +#define __NR_syscalls 442 /* * 32 bit systems traditionally used different diff --git a/kernel/ksysfs.c b/kernel/ksysfs.c index dfff31ed644a6..e3f0d1f9054aa 100644 --- a/kernel/ksysfs.c +++ b/kernel/ksysfs.c @@ -17,6 +17,7 @@ #include #include #include +#include #include /* rcu_expedited and rcu_normal */ @@ -155,6 +156,16 @@ static ssize_t fscaps_show(struct kobject *kobj, } KERNEL_ATTR_RO(fscaps); +#ifdef __NR_mcopy +static ssize_t ni_syscall_mcopy_show(struct kobject *kobj, + struct kobj_attribute *attr, + char *buf) +{ + return sprintf(buf, "%d\n", __NR_mcopy); +} +KERNEL_ATTR_RO(ni_syscall_mcopy); +#endif + #ifndef CONFIG_TINY_RCU int rcu_expedited; static ssize_t rcu_expedited_show(struct kobject *kobj, @@ -240,6 +251,9 @@ static struct attribute * kernel_attrs[] = { #endif #ifdef CONFIG_PREEMPT_RT &realtime_attr.attr, +#endif +#ifdef __NR_mcopy + &ni_syscall_mcopy_attr.attr, #endif NULL }; diff --git a/mm/maccess.c b/mm/maccess.c index 3bd70405f2d84..9fcd74b0181f2 100644 --- a/mm/maccess.c +++ b/mm/maccess.c @@ -5,6 +5,7 @@ #include #include #include +#include bool __weak copy_from_kernel_nofault_allowed(const void *unsafe_src, size_t size) @@ -319,3 +320,34 @@ long strnlen_user_nofault(const void __user *unsafe_addr, long count) return ret; } + +/* + * Safely copy 'len' bytes from user space 'src' to user space 'dst'. + * 'len' must be less than or equal to 64. In particular, safely here + * means that if we are trying to copy memory that has been freed and + * unmapped we don't crash. + * + * Returns + * 0 copy completed successfully + * + * EFAULT if either the source or destination blocks are not + * valid + * + * EINVAL len is greater than 64 + * + */ +SYSCALL_DEFINE3(mcopy, void*, dst, void*, src, size_t, len) +{ + char buf[64]; + + if (len > 64) + return -EINVAL; + + if (copy_from_user(buf, src, len)) + return -EFAULT; + + if (copy_to_user(dst, buf, len)) + return -EFAULT; + + return 0; +} From 124845db2e399ccc37b8e13428ecf20134f474a4 Mon Sep 17 00:00:00 2001 From: Terry Wilcox Date: Mon, 19 May 2014 15:28:03 -0500 Subject: [PATCH 004/110] kernel: Providing API to allow userland programs to request a cold or warm reboot Another group is requesting that we provide an API to allow them to signal that the next reboot should be "cold". They need this to guarantee that the FPGA will not be running and cause the system to reboot at a bad time. This change creates a RW file at /sys/kernel/ni_requested_reboot_type. The default value is 0. - If when we reboot the value is 0 then we do the normal reset behavior. - If the value is 1 we attempt to do a PCI reboot (using the CF9 register) and fall back to the normal reboot method if that fails. - If the value is 2 we attempt to do an ACPI reboot and fall back to the normal reboot method if that fails. We selected a reboot using the CF9 register over attempting to do an EFI reboot because we don't have much time to test this feature and we've found EFI features to be fairly buggy. For next release the plan is to do an EFI cold reboot, but put it in early enough to properly test it. Rebooting using the CF9 register should work on all x64 hardware that we will support for 2014 (smasher and hammerhead). Signed-off-by: Terry Wilcox Acked-by: Brad Mouring Natinst-ReviewBoard-ID: 68018 --- arch/x86/kernel/reboot.c | 49 ++++++++++++++++++++++++++++++++-------- kernel/ksysfs.c | 18 +++++++++++++++ 2 files changed, 58 insertions(+), 9 deletions(-) diff --git a/arch/x86/kernel/reboot.c b/arch/x86/kernel/reboot.c index db115943e8bdc..52754bee39ecb 100644 --- a/arch/x86/kernel/reboot.c +++ b/arch/x86/kernel/reboot.c @@ -39,6 +39,14 @@ void (*pm_power_off)(void); EXPORT_SYMBOL(pm_power_off); +enum requested_reboot_type { + REQUEST_DEFAULT_REBOOT, + REQUEST_COLD_REBOOT, + REQUEST_WARM_REBOOT +}; + +enum requested_reboot_type requested_reboot_type = REQUEST_DEFAULT_REBOOT; + /* * This is set if we need to go through the 'emergency' path. * When machine_emergency_restart() is called, we may be on @@ -571,6 +579,21 @@ void __attribute__((weak)) mach_reboot_fixups(void) { } +static void native_machine_restart_cf9(void) +{ + if (port_cf9_safe) { + u8 reboot_code = reboot_mode == REBOOT_WARM ? 0x06 : 0x0E; + u8 cf9 = inb(0xcf9) & ~reboot_code; + + outb(cf9|2, 0xcf9); /* Request hard reset */ + udelay(50); + /* Actually do the reset */ + outb(cf9|reboot_code, 0xcf9); + udelay(50); + } +} + + /* * To the best of our knowledge Windows compatible x86 hardware expects * the following on reboot: @@ -602,6 +625,22 @@ static void native_machine_emergency_restart(void) tboot_shutdown(TB_SHUTDOWN_REBOOT); + + switch (requested_reboot_type) { + case REQUEST_COLD_REBOOT: + port_cf9_safe = true; + native_machine_restart_cf9(); + break; + + case REQUEST_WARM_REBOOT: + acpi_reboot(); + break; + + case REQUEST_DEFAULT_REBOOT: + default: + break; + } + /* Tell the BIOS if we want cold or warm reboot */ mode = reboot_mode == REBOOT_WARM ? 0x1234 : 0; *((unsigned short *)__va(0x472)) = mode; @@ -657,15 +696,7 @@ static void native_machine_emergency_restart(void) fallthrough; case BOOT_CF9_SAFE: - if (port_cf9_safe) { - u8 reboot_code = reboot_mode == REBOOT_WARM ? 0x06 : 0x0E; - u8 cf9 = inb(0xcf9) & ~reboot_code; - outb(cf9|2, 0xcf9); /* Request hard reset */ - udelay(50); - /* Actually do the reset */ - outb(cf9|reboot_code, 0xcf9); - udelay(50); - } + native_machine_restart_cf9(); reboot_type = BOOT_TRIPLE; break; diff --git a/kernel/ksysfs.c b/kernel/ksysfs.c index e3f0d1f9054aa..4c779a24eb030 100644 --- a/kernel/ksysfs.c +++ b/kernel/ksysfs.c @@ -202,6 +202,23 @@ static ssize_t rcu_normal_store(struct kobject *kobj, KERNEL_ATTR_RW(rcu_normal); #endif /* #ifndef CONFIG_TINY_RCU */ +extern int requested_reboot_type; +static ssize_t ni_requested_reboot_type_show(struct kobject *kobj, + struct kobj_attribute *attr, char *buf) +{ + return sprintf(buf, "%d\n", requested_reboot_type); +} +static ssize_t ni_requested_reboot_type_store(struct kobject *kobj, + struct kobj_attribute *attr, + const char *buf, size_t count) +{ + if (kstrtoint(buf, 0, &requested_reboot_type)) + return -EINVAL; + + return count; +} +KERNEL_ATTR_RW(ni_requested_reboot_type); + /* * Make /sys/kernel/notes give the raw contents of our kernel .notes section. */ @@ -255,6 +272,7 @@ static struct attribute * kernel_attrs[] = { #ifdef __NR_mcopy &ni_syscall_mcopy_attr.attr, #endif + &ni_requested_reboot_type_attr.attr, NULL }; From 7084789f5c811c7f6426b07cacd7d8a367082781 Mon Sep 17 00:00:00 2001 From: Ben Shelton Date: Tue, 10 Jun 2014 15:04:11 -0500 Subject: [PATCH 005/110] kernel: Add config option to specify NI cold boot support Currently, we provide NI cold boot support on x64 targets. However, at some future point, we may wish to provide this support on other targets as well. Adding a config option to specify that a target supports NI cold boot functionality; this fixes the build for Zynq targets and doesn't paint us into a corner later. Signed-off-by: Ben Shelton --- arch/x86/Kconfig | 4 ++++ kernel/ksysfs.c | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index ed5780f610806..dd6db73b6458f 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -244,6 +244,10 @@ config X86 select X86_FEATURE_NAMES if PROC_FS select PROC_PID_ARCH_STATUS if PROC_FS imply IMA_SECURE_AND_OR_TRUSTED_BOOT if EFI + select NI_COLD_BOOT_SUPPORT + +config NI_COLD_BOOT_SUPPORT + def_bool n config INSTRUCTION_DECODER def_bool y diff --git a/kernel/ksysfs.c b/kernel/ksysfs.c index 4c779a24eb030..49b35cb4c0520 100644 --- a/kernel/ksysfs.c +++ b/kernel/ksysfs.c @@ -202,6 +202,7 @@ static ssize_t rcu_normal_store(struct kobject *kobj, KERNEL_ATTR_RW(rcu_normal); #endif /* #ifndef CONFIG_TINY_RCU */ +#ifdef CONFIG_NI_COLD_BOOT_SUPPORT extern int requested_reboot_type; static ssize_t ni_requested_reboot_type_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf) @@ -218,6 +219,7 @@ static ssize_t ni_requested_reboot_type_store(struct kobject *kobj, return count; } KERNEL_ATTR_RW(ni_requested_reboot_type); +#endif /* * Make /sys/kernel/notes give the raw contents of our kernel .notes section. @@ -272,7 +274,9 @@ static struct attribute * kernel_attrs[] = { #ifdef __NR_mcopy &ni_syscall_mcopy_attr.attr, #endif +#ifdef CONFIG_NI_COLD_BOOT_SUPPORT &ni_requested_reboot_type_attr.attr, +#endif NULL }; From 7685dd980829d2d326ded8b5cfea92c458dcd3f9 Mon Sep 17 00:00:00 2001 From: Jeff Westfahl Date: Mon, 16 Dec 2013 10:33:02 -0600 Subject: [PATCH 006/110] nirtfeatures: Added NI RT features driver Added an NI RT features driver. This is an ACPI device that exposes LEDs, switches, and other hardware features of the Smasher controllers. Not all of the proposed features of the device work as expected, and some features may be removed in the future. Development work on this device by the hardware team is currently not a high priority. These issues will be addressed once the hardware team gets back to this device. Signed-off-by: Jeff Westfahl [gratian: fix conflict with 7a6ff4c4cbc3 ("misc: hisi_hikey_usb: Driver to support onboard USB gpio hub on Hikey960")] Signed-off-by: Gratian Crisan --- drivers/misc/Kconfig | 31 ++ drivers/misc/Makefile | 1 + drivers/misc/nirtfeatures.c | 888 ++++++++++++++++++++++++++++++++++++ 3 files changed, 920 insertions(+) create mode 100644 drivers/misc/nirtfeatures.c diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig index fafa8b0d80996..ce0d7c4ed2be8 100644 --- a/drivers/misc/Kconfig +++ b/drivers/misc/Kconfig @@ -466,6 +466,37 @@ config HISI_HIKEY_USB switching between the dual-role USB-C port and the USB-A host ports using only one USB controller. +config NI_RT_FEATURES + bool "NI 903x/913x support" + depends on X86 && ACPI + help + This driver exposes LEDs and other features of NI 903x/913x Real-Time + controllers. + + If unsure, say N (but it's safe to say "Y"). + +config NI_LED_PREFIX + string "NI 903x/913x LED prefix" + depends on NI_RT_FEATURES + default "nizynqcpld" + help + This option defines the base name of LEDs exposed by NI_RT_FEATURES. + The default value maintains backwards compatibility with user-space + software that was originally written for ARM (Zynq) hardware. + + If unsure, use the default. + +config NI_HW_REBOOT + bool "Hardware reboot for NI 903x/913x" + depends on NI_RT_FEATURES && X86_64 + default n + help + If enabled, when rebooting an NI 903x/913x, on-board hardware will + be used to reset the system. If not enabled, the controller will do + a normal ACPI reset. + + If unsure, say N. + source "drivers/misc/c2port/Kconfig" source "drivers/misc/eeprom/Kconfig" source "drivers/misc/cb710/Kconfig" diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile index d23231e733303..9e6292035f0d8 100644 --- a/drivers/misc/Makefile +++ b/drivers/misc/Makefile @@ -57,3 +57,4 @@ obj-$(CONFIG_HABANA_AI) += habanalabs/ obj-$(CONFIG_UACCE) += uacce/ obj-$(CONFIG_XILINX_SDFEC) += xilinx_sdfec.o obj-$(CONFIG_HISI_HIKEY_USB) += hisi_hikey_usb.o +obj-$(CONFIG_NI_RT_FEATURES) += nirtfeatures.o diff --git a/drivers/misc/nirtfeatures.c b/drivers/misc/nirtfeatures.c new file mode 100644 index 0000000000000..11f6d1f0679e9 --- /dev/null +++ b/drivers/misc/nirtfeatures.c @@ -0,0 +1,888 @@ +/* + * Copyright (C) 2013 National Instruments Corp. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include +#include +#include +#include + +#ifdef CONFIG_NI_HW_REBOOT +#include +#endif + +#define MODULE_NAME "nirtfeatures" + +/* Register addresses */ + +#define NIRTF_SIGNATURE 0x00 +#define NIRTF_YEAR 0x01 +#define NIRTF_MONTH 0x02 +#define NIRTF_DAY 0x03 +#define NIRTF_HOUR 0x04 +#define NIRTF_MINUTE 0x05 +#define NIRTF_SCRATCH 0x06 +#define NIRTF_BPINFO 0x07 +#define NIRTF_RAIL_STATUS1 0x08 +#define NIRTF_RAIL_STATUS2 0x09 +#define NIRTF_RESET 0x10 +#define NIRTF_RESET_SOURCE 0x11 +#define NIRTF_PROCESSOR_MODE 0x12 +#define NIRTF_SYSTEM_LEDS 0x20 +#define NIRTF_STATUS_LED_SHIFT1 0x21 +#define NIRTF_STATUS_LED_SHIFT0 0x22 +#define NIRTF_RT_LEDS 0x23 + +#define NIRTF_IO_SIZE 0x40 + +/* Register values */ + +#define NIRTF_BPINFO_ID_MASK 0x07 + +#define NIRTF_BPINFO_ID_MANHATTAN 0 +#define NIRTF_BPINFO_ID_HAMMERHEAD 1 + +#define NIRTF_RESET_RESET_PROCESSOR 0x80 + +#define NIRTF_RESET_SOURCE_SOFT_OFF 0x20 +#define NIRTF_RESET_SOURCE_SOFTWARE 0x10 +#define NIRTF_RESET_SOURCE_WATCHDOG 0x08 +#define NIRTF_RESET_SOURCE_FPGA 0x04 +#define NIRTF_RESET_SOURCE_PROCESSOR 0x02 +#define NIRTF_RESET_SOURCE_BUTTON 0x01 + +#define NIRTF_PROCESSOR_MODE_HARD_BOOT_N 0x20 +#define NIRTF_PROCESSOR_MODE_NO_FPGA 0x10 +#define NIRTF_PROCESSOR_MODE_RECOVERY 0x08 +#define NIRTF_PROCESSOR_MODE_CONSOLE_OUT 0x04 +#define NIRTF_PROCESSOR_MODE_IP_RESET 0x02 +#define NIRTF_PROCESSOR_MODE_SAFE 0x01 + +#define NIRTF_SYSTEM_LEDS_STATUS_RED 0x08 +#define NIRTF_SYSTEM_LEDS_STATUS_YELLOW 0x04 +#define NIRTF_SYSTEM_LEDS_POWER_GREEN 0x02 +#define NIRTF_SYSTEM_LEDS_POWER_YELLOW 0x01 + +#define NIRTF_RT_LEDS_USER2_GREEN 0x08 +#define NIRTF_RT_LEDS_USER2_YELLOW 0x04 +#define NIRTF_RT_LEDS_USER1_GREEN 0x02 +#define NIRTF_RT_LEDS_USER1_YELLOW 0x01 + +/* Structures */ + +struct nirtfeatures { + struct acpi_device *acpi_device; + u16 io_base; + u16 io_size; + spinlock_t lock; + u8 revision[5]; + const char *bpstring; + struct nirtfeatures_led *extra_leds; + unsigned num_extra_leds; +}; + +struct nirtfeatures_led { + struct led_classdev cdev; + struct nirtfeatures *nirtfeatures; + u8 address; + u8 mask; + u8 pattern_hi_addr; + u8 pattern_lo_addr; +}; + +/* sysfs files */ + +static ssize_t nirtfeatures_revision_get(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct acpi_device *acpi_device = to_acpi_device(dev); + struct nirtfeatures *nirtfeatures = acpi_device->driver_data; + + return sprintf(buf, "20%02X/%02X/%02X %02X:%02X\n", + nirtfeatures->revision[0], nirtfeatures->revision[1], + nirtfeatures->revision[2], nirtfeatures->revision[3], + nirtfeatures->revision[4]); +} + +static DEVICE_ATTR(revision, S_IRUGO, nirtfeatures_revision_get, NULL); + +static ssize_t nirtfeatures_scratch_get(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct acpi_device *acpi_device = to_acpi_device(dev); + struct nirtfeatures *nirtfeatures = acpi_device->driver_data; + u8 data; + + data = inb(nirtfeatures->io_base + NIRTF_SCRATCH); + + return sprintf(buf, "%02x\n", data); +} + +static ssize_t nirtfeatures_scratch_set(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct acpi_device *acpi_device = to_acpi_device(dev); + struct nirtfeatures *nirtfeatures = acpi_device->driver_data; + unsigned long tmp; + u8 data; + + if (kstrtoul(buf, 0, &tmp) || (tmp > 0xFF)) + return -EINVAL; + + data = (u8)tmp; + + outb(data, nirtfeatures->io_base + NIRTF_SCRATCH); + + return count; +} + +static DEVICE_ATTR(scratch, S_IRUGO|S_IWUSR, nirtfeatures_scratch_get, + nirtfeatures_scratch_set); + +static ssize_t nirtfeatures_backplane_id_get(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct acpi_device *acpi_device = to_acpi_device(dev); + struct nirtfeatures *nirtfeatures = acpi_device->driver_data; + + return sprintf(buf, "%s\n", nirtfeatures->bpstring); +} + +static DEVICE_ATTR(backplane_id, S_IRUGO, nirtfeatures_backplane_id_get, NULL); + +static ssize_t nirtfeatures_railstatus1_get(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct acpi_device *acpi_device = to_acpi_device(dev); + struct nirtfeatures *nirtfeatures = acpi_device->driver_data; + u8 data; + + data = inb(nirtfeatures->io_base + NIRTF_RAIL_STATUS1); + + return sprintf(buf, "%02x\n", data); +} + +static DEVICE_ATTR(railstatus1, S_IRUGO, nirtfeatures_railstatus1_get, NULL); + +static ssize_t nirtfeatures_railstatus2_get(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct acpi_device *acpi_device = to_acpi_device(dev); + struct nirtfeatures *nirtfeatures = acpi_device->driver_data; + u8 data; + + data = inb(nirtfeatures->io_base + NIRTF_RAIL_STATUS2); + + return sprintf(buf, "%02x\n", data); +} + +static DEVICE_ATTR(railstatus2, S_IRUGO, nirtfeatures_railstatus2_get, NULL); + +static ssize_t nirtfeatures_reset_set(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct acpi_device *acpi_device = to_acpi_device(dev); + struct nirtfeatures *nirtfeatures = acpi_device->driver_data; + + if (strcmp(buf, "1")) + return -EINVAL; + + outb(NIRTF_RESET_RESET_PROCESSOR, nirtfeatures->io_base + NIRTF_RESET); + + return count; +} + +static DEVICE_ATTR(reset, S_IWUSR, NULL, nirtfeatures_reset_set); + +static ssize_t nirtfeatures_reset_source_get(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct acpi_device *acpi_device = to_acpi_device(dev); + struct nirtfeatures *nirtfeatures = acpi_device->driver_data; + u8 data; + const char *reset_source; + + data = inb(nirtfeatures->io_base + NIRTF_PROCESSOR_MODE); + + data &= NIRTF_PROCESSOR_MODE_HARD_BOOT_N; + + /* Power-on reset status is in a different register from the other reset + sources, we must check it first. */ + if (!data) { + reset_source = "power-on reset"; + } else { + data = inb(nirtfeatures->io_base + NIRTF_RESET_SOURCE); + + switch (data) { + case NIRTF_RESET_SOURCE_SOFT_OFF: + reset_source = "soft off button"; + break; + case NIRTF_RESET_SOURCE_SOFTWARE: + reset_source = "software"; + break; + case NIRTF_RESET_SOURCE_WATCHDOG: + reset_source = "watchdog"; + break; + case NIRTF_RESET_SOURCE_FPGA: + reset_source = "FPGA"; + break; + case NIRTF_RESET_SOURCE_PROCESSOR: + reset_source = "processor"; + break; + case NIRTF_RESET_SOURCE_BUTTON: + reset_source = "reset button"; + break; + default: + dev_err(&nirtfeatures->acpi_device->dev, + "Unrecognized reset source 0x%02X\n", + data); + reset_source = "unknown"; + break; + } + } + + return sprintf(buf, "%s\n", reset_source); +} + +static DEVICE_ATTR(reset_source, S_IRUGO, nirtfeatures_reset_source_get, NULL); + +static ssize_t nirtfeatures_hard_boot_get(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct acpi_device *acpi_device = to_acpi_device(dev); + struct nirtfeatures *nirtfeatures = acpi_device->driver_data; + u8 data; + + data = inb(nirtfeatures->io_base + NIRTF_PROCESSOR_MODE); + + data &= NIRTF_PROCESSOR_MODE_HARD_BOOT_N; + + return sprintf(buf, "%s\n", data ? "soft reset" : "power-on reset"); +} + +static ssize_t nirtfeatures_hard_boot_set(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct acpi_device *acpi_device = to_acpi_device(dev); + struct nirtfeatures *nirtfeatures = acpi_device->driver_data; + u8 data; + + if (strcmp(buf, "1")) + return -EINVAL; + + spin_lock(&nirtfeatures->lock); + + data = inb(nirtfeatures->io_base + NIRTF_PROCESSOR_MODE); + + data |= NIRTF_PROCESSOR_MODE_HARD_BOOT_N; + + outb(data, nirtfeatures->io_base + NIRTF_PROCESSOR_MODE); + + spin_unlock(&nirtfeatures->lock); + + return count; +} + +static DEVICE_ATTR(hard_boot, S_IRUGO|S_IWUSR, nirtfeatures_hard_boot_get, + nirtfeatures_hard_boot_set); + +static ssize_t nirtfeatures_no_fpga_get(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct acpi_device *acpi_device = to_acpi_device(dev); + struct nirtfeatures *nirtfeatures = acpi_device->driver_data; + u8 data; + + data = inb(nirtfeatures->io_base + NIRTF_PROCESSOR_MODE); + + data &= NIRTF_PROCESSOR_MODE_NO_FPGA; + + return sprintf(buf, "%u\n", !!data); +} + +static ssize_t nirtfeatures_no_fpga_set(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct acpi_device *acpi_device = to_acpi_device(dev); + struct nirtfeatures *nirtfeatures = acpi_device->driver_data; + unsigned long tmp; + u8 data; + + if (kstrtoul(buf, 0, &tmp) || (tmp > 1)) + return -EINVAL; + + spin_lock(&nirtfeatures->lock); + + data = inb(nirtfeatures->io_base + NIRTF_PROCESSOR_MODE); + + if (tmp) + data |= NIRTF_PROCESSOR_MODE_NO_FPGA; + else + data &= ~NIRTF_PROCESSOR_MODE_NO_FPGA; + + outb(data, nirtfeatures->io_base + NIRTF_PROCESSOR_MODE); + + spin_unlock(&nirtfeatures->lock); + + return count; +} + +static DEVICE_ATTR(no_fpga, S_IRUGO|S_IWUSR, nirtfeatures_no_fpga_get, + nirtfeatures_no_fpga_set); + +static ssize_t nirtfeatures_recovery_mode_get(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct acpi_device *acpi_device = to_acpi_device(dev); + struct nirtfeatures *nirtfeatures = acpi_device->driver_data; + u8 data; + + data = inb(nirtfeatures->io_base + NIRTF_PROCESSOR_MODE); + + data &= NIRTF_PROCESSOR_MODE_RECOVERY; + + return sprintf(buf, "%u\n", !!data); +} + +static ssize_t nirtfeatures_recovery_mode_set(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct acpi_device *acpi_device = to_acpi_device(dev); + struct nirtfeatures *nirtfeatures = acpi_device->driver_data; + unsigned long tmp; + u8 data; + + if (kstrtoul(buf, 0, &tmp) || (tmp > 1)) + return -EINVAL; + + spin_lock(&nirtfeatures->lock); + + data = inb(nirtfeatures->io_base + NIRTF_PROCESSOR_MODE); + + if (tmp) + data |= NIRTF_PROCESSOR_MODE_RECOVERY; + else + data &= ~NIRTF_PROCESSOR_MODE_RECOVERY; + + outb(data, nirtfeatures->io_base + NIRTF_PROCESSOR_MODE); + + spin_unlock(&nirtfeatures->lock); + + return count; +} + +static DEVICE_ATTR(recovery_mode, S_IRUGO|S_IWUSR, + nirtfeatures_recovery_mode_get, nirtfeatures_recovery_mode_set); + +static ssize_t nirtfeatures_console_out_get(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct acpi_device *acpi_device = to_acpi_device(dev); + struct nirtfeatures *nirtfeatures = acpi_device->driver_data; + u8 data; + + data = inb(nirtfeatures->io_base + NIRTF_PROCESSOR_MODE); + + data &= NIRTF_PROCESSOR_MODE_CONSOLE_OUT; + + return sprintf(buf, "%u\n", !!data); +} + +static DEVICE_ATTR(console_out, S_IRUGO, nirtfeatures_console_out_get, NULL); + +static ssize_t nirtfeatures_ip_reset_get(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct acpi_device *acpi_device = to_acpi_device(dev); + struct nirtfeatures *nirtfeatures = acpi_device->driver_data; + u8 data; + + data = inb(nirtfeatures->io_base + NIRTF_PROCESSOR_MODE); + + data &= NIRTF_PROCESSOR_MODE_IP_RESET; + + return sprintf(buf, "%u\n", !!data); +} + +static DEVICE_ATTR(ip_reset, S_IRUGO, nirtfeatures_ip_reset_get, NULL); + +static ssize_t nirtfeatures_safe_mode_get(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct acpi_device *acpi_device = to_acpi_device(dev); + struct nirtfeatures *nirtfeatures = acpi_device->driver_data; + u8 data; + + data = inb(nirtfeatures->io_base + NIRTF_PROCESSOR_MODE); + + data &= NIRTF_PROCESSOR_MODE_SAFE; + + return sprintf(buf, "%u\n", !!data); +} + +static DEVICE_ATTR(safe_mode, S_IRUGO, nirtfeatures_safe_mode_get, NULL); + +static ssize_t nirtfeatures_register_dump_get(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct acpi_device *acpi_device = to_acpi_device(dev); + struct nirtfeatures *nirtfeatures = acpi_device->driver_data; + u8 signature, year, month, day, hour, minute, scratch, bpinfo; + u8 railstatus1, railstatus2, reset, reset_source, processor_mode; + u8 system_leds, status_led_shift1, status_led_shift0, rt_leds; + + signature = inb(nirtfeatures->io_base + NIRTF_SIGNATURE); + year = inb(nirtfeatures->io_base + NIRTF_YEAR); + month = inb(nirtfeatures->io_base + NIRTF_MONTH); + day = inb(nirtfeatures->io_base + NIRTF_DAY); + hour = inb(nirtfeatures->io_base + NIRTF_HOUR); + minute = inb(nirtfeatures->io_base + NIRTF_MINUTE); + scratch = inb(nirtfeatures->io_base + NIRTF_SCRATCH); + bpinfo = inb(nirtfeatures->io_base + NIRTF_BPINFO); + railstatus1 = inb(nirtfeatures->io_base + NIRTF_RAIL_STATUS1); + railstatus2 = inb(nirtfeatures->io_base + NIRTF_RAIL_STATUS2); + reset = inb(nirtfeatures->io_base + NIRTF_RESET); + reset_source = inb(nirtfeatures->io_base + NIRTF_RESET_SOURCE); + processor_mode = inb(nirtfeatures->io_base + NIRTF_PROCESSOR_MODE); + system_leds = inb(nirtfeatures->io_base + NIRTF_SYSTEM_LEDS); + status_led_shift1 = + inb(nirtfeatures->io_base + NIRTF_STATUS_LED_SHIFT1); + status_led_shift0 = + inb(nirtfeatures->io_base + NIRTF_STATUS_LED_SHIFT0); + rt_leds = inb(nirtfeatures->io_base + NIRTF_RT_LEDS); + + return sprintf(buf, + "Signature: 0x%02X\n" + "Year: 0x%02X\n" + "Month: 0x%02X\n" + "Day: 0x%02X\n" + "Hour: 0x%02X\n" + "Minute: 0x%02X\n" + "Scratch: 0x%02X\n" + "BPInfo: 0x%02X\n" + "Rail status 1: 0x%02X\n" + "Rail status 2: 0x%02X\n" + "Reset: 0x%02X\n" + "Reset source: 0x%02X\n" + "Processor mode: 0x%02X\n" + "System LEDs: 0x%02X\n" + "Status LED shift 1: 0x%02X\n" + "Status LED shift 0: 0x%02X\n" + "RT LEDs: 0x%02X\n", + signature, year, month, day, hour, minute, scratch, + bpinfo, railstatus1, railstatus2, reset, reset_source, + processor_mode, system_leds, status_led_shift1, + status_led_shift0, rt_leds); +} + +static DEVICE_ATTR(register_dump, S_IRUGO, nirtfeatures_register_dump_get, + NULL); + +static const struct attribute *nirtfeatures_attrs[] = { + &dev_attr_revision.attr, + &dev_attr_scratch.attr, + &dev_attr_backplane_id.attr, + &dev_attr_railstatus1.attr, + &dev_attr_railstatus2.attr, + &dev_attr_reset.attr, + &dev_attr_reset_source.attr, + &dev_attr_hard_boot.attr, + &dev_attr_no_fpga.attr, + &dev_attr_recovery_mode.attr, + &dev_attr_console_out.attr, + &dev_attr_ip_reset.attr, + &dev_attr_safe_mode.attr, + &dev_attr_register_dump.attr, + NULL +}; + +/* LEDs */ + +static void nirtfeatures_led_brightness_set(struct led_classdev *led_cdev, + enum led_brightness brightness) +{ + struct nirtfeatures_led *led = (struct nirtfeatures_led *)led_cdev; + u8 data; + bool on; + u16 pattern; + + on = !!brightness; + pattern = brightness; + + spin_lock(&led->nirtfeatures->lock); + + data = inb(led->nirtfeatures->io_base + led->address); + + data &= ~led->mask; + + if (on) + data |= led->mask; + + outb(data, led->nirtfeatures->io_base + led->address); + + if (led->pattern_hi_addr && led->pattern_lo_addr) { + /* Write the high byte first. */ + outb(pattern >> 8, + led->nirtfeatures->io_base + led->pattern_hi_addr); + outb(pattern & 0xFF, + led->nirtfeatures->io_base + led->pattern_lo_addr); + } + + spin_unlock(&led->nirtfeatures->lock); +} + +static enum led_brightness +nirtfeatures_led_brightness_get(struct led_classdev *led_cdev) +{ + struct nirtfeatures_led *led = (struct nirtfeatures_led *)led_cdev; + u8 data; + + data = inb(led->nirtfeatures->io_base + led->address); + + /* For the yellow status LED, the blink pattern used for brightness + on write is write-only, so we just return on/off for all LEDs. */ + return (data & led->mask) ? LED_FULL : LED_OFF; +} + +static struct nirtfeatures_led nirtfeatures_leds_common[] = { + { + { + .name = CONFIG_NI_LED_PREFIX ":user1:green", + }, + .address = NIRTF_RT_LEDS, + .mask = NIRTF_RT_LEDS_USER1_GREEN, + }, + { + { + .name = CONFIG_NI_LED_PREFIX ":user1:yellow", + }, + .address = NIRTF_RT_LEDS, + .mask = NIRTF_RT_LEDS_USER1_YELLOW, + }, + { + { + .name = CONFIG_NI_LED_PREFIX ":status:red", + }, + .address = NIRTF_SYSTEM_LEDS, + .mask = NIRTF_SYSTEM_LEDS_STATUS_RED, + }, + { + { + .name = CONFIG_NI_LED_PREFIX ":status:yellow", + .max_brightness = 0xFFFF, + }, + .address = NIRTF_SYSTEM_LEDS, + .mask = NIRTF_SYSTEM_LEDS_STATUS_YELLOW, + .pattern_hi_addr = NIRTF_STATUS_LED_SHIFT1, + .pattern_lo_addr = NIRTF_STATUS_LED_SHIFT0, + }, + { + { + .name = CONFIG_NI_LED_PREFIX ":power:green", + }, + .address = NIRTF_SYSTEM_LEDS, + .mask = NIRTF_SYSTEM_LEDS_POWER_GREEN, + }, + { + { + .name = CONFIG_NI_LED_PREFIX ":power:yellow", + }, + .address = NIRTF_SYSTEM_LEDS, + .mask = NIRTF_SYSTEM_LEDS_POWER_YELLOW, + }, +}; + +static struct nirtfeatures_led nirtfeatures_leds_cdaq[] = { + { + { + .name = CONFIG_NI_LED_PREFIX ":user2:green", + }, + .address = NIRTF_RT_LEDS, + .mask = NIRTF_RT_LEDS_USER2_GREEN, + }, + { + { + .name = CONFIG_NI_LED_PREFIX ":user2:yellow", + }, + .address = NIRTF_RT_LEDS, + .mask = NIRTF_RT_LEDS_USER2_YELLOW, + }, +}; + +static int nirtfeatures_create_leds(struct nirtfeatures *nirtfeatures) +{ + int i; + int err; + + for (i = 0; i < ARRAY_SIZE(nirtfeatures_leds_common); ++i) { + + nirtfeatures_leds_common[i].nirtfeatures = nirtfeatures; + + if (0 == nirtfeatures_leds_common[i].cdev.max_brightness) + nirtfeatures_leds_common[i].cdev.max_brightness = 1; + + nirtfeatures_leds_common[i].cdev.brightness_set = + nirtfeatures_led_brightness_set; + + nirtfeatures_leds_common[i].cdev.brightness_get = + nirtfeatures_led_brightness_get; + + err = led_classdev_register(&nirtfeatures->acpi_device->dev, + &nirtfeatures_leds_common[i].cdev); + if (err) + return err; + } + + for (i = 0; i < nirtfeatures->num_extra_leds; ++i) { + + nirtfeatures->extra_leds[i].nirtfeatures = nirtfeatures; + + if (0 == nirtfeatures->extra_leds[i].cdev.max_brightness) + nirtfeatures->extra_leds[i].cdev.max_brightness = 1; + + nirtfeatures->extra_leds[i].cdev.brightness_set = + nirtfeatures_led_brightness_set; + + nirtfeatures->extra_leds[i].cdev.brightness_get = + nirtfeatures_led_brightness_get; + + err = led_classdev_register(&nirtfeatures->acpi_device->dev, + &nirtfeatures->extra_leds[i].cdev); + if (err) + return err; + } + + return 0; +} + +static void nirtfeatures_remove_leds(struct nirtfeatures *nirtfeatures) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(nirtfeatures_leds_common); ++i) + led_classdev_unregister(&nirtfeatures_leds_common[i].cdev); + + for (i = 0; i < nirtfeatures->num_extra_leds; ++i) + led_classdev_unregister(&nirtfeatures->extra_leds[i].cdev); +} + +/* Board specific reboot fixup */ + +#ifdef CONFIG_NI_HW_REBOOT + +static u16 mach_reboot_fixup_io_base; + +void mach_reboot_fixups(void) +{ + int i; + + if (mach_reboot_fixup_io_base) + for (i = 0; i < 10; ++i) { + outb(NIRTF_RESET_RESET_PROCESSOR, + mach_reboot_fixup_io_base + NIRTF_RESET); + udelay(100); + } +} + +#endif + +/* ACPI driver */ + +static acpi_status nirtfeatures_resources(struct acpi_resource *res, void *data) +{ + struct nirtfeatures *nirtfeatures = data; + + switch (res->type) { + case ACPI_RESOURCE_TYPE_IO: + if ((nirtfeatures->io_base != 0) || + (nirtfeatures->io_size != 0)) { + dev_err(&nirtfeatures->acpi_device->dev, + "too many IO resources\n"); + return AE_ERROR; + } + + nirtfeatures->io_base = res->data.io.minimum; + nirtfeatures->io_size = res->data.io.address_length; + + return AE_OK; + + case ACPI_RESOURCE_TYPE_END_TAG: + return AE_OK; + + default: + dev_err(&nirtfeatures->acpi_device->dev, + "unsupported resource type %u\n", + res->type); + return AE_ERROR; + } + + return AE_OK; +} + +static int nirtfeatures_acpi_remove(struct acpi_device *device) +{ + struct nirtfeatures *nirtfeatures = device->driver_data; + + nirtfeatures_remove_leds(nirtfeatures); + + sysfs_remove_files(&nirtfeatures->acpi_device->dev.kobj, + nirtfeatures_attrs); + + if ((nirtfeatures->io_base != 0) && + (nirtfeatures->io_size == NIRTF_IO_SIZE)) + release_region(nirtfeatures->io_base, nirtfeatures->io_size); + + device->driver_data = NULL; + + kfree(nirtfeatures); + + return 0; +} + +static int nirtfeatures_acpi_add(struct acpi_device *device) +{ + struct nirtfeatures *nirtfeatures; + acpi_status acpi_ret; + u8 bpinfo; + int err; + + nirtfeatures = kzalloc(sizeof(*nirtfeatures), GFP_KERNEL); + + if (!nirtfeatures) + return -ENOMEM; + + device->driver_data = nirtfeatures; + + nirtfeatures->acpi_device = device; + + acpi_ret = acpi_walk_resources(device->handle, METHOD_NAME__CRS, + nirtfeatures_resources, nirtfeatures); + + if (ACPI_FAILURE(acpi_ret) || + (nirtfeatures->io_base == 0) || + (nirtfeatures->io_size != NIRTF_IO_SIZE)) { + nirtfeatures_acpi_remove(device); + return -ENODEV; + } + + if (!request_region(nirtfeatures->io_base, nirtfeatures->io_size, + MODULE_NAME)) { + nirtfeatures_acpi_remove(device); + return -EBUSY; + } + +#ifdef CONFIG_NI_HW_REBOOT + mach_reboot_fixup_io_base = nirtfeatures->io_base; + reboot_type = BOOT_KBD; +#endif + + bpinfo = inb(nirtfeatures->io_base + NIRTF_BPINFO); + + bpinfo &= NIRTF_BPINFO_ID_MASK; + + switch (bpinfo) { + case NIRTF_BPINFO_ID_MANHATTAN: + nirtfeatures->bpstring = "Manhattan"; + break; + case NIRTF_BPINFO_ID_HAMMERHEAD: + nirtfeatures->bpstring = "Hammerhead"; + nirtfeatures->extra_leds = nirtfeatures_leds_cdaq; + nirtfeatures->num_extra_leds = + ARRAY_SIZE(nirtfeatures_leds_cdaq); + break; + default: + dev_err(&nirtfeatures->acpi_device->dev, + "Unrecognized backplane type %u\n", + bpinfo); + nirtfeatures_acpi_remove(device); + return -ENODEV; + } + + err = sysfs_create_files(&nirtfeatures->acpi_device->dev.kobj, + nirtfeatures_attrs); + if (0 != err) { + nirtfeatures_acpi_remove(device); + return err; + } + + err = nirtfeatures_create_leds(nirtfeatures); + if (0 != err) { + nirtfeatures_acpi_remove(device); + return err; + } + + spin_lock_init(&nirtfeatures->lock); + + nirtfeatures->revision[0] = inb(nirtfeatures->io_base + NIRTF_YEAR); + nirtfeatures->revision[1] = inb(nirtfeatures->io_base + NIRTF_MONTH); + nirtfeatures->revision[2] = inb(nirtfeatures->io_base + NIRTF_DAY); + nirtfeatures->revision[3] = inb(nirtfeatures->io_base + NIRTF_HOUR); + nirtfeatures->revision[4] = inb(nirtfeatures->io_base + NIRTF_MINUTE); + + dev_info(&nirtfeatures->acpi_device->dev, + "IO range 0x%04X-0x%04X\n", + nirtfeatures->io_base, + nirtfeatures->io_base + nirtfeatures->io_size - 1); + + return 0; +} + +static const struct acpi_device_id nirtfeatures_device_ids[] = { + {"NIC775D", 0}, + {"", 0}, +}; + +static struct acpi_driver nirtfeatures_acpi_driver = { + .name = MODULE_NAME, + .ids = nirtfeatures_device_ids, + .ops = { + .add = nirtfeatures_acpi_add, + .remove = nirtfeatures_acpi_remove, + }, +}; + +static int __init nirtfeatures_init(void) +{ + return acpi_bus_register_driver(&nirtfeatures_acpi_driver); +} + +static void __exit nirtfeatures_exit(void) +{ + acpi_bus_unregister_driver(&nirtfeatures_acpi_driver); +} + +module_init(nirtfeatures_init); +module_exit(nirtfeatures_exit); + +MODULE_DEVICE_TABLE(acpi, nirtfeatures_device_ids); +MODULE_DESCRIPTION("NI RT Features"); +MODULE_AUTHOR("Jeff Westfahl "); +MODULE_LICENSE("GPL"); From 4c8721d136baa88719b6a466b8bad566d07ce1ed Mon Sep 17 00:00:00 2001 From: Jeff Westfahl Date: Fri, 14 Mar 2014 17:24:18 -0500 Subject: [PATCH 007/110] nirtfeatures: change hard_boot to soft_reset to match our Zynq targets On our Zynq targets, we expose the power-on reset status of the controller via a soft_reset sysfs file. The same underlying bit in the CPLD is exposed as hard_boot on our Smasher targets. In this commit we change the Smasher implementation to match Zynq. Signed-off-by: Jeff Westfahl --- drivers/misc/nirtfeatures.c | 37 ++++++------------------------------- 1 file changed, 6 insertions(+), 31 deletions(-) diff --git a/drivers/misc/nirtfeatures.c b/drivers/misc/nirtfeatures.c index 11f6d1f0679e9..0d94e62a5ec92 100644 --- a/drivers/misc/nirtfeatures.c +++ b/drivers/misc/nirtfeatures.c @@ -264,9 +264,9 @@ static ssize_t nirtfeatures_reset_source_get(struct device *dev, static DEVICE_ATTR(reset_source, S_IRUGO, nirtfeatures_reset_source_get, NULL); -static ssize_t nirtfeatures_hard_boot_get(struct device *dev, - struct device_attribute *attr, - char *buf) +static ssize_t nirtfeatures_soft_reset_get(struct device *dev, + struct device_attribute *attr, + char *buf) { struct acpi_device *acpi_device = to_acpi_device(dev); struct nirtfeatures *nirtfeatures = acpi_device->driver_data; @@ -276,35 +276,10 @@ static ssize_t nirtfeatures_hard_boot_get(struct device *dev, data &= NIRTF_PROCESSOR_MODE_HARD_BOOT_N; - return sprintf(buf, "%s\n", data ? "soft reset" : "power-on reset"); -} - -static ssize_t nirtfeatures_hard_boot_set(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) -{ - struct acpi_device *acpi_device = to_acpi_device(dev); - struct nirtfeatures *nirtfeatures = acpi_device->driver_data; - u8 data; - - if (strcmp(buf, "1")) - return -EINVAL; - - spin_lock(&nirtfeatures->lock); - - data = inb(nirtfeatures->io_base + NIRTF_PROCESSOR_MODE); - - data |= NIRTF_PROCESSOR_MODE_HARD_BOOT_N; - - outb(data, nirtfeatures->io_base + NIRTF_PROCESSOR_MODE); - - spin_unlock(&nirtfeatures->lock); - - return count; + return sprintf(buf, "%u\n", !!data); } -static DEVICE_ATTR(hard_boot, S_IRUGO|S_IWUSR, nirtfeatures_hard_boot_get, - nirtfeatures_hard_boot_set); +static DEVICE_ATTR(soft_reset, S_IRUGO, nirtfeatures_soft_reset_get, NULL); static ssize_t nirtfeatures_no_fpga_get(struct device *dev, struct device_attribute *attr, @@ -514,7 +489,7 @@ static const struct attribute *nirtfeatures_attrs[] = { &dev_attr_railstatus2.attr, &dev_attr_reset.attr, &dev_attr_reset_source.attr, - &dev_attr_hard_boot.attr, + &dev_attr_soft_reset.attr, &dev_attr_no_fpga.attr, &dev_attr_recovery_mode.attr, &dev_attr_console_out.attr, From c04ac1cf5fab6b4d66e9fed8f0b6f637b22dd70d Mon Sep 17 00:00:00 2001 From: Jeff Westfahl Date: Fri, 14 Mar 2014 16:52:23 -0500 Subject: [PATCH 008/110] nirtfeatures: set HARD_BOOT_N if necessary when the driver loads On systems where FPGA autoload is controlled by software, we need a way to determine if a system has just had power applied. This is necessary to implement the autoload on every power-on feature. Once the FPGA has been autloaded after power-on, software sets a bit in the CPLD so that subsequent (non power-on) resets don't cause the FPGA to be autoloaded again. The CPLD provides the HARD_BOOT_N bit for this purpose. On systems where FPGA autoload is controlled by hardware, such as Smasher, we need to set this bit at some point after power-on so that software can correctly determine the reset state of the controller. Since software has no insight into the status of FPGA autoload on these systems, we can just set this bit if necessary when the driver loads. Signed-off-by: Jeff Westfahl --- drivers/misc/nirtfeatures.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/misc/nirtfeatures.c b/drivers/misc/nirtfeatures.c index 0d94e62a5ec92..59456011d5d73 100644 --- a/drivers/misc/nirtfeatures.c +++ b/drivers/misc/nirtfeatures.c @@ -747,6 +747,7 @@ static int nirtfeatures_acpi_add(struct acpi_device *device) struct nirtfeatures *nirtfeatures; acpi_status acpi_ret; u8 bpinfo; + u8 procmode; int err; nirtfeatures = kzalloc(sizeof(*nirtfeatures), GFP_KERNEL); @@ -822,6 +823,13 @@ static int nirtfeatures_acpi_add(struct acpi_device *device) nirtfeatures->revision[3] = inb(nirtfeatures->io_base + NIRTF_HOUR); nirtfeatures->revision[4] = inb(nirtfeatures->io_base + NIRTF_MINUTE); + procmode = inb(nirtfeatures->io_base + NIRTF_PROCESSOR_MODE); + + if (!(procmode & NIRTF_PROCESSOR_MODE_HARD_BOOT_N)) { + procmode |= NIRTF_PROCESSOR_MODE_HARD_BOOT_N; + outb(procmode, nirtfeatures->io_base + NIRTF_PROCESSOR_MODE); + } + dev_info(&nirtfeatures->acpi_device->dev, "IO range 0x%04X-0x%04X\n", nirtfeatures->io_base, From 9fe1a5420a085483068320e59d3ce6ddd0a9a98a Mon Sep 17 00:00:00 2001 From: Jeff Westfahl Date: Fri, 14 Mar 2014 17:00:58 -0500 Subject: [PATCH 009/110] nirtfeatures: modify reset_source to match Zynq Changed the strings returned by the reset_source sysfs file to match those returned on Zynq. Changed the algorithm used to determine the reset source to match Zynq. Signed-off-by: Jeff Westfahl (Note that the Smasher CPLD currently returns incorrect values for the reset source in some cases. See CARs 458093 and 458094.) --- drivers/misc/nirtfeatures.c | 50 ++++++++----------------------------- 1 file changed, 11 insertions(+), 39 deletions(-) diff --git a/drivers/misc/nirtfeatures.c b/drivers/misc/nirtfeatures.c index 59456011d5d73..fe0d1ba868ddb 100644 --- a/drivers/misc/nirtfeatures.c +++ b/drivers/misc/nirtfeatures.c @@ -211,6 +211,10 @@ static ssize_t nirtfeatures_reset_set(struct device *dev, static DEVICE_ATTR(reset, S_IWUSR, NULL, nirtfeatures_reset_set); +static const char * const nirtfeatures_reset_source_strings[] = { + "button", "processor", "fpga", "watchdog", "software", "softoff", +}; + static ssize_t nirtfeatures_reset_source_get(struct device *dev, struct device_attribute *attr, char *buf) @@ -218,48 +222,16 @@ static ssize_t nirtfeatures_reset_source_get(struct device *dev, struct acpi_device *acpi_device = to_acpi_device(dev); struct nirtfeatures *nirtfeatures = acpi_device->driver_data; u8 data; - const char *reset_source; + int i; - data = inb(nirtfeatures->io_base + NIRTF_PROCESSOR_MODE); + data = inb(nirtfeatures->io_base + NIRTF_RESET_SOURCE); - data &= NIRTF_PROCESSOR_MODE_HARD_BOOT_N; - - /* Power-on reset status is in a different register from the other reset - sources, we must check it first. */ - if (!data) { - reset_source = "power-on reset"; - } else { - data = inb(nirtfeatures->io_base + NIRTF_RESET_SOURCE); - - switch (data) { - case NIRTF_RESET_SOURCE_SOFT_OFF: - reset_source = "soft off button"; - break; - case NIRTF_RESET_SOURCE_SOFTWARE: - reset_source = "software"; - break; - case NIRTF_RESET_SOURCE_WATCHDOG: - reset_source = "watchdog"; - break; - case NIRTF_RESET_SOURCE_FPGA: - reset_source = "FPGA"; - break; - case NIRTF_RESET_SOURCE_PROCESSOR: - reset_source = "processor"; - break; - case NIRTF_RESET_SOURCE_BUTTON: - reset_source = "reset button"; - break; - default: - dev_err(&nirtfeatures->acpi_device->dev, - "Unrecognized reset source 0x%02X\n", - data); - reset_source = "unknown"; - break; - } - } + for (i = 0; i < ARRAY_SIZE(nirtfeatures_reset_source_strings); i++) + if ((1 << i) & data) + return sprintf(buf, "%s\n", + nirtfeatures_reset_source_strings[i]); - return sprintf(buf, "%s\n", reset_source); + return sprintf(buf, "poweron\n"); } static DEVICE_ATTR(reset_source, S_IRUGO, nirtfeatures_reset_source_get, NULL); From 9c98bf3e7c18f79e5bd0bf1a202bddc7691d259e Mon Sep 17 00:00:00 2001 From: Jeff Westfahl Date: Fri, 14 Mar 2014 17:12:01 -0500 Subject: [PATCH 010/110] nirtfeatures: restructure init function to close holes In nirtfeatures_acpi_add, we create several sysfs files. As currently implemented, there is a window where access to a sysfs file may cause our spinlock to be used before it's been initialized, or may cause us to write an incorrect value to an I/O port. We can close this window by moving the creation of the sysfs files closer to the end of the function. Signed-off-by: Jeff Westfahl --- drivers/misc/nirtfeatures.c | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/drivers/misc/nirtfeatures.c b/drivers/misc/nirtfeatures.c index fe0d1ba868ddb..860aca2feca17 100644 --- a/drivers/misc/nirtfeatures.c +++ b/drivers/misc/nirtfeatures.c @@ -774,19 +774,6 @@ static int nirtfeatures_acpi_add(struct acpi_device *device) return -ENODEV; } - err = sysfs_create_files(&nirtfeatures->acpi_device->dev.kobj, - nirtfeatures_attrs); - if (0 != err) { - nirtfeatures_acpi_remove(device); - return err; - } - - err = nirtfeatures_create_leds(nirtfeatures); - if (0 != err) { - nirtfeatures_acpi_remove(device); - return err; - } - spin_lock_init(&nirtfeatures->lock); nirtfeatures->revision[0] = inb(nirtfeatures->io_base + NIRTF_YEAR); @@ -802,6 +789,19 @@ static int nirtfeatures_acpi_add(struct acpi_device *device) outb(procmode, nirtfeatures->io_base + NIRTF_PROCESSOR_MODE); } + err = sysfs_create_files(&nirtfeatures->acpi_device->dev.kobj, + nirtfeatures_attrs); + if (0 != err) { + nirtfeatures_acpi_remove(device); + return err; + } + + err = nirtfeatures_create_leds(nirtfeatures); + if (0 != err) { + nirtfeatures_acpi_remove(device); + return err; + } + dev_info(&nirtfeatures->acpi_device->dev, "IO range 0x%04X-0x%04X\n", nirtfeatures->io_base, From 6961636eea7c36bafc351452961575f222ea347b Mon Sep 17 00:00:00 2001 From: Jeff Westfahl Date: Fri, 14 Mar 2014 17:14:42 -0500 Subject: [PATCH 011/110] nirtfeatures: add LOCK, DEBUG_SWITCH, and GP_BUTTON registers The Smasher CPLD has recently exposed some new registers. In this commit we display the values of these registers in the output of the register_dump sysfs file. Signed-off-by: Jeff Westfahl --- drivers/misc/nirtfeatures.c | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/drivers/misc/nirtfeatures.c b/drivers/misc/nirtfeatures.c index 860aca2feca17..bac07b2015ce1 100644 --- a/drivers/misc/nirtfeatures.c +++ b/drivers/misc/nirtfeatures.c @@ -35,6 +35,7 @@ #define NIRTF_BPINFO 0x07 #define NIRTF_RAIL_STATUS1 0x08 #define NIRTF_RAIL_STATUS2 0x09 +#define NIRTF_LOCK 0x0F #define NIRTF_RESET 0x10 #define NIRTF_RESET_SOURCE 0x11 #define NIRTF_PROCESSOR_MODE 0x12 @@ -42,6 +43,8 @@ #define NIRTF_STATUS_LED_SHIFT1 0x21 #define NIRTF_STATUS_LED_SHIFT0 0x22 #define NIRTF_RT_LEDS 0x23 +#define NIRTF_DEBUG_SWITCH 0x30 +#define NIRTF_GP_BUTTON 0x31 #define NIRTF_IO_SIZE 0x40 @@ -403,8 +406,9 @@ static ssize_t nirtfeatures_register_dump_get(struct device *dev, struct acpi_device *acpi_device = to_acpi_device(dev); struct nirtfeatures *nirtfeatures = acpi_device->driver_data; u8 signature, year, month, day, hour, minute, scratch, bpinfo; - u8 railstatus1, railstatus2, reset, reset_source, processor_mode; + u8 railstatus1, railstatus2, lock, reset, reset_source, processor_mode; u8 system_leds, status_led_shift1, status_led_shift0, rt_leds; + u8 debug_switch, gp_button; signature = inb(nirtfeatures->io_base + NIRTF_SIGNATURE); year = inb(nirtfeatures->io_base + NIRTF_YEAR); @@ -416,6 +420,7 @@ static ssize_t nirtfeatures_register_dump_get(struct device *dev, bpinfo = inb(nirtfeatures->io_base + NIRTF_BPINFO); railstatus1 = inb(nirtfeatures->io_base + NIRTF_RAIL_STATUS1); railstatus2 = inb(nirtfeatures->io_base + NIRTF_RAIL_STATUS2); + lock = inb(nirtfeatures->io_base + NIRTF_LOCK); reset = inb(nirtfeatures->io_base + NIRTF_RESET); reset_source = inb(nirtfeatures->io_base + NIRTF_RESET_SOURCE); processor_mode = inb(nirtfeatures->io_base + NIRTF_PROCESSOR_MODE); @@ -425,6 +430,8 @@ static ssize_t nirtfeatures_register_dump_get(struct device *dev, status_led_shift0 = inb(nirtfeatures->io_base + NIRTF_STATUS_LED_SHIFT0); rt_leds = inb(nirtfeatures->io_base + NIRTF_RT_LEDS); + debug_switch = inb(nirtfeatures->io_base + NIRTF_DEBUG_SWITCH); + gp_button = inb(nirtfeatures->io_base + NIRTF_GP_BUTTON); return sprintf(buf, "Signature: 0x%02X\n" @@ -437,17 +444,21 @@ static ssize_t nirtfeatures_register_dump_get(struct device *dev, "BPInfo: 0x%02X\n" "Rail status 1: 0x%02X\n" "Rail status 2: 0x%02X\n" + "Lock: 0x%02X\n" "Reset: 0x%02X\n" "Reset source: 0x%02X\n" "Processor mode: 0x%02X\n" "System LEDs: 0x%02X\n" "Status LED shift 1: 0x%02X\n" "Status LED shift 0: 0x%02X\n" - "RT LEDs: 0x%02X\n", + "RT LEDs: 0x%02X\n" + "Debug switch: 0x%02X\n" + "GP button: 0x%02X\n", signature, year, month, day, hour, minute, scratch, - bpinfo, railstatus1, railstatus2, reset, reset_source, - processor_mode, system_leds, status_led_shift1, - status_led_shift0, rt_leds); + bpinfo, railstatus1, railstatus2, lock, reset, + reset_source, processor_mode, system_leds, + status_led_shift1, status_led_shift0, rt_leds, + debug_switch, gp_button); } static DEVICE_ATTR(register_dump, S_IRUGO, nirtfeatures_register_dump_get, From 71242819e14c0244ddda7b89f10f5d645bffaa78 Mon Sep 17 00:00:00 2001 From: Jeff Westfahl Date: Fri, 21 Mar 2014 15:42:17 -0500 Subject: [PATCH 012/110] nirtfeatures: Change Hammerhead ID to match hardware When we built Hammerhead, we used ID 4 instead of 1. We don't want to rework all of the boards to match the documentation, so we're just changing the documentation and driver to match what we built. Signed-off-by: Jeff Westfahl --- drivers/misc/nirtfeatures.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/misc/nirtfeatures.c b/drivers/misc/nirtfeatures.c index bac07b2015ce1..9dcfbe2973ad7 100644 --- a/drivers/misc/nirtfeatures.c +++ b/drivers/misc/nirtfeatures.c @@ -53,7 +53,7 @@ #define NIRTF_BPINFO_ID_MASK 0x07 #define NIRTF_BPINFO_ID_MANHATTAN 0 -#define NIRTF_BPINFO_ID_HAMMERHEAD 1 +#define NIRTF_BPINFO_ID_HAMMERHEAD 4 #define NIRTF_RESET_RESET_PROCESSOR 0x80 From 254f87c72b16b29d504e5e68d9caaef2dfa695d7 Mon Sep 17 00:00:00 2001 From: Jeff Westfahl Date: Tue, 1 Apr 2014 13:37:37 -0500 Subject: [PATCH 013/110] nirtfeatures: support for Winghead variant Signed-off-by: Jeff Westfahl --- drivers/misc/nirtfeatures.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/misc/nirtfeatures.c b/drivers/misc/nirtfeatures.c index 9dcfbe2973ad7..33004479fc5a5 100644 --- a/drivers/misc/nirtfeatures.c +++ b/drivers/misc/nirtfeatures.c @@ -54,6 +54,7 @@ #define NIRTF_BPINFO_ID_MANHATTAN 0 #define NIRTF_BPINFO_ID_HAMMERHEAD 4 +#define NIRTF_BPINFO_ID_WINGHEAD 5 #define NIRTF_RESET_RESET_PROCESSOR 0x80 @@ -777,6 +778,12 @@ static int nirtfeatures_acpi_add(struct acpi_device *device) nirtfeatures->num_extra_leds = ARRAY_SIZE(nirtfeatures_leds_cdaq); break; + case NIRTF_BPINFO_ID_WINGHEAD: + nirtfeatures->bpstring = "Winghead"; + nirtfeatures->extra_leds = nirtfeatures_leds_cdaq; + nirtfeatures->num_extra_leds = + ARRAY_SIZE(nirtfeatures_leds_cdaq); + break; default: dev_err(&nirtfeatures->acpi_device->dev, "Unrecognized backplane type %u\n", From fcb5f761e4d4cddb30d4642f79c1b427670c9fda Mon Sep 17 00:00:00 2001 From: Jeff Westfahl Date: Tue, 1 Apr 2014 13:58:01 -0500 Subject: [PATCH 014/110] nirtfeatures: support latest CPLD The existing recovery_mode and no_fpga bits are now read only. A new bit, no_fpga_sw, exists for software to tell the CPLD to assert NO_FPGA at the next reset. Signed-off-by: Jeff Westfahl --- drivers/misc/nirtfeatures.c | 85 +++++++++++++++++-------------------- 1 file changed, 38 insertions(+), 47 deletions(-) diff --git a/drivers/misc/nirtfeatures.c b/drivers/misc/nirtfeatures.c index 33004479fc5a5..3c494a1954cb5 100644 --- a/drivers/misc/nirtfeatures.c +++ b/drivers/misc/nirtfeatures.c @@ -65,6 +65,7 @@ #define NIRTF_RESET_SOURCE_PROCESSOR 0x02 #define NIRTF_RESET_SOURCE_BUTTON 0x01 +#define NIRTF_PROCESSOR_MODE_NO_FPGA_SW 0x40 #define NIRTF_PROCESSOR_MODE_HARD_BOOT_N 0x20 #define NIRTF_PROCESSOR_MODE_NO_FPGA 0x10 #define NIRTF_PROCESSOR_MODE_RECOVERY 0x08 @@ -240,7 +241,7 @@ static ssize_t nirtfeatures_reset_source_get(struct device *dev, static DEVICE_ATTR(reset_source, S_IRUGO, nirtfeatures_reset_source_get, NULL); -static ssize_t nirtfeatures_soft_reset_get(struct device *dev, +static ssize_t nirtfeatures_no_fpga_sw_get(struct device *dev, struct device_attribute *attr, char *buf) { @@ -250,31 +251,14 @@ static ssize_t nirtfeatures_soft_reset_get(struct device *dev, data = inb(nirtfeatures->io_base + NIRTF_PROCESSOR_MODE); - data &= NIRTF_PROCESSOR_MODE_HARD_BOOT_N; + data &= NIRTF_PROCESSOR_MODE_NO_FPGA_SW; return sprintf(buf, "%u\n", !!data); } -static DEVICE_ATTR(soft_reset, S_IRUGO, nirtfeatures_soft_reset_get, NULL); - -static ssize_t nirtfeatures_no_fpga_get(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct acpi_device *acpi_device = to_acpi_device(dev); - struct nirtfeatures *nirtfeatures = acpi_device->driver_data; - u8 data; - - data = inb(nirtfeatures->io_base + NIRTF_PROCESSOR_MODE); - - data &= NIRTF_PROCESSOR_MODE_NO_FPGA; - - return sprintf(buf, "%u\n", !!data); -} - -static ssize_t nirtfeatures_no_fpga_set(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) +static ssize_t nirtfeatures_no_fpga_sw_set(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) { struct acpi_device *acpi_device = to_acpi_device(dev); struct nirtfeatures *nirtfeatures = acpi_device->driver_data; @@ -289,9 +273,9 @@ static ssize_t nirtfeatures_no_fpga_set(struct device *dev, data = inb(nirtfeatures->io_base + NIRTF_PROCESSOR_MODE); if (tmp) - data |= NIRTF_PROCESSOR_MODE_NO_FPGA; + data |= NIRTF_PROCESSOR_MODE_NO_FPGA_SW; else - data &= ~NIRTF_PROCESSOR_MODE_NO_FPGA; + data &= ~NIRTF_PROCESSOR_MODE_NO_FPGA_SW; outb(data, nirtfeatures->io_base + NIRTF_PROCESSOR_MODE); @@ -300,12 +284,12 @@ static ssize_t nirtfeatures_no_fpga_set(struct device *dev, return count; } -static DEVICE_ATTR(no_fpga, S_IRUGO|S_IWUSR, nirtfeatures_no_fpga_get, - nirtfeatures_no_fpga_set); +static DEVICE_ATTR(no_fpga_sw, S_IRUGO|S_IWUSR, nirtfeatures_no_fpga_sw_get, + nirtfeatures_no_fpga_sw_set); -static ssize_t nirtfeatures_recovery_mode_get(struct device *dev, - struct device_attribute *attr, - char *buf) +static ssize_t nirtfeatures_soft_reset_get(struct device *dev, + struct device_attribute *attr, + char *buf) { struct acpi_device *acpi_device = to_acpi_device(dev); struct nirtfeatures *nirtfeatures = acpi_device->driver_data; @@ -313,41 +297,47 @@ static ssize_t nirtfeatures_recovery_mode_get(struct device *dev, data = inb(nirtfeatures->io_base + NIRTF_PROCESSOR_MODE); - data &= NIRTF_PROCESSOR_MODE_RECOVERY; + data &= NIRTF_PROCESSOR_MODE_HARD_BOOT_N; return sprintf(buf, "%u\n", !!data); } -static ssize_t nirtfeatures_recovery_mode_set(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) +static DEVICE_ATTR(soft_reset, S_IRUGO, nirtfeatures_soft_reset_get, NULL); + +static ssize_t nirtfeatures_no_fpga_get(struct device *dev, + struct device_attribute *attr, + char *buf) { struct acpi_device *acpi_device = to_acpi_device(dev); struct nirtfeatures *nirtfeatures = acpi_device->driver_data; - unsigned long tmp; u8 data; - if (kstrtoul(buf, 0, &tmp) || (tmp > 1)) - return -EINVAL; + data = inb(nirtfeatures->io_base + NIRTF_PROCESSOR_MODE); - spin_lock(&nirtfeatures->lock); + data &= NIRTF_PROCESSOR_MODE_NO_FPGA; - data = inb(nirtfeatures->io_base + NIRTF_PROCESSOR_MODE); + return sprintf(buf, "%u\n", !!data); +} - if (tmp) - data |= NIRTF_PROCESSOR_MODE_RECOVERY; - else - data &= ~NIRTF_PROCESSOR_MODE_RECOVERY; +static DEVICE_ATTR(no_fpga, S_IRUGO, nirtfeatures_no_fpga_get, NULL); - outb(data, nirtfeatures->io_base + NIRTF_PROCESSOR_MODE); +static ssize_t nirtfeatures_recovery_mode_get(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct acpi_device *acpi_device = to_acpi_device(dev); + struct nirtfeatures *nirtfeatures = acpi_device->driver_data; + u8 data; - spin_unlock(&nirtfeatures->lock); + data = inb(nirtfeatures->io_base + NIRTF_PROCESSOR_MODE); - return count; + data &= NIRTF_PROCESSOR_MODE_RECOVERY; + + return sprintf(buf, "%u\n", !!data); } -static DEVICE_ATTR(recovery_mode, S_IRUGO|S_IWUSR, - nirtfeatures_recovery_mode_get, nirtfeatures_recovery_mode_set); +static DEVICE_ATTR(recovery_mode, S_IRUGO, + nirtfeatures_recovery_mode_get, NULL); static ssize_t nirtfeatures_console_out_get(struct device *dev, struct device_attribute *attr, @@ -473,6 +463,7 @@ static const struct attribute *nirtfeatures_attrs[] = { &dev_attr_railstatus2.attr, &dev_attr_reset.attr, &dev_attr_reset_source.attr, + &dev_attr_no_fpga_sw.attr, &dev_attr_soft_reset.attr, &dev_attr_no_fpga.attr, &dev_attr_recovery_mode.attr, From b978cf5b235896cb90b2feadaa83613f409adecf Mon Sep 17 00:00:00 2001 From: Jeff Westfahl Date: Thu, 10 Apr 2014 16:56:04 -0500 Subject: [PATCH 015/110] nirtfeatures: don't bail out on unrecognized ID The driver currently returns an error from init if it doesn't recognize the backplane ID. This causes the kernel to hang on boot. Although this is probably a bug somewhere else in the kernel, there's no real benefit to returning an error in this case. It's sufficient to print an error message to the console and return "Unknown" as the backplane ID. Signed-off-by: Jeff Westfahl --- drivers/misc/nirtfeatures.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/misc/nirtfeatures.c b/drivers/misc/nirtfeatures.c index 3c494a1954cb5..e5d3fbb3c5aec 100644 --- a/drivers/misc/nirtfeatures.c +++ b/drivers/misc/nirtfeatures.c @@ -779,8 +779,8 @@ static int nirtfeatures_acpi_add(struct acpi_device *device) dev_err(&nirtfeatures->acpi_device->dev, "Unrecognized backplane type %u\n", bpinfo); - nirtfeatures_acpi_remove(device); - return -ENODEV; + nirtfeatures->bpstring = "Unknown"; + break; } spin_lock_init(&nirtfeatures->lock); From ec4bf5d1c9f610c125bfe5df0486421fdaed49e6 Mon Sep 17 00:00:00 2001 From: Jeff Westfahl Date: Thu, 10 Apr 2014 16:59:41 -0500 Subject: [PATCH 016/110] nirtfeatures: BIOS writes HARD_BOOT_N, so driver doesn't need to The BIOS will set the HARD_BOOT_N bit at post, so the driver no longer needs to do this. Signed-off-by: Jeff Westfahl --- drivers/misc/nirtfeatures.c | 8 -------- 1 file changed, 8 deletions(-) diff --git a/drivers/misc/nirtfeatures.c b/drivers/misc/nirtfeatures.c index e5d3fbb3c5aec..439d72a1f3beb 100644 --- a/drivers/misc/nirtfeatures.c +++ b/drivers/misc/nirtfeatures.c @@ -722,7 +722,6 @@ static int nirtfeatures_acpi_add(struct acpi_device *device) struct nirtfeatures *nirtfeatures; acpi_status acpi_ret; u8 bpinfo; - u8 procmode; int err; nirtfeatures = kzalloc(sizeof(*nirtfeatures), GFP_KERNEL); @@ -791,13 +790,6 @@ static int nirtfeatures_acpi_add(struct acpi_device *device) nirtfeatures->revision[3] = inb(nirtfeatures->io_base + NIRTF_HOUR); nirtfeatures->revision[4] = inb(nirtfeatures->io_base + NIRTF_MINUTE); - procmode = inb(nirtfeatures->io_base + NIRTF_PROCESSOR_MODE); - - if (!(procmode & NIRTF_PROCESSOR_MODE_HARD_BOOT_N)) { - procmode |= NIRTF_PROCESSOR_MODE_HARD_BOOT_N; - outb(procmode, nirtfeatures->io_base + NIRTF_PROCESSOR_MODE); - } - err = sysfs_create_files(&nirtfeatures->acpi_device->dev.kobj, nirtfeatures_attrs); if (0 != err) { From 2449a6c33441e2a001f8b3eee47e39f306eb1290 Mon Sep 17 00:00:00 2001 From: Jeff Westfahl Date: Fri, 11 Apr 2014 09:01:06 -0500 Subject: [PATCH 017/110] nirtfeatures: remove unused NI_HW_REBOOT config option Remove the unused NI_HW_REBOOT config option. We're not going to use this. Signed-off-by: Jeff Westfahl --- drivers/misc/Kconfig | 11 ----------- drivers/misc/nirtfeatures.c | 29 ----------------------------- 2 files changed, 40 deletions(-) diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig index ce0d7c4ed2be8..c18e8bc0f7450 100644 --- a/drivers/misc/Kconfig +++ b/drivers/misc/Kconfig @@ -486,17 +486,6 @@ config NI_LED_PREFIX If unsure, use the default. -config NI_HW_REBOOT - bool "Hardware reboot for NI 903x/913x" - depends on NI_RT_FEATURES && X86_64 - default n - help - If enabled, when rebooting an NI 903x/913x, on-board hardware will - be used to reset the system. If not enabled, the controller will do - a normal ACPI reset. - - If unsure, say N. - source "drivers/misc/c2port/Kconfig" source "drivers/misc/eeprom/Kconfig" source "drivers/misc/cb710/Kconfig" diff --git a/drivers/misc/nirtfeatures.c b/drivers/misc/nirtfeatures.c index 439d72a1f3beb..c2076f0f5f6ad 100644 --- a/drivers/misc/nirtfeatures.c +++ b/drivers/misc/nirtfeatures.c @@ -17,10 +17,6 @@ #include #include -#ifdef CONFIG_NI_HW_REBOOT -#include -#endif - #define MODULE_NAME "nirtfeatures" /* Register addresses */ @@ -644,26 +640,6 @@ static void nirtfeatures_remove_leds(struct nirtfeatures *nirtfeatures) led_classdev_unregister(&nirtfeatures->extra_leds[i].cdev); } -/* Board specific reboot fixup */ - -#ifdef CONFIG_NI_HW_REBOOT - -static u16 mach_reboot_fixup_io_base; - -void mach_reboot_fixups(void) -{ - int i; - - if (mach_reboot_fixup_io_base) - for (i = 0; i < 10; ++i) { - outb(NIRTF_RESET_RESET_PROCESSOR, - mach_reboot_fixup_io_base + NIRTF_RESET); - udelay(100); - } -} - -#endif - /* ACPI driver */ static acpi_status nirtfeatures_resources(struct acpi_resource *res, void *data) @@ -749,11 +725,6 @@ static int nirtfeatures_acpi_add(struct acpi_device *device) return -EBUSY; } -#ifdef CONFIG_NI_HW_REBOOT - mach_reboot_fixup_io_base = nirtfeatures->io_base; - reboot_type = BOOT_KBD; -#endif - bpinfo = inb(nirtfeatures->io_base + NIRTF_BPINFO); bpinfo &= NIRTF_BPINFO_ID_MASK; From e7835e98803facb4e2bdea26ae3a5ce025f7dfd0 Mon Sep 17 00:00:00 2001 From: Jeff Westfahl Date: Fri, 11 Apr 2014 10:09:59 -0500 Subject: [PATCH 018/110] nirtfeatures: update to latest CPLD and remove debugging features Updated registers to match the latest CPLD documentation, removed several sysfs files that were only used for development debugging, and removed several now unused constants. Signed-off-by: Jeff Westfahl --- drivers/misc/nirtfeatures.c | 211 +++++++----------------------------- 1 file changed, 39 insertions(+), 172 deletions(-) diff --git a/drivers/misc/nirtfeatures.c b/drivers/misc/nirtfeatures.c index c2076f0f5f6ad..51d7bdfac67cf 100644 --- a/drivers/misc/nirtfeatures.c +++ b/drivers/misc/nirtfeatures.c @@ -21,53 +21,36 @@ /* Register addresses */ -#define NIRTF_SIGNATURE 0x00 #define NIRTF_YEAR 0x01 #define NIRTF_MONTH 0x02 #define NIRTF_DAY 0x03 #define NIRTF_HOUR 0x04 #define NIRTF_MINUTE 0x05 #define NIRTF_SCRATCH 0x06 -#define NIRTF_BPINFO 0x07 -#define NIRTF_RAIL_STATUS1 0x08 -#define NIRTF_RAIL_STATUS2 0x09 -#define NIRTF_LOCK 0x0F -#define NIRTF_RESET 0x10 -#define NIRTF_RESET_SOURCE 0x11 -#define NIRTF_PROCESSOR_MODE 0x12 +#define NIRTF_PLATFORM_MISC 0x07 +#define NIRTF_PROC_RESET_SOURCE 0x11 +#define NIRTF_CONTROLLER_MODE 0x12 #define NIRTF_SYSTEM_LEDS 0x20 #define NIRTF_STATUS_LED_SHIFT1 0x21 #define NIRTF_STATUS_LED_SHIFT0 0x22 #define NIRTF_RT_LEDS 0x23 -#define NIRTF_DEBUG_SWITCH 0x30 -#define NIRTF_GP_BUTTON 0x31 #define NIRTF_IO_SIZE 0x40 /* Register values */ -#define NIRTF_BPINFO_ID_MASK 0x07 +#define NIRTF_PLATFORM_MISC_ID_MASK 0x07 +#define NIRTF_PLATFORM_MISC_ID_MANHATTAN 0 +#define NIRTF_PLATFORM_MISC_ID_HAMMERHEAD 4 +#define NIRTF_PLATFORM_MISC_ID_WINGHEAD 5 -#define NIRTF_BPINFO_ID_MANHATTAN 0 -#define NIRTF_BPINFO_ID_HAMMERHEAD 4 -#define NIRTF_BPINFO_ID_WINGHEAD 5 - -#define NIRTF_RESET_RESET_PROCESSOR 0x80 - -#define NIRTF_RESET_SOURCE_SOFT_OFF 0x20 -#define NIRTF_RESET_SOURCE_SOFTWARE 0x10 -#define NIRTF_RESET_SOURCE_WATCHDOG 0x08 -#define NIRTF_RESET_SOURCE_FPGA 0x04 -#define NIRTF_RESET_SOURCE_PROCESSOR 0x02 -#define NIRTF_RESET_SOURCE_BUTTON 0x01 - -#define NIRTF_PROCESSOR_MODE_NO_FPGA_SW 0x40 -#define NIRTF_PROCESSOR_MODE_HARD_BOOT_N 0x20 -#define NIRTF_PROCESSOR_MODE_NO_FPGA 0x10 -#define NIRTF_PROCESSOR_MODE_RECOVERY 0x08 -#define NIRTF_PROCESSOR_MODE_CONSOLE_OUT 0x04 -#define NIRTF_PROCESSOR_MODE_IP_RESET 0x02 -#define NIRTF_PROCESSOR_MODE_SAFE 0x01 +#define NIRTF_CONTROLLER_MODE_NO_FPGA_SW 0x40 +#define NIRTF_CONTROLLER_MODE_HARD_BOOT_N 0x20 +#define NIRTF_CONTROLLER_MODE_NO_FPGA 0x10 +#define NIRTF_CONTROLLER_MODE_RECOVERY 0x08 +#define NIRTF_CONTROLLER_MODE_CONSOLE_OUT 0x04 +#define NIRTF_CONTROLLER_MODE_IP_RESET 0x02 +#define NIRTF_CONTROLLER_MODE_SAFE 0x01 #define NIRTF_SYSTEM_LEDS_STATUS_RED 0x08 #define NIRTF_SYSTEM_LEDS_STATUS_YELLOW 0x04 @@ -165,55 +148,8 @@ static ssize_t nirtfeatures_backplane_id_get(struct device *dev, static DEVICE_ATTR(backplane_id, S_IRUGO, nirtfeatures_backplane_id_get, NULL); -static ssize_t nirtfeatures_railstatus1_get(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct acpi_device *acpi_device = to_acpi_device(dev); - struct nirtfeatures *nirtfeatures = acpi_device->driver_data; - u8 data; - - data = inb(nirtfeatures->io_base + NIRTF_RAIL_STATUS1); - - return sprintf(buf, "%02x\n", data); -} - -static DEVICE_ATTR(railstatus1, S_IRUGO, nirtfeatures_railstatus1_get, NULL); - -static ssize_t nirtfeatures_railstatus2_get(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct acpi_device *acpi_device = to_acpi_device(dev); - struct nirtfeatures *nirtfeatures = acpi_device->driver_data; - u8 data; - - data = inb(nirtfeatures->io_base + NIRTF_RAIL_STATUS2); - - return sprintf(buf, "%02x\n", data); -} - -static DEVICE_ATTR(railstatus2, S_IRUGO, nirtfeatures_railstatus2_get, NULL); - -static ssize_t nirtfeatures_reset_set(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) -{ - struct acpi_device *acpi_device = to_acpi_device(dev); - struct nirtfeatures *nirtfeatures = acpi_device->driver_data; - - if (strcmp(buf, "1")) - return -EINVAL; - - outb(NIRTF_RESET_RESET_PROCESSOR, nirtfeatures->io_base + NIRTF_RESET); - - return count; -} - -static DEVICE_ATTR(reset, S_IWUSR, NULL, nirtfeatures_reset_set); - static const char * const nirtfeatures_reset_source_strings[] = { - "button", "processor", "fpga", "watchdog", "software", "softoff", + "button", "processor", "fpga", "watchdog", "software", }; static ssize_t nirtfeatures_reset_source_get(struct device *dev, @@ -225,7 +161,7 @@ static ssize_t nirtfeatures_reset_source_get(struct device *dev, u8 data; int i; - data = inb(nirtfeatures->io_base + NIRTF_RESET_SOURCE); + data = inb(nirtfeatures->io_base + NIRTF_PROC_RESET_SOURCE); for (i = 0; i < ARRAY_SIZE(nirtfeatures_reset_source_strings); i++) if ((1 << i) & data) @@ -245,9 +181,9 @@ static ssize_t nirtfeatures_no_fpga_sw_get(struct device *dev, struct nirtfeatures *nirtfeatures = acpi_device->driver_data; u8 data; - data = inb(nirtfeatures->io_base + NIRTF_PROCESSOR_MODE); + data = inb(nirtfeatures->io_base + NIRTF_CONTROLLER_MODE); - data &= NIRTF_PROCESSOR_MODE_NO_FPGA_SW; + data &= NIRTF_CONTROLLER_MODE_NO_FPGA_SW; return sprintf(buf, "%u\n", !!data); } @@ -266,14 +202,14 @@ static ssize_t nirtfeatures_no_fpga_sw_set(struct device *dev, spin_lock(&nirtfeatures->lock); - data = inb(nirtfeatures->io_base + NIRTF_PROCESSOR_MODE); + data = inb(nirtfeatures->io_base + NIRTF_CONTROLLER_MODE); if (tmp) - data |= NIRTF_PROCESSOR_MODE_NO_FPGA_SW; + data |= NIRTF_CONTROLLER_MODE_NO_FPGA_SW; else - data &= ~NIRTF_PROCESSOR_MODE_NO_FPGA_SW; + data &= ~NIRTF_CONTROLLER_MODE_NO_FPGA_SW; - outb(data, nirtfeatures->io_base + NIRTF_PROCESSOR_MODE); + outb(data, nirtfeatures->io_base + NIRTF_CONTROLLER_MODE); spin_unlock(&nirtfeatures->lock); @@ -291,9 +227,9 @@ static ssize_t nirtfeatures_soft_reset_get(struct device *dev, struct nirtfeatures *nirtfeatures = acpi_device->driver_data; u8 data; - data = inb(nirtfeatures->io_base + NIRTF_PROCESSOR_MODE); + data = inb(nirtfeatures->io_base + NIRTF_CONTROLLER_MODE); - data &= NIRTF_PROCESSOR_MODE_HARD_BOOT_N; + data &= NIRTF_CONTROLLER_MODE_HARD_BOOT_N; return sprintf(buf, "%u\n", !!data); } @@ -308,9 +244,9 @@ static ssize_t nirtfeatures_no_fpga_get(struct device *dev, struct nirtfeatures *nirtfeatures = acpi_device->driver_data; u8 data; - data = inb(nirtfeatures->io_base + NIRTF_PROCESSOR_MODE); + data = inb(nirtfeatures->io_base + NIRTF_CONTROLLER_MODE); - data &= NIRTF_PROCESSOR_MODE_NO_FPGA; + data &= NIRTF_CONTROLLER_MODE_NO_FPGA; return sprintf(buf, "%u\n", !!data); } @@ -325,9 +261,9 @@ static ssize_t nirtfeatures_recovery_mode_get(struct device *dev, struct nirtfeatures *nirtfeatures = acpi_device->driver_data; u8 data; - data = inb(nirtfeatures->io_base + NIRTF_PROCESSOR_MODE); + data = inb(nirtfeatures->io_base + NIRTF_CONTROLLER_MODE); - data &= NIRTF_PROCESSOR_MODE_RECOVERY; + data &= NIRTF_CONTROLLER_MODE_RECOVERY; return sprintf(buf, "%u\n", !!data); } @@ -343,9 +279,9 @@ static ssize_t nirtfeatures_console_out_get(struct device *dev, struct nirtfeatures *nirtfeatures = acpi_device->driver_data; u8 data; - data = inb(nirtfeatures->io_base + NIRTF_PROCESSOR_MODE); + data = inb(nirtfeatures->io_base + NIRTF_CONTROLLER_MODE); - data &= NIRTF_PROCESSOR_MODE_CONSOLE_OUT; + data &= NIRTF_CONTROLLER_MODE_CONSOLE_OUT; return sprintf(buf, "%u\n", !!data); } @@ -360,9 +296,9 @@ static ssize_t nirtfeatures_ip_reset_get(struct device *dev, struct nirtfeatures *nirtfeatures = acpi_device->driver_data; u8 data; - data = inb(nirtfeatures->io_base + NIRTF_PROCESSOR_MODE); + data = inb(nirtfeatures->io_base + NIRTF_CONTROLLER_MODE); - data &= NIRTF_PROCESSOR_MODE_IP_RESET; + data &= NIRTF_CONTROLLER_MODE_IP_RESET; return sprintf(buf, "%u\n", !!data); } @@ -377,87 +313,19 @@ static ssize_t nirtfeatures_safe_mode_get(struct device *dev, struct nirtfeatures *nirtfeatures = acpi_device->driver_data; u8 data; - data = inb(nirtfeatures->io_base + NIRTF_PROCESSOR_MODE); + data = inb(nirtfeatures->io_base + NIRTF_CONTROLLER_MODE); - data &= NIRTF_PROCESSOR_MODE_SAFE; + data &= NIRTF_CONTROLLER_MODE_SAFE; return sprintf(buf, "%u\n", !!data); } static DEVICE_ATTR(safe_mode, S_IRUGO, nirtfeatures_safe_mode_get, NULL); -static ssize_t nirtfeatures_register_dump_get(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct acpi_device *acpi_device = to_acpi_device(dev); - struct nirtfeatures *nirtfeatures = acpi_device->driver_data; - u8 signature, year, month, day, hour, minute, scratch, bpinfo; - u8 railstatus1, railstatus2, lock, reset, reset_source, processor_mode; - u8 system_leds, status_led_shift1, status_led_shift0, rt_leds; - u8 debug_switch, gp_button; - - signature = inb(nirtfeatures->io_base + NIRTF_SIGNATURE); - year = inb(nirtfeatures->io_base + NIRTF_YEAR); - month = inb(nirtfeatures->io_base + NIRTF_MONTH); - day = inb(nirtfeatures->io_base + NIRTF_DAY); - hour = inb(nirtfeatures->io_base + NIRTF_HOUR); - minute = inb(nirtfeatures->io_base + NIRTF_MINUTE); - scratch = inb(nirtfeatures->io_base + NIRTF_SCRATCH); - bpinfo = inb(nirtfeatures->io_base + NIRTF_BPINFO); - railstatus1 = inb(nirtfeatures->io_base + NIRTF_RAIL_STATUS1); - railstatus2 = inb(nirtfeatures->io_base + NIRTF_RAIL_STATUS2); - lock = inb(nirtfeatures->io_base + NIRTF_LOCK); - reset = inb(nirtfeatures->io_base + NIRTF_RESET); - reset_source = inb(nirtfeatures->io_base + NIRTF_RESET_SOURCE); - processor_mode = inb(nirtfeatures->io_base + NIRTF_PROCESSOR_MODE); - system_leds = inb(nirtfeatures->io_base + NIRTF_SYSTEM_LEDS); - status_led_shift1 = - inb(nirtfeatures->io_base + NIRTF_STATUS_LED_SHIFT1); - status_led_shift0 = - inb(nirtfeatures->io_base + NIRTF_STATUS_LED_SHIFT0); - rt_leds = inb(nirtfeatures->io_base + NIRTF_RT_LEDS); - debug_switch = inb(nirtfeatures->io_base + NIRTF_DEBUG_SWITCH); - gp_button = inb(nirtfeatures->io_base + NIRTF_GP_BUTTON); - - return sprintf(buf, - "Signature: 0x%02X\n" - "Year: 0x%02X\n" - "Month: 0x%02X\n" - "Day: 0x%02X\n" - "Hour: 0x%02X\n" - "Minute: 0x%02X\n" - "Scratch: 0x%02X\n" - "BPInfo: 0x%02X\n" - "Rail status 1: 0x%02X\n" - "Rail status 2: 0x%02X\n" - "Lock: 0x%02X\n" - "Reset: 0x%02X\n" - "Reset source: 0x%02X\n" - "Processor mode: 0x%02X\n" - "System LEDs: 0x%02X\n" - "Status LED shift 1: 0x%02X\n" - "Status LED shift 0: 0x%02X\n" - "RT LEDs: 0x%02X\n" - "Debug switch: 0x%02X\n" - "GP button: 0x%02X\n", - signature, year, month, day, hour, minute, scratch, - bpinfo, railstatus1, railstatus2, lock, reset, - reset_source, processor_mode, system_leds, - status_led_shift1, status_led_shift0, rt_leds, - debug_switch, gp_button); -} - -static DEVICE_ATTR(register_dump, S_IRUGO, nirtfeatures_register_dump_get, - NULL); - static const struct attribute *nirtfeatures_attrs[] = { &dev_attr_revision.attr, &dev_attr_scratch.attr, &dev_attr_backplane_id.attr, - &dev_attr_railstatus1.attr, - &dev_attr_railstatus2.attr, - &dev_attr_reset.attr, &dev_attr_reset_source.attr, &dev_attr_no_fpga_sw.attr, &dev_attr_soft_reset.attr, @@ -466,7 +334,6 @@ static const struct attribute *nirtfeatures_attrs[] = { &dev_attr_console_out.attr, &dev_attr_ip_reset.attr, &dev_attr_safe_mode.attr, - &dev_attr_register_dump.attr, NULL }; @@ -725,21 +592,21 @@ static int nirtfeatures_acpi_add(struct acpi_device *device) return -EBUSY; } - bpinfo = inb(nirtfeatures->io_base + NIRTF_BPINFO); + bpinfo = inb(nirtfeatures->io_base + NIRTF_PLATFORM_MISC); - bpinfo &= NIRTF_BPINFO_ID_MASK; + bpinfo &= NIRTF_PLATFORM_MISC_ID_MASK; switch (bpinfo) { - case NIRTF_BPINFO_ID_MANHATTAN: + case NIRTF_PLATFORM_MISC_ID_MANHATTAN: nirtfeatures->bpstring = "Manhattan"; break; - case NIRTF_BPINFO_ID_HAMMERHEAD: + case NIRTF_PLATFORM_MISC_ID_HAMMERHEAD: nirtfeatures->bpstring = "Hammerhead"; nirtfeatures->extra_leds = nirtfeatures_leds_cdaq; nirtfeatures->num_extra_leds = ARRAY_SIZE(nirtfeatures_leds_cdaq); break; - case NIRTF_BPINFO_ID_WINGHEAD: + case NIRTF_PLATFORM_MISC_ID_WINGHEAD: nirtfeatures->bpstring = "Winghead"; nirtfeatures->extra_leds = nirtfeatures_leds_cdaq; nirtfeatures->num_extra_leds = From 556f7c00d7d64b639cec779e94196be3b76df9e6 Mon Sep 17 00:00:00 2001 From: Gratian Crisan Date: Tue, 13 May 2014 16:12:02 -0500 Subject: [PATCH 019/110] nirtfeatures: Physical interface element support These changes add support for PIEs (physical interface elements), which are defined as physical elements fixed to a controller/chassis with which a user can interact (e.g. LEDs and switches) and whose meaning is user-defined and implementation-specific. The support for these elements, in terms of enumerating and interacting with them (i.e. retrieving the list of elements, getting/setting their current state, enabling notifications, etc.) is embedded within the BIOS as a set of ACPI methods. The changes to the CPLD driver act as a bridge between these methods and existing Linux kernel facilities as described below to expose the elements and any applicable metadata to user mode. The metadata or knowledge needed for the interpretation thereof is not a prerequisite to interacting with the elements--it is there for upper-level value add software to use to improve the user experience. In other words, Linux users familiar with the class drivers by which the elements are surfaced should not have any issues interfacing with them without knowing the meaning of the attached metadata. Output elements, which consist currently of LEDs, are surfaced via the LED class driver. Each LED and color becomes its own LED class device with the naming convention 'nilrt:{name}:{color}'. Any additional attributes/metadata intended for upper-level software are appended to the name, each separated by colons, as suggested by the LED class driver documentation in the Linux kernel proper, except where there is already a standard way to communicate a specific piece of metadata (e.g., maximum brightness, which is exposed via the /sys/class/leds/.../ max_brightness attribute node). Input elements as surfaced via the input class driver. As with output elements, each input element registers its own separate driver whose name and associated metadata are transmitted via the name attribute attached to the input device, retrievable via the EVIOCGNAME ioctl, using the same convention as described above for output elements. The input class driver model is that events are pushed (i.e. reported) to indicate state changes, so to facilitate this, the CPLD driver has an ACPI notify callback that is invoked when an input element changes state and its BIOS support generates a general purpose event per the ACPI GPE model. The notify callback checks the instantaneous state of the input element and reports a keyboard event on its particular device with a scan code of 256 (BTN_0), where a key down event means that the input element is in the '1' state (down, engaged, on, pressed, etc.) and a key up event means that the input element is in the '0' state (off, disengaged, released, etc.). User mode software can then monitor for these specific events to determine when the state of the element has changed, or can use the EVIOCGKEY ioctl on the appropriate input device to retrieve the instantaneous state of the element. Signed-off-by: Aaron Rossetto (joshc: fixed up strnicmp -> strncasecmp for 4.0) Signed-off-by: Josh Cartwright --- drivers/misc/nirtfeatures.c | 812 +++++++++++++++++++++++++++++++++--- 1 file changed, 751 insertions(+), 61 deletions(-) diff --git a/drivers/misc/nirtfeatures.c b/drivers/misc/nirtfeatures.c index 51d7bdfac67cf..cce1c53d6252f 100644 --- a/drivers/misc/nirtfeatures.c +++ b/drivers/misc/nirtfeatures.c @@ -15,7 +15,9 @@ #include #include #include +#include #include +#include #define MODULE_NAME "nirtfeatures" @@ -57,10 +59,49 @@ #define NIRTF_SYSTEM_LEDS_POWER_GREEN 0x02 #define NIRTF_SYSTEM_LEDS_POWER_YELLOW 0x01 -#define NIRTF_RT_LEDS_USER2_GREEN 0x08 -#define NIRTF_RT_LEDS_USER2_YELLOW 0x04 -#define NIRTF_RT_LEDS_USER1_GREEN 0x02 -#define NIRTF_RT_LEDS_USER1_YELLOW 0x01 +/*===================================================================== + * ACPI NI physical interface element support + *===================================================================*/ +#define MAX_NAMELEN 64 +#define MAX_NODELEN 128 +#define MIN_PIE_CAPS_VERSION 2 +#define MAX_PIE_CAPS_VERSION 2 + +enum nirtfeatures_pie_class { + PIE_CLASS_INPUT = 0, + PIE_CLASS_OUTPUT = 1 +}; + +enum nirtfeatures_pie_type { + PIE_TYPE_UNKNOWN = 0, + PIE_TYPE_SWITCH = 1, + PIE_TYPE_LED = 2 +}; + +struct nirtfeatures_pie_descriptor { + char name[MAX_NAMELEN]; + enum nirtfeatures_pie_class pie_class; + enum nirtfeatures_pie_type pie_type; + bool is_user_visible; + unsigned int notification_value; +}; + +struct nirtfeatures_pie_descriptor_led_color { + char name[MAX_NAMELEN]; + int brightness_range_low; + int brightness_range_high; +}; + +struct nirtfeatures_pie_descriptor_switch { + unsigned int num_states; + unsigned int state_value[1]; +}; + +struct nirtfeatures_pie_location { + unsigned int element; + unsigned int subelement; +}; + /* Structures */ @@ -71,18 +112,31 @@ struct nirtfeatures { spinlock_t lock; u8 revision[5]; const char *bpstring; - struct nirtfeatures_led *extra_leds; - unsigned num_extra_leds; }; struct nirtfeatures_led { struct led_classdev cdev; struct nirtfeatures *nirtfeatures; + struct nirtfeatures_pie_location pie_location; + char name_string[MAX_NODELEN]; u8 address; u8 mask; u8 pattern_hi_addr; u8 pattern_lo_addr; + struct list_head node; +}; +LIST_HEAD(nirtfeatures_led_pie_list); + +struct nirtfeatures_switch { + struct input_dev *cdev; + struct nirtfeatures *nirtfeatures; + struct nirtfeatures_pie_descriptor pie_descriptor; + struct nirtfeatures_pie_location pie_location; + char name_string[MAX_NODELEN]; + char phys_location_string[MAX_NODELEN]; + struct list_head node; }; +LIST_HEAD(nirtfeatures_switch_pie_list); /* sysfs files */ @@ -386,20 +440,6 @@ nirtfeatures_led_brightness_get(struct led_classdev *led_cdev) } static struct nirtfeatures_led nirtfeatures_leds_common[] = { - { - { - .name = CONFIG_NI_LED_PREFIX ":user1:green", - }, - .address = NIRTF_RT_LEDS, - .mask = NIRTF_RT_LEDS_USER1_GREEN, - }, - { - { - .name = CONFIG_NI_LED_PREFIX ":user1:yellow", - }, - .address = NIRTF_RT_LEDS, - .mask = NIRTF_RT_LEDS_USER1_YELLOW, - }, { { .name = CONFIG_NI_LED_PREFIX ":status:red", @@ -433,22 +473,610 @@ static struct nirtfeatures_led nirtfeatures_leds_common[] = { }, }; -static struct nirtfeatures_led nirtfeatures_leds_cdaq[] = { - { - { - .name = CONFIG_NI_LED_PREFIX ":user2:green", - }, - .address = NIRTF_RT_LEDS, - .mask = NIRTF_RT_LEDS_USER2_GREEN, - }, - { - { - .name = CONFIG_NI_LED_PREFIX ":user2:yellow", - }, - .address = NIRTF_RT_LEDS, - .mask = NIRTF_RT_LEDS_USER2_YELLOW, - }, -}; +/*===================================================================== + * ACPI NI physical interface element support + *===================================================================*/ + +/* Note that callers of this function are responsible for deallocating + * the buffer allocated by acpi_evaluate_object() by calling + * kfree() on the pointer passed back in result_buffer. + */ +static int nirtfeatures_call_acpi_method(struct nirtfeatures *nirtfeatures, + const char *method_name, + int argc, + union acpi_object *argv, + acpi_size *result_size, + void **result_buffer) +{ + acpi_status acpi_ret; + acpi_handle acpi_hdl; + struct acpi_object_list acpi_params; + struct acpi_buffer acpi_result = { ACPI_ALLOCATE_BUFFER, NULL }; + + if (NULL == nirtfeatures || NULL == result_size || + NULL == result_buffer) + return -EINVAL; + + acpi_ret = acpi_get_handle(nirtfeatures->acpi_device->handle, + (acpi_string) method_name, &acpi_hdl); + if (ACPI_FAILURE(acpi_ret)) { + dev_err(&nirtfeatures->acpi_device->dev, + "nirtfeatures: ACPI get handle for %s failed (%d)\n", + method_name, acpi_ret); + return -1; + } + + acpi_params.count = argc; + acpi_params.pointer = argv; + + acpi_ret = acpi_evaluate_object(acpi_hdl, NULL, + &acpi_params, &acpi_result); + if (ACPI_FAILURE(acpi_ret)) { + dev_err(&nirtfeatures->acpi_device->dev, + "nirtfeatures: ACPI evaluate for %s failed (%d)\n", + method_name, acpi_ret); + return -1; + } + + *result_size = acpi_result.length; + *result_buffer = acpi_result.pointer; + return 0; +} + +/* This is the generic PIE set state wrapper. It invokes the PIES + * ACPI method to modify the state of the given PIE. + */ +static int nirtfeatures_pie_set_state(struct nirtfeatures *nirtfeatures, + unsigned int element, unsigned int subelement, int state) +{ + union acpi_object pies_args[3]; + acpi_size result_size; + void *result_buffer; + union acpi_object *acpi_buffer; + int err = 0; + + if (NULL == nirtfeatures) + return -EINVAL; + + pies_args[0].type = ACPI_TYPE_INTEGER; + pies_args[0].integer.value = element; + pies_args[1].type = ACPI_TYPE_INTEGER; + pies_args[1].integer.value = subelement; + pies_args[2].type = ACPI_TYPE_INTEGER; + pies_args[2].integer.value = state; + + /* evaluate PIES(element, subelement, value) ACPI method */ + err = nirtfeatures_call_acpi_method(nirtfeatures, "PIES", + 3, &pies_args[0], &result_size, &result_buffer); + + if (err == 0) { + acpi_buffer = (union acpi_object *) result_buffer; + if (ACPI_TYPE_INTEGER == acpi_buffer->type) + err = (int) acpi_buffer->integer.value; + kfree(result_buffer); + } + + return err; +} + +/* This is the generic PIE get state wrapper. It invokes the PIEG + * ACPI method to query the state of the given PIE. + */ +static int nirtfeatures_pie_get_state(struct nirtfeatures *nirtfeatures, + unsigned int element, unsigned int subelement, int *result) +{ + union acpi_object pies_args[2]; + acpi_size result_size; + void *result_buffer; + union acpi_object *acpi_buffer; + int err = 0; + + if (NULL == nirtfeatures || NULL == result) + return -EINVAL; + + pies_args[0].type = ACPI_TYPE_INTEGER; + pies_args[0].integer.value = element; + pies_args[1].type = ACPI_TYPE_INTEGER; + pies_args[1].integer.value = subelement; + + /* evaluate PIEG(element, subelement) ACPI method */ + err = nirtfeatures_call_acpi_method(nirtfeatures, "PIEG", + 2, &pies_args[0], &result_size, &result_buffer); + + if (err == 0) { + acpi_buffer = (union acpi_object *) result_buffer; + if (ACPI_TYPE_INTEGER == acpi_buffer->type) + *result = (int) acpi_buffer->integer.value; + kfree(result_buffer); + } + + return err; +} + +/* This function enables or disables notifications for a particular + * input class PIE. + */ +static int nirtfeatures_pie_enable_notifications( + struct nirtfeatures *nirtfeatures, + unsigned int element, unsigned int subelement, int enable) +{ + union acpi_object pies_args[3]; + acpi_size result_size; + void *result_buffer; + union acpi_object *acpi_buffer; + int err = 0; + + if (NULL == nirtfeatures) + return -EINVAL; + + pies_args[0].type = ACPI_TYPE_INTEGER; + pies_args[0].integer.value = element; + pies_args[1].type = ACPI_TYPE_INTEGER; + pies_args[1].integer.value = subelement; + pies_args[2].type = ACPI_TYPE_INTEGER; + pies_args[2].integer.value = enable; + + /* evaluate PIEF(element, subelement, enable) ACPI method */ + err = nirtfeatures_call_acpi_method(nirtfeatures, "PIEF", + 3, &pies_args[0], &result_size, &result_buffer); + + if (err == 0) { + acpi_buffer = (union acpi_object *) result_buffer; + if (ACPI_TYPE_INTEGER == acpi_buffer->type) + err = (int) acpi_buffer->integer.value; + kfree(result_buffer); + } + + return err; +} + +/* This is the set_brightness callback for a PIE-enumerated LED. + */ +static void nirtfeatures_led_pie_brightness_set( + struct led_classdev *led_cdev, enum led_brightness brightness) +{ + struct nirtfeatures_led *led = (struct nirtfeatures_led *)led_cdev; + + spin_lock(&led->nirtfeatures->lock); + + /* Delegate the control of the PIE to the ACPI method. */ + if (nirtfeatures_pie_set_state(led->nirtfeatures, + led->pie_location.element, led->pie_location.subelement, + brightness)) { + dev_err(&led->nirtfeatures->acpi_device->dev, + "nirtfeatures: set brightness failed for %s\n", + led->name_string); + } + + spin_unlock(&led->nirtfeatures->lock); +} + +/* This is the get_brightness callback for a PIE-enumerated LED. + */ +static enum led_brightness nirtfeatures_led_pie_brightness_get( + struct led_classdev *led_cdev) +{ + struct nirtfeatures_led *led = (struct nirtfeatures_led *)led_cdev; + int state = 0; + + spin_lock(&led->nirtfeatures->lock); + + if (nirtfeatures_pie_get_state(led->nirtfeatures, + led->pie_location.element, led->pie_location.subelement, &state)) { + dev_err(&led->nirtfeatures->acpi_device->dev, + "nirtfeatures: get brightness failed for %s\n", + led->name_string); + } + + spin_unlock(&led->nirtfeatures->lock); + return state; +} + +/* Parse a PIE LED color caps package and populate the + * corresponding nirtfeatures_pie_descriptor_led_color structure. + */ +static int nirtfeatures_parse_led_pie_color(struct nirtfeatures *nirtfeatures, + unsigned int pie_caps_version, + struct nirtfeatures_pie_descriptor_led_color *led_color_descriptor, + union acpi_object *acpi_buffer) +{ + unsigned int i; + + if (NULL == nirtfeatures || NULL == led_color_descriptor || + NULL == acpi_buffer) + return -EINVAL; + + /* element 0 of a PIE LED color caps package is the name */ + if (ACPI_TYPE_BUFFER == acpi_buffer->package.elements[0].type) { + for (i = 0; + i < acpi_buffer->package.elements[0].buffer.length; i++) { + /* get pointer to Nth Unicode character in name */ + unsigned short *unicode_char = (unsigned short *) + (acpi_buffer->package.elements[0].buffer.pointer + + (2 * i)); + /* naive convert to ASCII */ + led_color_descriptor->name[i] = + (char) *unicode_char & 0xff; + } + } else + return -EINVAL; + + /* element 1 is the brightness min value */ + if (ACPI_TYPE_INTEGER == acpi_buffer->package.elements[1].type) + led_color_descriptor->brightness_range_low = + (int) acpi_buffer->package.elements[1].integer.value; + else + return -EINVAL; + + /* element 2 is the brightness max value */ + if (ACPI_TYPE_INTEGER == acpi_buffer->package.elements[2].type) + led_color_descriptor->brightness_range_high = + (int) acpi_buffer->package.elements[2].integer.value; + else + return -EINVAL; + + return 0; +} + +/* Parse a PIE LED caps package and create an LED class device + * with the appropriate metadata. + */ +static int nirtfeatures_parse_led_pie( + struct nirtfeatures *nirtfeatures, + unsigned int pie_caps_version, + unsigned int pie_element, + struct nirtfeatures_pie_descriptor *pie, + union acpi_object *acpi_buffer) +{ + unsigned int num_colors; + unsigned int i; + struct nirtfeatures_pie_descriptor_led_color led_descriptor; + struct nirtfeatures_led *led_dev; + int err; + + if (NULL == nirtfeatures || NULL == pie || + NULL == acpi_buffer) + return -EINVAL; + + if (ACPI_TYPE_PACKAGE != acpi_buffer->type) + return -EINVAL; + + /* element 0 is the number of colors */ + if (ACPI_TYPE_INTEGER == acpi_buffer->package.elements[0].type) { + num_colors = (unsigned int) + acpi_buffer->package.elements[0].integer.value; + } else { + return -EINVAL; + } + + /* parse color caps and create LED class device */ + for (i = 0; i < num_colors; i++) { + if (nirtfeatures_parse_led_pie_color(nirtfeatures, + pie_caps_version, &led_descriptor, + &(acpi_buffer->package.elements[i + 1]))) + return -EINVAL; + + /* create an LED class device for this LED */ + led_dev = kzalloc(sizeof(struct nirtfeatures_led), GFP_KERNEL); + if (NULL == led_dev) + return -ENOMEM; + + /* for compatibility with existing LVRT support, PIEs beginning + * with 'user' should not affix the uservisible attribute to + * their name */ + if (strncasecmp(pie->name, "user", strlen("user")) != 0) { + snprintf(led_dev->name_string, MAX_NODELEN, + "%s:%s:%s:uservisible=%d", + CONFIG_NI_LED_PREFIX, + pie->name, led_descriptor.name, + pie->is_user_visible); + } else { + snprintf(led_dev->name_string, MAX_NODELEN, + "%s:%s:%s", + CONFIG_NI_LED_PREFIX, + pie->name, led_descriptor.name); + } + + led_dev->cdev.name = led_dev->name_string; + led_dev->cdev.brightness = + led_descriptor.brightness_range_low; + led_dev->cdev.max_brightness = + led_descriptor.brightness_range_high; + led_dev->cdev.brightness_set = + nirtfeatures_led_pie_brightness_set; + led_dev->cdev.brightness_get = + nirtfeatures_led_pie_brightness_get; + led_dev->nirtfeatures = nirtfeatures; + led_dev->pie_location.element = pie_element; + led_dev->pie_location.subelement = i; + + err = led_classdev_register(&nirtfeatures->acpi_device->dev, + &led_dev->cdev); + if (0 != err) { + kfree(led_dev); + return err; + } + + list_add_tail(&led_dev->node, &nirtfeatures_led_pie_list); + } + + return 0; +} + +/* Parse a PIE switch caps package and create an input class device + * with the appropriate metadata. + */ +static int nirtfeatures_parse_switch_pie(struct nirtfeatures *nirtfeatures, + unsigned int pie_caps_version, + unsigned int pie_element, + struct nirtfeatures_pie_descriptor *pie, + union acpi_object *acpi_buffer) +{ + unsigned int num_states; + unsigned int i; + struct nirtfeatures_pie_descriptor_switch *switch_descriptor = NULL; + struct nirtfeatures_switch *switch_dev = NULL; + int err = 0; + + if (NULL == nirtfeatures || NULL == pie || NULL == acpi_buffer) + return -EINVAL; + + if (ACPI_TYPE_PACKAGE != acpi_buffer->type) + return -EINVAL; + + /* element 0 is the number of states */ + if (ACPI_TYPE_INTEGER == acpi_buffer->package.elements[0].type) + num_states = (unsigned int) + acpi_buffer->package.elements[0].integer.value; + else + return -EINVAL; + + /* allocate storage for switch descriptor */ + switch_descriptor = kzalloc( + sizeof(struct nirtfeatures_pie_descriptor_switch) + + sizeof(int) * (num_states - 1), GFP_KERNEL); + if (NULL == switch_descriptor) + return -ENOMEM; + + switch_descriptor->num_states = num_states; + + /* parse individual states in elements 1..N-1 */ + for (i = 0; i < num_states; i++) { + if (ACPI_TYPE_INTEGER != + acpi_buffer->package.elements[i + 1].type) { + err = -EINVAL; + goto exit; + } + + switch_descriptor->state_value[i] = + (int) acpi_buffer->package.elements[i + 1].integer.value; + } + + /* create an input class device for this switch */ + switch_dev = kzalloc(sizeof(struct nirtfeatures_switch), GFP_KERNEL); + if (NULL == switch_dev) { + err = -ENOMEM; + goto exit; + } + + switch_dev->cdev = input_allocate_device(); + if (NULL == switch_dev->cdev) { + err = -ENOMEM; + goto exit_dealloc_switch_dev; + } + + switch_dev->nirtfeatures = nirtfeatures; + switch_dev->pie_location.element = pie_element; + switch_dev->pie_location.subelement = 0; + memcpy(&switch_dev->pie_descriptor, pie, + sizeof(struct nirtfeatures_pie_descriptor)); + + snprintf(switch_dev->name_string, MAX_NODELEN, + "%s:%s:uservisible=%d:states=(", + CONFIG_NI_LED_PREFIX, pie->name, pie->is_user_visible); + for (i = 0; i < switch_descriptor->num_states; i++) { + char temp[4] = { '\0' }; + + sprintf(temp, "%d%c", switch_descriptor->state_value[i], + (i < switch_descriptor->num_states - 1) ? ',' : ')'); + strncat(switch_dev->name_string, temp, MAX_NODELEN); + } + + snprintf(switch_dev->phys_location_string, MAX_NODELEN, "%s/%s/%s", + CONFIG_NI_LED_PREFIX, nirtfeatures->bpstring, pie->name); + + switch_dev->cdev->name = switch_dev->name_string; + switch_dev->cdev->phys = switch_dev->phys_location_string; + switch_dev->cdev->id.bustype = BUS_HOST; + switch_dev->cdev->id.vendor = 0x3923; + switch_dev->cdev->id.product = pie->pie_type; + switch_dev->cdev->id.version = pie_caps_version; + switch_dev->cdev->dev.parent = &nirtfeatures->acpi_device->dev; + + switch_dev->cdev->evbit[0] = BIT_MASK(EV_KEY); + set_bit(BTN_0, switch_dev->cdev->keybit); + + err = input_register_device(switch_dev->cdev); + if (0 != err) { + input_free_device(switch_dev->cdev); + goto exit_dealloc_switch_dev; + } + + /* if this PIE supports notifications, enable them now */ + if (pie->notification_value != 0) { + err = nirtfeatures_pie_enable_notifications(nirtfeatures, + pie_element, 0, 1); + if (0 != err) { + input_unregister_device(switch_dev->cdev); + input_free_device(switch_dev->cdev); + goto exit_dealloc_switch_dev; + } + } + + /* add the new device to our list of switch PIEs */ + list_add_tail(&switch_dev->node, &nirtfeatures_switch_pie_list); + goto exit; + +exit_dealloc_switch_dev: + kfree(switch_dev); + +exit: + kfree(switch_descriptor); + return err; +} + + +/* Parse a single PIE caps package from the PIEC buffer, determine the + * type of PIE it is, then dispatch to the appropriate parsing routine. + */ +static int nirtfeatures_parse_one_pie(struct nirtfeatures *nirtfeatures, + unsigned int pie_caps_version, + unsigned int pie_element, + union acpi_object *acpi_buffer) +{ + struct nirtfeatures_pie_descriptor pie; + unsigned int i; + + if (NULL == nirtfeatures || NULL == acpi_buffer) + return -EINVAL; + + /* check for proper type and number of elements */ + if (ACPI_TYPE_PACKAGE != acpi_buffer->type || + 6 != acpi_buffer->package.count) + return -EINVAL; + + /* element 0 of the package is the name */ + if (ACPI_TYPE_BUFFER == acpi_buffer->package.elements[0].type) { + for (i = 0; + i < acpi_buffer->package.elements[0].buffer.length && + i < MAX_NAMELEN; i++) { + /* get pointer to Nth Unicode character in name */ + unsigned short *unicode_char = (unsigned short *) + (acpi_buffer->package.elements[0].buffer.pointer + + (2 * i)); + /* naive convert to ASCII */ + pie.name[i] = (char) *unicode_char & 0xff; + } + } else + return -EINVAL; + + /* element 1 of the package is the PIE class */ + if (ACPI_TYPE_INTEGER == acpi_buffer->package.elements[1].type) + pie.pie_class = (enum nirtfeatures_pie_class) + acpi_buffer->package.elements[1].integer.value; + else + return -EINVAL; + + /* element 2 of the package is the PIE type */ + if (ACPI_TYPE_INTEGER == acpi_buffer->package.elements[2].type) + pie.pie_type = (enum nirtfeatures_pie_type) + acpi_buffer->package.elements[2].integer.value; + else + return -EINVAL; + + /* element 4 of an package is the visible flag */ + if (ACPI_TYPE_INTEGER == acpi_buffer->package.elements[4].type) + pie.is_user_visible = + (acpi_buffer->package.elements[4].integer.value != 0); + else + return -EINVAL; + + /* element 5 of the package is the notification value */ + if (ACPI_TYPE_INTEGER == acpi_buffer->package.elements[5].type) + pie.notification_value = + acpi_buffer->package.elements[5].integer.value; + else + return -EINVAL; + + /* parse the type-specific descriptor in element 3 */ + switch (pie.pie_type) { + case PIE_TYPE_LED: + if (nirtfeatures_parse_led_pie(nirtfeatures, + pie_caps_version, pie_element, &pie, + &(acpi_buffer->package.elements[3]))) + return -EINVAL; + break; + case PIE_TYPE_SWITCH: + if (nirtfeatures_parse_switch_pie(nirtfeatures, + pie_caps_version, pie_element, &pie, + &(acpi_buffer->package.elements[3]))) + return -EINVAL; + break; + + default: + return -EINVAL; + break; + } + + return 0; +} + +/* Populate the list of physical interface elements from the table in + * the DSDT and then generate the appropriate class devices. + */ +static int nirtfeatures_populate_pies(struct nirtfeatures *nirtfeatures) +{ + acpi_size result_size; + void *result_buffer; + union acpi_object *acpi_buffer; + unsigned int num_elements = 0; + unsigned int pie_caps_version; + unsigned int i; + unsigned int err = 0; + + if (NULL == nirtfeatures) + return -EINVAL; + + /* get the PIE descriptor buffer from DSDT */ + if (nirtfeatures_call_acpi_method(nirtfeatures, + "PIEC", 0, NULL, &result_size, &result_buffer)) + return -1; + + acpi_buffer = (union acpi_object *) result_buffer; + if (ACPI_TYPE_PACKAGE != acpi_buffer->type) { + err = -1; + goto exit; + } + + /* the first element of the package is the caps version */ + if (ACPI_TYPE_INTEGER == acpi_buffer->package.elements[0].type) + pie_caps_version = (unsigned int) + acpi_buffer->package.elements[0].integer.value; + else { + err = -1; + goto exit; + } + + if (pie_caps_version < MIN_PIE_CAPS_VERSION || + pie_caps_version > MAX_PIE_CAPS_VERSION) { + dev_err(&nirtfeatures->acpi_device->dev, + "nirtfeatures: invalid PIE caps version\n"); + err = -1; + goto exit; + } + + /* the second element of the package is the number of PIEs */ + if (ACPI_TYPE_INTEGER == acpi_buffer->package.elements[1].type) + num_elements = (unsigned int) + acpi_buffer->package.elements[1].integer.value; + else { + err = -1; + goto exit; + } + + /* parse elements 2..N as PIE descriptors */ + for (i = 2; i < acpi_buffer->package.count; i++) { + err = nirtfeatures_parse_one_pie(nirtfeatures, + pie_caps_version, i - 2, + &(acpi_buffer->package.elements[i])); + if (0 != err) + break; + } + +exit: + kfree(result_buffer); + return err; +} static int nirtfeatures_create_leds(struct nirtfeatures *nirtfeatures) { @@ -474,37 +1102,57 @@ static int nirtfeatures_create_leds(struct nirtfeatures *nirtfeatures) return err; } - for (i = 0; i < nirtfeatures->num_extra_leds; ++i) { + return 0; +} - nirtfeatures->extra_leds[i].nirtfeatures = nirtfeatures; +static void nirtfeatures_remove_leds(struct nirtfeatures *nirtfeatures) +{ + int i; - if (0 == nirtfeatures->extra_leds[i].cdev.max_brightness) - nirtfeatures->extra_leds[i].cdev.max_brightness = 1; + for (i = 0; i < ARRAY_SIZE(nirtfeatures_leds_common); ++i) + led_classdev_unregister(&nirtfeatures_leds_common[i].cdev); +} - nirtfeatures->extra_leds[i].cdev.brightness_set = - nirtfeatures_led_brightness_set; +static void nirtfeatures_remove_led_pies(struct nirtfeatures *nirtfeatures) +{ + struct nirtfeatures_led *cdev_iter; + struct nirtfeatures_led *temp; - nirtfeatures->extra_leds[i].cdev.brightness_get = - nirtfeatures_led_brightness_get; + spin_lock(&nirtfeatures->lock); - err = led_classdev_register(&nirtfeatures->acpi_device->dev, - &nirtfeatures->extra_leds[i].cdev); - if (err) - return err; + /* walk the list of non-fixed LEDs and unregister/free their devices */ + list_for_each_entry_safe( + cdev_iter, temp, &nirtfeatures_led_pie_list, node) { + led_classdev_unregister(&cdev_iter->cdev); + kfree(cdev_iter); } - return 0; + spin_unlock(&nirtfeatures->lock); } -static void nirtfeatures_remove_leds(struct nirtfeatures *nirtfeatures) +static void nirtfeatures_remove_switch_pies(struct nirtfeatures *nirtfeatures) { - int i; + struct nirtfeatures_switch *cdev_iter; + struct nirtfeatures_switch *temp; - for (i = 0; i < ARRAY_SIZE(nirtfeatures_leds_common); ++i) - led_classdev_unregister(&nirtfeatures_leds_common[i].cdev); + spin_lock(&nirtfeatures->lock); + + /* walk the list of switch devices and unregister/free each one */ + list_for_each_entry_safe( + cdev_iter, temp, &nirtfeatures_switch_pie_list, node) { + /* disable notifications for this PIE if supported */ + if (cdev_iter->pie_descriptor.notification_value != 0) { + nirtfeatures_pie_enable_notifications(nirtfeatures, + cdev_iter->pie_location.element, + cdev_iter->pie_location.subelement, + 0); + } + input_unregister_device(cdev_iter->cdev); + input_free_device(cdev_iter->cdev); + kfree(cdev_iter); + } - for (i = 0; i < nirtfeatures->num_extra_leds; ++i) - led_classdev_unregister(&nirtfeatures->extra_leds[i].cdev); + spin_unlock(&nirtfeatures->lock); } /* ACPI driver */ @@ -540,12 +1188,53 @@ static acpi_status nirtfeatures_resources(struct acpi_resource *res, void *data) return AE_OK; } +/* Process a notification from ACPI, which typically occurs when a switch + * PIE is signalling a change of state via its GPE. + */ +static void nirtfeatures_acpi_notify(struct acpi_device *device, u32 event) +{ + /* find the switch PIE for which this notification was generated, + * and push an event into its associated input subsystem node + */ + struct nirtfeatures_switch *iter; + int state = 0; + struct nirtfeatures *nirtfeatures = + (struct nirtfeatures *)device->driver_data; + + spin_lock(&nirtfeatures->lock); + + list_for_each_entry(iter, &nirtfeatures_switch_pie_list, node) { + if (event == iter->pie_descriptor.notification_value) { + + /* query instantaneous switch state */ + if (!nirtfeatures_pie_get_state(iter->nirtfeatures, + iter->pie_location.element, + iter->pie_location.subelement, + &state)) { + /* push current state of switch */ + input_report_key(iter->cdev, BTN_0, !!state); + input_sync(iter->cdev); + } + spin_unlock(&nirtfeatures->lock); + return; + } + } + + spin_unlock(&nirtfeatures->lock); + + dev_err(&device->dev, "no input found for notification (event %02X)\n", + event); +} + static int nirtfeatures_acpi_remove(struct acpi_device *device) { struct nirtfeatures *nirtfeatures = device->driver_data; nirtfeatures_remove_leds(nirtfeatures); + nirtfeatures_remove_led_pies(nirtfeatures); + nirtfeatures_remove_switch_pies(nirtfeatures); + sysfs_remove_files(&nirtfeatures->acpi_device->dev.kobj, nirtfeatures_attrs); @@ -602,15 +1291,9 @@ static int nirtfeatures_acpi_add(struct acpi_device *device) break; case NIRTF_PLATFORM_MISC_ID_HAMMERHEAD: nirtfeatures->bpstring = "Hammerhead"; - nirtfeatures->extra_leds = nirtfeatures_leds_cdaq; - nirtfeatures->num_extra_leds = - ARRAY_SIZE(nirtfeatures_leds_cdaq); break; case NIRTF_PLATFORM_MISC_ID_WINGHEAD: nirtfeatures->bpstring = "Winghead"; - nirtfeatures->extra_leds = nirtfeatures_leds_cdaq; - nirtfeatures->num_extra_leds = - ARRAY_SIZE(nirtfeatures_leds_cdaq); break; default: dev_err(&nirtfeatures->acpi_device->dev, @@ -622,6 +1305,12 @@ static int nirtfeatures_acpi_add(struct acpi_device *device) spin_lock_init(&nirtfeatures->lock); + err = nirtfeatures_populate_pies(nirtfeatures); + if (0 != err) { + nirtfeatures_acpi_remove(device); + return err; + } + nirtfeatures->revision[0] = inb(nirtfeatures->io_base + NIRTF_YEAR); nirtfeatures->revision[1] = inb(nirtfeatures->io_base + NIRTF_MONTH); nirtfeatures->revision[2] = inb(nirtfeatures->io_base + NIRTF_DAY); @@ -660,6 +1349,7 @@ static struct acpi_driver nirtfeatures_acpi_driver = { .ops = { .add = nirtfeatures_acpi_add, .remove = nirtfeatures_acpi_remove, + .notify = nirtfeatures_acpi_notify, }, }; From d66de096114ae85f7e768fa17cd4ff6228fcb08f Mon Sep 17 00:00:00 2001 From: Nathan Sullivan Date: Tue, 29 Sep 2015 12:45:12 -0500 Subject: [PATCH 020/110] nirtfeatures: Don't rename wifi LEDs For compatibility with myRIO, don't change the name of the wireless PIE LEDs. Signed-off-by: Nathan Sullivan Reviewed-by: Jaeden Amero Reviewed-by: Josh Cartwright Natinst-ReviewBoard-ID: 107067 Natinst-CAR-ID: 540272 --- drivers/misc/nirtfeatures.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/drivers/misc/nirtfeatures.c b/drivers/misc/nirtfeatures.c index cce1c53d6252f..bc2a679c841f0 100644 --- a/drivers/misc/nirtfeatures.c +++ b/drivers/misc/nirtfeatures.c @@ -762,9 +762,10 @@ static int nirtfeatures_parse_led_pie( return -ENOMEM; /* for compatibility with existing LVRT support, PIEs beginning - * with 'user' should not affix the uservisible attribute to - * their name */ - if (strncasecmp(pie->name, "user", strlen("user")) != 0) { + * with 'user' or 'wifi' should not affix the uservisible + * attribute to their name */ + if (strncasecmp(pie->name, "user", strlen("user")) != 0 && + strncasecmp(pie->name, "wifi", strlen("wifi")) != 0) { snprintf(led_dev->name_string, MAX_NODELEN, "%s:%s:%s:uservisible=%d", CONFIG_NI_LED_PREFIX, From 0cbe7f11f5dacbd0eb7862f277846f3e799592f5 Mon Sep 17 00:00:00 2001 From: James Minor Date: Tue, 9 Aug 2016 13:50:02 -0500 Subject: [PATCH 021/110] nirtfeatures: Add control for WiFi reset as a vmmc regulator The MMC driver will enable/disable external regulators as part of enabling/disabling the SD Host Controller. The WLAN_PWD_L line (controlled from the CPLD) must be enabled/disabled at the same time that the controller is enabled/disabled. Allow the MMC driver to just control that pin directly via the regulator framework. Signed-off-by: James Minor --- drivers/misc/Kconfig | 1 + drivers/misc/nirtfeatures.c | 127 +++++++++++++++++++++++++++++++++++- 2 files changed, 126 insertions(+), 2 deletions(-) diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig index c18e8bc0f7450..a3b92c8eca2ce 100644 --- a/drivers/misc/Kconfig +++ b/drivers/misc/Kconfig @@ -469,6 +469,7 @@ config HISI_HIKEY_USB config NI_RT_FEATURES bool "NI 903x/913x support" depends on X86 && ACPI + select REGULATOR help This driver exposes LEDs and other features of NI 903x/913x Real-Time controllers. diff --git a/drivers/misc/nirtfeatures.c b/drivers/misc/nirtfeatures.c index bc2a679c841f0..0c8587c54041d 100644 --- a/drivers/misc/nirtfeatures.c +++ b/drivers/misc/nirtfeatures.c @@ -18,6 +18,8 @@ #include #include #include +#include +#include #define MODULE_NAME "nirtfeatures" @@ -36,6 +38,7 @@ #define NIRTF_STATUS_LED_SHIFT1 0x21 #define NIRTF_STATUS_LED_SHIFT0 0x22 #define NIRTF_RT_LEDS 0x23 +#define NIRTF_WLAN_CONTROLREG 0x32 #define NIRTF_IO_SIZE 0x40 @@ -59,6 +62,9 @@ #define NIRTF_SYSTEM_LEDS_POWER_GREEN 0x02 #define NIRTF_SYSTEM_LEDS_POWER_YELLOW 0x01 +#define NIRTF_WLAN_RESET_N 0x02 +#define NIRTF_WLAN_RESETENABLE 0x01 + /*===================================================================== * ACPI NI physical interface element support *===================================================================*/ @@ -112,6 +118,8 @@ struct nirtfeatures { spinlock_t lock; u8 revision[5]; const char *bpstring; + bool has_wifi; + struct regulator_dev *reg_dev; }; struct nirtfeatures_led { @@ -733,6 +741,7 @@ static int nirtfeatures_parse_led_pie( struct nirtfeatures_pie_descriptor_led_color led_descriptor; struct nirtfeatures_led *led_dev; int err; + int is_wifi, is_user; if (NULL == nirtfeatures || NULL == pie || NULL == acpi_buffer) @@ -764,8 +773,10 @@ static int nirtfeatures_parse_led_pie( /* for compatibility with existing LVRT support, PIEs beginning * with 'user' or 'wifi' should not affix the uservisible * attribute to their name */ - if (strncasecmp(pie->name, "user", strlen("user")) != 0 && - strncasecmp(pie->name, "wifi", strlen("wifi")) != 0) { + is_user = strncasecmp(pie->name, "user", strlen("user")); + is_wifi = strncasecmp(pie->name, "wifi", strlen("wifi")); + if (is_user != 0 && + is_wifi != 0) { snprintf(led_dev->name_string, MAX_NODELEN, "%s:%s:%s:uservisible=%d", CONFIG_NI_LED_PREFIX, @@ -778,6 +789,10 @@ static int nirtfeatures_parse_led_pie( pie->name, led_descriptor.name); } + /* The presence of any WiFi LED means this target has wifi */ + if (is_wifi == 0) + nirtfeatures->has_wifi = true; + led_dev->cdev.name = led_dev->name_string; led_dev->cdev.brightness = led_descriptor.brightness_range_low; @@ -1239,6 +1254,9 @@ static int nirtfeatures_acpi_remove(struct acpi_device *device) sysfs_remove_files(&nirtfeatures->acpi_device->dev.kobj, nirtfeatures_attrs); + if (nirtfeatures->reg_dev) + regulator_unregister(nirtfeatures->reg_dev); + if ((nirtfeatures->io_base != 0) && (nirtfeatures->io_size == NIRTF_IO_SIZE)) release_region(nirtfeatures->io_base, nirtfeatures->io_size); @@ -1250,6 +1268,102 @@ static int nirtfeatures_acpi_remove(struct acpi_device *device) return 0; } +static int nirtfeatures_wifi_regulator_list_voltage(struct regulator_dev *dev, + unsigned selector) +{ + return 3300000; +} + +static int nirtfeatures_wifi_regulator_enable(struct regulator_dev *dev) +{ + struct nirtfeatures *nirtfeatures; + + nirtfeatures = rdev_get_drvdata(dev); + + /* WiFi out of Reset */ + outb(NIRTF_WLAN_RESET_N | NIRTF_WLAN_RESETENABLE, + nirtfeatures->io_base + NIRTF_WLAN_CONTROLREG); + /* WiFi Reset Disable */ + outb(NIRTF_WLAN_RESET_N, + nirtfeatures->io_base + NIRTF_WLAN_CONTROLREG); + + return 0; +} + +static int nirtfeatures_wifi_regulator_disable(struct regulator_dev *dev) +{ + struct nirtfeatures *nirtfeatures; + + nirtfeatures = rdev_get_drvdata(dev); + + /* WiFi Reset Enable */ + outb(NIRTF_WLAN_RESET_N | NIRTF_WLAN_RESETENABLE, + nirtfeatures->io_base + NIRTF_WLAN_CONTROLREG); + /* WiFi into Reset */ + outb(NIRTF_WLAN_RESETENABLE, + nirtfeatures->io_base + NIRTF_WLAN_CONTROLREG); + + /* Silex specs say to assert reset for 5 us, make it 10 to be sure */ + usleep_range(10, 1000); + + return 0; +} + +static int nirtfeatures_wifi_regulator_is_enabled(struct regulator_dev *dev) +{ + struct nirtfeatures *nirtfeatures; + u8 data; + + nirtfeatures = rdev_get_drvdata(dev); + + data = inb(nirtfeatures->io_base + NIRTF_WLAN_CONTROLREG); + + return !!(data & NIRTF_WLAN_RESET_N); +} + +static struct regulator_ops nirtfeatures_wifi_regulator_voltage_ops = { + .list_voltage = nirtfeatures_wifi_regulator_list_voltage, + .enable = nirtfeatures_wifi_regulator_enable, + .disable = nirtfeatures_wifi_regulator_disable, + .is_enabled = nirtfeatures_wifi_regulator_is_enabled +}; + +static const struct regulator_desc nirtfeatures_wifi_regulator_desc = { + .name = "vmmc", + .id = -1, + .n_voltages = 1, + .ops = &nirtfeatures_wifi_regulator_voltage_ops, + .type = REGULATOR_VOLTAGE, + .owner = THIS_MODULE +}; + +static const struct regulator_init_data wifi_reset_init_data = { + .constraints = { + .min_uV = 3300000, + .max_uV = 3300000, + .valid_ops_mask = REGULATOR_CHANGE_STATUS, + } +}; + +static int nirtfeatures_wifi_regulator_init(struct device *dev, + struct nirtfeatures *nirtfeatures) +{ + struct regulator_config cfg = { }; + struct regulator_dev *reg_dev; + + cfg.dev = dev; + cfg.init_data = &wifi_reset_init_data; + cfg.driver_data = nirtfeatures; + reg_dev = regulator_register(&nirtfeatures_wifi_regulator_desc, + &cfg); + if (IS_ERR(reg_dev)) { + pr_err("Failed to register vmmc regulator for wifi\n"); + return -ENODEV; + } + nirtfeatures->reg_dev = reg_dev; + return 0; +} + static int nirtfeatures_acpi_add(struct acpi_device *device) { struct nirtfeatures *nirtfeatures; @@ -1336,6 +1450,15 @@ static int nirtfeatures_acpi_add(struct acpi_device *device) nirtfeatures->io_base, nirtfeatures->io_base + nirtfeatures->io_size - 1); + if (nirtfeatures->has_wifi) { + err = nirtfeatures_wifi_regulator_init(&device->dev, + nirtfeatures); + if (0 != err) { + nirtfeatures_acpi_remove(device); + return err; + } + } + return 0; } From 1fa8d1ad181be4281d58b27fb4d204b06940b061 Mon Sep 17 00:00:00 2001 From: Kyle Roeschley Date: Fri, 9 Sep 2016 13:07:35 -0500 Subject: [PATCH 022/110] nirtfeatures: Add Fire Eagle backplane ID Add the new Fire Eagle backplane ID so we stop complaining on boot. Signed-off-by: Kyle Roeschley Signed-off-by: Brad Mouring Acked-by: Xander Huff Natinst-ReviewBoard-ID: 152156 --- drivers/misc/nirtfeatures.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/misc/nirtfeatures.c b/drivers/misc/nirtfeatures.c index 0c8587c54041d..414ce7df12f72 100644 --- a/drivers/misc/nirtfeatures.c +++ b/drivers/misc/nirtfeatures.c @@ -46,6 +46,7 @@ #define NIRTF_PLATFORM_MISC_ID_MASK 0x07 #define NIRTF_PLATFORM_MISC_ID_MANHATTAN 0 +#define NIRTF_PLATFORM_MISC_ID_FIRE_EAGLE 2 #define NIRTF_PLATFORM_MISC_ID_HAMMERHEAD 4 #define NIRTF_PLATFORM_MISC_ID_WINGHEAD 5 @@ -1404,6 +1405,9 @@ static int nirtfeatures_acpi_add(struct acpi_device *device) case NIRTF_PLATFORM_MISC_ID_MANHATTAN: nirtfeatures->bpstring = "Manhattan"; break; + case NIRTF_PLATFORM_MISC_ID_FIRE_EAGLE: + nirtfeatures->bpstring = "Fire Eagle"; + break; case NIRTF_PLATFORM_MISC_ID_HAMMERHEAD: nirtfeatures->bpstring = "Hammerhead"; break; From de2daea47e67a90df931dc7a05ac92d90dbbbe76 Mon Sep 17 00:00:00 2001 From: Xander Huff Date: Fri, 14 Oct 2016 13:54:00 -0500 Subject: [PATCH 023/110] nirtfeatures: Housecleaning of comments, comparisons, etc. Fix checkpatch warnings: Block comments use * on subsequent lines Block comments use a trailing */ on a separate line Comparisons should place the constant on the right side of the test break is not useful after a goto or return Signed-off-by: Xander Huff Natinst-ReviewBoard-ID: 157395 --- drivers/misc/nirtfeatures.c | 107 ++++++++++++++++++------------------ 1 file changed, 55 insertions(+), 52 deletions(-) diff --git a/drivers/misc/nirtfeatures.c b/drivers/misc/nirtfeatures.c index 414ce7df12f72..41b2c63e86c24 100644 --- a/drivers/misc/nirtfeatures.c +++ b/drivers/misc/nirtfeatures.c @@ -68,7 +68,8 @@ /*===================================================================== * ACPI NI physical interface element support - *===================================================================*/ + *===================================================================== + */ #define MAX_NAMELEN 64 #define MAX_NODELEN 128 #define MIN_PIE_CAPS_VERSION 2 @@ -444,7 +445,8 @@ nirtfeatures_led_brightness_get(struct led_classdev *led_cdev) data = inb(led->nirtfeatures->io_base + led->address); /* For the yellow status LED, the blink pattern used for brightness - on write is write-only, so we just return on/off for all LEDs. */ + * on write is write-only, so we just return on/off for all LEDs. + */ return (data & led->mask) ? LED_FULL : LED_OFF; } @@ -484,7 +486,8 @@ static struct nirtfeatures_led nirtfeatures_leds_common[] = { /*===================================================================== * ACPI NI physical interface element support - *===================================================================*/ + *===================================================================== + */ /* Note that callers of this function are responsible for deallocating * the buffer allocated by acpi_evaluate_object() by calling @@ -502,8 +505,8 @@ static int nirtfeatures_call_acpi_method(struct nirtfeatures *nirtfeatures, struct acpi_object_list acpi_params; struct acpi_buffer acpi_result = { ACPI_ALLOCATE_BUFFER, NULL }; - if (NULL == nirtfeatures || NULL == result_size || - NULL == result_buffer) + if (nirtfeatures == NULL || result_size == NULL || + result_buffer == NULL) return -EINVAL; acpi_ret = acpi_get_handle(nirtfeatures->acpi_device->handle, @@ -544,7 +547,7 @@ static int nirtfeatures_pie_set_state(struct nirtfeatures *nirtfeatures, union acpi_object *acpi_buffer; int err = 0; - if (NULL == nirtfeatures) + if (nirtfeatures == NULL) return -EINVAL; pies_args[0].type = ACPI_TYPE_INTEGER; @@ -560,7 +563,7 @@ static int nirtfeatures_pie_set_state(struct nirtfeatures *nirtfeatures, if (err == 0) { acpi_buffer = (union acpi_object *) result_buffer; - if (ACPI_TYPE_INTEGER == acpi_buffer->type) + if (acpi_buffer->type == ACPI_TYPE_INTEGER) err = (int) acpi_buffer->integer.value; kfree(result_buffer); } @@ -580,7 +583,7 @@ static int nirtfeatures_pie_get_state(struct nirtfeatures *nirtfeatures, union acpi_object *acpi_buffer; int err = 0; - if (NULL == nirtfeatures || NULL == result) + if (nirtfeatures == NULL || result == NULL) return -EINVAL; pies_args[0].type = ACPI_TYPE_INTEGER; @@ -594,7 +597,7 @@ static int nirtfeatures_pie_get_state(struct nirtfeatures *nirtfeatures, if (err == 0) { acpi_buffer = (union acpi_object *) result_buffer; - if (ACPI_TYPE_INTEGER == acpi_buffer->type) + if (acpi_buffer->type == ACPI_TYPE_INTEGER) *result = (int) acpi_buffer->integer.value; kfree(result_buffer); } @@ -615,7 +618,7 @@ static int nirtfeatures_pie_enable_notifications( union acpi_object *acpi_buffer; int err = 0; - if (NULL == nirtfeatures) + if (nirtfeatures == NULL) return -EINVAL; pies_args[0].type = ACPI_TYPE_INTEGER; @@ -631,7 +634,7 @@ static int nirtfeatures_pie_enable_notifications( if (err == 0) { acpi_buffer = (union acpi_object *) result_buffer; - if (ACPI_TYPE_INTEGER == acpi_buffer->type) + if (acpi_buffer->type == ACPI_TYPE_INTEGER) err = (int) acpi_buffer->integer.value; kfree(result_buffer); } @@ -691,12 +694,12 @@ static int nirtfeatures_parse_led_pie_color(struct nirtfeatures *nirtfeatures, { unsigned int i; - if (NULL == nirtfeatures || NULL == led_color_descriptor || - NULL == acpi_buffer) + if (nirtfeatures == NULL || led_color_descriptor == NULL || + acpi_buffer == NULL) return -EINVAL; /* element 0 of a PIE LED color caps package is the name */ - if (ACPI_TYPE_BUFFER == acpi_buffer->package.elements[0].type) { + if (acpi_buffer->package.elements[0].type == ACPI_TYPE_BUFFER) { for (i = 0; i < acpi_buffer->package.elements[0].buffer.length; i++) { /* get pointer to Nth Unicode character in name */ @@ -711,14 +714,14 @@ static int nirtfeatures_parse_led_pie_color(struct nirtfeatures *nirtfeatures, return -EINVAL; /* element 1 is the brightness min value */ - if (ACPI_TYPE_INTEGER == acpi_buffer->package.elements[1].type) + if (acpi_buffer->package.elements[1].type == ACPI_TYPE_INTEGER) led_color_descriptor->brightness_range_low = (int) acpi_buffer->package.elements[1].integer.value; else return -EINVAL; /* element 2 is the brightness max value */ - if (ACPI_TYPE_INTEGER == acpi_buffer->package.elements[2].type) + if (acpi_buffer->package.elements[2].type == ACPI_TYPE_INTEGER) led_color_descriptor->brightness_range_high = (int) acpi_buffer->package.elements[2].integer.value; else @@ -744,15 +747,15 @@ static int nirtfeatures_parse_led_pie( int err; int is_wifi, is_user; - if (NULL == nirtfeatures || NULL == pie || - NULL == acpi_buffer) + if (nirtfeatures == NULL || pie == NULL || + acpi_buffer == NULL) return -EINVAL; - if (ACPI_TYPE_PACKAGE != acpi_buffer->type) + if (acpi_buffer->type != ACPI_TYPE_PACKAGE) return -EINVAL; /* element 0 is the number of colors */ - if (ACPI_TYPE_INTEGER == acpi_buffer->package.elements[0].type) { + if (acpi_buffer->package.elements[0].type == ACPI_TYPE_INTEGER) { num_colors = (unsigned int) acpi_buffer->package.elements[0].integer.value; } else { @@ -768,12 +771,13 @@ static int nirtfeatures_parse_led_pie( /* create an LED class device for this LED */ led_dev = kzalloc(sizeof(struct nirtfeatures_led), GFP_KERNEL); - if (NULL == led_dev) + if (led_dev == NULL) return -ENOMEM; /* for compatibility with existing LVRT support, PIEs beginning * with 'user' or 'wifi' should not affix the uservisible - * attribute to their name */ + * attribute to their name + */ is_user = strncasecmp(pie->name, "user", strlen("user")); is_wifi = strncasecmp(pie->name, "wifi", strlen("wifi")); if (is_user != 0 && @@ -809,7 +813,7 @@ static int nirtfeatures_parse_led_pie( err = led_classdev_register(&nirtfeatures->acpi_device->dev, &led_dev->cdev); - if (0 != err) { + if (err != 0) { kfree(led_dev); return err; } @@ -835,14 +839,14 @@ static int nirtfeatures_parse_switch_pie(struct nirtfeatures *nirtfeatures, struct nirtfeatures_switch *switch_dev = NULL; int err = 0; - if (NULL == nirtfeatures || NULL == pie || NULL == acpi_buffer) + if (nirtfeatures == NULL || pie == NULL || acpi_buffer == NULL) return -EINVAL; - if (ACPI_TYPE_PACKAGE != acpi_buffer->type) + if (acpi_buffer->type != ACPI_TYPE_PACKAGE) return -EINVAL; /* element 0 is the number of states */ - if (ACPI_TYPE_INTEGER == acpi_buffer->package.elements[0].type) + if (acpi_buffer->package.elements[0].type == ACPI_TYPE_INTEGER) num_states = (unsigned int) acpi_buffer->package.elements[0].integer.value; else @@ -852,15 +856,15 @@ static int nirtfeatures_parse_switch_pie(struct nirtfeatures *nirtfeatures, switch_descriptor = kzalloc( sizeof(struct nirtfeatures_pie_descriptor_switch) + sizeof(int) * (num_states - 1), GFP_KERNEL); - if (NULL == switch_descriptor) + if (switch_descriptor == NULL) return -ENOMEM; switch_descriptor->num_states = num_states; /* parse individual states in elements 1..N-1 */ for (i = 0; i < num_states; i++) { - if (ACPI_TYPE_INTEGER != - acpi_buffer->package.elements[i + 1].type) { + if (acpi_buffer->package.elements[i + 1].type + != ACPI_TYPE_INTEGER) { err = -EINVAL; goto exit; } @@ -871,13 +875,13 @@ static int nirtfeatures_parse_switch_pie(struct nirtfeatures *nirtfeatures, /* create an input class device for this switch */ switch_dev = kzalloc(sizeof(struct nirtfeatures_switch), GFP_KERNEL); - if (NULL == switch_dev) { + if (switch_dev == NULL) { err = -ENOMEM; goto exit; } switch_dev->cdev = input_allocate_device(); - if (NULL == switch_dev->cdev) { + if (switch_dev->cdev == NULL) { err = -ENOMEM; goto exit_dealloc_switch_dev; } @@ -914,7 +918,7 @@ static int nirtfeatures_parse_switch_pie(struct nirtfeatures *nirtfeatures, set_bit(BTN_0, switch_dev->cdev->keybit); err = input_register_device(switch_dev->cdev); - if (0 != err) { + if (err != 0) { input_free_device(switch_dev->cdev); goto exit_dealloc_switch_dev; } @@ -923,7 +927,7 @@ static int nirtfeatures_parse_switch_pie(struct nirtfeatures *nirtfeatures, if (pie->notification_value != 0) { err = nirtfeatures_pie_enable_notifications(nirtfeatures, pie_element, 0, 1); - if (0 != err) { + if (err != 0) { input_unregister_device(switch_dev->cdev); input_free_device(switch_dev->cdev); goto exit_dealloc_switch_dev; @@ -954,16 +958,16 @@ static int nirtfeatures_parse_one_pie(struct nirtfeatures *nirtfeatures, struct nirtfeatures_pie_descriptor pie; unsigned int i; - if (NULL == nirtfeatures || NULL == acpi_buffer) + if (nirtfeatures == NULL || acpi_buffer == NULL) return -EINVAL; /* check for proper type and number of elements */ - if (ACPI_TYPE_PACKAGE != acpi_buffer->type || - 6 != acpi_buffer->package.count) + if (acpi_buffer->type != ACPI_TYPE_PACKAGE || + acpi_buffer->package.count != 6) return -EINVAL; /* element 0 of the package is the name */ - if (ACPI_TYPE_BUFFER == acpi_buffer->package.elements[0].type) { + if (acpi_buffer->package.elements[0].type == ACPI_TYPE_BUFFER) { for (i = 0; i < acpi_buffer->package.elements[0].buffer.length && i < MAX_NAMELEN; i++) { @@ -978,28 +982,28 @@ static int nirtfeatures_parse_one_pie(struct nirtfeatures *nirtfeatures, return -EINVAL; /* element 1 of the package is the PIE class */ - if (ACPI_TYPE_INTEGER == acpi_buffer->package.elements[1].type) + if (acpi_buffer->package.elements[1].type == ACPI_TYPE_INTEGER) pie.pie_class = (enum nirtfeatures_pie_class) acpi_buffer->package.elements[1].integer.value; else return -EINVAL; /* element 2 of the package is the PIE type */ - if (ACPI_TYPE_INTEGER == acpi_buffer->package.elements[2].type) + if (acpi_buffer->package.elements[2].type == ACPI_TYPE_INTEGER) pie.pie_type = (enum nirtfeatures_pie_type) acpi_buffer->package.elements[2].integer.value; else return -EINVAL; /* element 4 of an package is the visible flag */ - if (ACPI_TYPE_INTEGER == acpi_buffer->package.elements[4].type) + if (acpi_buffer->package.elements[4].type == ACPI_TYPE_INTEGER) pie.is_user_visible = (acpi_buffer->package.elements[4].integer.value != 0); else return -EINVAL; /* element 5 of the package is the notification value */ - if (ACPI_TYPE_INTEGER == acpi_buffer->package.elements[5].type) + if (acpi_buffer->package.elements[5].type == ACPI_TYPE_INTEGER) pie.notification_value = acpi_buffer->package.elements[5].integer.value; else @@ -1022,7 +1026,6 @@ static int nirtfeatures_parse_one_pie(struct nirtfeatures *nirtfeatures, default: return -EINVAL; - break; } return 0; @@ -1041,7 +1044,7 @@ static int nirtfeatures_populate_pies(struct nirtfeatures *nirtfeatures) unsigned int i; unsigned int err = 0; - if (NULL == nirtfeatures) + if (nirtfeatures == NULL) return -EINVAL; /* get the PIE descriptor buffer from DSDT */ @@ -1050,13 +1053,13 @@ static int nirtfeatures_populate_pies(struct nirtfeatures *nirtfeatures) return -1; acpi_buffer = (union acpi_object *) result_buffer; - if (ACPI_TYPE_PACKAGE != acpi_buffer->type) { + if (acpi_buffer->type != ACPI_TYPE_PACKAGE) { err = -1; goto exit; } /* the first element of the package is the caps version */ - if (ACPI_TYPE_INTEGER == acpi_buffer->package.elements[0].type) + if (acpi_buffer->package.elements[0].type == ACPI_TYPE_INTEGER) pie_caps_version = (unsigned int) acpi_buffer->package.elements[0].integer.value; else { @@ -1073,7 +1076,7 @@ static int nirtfeatures_populate_pies(struct nirtfeatures *nirtfeatures) } /* the second element of the package is the number of PIEs */ - if (ACPI_TYPE_INTEGER == acpi_buffer->package.elements[1].type) + if (acpi_buffer->package.elements[1].type == ACPI_TYPE_INTEGER) num_elements = (unsigned int) acpi_buffer->package.elements[1].integer.value; else { @@ -1086,7 +1089,7 @@ static int nirtfeatures_populate_pies(struct nirtfeatures *nirtfeatures) err = nirtfeatures_parse_one_pie(nirtfeatures, pie_caps_version, i - 2, &(acpi_buffer->package.elements[i])); - if (0 != err) + if (err != 0) break; } @@ -1104,7 +1107,7 @@ static int nirtfeatures_create_leds(struct nirtfeatures *nirtfeatures) nirtfeatures_leds_common[i].nirtfeatures = nirtfeatures; - if (0 == nirtfeatures_leds_common[i].cdev.max_brightness) + if (nirtfeatures_leds_common[i].cdev.max_brightness == 0) nirtfeatures_leds_common[i].cdev.max_brightness = 1; nirtfeatures_leds_common[i].cdev.brightness_set = @@ -1425,7 +1428,7 @@ static int nirtfeatures_acpi_add(struct acpi_device *device) spin_lock_init(&nirtfeatures->lock); err = nirtfeatures_populate_pies(nirtfeatures); - if (0 != err) { + if (err != 0) { nirtfeatures_acpi_remove(device); return err; } @@ -1438,13 +1441,13 @@ static int nirtfeatures_acpi_add(struct acpi_device *device) err = sysfs_create_files(&nirtfeatures->acpi_device->dev.kobj, nirtfeatures_attrs); - if (0 != err) { + if (err != 0) { nirtfeatures_acpi_remove(device); return err; } err = nirtfeatures_create_leds(nirtfeatures); - if (0 != err) { + if (err != 0) { nirtfeatures_acpi_remove(device); return err; } @@ -1457,7 +1460,7 @@ static int nirtfeatures_acpi_add(struct acpi_device *device) if (nirtfeatures->has_wifi) { err = nirtfeatures_wifi_regulator_init(&device->dev, nirtfeatures); - if (0 != err) { + if (err != 0) { nirtfeatures_acpi_remove(device); return err; } From 11e8770c8fe5823d6fb1c2eaa7b24cdb2df25022 Mon Sep 17 00:00:00 2001 From: Akash Mankar Date: Fri, 17 Feb 2017 16:52:58 -0600 Subject: [PATCH 024/110] nirtfeatures: Implement serial IRQ mechanism for user push button. This commit assumes that BIOS will implement a change to add a new field to PIEC capability structure. Also bumping the capabilities version by 1. Adding IRQ mechanism for user Push button instead of GPIO This change registers and requests an IRQ for User push button.Adds a new handler pushbutton_interrupt_handler() to handle the interrupt when the button is pressed or released. Adds a new field to struct nirtfeatures_pie_descriptor called notification_method. If this field is 1, it indicates interrupt mechanism. We check this field only for caps version=3 and pie_type=switch. Also bumps the MAX_PIE_CAPS_VERSION to 3. The kernel and BIOS have to be updated at the same time in order for this change to be successful. If kernel is updated first on a controller, user button will simply not function but will have no other side effects. If BIOS is updated first, then system will end in kernel panic and reboot constantly. Signed-off-by: Akash Mankar Signed-off-by: Brad Mouring Acked-by: Zach Hindes Acked-by: Aaron Rossetto Natinst-ReviewBoard-ID: 174593 --- drivers/misc/nirtfeatures.c | 85 ++++++++++++++++++++++++++++++++++--- 1 file changed, 80 insertions(+), 5 deletions(-) diff --git a/drivers/misc/nirtfeatures.c b/drivers/misc/nirtfeatures.c index 41b2c63e86c24..53c8b012ebbd0 100644 --- a/drivers/misc/nirtfeatures.c +++ b/drivers/misc/nirtfeatures.c @@ -13,6 +13,7 @@ */ #include +#include #include #include #include @@ -73,7 +74,9 @@ #define MAX_NAMELEN 64 #define MAX_NODELEN 128 #define MIN_PIE_CAPS_VERSION 2 -#define MAX_PIE_CAPS_VERSION 2 +#define MAX_PIE_CAPS_VERSION 3 +#define NOTIFY_METHOD_INTERRUPT 1 +#define NOTIFY_METHOD_GPIO 0 enum nirtfeatures_pie_class { PIE_CLASS_INPUT = 0, @@ -92,6 +95,8 @@ struct nirtfeatures_pie_descriptor { enum nirtfeatures_pie_type pie_type; bool is_user_visible; unsigned int notification_value; + /* notification_method applicable only for caps version 3 & above */ + unsigned int notification_method; }; struct nirtfeatures_pie_descriptor_led_color { @@ -122,6 +127,7 @@ struct nirtfeatures { const char *bpstring; bool has_wifi; struct regulator_dev *reg_dev; + unsigned int irq; }; struct nirtfeatures_led { @@ -961,9 +967,14 @@ static int nirtfeatures_parse_one_pie(struct nirtfeatures *nirtfeatures, if (nirtfeatures == NULL || acpi_buffer == NULL) return -EINVAL; - /* check for proper type and number of elements */ + /* + * check for proper type and number of elements + * caps_version 2 or less, support only 6 elements in package + * caps_version 3 or more, support only up to 7 elements in package + */ if (acpi_buffer->type != ACPI_TYPE_PACKAGE || - acpi_buffer->package.count != 6) + (acpi_buffer->package.count != 6 && pie_caps_version < 3) || + (acpi_buffer->package.count > 7 && pie_caps_version >= 3)) return -EINVAL; /* element 0 of the package is the name */ @@ -1005,10 +1016,23 @@ static int nirtfeatures_parse_one_pie(struct nirtfeatures *nirtfeatures, /* element 5 of the package is the notification value */ if (acpi_buffer->package.elements[5].type == ACPI_TYPE_INTEGER) pie.notification_value = - acpi_buffer->package.elements[5].integer.value; + acpi_buffer->package.elements[5].integer.value; else return -EINVAL; + /* + * element 6 of the package is notification method + * used only for pie type switch and caps_Version >= 3 + * don't worry about it for lower caps versions. + */ + if (pie_caps_version >= 3 && pie.pie_type == PIE_TYPE_SWITCH) { + if (acpi_buffer->package.elements[6].type == ACPI_TYPE_INTEGER) + pie.notification_method = + acpi_buffer->package.elements[6].integer.value; + else + return -EINVAL; + } + /* parse the type-specific descriptor in element 3 */ switch (pie.pie_type) { case PIE_TYPE_LED: @@ -1175,13 +1199,64 @@ static void nirtfeatures_remove_switch_pies(struct nirtfeatures *nirtfeatures) spin_unlock(&nirtfeatures->lock); } +/* IRQ Handler for User push button */ +static irqreturn_t pushbutton_interrupt_handler(int irq, void *data) +{ + /* find the switch PIE for which this interrupt was generated */ + struct nirtfeatures_switch *iter; + struct nirtfeatures *nirtfeatures = (struct nirtfeatures *)data; + int state = 0; + + spin_lock(&nirtfeatures->lock); + list_for_each_entry(iter, &nirtfeatures_switch_pie_list, node) { + if (iter->pie_descriptor.notification_method == NOTIFY_METHOD_INTERRUPT && + iter->pie_descriptor.notification_value == irq) { + /* query instantaneous switch state */ + if (!nirtfeatures_pie_get_state(iter->nirtfeatures, + iter->pie_location.element, + iter->pie_location.subelement, + &state)) { + /* push current state of switch */ + input_report_key(iter->cdev, BTN_0, !!state); + input_sync(iter->cdev); + } + spin_unlock(&nirtfeatures->lock); + return IRQ_HANDLED; + } + } + spin_unlock(&nirtfeatures->lock); + return IRQ_NONE; +} + /* ACPI driver */ static acpi_status nirtfeatures_resources(struct acpi_resource *res, void *data) { struct nirtfeatures *nirtfeatures = data; + int err; switch (res->type) { + case ACPI_RESOURCE_TYPE_IRQ: + if (nirtfeatures->irq != 0) { + dev_err(&nirtfeatures->acpi_device->dev, + "too many IRQ resources\n"); + return AE_ERROR; + } + + nirtfeatures->irq = res->data.irq.interrupts[0]; + + err = devm_request_irq(&nirtfeatures->acpi_device->dev, + nirtfeatures->irq, + pushbutton_interrupt_handler, + 0 /*irq_flags*/, MODULE_NAME, + nirtfeatures); + if (err) { + dev_err(&nirtfeatures->acpi_device->dev, + "failed to request IRQ (err %d)\n", err); + return AE_ERROR; + } + return AE_OK; + case ACPI_RESOURCE_TYPE_IO: if ((nirtfeatures->io_base != 0) || (nirtfeatures->io_size != 0)) { @@ -1385,7 +1460,7 @@ static int nirtfeatures_acpi_add(struct acpi_device *device) nirtfeatures->acpi_device = device; acpi_ret = acpi_walk_resources(device->handle, METHOD_NAME__CRS, - nirtfeatures_resources, nirtfeatures); + nirtfeatures_resources, nirtfeatures); if (ACPI_FAILURE(acpi_ret) || (nirtfeatures->io_base == 0) || From 1477bfdd5a9aedbb8da589e14de07d75d6ee14a2 Mon Sep 17 00:00:00 2001 From: Kyle Roeschley Date: Wed, 15 Feb 2017 09:12:38 -0600 Subject: [PATCH 025/110] nirtfeatures: Add Ironclad reset source string On Fire Eagle, the Ironclad ASIC has an internal watchdog which will reset the chip if the its firmware hangs. Unless we're in button- directed safemode, this will also reset the whole system. Add this reset reason to our strings so we can tell when this happens. Signed-off-by: Kyle Roeschley Signed-off-by: Brad Mouring Acked-by: James Minor Acked-by: Zach Brown Acked-by: Akash Mankar Natinst-ReviewBoard-ID: 176049 --- drivers/misc/nirtfeatures.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/misc/nirtfeatures.c b/drivers/misc/nirtfeatures.c index 53c8b012ebbd0..83711f1119c79 100644 --- a/drivers/misc/nirtfeatures.c +++ b/drivers/misc/nirtfeatures.c @@ -219,7 +219,7 @@ static ssize_t nirtfeatures_backplane_id_get(struct device *dev, static DEVICE_ATTR(backplane_id, S_IRUGO, nirtfeatures_backplane_id_get, NULL); static const char * const nirtfeatures_reset_source_strings[] = { - "button", "processor", "fpga", "watchdog", "software", + "button", "processor", "fpga", "watchdog", "software", "ironclad", }; static ssize_t nirtfeatures_reset_source_get(struct device *dev, From fa3bb2841eca0e4959ad52f1129ea60a35ed4241 Mon Sep 17 00:00:00 2001 From: Kyle Roeschley Date: Thu, 16 Mar 2017 14:13:38 -0500 Subject: [PATCH 026/110] nirtfeatures: Use managed resource allocation Adding a new ACPI resource to device BIOS exposed the fact that our error handling on a failed device probe is very broken. To fix this, use managed allocation (devm_*) for all resources which support it. Signed-off-by: Kyle Roeschley Signed-off-by: Brad Mouring Acked-by: James Minor Acked-by: Zach Brown Acked-by: Akash Mankar Natinst-ReviewBoard-ID: 176049 --- drivers/misc/nirtfeatures.c | 191 +++++++++--------------------------- 1 file changed, 48 insertions(+), 143 deletions(-) diff --git a/drivers/misc/nirtfeatures.c b/drivers/misc/nirtfeatures.c index 83711f1119c79..a97755f965567 100644 --- a/drivers/misc/nirtfeatures.c +++ b/drivers/misc/nirtfeatures.c @@ -776,7 +776,9 @@ static int nirtfeatures_parse_led_pie( return -EINVAL; /* create an LED class device for this LED */ - led_dev = kzalloc(sizeof(struct nirtfeatures_led), GFP_KERNEL); + led_dev = devm_kzalloc(&nirtfeatures->acpi_device->dev, + sizeof(struct nirtfeatures_led), + GFP_KERNEL); if (led_dev == NULL) return -ENOMEM; @@ -817,12 +819,10 @@ static int nirtfeatures_parse_led_pie( led_dev->pie_location.element = pie_element; led_dev->pie_location.subelement = i; - err = led_classdev_register(&nirtfeatures->acpi_device->dev, - &led_dev->cdev); - if (err != 0) { - kfree(led_dev); + err = devm_led_classdev_register(&nirtfeatures->acpi_device->dev, + &led_dev->cdev); + if (err) return err; - } list_add_tail(&led_dev->node, &nirtfeatures_led_pie_list); } @@ -844,6 +844,7 @@ static int nirtfeatures_parse_switch_pie(struct nirtfeatures *nirtfeatures, struct nirtfeatures_pie_descriptor_switch *switch_descriptor = NULL; struct nirtfeatures_switch *switch_dev = NULL; int err = 0; + struct device *dev = &nirtfeatures->acpi_device->dev; if (nirtfeatures == NULL || pie == NULL || acpi_buffer == NULL) return -EINVAL; @@ -859,9 +860,9 @@ static int nirtfeatures_parse_switch_pie(struct nirtfeatures *nirtfeatures, return -EINVAL; /* allocate storage for switch descriptor */ - switch_descriptor = kzalloc( - sizeof(struct nirtfeatures_pie_descriptor_switch) + - sizeof(int) * (num_states - 1), GFP_KERNEL); + switch_descriptor = devm_kzalloc(dev, sizeof(*switch_descriptor) + + sizeof(int) * (num_states - 1), + GFP_KERNEL); if (switch_descriptor == NULL) return -ENOMEM; @@ -869,28 +870,23 @@ static int nirtfeatures_parse_switch_pie(struct nirtfeatures *nirtfeatures, /* parse individual states in elements 1..N-1 */ for (i = 0; i < num_states; i++) { - if (acpi_buffer->package.elements[i + 1].type - != ACPI_TYPE_INTEGER) { - err = -EINVAL; - goto exit; - } + if (acpi_buffer->package.elements[i + 1].type != + ACPI_TYPE_INTEGER) + return -EINVAL; switch_descriptor->state_value[i] = (int) acpi_buffer->package.elements[i + 1].integer.value; } /* create an input class device for this switch */ - switch_dev = kzalloc(sizeof(struct nirtfeatures_switch), GFP_KERNEL); - if (switch_dev == NULL) { - err = -ENOMEM; - goto exit; - } + switch_dev = devm_kzalloc(dev, sizeof(struct nirtfeatures_switch), + GFP_KERNEL); + if (switch_dev == NULL) + return -ENOMEM; - switch_dev->cdev = input_allocate_device(); - if (switch_dev->cdev == NULL) { - err = -ENOMEM; - goto exit_dealloc_switch_dev; - } + switch_dev->cdev = devm_input_allocate_device(dev); + if (switch_dev->cdev == NULL) + return -ENOMEM; switch_dev->nirtfeatures = nirtfeatures; switch_dev->pie_location.element = pie_element; @@ -924,32 +920,21 @@ static int nirtfeatures_parse_switch_pie(struct nirtfeatures *nirtfeatures, set_bit(BTN_0, switch_dev->cdev->keybit); err = input_register_device(switch_dev->cdev); - if (err != 0) { - input_free_device(switch_dev->cdev); - goto exit_dealloc_switch_dev; - } + if (err) + return err; /* if this PIE supports notifications, enable them now */ if (pie->notification_value != 0) { err = nirtfeatures_pie_enable_notifications(nirtfeatures, - pie_element, 0, 1); - if (err != 0) { - input_unregister_device(switch_dev->cdev); - input_free_device(switch_dev->cdev); - goto exit_dealloc_switch_dev; - } + pie_element, 0, 1); + if (err) + return err; } /* add the new device to our list of switch PIEs */ list_add_tail(&switch_dev->node, &nirtfeatures_switch_pie_list); - goto exit; - -exit_dealloc_switch_dev: - kfree(switch_dev); -exit: - kfree(switch_descriptor); - return err; + return 0; } @@ -1140,8 +1125,8 @@ static int nirtfeatures_create_leds(struct nirtfeatures *nirtfeatures) nirtfeatures_leds_common[i].cdev.brightness_get = nirtfeatures_led_brightness_get; - err = led_classdev_register(&nirtfeatures->acpi_device->dev, - &nirtfeatures_leds_common[i].cdev); + err = devm_led_classdev_register(&nirtfeatures->acpi_device->dev, + &nirtfeatures_leds_common[i].cdev); if (err) return err; } @@ -1149,56 +1134,6 @@ static int nirtfeatures_create_leds(struct nirtfeatures *nirtfeatures) return 0; } -static void nirtfeatures_remove_leds(struct nirtfeatures *nirtfeatures) -{ - int i; - - for (i = 0; i < ARRAY_SIZE(nirtfeatures_leds_common); ++i) - led_classdev_unregister(&nirtfeatures_leds_common[i].cdev); -} - -static void nirtfeatures_remove_led_pies(struct nirtfeatures *nirtfeatures) -{ - struct nirtfeatures_led *cdev_iter; - struct nirtfeatures_led *temp; - - spin_lock(&nirtfeatures->lock); - - /* walk the list of non-fixed LEDs and unregister/free their devices */ - list_for_each_entry_safe( - cdev_iter, temp, &nirtfeatures_led_pie_list, node) { - led_classdev_unregister(&cdev_iter->cdev); - kfree(cdev_iter); - } - - spin_unlock(&nirtfeatures->lock); -} - -static void nirtfeatures_remove_switch_pies(struct nirtfeatures *nirtfeatures) -{ - struct nirtfeatures_switch *cdev_iter; - struct nirtfeatures_switch *temp; - - spin_lock(&nirtfeatures->lock); - - /* walk the list of switch devices and unregister/free each one */ - list_for_each_entry_safe( - cdev_iter, temp, &nirtfeatures_switch_pie_list, node) { - /* disable notifications for this PIE if supported */ - if (cdev_iter->pie_descriptor.notification_value != 0) { - nirtfeatures_pie_enable_notifications(nirtfeatures, - cdev_iter->pie_location.element, - cdev_iter->pie_location.subelement, - 0); - } - input_unregister_device(cdev_iter->cdev); - input_free_device(cdev_iter->cdev); - kfree(cdev_iter); - } - - spin_unlock(&nirtfeatures->lock); -} - /* IRQ Handler for User push button */ static irqreturn_t pushbutton_interrupt_handler(int irq, void *data) { @@ -1323,26 +1258,7 @@ static void nirtfeatures_acpi_notify(struct acpi_device *device, u32 event) static int nirtfeatures_acpi_remove(struct acpi_device *device) { - struct nirtfeatures *nirtfeatures = device->driver_data; - - nirtfeatures_remove_leds(nirtfeatures); - - nirtfeatures_remove_led_pies(nirtfeatures); - nirtfeatures_remove_switch_pies(nirtfeatures); - - sysfs_remove_files(&nirtfeatures->acpi_device->dev.kobj, - nirtfeatures_attrs); - - if (nirtfeatures->reg_dev) - regulator_unregister(nirtfeatures->reg_dev); - - if ((nirtfeatures->io_base != 0) && - (nirtfeatures->io_size == NIRTF_IO_SIZE)) - release_region(nirtfeatures->io_base, nirtfeatures->io_size); - - device->driver_data = NULL; - - kfree(nirtfeatures); + sysfs_remove_files(&device->dev.kobj, nirtfeatures_attrs); return 0; } @@ -1433,8 +1349,9 @@ static int nirtfeatures_wifi_regulator_init(struct device *dev, cfg.dev = dev; cfg.init_data = &wifi_reset_init_data; cfg.driver_data = nirtfeatures; - reg_dev = regulator_register(&nirtfeatures_wifi_regulator_desc, - &cfg); + reg_dev = devm_regulator_register(dev, + &nirtfeatures_wifi_regulator_desc, + &cfg); if (IS_ERR(reg_dev)) { pr_err("Failed to register vmmc regulator for wifi\n"); return -ENODEV; @@ -1450,7 +1367,8 @@ static int nirtfeatures_acpi_add(struct acpi_device *device) u8 bpinfo; int err; - nirtfeatures = kzalloc(sizeof(*nirtfeatures), GFP_KERNEL); + nirtfeatures = devm_kzalloc(&device->dev, sizeof(*nirtfeatures), + GFP_KERNEL); if (!nirtfeatures) return -ENOMEM; @@ -1464,16 +1382,12 @@ static int nirtfeatures_acpi_add(struct acpi_device *device) if (ACPI_FAILURE(acpi_ret) || (nirtfeatures->io_base == 0) || - (nirtfeatures->io_size != NIRTF_IO_SIZE)) { - nirtfeatures_acpi_remove(device); + (nirtfeatures->io_size != NIRTF_IO_SIZE)) return -ENODEV; - } - if (!request_region(nirtfeatures->io_base, nirtfeatures->io_size, - MODULE_NAME)) { - nirtfeatures_acpi_remove(device); + if (!devm_request_region(&device->dev, nirtfeatures->io_base, + nirtfeatures->io_size, MODULE_NAME)) return -EBUSY; - } bpinfo = inb(nirtfeatures->io_base + NIRTF_PLATFORM_MISC); @@ -1503,10 +1417,8 @@ static int nirtfeatures_acpi_add(struct acpi_device *device) spin_lock_init(&nirtfeatures->lock); err = nirtfeatures_populate_pies(nirtfeatures); - if (err != 0) { - nirtfeatures_acpi_remove(device); + if (err) return err; - } nirtfeatures->revision[0] = inb(nirtfeatures->io_base + NIRTF_YEAR); nirtfeatures->revision[1] = inb(nirtfeatures->io_base + NIRTF_MONTH); @@ -1514,33 +1426,26 @@ static int nirtfeatures_acpi_add(struct acpi_device *device) nirtfeatures->revision[3] = inb(nirtfeatures->io_base + NIRTF_HOUR); nirtfeatures->revision[4] = inb(nirtfeatures->io_base + NIRTF_MINUTE); - err = sysfs_create_files(&nirtfeatures->acpi_device->dev.kobj, - nirtfeatures_attrs); - if (err != 0) { - nirtfeatures_acpi_remove(device); + err = nirtfeatures_create_leds(nirtfeatures); + if (err) return err; + + if (nirtfeatures->has_wifi) { + err = nirtfeatures_wifi_regulator_init(&device->dev, + nirtfeatures); + if (err) + return err; } - err = nirtfeatures_create_leds(nirtfeatures); - if (err != 0) { - nirtfeatures_acpi_remove(device); + err = sysfs_create_files(&device->dev.kobj, nirtfeatures_attrs); + if (err) return err; - } dev_info(&nirtfeatures->acpi_device->dev, "IO range 0x%04X-0x%04X\n", nirtfeatures->io_base, nirtfeatures->io_base + nirtfeatures->io_size - 1); - if (nirtfeatures->has_wifi) { - err = nirtfeatures_wifi_regulator_init(&device->dev, - nirtfeatures); - if (err != 0) { - nirtfeatures_acpi_remove(device); - return err; - } - } - return 0; } From b8d20956a2b7370fa510bfbe4c1da10399023fd8 Mon Sep 17 00:00:00 2001 From: Kyle Roeschley Date: Wed, 14 Mar 2018 18:22:42 -0500 Subject: [PATCH 027/110] nirtfeatures: Add Swordfish backplane ID Add the new Swordfish backplane ID to stop errors on boot. Signed-off-by: Kyle Roeschley Signed-off-by: Brad Mouring Acked-by: Zach Brown Acked-by: Nathan Sullivan Acked-by: Julia Cartwright Natinst-ReviewBoard-ID: 227200 --- drivers/misc/nirtfeatures.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/misc/nirtfeatures.c b/drivers/misc/nirtfeatures.c index a97755f965567..76f06f82cb537 100644 --- a/drivers/misc/nirtfeatures.c +++ b/drivers/misc/nirtfeatures.c @@ -47,6 +47,7 @@ #define NIRTF_PLATFORM_MISC_ID_MASK 0x07 #define NIRTF_PLATFORM_MISC_ID_MANHATTAN 0 +#define NIRTF_PLATFORM_MISC_ID_SWORDFISH 1 #define NIRTF_PLATFORM_MISC_ID_FIRE_EAGLE 2 #define NIRTF_PLATFORM_MISC_ID_HAMMERHEAD 4 #define NIRTF_PLATFORM_MISC_ID_WINGHEAD 5 @@ -1400,6 +1401,9 @@ static int nirtfeatures_acpi_add(struct acpi_device *device) case NIRTF_PLATFORM_MISC_ID_FIRE_EAGLE: nirtfeatures->bpstring = "Fire Eagle"; break; + case NIRTF_PLATFORM_MISC_ID_SWORDFISH: + nirtfeatures->bpstring = "Swordfish"; + break; case NIRTF_PLATFORM_MISC_ID_HAMMERHEAD: nirtfeatures->bpstring = "Hammerhead"; break; From 78d429b9e01fda05e0cea4c9ea882004a6fe0e0a Mon Sep 17 00:00:00 2001 From: Kyle Roeschley Date: Wed, 14 Mar 2018 18:23:30 -0500 Subject: [PATCH 028/110] nirtfeatures: Only register bi-color LEDs on supported targets Unlike all previous controllers, Swordfish targets do not have bi-color power and status LEDs. Check our backplane ID and don't register the second color if we're on a Swordfish. Signed-off-by: Kyle Roeschley Signed-off-by: Brad Mouring Acked-by: Zach Brown Acked-by: Nathan Sullivan Acked-by: Julia Cartwright Natinst-ReviewBoard-ID: 227200 Natinst-CAR-ID: 691081 --- drivers/misc/nirtfeatures.c | 130 +++++++++++++++++++++++++----------- 1 file changed, 91 insertions(+), 39 deletions(-) diff --git a/drivers/misc/nirtfeatures.c b/drivers/misc/nirtfeatures.c index 76f06f82cb537..6677318325c0a 100644 --- a/drivers/misc/nirtfeatures.c +++ b/drivers/misc/nirtfeatures.c @@ -125,10 +125,17 @@ struct nirtfeatures { u16 io_size; spinlock_t lock; u8 revision[5]; - const char *bpstring; bool has_wifi; struct regulator_dev *reg_dev; unsigned int irq; + struct nirtfeatures_desc *desc; +}; + +struct nirtfeatures_desc { + unsigned int backplane_id; + const char *name; + struct nirtfeatures_led *leds; + unsigned int num_leds; }; struct nirtfeatures_led { @@ -214,7 +221,7 @@ static ssize_t nirtfeatures_backplane_id_get(struct device *dev, struct acpi_device *acpi_device = to_acpi_device(dev); struct nirtfeatures *nirtfeatures = acpi_device->driver_data; - return sprintf(buf, "%s\n", nirtfeatures->bpstring); + return sprintf(buf, "%s\n", nirtfeatures->desc->name); } static DEVICE_ATTR(backplane_id, S_IRUGO, nirtfeatures_backplane_id_get, NULL); @@ -457,7 +464,7 @@ nirtfeatures_led_brightness_get(struct led_classdev *led_cdev) return (data & led->mask) ? LED_FULL : LED_OFF; } -static struct nirtfeatures_led nirtfeatures_leds_common[] = { +static struct nirtfeatures_led nirtfeatures_leds[] = { { { .name = CONFIG_NI_LED_PREFIX ":status:red", @@ -488,7 +495,67 @@ static struct nirtfeatures_led nirtfeatures_leds_common[] = { }, .address = NIRTF_SYSTEM_LEDS, .mask = NIRTF_SYSTEM_LEDS_POWER_YELLOW, + } +}; + +static struct nirtfeatures_led nirtfeatures_leds_monochrome[] = { + { + { + .name = CONFIG_NI_LED_PREFIX ":status:yellow", + .max_brightness = 0xFFFF, + }, + .address = NIRTF_SYSTEM_LEDS, + .mask = NIRTF_SYSTEM_LEDS_STATUS_YELLOW, + .pattern_hi_addr = NIRTF_STATUS_LED_SHIFT1, + .pattern_lo_addr = NIRTF_STATUS_LED_SHIFT0, }, + { + { + .name = CONFIG_NI_LED_PREFIX ":power:green", + }, + .address = NIRTF_SYSTEM_LEDS, + .mask = NIRTF_SYSTEM_LEDS_POWER_GREEN, + } +}; + +static struct nirtfeatures_desc nirtfeatures_descs[] = { + { + .backplane_id = NIRTF_PLATFORM_MISC_ID_MANHATTAN, + .name = "Manhattan", + .leds = nirtfeatures_leds, + .num_leds = ARRAY_SIZE(nirtfeatures_leds), + }, + { + .backplane_id = NIRTF_PLATFORM_MISC_ID_FIRE_EAGLE, + .name = "Fire Eagle", + .leds = nirtfeatures_leds, + .num_leds = ARRAY_SIZE(nirtfeatures_leds), + }, + { + .backplane_id = NIRTF_PLATFORM_MISC_ID_SWORDFISH, + .name = "Swordfish", + .leds = nirtfeatures_leds_monochrome, + .num_leds = ARRAY_SIZE(nirtfeatures_leds_monochrome), + }, + { + .backplane_id = NIRTF_PLATFORM_MISC_ID_HAMMERHEAD, + .name = "Hammerhead", + .leds = nirtfeatures_leds, + .num_leds = ARRAY_SIZE(nirtfeatures_leds), + }, + { + .backplane_id = NIRTF_PLATFORM_MISC_ID_WINGHEAD, + .name = "Winghead", + .leds = nirtfeatures_leds, + .num_leds = ARRAY_SIZE(nirtfeatures_leds), + } +}; + +static struct nirtfeatures_desc nirtfeatures_desc_unknown = { + .backplane_id = 0xf, + .name = "Unknown", + .leds = nirtfeatures_leds, + .num_leds = ARRAY_SIZE(nirtfeatures_leds), }; /*===================================================================== @@ -907,7 +974,7 @@ static int nirtfeatures_parse_switch_pie(struct nirtfeatures *nirtfeatures, } snprintf(switch_dev->phys_location_string, MAX_NODELEN, "%s/%s/%s", - CONFIG_NI_LED_PREFIX, nirtfeatures->bpstring, pie->name); + CONFIG_NI_LED_PREFIX, nirtfeatures->desc->name, pie->name); switch_dev->cdev->name = switch_dev->name_string; switch_dev->cdev->phys = switch_dev->phys_location_string; @@ -1110,24 +1177,20 @@ static int nirtfeatures_populate_pies(struct nirtfeatures *nirtfeatures) static int nirtfeatures_create_leds(struct nirtfeatures *nirtfeatures) { - int i; - int err; - - for (i = 0; i < ARRAY_SIZE(nirtfeatures_leds_common); ++i) { - - nirtfeatures_leds_common[i].nirtfeatures = nirtfeatures; + struct nirtfeatures_led *leds = nirtfeatures->desc->leds; + int i, err; - if (nirtfeatures_leds_common[i].cdev.max_brightness == 0) - nirtfeatures_leds_common[i].cdev.max_brightness = 1; + for (i = 0; i < nirtfeatures->desc->num_leds; i++) { + leds[i].nirtfeatures = nirtfeatures; - nirtfeatures_leds_common[i].cdev.brightness_set = - nirtfeatures_led_brightness_set; + if (leds[i].cdev.max_brightness == 0) + leds[i].cdev.max_brightness = 1; - nirtfeatures_leds_common[i].cdev.brightness_get = - nirtfeatures_led_brightness_get; + leds[i].cdev.brightness_set = nirtfeatures_led_brightness_set; + leds[i].cdev.brightness_get = nirtfeatures_led_brightness_get; err = devm_led_classdev_register(&nirtfeatures->acpi_device->dev, - &nirtfeatures_leds_common[i].cdev); + &leds[i].cdev); if (err) return err; } @@ -1366,7 +1429,7 @@ static int nirtfeatures_acpi_add(struct acpi_device *device) struct nirtfeatures *nirtfeatures; acpi_status acpi_ret; u8 bpinfo; - int err; + int err, i; nirtfeatures = devm_kzalloc(&device->dev, sizeof(*nirtfeatures), GFP_KERNEL); @@ -1394,28 +1457,17 @@ static int nirtfeatures_acpi_add(struct acpi_device *device) bpinfo &= NIRTF_PLATFORM_MISC_ID_MASK; - switch (bpinfo) { - case NIRTF_PLATFORM_MISC_ID_MANHATTAN: - nirtfeatures->bpstring = "Manhattan"; - break; - case NIRTF_PLATFORM_MISC_ID_FIRE_EAGLE: - nirtfeatures->bpstring = "Fire Eagle"; - break; - case NIRTF_PLATFORM_MISC_ID_SWORDFISH: - nirtfeatures->bpstring = "Swordfish"; - break; - case NIRTF_PLATFORM_MISC_ID_HAMMERHEAD: - nirtfeatures->bpstring = "Hammerhead"; - break; - case NIRTF_PLATFORM_MISC_ID_WINGHEAD: - nirtfeatures->bpstring = "Winghead"; - break; - default: + for (i = 0; i < ARRAY_SIZE(nirtfeatures_descs); i++) { + if (bpinfo == nirtfeatures_descs[i].backplane_id) { + nirtfeatures->desc = &nirtfeatures_descs[i]; + break; + } + } + + if (!nirtfeatures->desc) { dev_err(&nirtfeatures->acpi_device->dev, - "Unrecognized backplane type %u\n", - bpinfo); - nirtfeatures->bpstring = "Unknown"; - break; + "Unrecognized backplane ID %u\n", bpinfo); + nirtfeatures->desc = &nirtfeatures_desc_unknown; } spin_lock_init(&nirtfeatures->lock); From 8581ff96ecae6bb17918a184ff23aaf3ada33bb0 Mon Sep 17 00:00:00 2001 From: Jeff Westfahl Date: Mon, 16 Dec 2013 10:44:59 -0600 Subject: [PATCH 029/110] niwatchdog: Added NI Watchdog driver Added an NI Watchdog driver. This is an ACPI device that exposes the NI Watchdog hardware interface. Not all of the proposed features of the device work as expected. Development work on this device by the hardware team is currently not a high priority. These issues will be addressed once the hardware team gets back to this device. Signed-off-by: Jeff Westfahl --- drivers/misc/Kconfig | 9 ++ drivers/misc/Makefile | 1 + drivers/misc/niwatchdog.c | 254 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 264 insertions(+) create mode 100644 drivers/misc/niwatchdog.c diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig index a3b92c8eca2ce..0cb4b8b693b81 100644 --- a/drivers/misc/Kconfig +++ b/drivers/misc/Kconfig @@ -487,6 +487,15 @@ config NI_LED_PREFIX If unsure, use the default. +config NI_WATCHDOG + bool "NI Watchdog support for NI 903x/913x" + depends on X86 && ACPI + help + This driver exposes the NI Watchdog feature of NI 903x/913x Real-Time + controllers. + + If unsure, say N (but it's safe to say "Y"). + source "drivers/misc/c2port/Kconfig" source "drivers/misc/eeprom/Kconfig" source "drivers/misc/cb710/Kconfig" diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile index 9e6292035f0d8..199a58dfccfdc 100644 --- a/drivers/misc/Makefile +++ b/drivers/misc/Makefile @@ -58,3 +58,4 @@ obj-$(CONFIG_UACCE) += uacce/ obj-$(CONFIG_XILINX_SDFEC) += xilinx_sdfec.o obj-$(CONFIG_HISI_HIKEY_USB) += hisi_hikey_usb.o obj-$(CONFIG_NI_RT_FEATURES) += nirtfeatures.o +obj-$(CONFIG_NI_WATCHDOG) += niwatchdog.o diff --git a/drivers/misc/niwatchdog.c b/drivers/misc/niwatchdog.c new file mode 100644 index 0000000000000..d488b49e10a5f --- /dev/null +++ b/drivers/misc/niwatchdog.c @@ -0,0 +1,254 @@ +/* + * Copyright (C) 2013 National Instruments Corp. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include +#include + +#define MODULE_NAME "niwatchdog" + +#define NIWD_CONTROL 0x01 +#define NIWD_COUNTER2 0x02 +#define NIWD_COUNTER1 0x03 +#define NIWD_COUNTER0 0x04 +#define NIWD_SEED2 0x05 +#define NIWD_SEED1 0x06 +#define NIWD_SEED0 0x07 + +#define NIWD_IO_SIZE 0x08 + +#define NIWD_CONTROL_MODE 0x80 +#define NIWD_CONTROL_RESET 0x02 + +struct niwatchdog { + struct acpi_device *acpi_device; + u16 io_base; + u16 io_size; + u32 irq; + spinlock_t lock; +}; + +static ssize_t niwatchdog_wdmode_get(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct acpi_device *acpi_device = to_acpi_device(dev); + struct niwatchdog *niwatchdog = acpi_device->driver_data; + u8 data; + + data = inb(niwatchdog->io_base + NIWD_CONTROL); + + data &= NIWD_CONTROL_MODE; + + return sprintf(buf, "%s\n", data ? "boot" : "user"); +} + +static ssize_t niwatchdog_wdmode_set(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct acpi_device *acpi_device = to_acpi_device(dev); + struct niwatchdog *niwatchdog = acpi_device->driver_data; + u8 data; + + /* you can only switch boot->user */ + if (strcmp(buf, "user")) + return -EINVAL; + + data = NIWD_CONTROL_MODE | NIWD_CONTROL_RESET; + + outb(data, niwatchdog->io_base + NIWD_CONTROL); + + return count; +} + +static DEVICE_ATTR(watchdog_mode, S_IRUSR|S_IWUSR, niwatchdog_wdmode_get, + niwatchdog_wdmode_set); + +static ssize_t niwatchdog_register_dump_get(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct acpi_device *acpi_device = to_acpi_device(dev); + struct niwatchdog *niwatchdog = acpi_device->driver_data; + u8 control, counter2, counter1, counter0; + u8 seed2, seed1, seed0; + + control = inb(niwatchdog->io_base + NIWD_CONTROL); + counter2 = inb(niwatchdog->io_base + NIWD_COUNTER2); + counter1 = inb(niwatchdog->io_base + NIWD_COUNTER1); + counter0 = inb(niwatchdog->io_base + NIWD_COUNTER0); + seed2 = inb(niwatchdog->io_base + NIWD_SEED2); + seed1 = inb(niwatchdog->io_base + NIWD_SEED1); + seed0 = inb(niwatchdog->io_base + NIWD_SEED0); + + return sprintf(buf, + "Control: 0x%02X\n" + "Counter 2: 0x%02X\n" + "Counter 1: 0x%02X\n" + "Counter 0: 0x%02X\n" + "Seed 2: 0x%02X\n" + "Seed 1: 0x%02X\n" + "Seed 0: 0x%02X\n", + control, counter2, counter1, counter0, + seed2, seed1, seed0); +} + +static DEVICE_ATTR(register_dump, S_IRUGO, niwatchdog_register_dump_get, NULL); + +static const struct attribute *niwatchdog_attrs[] = { + &dev_attr_watchdog_mode.attr, + &dev_attr_register_dump.attr, + NULL +}; + +static acpi_status niwatchdog_resources(struct acpi_resource *res, void *data) +{ + struct niwatchdog *niwatchdog = data; + + switch (res->type) { + case ACPI_RESOURCE_TYPE_IO: + if ((niwatchdog->io_base != 0) || + (niwatchdog->io_size != 0)) { + dev_err(&niwatchdog->acpi_device->dev, + "too many IO resources\n"); + return AE_ERROR; + } + + niwatchdog->io_base = res->data.io.minimum; + niwatchdog->io_size = res->data.io.address_length; + + return AE_OK; + + case ACPI_RESOURCE_TYPE_IRQ: + if (niwatchdog->irq != 0) { + dev_err(&niwatchdog->acpi_device->dev, + "too many IRQ resources\n"); + return AE_ERROR; + } + + niwatchdog->irq = res->data.irq.interrupts[0]; + + return AE_OK; + + case ACPI_RESOURCE_TYPE_END_TAG: + return AE_OK; + + default: + dev_err(&niwatchdog->acpi_device->dev, + "unsupported resource type %d\n", + res->type); + return AE_ERROR; + } + + return AE_OK; +} + +static int niwatchdog_acpi_remove(struct acpi_device *device) +{ + struct niwatchdog *niwatchdog = device->driver_data; + + sysfs_remove_files(&niwatchdog->acpi_device->dev.kobj, + niwatchdog_attrs); + + if ((niwatchdog->io_base != 0) && + (niwatchdog->io_size == NIWD_IO_SIZE)) + release_region(niwatchdog->io_base, niwatchdog->io_size); + + device->driver_data = NULL; + + kfree(niwatchdog); + + return 0; +} + +static int niwatchdog_acpi_add(struct acpi_device *device) +{ + struct niwatchdog *niwatchdog; + acpi_status acpi_ret; + int err; + + niwatchdog = kzalloc(sizeof(*niwatchdog), GFP_KERNEL); + + if (!niwatchdog) + return -ENOMEM; + + device->driver_data = niwatchdog; + + niwatchdog->acpi_device = device; + + acpi_ret = acpi_walk_resources(device->handle, METHOD_NAME__CRS, + niwatchdog_resources, niwatchdog); + + if (ACPI_FAILURE(acpi_ret) || + (niwatchdog->io_base == 0) || + (niwatchdog->io_size != NIWD_IO_SIZE) || + (niwatchdog->irq == 0)) { + niwatchdog_acpi_remove(device); + return -ENODEV; + } + + if (!request_region(niwatchdog->io_base, niwatchdog->io_size, + MODULE_NAME)) { + niwatchdog_acpi_remove(device); + return -EBUSY; + } + + err = sysfs_create_files(&niwatchdog->acpi_device->dev.kobj, + niwatchdog_attrs); + if (err) { + niwatchdog_acpi_remove(device); + return err; + } + + spin_lock_init(&niwatchdog->lock); + + dev_info(&niwatchdog->acpi_device->dev, + "IO range 0x%04X-0x%04X, IRQ %d\n", + niwatchdog->io_base, + niwatchdog->io_base + niwatchdog->io_size - 1, niwatchdog->irq); + + return 0; +} + +static const struct acpi_device_id niwatchdog_device_ids[] = { + {"NIC775C", 0}, + {"", 0}, +}; + +static struct acpi_driver niwatchdog_acpi_driver = { + .name = MODULE_NAME, + .ids = niwatchdog_device_ids, + .ops = { + .add = niwatchdog_acpi_add, + .remove = niwatchdog_acpi_remove, + }, +}; + +static int __init niwatchdog_init(void) +{ + return acpi_bus_register_driver(&niwatchdog_acpi_driver); +} + +static void __exit niwatchdog_exit(void) +{ + acpi_bus_unregister_driver(&niwatchdog_acpi_driver); +} + +module_init(niwatchdog_init); +module_exit(niwatchdog_exit); + +MODULE_DEVICE_TABLE(acpi, niwatchdog_device_ids); +MODULE_DESCRIPTION("NI Watchdog"); +MODULE_AUTHOR("Jeff Westfahl "); +MODULE_LICENSE("GPL"); From 5097f410bf4a98c191bf028b752a42b25771f601 Mon Sep 17 00:00:00 2001 From: Jeff Westfahl Date: Wed, 5 Mar 2014 09:50:05 -0600 Subject: [PATCH 030/110] niwatchdog: Added ioctl interface for NI Watchdog Added a new header file with an ioctl interface for NI Watchdog. This file is installed as part of 'make headers_install'. Signed-off-by: Jeff Westfahl [gratian: fix Kbuild conflict, no need to explicitly list headers anymore] Signed-off-by: Gratian Crisan --- include/uapi/linux/niwatchdog.h | 39 +++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) create mode 100644 include/uapi/linux/niwatchdog.h diff --git a/include/uapi/linux/niwatchdog.h b/include/uapi/linux/niwatchdog.h new file mode 100644 index 0000000000000..804d45f0243fa --- /dev/null +++ b/include/uapi/linux/niwatchdog.h @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2012 National Instruments Corp. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#ifndef _LINUX_NIWATCHDOG_H_ +#define _LINUX_NIWATCHDOG_H_ + +#include +#include + +#define NIWATCHDOG_ACTION_INTERRUPT 0 +#define NIWATCHDOG_ACTION_RESET 1 + +#define NIWATCHDOG_STATE_RUNNING 0 +#define NIWATCHDOG_STATE_EXPIRED 1 + +#define NIWATCHDOG_IOCTL_PERIOD_NS _IOR('W', 0, __u32) +#define NIWATCHDOG_IOCTL_MAX_COUNTER _IOR('W', 1, __u32) +#define NIWATCHDOG_IOCTL_COUNTER_SET _IOW('W', 2, __u32) +#define NIWATCHDOG_IOCTL_CHECK_ACTION _IOW('W', 3, __u32) +#define NIWATCHDOG_IOCTL_ADD_ACTION _IOW('W', 4, __u32) +#define NIWATCHDOG_IOCTL_START _IO('W', 5) +#define NIWATCHDOG_IOCTL_PET _IOR('W', 6, __u32) +#define NIWATCHDOG_IOCTL_RESET _IO('W', 7) +#define NIWATCHDOG_IOCTL_COUNTER_GET _IOR('W', 8, __u32) + +#define NIWATCHDOG_NAME "niwatchdog" + +#endif /* _LINUX_NIWATCHDOG_H_ */ From 396f76015a1392598f7dc23879d434ebb347e081 Mon Sep 17 00:00:00 2001 From: Jeff Westfahl Date: Thu, 6 Mar 2014 11:07:15 -0600 Subject: [PATCH 031/110] niwatchdog: Added NIWATCHDOG_STATE_DISABLED Signed-off-by: Jeff Westfahl --- include/uapi/linux/niwatchdog.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/uapi/linux/niwatchdog.h b/include/uapi/linux/niwatchdog.h index 804d45f0243fa..a5931a4c8a277 100644 --- a/include/uapi/linux/niwatchdog.h +++ b/include/uapi/linux/niwatchdog.h @@ -23,6 +23,7 @@ #define NIWATCHDOG_STATE_RUNNING 0 #define NIWATCHDOG_STATE_EXPIRED 1 +#define NIWATCHDOG_STATE_DISABLED 2 #define NIWATCHDOG_IOCTL_PERIOD_NS _IOR('W', 0, __u32) #define NIWATCHDOG_IOCTL_MAX_COUNTER _IOR('W', 1, __u32) From d4fcbe76029b7f838a659bf01ca7ab2df3768cd2 Mon Sep 17 00:00:00 2001 From: Jeff Westfahl Date: Thu, 6 Mar 2014 11:17:36 -0600 Subject: [PATCH 032/110] niwatchdog: Implemented NI Watchdog for NI Linux x64 targets. Signed-off-by: Jeff Westfahl --- drivers/misc/niwatchdog.c | 363 +++++++++++++++++++++++++++++++++++++- 1 file changed, 361 insertions(+), 2 deletions(-) diff --git a/drivers/misc/niwatchdog.c b/drivers/misc/niwatchdog.c index d488b49e10a5f..f3fe69777d022 100644 --- a/drivers/misc/niwatchdog.c +++ b/drivers/misc/niwatchdog.c @@ -14,6 +14,10 @@ #include #include +#include +#include +#include +#include #define MODULE_NAME "niwatchdog" @@ -27,8 +31,18 @@ #define NIWD_IO_SIZE 0x08 -#define NIWD_CONTROL_MODE 0x80 -#define NIWD_CONTROL_RESET 0x02 +#define NIWD_CONTROL_MODE 0x80 +#define NIWD_CONTROL_PROC_INTERRUPT 0x40 +#define NIWD_CONTROL_PROC_RESET 0x20 +#define NIWD_CONTROL_PET 0x10 +#define NIWD_CONTROL_RUNNING 0x08 +#define NIWD_CONTROL_CAPTURECOUNTER 0x04 +#define NIWD_CONTROL_RESET 0x02 +#define NIWD_CONTROL_ALARM 0x01 + +#define NIWD_PERIOD_NS 30720 +#define NIWD_MAX_COUNTER 0x00FFFFFF + struct niwatchdog { struct acpi_device *acpi_device; @@ -36,6 +50,11 @@ struct niwatchdog { u16 io_size; u32 irq; spinlock_t lock; + struct miscdevice misc_dev; + atomic_t available; + wait_queue_head_t irq_event; + u32 running:1; + u32 expired:1; }; static ssize_t niwatchdog_wdmode_get(struct device *dev, @@ -65,6 +84,12 @@ static ssize_t niwatchdog_wdmode_set(struct device *dev, if (strcmp(buf, "user")) return -EINVAL; + data = inb(niwatchdog->io_base + NIWD_CONTROL); + + /* Check if we're already in user mode. */ + if (!(data & NIWD_CONTROL_MODE)) + return count; + data = NIWD_CONTROL_MODE | NIWD_CONTROL_RESET; outb(data, niwatchdog->io_base + NIWD_CONTROL); @@ -112,6 +137,323 @@ static const struct attribute *niwatchdog_attrs[] = { NULL }; +static int niwatchdog_counter_set(struct niwatchdog *niwatchdog, u32 counter) +{ + int ret; + unsigned long flags; + + spin_lock_irqsave(&niwatchdog->lock, flags); + + /* Prevent changing the counter while the watchdog is running. */ + if (niwatchdog->running) { + ret = -EBUSY; + goto out_unlock; + } + + outb(((0x00FF0000 & counter) >> 16), niwatchdog->io_base + NIWD_SEED2); + outb(((0x0000FF00 & counter) >> 8), niwatchdog->io_base + NIWD_SEED1); + outb((0x000000FF & counter), niwatchdog->io_base + NIWD_SEED0); + + ret = 0; + +out_unlock: + spin_unlock_irqrestore(&niwatchdog->lock, flags); + + return ret; +} + +static int niwatchdog_check_action(u32 action) +{ + int err = 0; + + switch (action) { + case NIWD_CONTROL_PROC_INTERRUPT: + case NIWD_CONTROL_PROC_RESET: + break; + default: + err = -ENOTSUPP; + } + + return err; +} + +static int niwatchdog_add_action(struct niwatchdog *niwatchdog, u32 action) +{ + u8 action_mask; + u8 control; + unsigned long flags; + + if (action == NIWATCHDOG_ACTION_INTERRUPT) + action_mask = NIWD_CONTROL_PROC_INTERRUPT; + else if (action == NIWATCHDOG_ACTION_RESET) + action_mask = NIWD_CONTROL_PROC_RESET; + else + return -ENOTSUPP; + + spin_lock_irqsave(&niwatchdog->lock, flags); + + control = inb(niwatchdog->io_base + NIWD_CONTROL); + control |= action_mask; + outb(control, niwatchdog->io_base + NIWD_CONTROL); + + spin_unlock_irqrestore(&niwatchdog->lock, flags); + + return 0; +} + +static int niwatchdog_start(struct niwatchdog *niwatchdog) +{ + u8 control; + unsigned long flags; + + spin_lock_irqsave(&niwatchdog->lock, flags); + + niwatchdog->running = true; + niwatchdog->expired = false; + + control = inb(niwatchdog->io_base + NIWD_CONTROL); + outb(control | NIWD_CONTROL_RESET, niwatchdog->io_base + NIWD_CONTROL); + outb(control | NIWD_CONTROL_PET, niwatchdog->io_base + NIWD_CONTROL); + + spin_unlock_irqrestore(&niwatchdog->lock, flags); + + return 0; +} + +static int niwatchdog_pet(struct niwatchdog *niwatchdog, u32 *state) +{ + u8 control; + unsigned long flags; + + spin_lock_irqsave(&niwatchdog->lock, flags); + + if (niwatchdog->expired) { + *state = NIWATCHDOG_STATE_EXPIRED; + } else if (!niwatchdog->running) { + *state = NIWATCHDOG_STATE_DISABLED; + } else { + control = inb(niwatchdog->io_base + NIWD_CONTROL); + control |= NIWD_CONTROL_PET; + outb(control, niwatchdog->io_base + NIWD_CONTROL); + + *state = NIWATCHDOG_STATE_RUNNING; + } + + spin_unlock_irqrestore(&niwatchdog->lock, flags); + + return 0; +} + +static int niwatchdog_reset(struct niwatchdog *niwatchdog) +{ + unsigned long flags; + + spin_lock_irqsave(&niwatchdog->lock, flags); + + niwatchdog->running = false; + niwatchdog->expired = false; + + outb(NIWD_CONTROL_RESET, niwatchdog->io_base + NIWD_CONTROL); + + spin_unlock_irqrestore(&niwatchdog->lock, flags); + + return 0; +} + +static int niwatchdog_counter_get(struct niwatchdog *niwatchdog, + u32 *counter) +{ + u8 control; + u8 counter2, counter1, counter0; + unsigned long flags; + + spin_lock_irqsave(&niwatchdog->lock, flags); + + control = inb(niwatchdog->io_base + NIWD_CONTROL); + control |= NIWD_CONTROL_CAPTURECOUNTER; + outb(control, niwatchdog->io_base + NIWD_CONTROL); + + counter2 = inb(niwatchdog->io_base + NIWD_COUNTER2); + counter1 = inb(niwatchdog->io_base + NIWD_COUNTER1); + counter0 = inb(niwatchdog->io_base + NIWD_COUNTER0); + + *counter = (counter2 << 16) | (counter1 << 8) | counter0; + + spin_unlock_irqrestore(&niwatchdog->lock, flags); + + return 0; +} + +static irqreturn_t niwatchdog_irq(int irq, void *data) +{ + struct niwatchdog *niwatchdog = data; + irqreturn_t ret = IRQ_NONE; + u8 control; + unsigned long flags; + + spin_lock_irqsave(&niwatchdog->lock, flags); + + control = inb(niwatchdog->io_base + NIWD_CONTROL); + + if (!(NIWD_CONTROL_ALARM & control)) { + dev_err(&niwatchdog->acpi_device->dev, + "Spurious watchdog interrupt, 0x%02X\n", control); + goto out_unlock; + } + + niwatchdog->running = false; + niwatchdog->expired = true; + + /* Acknowledge the interrupt. */ + control |= NIWD_CONTROL_RESET; + outb(control, niwatchdog->io_base + NIWD_CONTROL); + + /* Signal the watchdog event. */ + wake_up_all(&niwatchdog->irq_event); + + ret = IRQ_HANDLED; + +out_unlock: + spin_unlock_irqrestore(&niwatchdog->lock, flags); + + return ret; +} + +static int niwatchdog_misc_open(struct inode *inode, struct file *file) +{ + struct miscdevice *misc_dev = file->private_data; + struct niwatchdog *niwatchdog = container_of( + misc_dev, struct niwatchdog, misc_dev); + + file->private_data = niwatchdog; + + if (!atomic_dec_and_test(&niwatchdog->available)) { + atomic_inc(&niwatchdog->available); + return -EBUSY; + } + + return request_irq(niwatchdog->irq, niwatchdog_irq, 0, + NIWATCHDOG_NAME, niwatchdog); +} + +static int niwatchdog_misc_release(struct inode *inode, struct file *file) +{ + struct niwatchdog *niwatchdog = file->private_data; + + free_irq(niwatchdog->irq, niwatchdog); + atomic_inc(&niwatchdog->available); + return 0; +} + +static long niwatchdog_misc_ioctl(struct file *file, unsigned int cmd, + unsigned long arg) +{ + struct niwatchdog *niwatchdog = file->private_data; + int err; + + switch (cmd) { + case NIWATCHDOG_IOCTL_PERIOD_NS: { + __u32 period = NIWD_PERIOD_NS; + + err = copy_to_user((__u32 *)arg, &period, + sizeof(__u32)); + break; + } + case NIWATCHDOG_IOCTL_MAX_COUNTER: { + __u32 counter = NIWD_MAX_COUNTER; + + err = copy_to_user((__u32 *)arg, &counter, + sizeof(__u32)); + break; + } + case NIWATCHDOG_IOCTL_COUNTER_SET: { + __u32 counter; + + err = copy_from_user(&counter, (__u32 *)arg, + sizeof(__u32)); + if (!err) + err = niwatchdog_counter_set(niwatchdog, counter); + break; + } + case NIWATCHDOG_IOCTL_CHECK_ACTION: { + __u32 action; + + err = copy_from_user(&action, (__u32 *)arg, + sizeof(__u32)); + if (!err) + err = niwatchdog_check_action(action); + break; + } + case NIWATCHDOG_IOCTL_ADD_ACTION: { + __u32 action; + err = copy_from_user(&action, (__u32 *)arg, + sizeof(__u32)); + if (!err) + err = niwatchdog_add_action(niwatchdog, action); + break; + } + case NIWATCHDOG_IOCTL_START: { + err = niwatchdog_start(niwatchdog); + break; + } + case NIWATCHDOG_IOCTL_PET: { + __u32 state; + + err = niwatchdog_pet(niwatchdog, &state); + if (!err) + err = copy_to_user((__u32 *)arg, &state, + sizeof(__u32)); + break; + } + case NIWATCHDOG_IOCTL_RESET: { + err = niwatchdog_reset(niwatchdog); + break; + } + case NIWATCHDOG_IOCTL_COUNTER_GET: { + __u32 counter; + + err = niwatchdog_counter_get(niwatchdog, &counter); + if (!err) { + err = copy_to_user((__u32 *)arg, &counter, + sizeof(__u32)); + } + break; + } + default: + err = -EINVAL; + break; + }; + + return err; +} + +unsigned int niwatchdog_misc_poll(struct file *file, + struct poll_table_struct *wait) +{ + struct niwatchdog *niwatchdog = file->private_data; + unsigned int mask = 0; + unsigned long flags; + + poll_wait(file, &niwatchdog->irq_event, wait); + + spin_lock_irqsave(&niwatchdog->lock, flags); + + if (niwatchdog->expired) + mask = POLLIN; + + spin_unlock_irqrestore(&niwatchdog->lock, flags); + + return mask; +} + +static const struct file_operations niwatchdog_misc_fops = { + .owner = THIS_MODULE, + .open = niwatchdog_misc_open, + .release = niwatchdog_misc_release, + .unlocked_ioctl = niwatchdog_misc_ioctl, + .poll = niwatchdog_misc_poll, +}; + static acpi_status niwatchdog_resources(struct acpi_resource *res, void *data) { struct niwatchdog *niwatchdog = data; @@ -158,6 +500,8 @@ static int niwatchdog_acpi_remove(struct acpi_device *device) { struct niwatchdog *niwatchdog = device->driver_data; + misc_deregister(&niwatchdog->misc_dev); + sysfs_remove_files(&niwatchdog->acpi_device->dev.kobj, niwatchdog_attrs); @@ -213,6 +557,21 @@ static int niwatchdog_acpi_add(struct acpi_device *device) spin_lock_init(&niwatchdog->lock); + atomic_set(&niwatchdog->available, 1); + init_waitqueue_head(&niwatchdog->irq_event); + niwatchdog->expired = false; + + niwatchdog->misc_dev.minor = MISC_DYNAMIC_MINOR; + niwatchdog->misc_dev.name = NIWATCHDOG_NAME; + niwatchdog->misc_dev.fops = &niwatchdog_misc_fops; + + err = misc_register(&niwatchdog->misc_dev); + + if (err) { + niwatchdog_acpi_remove(device); + return err; + } + dev_info(&niwatchdog->acpi_device->dev, "IO range 0x%04X-0x%04X, IRQ %d\n", niwatchdog->io_base, From efa830b4d933d8b036ee06392aae1547745f3bcb Mon Sep 17 00:00:00 2001 From: Jeff Westfahl Date: Thu, 10 Apr 2014 16:40:22 -0500 Subject: [PATCH 033/110] niwatchdog: remove register_dump Removed the register_dump sysfs file. The watchdog works well, there's no longer a need for this debugging file. Signed-off-by: Jeff Westfahl --- drivers/misc/niwatchdog.c | 32 -------------------------------- 1 file changed, 32 deletions(-) diff --git a/drivers/misc/niwatchdog.c b/drivers/misc/niwatchdog.c index f3fe69777d022..c09702b6c19a8 100644 --- a/drivers/misc/niwatchdog.c +++ b/drivers/misc/niwatchdog.c @@ -100,40 +100,8 @@ static ssize_t niwatchdog_wdmode_set(struct device *dev, static DEVICE_ATTR(watchdog_mode, S_IRUSR|S_IWUSR, niwatchdog_wdmode_get, niwatchdog_wdmode_set); -static ssize_t niwatchdog_register_dump_get(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct acpi_device *acpi_device = to_acpi_device(dev); - struct niwatchdog *niwatchdog = acpi_device->driver_data; - u8 control, counter2, counter1, counter0; - u8 seed2, seed1, seed0; - - control = inb(niwatchdog->io_base + NIWD_CONTROL); - counter2 = inb(niwatchdog->io_base + NIWD_COUNTER2); - counter1 = inb(niwatchdog->io_base + NIWD_COUNTER1); - counter0 = inb(niwatchdog->io_base + NIWD_COUNTER0); - seed2 = inb(niwatchdog->io_base + NIWD_SEED2); - seed1 = inb(niwatchdog->io_base + NIWD_SEED1); - seed0 = inb(niwatchdog->io_base + NIWD_SEED0); - - return sprintf(buf, - "Control: 0x%02X\n" - "Counter 2: 0x%02X\n" - "Counter 1: 0x%02X\n" - "Counter 0: 0x%02X\n" - "Seed 2: 0x%02X\n" - "Seed 1: 0x%02X\n" - "Seed 0: 0x%02X\n", - control, counter2, counter1, counter0, - seed2, seed1, seed0); -} - -static DEVICE_ATTR(register_dump, S_IRUGO, niwatchdog_register_dump_get, NULL); - static const struct attribute *niwatchdog_attrs[] = { &dev_attr_watchdog_mode.attr, - &dev_attr_register_dump.attr, NULL }; From 28ef0f1e73f49940dee9371596d4e611c2a15624 Mon Sep 17 00:00:00 2001 From: Kyle Roeschley Date: Fri, 19 Feb 2016 14:27:22 -0600 Subject: [PATCH 034/110] niwatchdog: Explicitly request threaded interrupt Requesting a threaded interrupt explicity and doing so with a NULL handler/non-NULL thread_fn avoids disabling softirqs while the handler executes. This does require setting IRQF_ONESHOT, which was set automatically when using request_irq before. Signed-off-by: Kyle Roeschley Signed-off-by: Brad Mouring Acked-by: Josh Cartwright Natinst-ReviewBoard-ID: 127047 --- drivers/misc/niwatchdog.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/misc/niwatchdog.c b/drivers/misc/niwatchdog.c index c09702b6c19a8..1b9ba115b94b9 100644 --- a/drivers/misc/niwatchdog.c +++ b/drivers/misc/niwatchdog.c @@ -300,8 +300,8 @@ static int niwatchdog_misc_open(struct inode *inode, struct file *file) return -EBUSY; } - return request_irq(niwatchdog->irq, niwatchdog_irq, 0, - NIWATCHDOG_NAME, niwatchdog); + return request_threaded_irq(niwatchdog->irq, NULL, niwatchdog_irq, + IRQF_ONESHOT, NIWATCHDOG_NAME, niwatchdog); } static int niwatchdog_misc_release(struct inode *inode, struct file *file) From 72dd1adea1f6a9da6de9f2dcf2a7def8e5bd1d58 Mon Sep 17 00:00:00 2001 From: Kyle Roeschley Date: Mon, 7 Aug 2017 15:17:44 -0500 Subject: [PATCH 035/110] niwatchdog: Fix error path in ACPI add Use device-managed resource allocation where possible and clean up correctly in the event of an error during ACPI add. Signed-off-by: Kyle Roeschley Signed-off-by: Brad Mouring Acked-by: Zach Brown Acked-by: James Minor Acked-by: Ovidiu Vancea Acked-by: Julia Cartwright Natinst-ReviewBoard-ID: 196333 --- drivers/misc/niwatchdog.c | 94 +++++++++++++-------------------------- 1 file changed, 32 insertions(+), 62 deletions(-) diff --git a/drivers/misc/niwatchdog.c b/drivers/misc/niwatchdog.c index 1b9ba115b94b9..83a6a8bd75691 100644 --- a/drivers/misc/niwatchdog.c +++ b/drivers/misc/niwatchdog.c @@ -47,7 +47,6 @@ struct niwatchdog { struct acpi_device *acpi_device; u16 io_base; - u16 io_size; u32 irq; spinlock_t lock; struct miscdevice misc_dev; @@ -425,25 +424,35 @@ static const struct file_operations niwatchdog_misc_fops = { static acpi_status niwatchdog_resources(struct acpi_resource *res, void *data) { struct niwatchdog *niwatchdog = data; + struct device *dev = &niwatchdog->acpi_device->dev; + u16 io_size; switch (res->type) { case ACPI_RESOURCE_TYPE_IO: - if ((niwatchdog->io_base != 0) || - (niwatchdog->io_size != 0)) { - dev_err(&niwatchdog->acpi_device->dev, - "too many IO resources\n"); + if (niwatchdog->io_base != 0) { + dev_err(dev, "too many IO resources\n"); return AE_ERROR; } niwatchdog->io_base = res->data.io.minimum; - niwatchdog->io_size = res->data.io.address_length; + io_size = res->data.io.address_length; + + if (io_size < NIWD_IO_SIZE) { + dev_err(dev, "memory region too small\n"); + return AE_ERROR; + } + + if (!devm_request_region(dev, niwatchdog->io_base, io_size, + MODULE_NAME)) { + dev_err(dev, "failed to get memory region\n"); + return AE_ERROR; + } return AE_OK; case ACPI_RESOURCE_TYPE_IRQ: if (niwatchdog->irq != 0) { - dev_err(&niwatchdog->acpi_device->dev, - "too many IRQ resources\n"); + dev_err(dev, "too many IRQ resources\n"); return AE_ERROR; } @@ -455,13 +464,9 @@ static acpi_status niwatchdog_resources(struct acpi_resource *res, void *data) return AE_OK; default: - dev_err(&niwatchdog->acpi_device->dev, - "unsupported resource type %d\n", - res->type); + dev_err(dev, "unsupported resource type %d\n", res->type); return AE_ERROR; } - - return AE_OK; } static int niwatchdog_acpi_remove(struct acpi_device *device) @@ -473,78 +478,54 @@ static int niwatchdog_acpi_remove(struct acpi_device *device) sysfs_remove_files(&niwatchdog->acpi_device->dev.kobj, niwatchdog_attrs); - if ((niwatchdog->io_base != 0) && - (niwatchdog->io_size == NIWD_IO_SIZE)) - release_region(niwatchdog->io_base, niwatchdog->io_size); - - device->driver_data = NULL; - - kfree(niwatchdog); - return 0; } static int niwatchdog_acpi_add(struct acpi_device *device) { + struct device *dev = &device->dev; struct niwatchdog *niwatchdog; acpi_status acpi_ret; int err; - niwatchdog = kzalloc(sizeof(*niwatchdog), GFP_KERNEL); - + niwatchdog = devm_kzalloc(dev, sizeof(*niwatchdog), GFP_KERNEL); if (!niwatchdog) return -ENOMEM; device->driver_data = niwatchdog; - niwatchdog->acpi_device = device; acpi_ret = acpi_walk_resources(device->handle, METHOD_NAME__CRS, niwatchdog_resources, niwatchdog); - - if (ACPI_FAILURE(acpi_ret) || - (niwatchdog->io_base == 0) || - (niwatchdog->io_size != NIWD_IO_SIZE) || - (niwatchdog->irq == 0)) { - niwatchdog_acpi_remove(device); + if (ACPI_FAILURE(acpi_ret) || niwatchdog->io_base == 0 || + niwatchdog->irq == 0) { + dev_err(dev, "failed to get resources\n"); return -ENODEV; } - if (!request_region(niwatchdog->io_base, niwatchdog->io_size, - MODULE_NAME)) { - niwatchdog_acpi_remove(device); - return -EBUSY; - } - - err = sysfs_create_files(&niwatchdog->acpi_device->dev.kobj, - niwatchdog_attrs); - if (err) { - niwatchdog_acpi_remove(device); - return err; - } - spin_lock_init(&niwatchdog->lock); atomic_set(&niwatchdog->available, 1); init_waitqueue_head(&niwatchdog->irq_event); niwatchdog->expired = false; + err = sysfs_create_files(&dev->kobj, niwatchdog_attrs); + if (err) { + dev_err(dev, "failed to create sysfs attributes\n"); + return err; + } + niwatchdog->misc_dev.minor = MISC_DYNAMIC_MINOR; niwatchdog->misc_dev.name = NIWATCHDOG_NAME; niwatchdog->misc_dev.fops = &niwatchdog_misc_fops; err = misc_register(&niwatchdog->misc_dev); - if (err) { - niwatchdog_acpi_remove(device); + dev_err(dev, "failed to register misc device\n"); + sysfs_remove_files(&dev->kobj, niwatchdog_attrs); return err; } - dev_info(&niwatchdog->acpi_device->dev, - "IO range 0x%04X-0x%04X, IRQ %d\n", - niwatchdog->io_base, - niwatchdog->io_base + niwatchdog->io_size - 1, niwatchdog->irq); - return 0; } @@ -562,18 +543,7 @@ static struct acpi_driver niwatchdog_acpi_driver = { }, }; -static int __init niwatchdog_init(void) -{ - return acpi_bus_register_driver(&niwatchdog_acpi_driver); -} - -static void __exit niwatchdog_exit(void) -{ - acpi_bus_unregister_driver(&niwatchdog_acpi_driver); -} - -module_init(niwatchdog_init); -module_exit(niwatchdog_exit); +module_acpi_driver(niwatchdog_acpi_driver); MODULE_DEVICE_TABLE(acpi, niwatchdog_device_ids); MODULE_DESCRIPTION("NI Watchdog"); From 85c7d5636780d714ff27a3bc070a37bd15d62e8f Mon Sep 17 00:00:00 2001 From: Kyle Roeschley Date: Wed, 2 Aug 2017 13:08:03 -0500 Subject: [PATCH 036/110] niwatchdog: Request IRQ on ACPI add instead of miscdevice open Do what most sane drivers do and request our IRQ on ACPI add rather than doing it every time someone opens our char device. This ensures that our thread exists at boot time, which means priority changes can be done in user mode. Signed-off-by: Kyle Roeschley Signed-off-by: Brad Mouring Acked-by: Zach Brown Acked-by: James Minor Acked-by: Ovidiu Vancea Acked-by: Julia Cartwright Natinst-CAR-ID: 648185 Natinst-ReviewBoard-ID: 196333 --- drivers/misc/niwatchdog.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/drivers/misc/niwatchdog.c b/drivers/misc/niwatchdog.c index 83a6a8bd75691..df7f5cfc7b855 100644 --- a/drivers/misc/niwatchdog.c +++ b/drivers/misc/niwatchdog.c @@ -299,15 +299,13 @@ static int niwatchdog_misc_open(struct inode *inode, struct file *file) return -EBUSY; } - return request_threaded_irq(niwatchdog->irq, NULL, niwatchdog_irq, - IRQF_ONESHOT, NIWATCHDOG_NAME, niwatchdog); + return 0; } static int niwatchdog_misc_release(struct inode *inode, struct file *file) { struct niwatchdog *niwatchdog = file->private_data; - free_irq(niwatchdog->irq, niwatchdog); atomic_inc(&niwatchdog->available); return 0; } @@ -458,6 +456,13 @@ static acpi_status niwatchdog_resources(struct acpi_resource *res, void *data) niwatchdog->irq = res->data.irq.interrupts[0]; + if (devm_request_threaded_irq(dev, niwatchdog->irq, NULL, + niwatchdog_irq, IRQF_ONESHOT, + NIWATCHDOG_NAME, niwatchdog)) { + dev_err(dev, "failed to get interrupt\n"); + return AE_ERROR; + } + return AE_OK; case ACPI_RESOURCE_TYPE_END_TAG: From 6e49f986544ba3ddcf245863875b56f0a296a582 Mon Sep 17 00:00:00 2001 From: Jaeden Amero Date: Thu, 2 Aug 2012 15:51:01 -0500 Subject: [PATCH 037/110] serial_core: Provide a transceiver interface Before this change, to enable transceiver control for RS-485 ports, client drivers had to implement the TIOCSRS485/TIOCGRS485 ioctls. This change provides a common transceiver interface so that we have a common way for all client drivers to do transceiver control. When registering a new port, client drivers will have the option of providing a struct txvr_ops which has callbacks for transceiver operations. This makes it easier to have a common UART driver (like the 8250) for both RS-232 and RS-485 ports and transceiver operations can be added for the RS-485 ports alone. Signed-off-by: Jaeden Amero Signed-off-by: Xander Huff Acked-by: Karthik Manamcheri Acked-by: Ben Shelton Natinst-ReviewBoard-ID: 88262 --- drivers/tty/serial/serial_core.c | 11 +++++++++++ include/linux/serial_core.h | 10 ++++++++++ 2 files changed, 21 insertions(+) diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c index f41cba10b86b9..e70e49b508b79 100644 --- a/drivers/tty/serial/serial_core.c +++ b/drivers/tty/serial/serial_core.c @@ -229,6 +229,10 @@ static int uart_port_startup(struct tty_struct *tty, struct uart_state *state, */ uart_change_speed(tty, state, NULL); + /* Enable Transceivers */ + if (uport->txvr_ops && uport->txvr_ops->enable_transceivers) + uport->txvr_ops->enable_transceivers(uport); + /* * Setup the RTS and DTR signals once the * port is open and ready to respond. @@ -1690,6 +1694,10 @@ static void uart_port_shutdown(struct tty_port *port) struct uart_state *state = container_of(port, struct uart_state, port); struct uart_port *uport = uart_port_check(state); + /* Disable Transceivers */ + if (uport->txvr_ops && uport->txvr_ops->disable_transceivers) + uport->txvr_ops->disable_transceivers(uport); + /* * clear delta_msr_wait queue to avoid mem leaks: we may free * the irq here so the queue might never be woken up. Note @@ -2283,6 +2291,9 @@ int uart_resume_port(struct uart_driver *drv, struct uart_port *uport) if (tty) uart_change_speed(tty, state, NULL); spin_lock_irq(&uport->lock); + if (uport->rs485_config) + uport->rs485_config(uport, + &uport->rs485); ops->set_mctrl(uport, uport->mctrl); ops->start_tx(uport); spin_unlock_irq(&uport->lock); diff --git a/include/linux/serial_core.h b/include/linux/serial_core.h index ff63c2963359d..0f1f48a931d06 100644 --- a/include/linux/serial_core.h +++ b/include/linux/serial_core.h @@ -82,6 +82,15 @@ struct uart_ops { #endif }; +/* + * This structure describes all the operations that can be done through + * transceiver controllers. + */ +struct txvr_ops { + int (*enable_transceivers)(struct uart_port *); + int (*disable_transceivers)(struct uart_port *); +}; + #define NO_POLL_CHAR 0x00ff0000 #define UART_CONFIG_TYPE (1 << 0) #define UART_CONFIG_IRQ (1 << 1) @@ -234,6 +243,7 @@ struct uart_port { unsigned int timeout; /* character-based timeout */ unsigned int type; /* port type */ const struct uart_ops *ops; + const struct txvr_ops *txvr_ops; /* transceiver ops */ unsigned int custom_divisor; unsigned int line; /* port index */ unsigned int minor; From 7c04fe388f16a537230ce0c815b237396cf1196a Mon Sep 17 00:00:00 2001 From: Jaeden Amero Date: Tue, 11 Mar 2014 15:43:01 -0500 Subject: [PATCH 038/110] 8250: Allow client drivers to control transceivers This change allows 8250 client drivers to register txvr_ops, so that they can implement transceiver control for RS-485 ports. Signed-off-by: Jaeden Amero Signed-off-by: Xander Huff Acked-by: Karthik Manamcheri Acked-by: Ben Shelton Natinst-ReviewBoard-ID: 88262 --- drivers/tty/serial/8250/8250_core.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/tty/serial/8250/8250_core.c b/drivers/tty/serial/8250/8250_core.c index 47dd230562719..384a2e68353de 100644 --- a/drivers/tty/serial/8250/8250_core.c +++ b/drivers/tty/serial/8250/8250_core.c @@ -1064,6 +1064,8 @@ int serial8250_register_8250_port(struct uart_8250_port *up) uart->port.serial_out = up->port.serial_out; if (up->port.handle_irq) uart->port.handle_irq = up->port.handle_irq; + if (up->port.txvr_ops) + uart->port.txvr_ops = up->port.txvr_ops; /* Possibly override set_termios call */ if (up->port.set_termios) uart->port.set_termios = up->port.set_termios; From 0303fb05d9da5d7a4f8f8d78463739ed889bc952 Mon Sep 17 00:00:00 2001 From: Jaeden Amero Date: Tue, 11 Mar 2014 16:52:15 -0500 Subject: [PATCH 039/110] 8250: Add a driver for NI 16550 UART The National Instruments (NI) 16550 is a standard 16550 with larger FIFOs and embedded RS-485 transceiver control circuitry. This patch adds a driver that can operate this UART. Signed-off-by: Jaeden Amero Acked-by: Karthik Manamcheri [gratian: fix conflict with aa42db44f670 ("8250: of: remove remnants of generic of_serial driver")] Signed-off-by: Gratian Crisan [bstreiff: renumber out-of-tree definition of PORT_NI16550 from 118 to 123.] Signed-off-by: Brandon Streiff --- drivers/tty/serial/8250/8250_ni16550.c | 134 +++++++++++++++++++++++++ drivers/tty/serial/8250/8250_of.c | 24 +++++ drivers/tty/serial/8250/Kconfig | 6 ++ drivers/tty/serial/8250/Makefile | 1 + include/linux/ni16550.h | 26 +++++ include/uapi/linux/serial_core.h | 3 + include/uapi/linux/serial_reg.h | 1 + 7 files changed, 195 insertions(+) create mode 100644 drivers/tty/serial/8250/8250_ni16550.c create mode 100644 include/linux/ni16550.h diff --git a/drivers/tty/serial/8250/8250_ni16550.c b/drivers/tty/serial/8250/8250_ni16550.c new file mode 100644 index 0000000000000..d8dc0960fc3b2 --- /dev/null +++ b/drivers/tty/serial/8250/8250_ni16550.c @@ -0,0 +1,134 @@ +/* + * NI 16550 Transceiver Driver + * + * The National Instruments (NI) 16550 has built-in RS-485 transceiver control + * circuitry. This driver provides the transceiver control functionality + * for the RS-485 ports and uses the 8250 driver for the UART functionality. + * + * Copyright 2012 National Instruments Corporation + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + */ + +#include "8250.h" +#include +#include +#include + +#define NI16550_PCR_OFFSET 0x0F +#define NI16550_PCR_RS422 0x00 +#define NI16550_PCR_ECHO_RS485 0x01 +#define NI16550_PCR_DTR_RS485 0x02 +#define NI16550_PCR_AUTO_RS485 0x03 +#define NI16550_PCR_WIRE_MODE_MASK 0x03 +#define NI16550_PCR_TXVR_ENABLE_BIT (1 << 3) +#define NI16550_PCR_RS485_TERMINATION_BIT (1 << 6) + +static int ni16550_enable_transceivers(struct uart_port *port) +{ + uint8_t pcr; + + dev_dbg(port->dev, ">ni16550_enable_transceivers\n"); + + pcr = port->serial_in(port, NI16550_PCR_OFFSET); + pcr |= NI16550_PCR_TXVR_ENABLE_BIT; + dev_dbg(port->dev, "write pcr: 0x%08x\n", pcr); + port->serial_out(port, NI16550_PCR_OFFSET, pcr); + + dev_dbg(port->dev, "dev, ">ni16550_disable_transceivers\n"); + + pcr = port->serial_in(port, NI16550_PCR_OFFSET); + pcr &= ~NI16550_PCR_TXVR_ENABLE_BIT; + dev_dbg(port->dev, "write pcr: 0x%08x\n", pcr); + port->serial_out(port, NI16550_PCR_OFFSET, pcr); + + dev_dbg(port->dev, "dev, ">ni16550_config_rs485\n"); + + /* "rs485" should be given to us non-NULL. */ + BUG_ON(rs485 == NULL); + + pcr = port->serial_in(port, NI16550_PCR_OFFSET); + pcr &= ~NI16550_PCR_WIRE_MODE_MASK; + + if (rs485->flags & SER_RS485_ENABLED) { + /* RS-485 */ + if ((rs485->flags & SER_RS485_RX_DURING_TX) && + (rs485->flags & SER_RS485_RTS_ON_SEND)) { + dev_dbg(port->dev, "Invalid 2-wire mode\n"); + return -EINVAL; + } + + if (rs485->flags & SER_RS485_RX_DURING_TX) { + /* Echo */ + dev_vdbg(port->dev, "2-wire DTR with echo\n"); + pcr |= NI16550_PCR_ECHO_RS485; + } else { + /* Auto or DTR */ + if (rs485->flags & SER_RS485_RTS_ON_SEND) { + /* Auto */ + dev_vdbg(port->dev, "2-wire Auto\n"); + pcr |= NI16550_PCR_AUTO_RS485; + } else { + /* DTR-controlled */ + /* No Echo */ + dev_vdbg(port->dev, "2-wire DTR no echo\n"); + pcr |= NI16550_PCR_DTR_RS485; + } + } + } else { + /* RS-422 */ + dev_vdbg(port->dev, "4-wire\n"); + pcr |= NI16550_PCR_RS422; + } + + dev_dbg(port->dev, "write pcr: 0x%08x\n", pcr); + port->serial_out(port, NI16550_PCR_OFFSET, pcr); + + /* Update the cache. */ + port->rs485 = *rs485; + + dev_dbg(port->dev, "txvr_ops = &ni16550_txvr_ops; + port->rs485_config = &ni16550_config_rs485; + /* The hardware comes up by default in 2-wire auto mode and we + * set the flags to represent that + */ + port->rs485.flags = SER_RS485_ENABLED | SER_RS485_RTS_ON_SEND; +} diff --git a/drivers/tty/serial/8250/8250_of.c b/drivers/tty/serial/8250/8250_of.c index 65e9045dafe6d..35049a305515a 100644 --- a/drivers/tty/serial/8250/8250_of.c +++ b/drivers/tty/serial/8250/8250_of.c @@ -9,6 +9,7 @@ #include #include #include +#include #include #include #include @@ -163,6 +164,23 @@ static int of_platform_serial_setup(struct platform_device *ofdev, case PORT_RT2880: port->iotype = UPIO_AU; break; +#ifdef CONFIG_SERIAL_8250_NI16550 + case PORT_NI16550_F16: + case PORT_NI16550_F128: + { + const char *transceiver; + + if (of_property_read_string(np, "transceiver", &transceiver)) { + dev_warn(&ofdev->dev, "no transceiver property set\n"); + ret = -EINVAL; + goto err_dispose; + } + + if (strcmp(transceiver, "RS-485") == 0) + ni16550_port_setup(port); + break; + } +#endif } if (IS_ENABLED(CONFIG_SERIAL_8250_FSL) && @@ -319,6 +337,12 @@ static const struct of_device_id of_platform_serial_table[] = { .data = (void *)PORT_XSCALE, }, { .compatible = "ti,da830-uart", .data = (void *)PORT_DA830, }, { .compatible = "nuvoton,npcm750-uart", .data = (void *)PORT_NPCM, }, +#ifdef CONFIG_SERIAL_8250_NI16550 + { .compatible = "ni16550-fifo16", + .data = (void *)PORT_NI16550_F16, }, + { .compatible = "ni16550-fifo128", + .data = (void *)PORT_NI16550_F128, }, +#endif { /* end of list */ }, }; MODULE_DEVICE_TABLE(of, of_platform_serial_table); diff --git a/drivers/tty/serial/8250/Kconfig b/drivers/tty/serial/8250/Kconfig index 603137da47363..d73a72734c485 100644 --- a/drivers/tty/serial/8250/Kconfig +++ b/drivers/tty/serial/8250/Kconfig @@ -518,3 +518,9 @@ config SERIAL_OF_PLATFORM are probed through devicetree, including Open Firmware based PowerPC systems and embedded systems on architectures using the flattened device tree format. + +config SERIAL_8250_NI16550 + bool "NI 16550 UART support" + depends on SERIAL_8250 + help + This driver supports the National Instruments (NI) 16550 UART port. diff --git a/drivers/tty/serial/8250/Makefile b/drivers/tty/serial/8250/Makefile index a8bfb654d4908..de5c8f2c877f8 100644 --- a/drivers/tty/serial/8250/Makefile +++ b/drivers/tty/serial/8250/Makefile @@ -39,5 +39,6 @@ obj-$(CONFIG_SERIAL_8250_MID) += 8250_mid.o obj-$(CONFIG_SERIAL_8250_PXA) += 8250_pxa.o obj-$(CONFIG_SERIAL_8250_TEGRA) += 8250_tegra.o obj-$(CONFIG_SERIAL_OF_PLATFORM) += 8250_of.o +obj-$(CONFIG_SERIAL_8250_NI16550) += 8250_ni16550.o CFLAGS_8250_ingenic.o += -I$(srctree)/scripts/dtc/libfdt diff --git a/include/linux/ni16550.h b/include/linux/ni16550.h new file mode 100644 index 0000000000000..eea3857551d4a --- /dev/null +++ b/include/linux/ni16550.h @@ -0,0 +1,26 @@ +/* + * NI 16550 Transceiver Driver + * + * The National Instruments (NI) 16550 has built-in RS-485 transceiver control + * circuitry. This driver provides the transceiver control functionality + * for the RS-485 ports and uses the 8250 driver for the UART functionality. + * + * Copyright 2012 National Instruments Corporation + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + */ + +#ifndef _NI16550_H +#define _NI16550_H + +void ni16550_port_setup(struct uart_port *port); + +#endif diff --git a/include/uapi/linux/serial_core.h b/include/uapi/linux/serial_core.h index 851b982f8c4b8..80eb93cfd5d23 100644 --- a/include/uapi/linux/serial_core.h +++ b/include/uapi/linux/serial_core.h @@ -279,4 +279,7 @@ /* Freescale LINFlexD UART */ #define PORT_LINFLEXUART 122 +/* National Instruments 16550 UART */ +#define PORT_NI16550 123 + #endif /* _UAPILINUX_SERIAL_CORE_H */ diff --git a/include/uapi/linux/serial_reg.h b/include/uapi/linux/serial_reg.h index be07b5470f4bb..57aa4c42a43ff 100644 --- a/include/uapi/linux/serial_reg.h +++ b/include/uapi/linux/serial_reg.h @@ -63,6 +63,7 @@ * TI16C750: 1 16 32 56 xx xx xx xx PORT_16750 * TI16C752: 8 16 56 60 8 16 32 56 * Tegra: 1 4 8 14 16 8 4 1 PORT_TEGRA + * NI 16550: 1 32 64 112 xx xx xx xx PORT_NI16550 */ #define UART_FCR_R_TRIG_00 0x00 #define UART_FCR_R_TRIG_01 0x40 From 1640ee426149d4fc12dd8a3b6fe813cebdd0a17e Mon Sep 17 00:00:00 2001 From: Karthik Manamcheri Date: Wed, 12 Mar 2014 13:09:29 -0500 Subject: [PATCH 040/110] 8250_pnp: Make NIC7750 ID spawn a NI 16550 port This commit adds a new ACPI ID, NIC7750, which will be used to represent a National Instruments NI 16550 UART. To enable this driver, you need to set CONFIG_SERIAL_8250_NI16550 in the kernel config. Signed-off-by: Karthik Manamcheri Acked-by: Jaeden Amero --- drivers/tty/serial/8250/8250_pnp.c | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/drivers/tty/serial/8250/8250_pnp.c b/drivers/tty/serial/8250/8250_pnp.c index de90d681b64c3..46aad96965fb3 100644 --- a/drivers/tty/serial/8250/8250_pnp.c +++ b/drivers/tty/serial/8250/8250_pnp.c @@ -20,9 +20,21 @@ #include "8250.h" +#include + #define UNKNOWN_DEV 0x3000 #define CIR_PORT 0x0800 +#define NI_PORT_ID "NIC7750" +#define NI_PORT_CLK 33333333 +static bool is_niport(struct pnp_dev *dev) +{ + if (strncmp(dev->id->id, NI_PORT_ID, sizeof(NI_PORT_ID)) == 0) + return true; + else + return false; +} + static const struct pnp_device_id pnp_dev_table[] = { /* Archtek America Corp. */ /* Archtek SmartLink Modem 3334BT Plug & Play */ @@ -194,6 +206,8 @@ static const struct pnp_device_id pnp_dev_table[] = { /* Com 1 */ /* Deskline K56 Phone System PnP */ { "MVX00A1", 0 }, + /* National Instruments (NI) 16550 PNP */ + { NI_PORT_ID, 0 }, /* PC Rider K56 Phone System PnP */ { "MVX00F2", 0 }, /* NEC 98NOTE SPEAKER PHONE FAX MODEM(33600bps) */ @@ -477,6 +491,14 @@ serial_pnp_probe(struct pnp_dev *dev, const struct pnp_device_id *dev_id) uart.port.uartclk = 1843200; uart.port.dev = &dev->dev; +#ifdef CONFIG_SERIAL_8250_NI16550 + if (is_niport(dev)) { + uart.port.uartclk = NI_PORT_CLK; + uart.port.flags |= UPF_FIXED_PORT | UPF_FIXED_TYPE; + uart.port.type = PORT_NI16550; + ni16550_port_setup(&uart.port); + } +#endif line = serial8250_register_8250_port(&uart); if (line < 0 || (flags & CIR_PORT)) return -ENODEV; From 9f44a76245089d7d55339acfcbd9436ec1d44715 Mon Sep 17 00:00:00 2001 From: Karthik Manamcheri Date: Thu, 22 May 2014 15:29:15 -0500 Subject: [PATCH 041/110] 8250_pnp: NI ACPI IDs start with NIC To determine if a device is a NI device, we should check the first three characters of the ACPI ID (All NI IDs start with "NIC"). Signed-off-by: Karthik Manamcheri Acked-by: Jaeden Amero --- drivers/tty/serial/8250/8250_pnp.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/drivers/tty/serial/8250/8250_pnp.c b/drivers/tty/serial/8250/8250_pnp.c index 46aad96965fb3..e49971960f575 100644 --- a/drivers/tty/serial/8250/8250_pnp.c +++ b/drivers/tty/serial/8250/8250_pnp.c @@ -25,11 +25,12 @@ #define UNKNOWN_DEV 0x3000 #define CIR_PORT 0x0800 -#define NI_PORT_ID "NIC7750" -#define NI_PORT_CLK 33333333 +#define NI_CLK_33333333 0x0002 + static bool is_niport(struct pnp_dev *dev) { - if (strncmp(dev->id->id, NI_PORT_ID, sizeof(NI_PORT_ID)) == 0) + /* All National Instruments ACPI IDs start with NIC */ + if (strncmp(dev->id->id, "NIC", 3) == 0) return true; else return false; @@ -206,10 +207,10 @@ static const struct pnp_device_id pnp_dev_table[] = { /* Com 1 */ /* Deskline K56 Phone System PnP */ { "MVX00A1", 0 }, - /* National Instruments (NI) 16550 PNP */ - { NI_PORT_ID, 0 }, /* PC Rider K56 Phone System PnP */ { "MVX00F2", 0 }, + /* National Instruments (NI) 16550 PNP */ + { "NIC7750", NI_CLK_33333333 }, /* NEC 98NOTE SPEAKER PHONE FAX MODEM(33600bps) */ { "nEC8241", 0 }, /* Pace 56 Voice Internal Plug & Play Modem */ @@ -493,7 +494,9 @@ serial_pnp_probe(struct pnp_dev *dev, const struct pnp_device_id *dev_id) #ifdef CONFIG_SERIAL_8250_NI16550 if (is_niport(dev)) { - uart.port.uartclk = NI_PORT_CLK; + if (flags & NI_CLK_33333333) + uart.port.uartclk = 33333333; + uart.port.flags |= UPF_FIXED_PORT | UPF_FIXED_TYPE; uart.port.type = PORT_NI16550; ni16550_port_setup(&uart.port); From 440831a1d83fdd2ed83c4d459ff7dee062571a66 Mon Sep 17 00:00:00 2001 From: Karthik Manamcheri Date: Thu, 22 May 2014 15:50:09 -0500 Subject: [PATCH 042/110] 8250_pnp: Support dual-mode UART through PMR The NI CVS-1459RT Controller has a NI 16550 UART which can be connected to either a RS-232 transceiver or a RS-485 transceiver. This dual-mode support is implemented through the Port Mode Register (PMR). This change will add support for the 8250 PNP driver to read the PMR and based on the mode, will register the appropriate driver. Signed-off-by: Karthik Manamcheri Acked-by: Jaeden Amero Acked-by: Justin Tang --- drivers/tty/serial/8250/8250_ni16550.c | 50 ++++++++++++++++++++++++++ drivers/tty/serial/8250/8250_pnp.c | 19 ++++++++-- include/linux/ni16550.h | 1 + 3 files changed, 68 insertions(+), 2 deletions(-) diff --git a/drivers/tty/serial/8250/8250_ni16550.c b/drivers/tty/serial/8250/8250_ni16550.c index d8dc0960fc3b2..5c886836ae056 100644 --- a/drivers/tty/serial/8250/8250_ni16550.c +++ b/drivers/tty/serial/8250/8250_ni16550.c @@ -32,6 +32,33 @@ #define NI16550_PCR_TXVR_ENABLE_BIT (1 << 3) #define NI16550_PCR_RS485_TERMINATION_BIT (1 << 6) +#define NI16550_PMR_OFFSET 0x0E +/* + * PMR[1:0] - Port Capabilities + * + * 0 - Register not implemented/supported + * 1 - RS-232 capable + * 2 - RS-485 capable + * 3 - RS-232/RS-485 dual-mode capable + * + */ +#define NI16550_PMR_CAP_MASK 0x03 +#define NI16550_PMR_NOT_IMPL 0x00 +#define NI16550_PMR_CAP_RS232 0x01 +#define NI16550_PMR_CAP_RS485 0x02 +#define NI16550_PMR_CAP_DUAL 0x03 +/* + * PMR[4] - Interface Mode + * + * 0 - RS-232 mode + * 1 - RS-485 mode + * + */ +#define NI16550_PMR_MODE_MASK 0x10 +#define NI16550_PMR_MODE_RS232 0x00 +#define NI16550_PMR_MODE_RS485 0x10 + + static int ni16550_enable_transceivers(struct uart_port *port) { uint8_t pcr; @@ -118,6 +145,29 @@ static int ni16550_config_rs485(struct uart_port *port, return 0; } +bool is_rs232_mode(unsigned long iobase) +{ + uint8_t pmr = inb(iobase + NI16550_PMR_OFFSET); + + /* If the PMR is not implemented, then by default NI UARTs are + * connected to RS-485 transceivers + */ + if ((pmr & NI16550_PMR_CAP_MASK) == NI16550_PMR_NOT_IMPL) + return false; + + if ((pmr & NI16550_PMR_CAP_MASK) == NI16550_PMR_CAP_DUAL) + /* If the port is dual-mode capable, then read the mode bit + * to know the current mode + */ + return ((pmr & NI16550_PMR_MODE_MASK) + == NI16550_PMR_MODE_RS232); + else + /* If it is not dual-mode capable, then decide based on the + * capability + */ + return ((pmr & NI16550_PMR_CAP_MASK) == NI16550_PMR_CAP_RS232); +} + static struct txvr_ops ni16550_txvr_ops = { .enable_transceivers = ni16550_enable_transceivers, .disable_transceivers = ni16550_disable_transceivers, diff --git a/drivers/tty/serial/8250/8250_pnp.c b/drivers/tty/serial/8250/8250_pnp.c index e49971960f575..36885482e2a55 100644 --- a/drivers/tty/serial/8250/8250_pnp.c +++ b/drivers/tty/serial/8250/8250_pnp.c @@ -26,6 +26,7 @@ #define CIR_PORT 0x0800 #define NI_CLK_33333333 0x0002 +#define NI_CAP_PMR 0x0001 static bool is_niport(struct pnp_dev *dev) { @@ -496,10 +497,24 @@ serial_pnp_probe(struct pnp_dev *dev, const struct pnp_device_id *dev_id) if (is_niport(dev)) { if (flags & NI_CLK_33333333) uart.port.uartclk = 33333333; - uart.port.flags |= UPF_FIXED_PORT | UPF_FIXED_TYPE; uart.port.type = PORT_NI16550; - ni16550_port_setup(&uart.port); + + /* + * NI UARTs are by default connected to RS-485 transceivers, + * unless the PMR register is implemented, and the UART is + * dual-mode capable. Then it could be in RS-232 mode and if it + * is, we will register as a standard 8250 port. + */ + if ((flags & NI_CAP_PMR) && is_rs232_mode(uart.port.iobase)) + pr_info("NI 16550 at I/O 0x%x (irq = %d) is dual-mode capable and is in RS-232 mode\n", + (unsigned int)uart.port.iobase, + uart.port.irq); + else + /* Either the PMR register is not implemented, or it is + * and the UART is in RS-485 mode as set in the PMR + */ + ni16550_port_setup(&uart.port); } #endif line = serial8250_register_8250_port(&uart); diff --git a/include/linux/ni16550.h b/include/linux/ni16550.h index eea3857551d4a..a71d71c27ae44 100644 --- a/include/linux/ni16550.h +++ b/include/linux/ni16550.h @@ -21,6 +21,7 @@ #ifndef _NI16550_H #define _NI16550_H +bool is_rs232_mode(unsigned long iobase); void ni16550_port_setup(struct uart_port *port); #endif From 2feedcee5889fb847d0ee45040e4bbd406544e71 Mon Sep 17 00:00:00 2001 From: Karthik Manamcheri Date: Fri, 23 May 2014 10:00:22 -0500 Subject: [PATCH 043/110] 8250: NI 16550 can have different FIFO sizes The NI 16550 is a CPLD UART and depending on restrictions on CPLD size, different implementations can have different FIFO sizes. This change provides two NI 16550 types, one with a smaller 16-byte FIFOs and the other with the original 128-byte FIFOs. Signed-off-by: Karthik Manamcheri Acked-by: Justin Tang Acked-by: Jaeden Amero [bstreiff: renumber PORT_NI16550_*] Signed-off-by: Brandon Streiff --- drivers/tty/serial/8250/8250_pnp.c | 2 +- drivers/tty/serial/8250/8250_port.c | 14 ++++++++++++++ include/uapi/linux/serial_core.h | 3 ++- include/uapi/linux/serial_reg.h | 3 ++- 4 files changed, 19 insertions(+), 3 deletions(-) diff --git a/drivers/tty/serial/8250/8250_pnp.c b/drivers/tty/serial/8250/8250_pnp.c index 36885482e2a55..a424cd9f4ee93 100644 --- a/drivers/tty/serial/8250/8250_pnp.c +++ b/drivers/tty/serial/8250/8250_pnp.c @@ -498,7 +498,7 @@ serial_pnp_probe(struct pnp_dev *dev, const struct pnp_device_id *dev_id) if (flags & NI_CLK_33333333) uart.port.uartclk = 33333333; uart.port.flags |= UPF_FIXED_PORT | UPF_FIXED_TYPE; - uart.port.type = PORT_NI16550; + uart.port.type = PORT_NI16550_F128; /* * NI UARTs are by default connected to RS-485 transceivers, diff --git a/drivers/tty/serial/8250/8250_port.c b/drivers/tty/serial/8250/8250_port.c index b05f8c34b291a..9519a9465b573 100644 --- a/drivers/tty/serial/8250/8250_port.c +++ b/drivers/tty/serial/8250/8250_port.c @@ -306,6 +306,20 @@ static const struct serial8250_config uart_config[] = { .rxtrig_bytes = {1, 32, 64, 112}, .flags = UART_CAP_FIFO | UART_CAP_SLEEP, }, + [PORT_NI16550_F16] = { + .name = "NI 16550 (with 16-byte FIFOs)", + .fifo_size = 16, + .tx_loadsz = 16, + .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10, + .flags = UART_CAP_FIFO | UART_CAP_AFE | UART_CAP_EFR, + }, + [PORT_NI16550_F128] = { + .name = "NI 16550 (with 128-byte FIFOs)", + .fifo_size = 128, + .tx_loadsz = 128, + .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10, + .flags = UART_CAP_FIFO | UART_CAP_AFE | UART_CAP_EFR, + }, }; /* Uart divisor latch read */ diff --git a/include/uapi/linux/serial_core.h b/include/uapi/linux/serial_core.h index 80eb93cfd5d23..8cfcf768586d6 100644 --- a/include/uapi/linux/serial_core.h +++ b/include/uapi/linux/serial_core.h @@ -280,6 +280,7 @@ #define PORT_LINFLEXUART 122 /* National Instruments 16550 UART */ -#define PORT_NI16550 123 +#define PORT_NI16550_F16 123 /* 16-byte FIFOs */ +#define PORT_NI16550_F128 124 /* 128-byte FIFOs */ #endif /* _UAPILINUX_SERIAL_CORE_H */ diff --git a/include/uapi/linux/serial_reg.h b/include/uapi/linux/serial_reg.h index 57aa4c42a43ff..9452066276d51 100644 --- a/include/uapi/linux/serial_reg.h +++ b/include/uapi/linux/serial_reg.h @@ -63,7 +63,8 @@ * TI16C750: 1 16 32 56 xx xx xx xx PORT_16750 * TI16C752: 8 16 56 60 8 16 32 56 * Tegra: 1 4 8 14 16 8 4 1 PORT_TEGRA - * NI 16550: 1 32 64 112 xx xx xx xx PORT_NI16550 + * NI 16550: 1 4 8 14 xx xx xx xx PORT_NI16550_F16 + * NI 16550: 1 32 64 112 xx xx xx xx PORT_NI16550_F128 */ #define UART_FCR_R_TRIG_00 0x00 #define UART_FCR_R_TRIG_01 0x40 From ffbe7ce9fd393d399c2fcacc81c5d7e2a343ca43 Mon Sep 17 00:00:00 2001 From: Karthik Manamcheri Date: Fri, 23 May 2014 14:46:42 -0500 Subject: [PATCH 044/110] 8250_pnp: Provide NI_16BYTE_FIFO flag This change will provide a flag, NI_16BYTE_FIFO, which when used as the flag for ACPI IDs will spawn a NI UART with a 16-byte FIFO (instead of the default 128-byte FIFO) Signed-off-by: Karthik Manamcheri Acked-by: Justin Tang --- drivers/tty/serial/8250/8250_pnp.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/tty/serial/8250/8250_pnp.c b/drivers/tty/serial/8250/8250_pnp.c index a424cd9f4ee93..8d4ac36a72c13 100644 --- a/drivers/tty/serial/8250/8250_pnp.c +++ b/drivers/tty/serial/8250/8250_pnp.c @@ -25,6 +25,7 @@ #define UNKNOWN_DEV 0x3000 #define CIR_PORT 0x0800 +#define NI_16BYTE_FIFO 0x0004 #define NI_CLK_33333333 0x0002 #define NI_CAP_PMR 0x0001 @@ -498,7 +499,11 @@ serial_pnp_probe(struct pnp_dev *dev, const struct pnp_device_id *dev_id) if (flags & NI_CLK_33333333) uart.port.uartclk = 33333333; uart.port.flags |= UPF_FIXED_PORT | UPF_FIXED_TYPE; - uart.port.type = PORT_NI16550_F128; + + if (flags & NI_16BYTE_FIFO) + uart.port.type = PORT_NI16550_F16; + else + uart.port.type = PORT_NI16550_F128; /* * NI UARTs are by default connected to RS-485 transceivers, From b9f79d9d9b00bbe28c8dcb13beb6eab6e772f59b Mon Sep 17 00:00:00 2001 From: Karthik Manamcheri Date: Fri, 23 May 2014 15:59:54 -0500 Subject: [PATCH 045/110] 8250_pnp: Make NIC7772 spawn a dual-mode UART This commit adds a new ACPI ID, NIC7772. This ID represents a National Instruments NI 16550 UART which is dual-mode capable (Port Mode Register is implemented) and has 16-byte FIFOs. To use this port, you need to set CONFIG_SERIAL_8250_NI16550 in the kernel config. Signed-off-by: Karthik Manamcheri --- drivers/tty/serial/8250/8250_pnp.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/tty/serial/8250/8250_pnp.c b/drivers/tty/serial/8250/8250_pnp.c index 8d4ac36a72c13..1fc07075f5b66 100644 --- a/drivers/tty/serial/8250/8250_pnp.c +++ b/drivers/tty/serial/8250/8250_pnp.c @@ -212,7 +212,8 @@ static const struct pnp_device_id pnp_dev_table[] = { /* PC Rider K56 Phone System PnP */ { "MVX00F2", 0 }, /* National Instruments (NI) 16550 PNP */ - { "NIC7750", NI_CLK_33333333 }, + { "NIC7750", NI_CLK_33333333 }, + { "NIC7772", NI_CAP_PMR | NI_16BYTE_FIFO }, /* NEC 98NOTE SPEAKER PHONE FAX MODEM(33600bps) */ { "nEC8241", 0 }, /* Pace 56 Voice Internal Plug & Play Modem */ From edc6535ed5f661519dfa2bc6fac4eb3464dbb70e Mon Sep 17 00:00:00 2001 From: Nathan Sullivan Date: Tue, 26 Apr 2016 15:59:36 -0500 Subject: [PATCH 046/110] ACPI / PNP: Add IDs for NI 16550 to list Add the two PNP IDs for NI 16550 serial ports to the PNP device ID list, so they are enumerated as PNP devices. Signed-off-by: Nathan Sullivan Signed-off-by: Brad Mouring Acked-by: Xander Huff Natinst-ReviewBoard-ID: 135498 Natinst-CAR-ID: 584586 --- drivers/acpi/acpi_pnp.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/acpi/acpi_pnp.c b/drivers/acpi/acpi_pnp.c index 4ed755a963aa5..a54d1fe17f168 100644 --- a/drivers/acpi/acpi_pnp.c +++ b/drivers/acpi/acpi_pnp.c @@ -220,6 +220,8 @@ static const struct acpi_device_id acpi_pnp_device_ids[] = { {"MVX00A1"}, /* Deskline K56 Phone System PnP */ {"MVX00F2"}, /* PC Rider K56 Phone System PnP */ {"nEC8241"}, /* NEC 98NOTE SPEAKER PHONE FAX MODEM(33600bps) */ + {"NIC7750"}, /* National Instruments (NI) 16550 PNP */ + {"NIC7772"}, /* National Instruments (NI) 16550 PNP */ {"PMC2430"}, /* Pace 56 Voice Internal Plug & Play Modem */ {"PNP0500"}, /* Generic standard PC COM port */ {"PNP0501"}, /* Generic 16550A-compatible COM port */ From 953b46ea3f5fd09764c98b1ea363efecf3a5f025 Mon Sep 17 00:00:00 2001 From: Stephen Lee Date: Fri, 23 Dec 2016 00:26:24 -0600 Subject: [PATCH 047/110] 8250_pnp: Add new ID NIC792B for NI 16550 UART 25MHz Add the new ACPI ID NIC792B into 8250_pnp driver to support NI 16550 UART with 25MHz clock. Signed-off-by: Stephen Lee Signed-off-by: Brad Mouring Acked-by: Hui Chun Ong Reviewed-by: Jason Smith Natinst-ReviewBoard-ID: 166881 --- drivers/acpi/acpi_pnp.c | 1 + drivers/tty/serial/8250/8250_core.c | 1 + drivers/tty/serial/8250/8250_ni16550.c | 25 +++++++++++++++++++++++++ drivers/tty/serial/8250/8250_pnp.c | 20 ++++++++++++++++---- include/linux/ni16550.h | 1 + 5 files changed, 44 insertions(+), 4 deletions(-) diff --git a/drivers/acpi/acpi_pnp.c b/drivers/acpi/acpi_pnp.c index a54d1fe17f168..7fb47477acf70 100644 --- a/drivers/acpi/acpi_pnp.c +++ b/drivers/acpi/acpi_pnp.c @@ -222,6 +222,7 @@ static const struct acpi_device_id acpi_pnp_device_ids[] = { {"nEC8241"}, /* NEC 98NOTE SPEAKER PHONE FAX MODEM(33600bps) */ {"NIC7750"}, /* National Instruments (NI) 16550 PNP */ {"NIC7772"}, /* National Instruments (NI) 16550 PNP */ + {"NIC792B"}, /* National Instruments (NI) 16550 PNP */ {"PMC2430"}, /* Pace 56 Voice Internal Plug & Play Modem */ {"PNP0500"}, /* Generic standard PC COM port */ {"PNP0501"}, /* Generic 16550A-compatible COM port */ diff --git a/drivers/tty/serial/8250/8250_core.c b/drivers/tty/serial/8250/8250_core.c index 384a2e68353de..8c87984a89976 100644 --- a/drivers/tty/serial/8250/8250_core.c +++ b/drivers/tty/serial/8250/8250_core.c @@ -1026,6 +1026,7 @@ int serial8250_register_8250_port(struct uart_8250_port *up) uart->rs485_start_tx = up->rs485_start_tx; uart->rs485_stop_tx = up->rs485_stop_tx; uart->dma = up->dma; + uart->mcr_force = up->mcr_force; /* Take tx_loadsz from fifosize if it wasn't set separately */ if (uart->port.fifosize && !uart->tx_loadsz) diff --git a/drivers/tty/serial/8250/8250_ni16550.c b/drivers/tty/serial/8250/8250_ni16550.c index 5c886836ae056..a36fdae983ca6 100644 --- a/drivers/tty/serial/8250/8250_ni16550.c +++ b/drivers/tty/serial/8250/8250_ni16550.c @@ -168,6 +168,31 @@ bool is_rs232_mode(unsigned long iobase) return ((pmr & NI16550_PMR_CAP_MASK) == NI16550_PMR_CAP_RS232); } +void ni16550_config_prescaler(unsigned long iobase, uint8_t prescaler) +{ + /* Page in the Enhanced Mode Registers + * Sets EFR[4] for Enhanced Mode. + */ + uint8_t lcr_value; + + lcr_value = inb(iobase + UART_LCR); + outb(UART_LCR_CONF_MODE_B, iobase + UART_LCR); + + uint8_t efr_value; + + efr_value = inb(iobase + UART_EFR); + efr_value |= UART_EFR_ECB; + + outb(efr_value, iobase + UART_EFR); + + /* Page out the Enhanced Mode Registers */ + outb(lcr_value, iobase + UART_LCR); + + /* Set prescaler to CPR register. */ + outb(UART_CPR, iobase + UART_SCR); + outb(prescaler, iobase + UART_ICR); +} + static struct txvr_ops ni16550_txvr_ops = { .enable_transceivers = ni16550_enable_transceivers, .disable_transceivers = ni16550_disable_transceivers, diff --git a/drivers/tty/serial/8250/8250_pnp.c b/drivers/tty/serial/8250/8250_pnp.c index 1fc07075f5b66..f4eb3c2ac803e 100644 --- a/drivers/tty/serial/8250/8250_pnp.c +++ b/drivers/tty/serial/8250/8250_pnp.c @@ -25,9 +25,10 @@ #define UNKNOWN_DEV 0x3000 #define CIR_PORT 0x0800 -#define NI_16BYTE_FIFO 0x0004 -#define NI_CLK_33333333 0x0002 -#define NI_CAP_PMR 0x0001 +#define NI_16BYTE_FIFO 0x0004 +#define NI_CAP_PMR 0x0001 +#define NI_CLK_33333333 0x0002 +#define NI_CPR_CLK_25000000 0x0008 static bool is_niport(struct pnp_dev *dev) { @@ -214,6 +215,7 @@ static const struct pnp_device_id pnp_dev_table[] = { /* National Instruments (NI) 16550 PNP */ { "NIC7750", NI_CLK_33333333 }, { "NIC7772", NI_CAP_PMR | NI_16BYTE_FIFO }, + { "NIC792B", NI_CPR_CLK_25000000 }, /* NEC 98NOTE SPEAKER PHONE FAX MODEM(33600bps) */ { "nEC8241", 0 }, /* Pace 56 Voice Internal Plug & Play Modem */ @@ -497,8 +499,19 @@ serial_pnp_probe(struct pnp_dev *dev, const struct pnp_device_id *dev_id) #ifdef CONFIG_SERIAL_8250_NI16550 if (is_niport(dev)) { + WARN_ON((flags & (NI_CLK_33333333 | NI_CPR_CLK_25000000)) == + (NI_CLK_33333333 | NI_CPR_CLK_25000000)); if (flags & NI_CLK_33333333) uart.port.uartclk = 33333333; + if (flags & NI_CPR_CLK_25000000) { + /* Sets UART clock rate to 22.222 MHz + * with prescaler 1.125. + */ + uart.port.uartclk = 22222222; + uart.mcr_force = UART_MCR_CLKSEL; + ni16550_config_prescaler(uart.port.iobase, 0x9); + } + uart.port.flags |= UPF_FIXED_PORT | UPF_FIXED_TYPE; if (flags & NI_16BYTE_FIFO) @@ -585,4 +598,3 @@ void serial8250_pnp_exit(void) { pnp_unregister_driver(&serial_pnp_driver); } - diff --git a/include/linux/ni16550.h b/include/linux/ni16550.h index a71d71c27ae44..155277de2f1aa 100644 --- a/include/linux/ni16550.h +++ b/include/linux/ni16550.h @@ -23,5 +23,6 @@ bool is_rs232_mode(unsigned long iobase); void ni16550_port_setup(struct uart_port *port); +void ni16550_config_prescaler(unsigned long iobase, uint8_t prescaler); #endif From 74d1f3522d9585057c39f4bab3f3c28f0672ffc3 Mon Sep 17 00:00:00 2001 From: Karthik Manamcheri Date: Fri, 14 Mar 2014 13:15:59 -0500 Subject: [PATCH 048/110] 8250: Make SERIAL_8250_RUNTIME_UARTS work correctly Consider a situation where I have an ARM based system (such as the Zynq) and therefore no legacy ports. I have three memory-mapped ports (such as cRIO-9068). I use device tree to describe the ports. What would be the config options I set so that I get only the three ports in my system? I do not want legacy ports being created automatically and I want it to be flexible enough that it creates the devices based only on the device tree. I expected setting SERIAL_8250_RUNTIME_UARTS = 0 to work because the description said, "Set this to the maximum number of serial ports you want the kernel to register at boot time." Unfortunately, even though SERIAL_8250_NR_UARTS was set to the default value of 4, I did not get any device nodes (because SERIAL_8250_RUNTIME_UARTS was 0). This is what this change is addressing. SERIAL_8250_NR_UARTS controls the maximum number of ports you can support. SERIAL_8250_RUNTIME_UARTS specifies the number of ports you want to create automatically for legacy ports at boot time. All other ports will be created when serial8250_register_port is called (and if it does not exceed the total number of supported ports as specified by SERIAL_8250_NR_UARTS). Signed-off-by: Karthik Manamcheri Acked-by: Jaeden Amero --- drivers/tty/serial/8250/8250_core.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/tty/serial/8250/8250_core.c b/drivers/tty/serial/8250/8250_core.c index 8c87984a89976..16878472c78f1 100644 --- a/drivers/tty/serial/8250/8250_core.c +++ b/drivers/tty/serial/8250/8250_core.c @@ -503,7 +503,7 @@ static void __init serial8250_isa_init_ports(void) if (nr_uarts > UART_NR) nr_uarts = UART_NR; - for (i = 0; i < nr_uarts; i++) { + for (i = 0; i < UART_NR; i++) { struct uart_8250_port *up = &serial8250_ports[i]; struct uart_port *port = &up->port; @@ -602,7 +602,7 @@ static int univ8250_console_setup(struct console *co, char *options) * if so, search for the first available port that does have * console support. */ - if (co->index >= nr_uarts) + if (co->index >= UART_NR) co->index = 0; port = &serial8250_ports[co->index].port; /* link port to console */ @@ -655,7 +655,7 @@ static int univ8250_console_match(struct console *co, char *name, int idx, return -ENODEV; /* try to match the port specified on the command line */ - for (i = 0; i < nr_uarts; i++) { + for (i = 0; i < UART_NR; i++) { struct uart_port *port = &serial8250_ports[i].port; if (port->iotype != iotype) @@ -862,7 +862,7 @@ static int serial8250_remove(struct platform_device *dev) { int i; - for (i = 0; i < nr_uarts; i++) { + for (i = 0; i < UART_NR; i++) { struct uart_8250_port *up = &serial8250_ports[i]; if (up->port.dev == &dev->dev) @@ -929,7 +929,7 @@ static struct uart_8250_port *serial8250_find_match_or_unused(struct uart_port * /* * First, find a port entry which matches. */ - for (i = 0; i < nr_uarts; i++) + for (i = 0; i < UART_NR; i++) if (uart_match_port(&serial8250_ports[i].port, port)) return &serial8250_ports[i]; @@ -943,7 +943,7 @@ static struct uart_8250_port *serial8250_find_match_or_unused(struct uart_port * * free entry. We look for one which hasn't been previously * used (indicated by zero iobase). */ - for (i = 0; i < nr_uarts; i++) + for (i = 0; i < UART_NR; i++) if (serial8250_ports[i].port.type == PORT_UNKNOWN && serial8250_ports[i].port.iobase == 0) return &serial8250_ports[i]; @@ -952,7 +952,7 @@ static struct uart_8250_port *serial8250_find_match_or_unused(struct uart_port * * That also failed. Last resort is to find any entry which * doesn't have a real port associated with it. */ - for (i = 0; i < nr_uarts; i++) + for (i = 0; i < UART_NR; i++) if (serial8250_ports[i].port.type == PORT_UNKNOWN) return &serial8250_ports[i]; From 6a8a020a8aebbde06bdc76e9f7310f7fd1a81659 Mon Sep 17 00:00:00 2001 From: Richard Tollerton Date: Fri, 21 Apr 2017 14:13:52 -0500 Subject: [PATCH 049/110] Revert "serial: 8250: Do nothing if nr_uarts=0" This reverts commit 59cfc45f17d6d1dda2990e6f5a94df24a18330b8. It conflicts with "8250: Make SERIAL_8250_RUNTIME_UARTS work correctly", and so prevents systems whose UARTs are all hotplugged from being able to set nr_uarts=0 on bootup. Natinst-CAR-ID: 634278 Signed-off-by: Richard Tollerton Signed-off-by: Brad Mouring Natinst-ReviewBoard-ID: 183619 --- drivers/tty/serial/8250/8250_core.c | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/drivers/tty/serial/8250/8250_core.c b/drivers/tty/serial/8250/8250_core.c index 16878472c78f1..ae1f8c22424ef 100644 --- a/drivers/tty/serial/8250/8250_core.c +++ b/drivers/tty/serial/8250/8250_core.c @@ -690,9 +690,6 @@ static struct console univ8250_console = { static int __init univ8250_console_init(void) { - if (nr_uarts == 0) - return -ENODEV; - serial8250_isa_init_ports(); register_console(&univ8250_console); return 0; @@ -723,7 +720,7 @@ int __init early_serial_setup(struct uart_port *port) { struct uart_port *p; - if (port->line >= ARRAY_SIZE(serial8250_ports) || nr_uarts == 0) + if (port->line >= ARRAY_SIZE(serial8250_ports)) return -ENODEV; serial8250_isa_init_ports(); @@ -1177,9 +1174,6 @@ static int __init serial8250_init(void) { int ret; - if (nr_uarts == 0) - return -ENODEV; - serial8250_isa_init_ports(); pr_info("Serial: 8250/16550 driver, %d ports, IRQ sharing %sabled\n", From 179d0221810454f0e5eeed16277880e861e48615 Mon Sep 17 00:00:00 2001 From: Gratian Crisan Date: Thu, 24 Mar 2016 13:52:00 -0500 Subject: [PATCH 050/110] time: Make the clocksource watchdog user configurable The clocksource watchdog is used to detect instabilities in the current clocksource. This is a beneficial feature on new/unknown hardware however it can create problems by falsely triggering when the watchdog wraps. The reason is that an interrupt storm and/or high priority (FIFO/RR) tasks can preempt the timer softirq long enough for the watchdog to wrap if it has a limited number of bits available by comparison with the main clocksource. One observed example is on a Intel Baytrail platform where TSC is the main clocksource, HPET is disabled due to a hardware bug and acpi_pm gets selected as the watchdog clocksource. Provide the option to disable the clocksource watchdog for hardware where the clocksource stability has been validated. Signed-off-by: Gratian Crisan --- arch/x86/Kconfig | 2 +- kernel/time/Kconfig | 12 +++++++++++- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index dd6db73b6458f..ed6d0a84c928b 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -106,7 +106,7 @@ config X86 select BUILDTIME_TABLE_SORT select CLKEVT_I8253 select CLOCKSOURCE_VALIDATE_LAST_CYCLE - select CLOCKSOURCE_WATCHDOG + select HAVE_CLOCKSOURCE_WATCHDOG select DCACHE_WORD_ACCESS select EDAC_ATOMIC_SCRUB select EDAC_SUPPORT diff --git a/kernel/time/Kconfig b/kernel/time/Kconfig index a09b1d61df6a5..e22a4ecda5dae 100644 --- a/kernel/time/Kconfig +++ b/kernel/time/Kconfig @@ -6,7 +6,7 @@ # Options selectable by arch Kconfig # Watchdog function for clocksources to detect instabilities -config CLOCKSOURCE_WATCHDOG +config HAVE_CLOCKSOURCE_WATCHDOG bool # Architecture has extra clocksource data @@ -173,5 +173,15 @@ config HIGH_RES_TIMERS hardware is not capable then this option only increases the size of the kernel image. +config CLOCKSOURCE_WATCHDOG + bool "Clocksource watchdog" + depends on HAVE_CLOCKSOURCE_WATCHDOG + default y + help + This option enables the watchdog function for clocksources. It is + used to detect instabilities in the currently selected clocksource. + + Say Y if you are unsure. + endmenu endif From 4f5285bbfd5efe2c29c7e49c8f9a206ce24055a0 Mon Sep 17 00:00:00 2001 From: Josh Cartwright Date: Tue, 19 May 2015 19:24:43 -0500 Subject: [PATCH 051/110] nati_x86_64_defconfig: add initial defconfig for NI x86_64-based targets Signed-off-by: Josh Cartwright --- arch/x86/configs/nati_x86_64_defconfig | 520 +++++++++++++++++++++++++ 1 file changed, 520 insertions(+) create mode 100644 arch/x86/configs/nati_x86_64_defconfig diff --git a/arch/x86/configs/nati_x86_64_defconfig b/arch/x86/configs/nati_x86_64_defconfig new file mode 100644 index 0000000000000..797c1eb8e0cf4 --- /dev/null +++ b/arch/x86/configs/nati_x86_64_defconfig @@ -0,0 +1,520 @@ +CONFIG_SYSVIPC=y +CONFIG_POSIX_MQUEUE=y +CONFIG_AUDIT=y +CONFIG_HIGH_RES_TIMERS=y +# CONFIG_CLOCKSOURCE_WATCHDOG is not set +CONFIG_VIRT_CPU_ACCOUNTING_GEN=y +CONFIG_BSD_PROCESS_ACCT=y +CONFIG_BSD_PROCESS_ACCT_V3=y +# CONFIG_CONTEXT_TRACKING_FORCE is not set +CONFIG_RCU_NOCB_CPU=y +CONFIG_RCU_NOCB_CPU_ALL=y +CONFIG_IKCONFIG=y +CONFIG_IKCONFIG_PROC=y +CONFIG_LOG_BUF_SHIFT=18 +CONFIG_CGROUPS=y +CONFIG_CPUSETS=y +# CONFIG_PROC_PID_CPUSET is not set +CONFIG_CGROUP_CPUACCT=y +CONFIG_RELAY=y +CONFIG_BLK_DEV_INITRD=y +CONFIG_SYSCTL_SYSCALL=y +CONFIG_KALLSYMS_ALL=y +# CONFIG_PCSPKR_PLATFORM is not set +CONFIG_EMBEDDED=y +# CONFIG_SLUB_DEBUG is not set +# CONFIG_COMPAT_BRK is not set +CONFIG_JUMP_LABEL=y +CONFIG_MODULES=y +CONFIG_MODULE_UNLOAD=y +CONFIG_MODVERSIONS=y +CONFIG_BLK_DEV_INTEGRITY=y +CONFIG_SMP=y +CONFIG_X86_X2APIC=y +# CONFIG_X86_EXTENDED_PLATFORM is not set +CONFIG_X86_INTEL_LPSS=y +# CONFIG_SCHED_OMIT_FRAME_POINTER is not set +CONFIG_PROCESSOR_SELECT=y +# CONFIG_CPU_SUP_AMD is not set +# CONFIG_CPU_SUP_CENTAUR is not set +CONFIG_NR_CPUS=16 +# CONFIG_SCHED_MC is not set +CONFIG_PREEMPT_RT_FULL=y +CONFIG_X86_REROUTE_FOR_BROKEN_BOOT_IRQS=y +# CONFIG_X86_MCE_AMD is not set +CONFIG_X86_MSR=m +CONFIG_X86_CPUID=m +CONFIG_NUMA=y +# CONFIG_AMD_NUMA is not set +CONFIG_KSM=y +CONFIG_DEFAULT_MMAP_MIN_ADDR=65536 +CONFIG_MEMORY_FAILURE=y +CONFIG_CLEANCACHE=y +CONFIG_MTRR_SANITIZER_ENABLE_DEFAULT=1 +CONFIG_EFI=y +CONFIG_HZ_100=y +# CONFIG_MODIFY_LDT_SYSCALL is not set +# CONFIG_SUSPEND is not set +# CONFIG_ACPI_AC is not set +# CONFIG_ACPI_BATTERY is not set +CONFIG_ACPI_BUTTON=m +# CONFIG_ACPI_FAN is not set +# CONFIG_ACPI_THERMAL is not set +CONFIG_ACPI_APEI=y +CONFIG_ACPI_APEI_GHES=y +CONFIG_ACPI_APEI_PCIEAER=y +CONFIG_ACPI_APEI_MEMORY_FAILURE=y +CONFIG_SFI=y +CONFIG_CPU_FREQ=y +# CONFIG_CPU_FREQ_STAT is not set +CONFIG_X86_INTEL_PSTATE=y +CONFIG_INTEL_IDLE=y +CONFIG_PCI_MMCONFIG=y +CONFIG_PCIEPORTBUS=y +# CONFIG_PCIEASPM is not set +CONFIG_PCI_MSI=y +CONFIG_PCI_IOV=y +CONFIG_PCI_PRI=y +CONFIG_PCI_PASID=y +# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set +CONFIG_IA32_EMULATION=y +CONFIG_NET=y +CONFIG_PACKET=y +CONFIG_UNIX=y +CONFIG_INET=y +CONFIG_IP_MULTICAST=y +CONFIG_IP_ADVANCED_ROUTER=y +CONFIG_IP_MULTIPLE_TABLES=y +CONFIG_IP_ROUTE_MULTIPATH=y +CONFIG_IP_ROUTE_VERBOSE=y +CONFIG_IP_PNP=y +CONFIG_IP_PNP_DHCP=y +CONFIG_IP_PNP_BOOTP=y +CONFIG_IP_PNP_RARP=y +CONFIG_NET_IPIP=m +CONFIG_NET_IPGRE_DEMUX=m +CONFIG_NET_IPGRE=m +CONFIG_NET_IPGRE_BROADCAST=y +CONFIG_IP_MROUTE=y +CONFIG_IP_MROUTE_MULTIPLE_TABLES=y +CONFIG_IP_PIMSM_V1=y +CONFIG_IP_PIMSM_V2=y +CONFIG_INET_AH=m +CONFIG_INET_ESP=m +CONFIG_INET_IPCOMP=m +CONFIG_INET_XFRM_MODE_TRANSPORT=m +CONFIG_INET_XFRM_MODE_TUNNEL=m +CONFIG_INET_XFRM_MODE_BEET=m +CONFIG_INET_DIAG=m +CONFIG_IPV6=m +CONFIG_INET6_AH=m +CONFIG_INET6_ESP=m +CONFIG_INET6_IPCOMP=m +CONFIG_NETFILTER=y +CONFIG_NETFILTER_DEBUG=y +CONFIG_NF_CONNTRACK=m +CONFIG_NF_CONNTRACK_EVENTS=y +CONFIG_NF_CONNTRACK_TIMESTAMP=y +CONFIG_NF_CT_PROTO_DCCP=m +CONFIG_NF_CT_PROTO_SCTP=m +CONFIG_NF_CT_PROTO_UDPLITE=m +CONFIG_NF_CONNTRACK_AMANDA=m +CONFIG_NF_CONNTRACK_FTP=m +CONFIG_NF_CONNTRACK_H323=m +CONFIG_NF_CONNTRACK_IRC=m +CONFIG_NF_CONNTRACK_NETBIOS_NS=m +CONFIG_NF_CONNTRACK_SNMP=m +CONFIG_NF_CONNTRACK_PPTP=m +CONFIG_NF_CONNTRACK_SANE=m +CONFIG_NF_CONNTRACK_SIP=m +CONFIG_NF_CONNTRACK_TFTP=m +CONFIG_NF_CT_NETLINK=m +CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m +CONFIG_NETFILTER_XT_TARGET_CONNMARK=m +CONFIG_NETFILTER_XT_TARGET_IDLETIMER=m +CONFIG_NETFILTER_XT_TARGET_LOG=m +CONFIG_NETFILTER_XT_TARGET_MARK=m +CONFIG_NETFILTER_XT_TARGET_NFLOG=m +CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m +CONFIG_NETFILTER_XT_TARGET_TEE=m +CONFIG_NETFILTER_XT_TARGET_TCPMSS=m +CONFIG_NETFILTER_XT_MATCH_ADDRTYPE=m +CONFIG_NETFILTER_XT_MATCH_CLUSTER=m +CONFIG_NETFILTER_XT_MATCH_COMMENT=m +CONFIG_NETFILTER_XT_MATCH_CONNBYTES=m +CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=m +CONFIG_NETFILTER_XT_MATCH_CONNMARK=m +CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m +CONFIG_NETFILTER_XT_MATCH_CPU=m +CONFIG_NETFILTER_XT_MATCH_DCCP=m +CONFIG_NETFILTER_XT_MATCH_DEVGROUP=m +CONFIG_NETFILTER_XT_MATCH_DSCP=m +CONFIG_NETFILTER_XT_MATCH_ESP=m +CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=m +CONFIG_NETFILTER_XT_MATCH_HELPER=m +CONFIG_NETFILTER_XT_MATCH_IPRANGE=m +CONFIG_NETFILTER_XT_MATCH_LENGTH=m +CONFIG_NETFILTER_XT_MATCH_LIMIT=m +CONFIG_NETFILTER_XT_MATCH_MAC=m +CONFIG_NETFILTER_XT_MATCH_MARK=m +CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m +CONFIG_NETFILTER_XT_MATCH_OSF=m +CONFIG_NETFILTER_XT_MATCH_OWNER=m +CONFIG_NETFILTER_XT_MATCH_POLICY=m +CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m +CONFIG_NETFILTER_XT_MATCH_QUOTA=m +CONFIG_NETFILTER_XT_MATCH_RATEEST=m +CONFIG_NETFILTER_XT_MATCH_REALM=m +CONFIG_NETFILTER_XT_MATCH_RECENT=m +CONFIG_NETFILTER_XT_MATCH_SCTP=m +CONFIG_NETFILTER_XT_MATCH_STATE=m +CONFIG_NETFILTER_XT_MATCH_STATISTIC=m +CONFIG_NETFILTER_XT_MATCH_STRING=m +CONFIG_NETFILTER_XT_MATCH_TCPMSS=m +CONFIG_NETFILTER_XT_MATCH_TIME=m +CONFIG_NETFILTER_XT_MATCH_U32=m +CONFIG_NF_CONNTRACK_IPV4=m +CONFIG_IP_NF_IPTABLES=m +CONFIG_IP_NF_MATCH_AH=m +CONFIG_IP_NF_MATCH_ECN=m +CONFIG_IP_NF_MATCH_TTL=m +CONFIG_IP_NF_FILTER=m +CONFIG_IP_NF_TARGET_REJECT=m +CONFIG_IP_NF_MANGLE=m +CONFIG_IP_NF_TARGET_CLUSTERIP=m +CONFIG_IP_NF_TARGET_ECN=m +CONFIG_IP_NF_TARGET_TTL=m +CONFIG_IP_NF_RAW=m +CONFIG_IP_NF_ARPTABLES=m +CONFIG_IP_NF_ARPFILTER=m +CONFIG_IP_NF_ARP_MANGLE=m +CONFIG_NF_CONNTRACK_IPV6=m +CONFIG_IP6_NF_IPTABLES=m +CONFIG_IP6_NF_MATCH_AH=m +CONFIG_IP6_NF_MATCH_EUI64=m +CONFIG_IP6_NF_MATCH_FRAG=m +CONFIG_IP6_NF_MATCH_OPTS=m +CONFIG_IP6_NF_MATCH_HL=m +CONFIG_IP6_NF_MATCH_IPV6HEADER=m +CONFIG_IP6_NF_MATCH_MH=m +CONFIG_IP6_NF_MATCH_RT=m +CONFIG_IP6_NF_TARGET_HL=m +CONFIG_IP6_NF_FILTER=m +CONFIG_IP6_NF_TARGET_REJECT=m +CONFIG_IP6_NF_MANGLE=m +CONFIG_IP6_NF_RAW=m +CONFIG_L2TP=m +CONFIG_L2TP_DEBUGFS=m +CONFIG_L2TP_V3=y +CONFIG_L2TP_IP=m +CONFIG_L2TP_ETH=m +CONFIG_BRIDGE=m +CONFIG_VLAN_8021Q=m +CONFIG_NET_SCHED=y +CONFIG_NET_SCH_MULTIQ=m +CONFIG_NET_CLS_BASIC=m +CONFIG_NET_CLS_U32=m +CONFIG_NET_EMATCH=y +CONFIG_NET_EMATCH_CMP=m +CONFIG_NET_CLS_ACT=y +CONFIG_NET_ACT_SKBEDIT=m +CONFIG_DNS_RESOLVER=y +CONFIG_BPF_JIT=y +CONFIG_BT=m +CONFIG_BT_HCIBTUSB=m +CONFIG_CFG80211=m +CONFIG_NL80211_TESTMODE=y +CONFIG_CFG80211_WEXT=y +CONFIG_MAC80211=m +CONFIG_RFKILL=y +CONFIG_DEVTMPFS=y +CONFIG_DEVTMPFS_MOUNT=y +CONFIG_CONNECTOR=y +CONFIG_BLK_DEV_LOOP=y +CONFIG_BLK_DEV_RAM=y +CONFIG_VIRTIO_BLK=m +# CONFIG_HWLAT_DETECTOR is not set +CONFIG_NI_RT_FEATURES=y +CONFIG_NI_LED_PREFIX="nilrt" +CONFIG_NI_WATCHDOG=y +CONFIG_BLK_DEV_SD=y +CONFIG_BLK_DEV_SR=y +CONFIG_SCSI_SAS_ATA=y +CONFIG_SCSI_AACRAID=m +CONFIG_SCSI_MVSAS=m +CONFIG_SCSI_ARCMSR=m +CONFIG_SCSI_SYM53C8XX_2=m +CONFIG_ATA=y +CONFIG_SATA_AHCI=y +CONFIG_ATA_PIIX=y +CONFIG_SATA_MV=m +CONFIG_SATA_SIL=m +CONFIG_FIREWIRE=m +CONFIG_FIREWIRE_OHCI=m +CONFIG_FIREWIRE_SBP2=m +CONFIG_FIREWIRE_NET=m +CONFIG_NETDEVICES=y +CONFIG_BONDING=m +CONFIG_TUN=y +CONFIG_VIRTIO_NET=m +# CONFIG_NET_VENDOR_3COM is not set +# CONFIG_NET_VENDOR_ADAPTEC is not set +# CONFIG_NET_VENDOR_ALTEON is not set +# CONFIG_NET_VENDOR_AMD is not set +# CONFIG_NET_VENDOR_ATHEROS is not set +CONFIG_TIGON3=m +# CONFIG_NET_VENDOR_BROCADE is not set +# CONFIG_NET_VENDOR_CHELSIO is not set +# CONFIG_NET_VENDOR_CISCO is not set +# CONFIG_NET_VENDOR_DEC is not set +# CONFIG_NET_VENDOR_DLINK is not set +# CONFIG_NET_VENDOR_EMULEX is not set +# CONFIG_NET_VENDOR_EXAR is not set +# CONFIG_NET_VENDOR_HP is not set +CONFIG_E100=m +CONFIG_E1000=m +CONFIG_E1000E=m +CONFIG_E1000_DELAY=y +CONFIG_IGB=m +CONFIG_IGBVF=m +CONFIG_IXGB=m +CONFIG_IXGBE=m +# CONFIG_IXGBE_HWMON is not set +# CONFIG_NET_VENDOR_I825XX is not set +# CONFIG_NET_VENDOR_MARVELL is not set +# CONFIG_NET_VENDOR_MELLANOX is not set +# CONFIG_NET_VENDOR_MICREL is not set +# CONFIG_NET_VENDOR_MICROCHIP is not set +# CONFIG_NET_VENDOR_MYRI is not set +# CONFIG_NET_VENDOR_NATSEMI is not set +# CONFIG_NET_VENDOR_NVIDIA is not set +# CONFIG_NET_VENDOR_OKI is not set +# CONFIG_NET_PACKET_ENGINE is not set +# CONFIG_NET_VENDOR_QLOGIC is not set +# CONFIG_NET_VENDOR_REALTEK is not set +# CONFIG_NET_VENDOR_RDC is not set +# CONFIG_NET_VENDOR_SEEQ is not set +# CONFIG_NET_VENDOR_SILAN is not set +# CONFIG_NET_VENDOR_SIS is not set +# CONFIG_NET_VENDOR_SMSC is not set +# CONFIG_NET_VENDOR_STMICRO is not set +# CONFIG_NET_VENDOR_SUN is not set +# CONFIG_NET_VENDOR_TEHUTI is not set +# CONFIG_NET_VENDOR_TI is not set +# CONFIG_NET_VENDOR_VIA is not set +# CONFIG_NET_VENDOR_WIZNET is not set +CONFIG_PHYLIB=y +CONFIG_MICROCHIP_PHY=m +CONFIG_PPP=m +CONFIG_PPP_BSDCOMP=m +CONFIG_PPP_DEFLATE=m +CONFIG_PPP_ASYNC=m +CONFIG_PPP_SYNC_TTY=m +CONFIG_USB_CATC=m +CONFIG_USB_KAWETH=m +CONFIG_USB_PEGASUS=m +CONFIG_USB_RTL8150=m +CONFIG_USB_RTL8152=m +CONFIG_USB_USBNET=m +CONFIG_USB_NET_CDC_EEM=m +CONFIG_USB_NET_SMSC75XX=m +CONFIG_USB_NET_SMSC95XX=m +CONFIG_USB_NET_PLUSB=m +CONFIG_USB_NET_RNDIS_HOST=m +CONFIG_USB_IPHETH=m +CONFIG_USB_SIERRA_NET=m +CONFIG_USB_VL600=m +CONFIG_USB_NET_CH9200=m +CONFIG_CARL9170=m +CONFIG_ATH6KL=m +CONFIG_ATH6KL_SDIO=m +CONFIG_ATH6KL_USB=m +CONFIG_ATH6KL_NI_BIOS_DOMAIN=y +CONFIG_ATH6KL_SILEX_FIRMWARE=y +CONFIG_AR5523=m +CONFIG_AT76C50X_USB=m +CONFIG_MT7601U=m +CONFIG_RT2X00=m +CONFIG_RT2500USB=m +CONFIG_RT73USB=m +CONFIG_RT2800USB=m +CONFIG_RT2800USB_RT53XX=y +CONFIG_RT2800USB_RT55XX=y +CONFIG_RT2800USB_UNKNOWN=y +CONFIG_RTL8187=m +CONFIG_RTL8192CU=m +CONFIG_USB_ZD1201=m +CONFIG_ZD1211RW=m +CONFIG_INPUT_EVDEV=y +CONFIG_KEYBOARD_ATKBD=m +CONFIG_MOUSE_PS2=m +CONFIG_INPUT_TABLET=y +CONFIG_TABLET_SERIAL_WACOM4=m +CONFIG_INPUT_TOUCHSCREEN=y +CONFIG_TOUCHSCREEN_USB_COMPOSITE=m +CONFIG_SERIO=m +# CONFIG_DEVKMEM is not set +CONFIG_SERIAL_8250=y +CONFIG_SERIAL_8250_CONSOLE=y +CONFIG_SERIAL_8250_NR_UARTS=32 +CONFIG_SERIAL_8250_RUNTIME_UARTS=2 +CONFIG_SERIAL_8250_EXTENDED=y +CONFIG_SERIAL_8250_SHARE_IRQ=y +CONFIG_SERIAL_8250_DETECT_IRQ=y +CONFIG_SERIAL_8250_RSA=y +CONFIG_SERIAL_8250_DW=y +CONFIG_SERIAL_8250_NI16550=y +CONFIG_VIRTIO_CONSOLE=m +# CONFIG_HW_RANDOM_AMD is not set +# CONFIG_HW_RANDOM_VIA is not set +CONFIG_HPET=y +CONFIG_TCG_TPM=m +CONFIG_TCG_TIS=m +CONFIG_I2C=y +CONFIG_I2C_CHARDEV=m +CONFIG_I2C_I801=m +CONFIG_I2C_DESIGNWARE_PLATFORM=m +CONFIG_I2C_DESIGNWARE_PCI=m +CONFIG_SPI=y +CONFIG_SPI_PXA2XX=m +CONFIG_SPI_SPIDEV=m +CONFIG_PTP_1588_CLOCK=y +CONFIG_PINCTRL_BROXTON=y +CONFIG_SENSORS_CORETEMP=m +CONFIG_SENSORS_TMP421=m +CONFIG_WATCHDOG=y +CONFIG_SOFT_WATCHDOG=m +CONFIG_LPC_ICH=m +CONFIG_MEDIA_SUPPORT=m +CONFIG_MEDIA_CAMERA_SUPPORT=y +CONFIG_MEDIA_USB_SUPPORT=y +CONFIG_USB_VIDEO_CLASS=m +# CONFIG_USB_GSPCA is not set +CONFIG_AGP=m +CONFIG_DRM=m +CONFIG_DRM_RADEON=m +CONFIG_DRM_I915=m +CONFIG_DRM_I915_PRELIMINARY_HW_SUPPORT=y +CONFIG_FB=y +CONFIG_FB_MODE_HELPERS=y +CONFIG_FB_EFI=y +CONFIG_FRAMEBUFFER_CONSOLE=y +CONFIG_HID_MICROSOFT=m +CONFIG_HID_MULTITOUCH=m +CONFIG_HID_PENMOUNT=m +CONFIG_USB=y +CONFIG_USB_DYNAMIC_MINORS=y +CONFIG_USB_XHCI_HCD=y +CONFIG_USB_XHCI_PLATFORM=y +CONFIG_USB_EHCI_HCD=y +CONFIG_USB_EHCI_ROOT_HUB_TT=y +CONFIG_USB_UHCI_HCD=y +CONFIG_USB_STORAGE=y +CONFIG_USB_DWC3=m +CONFIG_USB_DWC3_GADGET=y +CONFIG_USB_SERIAL=m +CONFIG_USB_SERIAL_CH341=m +CONFIG_USB_SERIAL_WHITEHEAT=m +CONFIG_USB_SERIAL_DIGI_ACCELEPORT=m +CONFIG_USB_SERIAL_CP210X=m +CONFIG_USB_SERIAL_FTDI_SIO=m +CONFIG_USB_SERIAL_MOS7720=m +CONFIG_USB_SERIAL_MOS7840=m +CONFIG_USB_SERIAL_PL2303=m +CONFIG_USB_SERIAL_QUALCOMM=m +CONFIG_USB_SERIAL_SIERRAWIRELESS=m +CONFIG_NOP_USB_XCEIV=y +CONFIG_USB_GADGET=m +CONFIG_USB_ETH=m +# CONFIG_USB_ETH_RNDIS is not set +CONFIG_USB_ETH_EEM=y +CONFIG_MMC=y +CONFIG_MMC_SDHCI=y +CONFIG_MMC_SDHCI_PCI=y +CONFIG_MMC_SDHCI_ACPI=y +CONFIG_LEDS_CLASS=y +CONFIG_LEDS_NIC78BX=m +CONFIG_RTC_CLASS=y +CONFIG_DMADEVICES=y +CONFIG_DW_DMAC_PCI=y +CONFIG_VIRTIO_PCI=m +CONFIG_VIRTIO_BALLOON=m +CONFIG_VIRTIO_MMIO=m +CONFIG_INTEL_IOMMU=y +# CONFIG_INTEL_IOMMU_DEFAULT_ON is not set +CONFIG_IRQ_REMAP=y +CONFIG_EDD=y +CONFIG_EDD_OFF=y +CONFIG_DMI_SYSFS=m +CONFIG_ISCSI_IBFT_FIND=y +CONFIG_EFI_VARS=y +CONFIG_EXT2_FS=y +CONFIG_EXT2_FS_XATTR=y +CONFIG_EXT2_FS_POSIX_ACL=y +CONFIG_EXT2_FS_SECURITY=y +CONFIG_EXT3_FS=y +CONFIG_EXT3_FS_POSIX_ACL=y +CONFIG_EXT3_FS_SECURITY=y +CONFIG_BTRFS_FS=m +CONFIG_BTRFS_FS_POSIX_ACL=y +# CONFIG_DNOTIFY is not set +CONFIG_FUSE_FS=m +CONFIG_ISO9660_FS=y +CONFIG_MSDOS_FS=y +CONFIG_VFAT_FS=y +CONFIG_NTFS_FS=m +CONFIG_PROC_KCORE=y +CONFIG_TMPFS_POSIX_ACL=y +CONFIG_CONFIGFS_FS=y +CONFIG_EFIVAR_FS=y +CONFIG_SQUASHFS=m +CONFIG_SQUASHFS_XATTR=y +CONFIG_NFS_FS=m +CONFIG_NFS_V4=m +CONFIG_NFS_V4_1=y +CONFIG_CIFS=m +CONFIG_CIFS_XATTR=y +CONFIG_CIFS_POSIX=y +CONFIG_NLS_CODEPAGE_437=y +CONFIG_NLS_ASCII=y +CONFIG_NLS_ISO8859_1=y +CONFIG_NLS_UTF8=y +CONFIG_PRINTK_TIME=y +# CONFIG_ENABLE_WARN_DEPRECATED is not set +# CONFIG_ENABLE_MUST_CHECK is not set +CONFIG_FRAME_WARN=1024 +# CONFIG_UNUSED_SYMBOLS is not set +# CONFIG_FRAME_POINTER is not set +CONFIG_MAGIC_SYSRQ=y +CONFIG_PANIC_ON_OOPS=y +CONFIG_PANIC_TIMEOUT=30 +# CONFIG_SCHED_DEBUG is not set +# CONFIG_DEBUG_PREEMPT is not set +CONFIG_RCU_CPU_STALL_TIMEOUT=60 +CONFIG_FUNCTION_TRACER=y +CONFIG_FTRACE_SYSCALLS=y +CONFIG_TRACER_SNAPSHOT=y +CONFIG_TRACER_SNAPSHOT_PER_CPU_SWAP=y +CONFIG_FUNCTION_PROFILER=y +# CONFIG_X86_VERBOSE_BOOTUP is not set +# CONFIG_EARLY_PRINTK is not set +# CONFIG_DEBUG_RODATA_TEST is not set +CONFIG_IO_DELAY_0XED=y +CONFIG_OPTIMIZE_INLINING=y +CONFIG_SECURITY=y +CONFIG_SECURITY_NETWORK=y +CONFIG_SECURITY_SELINUX=y +CONFIG_SECURITY_SELINUX_BOOTPARAM=y +CONFIG_SECURITY_SELINUX_BOOTPARAM_VALUE=0 +CONFIG_DEFAULT_SECURITY_DAC=y +CONFIG_CRYPTO_CBC=y +CONFIG_CRYPTO_ECB=y +CONFIG_CRYPTO_HMAC=y +CONFIG_CRYPTO_CRC32C_INTEL=y +CONFIG_CRYPTO_MD5=y +CONFIG_CRYPTO_SHA1=y +CONFIG_CRYPTO_SHA256=y +# CONFIG_VIRTUALIZATION is not set +CONFIG_CRC7=m +CONFIG_LIBCRC32C=y +CONFIG_CRC8=m From 439f346237f9ee4a74ddf88ddb3ed96bcc249c19 Mon Sep 17 00:00:00 2001 From: Gangfeng Huang Date: Tue, 6 Dec 2016 17:44:49 +0800 Subject: [PATCH 052/110] nat_x86_64_defconfig: Enable Network Emulator ECAT needs to leverage i210 (driver) on smasher sync (x64) to implement high accuracy synchronization feature. This kernel config is used to disable all best effort traffic ("tc qdisc add dev eth0 root netem loss 100%") while ECAT is in use so that ECAT packets won't be interrupted at all. This ECAT release that includes the feature depends on LV/RT 17.0 Signed-off-by: Gangfeng Huang Signed-off-by: Brad Mouring Acked-by: Zyan Wu Natinst-ReviewBoard-ID:163669 --- arch/x86/configs/nati_x86_64_defconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/x86/configs/nati_x86_64_defconfig b/arch/x86/configs/nati_x86_64_defconfig index 797c1eb8e0cf4..199b2093b0908 100644 --- a/arch/x86/configs/nati_x86_64_defconfig +++ b/arch/x86/configs/nati_x86_64_defconfig @@ -212,6 +212,7 @@ CONFIG_BRIDGE=m CONFIG_VLAN_8021Q=m CONFIG_NET_SCHED=y CONFIG_NET_SCH_MULTIQ=m +CONFIG_NET_SCH_NETEM=m CONFIG_NET_CLS_BASIC=m CONFIG_NET_CLS_U32=m CONFIG_NET_EMATCH=y From 605d32e3cccc1dd5fd367fd67cd075602b930c77 Mon Sep 17 00:00:00 2001 From: Bogdan Hopulele Date: Mon, 12 Dec 2016 15:50:57 +0000 Subject: [PATCH 053/110] nati_x86_64_defconfig: Add kernel support for LUKS disk encryption Enables the use of cryptsetup. https://wiki.gentoo.org/wiki/Dm-crypt Signed-off-by: Bogdan Hopulele Signed-off-by: Brad Mouring Natinst-ReviewBoard-ID: 164875 --- arch/x86/configs/nati_x86_64_defconfig | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/arch/x86/configs/nati_x86_64_defconfig b/arch/x86/configs/nati_x86_64_defconfig index 199b2093b0908..490c1e934d99f 100644 --- a/arch/x86/configs/nati_x86_64_defconfig +++ b/arch/x86/configs/nati_x86_64_defconfig @@ -250,6 +250,9 @@ CONFIG_SATA_AHCI=y CONFIG_ATA_PIIX=y CONFIG_SATA_MV=m CONFIG_SATA_SIL=m +CONFIG_MD=y +CONFIG_BLK_DEV_DM=m +CONFIG_DM_CRYPT=m CONFIG_FIREWIRE=m CONFIG_FIREWIRE_OHCI=m CONFIG_FIREWIRE_SBP2=m @@ -508,13 +511,17 @@ CONFIG_SECURITY_SELINUX=y CONFIG_SECURITY_SELINUX_BOOTPARAM=y CONFIG_SECURITY_SELINUX_BOOTPARAM_VALUE=0 CONFIG_DEFAULT_SECURITY_DAC=y +CONFIG_CRYPTO_GF128MUL=y CONFIG_CRYPTO_CBC=y CONFIG_CRYPTO_ECB=y +CONFIG_CRYPTO_XTS=m CONFIG_CRYPTO_HMAC=y CONFIG_CRYPTO_CRC32C_INTEL=y CONFIG_CRYPTO_MD5=y CONFIG_CRYPTO_SHA1=y CONFIG_CRYPTO_SHA256=y +CONFIG_CRYPTO_AES_X86_64=y +CONFIG_CRYPTO_USER_API_SKCIPHER=m # CONFIG_VIRTUALIZATION is not set CONFIG_CRC7=m CONFIG_LIBCRC32C=y From b5cdd930ee6093569ca9ffb7f71066c174d89b56 Mon Sep 17 00:00:00 2001 From: Haris Okanovic Date: Mon, 17 Apr 2017 09:42:43 -0500 Subject: [PATCH 054/110] nati_x86_64_defconfig: Add DC21140 NIC driver for HyperV Add driver for Digital Equipment Corporation DC21140 NIC to support NILRT on HyperV (with "legacy network adapter"). https://technet.microsoft.com/en-us/library/cc770380(v=ws.11).aspx Signed-off-by: Haris Okanovic Signed-off-by: Brad Mouring Acked-by: Gratian Crisan Acked-by: Rich Tollerton Natinst-ReviewBoard-ID: 182439 --- arch/x86/configs/nati_x86_64_defconfig | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/arch/x86/configs/nati_x86_64_defconfig b/arch/x86/configs/nati_x86_64_defconfig index 490c1e934d99f..76a3c2321bf19 100644 --- a/arch/x86/configs/nati_x86_64_defconfig +++ b/arch/x86/configs/nati_x86_64_defconfig @@ -270,7 +270,8 @@ CONFIG_TIGON3=m # CONFIG_NET_VENDOR_BROCADE is not set # CONFIG_NET_VENDOR_CHELSIO is not set # CONFIG_NET_VENDOR_CISCO is not set -# CONFIG_NET_VENDOR_DEC is not set +CONFIG_NET_TULIP=y +CONFIG_TULIP=m # CONFIG_NET_VENDOR_DLINK is not set # CONFIG_NET_VENDOR_EMULEX is not set # CONFIG_NET_VENDOR_EXAR is not set From 28a4f2425299b2421512495331aec20cad060eeb Mon Sep 17 00:00:00 2001 From: Richard Tollerton Date: Fri, 21 Apr 2017 14:50:07 -0500 Subject: [PATCH 055/110] nati_x86_64_defconfig: reset CONFIG_SERIAL_8250_RUNTIME_UARTS=0 The previous setting of CONFIG_SERIAL_8250_RUNTIME_UARTS=2 was a workaround for a commit introduced in 4.6 which is now removed. Natinst-CAR-ID: 634278 Signed-off-by: Richard Tollerton Signed-off-by: Brad Mouring Natinst-ReviewBoard-ID: 183619 (cherry picked from commit 42b239a74ffbedf39c79250c3167fe7ca18659ab) (cherry picked from commit 588ea61b5786a1aee0c87bda333c89092bdba416) --- arch/x86/configs/nati_x86_64_defconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/x86/configs/nati_x86_64_defconfig b/arch/x86/configs/nati_x86_64_defconfig index 76a3c2321bf19..4a80591acf197 100644 --- a/arch/x86/configs/nati_x86_64_defconfig +++ b/arch/x86/configs/nati_x86_64_defconfig @@ -362,7 +362,7 @@ CONFIG_SERIO=m CONFIG_SERIAL_8250=y CONFIG_SERIAL_8250_CONSOLE=y CONFIG_SERIAL_8250_NR_UARTS=32 -CONFIG_SERIAL_8250_RUNTIME_UARTS=2 +CONFIG_SERIAL_8250_RUNTIME_UARTS=0 CONFIG_SERIAL_8250_EXTENDED=y CONFIG_SERIAL_8250_SHARE_IRQ=y CONFIG_SERIAL_8250_DETECT_IRQ=y From c2d692efddfd50f33aa128202591af16cd50c85b Mon Sep 17 00:00:00 2001 From: Hui Chun Ong Date: Fri, 30 Jun 2017 17:17:18 +0800 Subject: [PATCH 056/110] nati_x86_64_defconfig: Enable NIC7018 watchdog driver Update config to enable nic7018_wdt watchdog driver. Signed-off-by: Hui Chun Ong Signed-off-by: Brad Mouring Acked-by: Gratian Crisan Acked-by: Vee Khee Wong Acked-by: Kar Hin Ong Natinst-ReviewBoard-ID: 192171 (cherry picked from commit 453707646d31f88c9aeacf7071743ff8491b3a87) (cherry picked from commit 4819538d26a937917cf6287520d39d6295d45288) --- arch/x86/configs/nati_x86_64_defconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/x86/configs/nati_x86_64_defconfig b/arch/x86/configs/nati_x86_64_defconfig index 4a80591acf197..28304bdf76502 100644 --- a/arch/x86/configs/nati_x86_64_defconfig +++ b/arch/x86/configs/nati_x86_64_defconfig @@ -389,6 +389,7 @@ CONFIG_SENSORS_CORETEMP=m CONFIG_SENSORS_TMP421=m CONFIG_WATCHDOG=y CONFIG_SOFT_WATCHDOG=m +CONFIG_NIC7018_WDT=m CONFIG_LPC_ICH=m CONFIG_MEDIA_SUPPORT=m CONFIG_MEDIA_CAMERA_SUPPORT=y From fc8241e139c2ce7abaebf09fc958b9cc19c9efa3 Mon Sep 17 00:00:00 2001 From: Hui Chun Ong Date: Wed, 5 Jul 2017 17:14:36 +0800 Subject: [PATCH 057/110] nati_x86_64_defconfig: Enable NI PXIe-8240 Ethernet module support Enable Intel(R) Ethernet Controller XL710 Family device driver to support NI PXIe-8240 40GbE Ethernet module. Signed-off-by: Hui Chun Ong Signed-off-by: Brad Mouring Acked-by: Jonathan Hearn Acked-by: Vee Khee Wong Acked-by: Kar Hin Ong Natinst-ReviewBoard-ID: 192408 (cherry picked from commit 9f76fb8d1d725f39ea8f957cc2a14521109367a3) (cherry picked from commit 1a2d7fde798aa9ba9b1059562cb6d137ba6d9ca6) --- arch/x86/configs/nati_x86_64_defconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/x86/configs/nati_x86_64_defconfig b/arch/x86/configs/nati_x86_64_defconfig index 28304bdf76502..d455bc9cbbdff 100644 --- a/arch/x86/configs/nati_x86_64_defconfig +++ b/arch/x86/configs/nati_x86_64_defconfig @@ -285,6 +285,7 @@ CONFIG_IGBVF=m CONFIG_IXGB=m CONFIG_IXGBE=m # CONFIG_IXGBE_HWMON is not set +CONFIG_I40E=m # CONFIG_NET_VENDOR_I825XX is not set # CONFIG_NET_VENDOR_MARVELL is not set # CONFIG_NET_VENDOR_MELLANOX is not set From 4df81c63d0bdefcaf1a807827c32ec1c20ede5ee Mon Sep 17 00:00:00 2001 From: Haris Okanovic Date: Mon, 6 Nov 2017 10:53:04 -0600 Subject: [PATCH 058/110] nati_x86_64_defconfig: Add CONFIG_CRYPTO_AES_NI_INTEL=m Add support for x86 AES extensions to improve luks performance. https://software.intel.com/en-us/articles/intel-advanced-encryption-standard-aes-instructions-set/ Signed-off-by: Haris Okanovic Signed-off-by: Brad Mouring Acked-by: Chris Graf Acked-by: Adrian Ratiu Natinst-Rally-ID: F12416 Natinst-ReviewBoard-ID: 208963 --- arch/x86/configs/nati_x86_64_defconfig | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/arch/x86/configs/nati_x86_64_defconfig b/arch/x86/configs/nati_x86_64_defconfig index d455bc9cbbdff..a70be6a8be0e0 100644 --- a/arch/x86/configs/nati_x86_64_defconfig +++ b/arch/x86/configs/nati_x86_64_defconfig @@ -514,16 +514,18 @@ CONFIG_SECURITY_SELINUX=y CONFIG_SECURITY_SELINUX_BOOTPARAM=y CONFIG_SECURITY_SELINUX_BOOTPARAM_VALUE=0 CONFIG_DEFAULT_SECURITY_DAC=y -CONFIG_CRYPTO_GF128MUL=y +CONFIG_CRYPTO_CRYPTD=y CONFIG_CRYPTO_CBC=y CONFIG_CRYPTO_ECB=y -CONFIG_CRYPTO_XTS=m +CONFIG_CRYPTO_LRW=y +CONFIG_CRYPTO_XTS=y CONFIG_CRYPTO_HMAC=y CONFIG_CRYPTO_CRC32C_INTEL=y CONFIG_CRYPTO_MD5=y CONFIG_CRYPTO_SHA1=y CONFIG_CRYPTO_SHA256=y CONFIG_CRYPTO_AES_X86_64=y +CONFIG_CRYPTO_AES_NI_INTEL=m CONFIG_CRYPTO_USER_API_SKCIPHER=m # CONFIG_VIRTUALIZATION is not set CONFIG_CRC7=m From da7693fadc2fe94cd887a309b9a1cb35fc2b6fc5 Mon Sep 17 00:00:00 2001 From: Ioan-Adrian Ratiu Date: Fri, 13 Jan 2017 15:47:19 +0200 Subject: [PATCH 059/110] nati_x86_64_defconfig: disable BTRFS AFAIK no one is using BTRFS on nilrt; it was enabled along with many others in 79ec8745992 ("nati_zynq_defconfig: Regenerate, add functionality"). Between the 2016 and 2017 releases the kernel increased around 5.8 mb which is problematic for the memory constrained devices running in safemode with all kernel modules installed by default. BTRFS is about 1.3 mb (including it's raid6_pq dependency) out of those 5.6 so remove it to free up disk space. Signed-off-by: Ioan-Adrian Ratiu Signed-off-by: Brad Mouring Acked-by: Ken Sharp Acked-by: Bill Pittman Acked-by: Rich Tollerton Acked-by: Gratian Crisan Natinst-ReviewBoard-ID: 168207 [bstreiff: drop zynq, leave x86_64] Signed-off-by: Brandon Streiff --- arch/x86/configs/nati_x86_64_defconfig | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/arch/x86/configs/nati_x86_64_defconfig b/arch/x86/configs/nati_x86_64_defconfig index a70be6a8be0e0..a969a460b1b89 100644 --- a/arch/x86/configs/nati_x86_64_defconfig +++ b/arch/x86/configs/nati_x86_64_defconfig @@ -462,8 +462,7 @@ CONFIG_EXT2_FS_SECURITY=y CONFIG_EXT3_FS=y CONFIG_EXT3_FS_POSIX_ACL=y CONFIG_EXT3_FS_SECURITY=y -CONFIG_BTRFS_FS=m -CONFIG_BTRFS_FS_POSIX_ACL=y +CONFIG_BTRFS_FS=n # CONFIG_DNOTIFY is not set CONFIG_FUSE_FS=m CONFIG_ISO9660_FS=y From c5ceaf7855d7593f4047bd9602173912f85fa447 Mon Sep 17 00:00:00 2001 From: Haris Okanovic Date: Thu, 2 Feb 2017 16:49:52 -0600 Subject: [PATCH 060/110] nati_x86_64_defconfig: Update for v4.9.6-rt4 Load and re-save nati_x86_64_defconfig in 4.9. Signed-off-by: Haris Okanovic [bstreiff: drop zynq, leave x86_64] Signed-off-by: Brandon Streiff --- arch/x86/configs/nati_x86_64_defconfig | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/arch/x86/configs/nati_x86_64_defconfig b/arch/x86/configs/nati_x86_64_defconfig index a969a460b1b89..8b9f78969f1d7 100644 --- a/arch/x86/configs/nati_x86_64_defconfig +++ b/arch/x86/configs/nati_x86_64_defconfig @@ -66,7 +66,6 @@ CONFIG_ACPI_APEI_PCIEAER=y CONFIG_ACPI_APEI_MEMORY_FAILURE=y CONFIG_SFI=y CONFIG_CPU_FREQ=y -# CONFIG_CPU_FREQ_STAT is not set CONFIG_X86_INTEL_PSTATE=y CONFIG_INTEL_IDLE=y CONFIG_PCI_MMCONFIG=y @@ -234,7 +233,6 @@ CONFIG_CONNECTOR=y CONFIG_BLK_DEV_LOOP=y CONFIG_BLK_DEV_RAM=y CONFIG_VIRTIO_BLK=m -# CONFIG_HWLAT_DETECTOR is not set CONFIG_NI_RT_FEATURES=y CONFIG_NI_LED_PREFIX="nilrt" CONFIG_NI_WATCHDOG=y @@ -430,7 +428,7 @@ CONFIG_USB_SERIAL_MOS7840=m CONFIG_USB_SERIAL_PL2303=m CONFIG_USB_SERIAL_QUALCOMM=m CONFIG_USB_SERIAL_SIERRAWIRELESS=m -CONFIG_NOP_USB_XCEIV=y +CONFIG_NOP_USB_XCEIV=m CONFIG_USB_GADGET=m CONFIG_USB_ETH=m # CONFIG_USB_ETH_RNDIS is not set @@ -443,7 +441,6 @@ CONFIG_LEDS_CLASS=y CONFIG_LEDS_NIC78BX=m CONFIG_RTC_CLASS=y CONFIG_DMADEVICES=y -CONFIG_DW_DMAC_PCI=y CONFIG_VIRTIO_PCI=m CONFIG_VIRTIO_BALLOON=m CONFIG_VIRTIO_MMIO=m @@ -462,7 +459,6 @@ CONFIG_EXT2_FS_SECURITY=y CONFIG_EXT3_FS=y CONFIG_EXT3_FS_POSIX_ACL=y CONFIG_EXT3_FS_SECURITY=y -CONFIG_BTRFS_FS=n # CONFIG_DNOTIFY is not set CONFIG_FUSE_FS=m CONFIG_ISO9660_FS=y From 04e0052789d00036f48a18ff4d8caa53e9e37f7d Mon Sep 17 00:00:00 2001 From: Richard Tollerton Date: Wed, 15 Feb 2017 16:36:24 -0600 Subject: [PATCH 061/110] nati_x86_64_defconfig: enable hidraw, hiddev Enable CONFIG_HIDRAW and CONFIG_USB_HIDDEV so as to support userspace access to non-user-interface devices. Natinst-CAR-ID: 630683 Natinst-Reviewboard-ID: 173707 Signed-off-by: Richard Tollerton Signed-off-by: Brad Mouring Acked-by: Gratian Crisan [bstreiff: drop zynq, leave x86_64] Signed-off-by: Brandon Streiff --- arch/x86/configs/nati_x86_64_defconfig | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/x86/configs/nati_x86_64_defconfig b/arch/x86/configs/nati_x86_64_defconfig index 8b9f78969f1d7..e26b35aae93cf 100644 --- a/arch/x86/configs/nati_x86_64_defconfig +++ b/arch/x86/configs/nati_x86_64_defconfig @@ -404,9 +404,11 @@ CONFIG_FB=y CONFIG_FB_MODE_HELPERS=y CONFIG_FB_EFI=y CONFIG_FRAMEBUFFER_CONSOLE=y +CONFIG_HIDRAW=y CONFIG_HID_MICROSOFT=m CONFIG_HID_MULTITOUCH=m CONFIG_HID_PENMOUNT=m +CONFIG_USB_HIDDEV=y CONFIG_USB=y CONFIG_USB_DYNAMIC_MINORS=y CONFIG_USB_XHCI_HCD=y From 869a88f3f8a7029d8e23c1294d88f6bf0ca6cbf1 Mon Sep 17 00:00:00 2001 From: Sankara S Muthukrishnan Date: Fri, 5 Oct 2012 13:21:14 -0500 Subject: [PATCH 062/110] irq: Add priority support to /proc/irq/../ This patch allows configuring priority for different irq threads through the /proc/irq/ system (much same as the existing mechanism to configure the core affinity for irqs). Priority of an already running irq thread can be changed also, however, the new priority will take into effect when the irq thread is scheduled to run the next time. An irq thread that gets created will use the priority specified in the /proc/irq/../priority file. Thanks Josh Cartwright for suggesting this idea. Also fix up the original commit by moving the code out from under the CONFIG_SMP conditional to allow building a uniprocessor kernel. Signed-off-by: Sankara S Muthukrishnan Signed-off-by: Josh Cartwright Acked-by: Josh Cartwright Acked-by: Jeff Westfahl Acked-by: Gratian Crisan [gratian: rename setup_affinity() to irq_setup_affinity() per commit 43564bd97d0e ("genirq: Rename setup_affinity() to irq_setup_affinity()")] Signed-off-by: Gratian Crisan [bstreiff: drop dependency on reverted commit 87fdb9bd58c3460fa8c0655b3b82ece1d6bbb955 ("boot: add kernel boot parameters for kernel thread priorities")] [bstreiff: convert from file_operations to proc_ops] Signed-off-by: Brandon Streiff --- include/linux/interrupt.h | 3 ++ include/linux/irq.h | 1 + kernel/irq/internals.h | 1 + kernel/irq/irqdesc.c | 1 + kernel/irq/manage.c | 62 +++++++++++++++++++++++++++++++++++++++ kernel/irq/proc.c | 56 +++++++++++++++++++++++++++++++++++ 6 files changed, 124 insertions(+) diff --git a/include/linux/interrupt.h b/include/linux/interrupt.h index e65df3c95bc55..0ff3c454ad2d7 100644 --- a/include/linux/interrupt.h +++ b/include/linux/interrupt.h @@ -255,6 +255,9 @@ extern void suspend_device_irqs(void); extern void resume_device_irqs(void); extern void rearm_wake_irq(unsigned int irq); +extern void init_irq_default_prio(struct irq_desc *desc); +extern int irq_set_priority(unsigned int irq, int priority); + /** * struct irq_affinity_notify - context for notification of IRQ affinity changes * @irq: Interrupt to which notification applies diff --git a/include/linux/irq.h b/include/linux/irq.h index c54365309e975..ddbd164dd060f 100644 --- a/include/linux/irq.h +++ b/include/linux/irq.h @@ -183,6 +183,7 @@ struct irq_data { struct irq_data *parent_data; #endif void *chip_data; + int priority; }; /* diff --git a/kernel/irq/internals.h b/kernel/irq/internals.h index 54363527feea4..e05660fed2885 100644 --- a/kernel/irq/internals.h +++ b/kernel/irq/internals.h @@ -35,6 +35,7 @@ enum { IRQTF_WARNED, IRQTF_AFFINITY, IRQTF_FORCED_THREAD, + IRQTF_PRIORITY, }; /* diff --git a/kernel/irq/irqdesc.c b/kernel/irq/irqdesc.c index 1a7723604399c..3b2daef73b4be 100644 --- a/kernel/irq/irqdesc.c +++ b/kernel/irq/irqdesc.c @@ -112,6 +112,7 @@ static void desc_set_defaults(unsigned int irq, struct irq_desc *desc, int node, desc->irq_data.irq = irq; desc->irq_data.chip = &no_irq_chip; desc->irq_data.chip_data = NULL; + init_irq_default_prio(desc); irq_settings_clr_and_set(desc, ~0, _IRQ_DEFAULT_INIT_FLAGS); irqd_set(&desc->irq_data, IRQD_IRQ_DISABLED); irqd_set(&desc->irq_data, IRQD_IRQ_MASKED); diff --git a/kernel/irq/manage.c b/kernel/irq/manage.c index ef4c1343bd0ca..0055b49976970 100644 --- a/kernel/irq/manage.c +++ b/kernel/irq/manage.c @@ -36,6 +36,11 @@ static int __init setup_forced_irqthreads(char *arg) early_param("threadirqs", setup_forced_irqthreads); #endif +void init_irq_default_prio(struct irq_desc *desc) +{ + desc->irq_data.priority = MAX_USER_RT_PRIO/2; +} + static void __synchronize_hardirq(struct irq_desc *desc, bool sync_chip) { struct irq_data *irqd = irq_desc_get_irq_data(desc); @@ -141,6 +146,45 @@ void synchronize_irq(unsigned int irq) } EXPORT_SYMBOL(synchronize_irq); +static void +irq_thread_check_priority(struct irq_desc *desc, struct irqaction *action) +{ + struct sched_param param; + + if (!test_and_clear_bit(IRQTF_PRIORITY, &action->thread_flags)) + return; + + param.sched_priority = desc->irq_data.priority; + sched_setscheduler(current, SCHED_FIFO, ¶m); +} + +void irq_set_thread_priority(struct irq_desc *desc) +{ + struct irqaction *action = desc->action; + + while (action) { + if (action->thread) + set_bit(IRQTF_PRIORITY, &action->thread_flags); + action = action->next; + } +} + +int irq_set_priority(unsigned int irq, int priority) +{ + unsigned long flags; + struct irq_desc *desc = irq_to_desc(irq); + + if (!desc) + return -EINVAL; + if (!(priority > 0 && priority < MAX_USER_RT_PRIO)) + return -EINVAL; + raw_spin_lock_irqsave(&desc->lock, flags); + desc->irq_data.priority = priority; + irq_set_thread_priority(desc); + raw_spin_unlock_irqrestore(&desc->lock, flags); + return 0; +} + #ifdef CONFIG_SMP cpumask_var_t irq_default_affinity; @@ -1166,12 +1210,17 @@ static int irq_thread(void *data) init_task_work(&on_exit_work, irq_thread_dtor); task_work_add(current, &on_exit_work, TWA_NONE); + /* optimize jitter for the irq threads that don't change affinity or + * priority dynamically + */ irq_thread_check_affinity(desc, action); + irq_thread_check_priority(desc, action); while (!irq_wait_for_interrupt(action)) { irqreturn_t action_ret; irq_thread_check_affinity(desc, action); + irq_thread_check_priority(desc, action); action_ret = handler_fn(desc, action); if (action_ret == IRQ_WAKE_THREAD) @@ -1344,6 +1393,7 @@ setup_irq_thread(struct irqaction *new, unsigned int irq, bool secondary) * on which the requesting code placed the interrupt. */ set_bit(IRQTF_AFFINITY, &new->thread_flags); + set_bit(IRQTF_PRIORITY, &new->thread_flags); return 0; } @@ -1655,6 +1705,18 @@ __setup_irq(unsigned int irq, struct irq_desc *desc, struct irqaction *new) *old_ptr = new; + /* Set default affinity mask once everything is setup. + * We have to do this after the desc->action is assigned the new action + * just above. If setup_affinity is called before, then the IRQ thread + * associated with the new action does not inherit the core affinity + * specified in /proc/irq//smp_affinity file whereas the IRQ + * threads of the existing action handlers do inherit. + */ + if (!shared) { + irq_setup_affinity(desc); + irq_set_thread_priority(desc); + } + irq_pm_install_action(desc, new); /* Reset broken irq detection when installing new handler */ diff --git a/kernel/irq/proc.c b/kernel/irq/proc.c index 72513ed2a5fc6..20bc1cee5e512 100644 --- a/kernel/irq/proc.c +++ b/kernel/irq/proc.c @@ -5,6 +5,8 @@ * This file contains the /proc/irq/ handling code. */ +#include + #include #include #include @@ -295,6 +297,57 @@ static int irq_spurious_proc_show(struct seq_file *m, void *v) return 0; } +static ssize_t irq_priority_proc_write(struct file *file, + const char __user *user_buf, size_t count, loff_t *pos) +{ + int priority; + int err = 0; + unsigned int irq; + char buffer[20]; + + memset(buffer, 0, sizeof(buffer)); + if (count > sizeof(buffer) - 1) + count = sizeof(buffer) - 1; + if (copy_from_user(buffer, user_buf, count)) { + err = -EFAULT; + goto out; + } + err = kstrtoint(strstrip(buffer), 0, &priority); + if (err) + goto out; + irq = (int)(long)PDE_DATA(file_inode(file)); + err = irq_set_priority(irq, priority); +out: + return err < 0 ? err : count; +} + +static int show_irq_priority(int type, struct seq_file *m, void *v) +{ + struct irq_desc *desc = irq_to_desc((long)m->private); + int prio = desc->irq_data.priority; + + seq_printf(m, "%d\n", prio); + return 0; +} + +static int irq_priority_proc_show(struct seq_file *m, void *v) +{ + return show_irq_priority(0, m, v); +} + +static int irq_priority_proc_open(struct inode *inode, struct file *file) +{ + return single_open(file, irq_priority_proc_show, PDE_DATA(inode)); +} + +static const struct proc_ops irq_priority_proc_ops = { + .proc_open = irq_priority_proc_open, + .proc_read = seq_read, + .proc_lseek = seq_lseek, + .proc_release = single_release, + .proc_write = irq_priority_proc_write, +}; + #define MAX_NAMELEN 128 static int name_unique(unsigned int irq, struct irqaction *new_action) @@ -386,6 +439,8 @@ void register_irq_proc(unsigned int irq, struct irq_desc *desc) proc_create_single_data("spurious", 0444, desc->dir, irq_spurious_proc_show, (void *)(long)irq); + proc_create_data("priority", 0600, desc->dir, + &irq_priority_proc_ops, irqp); out_unlock: mutex_unlock(®ister_lock); } @@ -407,6 +462,7 @@ void unregister_irq_proc(unsigned int irq, struct irq_desc *desc) # endif #endif remove_proc_entry("spurious", desc->dir); + remove_proc_entry("priority", desc->dir); sprintf(name, "%u", irq); remove_proc_entry(name, root_irq_dir); From e372d20c2fbcaf4a8633d2381901a5804ab6ae98 Mon Sep 17 00:00:00 2001 From: Haris Okanovic Date: Fri, 25 Sep 2015 11:34:42 -0500 Subject: [PATCH 063/110] proc/interrupts: Add polling Implement polling on procfs' "interrupts" file which observes changes to IRQ action handlers. The poll fires each time an action handler is registered or unregistered. This change enables daemons to watch for changes and apply certain system policies relating to IRQ processing. For example, modify execution priority of dedicated IRQ tasks after they're created. include/linux/interrupt.h kernel/irq/manage.c Add change counter for handler registrations and a wait queue to notify tasks on updates. fs/proc/interrupts.c Add polling callback on aforementioned counter and wait queue. Signed-off-by: Haris Okanovic Signed-off-by: Ovidiu-Adrian Vancea Signed-off-by: Brad Mouring Natinst-ReviewBoard-ID: 111860, 163902 [gratian: fixed small rebase conflict] Signed-off-by: Gratian Crisan [bstreiff: un-trivialize from changes in fddda2b7b521 ("proc: introduce proc_create_seq{,_data}") and convert file_operations to proc_ops] Signed-off-by: Brandon Streiff --- fs/proc/interrupts.c | 74 ++++++++++++++++++++++++++++++++++++++- include/linux/interrupt.h | 3 ++ kernel/irq/manage.c | 18 ++++++++++ 3 files changed, 94 insertions(+), 1 deletion(-) diff --git a/fs/proc/interrupts.c b/fs/proc/interrupts.c index cb0edc7cbf092..624eb74af1e3c 100644 --- a/fs/proc/interrupts.c +++ b/fs/proc/interrupts.c @@ -1,10 +1,12 @@ // SPDX-License-Identifier: GPL-2.0 #include +#include #include #include #include #include #include +#include /* * /proc/interrupts @@ -34,9 +36,79 @@ static const struct seq_operations int_seq_ops = { .show = show_interrupts }; +struct interrupts_fd_state { + atomic_long_t last_irq_change_count; +}; + +static int interrupts_open(struct inode *inode, struct file *filp) +{ + int res; + struct interrupts_fd_state *privdata; + struct seq_file *sf; + + privdata = kzalloc(sizeof(struct interrupts_fd_state), GFP_KERNEL); + if (!privdata) { + res = -ENOMEM; + goto exit; + } + + res = seq_open(filp, &int_seq_ops); + if (res) { + kfree(privdata); + goto exit; + } + + sf = filp->private_data; + sf->private = privdata; + + atomic_long_set(&(privdata->last_irq_change_count), + get_irq_handler_change_count()); + +exit: + return res; +} + +static int interrupts_release(struct inode *inode, struct file *filp) +{ + struct seq_file *sf = filp->private_data; + + kfree(sf->private); + return seq_release(inode, filp); +} + +static unsigned int interrupts_poll(struct file *filp, + struct poll_table_struct *pt) +{ + unsigned int mask = POLLIN | POLLRDNORM; + long newcount, oldcount; + struct seq_file *sf = filp->private_data; + struct interrupts_fd_state *fds = sf->private; + + /* Register for changes to IRQ handlers */ + poll_wait(filp, &irq_handler_change_wq, pt); + + /* Store new change count in priv data */ + newcount = get_irq_handler_change_count(); + oldcount = atomic_long_xchg( + &(fds->last_irq_change_count), newcount); + + if (newcount != oldcount) + mask |= POLLERR | POLLPRI; + + return mask; +} + +static const struct proc_ops interrupts_proc_ops = { + .proc_open = interrupts_open, + .proc_read = seq_read, + .proc_poll = interrupts_poll, + .proc_lseek = seq_lseek, + .proc_release = interrupts_release, +}; + static int __init proc_interrupts_init(void) { - proc_create_seq("interrupts", 0, NULL, &int_seq_ops); + proc_create("interrupts", 0, NULL, &interrupts_proc_ops); return 0; } fs_initcall(proc_interrupts_init); diff --git a/include/linux/interrupt.h b/include/linux/interrupt.h index 0ff3c454ad2d7..d1724098278d2 100644 --- a/include/linux/interrupt.h +++ b/include/linux/interrupt.h @@ -788,6 +788,9 @@ extern int early_irq_init(void); extern int arch_probe_nr_irqs(void); extern int arch_early_irq_init(void); +extern long get_irq_handler_change_count(void); +extern wait_queue_head_t irq_handler_change_wq; + /* * We want to know which function is an entrypoint of a hardirq or a softirq. */ diff --git a/kernel/irq/manage.c b/kernel/irq/manage.c index 0055b49976970..15d7036842d20 100644 --- a/kernel/irq/manage.c +++ b/kernel/irq/manage.c @@ -41,6 +41,22 @@ void init_irq_default_prio(struct irq_desc *desc) desc->irq_data.priority = MAX_USER_RT_PRIO/2; } +static atomic_long_t irq_handler_change_count = ATOMIC_LONG_INIT(0); +DECLARE_WAIT_QUEUE_HEAD(irq_handler_change_wq); + +/* Bump change count and wake up anything waiting on changes to + * IRQ handlers */ +static void __irq_handler_change_event(void) +{ + atomic_long_inc(&irq_handler_change_count); + wake_up(&irq_handler_change_wq); +} + +long get_irq_handler_change_count(void) +{ + return atomic_long_read(&irq_handler_change_count); +} + static void __synchronize_hardirq(struct irq_desc *desc, bool sync_chip) { struct irq_data *irqd = irq_desc_get_irq_data(desc); @@ -1750,6 +1766,7 @@ __setup_irq(unsigned int irq, struct irq_desc *desc, struct irqaction *new) register_irq_proc(irq, desc); new->dir = NULL; register_handler_proc(irq, new); + __irq_handler_change_event(); return 0; mismatch: @@ -1928,6 +1945,7 @@ static struct irqaction *__free_irq(struct irq_desc *desc, void *dev_id) irq_chip_pm_put(&desc->irq_data); module_put(desc->owner); kfree(action->secondary); + __irq_handler_change_event(); return action; } From 07e9cbd4bdb8ac45dae3a335b33cc678b00f3d3e Mon Sep 17 00:00:00 2001 From: Hui Chun Ong Date: Mon, 6 Feb 2017 23:49:09 +0800 Subject: [PATCH 064/110] watchdog: nic7018_wdt: Add support for trigger pet and trigger assert Add capabilities to use trigger line to reset timer and to assert trigger line upon timeout. The trigger line control and selection is done through sysfs attributes. Signed-off-by: Hui Chun Ong Signed-off-by: Brad Mouring Acked-by: Gratian Crisan Acked-by: Julia Cartwright Natinst-ReviewBoard-ID: 192326 (cherry picked from commit d6351b1a5530fb532e948fec6a8e947cca384880) (cherry picked from commit be8a29797de3c2fc60a44993edc24071da2c7f5f) --- drivers/watchdog/nic7018_wdt.c | 168 +++++++++++++++++++++++++++++++++ 1 file changed, 168 insertions(+) diff --git a/drivers/watchdog/nic7018_wdt.c b/drivers/watchdog/nic7018_wdt.c index 2a46cc6629437..b5cb8a4d4e151 100644 --- a/drivers/watchdog/nic7018_wdt.c +++ b/drivers/watchdog/nic7018_wdt.c @@ -8,7 +8,9 @@ #include #include #include +#include #include +#include #include #define LOCK 0xA5 @@ -16,6 +18,8 @@ #define WDT_CTRL_RESET_EN BIT(7) #define WDT_RELOAD_PORT_EN BIT(7) +#define WDT_CTRL_TRIG_POL BIT(4) +#define WDT_RELOAD_TRIG_POL BIT(6) #define WDT_CTRL 1 #define WDT_RELOAD_CTRL 2 @@ -46,6 +50,7 @@ struct nic7018_wdt { u16 io_base; u32 period; struct watchdog_device wdd; + struct mutex lock; }; struct nic7018_config { @@ -165,6 +170,166 @@ static const struct watchdog_ops nic7018_wdd_ops = { .get_timeleft = nic7018_get_timeleft, }; +struct nic7018_attr { + struct device_attribute dev_attr; + u8 offset; + u8 bit; +}; +#define to_nic7018_attr(_attr) \ + container_of((_attr), struct nic7018_attr, dev_attr) + +static ssize_t wdt_attr_show(struct device *dev, + struct device_attribute *da, + char *buf) +{ + struct watchdog_device *wdd = dev_get_drvdata(dev); + struct nic7018_wdt *wdt = watchdog_get_drvdata(wdd); + struct nic7018_attr *attr = to_nic7018_attr(da); + u8 control; + + mutex_lock(&wdt->lock); + + control = inb(wdt->io_base + attr->offset); + + mutex_unlock(&wdt->lock); + return sprintf(buf, "%u\n", !!(control & attr->bit)); +} + +static ssize_t wdt_attr_store(struct device *dev, + struct device_attribute *da, + const char *buf, + size_t size) +{ + struct watchdog_device *wdd = dev_get_drvdata(dev); + struct nic7018_wdt *wdt = watchdog_get_drvdata(wdd); + struct nic7018_attr *attr = to_nic7018_attr(da); + unsigned long val; + u8 control; + + int ret = kstrtoul(buf, 10, &val); + + if (ret) + return ret; + + if (val > 1) + return -EINVAL; + + mutex_lock(&wdt->lock); + + control = inb(wdt->io_base + attr->offset); + if (val) + outb(control | attr->bit, wdt->io_base + attr->offset); + else + outb(control & ~attr->bit, wdt->io_base + attr->offset); + + mutex_unlock(&wdt->lock); + return size; +} + +#define WDT_ATTR(_name, _offset, _bit) \ + struct nic7018_attr dev_attr_##_name = { \ + .offset = _offset, \ + .bit = _bit, \ + .dev_attr = \ + __ATTR(_name, S_IWUSR | S_IRUGO, \ + wdt_attr_show, wdt_attr_store), \ + } + +static WDT_ATTR(enable_reset, WDT_CTRL, WDT_CTRL_RESET_EN); +static WDT_ATTR(enable_soft_ping, WDT_RELOAD_CTRL, WDT_RELOAD_PORT_EN); +static WDT_ATTR(trigger_polarity, WDT_CTRL, WDT_CTRL_TRIG_POL); +static WDT_ATTR(keepalive_trigger_polarity, WDT_RELOAD_CTRL, + WDT_RELOAD_TRIG_POL); + +static ssize_t wdt_trig_show(struct device *dev, + struct device_attribute *da, + char *buf) +{ + struct watchdog_device *wdd = dev_get_drvdata(dev); + struct nic7018_wdt *wdt = watchdog_get_drvdata(wdd); + struct nic7018_attr *attr = to_nic7018_attr(da); + u8 control; + + mutex_lock(&wdt->lock); + + control = inb(wdt->io_base + attr->offset); + + mutex_unlock(&wdt->lock); + + if (control & 0x0F) + return sprintf(buf, "trig%u\n", (control & 0x0F) - 1); + else + return sprintf(buf, "none\n"); +} + +static ssize_t wdt_trig_store(struct device *dev, + struct device_attribute *da, + const char *buf, + size_t size) +{ + struct watchdog_device *wdd = dev_get_drvdata(dev); + struct nic7018_wdt *wdt = watchdog_get_drvdata(wdd); + struct nic7018_attr *attr = to_nic7018_attr(da); + u8 control; + + char *p = memchr(buf, '\n', size); + size_t count = p ? p - buf : size; + + if (count == 5 && !strncmp(buf, "trig", 4)) { + unsigned long val; + int ret; + + ret = kstrtoul(buf + 4, 10, &val); + if (ret) + return ret; + + if (val > 8) + return -EINVAL; + + mutex_lock(&wdt->lock); + + control = inb(wdt->io_base + attr->offset); + outb((control & 0xF0) | (val + 1), + wdt->io_base + attr->offset); + + mutex_unlock(&wdt->lock); + + } else if (count == 4 && !strncmp(buf, "none", 4)) { + mutex_lock(&wdt->lock); + + control = inb(wdt->io_base + attr->offset); + outb(control & 0xF0, wdt->io_base + attr->offset); + + mutex_unlock(&wdt->lock); + } else { + return -EINVAL; + } + + return size; +} + +#define WDT_TRIG_ATTR(_name, _offset) \ + struct nic7018_attr dev_attr_##_name = { \ + .offset = _offset, \ + .dev_attr = \ + __ATTR(_name, S_IWUSR | S_IRUGO, \ + wdt_trig_show, wdt_trig_store), \ + } + +static WDT_TRIG_ATTR(trigger, WDT_CTRL); +static WDT_TRIG_ATTR(keepalive_trigger, WDT_RELOAD_CTRL); + +static struct attribute *nic7018_wdt_attrs[] = { + &dev_attr_enable_reset.dev_attr.attr, + &dev_attr_enable_soft_ping.dev_attr.attr, + &dev_attr_trigger_polarity.dev_attr.attr, + &dev_attr_keepalive_trigger_polarity.dev_attr.attr, + &dev_attr_trigger.dev_attr.attr, + &dev_attr_keepalive_trigger.dev_attr.attr, + NULL +}; +ATTRIBUTE_GROUPS(nic7018_wdt); + static int nic7018_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; @@ -191,6 +356,8 @@ static int nic7018_probe(struct platform_device *pdev) return -EBUSY; } + mutex_init(&wdt->lock); + wdt->io_base = io_rc->start; wdd = &wdt->wdd; wdd->info = &nic7018_wdd_info; @@ -199,6 +366,7 @@ static int nic7018_probe(struct platform_device *pdev) wdd->max_timeout = WDT_MAX_TIMEOUT; wdd->timeout = WDT_DEFAULT_TIMEOUT; wdd->parent = dev; + wdd->groups = nic7018_wdt_groups; watchdog_set_drvdata(wdd, wdt); watchdog_set_nowayout(wdd, nowayout); From 9f730de413a6429f655f1f568f9afdeb9fdf6517 Mon Sep 17 00:00:00 2001 From: Hui Chun Ong Date: Sat, 8 Jul 2017 12:33:34 +0800 Subject: [PATCH 065/110] watchdog: nic7018_wdt: Add support for timeout interrupt Add interrupt handling for watchdog timeout. Interrupt control is done through sysfs "enable_interrupt" attribute. uevent is used to signal userspace when interrupt occurred as oppose to using poll due to no support in watchdog core. Signed-off-by: Hui Chun Ong Signed-off-by: Brad Mouring Acked-by: Julia Cartwright Natinst-ReviewBoard-ID: 195479 --- drivers/watchdog/nic7018_wdt.c | 45 +++++++++++++++++++++++++++++++++- 1 file changed, 44 insertions(+), 1 deletion(-) diff --git a/drivers/watchdog/nic7018_wdt.c b/drivers/watchdog/nic7018_wdt.c index b5cb8a4d4e151..30c9bccc685fe 100644 --- a/drivers/watchdog/nic7018_wdt.c +++ b/drivers/watchdog/nic7018_wdt.c @@ -6,6 +6,7 @@ #include #include #include +#include #include #include #include @@ -20,7 +21,9 @@ #define WDT_RELOAD_PORT_EN BIT(7) #define WDT_CTRL_TRIG_POL BIT(4) #define WDT_RELOAD_TRIG_POL BIT(6) +#define WDT_CTRL_INTERRUPT_EN BIT(5) +#define WDT_STATUS 0 #define WDT_CTRL 1 #define WDT_RELOAD_CTRL 2 #define WDT_PRESET_PRESCALE 4 @@ -106,6 +109,31 @@ static int nic7018_set_timeout(struct watchdog_device *wdd, return 0; } +static irqreturn_t nic7018_thread_isr(int irq, void *wdt_arg) +{ + struct nic7018_wdt *wdt = wdt_arg; + struct watchdog_device *wdd = &wdt->wdd; + u8 status, control; + + status = inb(wdt->io_base + WDT_STATUS); + + /* IRQ line asserted */ + if (status & 0x20) { + + mutex_lock(&wdt->lock); + + control = inb(wdt->io_base + WDT_CTRL); + /* Disable IRQ line */ + outb(control & ~WDT_CTRL_INTERRUPT_EN, + wdt->io_base + WDT_CTRL); + + mutex_unlock(&wdt->lock); + + kobject_uevent(&wdd->parent->kobj, KOBJ_CHANGE); + } + return IRQ_HANDLED; +} + static int nic7018_start(struct watchdog_device *wdd) { struct nic7018_wdt *wdt = watchdog_get_drvdata(wdd); @@ -240,6 +268,7 @@ static WDT_ATTR(enable_soft_ping, WDT_RELOAD_CTRL, WDT_RELOAD_PORT_EN); static WDT_ATTR(trigger_polarity, WDT_CTRL, WDT_CTRL_TRIG_POL); static WDT_ATTR(keepalive_trigger_polarity, WDT_RELOAD_CTRL, WDT_RELOAD_TRIG_POL); +static WDT_ATTR(enable_interrupt, WDT_CTRL, WDT_CTRL_INTERRUPT_EN); static ssize_t wdt_trig_show(struct device *dev, struct device_attribute *da, @@ -324,6 +353,7 @@ static struct attribute *nic7018_wdt_attrs[] = { &dev_attr_enable_soft_ping.dev_attr.attr, &dev_attr_trigger_polarity.dev_attr.attr, &dev_attr_keepalive_trigger_polarity.dev_attr.attr, + &dev_attr_enable_interrupt.dev_attr.attr, &dev_attr_trigger.dev_attr.attr, &dev_attr_keepalive_trigger.dev_attr.attr, NULL @@ -336,7 +366,7 @@ static int nic7018_probe(struct platform_device *pdev) struct watchdog_device *wdd; struct nic7018_wdt *wdt; struct resource *io_rc; - int ret; + int ret, irq; wdt = devm_kzalloc(dev, sizeof(*wdt), GFP_KERNEL); if (!wdt) @@ -356,6 +386,10 @@ static int nic7018_probe(struct platform_device *pdev) return -EBUSY; } + irq = platform_get_irq(pdev, 0); + if (!irq) + return -EINVAL; + mutex_init(&wdt->lock); wdt->io_base = io_rc->start; @@ -372,6 +406,15 @@ static int nic7018_probe(struct platform_device *pdev) watchdog_set_nowayout(wdd, nowayout); watchdog_init_timeout(wdd, timeout, dev); + ret = devm_request_threaded_irq(dev, irq, NULL, + nic7018_thread_isr, + IRQF_ONESHOT, + KBUILD_MODNAME, wdt); + if (ret) { + dev_err(dev, "failed to register interrupt handler\n"); + return ret; + } + /* Unlock WDT register */ outb(UNLOCK, wdt->io_base + WDT_REG_LOCK); From 4c7ea05ea5467d85c699de61e619f3b1e7e04bff Mon Sep 17 00:00:00 2001 From: Jonathan David Date: Thu, 15 Oct 2015 15:39:04 -0500 Subject: [PATCH 066/110] e1000e: Add delays after writing to registers There is a noticeable impact on determinism when a large number of writes are flushed. Writes to the hardware registers are sent across the PCI bus and take a significant amount of time to complete after a flush, which causes high priority tasks (including interrupts) to be delayed. This problem stems from an issue with the PCI bus where a fabric lock is held during I/O buffer drain. This process can be detrimental to real-time systems and is seen whenever a large number of MMIO writes are issued. In the case of the e1000 drivers, when a device is reset several tables (MTA, VLAN, etc) are rewritten, generating enough MMIO writes over PCI for the latency issues to be seen. Adding a delay after long series of writes gives them time to complete (drain the I/O buffer), and for higher priority tasks to run unimpeded. Signed-off-by: Jonathan David Signed-off-by: Brad Mouring [bstreiff: remove unused 'rar_count'] Signed-off-by: Brandon Streiff [gratian: update Kconfig '---help---' to 'help'] Signed-off-by: Gratian Crisan --- drivers/net/ethernet/intel/Kconfig | 9 +++++++++ drivers/net/ethernet/intel/e1000/e1000.h | 7 +++++++ drivers/net/ethernet/intel/e1000/e1000_main.c | 5 +++++ drivers/net/ethernet/intel/e1000e/82571.c | 5 +++++ drivers/net/ethernet/intel/e1000e/e1000.h | 7 +++++++ drivers/net/ethernet/intel/e1000e/mac.c | 1 + drivers/net/ethernet/intel/e1000e/netdev.c | 7 +++++++ 7 files changed, 41 insertions(+) diff --git a/drivers/net/ethernet/intel/Kconfig b/drivers/net/ethernet/intel/Kconfig index 5aa86318ed3e1..d605f6c9bd594 100644 --- a/drivers/net/ethernet/intel/Kconfig +++ b/drivers/net/ethernet/intel/Kconfig @@ -84,6 +84,15 @@ config E1000E_HWTS devices. The cross-timestamp is available through the PTP clock driver precise cross-timestamp ioctl (PTP_SYS_OFFSET_PRECISE). +config E1000_DELAY + bool "Add delays to e1000x drivers" + default n + depends on (E1000E || E1000) && PREEMPT_RT_FULL + help + Enable delays after large numbers of MMIO writes to registers. + The delays aid in preventing noticeable impact on real-time + performance when a connection is interrupted. + config IGB tristate "Intel(R) 82575/82576 PCI-Express Gigabit Ethernet support" depends on PCI diff --git a/drivers/net/ethernet/intel/e1000/e1000.h b/drivers/net/ethernet/intel/e1000/e1000.h index 4817eb13ca6f8..d699128f329e3 100644 --- a/drivers/net/ethernet/intel/e1000/e1000.h +++ b/drivers/net/ethernet/intel/e1000/e1000.h @@ -199,6 +199,13 @@ struct e1000_rx_ring { #define E1000_TX_DESC(R, i) E1000_GET_DESC(R, i, e1000_tx_desc) #define E1000_CONTEXT_DESC(R, i) E1000_GET_DESC(R, i, e1000_context_desc) +/* Time to wait after writing large amount of data to registers */ +#ifdef CONFIG_E1000_DELAY +#define E1000_WR_DELAY() usleep_range(50, 100) +#else +#define E1000_WR_DELAY() +#endif + /* board specific private data structure */ struct e1000_adapter { diff --git a/drivers/net/ethernet/intel/e1000/e1000_main.c b/drivers/net/ethernet/intel/e1000/e1000_main.c index 5e28cf4fa2cd9..2d384b19822a9 100644 --- a/drivers/net/ethernet/intel/e1000/e1000_main.c +++ b/drivers/net/ethernet/intel/e1000/e1000_main.c @@ -2158,6 +2158,7 @@ static void e1000_enter_82542_rst(struct e1000_adapter *adapter) rctl = er32(RCTL); rctl |= E1000_RCTL_RST; ew32(RCTL, rctl); + E1000_WR_DELAY(); E1000_WRITE_FLUSH(); mdelay(5); @@ -2174,6 +2175,7 @@ static void e1000_leave_82542_rst(struct e1000_adapter *adapter) rctl = er32(RCTL); rctl &= ~E1000_RCTL_RST; ew32(RCTL, rctl); + E1000_WR_DELAY(); E1000_WRITE_FLUSH(); mdelay(5); @@ -2322,6 +2324,9 @@ static void e1000_set_rx_mode(struct net_device *netdev) */ E1000_WRITE_REG_ARRAY(hw, MTA, i, mcarray[i]); } + + E1000_WR_DELAY(); + E1000_WRITE_FLUSH(); if (hw->mac_type == e1000_82542_rev2_0) diff --git a/drivers/net/ethernet/intel/e1000e/82571.c b/drivers/net/ethernet/intel/e1000e/82571.c index 88faf05e23baf..2486c689e143e 100644 --- a/drivers/net/ethernet/intel/e1000e/82571.c +++ b/drivers/net/ethernet/intel/e1000e/82571.c @@ -494,6 +494,8 @@ static void e1000_put_hw_semaphore_82571(struct e1000_hw *hw) { u32 swsm; + E1000_WR_DELAY(); + swsm = er32(SWSM); swsm &= ~(E1000_SWSM_SMBI | E1000_SWSM_SWESMBI); ew32(SWSM, swsm); @@ -545,6 +547,7 @@ static void e1000_put_hw_semaphore_82573(struct e1000_hw *hw) { u32 extcnf_ctrl; + E1000_WR_DELAY(); extcnf_ctrl = er32(EXTCNF_CTRL); extcnf_ctrl &= ~E1000_EXTCNF_CTRL_MDIO_SW_OWNERSHIP; ew32(EXTCNF_CTRL, extcnf_ctrl); @@ -1094,6 +1097,8 @@ static s32 e1000_init_hw_82571(struct e1000_hw *hw) for (i = 0; i < mac->mta_reg_count; i++) E1000_WRITE_REG_ARRAY(hw, E1000_MTA, i, 0); + E1000_WR_DELAY(); + /* Setup link and flow control */ ret_val = mac->ops.setup_link(hw); diff --git a/drivers/net/ethernet/intel/e1000e/e1000.h b/drivers/net/ethernet/intel/e1000e/e1000.h index ba7a0f8f69376..07aee62e4355a 100644 --- a/drivers/net/ethernet/intel/e1000e/e1000.h +++ b/drivers/net/ethernet/intel/e1000e/e1000.h @@ -70,6 +70,13 @@ struct e1000_info; /* Time to wait before putting the device into D3 if there's no link (in ms). */ #define LINK_TIMEOUT 100 +/* Time to wait after writing large amount of data to registers */ +#ifdef CONFIG_E1000_DELAY +#define E1000_WR_DELAY() usleep_range(50, 100) +#else +#define E1000_WR_DELAY() +#endif + /* Count for polling __E1000_RESET condition every 10-20msec. * Experimentation has shown the reset can take approximately 210msec. */ diff --git a/drivers/net/ethernet/intel/e1000e/mac.c b/drivers/net/ethernet/intel/e1000e/mac.c index 51512a73fdd07..6aac464ae0cb9 100644 --- a/drivers/net/ethernet/intel/e1000e/mac.c +++ b/drivers/net/ethernet/intel/e1000e/mac.c @@ -335,6 +335,7 @@ void e1000e_update_mc_addr_list_generic(struct e1000_hw *hw, /* replace the entire MTA table */ for (i = hw->mac.mta_reg_count - 1; i >= 0; i--) E1000_WRITE_REG_ARRAY(hw, E1000_MTA, i, hw->mac.mta_shadow[i]); + E1000_WR_DELAY(); e1e_flush(); } diff --git a/drivers/net/ethernet/intel/e1000e/netdev.c b/drivers/net/ethernet/intel/e1000e/netdev.c index b30f00891c037..2ec2eeb72777a 100644 --- a/drivers/net/ethernet/intel/e1000e/netdev.c +++ b/drivers/net/ethernet/intel/e1000e/netdev.c @@ -2980,6 +2980,7 @@ static void e1000_configure_tx(struct e1000_adapter *adapter) e1000e_update_tdt_wa(tx_ring, 0); else writel(0, tx_ring->tail); + E1000_WR_DELAY(); /* Set the Tx Interrupt Delay register */ ew32(TIDV, adapter->tx_int_delay); @@ -3257,6 +3258,7 @@ static void e1000_configure_rx(struct e1000_adapter *adapter) rctl = er32(RCTL); if (!(adapter->flags2 & FLAG2_NO_DISABLE_RX)) ew32(RCTL, rctl & ~E1000_RCTL_EN); + E1000_WR_DELAY(); e1e_flush(); usleep_range(10000, 11000); @@ -3286,6 +3288,7 @@ static void e1000_configure_rx(struct e1000_adapter *adapter) ctrl_ext |= E1000_CTRL_EXT_IAME; ew32(IAM, 0xffffffff); ew32(CTRL_EXT, ctrl_ext); + E1000_WR_DELAY(); e1e_flush(); /* Setup the HW Rx Head and Tail Descriptor Pointers and @@ -3305,6 +3308,7 @@ static void e1000_configure_rx(struct e1000_adapter *adapter) e1000e_update_rdt_wa(rx_ring, 0); else writel(0, rx_ring->tail); + E1000_WR_DELAY(); /* Enable Receive Checksum Offload for TCP and UDP */ rxcsum = er32(RXCSUM); @@ -3430,6 +3434,7 @@ static int e1000e_write_uc_addr_list(struct net_device *netdev) ew32(RAH(rar_entries), 0); ew32(RAL(rar_entries), 0); } + E1000_WR_DELAY(); e1e_flush(); return count; @@ -3505,10 +3510,12 @@ static void e1000e_setup_rss_hash(struct e1000_adapter *adapter) netdev_rss_key_fill(rss_key, sizeof(rss_key)); for (i = 0; i < 10; i++) ew32(RSSRK(i), rss_key[i]); + E1000_WR_DELAY(); /* Direct all traffic to queue 0 */ for (i = 0; i < 32; i++) ew32(RETA(i), 0); + E1000_WR_DELAY(); /* Disable raw packet checksumming so that RSS hash is placed in * descriptor on writeback. From 14f7cee140c7c1cd9983092841ff612c69cdb698 Mon Sep 17 00:00:00 2001 From: Sundar Subbiah Date: Tue, 2 Apr 2013 15:19:22 -0500 Subject: [PATCH 067/110] wlcore: Depend on WIRELESS_EXT for nitargetcfg This is a hack to get CONFIG_WIRELESS_EXT enabled, since if it is turned on in the defconfig it will not propogate to the .config (as it is not user selectable). Even though the driver does not need it, the current NI user-mode software stacks require this support for scanning and interface enumeration. With this change, it will propogate to the wl12xx driver build (from compat-wireless) and thus include WEXT support in that driver and wireless networking modules. Signed-off-by: Sundar Subbiah Acked-by: James Minor Acked-by: Josh Cartwright Acked-by: Jeff Westfahl Acked-by: Ken Sharp Natinst-ReviewBoard-ID: 37925 --- drivers/net/wireless/ti/wlcore/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/wireless/ti/wlcore/Kconfig b/drivers/net/wireless/ti/wlcore/Kconfig index 8094323256fb9..3f652e66e2553 100644 --- a/drivers/net/wireless/ti/wlcore/Kconfig +++ b/drivers/net/wireless/ti/wlcore/Kconfig @@ -3,6 +3,7 @@ config WLCORE tristate "TI wlcore support" depends on MAC80211 select FW_LOADER + select WIRELESS_EXT help This module contains the main code for TI WLAN chips. It abstracts hardware-specific differences among different chipset families. From 0bbbe16f4e01a758ef6a15ba74f60f89bb84ea2d Mon Sep 17 00:00:00 2001 From: James Minor Date: Mon, 16 Mar 2015 17:22:51 -0500 Subject: [PATCH 068/110] cfg80211: wext: Force scans to occur in AP mode When in AP mode, we should force scans to happen from the wext compatibility layer. This won't hurt when in station mode, and only affects the wl12xx driver. This change is to retain parity with NI's shipped 3.2 kernel. It can be dropped when we switch away from using the WEXT interface, and should not be upstreamed. Signed-off-by: James Minor Reviewed-by: Ben Shelton Reviewed-by: Jaeden Amero Natinst-ReviewBoard-ID: 92027 --- net/wireless/scan.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/net/wireless/scan.c b/net/wireless/scan.c index 8d0e49c46db37..3afc1a9e922b0 100644 --- a/net/wireless/scan.c +++ b/net/wireless/scan.c @@ -2753,6 +2753,9 @@ int cfg80211_wext_siwscan(struct net_device *dev, /* Set real number of channels specified in creq->channels[] */ creq->n_channels = i; + /* Force the scan if we are in AP mode */ + creq->flags |= NL80211_SCAN_FLAG_AP; + /* translate "Scan for SSID" request */ if (wreq) { if (wrqu->data.flags & IW_SCAN_THIS_ESSID) { From 76a6760ceac56b74c4e531066a904a0a0cd39b2e Mon Sep 17 00:00:00 2001 From: Nathan Sullivan Date: Thu, 5 Nov 2015 14:53:58 -0600 Subject: [PATCH 069/110] ath6kl: set initial region using DMI info Use the BIOS DMI tables to select an initial region for regulatory info. The region in BIOS will be set in manufacturing based on where the product is to be used. This is intended to facilitate channel and power level selection based on the product's SKU. Signed-off-by: Nathan Sullivan Signed-off-by: James Minor Signed-off-by: Brad Mouring Natinst-CAR-ID: 578408 Natinst-ReviewBoard-ID: 120508 Natinst-ReviewBoard-ID: 130950 Natinst-Trello-ID: https://trello.com/c/xCpOlFJt [bstreiff: remove elvisiii dts changes as part of zynq removal] Signed-off-by: Brandon Streiff [gratian: update Kconfig '---help---' to 'help'] Signed-off-by: Gratian Crisan --- drivers/net/wireless/ath/ath6kl/Kconfig | 9 +++++ drivers/net/wireless/ath/ath6kl/core.c | 50 +++++++++++++++++++++++++ drivers/net/wireless/ath/ath6kl/wmi.c | 6 +++ drivers/net/wireless/ath/ath6kl/wmi.h | 3 ++ 4 files changed, 68 insertions(+) diff --git a/drivers/net/wireless/ath/ath6kl/Kconfig b/drivers/net/wireless/ath/ath6kl/Kconfig index cd96cf8d99409..a9ac19f2c3727 100644 --- a/drivers/net/wireless/ath/ath6kl/Kconfig +++ b/drivers/net/wireless/ath/ath6kl/Kconfig @@ -64,3 +64,12 @@ config ATH6KL_REGDOMAIN are taken into account. If unsure, say N. + +config ATH6KL_NI_BIOS_DOMAIN + bool "Atheros ath6kl DMI regdomain support" + depends on ATH6KL + help + Enabling this will cause the ath6kl driver to load the initial + regdomain from BIOS DMI tables. + + If unsure, say N. diff --git a/drivers/net/wireless/ath/ath6kl/core.c b/drivers/net/wireless/ath/ath6kl/core.c index ebb9f163710fa..d6b91c27bed9a 100644 --- a/drivers/net/wireless/ath/ath6kl/core.c +++ b/drivers/net/wireless/ath/ath6kl/core.c @@ -21,6 +21,8 @@ #include #include #include +#include +#include #include "debug.h" #include "hif-ops.h" @@ -51,6 +53,31 @@ MODULE_PARM_DESC(heart_beat_poll, "Enable fw error detection periodic polling in msecs - Also set recovery_enable for this to be effective"); +#define WLAN_REGION_ID 161 +#ifdef CONFIG_ATH6KL_NI_BIOS_DOMAIN +struct region_table { + struct dmi_header header; + char padding[3]; + char alpha2[2]; +}; + +static char region[2]; +static void find_region_type(const struct dmi_header *dm, void *private_data) +{ + int *found = (int *)private_data; + + if (dm->type == WLAN_REGION_ID) { + struct region_table *table = + container_of(dm, struct region_table, header); + + ath6kl_dbg(ATH6KL_DBG_TRC, "Region code from BIOS: %c%c\n", + table->alpha2[0], table->alpha2[1]); + memcpy(region, table->alpha2, 2); + *found = 1; + } +} +#endif + void ath6kl_core_tx_complete(struct ath6kl *ar, struct sk_buff *skb) { ath6kl_htc_tx_complete(ar, skb); @@ -69,6 +96,20 @@ int ath6kl_core_init(struct ath6kl *ar, enum ath6kl_htc_type htc_type) struct wireless_dev *wdev; int ret = 0, i; +#ifdef CONFIG_ATH6KL_NI_BIOS_DOMAIN + /* get region code from DMI */ + dmi_walk(find_region_type, &ret); + if (!ret) + return -ENODEV; + + if (!isascii(region[0]) || !isascii(region[1])) + return -EINVAL; + + ath6kl_info("Using region: %c%c\n", + region[0], + region[1]); +#endif + switch (htc_type) { case ATH6KL_HTC_TYPE_MBOX: ath6kl_htc_mbox_attach(ar); @@ -194,6 +235,15 @@ int ath6kl_core_init(struct ath6kl *ar, enum ath6kl_htc_type htc_type) goto err_rxbuf_cleanup; } +#ifdef CONFIG_ATH6KL_NI_BIOS_DOMAIN + /* set region from DMI if it is US */ + if (region[0] == 'U' && region[1] == 'S') { + ret = ath6kl_wmi_set_regdomain_cmd(ar->wmi, region); + if (ret) + goto err_rxbuf_cleanup; + } +#endif + /* give our connected endpoints some buffers */ ath6kl_rx_refill(ar->htc_target, ar->ctrl_ep); ath6kl_rx_refill(ar->htc_target, ar->ac2ep_map[WMM_AC_BE]); diff --git a/drivers/net/wireless/ath/ath6kl/wmi.c b/drivers/net/wireless/ath/ath6kl/wmi.c index dbc47702a268d..a40d0ca71e2e8 100644 --- a/drivers/net/wireless/ath/ath6kl/wmi.c +++ b/drivers/net/wireless/ath/ath6kl/wmi.c @@ -3306,9 +3306,15 @@ int ath6kl_wmi_set_regdomain_cmd(struct wmi *wmi, const char *alpha2) cmd = (struct wmi_set_regdomain_cmd *) skb->data; memcpy(cmd->iso_name, alpha2, 2); +#ifdef CONFIG_ATH6KL_SILEX_FIRMWARE + return ath6kl_wmi_cmd_send(wmi, 0, skb, + WMI_SET_REGDOMAIN_SILEX_CMDID, + NO_SYNC_WMIFLAG); +#else return ath6kl_wmi_cmd_send(wmi, 0, skb, WMI_SET_REGDOMAIN_CMDID, NO_SYNC_WMIFLAG); +#endif } s32 ath6kl_wmi_get_rate(struct wmi *wmi, s8 rate_index) diff --git a/drivers/net/wireless/ath/ath6kl/wmi.h b/drivers/net/wireless/ath/ath6kl/wmi.h index 784940ba4c909..7de770a1f238c 100644 --- a/drivers/net/wireless/ath/ath6kl/wmi.h +++ b/drivers/net/wireless/ath/ath6kl/wmi.h @@ -644,6 +644,9 @@ enum wmi_cmd_id { WMI_ENABLE_SCHED_SCAN_CMDID, }; +/* Silex has this command at a different ID */ +#define WMI_SET_REGDOMAIN_SILEX_CMDID 0xf0b0 + enum wmi_mgmt_frame_type { WMI_FRAME_BEACON = 0, WMI_FRAME_PROBE_REQ, From 4f6be2e4403f1b614a173362383ee7c337e25495 Mon Sep 17 00:00:00 2001 From: James Minor Date: Wed, 28 Oct 2015 12:16:56 -0500 Subject: [PATCH 070/110] ath6kl: Add Silex firmware capabilities Signed-off-by: James Minor [gratian: update Kconfig '---help---' to 'help'] Signed-off-by: Gratian Crisan --- drivers/net/wireless/ath/ath6kl/Kconfig | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/drivers/net/wireless/ath/ath6kl/Kconfig b/drivers/net/wireless/ath/ath6kl/Kconfig index a9ac19f2c3727..89eddce784310 100644 --- a/drivers/net/wireless/ath/ath6kl/Kconfig +++ b/drivers/net/wireless/ath/ath6kl/Kconfig @@ -73,3 +73,12 @@ config ATH6KL_NI_BIOS_DOMAIN regdomain from BIOS DMI tables. If unsure, say N. + +config ATH6KL_SILEX_FIRMWARE + bool "Atheros ath6kl Silex firmware support" + depends on ATH6KL + help + Enabling this will cause the ath6kl driver to use customizations + required by the firmware from Silex. + + If unsure, say N. From 37962b9999e006f04ad2431fd0c544b2e8facbe1 Mon Sep 17 00:00:00 2001 From: Nathan Sullivan Date: Wed, 16 Mar 2016 09:01:15 -0500 Subject: [PATCH 071/110] ath6kl: select board file using DMI info In addition to setting the region on the device, switch board files based on the selected region from BIOS. This allows different boards to load files with different power levels for regulatory purposes. Signed-off-by: Nathan Sullivan Signed-off-by: Brad Mouring Acked-by: Xander Huff Acked-by: James Minor Natinst-CAR-ID: 578408 Natinst-ReviewBoard-ID: 130950 --- drivers/net/wireless/ath/ath6kl/core.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/drivers/net/wireless/ath/ath6kl/core.c b/drivers/net/wireless/ath/ath6kl/core.c index d6b91c27bed9a..164a8f8cc5637 100644 --- a/drivers/net/wireless/ath/ath6kl/core.c +++ b/drivers/net/wireless/ath/ath6kl/core.c @@ -97,6 +97,7 @@ int ath6kl_core_init(struct ath6kl *ar, enum ath6kl_htc_type htc_type) int ret = 0, i; #ifdef CONFIG_ATH6KL_NI_BIOS_DOMAIN + char *region_board_file = NULL; /* get region code from DMI */ dmi_walk(find_region_type, &ret); if (!ret) @@ -160,6 +161,17 @@ int ath6kl_core_init(struct ath6kl *ar, enum ath6kl_htc_type htc_type) ar->testmode = testmode; +#ifdef CONFIG_ATH6KL_NI_BIOS_DOMAIN + /* ath6kl_init_hw_params() will set the board file name, but we want + * to override it with a region specific board file here. + */ + region_board_file = devm_kzalloc(ar->dev, 64, GFP_KERNEL); + + snprintf(region_board_file, 64, AR6004_HW_3_0_FW_DIR "/bdata%c%c.bin", + region[0], region[1]); + + ar->hw.fw_board = region_board_file; +#endif ret = ath6kl_init_fetch_firmwares(ar); if (ret) goto err_htc_cleanup; From 293d0752dddb93026a7724756fd325aea7113d00 Mon Sep 17 00:00:00 2001 From: James Minor Date: Mon, 4 Apr 2016 12:15:18 -0500 Subject: [PATCH 072/110] ath6kl: Add ATH6KL_FW_CAPABILITY_SET_RSN_CAP capabilities Some firmwares offer the ability to directly set the RSN with WMI_SET_RSN_CAP_CMDID instead of using WMI_SET_IE_CMDID. Add the flags and functions to make that work. Signed-off-by: James Minor Signed-off-by: Brad Mouring Natinst-ReviewBoard-ID: 133028 Natinst-CAR-ID: 577496 --- drivers/net/wireless/ath/ath6kl/cfg80211.c | 22 +++++++++++++++------- drivers/net/wireless/ath/ath6kl/core.h | 3 +++ drivers/net/wireless/ath/ath6kl/init.c | 1 + drivers/net/wireless/ath/ath6kl/wmi.c | 18 ++++++++++++++++++ drivers/net/wireless/ath/ath6kl/wmi.h | 6 ++++++ 5 files changed, 43 insertions(+), 7 deletions(-) diff --git a/drivers/net/wireless/ath/ath6kl/cfg80211.c b/drivers/net/wireless/ath/ath6kl/cfg80211.c index 9c83e9a4299b0..b2e73d7b292d4 100644 --- a/drivers/net/wireless/ath/ath6kl/cfg80211.c +++ b/drivers/net/wireless/ath/ath6kl/cfg80211.c @@ -2933,14 +2933,22 @@ static int ath6kl_start_ap(struct wiphy *wiphy, struct net_device *dev, * advertise the same in beacon/probe response. Send * the complete RSN IE capability field to firmware */ - if (!ath6kl_get_rsn_capab(&info->beacon, (u8 *) &rsn_capab) && - test_bit(ATH6KL_FW_CAPABILITY_RSN_CAP_OVERRIDE, - ar->fw_capabilities)) { - res = ath6kl_wmi_set_ie_cmd(ar->wmi, vif->fw_vif_idx, - WLAN_EID_RSN, WMI_RSN_IE_CAPB, - (const u8 *) &rsn_capab, - sizeof(rsn_capab)); + if (!ath6kl_get_rsn_capab(&info->beacon, (u8 *)&rsn_capab)) { vif->rsn_capab = rsn_capab; + res = -EIO; + if (test_bit(ATH6KL_FW_CAPABILITY_RSN_CAP_OVERRIDE, + ar->fw_capabilities)) { + res = ath6kl_wmi_set_ie_cmd(ar->wmi, vif->fw_vif_idx, + WLAN_EID_RSN, + WMI_RSN_IE_CAPB, + (const u8 *)&rsn_capab, + sizeof(rsn_capab)); + } + if (test_bit(ATH6KL_FW_CAPABILITY_SET_RSN_CAP, + ar->fw_capabilities)) { + res = ath6kl_wmi_set_rsn_cmd(ar->wmi, vif->fw_vif_idx, + rsn_capab); + } if (res < 0) return res; } diff --git a/drivers/net/wireless/ath/ath6kl/core.h b/drivers/net/wireless/ath/ath6kl/core.h index 77e052336eb5b..96c8ab6f096f7 100644 --- a/drivers/net/wireless/ath/ath6kl/core.h +++ b/drivers/net/wireless/ath/ath6kl/core.h @@ -151,6 +151,9 @@ enum ath6kl_fw_capability { /* firmware doesn't support IP checksumming */ ATH6KL_FW_CAPABILITY_NO_IP_CHECKSUM, + /* firmware supports setting RSN CAP directly */ + ATH6KL_FW_CAPABILITY_SET_RSN_CAP, + /* this needs to be last */ ATH6KL_FW_CAPABILITY_MAX, }; diff --git a/drivers/net/wireless/ath/ath6kl/init.c b/drivers/net/wireless/ath/ath6kl/init.c index 39bf196861751..0e84c39ed0c6e 100644 --- a/drivers/net/wireless/ath/ath6kl/init.c +++ b/drivers/net/wireless/ath/ath6kl/init.c @@ -1644,6 +1644,7 @@ static const struct fw_capa_str_map { { ATH6KL_FW_CAPABILITY_MAP_LP_ENDPOINT, "map-lp-endpoint" }, { ATH6KL_FW_CAPABILITY_RATETABLE_MCS15, "ratetable-mcs15" }, { ATH6KL_FW_CAPABILITY_NO_IP_CHECKSUM, "no-ip-checksum" }, + { ATH6KL_FW_CAPABILITY_SET_RSN_CAP, "set-rsn-cap" }, }; static const char *ath6kl_init_get_fw_capa_name(unsigned int id) diff --git a/drivers/net/wireless/ath/ath6kl/wmi.c b/drivers/net/wireless/ath/ath6kl/wmi.c index a40d0ca71e2e8..6d5aa0d5acb6d 100644 --- a/drivers/net/wireless/ath/ath6kl/wmi.c +++ b/drivers/net/wireless/ath/ath6kl/wmi.c @@ -3581,6 +3581,24 @@ int ath6kl_wmi_set_appie_cmd(struct wmi *wmi, u8 if_idx, u8 mgmt_frm_type, NO_SYNC_WMIFLAG); } +int ath6kl_wmi_set_rsn_cmd(struct wmi *wmi, u8 if_idx, u16 rsn_capab) +{ + struct sk_buff *skb; + struct wmi_set_rsn_cmd *p; + + skb = ath6kl_wmi_get_new_buf(sizeof(*p)); + if (!skb) + return -ENOMEM; + + ath6kl_info("set_rsn_cmd: rsn_capab=0x%4.4x\n", + rsn_capab); + p = (struct wmi_set_rsn_cmd *)skb->data; + p->rsn_capab = rsn_capab; + + return ath6kl_wmi_cmd_send(wmi, if_idx, skb, WMI_SET_RSN_CAP_CMDID, + NO_SYNC_WMIFLAG); +} + int ath6kl_wmi_set_ie_cmd(struct wmi *wmi, u8 if_idx, u8 ie_id, u8 ie_field, const u8 *ie_info, u8 ie_len) { diff --git a/drivers/net/wireless/ath/ath6kl/wmi.h b/drivers/net/wireless/ath/ath6kl/wmi.h index 7de770a1f238c..facdd4e3716c0 100644 --- a/drivers/net/wireless/ath/ath6kl/wmi.h +++ b/drivers/net/wireless/ath/ath6kl/wmi.h @@ -2057,6 +2057,10 @@ struct wmi_set_appie_cmd { u8 ie_info[0]; } __packed; +struct wmi_set_rsn_cmd { + u16 rsn_capab; +} __packed; + struct wmi_set_ie_cmd { u8 ie_id; u8 ie_field; /* enum wmi_ie_field_type */ @@ -2691,6 +2695,8 @@ int ath6kl_wmi_set_rx_frame_format_cmd(struct wmi *wmi, u8 if_idx, u8 rx_meta_version, bool rx_dot11_hdr, bool defrag_on_host); +int ath6kl_wmi_set_rsn_cmd(struct wmi *wmi, u8 if_idx, u16 rsn_capab); + int ath6kl_wmi_set_appie_cmd(struct wmi *wmi, u8 if_idx, u8 mgmt_frm_type, const u8 *ie, u8 ie_len); From c4cb4f8dcbea7c73ab1520d4bc6e2a04e52c91a2 Mon Sep 17 00:00:00 2001 From: James Minor Date: Mon, 4 Apr 2016 12:17:46 -0500 Subject: [PATCH 073/110] ath6kl: Add Silex enums to set APPIE and RSN CAP Silex uses different command IDs for the commands WMI_SET_APPIE_CMDID and WMI_SET_RSN_CAP_SILEX_CMDID. In case of the Silex firmware, remap them to the correct command ID. Signed-off-by: James Minor Signed-off-by: Brad Mouring Natinst-ReviewBoard-ID: 133028 Natinst-CAR-ID: 577496 --- drivers/net/wireless/ath/ath6kl/wmi.c | 18 +++++++++++++++--- drivers/net/wireless/ath/ath6kl/wmi.h | 2 ++ 2 files changed, 17 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/ath/ath6kl/wmi.c b/drivers/net/wireless/ath/ath6kl/wmi.c index 6d5aa0d5acb6d..2255e01ca0c97 100644 --- a/drivers/net/wireless/ath/ath6kl/wmi.c +++ b/drivers/net/wireless/ath/ath6kl/wmi.c @@ -3577,8 +3577,13 @@ int ath6kl_wmi_set_appie_cmd(struct wmi *wmi, u8 if_idx, u8 mgmt_frm_type, if (ie != NULL && ie_len > 0) memcpy(p->ie_info, ie, ie_len); - return ath6kl_wmi_cmd_send(wmi, if_idx, skb, WMI_SET_APPIE_CMDID, - NO_SYNC_WMIFLAG); +#ifdef CONFIG_ATH6KL_SILEX_FIRMWARE + return ath6kl_wmi_cmd_send(wmi, if_idx, skb, + WMI_SET_APPIE_SILEX_CMDID, NO_SYNC_WMIFLAG); +#else + return ath6kl_wmi_cmd_send(wmi, if_idx, skb, + WMI_SET_APPIE_CMDID, NO_SYNC_WMIFLAG); +#endif } int ath6kl_wmi_set_rsn_cmd(struct wmi *wmi, u8 if_idx, u16 rsn_capab) @@ -3595,8 +3600,15 @@ int ath6kl_wmi_set_rsn_cmd(struct wmi *wmi, u8 if_idx, u16 rsn_capab) p = (struct wmi_set_rsn_cmd *)skb->data; p->rsn_capab = rsn_capab; - return ath6kl_wmi_cmd_send(wmi, if_idx, skb, WMI_SET_RSN_CAP_CMDID, +#ifdef CONFIG_ATH6KL_SILEX_FIRMWARE + return ath6kl_wmi_cmd_send(wmi, if_idx, skb, + WMI_SET_RSN_CAP_SILEX_CMDID, + NO_SYNC_WMIFLAG); +#else + return ath6kl_wmi_cmd_send(wmi, if_idx, skb, + WMI_SET_RSN_CAP_CMDID, NO_SYNC_WMIFLAG); +#endif } int ath6kl_wmi_set_ie_cmd(struct wmi *wmi, u8 if_idx, u8 ie_id, u8 ie_field, diff --git a/drivers/net/wireless/ath/ath6kl/wmi.h b/drivers/net/wireless/ath/ath6kl/wmi.h index facdd4e3716c0..5e44ee92b0b55 100644 --- a/drivers/net/wireless/ath/ath6kl/wmi.h +++ b/drivers/net/wireless/ath/ath6kl/wmi.h @@ -646,6 +646,8 @@ enum wmi_cmd_id { /* Silex has this command at a different ID */ #define WMI_SET_REGDOMAIN_SILEX_CMDID 0xf0b0 +#define WMI_SET_APPIE_SILEX_CMDID 0x3f +#define WMI_SET_RSN_CAP_SILEX_CMDID 0xf082 enum wmi_mgmt_frame_type { WMI_FRAME_BEACON = 0, From 46c921f813fa3d5d15decd4006c8445bf7dc1ab0 Mon Sep 17 00:00:00 2001 From: James Minor Date: Thu, 25 Feb 2016 10:18:02 -0600 Subject: [PATCH 074/110] ath6kl: fix firmware race condition by retrying initialization Sometimes the devices will fail to boot the first time, but will work fine when retried. Retry the initialization a few times before failing (and reset the hardware properly when it fails). Signed-off-by: James Minor Signed-off-by: Brad Mouring Natinst-ReviewBoard-ID: 130170 Natinst-CAR-ID: 566029 --- drivers/net/wireless/ath/ath6kl/core.c | 18 +++++++++++++++--- drivers/net/wireless/ath/ath6kl/core.h | 3 +++ drivers/net/wireless/ath/ath6kl/init.c | 2 ++ 3 files changed, 20 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/ath/ath6kl/core.c b/drivers/net/wireless/ath/ath6kl/core.c index 164a8f8cc5637..633e0d4367f9c 100644 --- a/drivers/net/wireless/ath/ath6kl/core.c +++ b/drivers/net/wireless/ath/ath6kl/core.c @@ -38,6 +38,7 @@ static unsigned int ath6kl_p2p; static unsigned int testmode; static unsigned int recovery_enable; static unsigned int heart_beat_poll; +static unsigned int boot_attempts; module_param(debug_mask, uint, 0644); module_param(suspend_mode, uint, 0644); @@ -48,9 +49,11 @@ module_param(ath6kl_p2p, uint, 0644); module_param(testmode, uint, 0644); module_param(recovery_enable, uint, 0644); module_param(heart_beat_poll, uint, 0644); +module_param(boot_attempts, uint, 0644); MODULE_PARM_DESC(recovery_enable, "Enable recovery from firmware error"); MODULE_PARM_DESC(heart_beat_poll, "Enable fw error detection periodic polling in msecs - Also set recovery_enable for this to be effective"); +MODULE_PARM_DESC(boot_attempts, "Number of times to retry booting the firmware"); #define WLAN_REGION_ID 161 @@ -111,6 +114,8 @@ int ath6kl_core_init(struct ath6kl *ar, enum ath6kl_htc_type htc_type) region[1]); #endif + ar->boot_attempts = boot_attempts; + switch (htc_type) { case ATH6KL_HTC_TYPE_MBOX: ath6kl_htc_mbox_attach(ar); @@ -242,11 +247,18 @@ int ath6kl_core_init(struct ath6kl *ar, enum ath6kl_htc_type htc_type) ath6kl_debug_init(ar); ret = ath6kl_init_hw_start(ar); - if (ret) { - ath6kl_err("Failed to start hardware: %d\n", ret); - goto err_rxbuf_cleanup; + while (ret && ar->boot_attempts) { + ath6kl_err("Failed to start hardware: %d (retry %d)\n", + ret, + ar->boot_attempts); + ar->boot_attempts--; + ret = ath6kl_init_hw_start(ar); } + if (ret) + /* Did not boot after several attempts */ + goto err_rxbuf_cleanup; + #ifdef CONFIG_ATH6KL_NI_BIOS_DOMAIN /* set region from DMI if it is US */ if (region[0] == 'U' && region[1] == 'S') { diff --git a/drivers/net/wireless/ath/ath6kl/core.h b/drivers/net/wireless/ath/ath6kl/core.h index 96c8ab6f096f7..2c9c0cac314eb 100644 --- a/drivers/net/wireless/ath/ath6kl/core.h +++ b/drivers/net/wireless/ath/ath6kl/core.h @@ -874,6 +874,9 @@ struct ath6kl { u8 disc_timeout; } debug; #endif /* CONFIG_ATH6KL_DEBUG */ + + /* Number of times we have attempted to boot the radio */ + unsigned int boot_attempts; }; static inline struct ath6kl *ath6kl_priv(struct net_device *dev) diff --git a/drivers/net/wireless/ath/ath6kl/init.c b/drivers/net/wireless/ath/ath6kl/init.c index 0e84c39ed0c6e..807889e18e904 100644 --- a/drivers/net/wireless/ath/ath6kl/init.c +++ b/drivers/net/wireless/ath/ath6kl/init.c @@ -1775,6 +1775,8 @@ static int __ath6kl_init_hw_start(struct ath6kl *ar) WMI_TIMEOUT); if (timeleft <= 0) { clear_bit(WMI_READY, &ar->flag); + ath6kl_init_hw_reset(ar); + ath6kl_bmi_reset(ar); ath6kl_err("wmi is not ready or wait was interrupted: %ld\n", timeleft); ret = -EIO; From 385cedeb7ef571f6df6cc241d726ecb3e12d9442 Mon Sep 17 00:00:00 2001 From: James Minor Date: Mon, 25 Apr 2016 12:18:10 -0500 Subject: [PATCH 075/110] ath6kl: Retry SDIO function initialization on failure Sometimes the AR6234 gives us a error "ath6kl: Unable to enable sdio func: -62". This indicates that the enable bit for the function did not result in the function's status bit in the SDIO_CCCR_IORx register getting set within a reasonable period of time (like 400ms). The guess at this point is that the radio is coming up in some strange state and the power-on reset did not clean things up as it should have. This occurs about once every thousand or so reboots. Experimentation has shown that resetting the device after this has happened allows the function enable to correctly set the function's bit in the SDIO_CCCR_IORx. This change will reset the AR6234 and try the function enable again if the module parameter boot_attempts is set to >0. This has been tested over several thousand reboots, and the driver will recover correctly when it would have otherwise failed to initialize. Signed-off-by: James Minor Signed-off-by: Brad Mouring Acked-by: Nathan Sullivan Acked-by: Xander Huff Natinst-ReviewBoard-ID: 135864 Natinst-CAR-ID: 579000 --- drivers/net/wireless/ath/ath6kl/core.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/drivers/net/wireless/ath/ath6kl/core.c b/drivers/net/wireless/ath/ath6kl/core.c index 633e0d4367f9c..74feba39e99bf 100644 --- a/drivers/net/wireless/ath/ath6kl/core.c +++ b/drivers/net/wireless/ath/ath6kl/core.c @@ -142,6 +142,15 @@ int ath6kl_core_init(struct ath6kl *ar, enum ath6kl_htc_type htc_type) * seconds. */ ret = ath6kl_hif_power_on(ar); + while (ret && ar->boot_attempts) { + ath6kl_err("Failed to turn on hardware: %d (retry %d)\n", + ret, + ar->boot_attempts); + ar->boot_attempts--; + ret = ath6kl_hif_power_off(ar); + ret = ath6kl_hif_power_on(ar); + } + if (ret) goto err_bmi_cleanup; From 2c51930755aa16395b815f7b6b710c361635975f Mon Sep 17 00:00:00 2001 From: Wilson Lee Date: Mon, 5 Jun 2017 11:00:51 +0800 Subject: [PATCH 076/110] ni: wifi: ath6kl: Enable BIOS code to load "bdata.XX.bin" board file. Linux upstream had accepted the load of different board file using DTS method with board file name format of "bdata.XX.bin". Hence, we need to modify BIOS code to use same board file name format to match with the upstream code. Signed-off-by: Wilson Lee Signed-off-by: Brad Mouring Acked-by: Keng Soon Cheah Acked-by: Joseph Hershberger Acked-by: Chen Yee Chew Natinst-ReviewBoard-ID: 203623 Perforce-ReviewBoard-ID: 203621 --- drivers/net/wireless/ath/ath6kl/core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath/ath6kl/core.c b/drivers/net/wireless/ath/ath6kl/core.c index 74feba39e99bf..12a04ba939237 100644 --- a/drivers/net/wireless/ath/ath6kl/core.c +++ b/drivers/net/wireless/ath/ath6kl/core.c @@ -181,7 +181,7 @@ int ath6kl_core_init(struct ath6kl *ar, enum ath6kl_htc_type htc_type) */ region_board_file = devm_kzalloc(ar->dev, 64, GFP_KERNEL); - snprintf(region_board_file, 64, AR6004_HW_3_0_FW_DIR "/bdata%c%c.bin", + snprintf(region_board_file, 64, AR6004_HW_3_0_FW_DIR "/bdata.%c%c.bin", region[0], region[1]); ar->hw.fw_board = region_board_file; From 4f19c5f701060cf987c4d53f8162a56caebe33f9 Mon Sep 17 00:00:00 2001 From: James Minor Date: Tue, 27 Feb 2018 16:08:49 -0600 Subject: [PATCH 077/110] net: ath6kl: silex: Separate region and board file selection To support the single antenna board files for products with 1 antenna, separate out the selection of the region from the selection of the board file. On OF platforms, there will now be 2 device tree entries: atheros,region-code - The region code (like US) atheros,board-id - The board file code (like 00, 10, etc) In the process, do a small refactor of the CONFIG_ATH6KL_NI_BIOS_DOMAIN case to be more consistent with the device tree case. Signed-off-by: James Minor Signed-off-by: Brad Mouring Acked-by: Nathan Sullivan Acked-by: Kyle Roeschley Natinst-ReviewBoard-ID: 223288 Natinst-CAR-ID: 686866 --- drivers/net/wireless/ath/ath6kl/core.c | 61 ++--------------- drivers/net/wireless/ath/ath6kl/core.h | 4 ++ drivers/net/wireless/ath/ath6kl/init.c | 90 ++++++++++++++++++++++++++ 3 files changed, 98 insertions(+), 57 deletions(-) diff --git a/drivers/net/wireless/ath/ath6kl/core.c b/drivers/net/wireless/ath/ath6kl/core.c index 12a04ba939237..c53f268058742 100644 --- a/drivers/net/wireless/ath/ath6kl/core.c +++ b/drivers/net/wireless/ath/ath6kl/core.c @@ -21,8 +21,6 @@ #include #include #include -#include -#include #include "debug.h" #include "hif-ops.h" @@ -56,31 +54,6 @@ MODULE_PARM_DESC(heart_beat_poll, MODULE_PARM_DESC(boot_attempts, "Number of times to retry booting the firmware"); -#define WLAN_REGION_ID 161 -#ifdef CONFIG_ATH6KL_NI_BIOS_DOMAIN -struct region_table { - struct dmi_header header; - char padding[3]; - char alpha2[2]; -}; - -static char region[2]; -static void find_region_type(const struct dmi_header *dm, void *private_data) -{ - int *found = (int *)private_data; - - if (dm->type == WLAN_REGION_ID) { - struct region_table *table = - container_of(dm, struct region_table, header); - - ath6kl_dbg(ATH6KL_DBG_TRC, "Region code from BIOS: %c%c\n", - table->alpha2[0], table->alpha2[1]); - memcpy(region, table->alpha2, 2); - *found = 1; - } -} -#endif - void ath6kl_core_tx_complete(struct ath6kl *ar, struct sk_buff *skb) { ath6kl_htc_tx_complete(ar, skb); @@ -99,21 +72,6 @@ int ath6kl_core_init(struct ath6kl *ar, enum ath6kl_htc_type htc_type) struct wireless_dev *wdev; int ret = 0, i; -#ifdef CONFIG_ATH6KL_NI_BIOS_DOMAIN - char *region_board_file = NULL; - /* get region code from DMI */ - dmi_walk(find_region_type, &ret); - if (!ret) - return -ENODEV; - - if (!isascii(region[0]) || !isascii(region[1])) - return -EINVAL; - - ath6kl_info("Using region: %c%c\n", - region[0], - region[1]); -#endif - ar->boot_attempts = boot_attempts; switch (htc_type) { @@ -175,17 +133,6 @@ int ath6kl_core_init(struct ath6kl *ar, enum ath6kl_htc_type htc_type) ar->testmode = testmode; -#ifdef CONFIG_ATH6KL_NI_BIOS_DOMAIN - /* ath6kl_init_hw_params() will set the board file name, but we want - * to override it with a region specific board file here. - */ - region_board_file = devm_kzalloc(ar->dev, 64, GFP_KERNEL); - - snprintf(region_board_file, 64, AR6004_HW_3_0_FW_DIR "/bdata.%c%c.bin", - region[0], region[1]); - - ar->hw.fw_board = region_board_file; -#endif ret = ath6kl_init_fetch_firmwares(ar); if (ret) goto err_htc_cleanup; @@ -268,10 +215,10 @@ int ath6kl_core_init(struct ath6kl *ar, enum ath6kl_htc_type htc_type) /* Did not boot after several attempts */ goto err_rxbuf_cleanup; -#ifdef CONFIG_ATH6KL_NI_BIOS_DOMAIN - /* set region from DMI if it is US */ - if (region[0] == 'U' && region[1] == 'S') { - ret = ath6kl_wmi_set_regdomain_cmd(ar->wmi, region); +#ifdef CONFIG_ATH6KL_SILEX_FIRMWARE + /* set US region if this device is a US device (US or 1S) */ + if (ar->region[0] == 'U' && ar->region[1] == 'S') { + ret = ath6kl_wmi_set_regdomain_cmd(ar->wmi, ar->region); if (ret) goto err_rxbuf_cleanup; } diff --git a/drivers/net/wireless/ath/ath6kl/core.h b/drivers/net/wireless/ath/ath6kl/core.h index 2c9c0cac314eb..6fdbaf977154d 100644 --- a/drivers/net/wireless/ath/ath6kl/core.h +++ b/drivers/net/wireless/ath/ath6kl/core.h @@ -877,6 +877,10 @@ struct ath6kl { /* Number of times we have attempted to boot the radio */ unsigned int boot_attempts; + +#ifdef CONFIG_ATH6KL_SILEX_FIRMWARE + unsigned char region[2]; +#endif }; static inline struct ath6kl *ath6kl_priv(struct net_device *dev) diff --git a/drivers/net/wireless/ath/ath6kl/init.c b/drivers/net/wireless/ath/ath6kl/init.c index 807889e18e904..9cc2e3e1cd9f5 100644 --- a/drivers/net/wireless/ath/ath6kl/init.c +++ b/drivers/net/wireless/ath/ath6kl/init.c @@ -24,6 +24,8 @@ #include #include #include +#include +#include #include "core.h" #include "cfg80211.h" @@ -32,6 +34,8 @@ #include "hif-ops.h" #include "htc-ops.h" +#define WLAN_REGION_ID 161 + static const struct ath6kl_hw hw_list[] = { { .id = AR6003_HW_2_0_VERSION, @@ -706,6 +710,10 @@ static bool check_device_tree(struct ath6kl *ar) char board_filename[64]; const char *board_id; int ret; +#ifdef CONFIG_ATH6KL_SILEX_FIRMWARE + static const char *region_code_prop = "atheros,region-code"; + const char *region_code; +#endif for_each_compatible_node(node, NULL, "atheros,ath6kl") { board_id = of_get_property(node, board_id_prop, NULL); @@ -724,6 +732,16 @@ static bool check_device_tree(struct ath6kl *ar) board_filename, ret); continue; } +#ifdef CONFIG_ATH6KL_SILEX_FIRMWARE + region_code = of_get_property(node, region_code_prop, NULL); + if (region_code == NULL) { + ath6kl_warn("No \"%s\" property on %s node.\n", + region_code_prop, node->name); + continue; + } + /* Silex firmware needs a region command in some cases */ + memcpy(&ar->region, region_code, 2); +#endif of_node_put(node); return true; } @@ -736,6 +754,73 @@ static bool check_device_tree(struct ath6kl *ar) } #endif /* CONFIG_OF */ +#ifdef CONFIG_ATH6KL_NI_BIOS_DOMAIN +struct region_table { + struct dmi_header header; + char padding[3]; + char alpha2[2]; +}; + +static char region[2]; +static void find_region_type(const struct dmi_header *dm, void *private_data) +{ + int *found = (int *)private_data; + + if (dm->type == WLAN_REGION_ID) { + struct region_table *table = + container_of(dm, struct region_table, header); + + memcpy(region, table->alpha2, 2); + *found = 1; + } +} + +static bool check_ni_bios(struct ath6kl *ar) +{ + char *region_board_file = NULL; + int ret = 0; + + /* get region code from DMI */ + dmi_walk(find_region_type, &ret); + if (!ret) + return -ENODEV; + + if (!isascii(region[0]) || !isascii(region[1])) + return -EINVAL; + + ath6kl_info("Using BIOS region: %c%c\n", + region[0], + region[1]); + +#ifdef CONFIG_ATH6KL_SILEX_FIRMWARE + /* Silex firmware needs a region command in some cases */ + memcpy(&ar->region, region, 2); +#endif + + /* ath6kl_init_hw_params() will set the board file name, but we want + * to override it with a region specific board file here. + */ + region_board_file = devm_kzalloc(ar->dev, 64, GFP_KERNEL); + + snprintf(region_board_file, 64, AR6004_HW_3_0_FW_DIR "/bdata.%c%c.bin", + region[0], region[1]); + + ret = ath6kl_get_fw(ar, region_board_file, &ar->fw_board, + &ar->fw_board_len); + if (ret) { + ath6kl_err("Failed to get BIOS board file %s: %d\n", + region_board_file, ret); + return false; + } + return true; +} +#else +static bool check_ni_bios(struct ath6kl *ar) +{ + return false; +} +#endif /* CONFIG_ATH6KL_NI_BIOS_DOMAIN */ + static int ath6kl_fetch_board_file(struct ath6kl *ar) { const char *filename; @@ -761,6 +846,11 @@ static int ath6kl_fetch_board_file(struct ath6kl *ar) return 0; } + if (check_ni_bios(ar)) { + /* got board file from BIOS */ + return 0; + } + /* there was no proper board file, try to use default instead */ ath6kl_warn("Failed to get board file %s (%d), trying to find default board file.\n", filename, ret); From 23f5bb74065c4d22ad96026a2f0e16dd064a2f4a Mon Sep 17 00:00:00 2001 From: Chen Yee Chew Date: Thu, 28 May 2015 21:11:02 +0800 Subject: [PATCH 078/110] HACK sd: Prevent SD from doing high-speed timing This will prevent SD card from doing SD high-speed timing. It will not do SD high-speed timing for high-speed or standard-speed card. Signed-off-by: Chen Yee Chew Reviewed-by: Keng Soon Cheah Reviewed-by: Joe Hershberger Natinst-CAR-ID: 519438 Natinst-ReviewBoard-ID: 99036 [bstreiff: convert to device_property_present as per 8199d312dad7 ("mmc: sdhci-pltfm: Convert DT properties to generic device properties")] Signed-off-by: Brandon Streiff --- drivers/mmc/host/sdhci-pltfm.c | 3 +++ drivers/mmc/host/sdhci.c | 3 ++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/mmc/host/sdhci-pltfm.c b/drivers/mmc/host/sdhci-pltfm.c index 328b132bbe572..f0948c167c16e 100644 --- a/drivers/mmc/host/sdhci-pltfm.c +++ b/drivers/mmc/host/sdhci-pltfm.c @@ -97,6 +97,9 @@ void sdhci_get_property(struct platform_device *pdev) if (device_property_present(dev, "broken-cd")) host->quirks |= SDHCI_QUIRK_BROKEN_CARD_DETECTION; + if (device_property_present(dev, "force-sd-standard")) + host->quirks |= SDHCI_QUIRK_NO_HISPD_BIT; + if (device_property_present(dev, "no-1-8-v")) host->quirks2 |= SDHCI_QUIRK2_NO_1_8_V; diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c index 3561ae8a481a0..5aeed11e4b9ad 100644 --- a/drivers/mmc/host/sdhci.c +++ b/drivers/mmc/host/sdhci.c @@ -4374,7 +4374,8 @@ int sdhci_setup_host(struct sdhci_host *host) if (host->quirks2 & SDHCI_QUIRK2_HOST_NO_CMD23) mmc->caps &= ~MMC_CAP_CMD23; - if (host->caps & SDHCI_CAN_DO_HISPD) + if ((host->caps & SDHCI_CAN_DO_HISPD) && + !(host->quirks & SDHCI_QUIRK_NO_HISPD_BIT)) mmc->caps |= MMC_CAP_SD_HIGHSPEED | MMC_CAP_MMC_HIGHSPEED; if ((host->quirks & SDHCI_QUIRK_BROKEN_CARD_DETECTION) && From e9b7ac51432f902516d67aa1beb82196dec2e77e Mon Sep 17 00:00:00 2001 From: Kyle Roeschley Date: Thu, 31 Aug 2017 19:58:11 -0500 Subject: [PATCH 079/110] mmc: core: Wait for Vdd to settle on card power off The SD spec version 6.0 section 6.4.1.5 requires that Vdd must be lowered to less than 0.5V for a minimum of 1 ms when powering off a card. Increase our wait to 15 ms so that voltage has time to drain down to 0.5V. Signed-off-by: Kyle Roeschley Signed-off-by: Brad Mouring Acked-by: James Minor Acked-by: Brandon Streiff Natinst-ReviewBoard-ID: 203804 --- drivers/mmc/host/sdhci.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c index 5aeed11e4b9ad..52d450ad0f4a3 100644 --- a/drivers/mmc/host/sdhci.c +++ b/drivers/mmc/host/sdhci.c @@ -2286,6 +2286,9 @@ void sdhci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) else sdhci_set_power(host, ios->power_mode, ios->vdd); + if (ios->power_mode == MMC_POWER_OFF) + mdelay(15); + if (host->ops->platform_send_init_74_clocks) host->ops->platform_send_init_74_clocks(host, ios->power_mode); From e387f2ec94110d381d7ed732db6481fd40907e91 Mon Sep 17 00:00:00 2001 From: Kyle Roeschley Date: Tue, 24 Apr 2018 08:27:03 -0500 Subject: [PATCH 080/110] mmc: sdhci: Disable SD card clock before changing parameters MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Per the SD Host Controller Simplified Specification v4.20 §3.2.3, change the SD card clock parameters only after first disabling the external card clock. Doing this fixes a spurious clock pulse on Baytrail and Apollo Lake SD controllers which otherwise breaks voltage switching with a specific Swissbit SD card. Signed-off-by: Kyle Roeschley Signed-off-by: Brad Mouring Acked-by: Tony Liechty Acked-by: Nathan Sullivan Natinst-ReviewBoard-ID: 236135 Natinst-CAR-ID: 694815 --- drivers/mmc/host/sdhci.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c index 52d450ad0f4a3..969438ec08fe8 100644 --- a/drivers/mmc/host/sdhci.c +++ b/drivers/mmc/host/sdhci.c @@ -1992,10 +1992,15 @@ void sdhci_set_clock(struct sdhci_host *host, unsigned int clock) host->mmc->actual_clock = 0; - sdhci_writew(host, 0, SDHCI_CLOCK_CONTROL); + clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL); + if (clk & SDHCI_CLOCK_CARD_EN) + sdhci_writew(host, clk & ~SDHCI_CLOCK_CARD_EN, + SDHCI_CLOCK_CONTROL); - if (clock == 0) + if (clock == 0) { + sdhci_writew(host, 0, SDHCI_CLOCK_CONTROL); return; + } clk = sdhci_calc_clk(host, clock, &host->mmc->actual_clock); sdhci_enable_clk(host, clk); From 0297a2224224e04f87868b6aba7012dfd4a90b4e Mon Sep 17 00:00:00 2001 From: Kyle Roeschley Date: Mon, 14 May 2018 13:58:17 -0500 Subject: [PATCH 081/110] mmc: sdhci: Add quirk for delay between clock disable and param change Some SD controllers require a delay between clearing SDHCI_CLOCK_CARD_EN and changing the SD clock dividers in order to avoid a runt clock pulse which can otherwise cause problems with some SD cards. Signed-off-by: Kyle Roeschley Signed-off-by: Brad Mouring Acked-by: Tony Liechty Acked-by: Nathan Sullivan Natinst-ReviewBoard-ID: 236135 [bstreiff: minor fix to renumber flag bit] Signed-off-by: Brandon Streiff --- drivers/mmc/host/sdhci.c | 6 ++++++ drivers/mmc/host/sdhci.h | 2 ++ 2 files changed, 8 insertions(+) diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c index 969438ec08fe8..c3d5bbaab5914 100644 --- a/drivers/mmc/host/sdhci.c +++ b/drivers/mmc/host/sdhci.c @@ -1997,6 +1997,12 @@ void sdhci_set_clock(struct sdhci_host *host, unsigned int clock) sdhci_writew(host, clk & ~SDHCI_CLOCK_CARD_EN, SDHCI_CLOCK_CONTROL); + if (host->quirks2 & SDHCI_QUIRK2_NEED_DELAY_AFTER_CLK_DISABLE) { + spin_unlock_irq(&host->lock); + usleep_range(900, 1100); + spin_lock_irq(&host->lock); + } + if (clock == 0) { sdhci_writew(host, 0, SDHCI_CLOCK_CONTROL); return; diff --git a/drivers/mmc/host/sdhci.h b/drivers/mmc/host/sdhci.h index 0770c036e2ff5..84bff7ba79512 100644 --- a/drivers/mmc/host/sdhci.h +++ b/drivers/mmc/host/sdhci.h @@ -473,6 +473,8 @@ struct sdhci_host { * block count. */ #define SDHCI_QUIRK2_USE_32BIT_BLK_CNT (1<<18) +/* Controller requires delay between card clock disable and param change */ +#define SDHCI_QUIRK2_NEED_DELAY_AFTER_CLK_DISABLE (1<<19) int irq; /* Device IRQ */ void __iomem *ioaddr; /* Mapped address */ From d750d6c5810c14a9fb7711132080faf8aae634dd Mon Sep 17 00:00:00 2001 From: Kyle Roeschley Date: Wed, 16 May 2018 16:45:01 -0500 Subject: [PATCH 082/110] mmc: sdhci: Add quirk work around double rescan On some SD host controllers, we can see two SD card insert interrupts when inserting a card. This causes mmc_rescan() to be called twice in quick succession and generate one or two SD card clock pulses, which can cause some SD cards to become unresponsive. Signed-off-by: Kyle Roeschley Signed-off-by: Brad Mouring Acked-by: Tony Liechty Acked-by: Nathan Sullivan Natinst-ReviewBoard-ID: 236135 [gratian: fix conflict with fec796739740 ("mmc: sdhci: Factor out sdhci_enable_clk")] Signed-off-by: Gratian Crisan [bstreiff: minor change to renumber flag bit] Signed-off-by: Brandon Streiff --- drivers/mmc/host/sdhci.c | 8 +++++++- drivers/mmc/host/sdhci.h | 2 ++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c index c3d5bbaab5914..f5c954b75e1b9 100644 --- a/drivers/mmc/host/sdhci.c +++ b/drivers/mmc/host/sdhci.c @@ -2005,11 +2005,17 @@ void sdhci_set_clock(struct sdhci_host *host, unsigned int clock) if (clock == 0) { sdhci_writew(host, 0, SDHCI_CLOCK_CONTROL); - return; + goto out_delay; } clk = sdhci_calc_clk(host, clock, &host->mmc->actual_clock); sdhci_enable_clk(host, clk); +out_delay: + if (host->quirks2 & SDHCI_QUIRK2_SPURIOUS_CARD_INSERT_INTERRUPT) { + spin_unlock_irq(&host->lock); + usleep_range(4900, 5100); + spin_lock_irq(&host->lock); + } } EXPORT_SYMBOL_GPL(sdhci_set_clock); diff --git a/drivers/mmc/host/sdhci.h b/drivers/mmc/host/sdhci.h index 84bff7ba79512..763b0341c279d 100644 --- a/drivers/mmc/host/sdhci.h +++ b/drivers/mmc/host/sdhci.h @@ -475,6 +475,8 @@ struct sdhci_host { #define SDHCI_QUIRK2_USE_32BIT_BLK_CNT (1<<18) /* Controller requires delay between card clock disable and param change */ #define SDHCI_QUIRK2_NEED_DELAY_AFTER_CLK_DISABLE (1<<19) +/* Controller may interrupt multiple times for card insert */ +#define SDHCI_QUIRK2_SPURIOUS_CARD_INSERT_INTERRUPT (1<<20) int irq; /* Device IRQ */ void __iomem *ioaddr; /* Mapped address */ From 52b3875fde27f1eca1634ed69e48e0ae4772840a Mon Sep 17 00:00:00 2001 From: Kyle Roeschley Date: Thu, 17 May 2018 11:25:47 -0500 Subject: [PATCH 083/110] mmc: sdhci-pci: Use two delay quirks for Baytrail SD With the Baytrail SD controllers on cRIO-905x, we can run into two conditions which cause functional problems with the NI-recommended microSD card. The first is a runt pulse after SD card clock disable, which is fixed by using SDHCI_QUIRK2_NEED_DELAY_AFTER_CLK_DISABLE to wait after disabling the clock. The second is receiving two SDHCI_INT_CARD_INSERT interrupts, which causes us to set up the card twice a make our recommended microSD card unresponsive. Work around this by using SDHCI_QUIRK2_SPURIOUS_CARD_INSERT_INTERRUPT. Signed-off-by: Kyle Roeschley Signed-off-by: Brad Mouring Acked-by: Tony Liechty Acked-by: Nathan Sullivan Natinst-ReviewBoard-ID: 236135 Natinst-CAR-ID: 696865 Natinst-CAR-ID: 694815 --- drivers/mmc/host/sdhci-pci-core.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/mmc/host/sdhci-pci-core.c b/drivers/mmc/host/sdhci-pci-core.c index 23da7f7fe093a..16732e1d0b3a8 100644 --- a/drivers/mmc/host/sdhci-pci-core.c +++ b/drivers/mmc/host/sdhci-pci-core.c @@ -1143,6 +1143,10 @@ static int byt_sd_probe_slot(struct sdhci_pci_slot *slot) slot->chip->pdev->subsystem_device == PCI_SUBDEVICE_ID_NI_78E3) slot->host->mmc->caps2 |= MMC_CAP2_AVOID_3_3V; + if (slot->chip->pdev->device == PCI_DEVICE_ID_INTEL_BYT_SD) + slot->host->quirks2 |= SDHCI_QUIRK2_NEED_DELAY_AFTER_CLK_DISABLE | + SDHCI_QUIRK2_SPURIOUS_CARD_INSERT_INTERRUPT; + return 0; } From 4b543ed45ae745975737e7dee3da3c0f572f5367 Mon Sep 17 00:00:00 2001 From: Kyle Roeschley Date: Tue, 15 May 2018 13:56:50 -0500 Subject: [PATCH 084/110] mmc: sdhci: Handle tuning error interrupts MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Per the §2.2.19 of the SD Host Controller Simplified Specification Version 4.20, the Tuning Error interrupt is set when an unrecoverable error is detected by the host controller in the tuning circuit when not executing the tuning procedure. Handle this interrupt by printing a useful error message and re-tuning (also per the spec). Signed-off-by: Kyle Roeschley Signed-off-by: Brad Mouring Acked-by: Tony Liechty Acked-by: Nathan Sullivan Natinst-ReviewBoard-ID: 236135 Natinst-CAR-ID: 696866 [gratian: adjust includes for 5857b29b96dc ("mmc: core: Move public functions from host.h to private headers")] Signed-off-by: Gratian Crisan --- drivers/mmc/host/sdhci.c | 24 ++++++++++++++++++++++-- drivers/mmc/host/sdhci.h | 1 + 2 files changed, 23 insertions(+), 2 deletions(-) diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c index f5c954b75e1b9..46be69656a786 100644 --- a/drivers/mmc/host/sdhci.c +++ b/drivers/mmc/host/sdhci.c @@ -33,6 +33,7 @@ #include #include +#include "../core/host.h" #include "sdhci.h" #define DRIVER_NAME "sdhci" @@ -265,7 +266,7 @@ static void sdhci_set_default_irqs(struct sdhci_host *host) if (host->tuning_mode == SDHCI_TUNING_MODE_2 || host->tuning_mode == SDHCI_TUNING_MODE_3) - host->ier |= SDHCI_INT_RETUNE; + host->ier |= SDHCI_INT_RETUNE | SDHCI_INT_TUNING_ERR; sdhci_writel(host, host->ier, SDHCI_INT_ENABLE); sdhci_writel(host, host->ier, SDHCI_SIGNAL_ENABLE); @@ -3503,6 +3504,24 @@ static irqreturn_t sdhci_irq(int irq, void *dev_id) if (intmask & SDHCI_INT_RETUNE) mmc_retune_needed(host->mmc); + if (intmask & SDHCI_INT_TUNING_ERR) { + u16 ctrl2 = sdhci_readw(host, SDHCI_HOST_CONTROL2); + /* + * Only complain and retune if we're actually using the + * host's tuning circuits. + */ + if (ctrl2 & SDHCI_CTRL_TUNED_CLK) { + sdhci_writew(host, + ctrl2 & ~SDHCI_CTRL_TUNED_CLK, + SDHCI_HOST_CONTROL2); + mmc_retune_recheck(host->mmc); + pr_err("%s: Unrecoverable error in tuning circuit\n", + mmc_hostname(host->mmc)); + } + sdhci_writel(host, SDHCI_INT_TUNING_ERR, + SDHCI_INT_STATUS); + } + if ((intmask & SDHCI_INT_CARD_INT) && (host->ier & SDHCI_INT_CARD_INT)) { sdhci_enable_sdio_irq_nolock(host, false); @@ -3512,7 +3531,8 @@ static irqreturn_t sdhci_irq(int irq, void *dev_id) intmask &= ~(SDHCI_INT_CARD_INSERT | SDHCI_INT_CARD_REMOVE | SDHCI_INT_CMD_MASK | SDHCI_INT_DATA_MASK | SDHCI_INT_ERROR | SDHCI_INT_BUS_POWER | - SDHCI_INT_RETUNE | SDHCI_INT_CARD_INT); + SDHCI_INT_RETUNE | SDHCI_INT_TUNING_ERR | + SDHCI_INT_CARD_INT); if (intmask) { unexpected |= intmask; diff --git a/drivers/mmc/host/sdhci.h b/drivers/mmc/host/sdhci.h index 763b0341c279d..6dc02bd68850b 100644 --- a/drivers/mmc/host/sdhci.h +++ b/drivers/mmc/host/sdhci.h @@ -151,6 +151,7 @@ #define SDHCI_INT_BUS_POWER 0x00800000 #define SDHCI_INT_AUTO_CMD_ERR 0x01000000 #define SDHCI_INT_ADMA_ERROR 0x02000000 +#define SDHCI_INT_TUNING_ERR 0x04000000 #define SDHCI_INT_NORMAL_MASK 0x00007FFF #define SDHCI_INT_ERROR_MASK 0xFFFF8000 From 9b6ed9e00ac119032fc35badb1fc153d314e4f71 Mon Sep 17 00:00:00 2001 From: Kyle Roeschley Date: Tue, 15 May 2018 15:59:28 -0500 Subject: [PATCH 085/110] Revert "mmc: core: enable CMD19 tuning for DDR50 mode" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit 4324f6de6d2eb9b232410eb0d67bfafdde8ba711. The SD Physical Layer Simplified Specification Version 6.00 §4.2.4.5 says that tuning is only supported for SDR50 and SDR104 modes, not DDR50 mode. As a result, tuning always fails for DDR50 cards. Remove "support" for this in the kernel, as it only adds unnecessary error prints. This was tested with a variety of industrial and consumer microSD cards from Swissbit, Unirex, Patriot, SanDisk, and Link Depot. None of the cards were able to execute tuning in DDR50 mode. Signed-off-by: Kyle Roeschley Signed-off-by: Brad Mouring Acked-by: Tony Liechty Acked-by: Nathan Sullivan Natinst-ReviewBoard-ID: 236135 --- drivers/mmc/core/sd.c | 20 ++------------------ 1 file changed, 2 insertions(+), 18 deletions(-) diff --git a/drivers/mmc/core/sd.c b/drivers/mmc/core/sd.c index 6f054c449d467..7ceeab6a990a1 100644 --- a/drivers/mmc/core/sd.c +++ b/drivers/mmc/core/sd.c @@ -640,25 +640,9 @@ static int mmc_sd_init_uhs_card(struct mmc_card *card) * SDR104 mode SD-cards. Note that tuning is mandatory for SDR104. */ if (!mmc_host_is_spi(card->host) && - (card->host->ios.timing == MMC_TIMING_UHS_SDR50 || - card->host->ios.timing == MMC_TIMING_UHS_DDR50 || - card->host->ios.timing == MMC_TIMING_UHS_SDR104)) { + (card->sd_bus_speed == UHS_SDR50_BUS_SPEED || + card->sd_bus_speed == UHS_SDR104_BUS_SPEED)) err = mmc_execute_tuning(card); - - /* - * As SD Specifications Part1 Physical Layer Specification - * Version 3.01 says, CMD19 tuning is available for unlocked - * cards in transfer state of 1.8V signaling mode. The small - * difference between v3.00 and 3.01 spec means that CMD19 - * tuning is also available for DDR50 mode. - */ - if (err && card->host->ios.timing == MMC_TIMING_UHS_DDR50) { - pr_warn("%s: ddr50 tuning failed\n", - mmc_hostname(card->host)); - err = 0; - } - } - out: kfree(status); From 6e1b77aac3de735de77233fcafe8775d81faa008 Mon Sep 17 00:00:00 2001 From: Chris Graf Date: Tue, 29 Aug 2017 15:41:27 -0500 Subject: [PATCH 086/110] nati_x86_64_defconfig: Enable UIO generic PCI driver We will use UIO to read the contents of certain flash devices that hang off of PCI. This flash content will be cryptographically measured as part of the verified boot flow. Signed-off-by: Chris Graf Signed-off-by: Brad Mouring Acked-by: Gratian Crisan Acked-by: Haris Okanovic Natinst-ReviewBoard-ID: 199649 --- arch/x86/configs/nati_x86_64_defconfig | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/x86/configs/nati_x86_64_defconfig b/arch/x86/configs/nati_x86_64_defconfig index e26b35aae93cf..1df392217a832 100644 --- a/arch/x86/configs/nati_x86_64_defconfig +++ b/arch/x86/configs/nati_x86_64_defconfig @@ -443,6 +443,8 @@ CONFIG_LEDS_CLASS=y CONFIG_LEDS_NIC78BX=m CONFIG_RTC_CLASS=y CONFIG_DMADEVICES=y +CONFIG_UIO=m +CONFIG_UIO_PCI_GENERIC=m CONFIG_VIRTIO_PCI=m CONFIG_VIRTIO_BALLOON=m CONFIG_VIRTIO_MMIO=m From 32b139da8d06db16a742e4c56eabe5085a51dfe9 Mon Sep 17 00:00:00 2001 From: Haris Okanovic Date: Tue, 1 May 2018 10:56:45 -0500 Subject: [PATCH 087/110] nati_x86_64_defconfig: Set CONFIG_MAGIC_SYSRQ_DEFAULT_ENABLE=0x0 Disable sysrq by default. It may be enabled via sysctl.conf later in boot. Signed-off-by: Haris Okanovic Natinst-CAR-ID: 696003 Natinst-ReviewBoard-ID: 233569 [bstreiff: drop zynq, leave x86_64] Signed-off-by: Brandon Streiff --- arch/x86/configs/nati_x86_64_defconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/x86/configs/nati_x86_64_defconfig b/arch/x86/configs/nati_x86_64_defconfig index 1df392217a832..512154f212e15 100644 --- a/arch/x86/configs/nati_x86_64_defconfig +++ b/arch/x86/configs/nati_x86_64_defconfig @@ -492,6 +492,7 @@ CONFIG_FRAME_WARN=1024 # CONFIG_UNUSED_SYMBOLS is not set # CONFIG_FRAME_POINTER is not set CONFIG_MAGIC_SYSRQ=y +CONFIG_MAGIC_SYSRQ_DEFAULT_ENABLE=0x0 CONFIG_PANIC_ON_OOPS=y CONFIG_PANIC_TIMEOUT=30 # CONFIG_SCHED_DEBUG is not set From b8778062ae53171c7ff01366358ba05059550839 Mon Sep 17 00:00:00 2001 From: Ovidiu-Adrian Vancea Date: Tue, 19 Sep 2017 14:41:30 +0300 Subject: [PATCH 088/110] nati_x86_64_defconfig: add NVMe drive support Add x86_64 kernel support for solid state drives directly connected to the PCI or PCI Express bus. Signed-off-by: Ovidiu-Adrian Vancea Signed-off-by: Brad Mouring Acked-by: Gratian Crisan Acked-by: Haris Okanovic Natinst-ReviewBoard-ID: 200080 --- arch/x86/configs/nati_x86_64_defconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/x86/configs/nati_x86_64_defconfig b/arch/x86/configs/nati_x86_64_defconfig index 512154f212e15..bb645f9a61088 100644 --- a/arch/x86/configs/nati_x86_64_defconfig +++ b/arch/x86/configs/nati_x86_64_defconfig @@ -233,6 +233,7 @@ CONFIG_CONNECTOR=y CONFIG_BLK_DEV_LOOP=y CONFIG_BLK_DEV_RAM=y CONFIG_VIRTIO_BLK=m +CONFIG_BLK_DEV_NVME=y CONFIG_NI_RT_FEATURES=y CONFIG_NI_LED_PREFIX="nilrt" CONFIG_NI_WATCHDOG=y From 0c0a194cda937a231bfb118355ff8962149d61f0 Mon Sep 17 00:00:00 2001 From: Brad Mouring Date: Wed, 1 Mar 2017 13:43:12 -0600 Subject: [PATCH 089/110] Revert "time: Always make sure wall_to_monotonic isn't positive" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit e1d7ba8735551ed79c7a0463a042353574b96da3. NI has a use case that involves distributed networked Linux devices that need to share the same concept of time using a mechanism like IEEE-1588 or 802.1AS. The “master” device (ie. the device with the time all other devices will be synchronized to) is often a device that boots up set to the Posix Epoch, mainly because it lacks a battery-backed RTC. (note: the existence of an RTC does not prevent a device from booting up at or very near the Posix Epoch, it just greatly reduces the likelihood). If a slave device attempted to synchronize its CLOCK_REALTIME to that of the master – and the master’s time was < Epoch+slave uptime, that slave would not be able to synchronize. This use case is believed to be very common among embedded devices, especially those without RTCs. Long term: We (NI Timing & Sync) are planning on engaging with the upstream community to educate them on our use case and hopefully put a different solution in place which solves the original problem (preventing a negative boot time representation) while also allowing our use case to continue working as it did prior to the change we’re reverting. Once that happens, we can drop this revert. Signed-off-by: Brad Mouring Reported-by: Vineeth Acharya Tested-by: Rick Ratzel Natinst-CAR-ID: 629499 [bstreiff: reduced control flow in do_settimeofday64 due to unassigned 'ret'] Signed-off-by: Brandon Streiff --- kernel/time/timekeeping.c | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) diff --git a/kernel/time/timekeeping.c b/kernel/time/timekeeping.c index 6858a31364b64..e737881439001 100644 --- a/kernel/time/timekeeping.c +++ b/kernel/time/timekeeping.c @@ -1299,7 +1299,6 @@ int do_settimeofday64(const struct timespec64 *ts) struct timekeeper *tk = &tk_core.timekeeper; struct timespec64 ts_delta, xt; unsigned long flags; - int ret = 0; if (!timespec64_valid_settod(ts)) return -EINVAL; @@ -1313,15 +1312,10 @@ int do_settimeofday64(const struct timespec64 *ts) ts_delta.tv_sec = ts->tv_sec - xt.tv_sec; ts_delta.tv_nsec = ts->tv_nsec - xt.tv_nsec; - if (timespec64_compare(&tk->wall_to_monotonic, &ts_delta) > 0) { - ret = -EINVAL; - goto out; - } - tk_set_wall_to_mono(tk, timespec64_sub(tk->wall_to_monotonic, ts_delta)); tk_set_xtime(tk, ts); -out: + timekeeping_update(tk, TK_CLEAR_NTP | TK_MIRROR | TK_CLOCK_WAS_SET); write_seqcount_end(&tk_core.seq); @@ -1330,10 +1324,9 @@ int do_settimeofday64(const struct timespec64 *ts) /* signal hrtimers about time change */ clock_was_set(); - if (!ret) - audit_tk_injoffset(ts_delta); + audit_tk_injoffset(ts_delta); - return ret; + return 0; } EXPORT_SYMBOL(do_settimeofday64); @@ -1360,8 +1353,7 @@ static int timekeeping_inject_offset(const struct timespec64 *ts) /* Make sure the proposed value is valid */ tmp = timespec64_add(tk_xtime(tk), *ts); - if (timespec64_compare(&tk->wall_to_monotonic, ts) > 0 || - !timespec64_valid_settod(&tmp)) { + if (!timespec64_valid_settod(&tmp)) { ret = -EINVAL; goto error; } From 44bbaa90a9887cebd51183215f7eb397e373cb4d Mon Sep 17 00:00:00 2001 From: Gratian Crisan Date: Wed, 15 Aug 2018 15:19:59 -0500 Subject: [PATCH 090/110] nati_x86_64_defconfig: update defconfig with savedefconfig In order to keep future defconfig modifications clean and independent, rebuild nati_zynq_defconfig and nati_x86_64_defconfig with savedefconfig. Signed-off-by: Gratian Crisan [bstreiff: drop zynq, leave x86_64] Signed-off-by: Brandon Streiff --- arch/x86/configs/nati_x86_64_defconfig | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/arch/x86/configs/nati_x86_64_defconfig b/arch/x86/configs/nati_x86_64_defconfig index bb645f9a61088..c3de7c15c87df 100644 --- a/arch/x86/configs/nati_x86_64_defconfig +++ b/arch/x86/configs/nati_x86_64_defconfig @@ -8,7 +8,6 @@ CONFIG_BSD_PROCESS_ACCT=y CONFIG_BSD_PROCESS_ACCT_V3=y # CONFIG_CONTEXT_TRACKING_FORCE is not set CONFIG_RCU_NOCB_CPU=y -CONFIG_RCU_NOCB_CPU_ALL=y CONFIG_IKCONFIG=y CONFIG_IKCONFIG_PROC=y CONFIG_LOG_BUF_SHIFT=18 @@ -16,7 +15,6 @@ CONFIG_CGROUPS=y CONFIG_CPUSETS=y # CONFIG_PROC_PID_CPUSET is not set CONFIG_CGROUP_CPUACCT=y -CONFIG_RELAY=y CONFIG_BLK_DEV_INITRD=y CONFIG_SYSCTL_SYSCALL=y CONFIG_KALLSYMS_ALL=y @@ -41,7 +39,6 @@ CONFIG_NR_CPUS=16 # CONFIG_SCHED_MC is not set CONFIG_PREEMPT_RT_FULL=y CONFIG_X86_REROUTE_FOR_BROKEN_BOOT_IRQS=y -# CONFIG_X86_MCE_AMD is not set CONFIG_X86_MSR=m CONFIG_X86_CPUID=m CONFIG_NUMA=y @@ -110,13 +107,9 @@ CONFIG_INET6_AH=m CONFIG_INET6_ESP=m CONFIG_INET6_IPCOMP=m CONFIG_NETFILTER=y -CONFIG_NETFILTER_DEBUG=y CONFIG_NF_CONNTRACK=m CONFIG_NF_CONNTRACK_EVENTS=y CONFIG_NF_CONNTRACK_TIMESTAMP=y -CONFIG_NF_CT_PROTO_DCCP=m -CONFIG_NF_CT_PROTO_SCTP=m -CONFIG_NF_CT_PROTO_UDPLITE=m CONFIG_NF_CONNTRACK_AMANDA=m CONFIG_NF_CONNTRACK_FTP=m CONFIG_NF_CONNTRACK_H323=m @@ -358,7 +351,6 @@ CONFIG_TABLET_SERIAL_WACOM4=m CONFIG_INPUT_TOUCHSCREEN=y CONFIG_TOUCHSCREEN_USB_COMPOSITE=m CONFIG_SERIO=m -# CONFIG_DEVKMEM is not set CONFIG_SERIAL_8250=y CONFIG_SERIAL_8250_CONSOLE=y CONFIG_SERIAL_8250_NR_UARTS=32 @@ -400,7 +392,6 @@ CONFIG_AGP=m CONFIG_DRM=m CONFIG_DRM_RADEON=m CONFIG_DRM_I915=m -CONFIG_DRM_I915_PRELIMINARY_HW_SUPPORT=y CONFIG_FB=y CONFIG_FB_MODE_HELPERS=y CONFIG_FB_EFI=y @@ -491,7 +482,6 @@ CONFIG_PRINTK_TIME=y # CONFIG_ENABLE_MUST_CHECK is not set CONFIG_FRAME_WARN=1024 # CONFIG_UNUSED_SYMBOLS is not set -# CONFIG_FRAME_POINTER is not set CONFIG_MAGIC_SYSRQ=y CONFIG_MAGIC_SYSRQ_DEFAULT_ENABLE=0x0 CONFIG_PANIC_ON_OOPS=y @@ -506,7 +496,6 @@ CONFIG_TRACER_SNAPSHOT_PER_CPU_SWAP=y CONFIG_FUNCTION_PROFILER=y # CONFIG_X86_VERBOSE_BOOTUP is not set # CONFIG_EARLY_PRINTK is not set -# CONFIG_DEBUG_RODATA_TEST is not set CONFIG_IO_DELAY_0XED=y CONFIG_OPTIMIZE_INLINING=y CONFIG_SECURITY=y @@ -517,7 +506,6 @@ CONFIG_SECURITY_SELINUX_BOOTPARAM_VALUE=0 CONFIG_DEFAULT_SECURITY_DAC=y CONFIG_CRYPTO_CRYPTD=y CONFIG_CRYPTO_CBC=y -CONFIG_CRYPTO_ECB=y CONFIG_CRYPTO_LRW=y CONFIG_CRYPTO_XTS=y CONFIG_CRYPTO_HMAC=y From 5cf5271010591055ac69b0298d4187d9b6fcce82 Mon Sep 17 00:00:00 2001 From: Gratian Crisan Date: Mon, 10 Sep 2018 15:30:00 -0500 Subject: [PATCH 091/110] nati_x86_64_defconfig: Use the "guess" stack unwinder by default The new default ORC stack unwinder causes problems with older toolchains. Switch the default stack unwinder to the "guess" unwinder for the release kernel. This matches the configuration used in previous versions and introduces not performance penalties. Signed-off-by: Gratian Crisan --- arch/x86/configs/nati_x86_64_defconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/x86/configs/nati_x86_64_defconfig b/arch/x86/configs/nati_x86_64_defconfig index c3de7c15c87df..2de45bbc22732 100644 --- a/arch/x86/configs/nati_x86_64_defconfig +++ b/arch/x86/configs/nati_x86_64_defconfig @@ -498,6 +498,7 @@ CONFIG_FUNCTION_PROFILER=y # CONFIG_EARLY_PRINTK is not set CONFIG_IO_DELAY_0XED=y CONFIG_OPTIMIZE_INLINING=y +CONFIG_UNWINDER_GUESS=y CONFIG_SECURITY=y CONFIG_SECURITY_NETWORK=y CONFIG_SECURITY_SELINUX=y From 27a72da63e33b5b32a4c2852123ada04496b0778 Mon Sep 17 00:00:00 2001 From: Gratian Crisan Date: Mon, 17 Sep 2018 15:30:17 -0500 Subject: [PATCH 092/110] nati_x86_64_defconfig: Disable support for remote controllers Support for remote controllers is enabled by default in 4.14. These are (usually) IR based remote controls that are used in combination with TV video capture devices. They are not typically used by our customers and they were not enabled in previous releases. Disable support to reduce kernel memory/disk footprint. Signed-off-by: Gratian Crisan Acked-by: Julia Cartwright Natinst-ReviewBoard-ID: 253929 [bstreiff: drop zynq, leave x86_64] Signed-off-by: Brandon Streiff --- arch/x86/configs/nati_x86_64_defconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/x86/configs/nati_x86_64_defconfig b/arch/x86/configs/nati_x86_64_defconfig index 2de45bbc22732..990c8e61f2a07 100644 --- a/arch/x86/configs/nati_x86_64_defconfig +++ b/arch/x86/configs/nati_x86_64_defconfig @@ -383,6 +383,7 @@ CONFIG_WATCHDOG=y CONFIG_SOFT_WATCHDOG=m CONFIG_NIC7018_WDT=m CONFIG_LPC_ICH=m +# CONFIG_RC_CORE is not set CONFIG_MEDIA_SUPPORT=m CONFIG_MEDIA_CAMERA_SUPPORT=y CONFIG_MEDIA_USB_SUPPORT=y From 72198348efc507874dbfecf3bc75e762fb041aa2 Mon Sep 17 00:00:00 2001 From: Gratian Crisan Date: Mon, 17 Sep 2018 15:51:15 -0500 Subject: [PATCH 093/110] nati_x86_64_defconfig: Add mousedev module Before the 4.14 upgrade we were compiling in the mousedev support. After the upgrade it is not selected by default presumably because it is superseded by the input event interface. Re-add the mousedev interface driver as a module. It provides mouse access via /dev/input/mouseX and /dev/input/mice. The majority of newer devices work well with the generic input device event interface but there is still a fair amount of legacy hardware out there that might require this module. Signed-off-by: Gratian Crisan Acked-by: Julia Cartwright Natinst-ReviewBoard-ID: 253941 --- arch/x86/configs/nati_x86_64_defconfig | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/x86/configs/nati_x86_64_defconfig b/arch/x86/configs/nati_x86_64_defconfig index 990c8e61f2a07..e0511876df6f4 100644 --- a/arch/x86/configs/nati_x86_64_defconfig +++ b/arch/x86/configs/nati_x86_64_defconfig @@ -343,6 +343,8 @@ CONFIG_RTL8187=m CONFIG_RTL8192CU=m CONFIG_USB_ZD1201=m CONFIG_ZD1211RW=m +CONFIG_INPUT_MOUSEDEV=m +CONFIG_INPUT_MOUSEDEV_PSAUX=y CONFIG_INPUT_EVDEV=y CONFIG_KEYBOARD_ATKBD=m CONFIG_MOUSE_PS2=m From 200a83f45244fdc23a7679bff2f50ddb0dca3154 Mon Sep 17 00:00:00 2001 From: Hui Chun Ong Date: Mon, 24 Sep 2018 14:56:20 +0800 Subject: [PATCH 094/110] nati_x86_64_defconfig: Add USB-C hotplug support Add hotplug support for USB devices connected to USB Type-C ports. Signed-off-by: Hui Chun Ong Acked-by: Kar Hin Ong Acked-by: Jonathan Hearn Acked-by: Gratian Crisan Natinst-ReviewBoard-ID: 254967 [gratian: re-generate with savedefconfig to keep future updates clean] Signed-off-by: Gratian Crisan --- arch/x86/configs/nati_x86_64_defconfig | 3 +++ 1 file changed, 3 insertions(+) diff --git a/arch/x86/configs/nati_x86_64_defconfig b/arch/x86/configs/nati_x86_64_defconfig index e0511876df6f4..01bd31d0cf2aa 100644 --- a/arch/x86/configs/nati_x86_64_defconfig +++ b/arch/x86/configs/nati_x86_64_defconfig @@ -67,11 +67,14 @@ CONFIG_X86_INTEL_PSTATE=y CONFIG_INTEL_IDLE=y CONFIG_PCI_MMCONFIG=y CONFIG_PCIEPORTBUS=y +CONFIG_HOTPLUG_PCI_PCIE=y # CONFIG_PCIEASPM is not set CONFIG_PCI_MSI=y CONFIG_PCI_IOV=y CONFIG_PCI_PRI=y CONFIG_PCI_PASID=y +CONFIG_HOTPLUG_PCI=y +CONFIG_HOTPLUG_PCI_ACPI=y # CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set CONFIG_IA32_EMULATION=y CONFIG_NET=y From f25c6c12e909082edf54939840741cd6e9163773 Mon Sep 17 00:00:00 2001 From: Kar Hin Ong Date: Sun, 4 Nov 2018 19:44:41 -0800 Subject: [PATCH 095/110] nati_x86_64_defconfig: Enable Thunderbolt hotplug support Enable Thunderbolt hotplug support for PXIe-8861. Signed-off-by: Kar Hin Ong Acked-by: Adrian Ratiu Acked-by: Hui Chun Ong Acked-by: Gratian Crisan Acked-by: Jonathan Hearn Natinst-ReviewBoard-ID: 261660 --- arch/x86/configs/nati_x86_64_defconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/x86/configs/nati_x86_64_defconfig b/arch/x86/configs/nati_x86_64_defconfig index 01bd31d0cf2aa..54a908ec5aa66 100644 --- a/arch/x86/configs/nati_x86_64_defconfig +++ b/arch/x86/configs/nati_x86_64_defconfig @@ -449,6 +449,7 @@ CONFIG_VIRTIO_MMIO=m CONFIG_INTEL_IOMMU=y # CONFIG_INTEL_IOMMU_DEFAULT_ON is not set CONFIG_IRQ_REMAP=y +CONFIG_THUNDERBOLT=m CONFIG_EDD=y CONFIG_EDD_OFF=y CONFIG_DMI_SYSFS=m From 4c062d265ea6988a5fcd9a54b30e994060c16dd0 Mon Sep 17 00:00:00 2001 From: Kyle Roeschley Date: Tue, 20 Nov 2018 07:38:02 -0600 Subject: [PATCH 096/110] mmc: sdhci: Do not disable interrupts in sdhci_set_clock Upstream removed spin lock usage in the set_ios path with commit d1e4f74f911d ("mmc: sdhci: Do not use spin lock in set_ios paths"), which means that our calls to spin_(un)lock_irq() in sdhci_set_clock() now cause an error on boot if a card is not present or a crash if one is present. Remove these calls so we don't do that and to match upstream's change. Fixes: 815777e0a1fb2 ("mmc: sdhci: Add quirk for delay between clock disable and param change") Fixes: 30d2f458ba48f ("mmc: sdhci: Add quirk work around double rescan") Signed-off-by: Kyle Roeschley Acked-by: Gratian Crisan Acked-by: Brandon Streiff Natinst-ReviewBoard-ID: 264712 Natinst-CAR-ID: 720310 --- drivers/mmc/host/sdhci.c | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c index 46be69656a786..8ea31b30cae38 100644 --- a/drivers/mmc/host/sdhci.c +++ b/drivers/mmc/host/sdhci.c @@ -1998,11 +1998,8 @@ void sdhci_set_clock(struct sdhci_host *host, unsigned int clock) sdhci_writew(host, clk & ~SDHCI_CLOCK_CARD_EN, SDHCI_CLOCK_CONTROL); - if (host->quirks2 & SDHCI_QUIRK2_NEED_DELAY_AFTER_CLK_DISABLE) { - spin_unlock_irq(&host->lock); - usleep_range(900, 1100); - spin_lock_irq(&host->lock); - } + if (host->quirks2 & SDHCI_QUIRK2_NEED_DELAY_AFTER_CLK_DISABLE) + mdelay(1); if (clock == 0) { sdhci_writew(host, 0, SDHCI_CLOCK_CONTROL); @@ -2012,11 +2009,8 @@ void sdhci_set_clock(struct sdhci_host *host, unsigned int clock) clk = sdhci_calc_clk(host, clock, &host->mmc->actual_clock); sdhci_enable_clk(host, clk); out_delay: - if (host->quirks2 & SDHCI_QUIRK2_SPURIOUS_CARD_INSERT_INTERRUPT) { - spin_unlock_irq(&host->lock); - usleep_range(4900, 5100); - spin_lock_irq(&host->lock); - } + if (host->quirks2 & SDHCI_QUIRK2_SPURIOUS_CARD_INSERT_INTERRUPT) + mdelay(5); } EXPORT_SYMBOL_GPL(sdhci_set_clock); From 47a4fb87a11cb03b2ea59f9f2cb4499998feb30a Mon Sep 17 00:00:00 2001 From: Haris Okanovic Date: Fri, 11 Jan 2019 15:06:18 -0600 Subject: [PATCH 097/110] drivers/firmware/efi/Kconfig: Add EFI_RUNTIME Add Kconfig option to enable EFI runtime services by default on !PREEMPT_RT_BASE kernels, unless otherwise configured. This change refactors Sebastian Siewior's commit 55544e1d (efi: Disable runtime services on RT) as a Kconfig token, so that default behavior may be toggled at build time. There's no behavioral change. Signed-off-by: Haris Okanovic Acked-by: Julia Cartwright Acked-by: Gratian Crisan [bstreiff: change from PREEMPT_RT_BASE to PREEMPT_RT as per upstream commit change 987d6084b96c ("efi: Disable runtime services on RT")] Signed-off-by: Brandon Streiff --- drivers/firmware/efi/Kconfig | 9 +++++++++ drivers/firmware/efi/efi.c | 2 +- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/drivers/firmware/efi/Kconfig b/drivers/firmware/efi/Kconfig index 36ec1f7188934..a01a64fae64ed 100644 --- a/drivers/firmware/efi/Kconfig +++ b/drivers/firmware/efi/Kconfig @@ -14,6 +14,15 @@ config EFI_VARS legacy users: new users should use the efivarfs filesystem instead. +config EFI_RUNTIME + bool "Enable EFI runtime services on boot by default" + depends on EFI + default y if !PREEMPT_RT + help + Set Y to enable EFI runtime services on boot by default. + This selection is overridden by "efi=runtime" and "efi=noruntime" + boot parameters. + config EFI_ESRT bool depends on EFI && !IA64 diff --git a/drivers/firmware/efi/efi.c b/drivers/firmware/efi/efi.c index 73973f90404c7..7042efec2dcd4 100644 --- a/drivers/firmware/efi/efi.c +++ b/drivers/firmware/efi/efi.c @@ -65,7 +65,7 @@ struct mm_struct efi_mm = { struct workqueue_struct *efi_rts_wq; -static bool disable_runtime = IS_ENABLED(CONFIG_PREEMPT_RT); +static bool disable_runtime = !IS_ENABLED(CONFIG_EFI_RUNTIME); static int __init setup_noefi(char *arg) { disable_runtime = true; From 924818eee58f0c8aee500555f27355a087f73d9d Mon Sep 17 00:00:00 2001 From: Haris Okanovic Date: Mon, 14 Jan 2019 10:30:21 -0600 Subject: [PATCH 098/110] nati_x86_64_defconfig: Enable EFI_RUNTIME NI Linux RT runmode and safemode need access to EFI variables during boot and poweroff/reboot. Signed-off-by: Haris Okanovic Acked-by: Julia Cartwright Acked-by: Gratian Crisan --- arch/x86/configs/nati_x86_64_defconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/x86/configs/nati_x86_64_defconfig b/arch/x86/configs/nati_x86_64_defconfig index 54a908ec5aa66..29e2877531818 100644 --- a/arch/x86/configs/nati_x86_64_defconfig +++ b/arch/x86/configs/nati_x86_64_defconfig @@ -455,6 +455,7 @@ CONFIG_EDD_OFF=y CONFIG_DMI_SYSFS=m CONFIG_ISCSI_IBFT_FIND=y CONFIG_EFI_VARS=y +CONFIG_EFI_RUNTIME=y CONFIG_EXT2_FS=y CONFIG_EXT2_FS_XATTR=y CONFIG_EXT2_FS_POSIX_ACL=y From fa149e8f6946e21f1bca6ff357c22ff960d2b1f3 Mon Sep 17 00:00:00 2001 From: Bill Pittman Date: Tue, 22 Jan 2019 11:38:42 -0600 Subject: [PATCH 099/110] nati_x86_64_defconfig: Add CONFIG_RANDOM_TRUST_CPU token Set CONFIG_RANDOM_TRUST_CPU token to yes to allow for more entropy at system boot time. Signed-off-by: Bill Pittman Acked-by: Gratian Crisan Acked-by: Julia Cartwright Natinst-CAR-ID: 721885 Review-Board-ID: 272797 --- arch/x86/configs/nati_x86_64_defconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/x86/configs/nati_x86_64_defconfig b/arch/x86/configs/nati_x86_64_defconfig index 29e2877531818..a51988d0d8c68 100644 --- a/arch/x86/configs/nati_x86_64_defconfig +++ b/arch/x86/configs/nati_x86_64_defconfig @@ -372,6 +372,7 @@ CONFIG_VIRTIO_CONSOLE=m CONFIG_HPET=y CONFIG_TCG_TPM=m CONFIG_TCG_TIS=m +CONFIG_RANDOM_TRUST_CPU=y CONFIG_I2C=y CONFIG_I2C_CHARDEV=m CONFIG_I2C_I801=m From 79c0a580ef8858d61d4bf968e2f62b4fb9c0d8ab Mon Sep 17 00:00:00 2001 From: Kyle Roeschley Date: Fri, 30 Nov 2018 14:34:02 -0600 Subject: [PATCH 100/110] nirtfeatures: Add Dogfish backplane ID and LED info This family uses the same monochrome LEDs as Swordfish. Signed-off-by: Kyle Roeschley Acked-by: Brandon Streiff Acked-by: Gratian Crisan Acked-by: Julia Cartwright Natinst-ReviewBoard-ID: 273119 --- drivers/misc/nirtfeatures.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/misc/nirtfeatures.c b/drivers/misc/nirtfeatures.c index 6677318325c0a..08726721a534e 100644 --- a/drivers/misc/nirtfeatures.c +++ b/drivers/misc/nirtfeatures.c @@ -49,6 +49,7 @@ #define NIRTF_PLATFORM_MISC_ID_MANHATTAN 0 #define NIRTF_PLATFORM_MISC_ID_SWORDFISH 1 #define NIRTF_PLATFORM_MISC_ID_FIRE_EAGLE 2 +#define NIRTF_PLATFORM_MISC_ID_DOGFISH 3 #define NIRTF_PLATFORM_MISC_ID_HAMMERHEAD 4 #define NIRTF_PLATFORM_MISC_ID_WINGHEAD 5 @@ -537,6 +538,12 @@ static struct nirtfeatures_desc nirtfeatures_descs[] = { .leds = nirtfeatures_leds_monochrome, .num_leds = ARRAY_SIZE(nirtfeatures_leds_monochrome), }, + { + .backplane_id = NIRTF_PLATFORM_MISC_ID_DOGFISH, + .name = "Dogfish", + .leds = nirtfeatures_leds_monochrome, + .num_leds = ARRAY_SIZE(nirtfeatures_leds_monochrome), + }, { .backplane_id = NIRTF_PLATFORM_MISC_ID_HAMMERHEAD, .name = "Hammerhead", From 5a17e781cc1ce09514638df0d9631064946cc802 Mon Sep 17 00:00:00 2001 From: Kyle Roeschley Date: Thu, 11 Apr 2019 13:30:59 -0500 Subject: [PATCH 101/110] serial: 8250_ni16550: Add support for NIC7A69 This device uses a 33.333MHz clock with a prescaler value of 1.125 to achieve baud rates within 1% error up to 921600 baud. We query ACPI standard _DSD properties to determine if each port is an RS-232 or RS-485 port. Signed-off-by: Kyle Roeschley Natinst-ReviewBoard-ID: 286745 --- drivers/acpi/acpi_pnp.c | 1 + drivers/tty/serial/8250/8250_pnp.c | 50 ++++++++++++++++++++++++------ 2 files changed, 42 insertions(+), 9 deletions(-) diff --git a/drivers/acpi/acpi_pnp.c b/drivers/acpi/acpi_pnp.c index 7fb47477acf70..04cdbbbc510a2 100644 --- a/drivers/acpi/acpi_pnp.c +++ b/drivers/acpi/acpi_pnp.c @@ -223,6 +223,7 @@ static const struct acpi_device_id acpi_pnp_device_ids[] = { {"NIC7750"}, /* National Instruments (NI) 16550 PNP */ {"NIC7772"}, /* National Instruments (NI) 16550 PNP */ {"NIC792B"}, /* National Instruments (NI) 16550 PNP */ + {"NIC7A69"}, /* National Instruments (NI) 16550 PNP */ {"PMC2430"}, /* Pace 56 Voice Internal Plug & Play Modem */ {"PNP0500"}, /* Generic standard PC COM port */ {"PNP0501"}, /* Generic 16550A-compatible COM port */ diff --git a/drivers/tty/serial/8250/8250_pnp.c b/drivers/tty/serial/8250/8250_pnp.c index f4eb3c2ac803e..b780dc7ff318f 100644 --- a/drivers/tty/serial/8250/8250_pnp.c +++ b/drivers/tty/serial/8250/8250_pnp.c @@ -21,6 +21,7 @@ #include "8250.h" #include +#include #define UNKNOWN_DEV 0x3000 #define CIR_PORT 0x0800 @@ -29,6 +30,7 @@ #define NI_CAP_PMR 0x0001 #define NI_CLK_33333333 0x0002 #define NI_CPR_CLK_25000000 0x0008 +#define NI_CPR_CLK_33333333 0x0010 static bool is_niport(struct pnp_dev *dev) { @@ -216,6 +218,7 @@ static const struct pnp_device_id pnp_dev_table[] = { { "NIC7750", NI_CLK_33333333 }, { "NIC7772", NI_CAP_PMR | NI_16BYTE_FIFO }, { "NIC792B", NI_CPR_CLK_25000000 }, + { "NIC7A69", NI_CPR_CLK_33333333 }, /* NEC 98NOTE SPEAKER PHONE FAX MODEM(33600bps) */ { "nEC8241", 0 }, /* Pace 56 Voice Internal Plug & Play Modem */ @@ -499,10 +502,15 @@ serial_pnp_probe(struct pnp_dev *dev, const struct pnp_device_id *dev_id) #ifdef CONFIG_SERIAL_8250_NI16550 if (is_niport(dev)) { - WARN_ON((flags & (NI_CLK_33333333 | NI_CPR_CLK_25000000)) == - (NI_CLK_33333333 | NI_CPR_CLK_25000000)); + bool rs232_property = false; + + WARN_ON(hweight32(flags & (NI_CPR_CLK_25000000 | + NI_CPR_CLK_33333333 | + NI_CLK_33333333)) > 1); + if (flags & NI_CLK_33333333) uart.port.uartclk = 33333333; + if (flags & NI_CPR_CLK_25000000) { /* Sets UART clock rate to 22.222 MHz * with prescaler 1.125. @@ -512,6 +520,27 @@ serial_pnp_probe(struct pnp_dev *dev, const struct pnp_device_id *dev_id) ni16550_config_prescaler(uart.port.iobase, 0x9); } + if (flags & NI_CPR_CLK_33333333) { + const char *transceiver; + + /* + * Set UART clock rate to 29.629 MHz + * with prescaler 1.125. + */ + uart.port.uartclk = 29629629; + uart.mcr_force = UART_MCR_CLKSEL; + ni16550_config_prescaler(uart.port.iobase, 0x9); + + if (device_property_read_string(&dev->dev, + "transceiver", + &transceiver)) { + dev_err(&dev->dev, "transceiver property missing\n"); + return -EINVAL; + } + + rs232_property = strncmp(transceiver, "RS-232", 6) == 0; + } + uart.port.flags |= UPF_FIXED_PORT | UPF_FIXED_TYPE; if (flags & NI_16BYTE_FIFO) @@ -520,18 +549,21 @@ serial_pnp_probe(struct pnp_dev *dev, const struct pnp_device_id *dev_id) uart.port.type = PORT_NI16550_F128; /* - * NI UARTs are by default connected to RS-485 transceivers, - * unless the PMR register is implemented, and the UART is - * dual-mode capable. Then it could be in RS-232 mode and if it - * is, we will register as a standard 8250 port. + * NI UARTs may be connected to RS-485 or RS-232 transceivers, + * depending on the ACPI 'transceiver' property and whether or + * not the PMR is implemented. If the PMR is implemented and + * the port is in RS-232 mode, register as a standard 8250 port + * and print about it. */ if ((flags & NI_CAP_PMR) && is_rs232_mode(uart.port.iobase)) pr_info("NI 16550 at I/O 0x%x (irq = %d) is dual-mode capable and is in RS-232 mode\n", (unsigned int)uart.port.iobase, uart.port.irq); - else - /* Either the PMR register is not implemented, or it is - * and the UART is in RS-485 mode as set in the PMR + else if (!rs232_property) + /* + * Either the PMR is implemented and set to RS-485 mode + * or it's not implemented and the 'transceiver' ACPI + * property is 'RS-485'; */ ni16550_port_setup(&uart.port); } From 25caaf971b15f7a04bec696c21c2bb36758cace7 Mon Sep 17 00:00:00 2001 From: Bill Pittman Date: Mon, 4 Mar 2019 11:18:13 -0600 Subject: [PATCH 102/110] nati_x86_64_defconfig: build squashfs & overlayfs into the kernel Switch squashfs from a module to a built in component of the kernel. Also add overlayfs support to the kernel. The new file layout requires squashfs and overlayfs so they should be built in. Signed-off-by: Bill Pittman Acked-by: Gratian Crisan Natinst-ReviewBoard-ID: 294993 --- arch/x86/configs/nati_x86_64_defconfig | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/arch/x86/configs/nati_x86_64_defconfig b/arch/x86/configs/nati_x86_64_defconfig index a51988d0d8c68..ffc79d1072a34 100644 --- a/arch/x86/configs/nati_x86_64_defconfig +++ b/arch/x86/configs/nati_x86_64_defconfig @@ -466,6 +466,7 @@ CONFIG_EXT3_FS_POSIX_ACL=y CONFIG_EXT3_FS_SECURITY=y # CONFIG_DNOTIFY is not set CONFIG_FUSE_FS=m +CONFIG_OVERLAY_FS=y CONFIG_ISO9660_FS=y CONFIG_MSDOS_FS=y CONFIG_VFAT_FS=y @@ -474,7 +475,7 @@ CONFIG_PROC_KCORE=y CONFIG_TMPFS_POSIX_ACL=y CONFIG_CONFIGFS_FS=y CONFIG_EFIVAR_FS=y -CONFIG_SQUASHFS=m +CONFIG_SQUASHFS=y CONFIG_SQUASHFS_XATTR=y CONFIG_NFS_FS=m CONFIG_NFS_V4=m From 6ed310f4031eecbe740c03940121de37427b0ec1 Mon Sep 17 00:00:00 2001 From: Haris Okanovic Date: Tue, 29 Oct 2019 12:19:24 -0500 Subject: [PATCH 103/110] nati_x86_64_defconfig: Remove CONFIG_ISCSI_IBFT_FIND, add CONFIG_RCU_EXPERT=y Cleanup NILRT defconfigs after v4.14.146-rt67 upgrade. ISCSI_IBFT_FIND is removed by additional dependency on ISCSI_IBFT in commit a3e7eb5906 (iscsi_ibft: make ISCSI_IBFT dependson ACPI instead of ISCSI_IBFT_FIND). CONFIG_RCU_EXPERT=y is required to set CONFIG_RCU_NOCB_CPU=y after commit 44c65ff2e3 (rcu: Eliminate NOCBs CPU-state Kconfig options). Signed-off-by: Haris Okanovic Natinst-AZDO-ID: 898934 Natinst-ReviewBoard-ID: 315411 [bstreiff: drop zynq, leave x86_64] Signed-off-by: Brandon Streiff --- arch/x86/configs/nati_x86_64_defconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/x86/configs/nati_x86_64_defconfig b/arch/x86/configs/nati_x86_64_defconfig index ffc79d1072a34..8d68e5990197b 100644 --- a/arch/x86/configs/nati_x86_64_defconfig +++ b/arch/x86/configs/nati_x86_64_defconfig @@ -6,6 +6,7 @@ CONFIG_HIGH_RES_TIMERS=y CONFIG_VIRT_CPU_ACCOUNTING_GEN=y CONFIG_BSD_PROCESS_ACCT=y CONFIG_BSD_PROCESS_ACCT_V3=y +CONFIG_RCU_EXPERT=y # CONFIG_CONTEXT_TRACKING_FORCE is not set CONFIG_RCU_NOCB_CPU=y CONFIG_IKCONFIG=y @@ -454,7 +455,6 @@ CONFIG_THUNDERBOLT=m CONFIG_EDD=y CONFIG_EDD_OFF=y CONFIG_DMI_SYSFS=m -CONFIG_ISCSI_IBFT_FIND=y CONFIG_EFI_VARS=y CONFIG_EFI_RUNTIME=y CONFIG_EXT2_FS=y From 040ba97ea95fb1788fd8c7f3132cee8299341dbf Mon Sep 17 00:00:00 2001 From: Bill Pittman Date: Mon, 18 Nov 2019 12:02:04 -0600 Subject: [PATCH 104/110] virtio: Enable remaining virtio drivers as modules The virtio drivers are not very large and with increasing use and support of qemu images, it's useful to have the modules available. Signed-off-by: Bill Pittman Acked-by: Gratian Crisan Natinst-ReviewBoard-ID: 317990 --- arch/x86/configs/nati_x86_64_defconfig | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/arch/x86/configs/nati_x86_64_defconfig b/arch/x86/configs/nati_x86_64_defconfig index 8d68e5990197b..fc7b4e6d5db1c 100644 --- a/arch/x86/configs/nati_x86_64_defconfig +++ b/arch/x86/configs/nati_x86_64_defconfig @@ -241,6 +241,7 @@ CONFIG_SCSI_AACRAID=m CONFIG_SCSI_MVSAS=m CONFIG_SCSI_ARCMSR=m CONFIG_SCSI_SYM53C8XX_2=m +CONFIG_SCSI_VIRTIO=m CONFIG_ATA=y CONFIG_SATA_AHCI=y CONFIG_ATA_PIIX=y @@ -370,6 +371,7 @@ CONFIG_SERIAL_8250_NI16550=y CONFIG_VIRTIO_CONSOLE=m # CONFIG_HW_RANDOM_AMD is not set # CONFIG_HW_RANDOM_VIA is not set +CONFIG_HW_RANDOM_VIRTIO=m CONFIG_HPET=y CONFIG_TCG_TPM=m CONFIG_TCG_TIS=m @@ -400,6 +402,7 @@ CONFIG_AGP=m CONFIG_DRM=m CONFIG_DRM_RADEON=m CONFIG_DRM_I915=m +CONFIG_DRM_VIRTIO_GPU=m CONFIG_FB=y CONFIG_FB_MODE_HELPERS=y CONFIG_FB_EFI=y @@ -447,6 +450,7 @@ CONFIG_UIO=m CONFIG_UIO_PCI_GENERIC=m CONFIG_VIRTIO_PCI=m CONFIG_VIRTIO_BALLOON=m +CONFIG_VIRTIO_INPUT=m CONFIG_VIRTIO_MMIO=m CONFIG_INTEL_IOMMU=y # CONFIG_INTEL_IOMMU_DEFAULT_ON is not set From 15e0117a3d900d0ec3f6d5959e5dbbf4582484a2 Mon Sep 17 00:00:00 2001 From: Gratian Crisan Date: Mon, 6 Apr 2020 11:52:17 -0500 Subject: [PATCH 105/110] nati_x86_64_defconfig: Enable bochs-drm driver module Configure the bochs-drm driver as a module. This provides support for 3D acceleration in qemu virtual machines (qemu stdvga). Signed-off-by: Gratian Crisan Acked-by: Alex Stewart Natinst-AZDO-ID: 987050 Natinst-ReviewBoard-ID: 332135 --- arch/x86/configs/nati_x86_64_defconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/x86/configs/nati_x86_64_defconfig b/arch/x86/configs/nati_x86_64_defconfig index fc7b4e6d5db1c..e8c0c843668f7 100644 --- a/arch/x86/configs/nati_x86_64_defconfig +++ b/arch/x86/configs/nati_x86_64_defconfig @@ -402,6 +402,7 @@ CONFIG_AGP=m CONFIG_DRM=m CONFIG_DRM_RADEON=m CONFIG_DRM_I915=m +CONFIG_DRM_BOCHS=m CONFIG_DRM_VIRTIO_GPU=m CONFIG_FB=y CONFIG_FB_MODE_HELPERS=y From e13a124fc14ca9753b735237c217ddcb5a899434 Mon Sep 17 00:00:00 2001 From: Gratian Crisan Date: Mon, 6 Apr 2020 11:54:44 -0500 Subject: [PATCH 106/110] nati_x86_64_defconfig: Enable vmwgfx driver module Configure the vmwgfx driver as a module. This provides support for 3D acceleration in VMware virtual machines. Signed-off-by: Gratian Crisan Acked-by: Alex Stewart Natinst-AZDO-ID: 987050 Natinst-ReviewBoard-ID: 332135 --- arch/x86/configs/nati_x86_64_defconfig | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/x86/configs/nati_x86_64_defconfig b/arch/x86/configs/nati_x86_64_defconfig index e8c0c843668f7..5fd43a9eb4424 100644 --- a/arch/x86/configs/nati_x86_64_defconfig +++ b/arch/x86/configs/nati_x86_64_defconfig @@ -402,6 +402,8 @@ CONFIG_AGP=m CONFIG_DRM=m CONFIG_DRM_RADEON=m CONFIG_DRM_I915=m +CONFIG_DRM_VMWGFX=m +CONFIG_DRM_VMWGFX_FBCON=y CONFIG_DRM_BOCHS=m CONFIG_DRM_VIRTIO_GPU=m CONFIG_FB=y From 3b2161c22f1dfc6563fd1f7c41f221f4ef105c36 Mon Sep 17 00:00:00 2001 From: Brandon Streiff Date: Wed, 10 Jun 2020 15:16:49 -0500 Subject: [PATCH 107/110] nati_x86_64_defconfig: update to 5.6.14-rt7 Update defconfig from 4.14 to 5.6.14-rt7. Signed-off-by: Brandon Streiff [gratian: re-enable full real-time preemption after config name change] Signed-off-by: Gratian Crisan --- arch/x86/configs/nati_x86_64_defconfig | 134 ++++++++++++------------- 1 file changed, 65 insertions(+), 69 deletions(-) diff --git a/arch/x86/configs/nati_x86_64_defconfig b/arch/x86/configs/nati_x86_64_defconfig index 5fd43a9eb4424..6c51db067aed3 100644 --- a/arch/x86/configs/nati_x86_64_defconfig +++ b/arch/x86/configs/nati_x86_64_defconfig @@ -1,13 +1,14 @@ CONFIG_SYSVIPC=y CONFIG_POSIX_MQUEUE=y CONFIG_AUDIT=y +# CONFIG_CONTEXT_TRACKING_FORCE is not set CONFIG_HIGH_RES_TIMERS=y # CONFIG_CLOCKSOURCE_WATCHDOG is not set +CONFIG_PREEMPT_RT=y CONFIG_VIRT_CPU_ACCOUNTING_GEN=y CONFIG_BSD_PROCESS_ACCT=y CONFIG_BSD_PROCESS_ACCT_V3=y CONFIG_RCU_EXPERT=y -# CONFIG_CONTEXT_TRACKING_FORCE is not set CONFIG_RCU_NOCB_CPU=y CONFIG_IKCONFIG=y CONFIG_IKCONFIG_PROC=y @@ -17,40 +18,31 @@ CONFIG_CPUSETS=y # CONFIG_PROC_PID_CPUSET is not set CONFIG_CGROUP_CPUACCT=y CONFIG_BLK_DEV_INITRD=y -CONFIG_SYSCTL_SYSCALL=y -CONFIG_KALLSYMS_ALL=y # CONFIG_PCSPKR_PLATFORM is not set +CONFIG_KALLSYMS_ALL=y CONFIG_EMBEDDED=y # CONFIG_SLUB_DEBUG is not set # CONFIG_COMPAT_BRK is not set -CONFIG_JUMP_LABEL=y -CONFIG_MODULES=y -CONFIG_MODULE_UNLOAD=y -CONFIG_MODVERSIONS=y -CONFIG_BLK_DEV_INTEGRITY=y CONFIG_SMP=y CONFIG_X86_X2APIC=y # CONFIG_X86_EXTENDED_PLATFORM is not set CONFIG_X86_INTEL_LPSS=y # CONFIG_SCHED_OMIT_FRAME_POINTER is not set CONFIG_PROCESSOR_SELECT=y -# CONFIG_CPU_SUP_AMD is not set # CONFIG_CPU_SUP_CENTAUR is not set CONFIG_NR_CPUS=16 # CONFIG_SCHED_MC is not set -CONFIG_PREEMPT_RT_FULL=y CONFIG_X86_REROUTE_FOR_BROKEN_BOOT_IRQS=y +CONFIG_MICROCODE_OLD_INTERFACE=y CONFIG_X86_MSR=m CONFIG_X86_CPUID=m +# CONFIG_X86_5LEVEL is not set CONFIG_NUMA=y # CONFIG_AMD_NUMA is not set -CONFIG_KSM=y -CONFIG_DEFAULT_MMAP_MIN_ADDR=65536 -CONFIG_MEMORY_FAILURE=y -CONFIG_CLEANCACHE=y CONFIG_MTRR_SANITIZER_ENABLE_DEFAULT=1 CONFIG_EFI=y CONFIG_HZ_100=y +CONFIG_LEGACY_VSYSCALL_EMULATE=y # CONFIG_MODIFY_LDT_SYSCALL is not set # CONFIG_SUSPEND is not set # CONFIG_ACPI_AC is not set @@ -66,18 +58,23 @@ CONFIG_SFI=y CONFIG_CPU_FREQ=y CONFIG_X86_INTEL_PSTATE=y CONFIG_INTEL_IDLE=y -CONFIG_PCI_MMCONFIG=y -CONFIG_PCIEPORTBUS=y -CONFIG_HOTPLUG_PCI_PCIE=y -# CONFIG_PCIEASPM is not set -CONFIG_PCI_MSI=y -CONFIG_PCI_IOV=y -CONFIG_PCI_PRI=y -CONFIG_PCI_PASID=y -CONFIG_HOTPLUG_PCI=y -CONFIG_HOTPLUG_PCI_ACPI=y -# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set CONFIG_IA32_EMULATION=y +CONFIG_EDD=y +CONFIG_EDD_OFF=y +CONFIG_DMI_SYSFS=m +CONFIG_EFI_VARS=y +CONFIG_EFI_RUNTIME=y +# CONFIG_VIRTUALIZATION is not set +CONFIG_MODULES=y +CONFIG_MODULE_UNLOAD=y +CONFIG_MODVERSIONS=y +# CONFIG_UNUSED_SYMBOLS is not set +CONFIG_BLK_DEV_INTEGRITY=y +# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set +CONFIG_KSM=y +CONFIG_DEFAULT_MMAP_MIN_ADDR=65536 +CONFIG_MEMORY_FAILURE=y +CONFIG_CLEANCACHE=y CONFIG_NET=y CONFIG_PACKET=y CONFIG_UNIX=y @@ -102,15 +99,13 @@ CONFIG_IP_PIMSM_V2=y CONFIG_INET_AH=m CONFIG_INET_ESP=m CONFIG_INET_IPCOMP=m -CONFIG_INET_XFRM_MODE_TRANSPORT=m -CONFIG_INET_XFRM_MODE_TUNNEL=m -CONFIG_INET_XFRM_MODE_BEET=m CONFIG_INET_DIAG=m CONFIG_IPV6=m CONFIG_INET6_AH=m CONFIG_INET6_ESP=m CONFIG_INET6_IPCOMP=m CONFIG_NETFILTER=y +CONFIG_BRIDGE_NETFILTER=m CONFIG_NF_CONNTRACK=m CONFIG_NF_CONNTRACK_EVENTS=y CONFIG_NF_CONNTRACK_TIMESTAMP=y @@ -169,7 +164,6 @@ CONFIG_NETFILTER_XT_MATCH_STRING=m CONFIG_NETFILTER_XT_MATCH_TCPMSS=m CONFIG_NETFILTER_XT_MATCH_TIME=m CONFIG_NETFILTER_XT_MATCH_U32=m -CONFIG_NF_CONNTRACK_IPV4=m CONFIG_IP_NF_IPTABLES=m CONFIG_IP_NF_MATCH_AH=m CONFIG_IP_NF_MATCH_ECN=m @@ -184,7 +178,6 @@ CONFIG_IP_NF_RAW=m CONFIG_IP_NF_ARPTABLES=m CONFIG_IP_NF_ARPFILTER=m CONFIG_IP_NF_ARP_MANGLE=m -CONFIG_NF_CONNTRACK_IPV6=m CONFIG_IP6_NF_IPTABLES=m CONFIG_IP6_NF_MATCH_AH=m CONFIG_IP6_NF_MATCH_EUI64=m @@ -224,6 +217,17 @@ CONFIG_NL80211_TESTMODE=y CONFIG_CFG80211_WEXT=y CONFIG_MAC80211=m CONFIG_RFKILL=y +CONFIG_PCI=y +CONFIG_PCIEPORTBUS=y +CONFIG_HOTPLUG_PCI_PCIE=y +# CONFIG_PCIEASPM is not set +CONFIG_PCI_MSI=y +CONFIG_PCI_IOV=y +CONFIG_PCI_PRI=y +CONFIG_PCI_PASID=y +CONFIG_HOTPLUG_PCI=y +CONFIG_HOTPLUG_PCI_ACPI=y +CONFIG_UEVENT_HELPER=y CONFIG_DEVTMPFS=y CONFIG_DEVTMPFS_MOUNT=y CONFIG_CONNECTOR=y @@ -263,6 +267,7 @@ CONFIG_VIRTIO_NET=m # CONFIG_NET_VENDOR_ALTEON is not set # CONFIG_NET_VENDOR_AMD is not set # CONFIG_NET_VENDOR_ATHEROS is not set +# CONFIG_NET_VENDOR_AURORA is not set CONFIG_TIGON3=m # CONFIG_NET_VENDOR_BROCADE is not set # CONFIG_NET_VENDOR_CHELSIO is not set @@ -271,19 +276,16 @@ CONFIG_NET_TULIP=y CONFIG_TULIP=m # CONFIG_NET_VENDOR_DLINK is not set # CONFIG_NET_VENDOR_EMULEX is not set -# CONFIG_NET_VENDOR_EXAR is not set -# CONFIG_NET_VENDOR_HP is not set +# CONFIG_NET_VENDOR_I825XX is not set CONFIG_E100=m CONFIG_E1000=m CONFIG_E1000E=m -CONFIG_E1000_DELAY=y CONFIG_IGB=m CONFIG_IGBVF=m CONFIG_IXGB=m CONFIG_IXGBE=m # CONFIG_IXGBE_HWMON is not set CONFIG_I40E=m -# CONFIG_NET_VENDOR_I825XX is not set # CONFIG_NET_VENDOR_MARVELL is not set # CONFIG_NET_VENDOR_MELLANOX is not set # CONFIG_NET_VENDOR_MICREL is not set @@ -292,10 +294,9 @@ CONFIG_I40E=m # CONFIG_NET_VENDOR_NATSEMI is not set # CONFIG_NET_VENDOR_NVIDIA is not set # CONFIG_NET_VENDOR_OKI is not set -# CONFIG_NET_PACKET_ENGINE is not set # CONFIG_NET_VENDOR_QLOGIC is not set -# CONFIG_NET_VENDOR_REALTEK is not set # CONFIG_NET_VENDOR_RDC is not set +# CONFIG_NET_VENDOR_REALTEK is not set # CONFIG_NET_VENDOR_SEEQ is not set # CONFIG_NET_VENDOR_SILAN is not set # CONFIG_NET_VENDOR_SIS is not set @@ -361,7 +362,6 @@ CONFIG_SERIO=m CONFIG_SERIAL_8250=y CONFIG_SERIAL_8250_CONSOLE=y CONFIG_SERIAL_8250_NR_UARTS=32 -CONFIG_SERIAL_8250_RUNTIME_UARTS=0 CONFIG_SERIAL_8250_EXTENDED=y CONFIG_SERIAL_8250_SHARE_IRQ=y CONFIG_SERIAL_8250_DETECT_IRQ=y @@ -389,15 +389,16 @@ CONFIG_PINCTRL_BROXTON=y CONFIG_SENSORS_CORETEMP=m CONFIG_SENSORS_TMP421=m CONFIG_WATCHDOG=y +CONFIG_WATCHDOG_CORE=y CONFIG_SOFT_WATCHDOG=m CONFIG_NIC7018_WDT=m CONFIG_LPC_ICH=m -# CONFIG_RC_CORE is not set CONFIG_MEDIA_SUPPORT=m CONFIG_MEDIA_CAMERA_SUPPORT=y CONFIG_MEDIA_USB_SUPPORT=y CONFIG_USB_VIDEO_CLASS=m # CONFIG_USB_GSPCA is not set +CONFIG_MEDIA_SUBDRV_AUTOSELECT=y CONFIG_AGP=m CONFIG_DRM=m CONFIG_DRM_RADEON=m @@ -409,6 +410,7 @@ CONFIG_DRM_VIRTIO_GPU=m CONFIG_FB=y CONFIG_FB_MODE_HELPERS=y CONFIG_FB_EFI=y +CONFIG_LCD_CLASS_DEVICE=m CONFIG_FRAMEBUFFER_CONSOLE=y CONFIG_HIDRAW=y CONFIG_HID_MICROSOFT=m @@ -458,12 +460,7 @@ CONFIG_VIRTIO_MMIO=m CONFIG_INTEL_IOMMU=y # CONFIG_INTEL_IOMMU_DEFAULT_ON is not set CONFIG_IRQ_REMAP=y -CONFIG_THUNDERBOLT=m -CONFIG_EDD=y -CONFIG_EDD_OFF=y -CONFIG_DMI_SYSFS=m -CONFIG_EFI_VARS=y -CONFIG_EFI_RUNTIME=y +CONFIG_DAX=m CONFIG_EXT2_FS=y CONFIG_EXT2_FS_XATTR=y CONFIG_EXT2_FS_POSIX_ACL=y @@ -494,33 +491,10 @@ CONFIG_NLS_CODEPAGE_437=y CONFIG_NLS_ASCII=y CONFIG_NLS_ISO8859_1=y CONFIG_NLS_UTF8=y -CONFIG_PRINTK_TIME=y -# CONFIG_ENABLE_WARN_DEPRECATED is not set -# CONFIG_ENABLE_MUST_CHECK is not set -CONFIG_FRAME_WARN=1024 -# CONFIG_UNUSED_SYMBOLS is not set -CONFIG_MAGIC_SYSRQ=y -CONFIG_MAGIC_SYSRQ_DEFAULT_ENABLE=0x0 -CONFIG_PANIC_ON_OOPS=y -CONFIG_PANIC_TIMEOUT=30 -# CONFIG_SCHED_DEBUG is not set -# CONFIG_DEBUG_PREEMPT is not set -CONFIG_RCU_CPU_STALL_TIMEOUT=60 -CONFIG_FUNCTION_TRACER=y -CONFIG_FTRACE_SYSCALLS=y -CONFIG_TRACER_SNAPSHOT=y -CONFIG_TRACER_SNAPSHOT_PER_CPU_SWAP=y -CONFIG_FUNCTION_PROFILER=y -# CONFIG_X86_VERBOSE_BOOTUP is not set -# CONFIG_EARLY_PRINTK is not set -CONFIG_IO_DELAY_0XED=y -CONFIG_OPTIMIZE_INLINING=y -CONFIG_UNWINDER_GUESS=y CONFIG_SECURITY=y CONFIG_SECURITY_NETWORK=y CONFIG_SECURITY_SELINUX=y CONFIG_SECURITY_SELINUX_BOOTPARAM=y -CONFIG_SECURITY_SELINUX_BOOTPARAM_VALUE=0 CONFIG_DEFAULT_SECURITY_DAC=y CONFIG_CRYPTO_CRYPTD=y CONFIG_CRYPTO_CBC=y @@ -531,10 +505,32 @@ CONFIG_CRYPTO_CRC32C_INTEL=y CONFIG_CRYPTO_MD5=y CONFIG_CRYPTO_SHA1=y CONFIG_CRYPTO_SHA256=y -CONFIG_CRYPTO_AES_X86_64=y +CONFIG_CRYPTO_AES=y CONFIG_CRYPTO_AES_NI_INTEL=m +CONFIG_CRYPTO_ARC4=m CONFIG_CRYPTO_USER_API_SKCIPHER=m -# CONFIG_VIRTUALIZATION is not set CONFIG_CRC7=m CONFIG_LIBCRC32C=y CONFIG_CRC8=m +CONFIG_PRINTK_TIME=y +# CONFIG_ENABLE_MUST_CHECK is not set +CONFIG_FRAME_WARN=1024 +CONFIG_MAGIC_SYSRQ=y +CONFIG_MAGIC_SYSRQ_DEFAULT_ENABLE=0x0 +CONFIG_DEBUG_FS=y +CONFIG_PANIC_ON_OOPS=y +CONFIG_PANIC_TIMEOUT=30 +# CONFIG_SCHED_DEBUG is not set +# CONFIG_DEBUG_PREEMPT is not set +CONFIG_RCU_CPU_STALL_TIMEOUT=60 +# CONFIG_RCU_TRACE is not set +CONFIG_FUNCTION_TRACER=y +CONFIG_FUNCTION_PROFILER=y +CONFIG_FTRACE_SYSCALLS=y +CONFIG_TRACER_SNAPSHOT=y +CONFIG_TRACER_SNAPSHOT_PER_CPU_SWAP=y +# CONFIG_STRICT_DEVMEM is not set +# CONFIG_X86_VERBOSE_BOOTUP is not set +# CONFIG_EARLY_PRINTK is not set +CONFIG_IO_DELAY_0XED=y +CONFIG_UNWINDER_GUESS=y From 14f54e01fca49f603a314ad3861bb73fc007f04e Mon Sep 17 00:00:00 2001 From: Gratian Crisan Date: Thu, 3 Sep 2020 10:55:06 -0500 Subject: [PATCH 108/110] nati_x86_64_defconfig: Revert NR_CPUS to the default 64 Go back to the x86_64 SMP default for NR_CPUS of 64. This allows us to fully support new hardware with more cores than the previous 16 max cap, at the cost of a slight increase in memory usage: ~8KB/CPU according to the kernel help documentation. Signed-off-by: Gratian Crisan Acked-by: Brandon Streiff --- arch/x86/configs/nati_x86_64_defconfig | 1 - 1 file changed, 1 deletion(-) diff --git a/arch/x86/configs/nati_x86_64_defconfig b/arch/x86/configs/nati_x86_64_defconfig index 6c51db067aed3..339ce8ba2de1d 100644 --- a/arch/x86/configs/nati_x86_64_defconfig +++ b/arch/x86/configs/nati_x86_64_defconfig @@ -30,7 +30,6 @@ CONFIG_X86_INTEL_LPSS=y # CONFIG_SCHED_OMIT_FRAME_POINTER is not set CONFIG_PROCESSOR_SELECT=y # CONFIG_CPU_SUP_CENTAUR is not set -CONFIG_NR_CPUS=16 # CONFIG_SCHED_MC is not set CONFIG_X86_REROUTE_FOR_BROKEN_BOOT_IRQS=y CONFIG_MICROCODE_OLD_INTERFACE=y From 0a7b366b39a823617ac2e4975e299b65d665c2bf Mon Sep 17 00:00:00 2001 From: Han Yang Tan Date: Thu, 17 Sep 2020 01:21:34 -0700 Subject: [PATCH 109/110] nati_x86_64_defconfig: Turn on CONFIG_USB4 & CONFIG_PCIEASPM Upstream commit 690ac0d20d40 ("thunderbolt: Update Kconfig entries to USB4") renamed CONFIG_THUNDERBOLT to CONFIG_USB4 since USB4 is the public specification of Thunderbolt 3 protocol. Flip this token in our defconfig to (re)enable Thunderbolt support. Also enable CONFIG_PCIEASPM to support Thunderbolt hot-plug. Signed-off-by: Han Yang Tan Signed-off-by: Gratian Crisan --- arch/x86/configs/nati_x86_64_defconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/x86/configs/nati_x86_64_defconfig b/arch/x86/configs/nati_x86_64_defconfig index 339ce8ba2de1d..4c1434753993f 100644 --- a/arch/x86/configs/nati_x86_64_defconfig +++ b/arch/x86/configs/nati_x86_64_defconfig @@ -219,7 +219,6 @@ CONFIG_RFKILL=y CONFIG_PCI=y CONFIG_PCIEPORTBUS=y CONFIG_HOTPLUG_PCI_PCIE=y -# CONFIG_PCIEASPM is not set CONFIG_PCI_MSI=y CONFIG_PCI_IOV=y CONFIG_PCI_PRI=y @@ -459,6 +458,7 @@ CONFIG_VIRTIO_MMIO=m CONFIG_INTEL_IOMMU=y # CONFIG_INTEL_IOMMU_DEFAULT_ON is not set CONFIG_IRQ_REMAP=y +CONFIG_USB4=m CONFIG_DAX=m CONFIG_EXT2_FS=y CONFIG_EXT2_FS_XATTR=y From 72cea1c8bf7149e03361cca82d3fafa9ef372b5c Mon Sep 17 00:00:00 2001 From: Gratian Crisan Date: Tue, 17 Nov 2020 15:30:36 -0600 Subject: [PATCH 110/110] nati_x86_64_defconfig: update to 5.10 Update defconfig from 5.6 to 5.10. Signed-off-by: Gratian Crisan --- arch/x86/configs/nati_x86_64_defconfig | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/arch/x86/configs/nati_x86_64_defconfig b/arch/x86/configs/nati_x86_64_defconfig index 4c1434753993f..3835e1cbeb0e4 100644 --- a/arch/x86/configs/nati_x86_64_defconfig +++ b/arch/x86/configs/nati_x86_64_defconfig @@ -51,7 +51,6 @@ CONFIG_ACPI_BUTTON=m # CONFIG_ACPI_THERMAL is not set CONFIG_ACPI_APEI=y CONFIG_ACPI_APEI_GHES=y -CONFIG_ACPI_APEI_PCIEAER=y CONFIG_ACPI_APEI_MEMORY_FAILURE=y CONFIG_SFI=y CONFIG_CPU_FREQ=y @@ -392,11 +391,10 @@ CONFIG_SOFT_WATCHDOG=m CONFIG_NIC7018_WDT=m CONFIG_LPC_ICH=m CONFIG_MEDIA_SUPPORT=m -CONFIG_MEDIA_CAMERA_SUPPORT=y +CONFIG_MEDIA_SUBDRV_AUTOSELECT=y CONFIG_MEDIA_USB_SUPPORT=y CONFIG_USB_VIDEO_CLASS=m # CONFIG_USB_GSPCA is not set -CONFIG_MEDIA_SUBDRV_AUTOSELECT=y CONFIG_AGP=m CONFIG_DRM=m CONFIG_DRM_RADEON=m