Re: [PATCH v2 2/6] arm64: Introduce config for S32
On Fri, Aug 09, 2019 at 11:29:10AM +, Stefan-gabriel Mirea wrote: > From: Mihaela Martinas > > Add configuration option for the Freescale S32 platform family in > Kconfig.platforms. For starters, the only SoC supported will be Treerunner > (S32V234), with a single execution target: the S32V234-EVB (rev 29288) > board. > > Signed-off-by: Mihaela Martinas > Signed-off-by: Stoica Cosmin-Stefan > Signed-off-by: Stefan-Gabriel Mirea > --- > arch/arm64/Kconfig.platforms | 5 + > 1 file changed, 5 insertions(+) > > diff --git a/arch/arm64/Kconfig.platforms b/arch/arm64/Kconfig.platforms > index 4778c775de1b..a9a6152d37eb 100644 > --- a/arch/arm64/Kconfig.platforms > +++ b/arch/arm64/Kconfig.platforms > @@ -210,6 +210,11 @@ config ARCH_ROCKCHIP > This enables support for the ARMv8 based Rockchip chipsets, > like the RK3368. > > +config ARCH_S32 > + bool "Freescale S32 SoC Family" So you still want to use 'Freescale' than 'NXP' here? > + help > + This enables support for the Freescale S32 family of processors. Shawn > + > config ARCH_SEATTLE > bool "AMD Seattle SoC Family" > help > -- > 2.22.0 >
Re: [PATCH v2 3/6] arm64: dts: fsl: Add device tree for S32V234-EVB
On Fri, Aug 09, 2019 at 11:29:12AM +, Stefan-gabriel Mirea wrote: > From: Stoica Cosmin-Stefan > > Add initial version of device tree for S32V234-EVB, including nodes for the > 4 Cortex-A53 cores, AIPS bus with UART modules, ARM architected timer and > Generic Interrupt Controller (GIC). > > Keep SoC level separate from board level to let future boards with this SoC > share common properties, while the dts files will keep board-dependent > properties. > > Signed-off-by: Stoica Cosmin-Stefan > Signed-off-by: Mihaela Martinas > Signed-off-by: Dan Nica > Signed-off-by: Larisa Grigore > Signed-off-by: Phu Luu An > Signed-off-by: Stefan-Gabriel Mirea > --- > arch/arm64/boot/dts/freescale/Makefile| 2 + > .../boot/dts/freescale/fsl-s32v234-evb.dts| 24 The 'fsl-' prefix can be saved here, so that we can distinguish three families by starting string: imx??? for i.MX, fsl-??? for LayerScape, and s32??? for S32. > .../arm64/boot/dts/freescale/fsl-s32v234.dtsi | 130 ++ > 3 files changed, 156 insertions(+) > create mode 100644 arch/arm64/boot/dts/freescale/fsl-s32v234-evb.dts > create mode 100644 arch/arm64/boot/dts/freescale/fsl-s32v234.dtsi > > diff --git a/arch/arm64/boot/dts/freescale/Makefile > b/arch/arm64/boot/dts/freescale/Makefile > index c043aca66572..3af29b58a833 100644 > --- a/arch/arm64/boot/dts/freescale/Makefile > +++ b/arch/arm64/boot/dts/freescale/Makefile > @@ -26,3 +26,5 @@ dtb-$(CONFIG_ARCH_MXC) += imx8mq-librem5-devkit.dtb > dtb-$(CONFIG_ARCH_MXC) += imx8mq-zii-ultra-rmb3.dtb > dtb-$(CONFIG_ARCH_MXC) += imx8mq-zii-ultra-zest.dtb > dtb-$(CONFIG_ARCH_MXC) += imx8qxp-mek.dtb > + > +dtb-$(CONFIG_ARCH_S32) += fsl-s32v234-evb.dtb > diff --git a/arch/arm64/boot/dts/freescale/fsl-s32v234-evb.dts > b/arch/arm64/boot/dts/freescale/fsl-s32v234-evb.dts > new file mode 100644 > index ..92bf6c5563a3 > --- /dev/null > +++ b/arch/arm64/boot/dts/freescale/fsl-s32v234-evb.dts > @@ -0,0 +1,24 @@ > +// SPDX-License-Identifier: GPL-2.0-or-later > +/* > + * Copyright 2015-2016 Freescale Semiconductor, Inc. > + * Copyright 2016-2017 NXP > + */ > + > +/dts-v1/; > +#include "fsl-s32v234.dtsi" > + > +/ { > + compatible = "fsl,s32v234-evb", "fsl,s32v234"; > + > + chosen { > + stdout-path = "serial0:115200n8"; > + }; > +}; > + > +&uart0 { > + status = "okay"; > +}; > + > +&uart1 { > + status = "okay"; > +}; > diff --git a/arch/arm64/boot/dts/freescale/fsl-s32v234.dtsi > b/arch/arm64/boot/dts/freescale/fsl-s32v234.dtsi > new file mode 100644 > index ..6d686d3ba997 > --- /dev/null > +++ b/arch/arm64/boot/dts/freescale/fsl-s32v234.dtsi > @@ -0,0 +1,130 @@ > +// SPDX-License-Identifier: GPL-2.0-or-later > +/* > + * Copyright 2015-2016 Freescale Semiconductor, Inc. > + * Copyright 2016-2018 NXP > + */ > + > +/memreserve/ 0x8000 0x0001; > + > +/ { > + model = "Freescale S32V234"; The 'model' is usually used in board level DTS to describe the board. > + compatible = "fsl,s32v234"; > + interrupt-parent = <&gic>; > + #address-cells = <2>; > + #size-cells = <2>; > + > + aliases { > + serial0 = &uart0; > + serial1 = &uart1; > + }; > + > + cpus { > + #address-cells = <2>; > + #size-cells = <0>; > + > + cpu0: cpu@0 { > + device_type = "cpu"; > + compatible = "arm,cortex-a53"; > + reg = <0x0 0x0>; > + enable-method = "spin-table"; > + cpu-release-addr = <0x0 0x8000>; > + next-level-cache = <&cluster0_l2_cache>; > + }; Please have a newline between nodes. > + cpu1: cpu@1 { > + device_type = "cpu"; > + compatible = "arm,cortex-a53"; > + reg = <0x0 0x1>; > + enable-method = "spin-table"; > + cpu-release-addr = <0x0 0x8000>; > + next-level-cache = <&cluster0_l2_cache>; > + }; > + cpu2: cpu@100 { > + device_type = "cpu"; > + compatible = "arm,cortex-a53"; > + reg = <0x0 0x100>; > + enable-method = "spin-table"; > + cpu-release-addr = <0x0 0x8000>; > + next-level-cache = <&cluster1_l2_cache>; > + }; > + cpu3: cpu@101 { > + device_type = "cpu"; > + compatible = "arm,cortex-a53"; > + reg = <0x0 0x101>; > + enable-method = "spin-table"; > + cpu-release-addr = <0x0 0x8000>; > + next-level-cache = <&cluster1_l2_cache>; > + }; > + > + cluster0_l2_cache: l2-cache0 { > + compatible = "cache"; > + }; > + > + c
[PATCH v6 2/2] hwmon: pmbus: Add Inspur Power System power supply driver
Add the driver to monitor Inspur Power System power supplies with hwmon over pmbus. This driver adds sysfs attributes for additional power supply data, including vendor, model, part_number, serial number, firmware revision, hardware revision, and psu mode(active/standby). Signed-off-by: John Wang --- v6: - Name i2c device as ipsps1 - Use of_match_ptr to save a few bytes if CONFIG_OF is not enabled :) v5: - Align sysfs attrs description in inspur-ipsps1.rst (Use tab instead of space to sperate names and values) v4: - Remove the additional tabs in the Makefile - Rebased on 5.3-rc4, not 5.2 v3: - Sort kconfig/makefile entries alphabetically - Remove unnecessary initialization - Use ATTRIBUTE_GROUPS instead of expanding directly - Use memscan to avoid reimplementation v2: - Fix typos in commit message - Invert Christmas tree - Configure device with sysfs attrs, not debugfs entries - Fix errno in fw_version_read, ENODATA to EPROTO - Change the print format of fw-version - Use sysfs_streq instead of strcmp("xxx" "\n", "xxx") - Document sysfs attributes --- Documentation/hwmon/inspur-ipsps1.rst | 79 + drivers/hwmon/pmbus/Kconfig | 9 + drivers/hwmon/pmbus/Makefile | 1 + drivers/hwmon/pmbus/inspur-ipsps.c| 228 ++ 4 files changed, 317 insertions(+) create mode 100644 Documentation/hwmon/inspur-ipsps1.rst create mode 100644 drivers/hwmon/pmbus/inspur-ipsps.c diff --git a/Documentation/hwmon/inspur-ipsps1.rst b/Documentation/hwmon/inspur-ipsps1.rst new file mode 100644 index ..2b871ae3448f --- /dev/null +++ b/Documentation/hwmon/inspur-ipsps1.rst @@ -0,0 +1,79 @@ +Kernel driver inspur-ipsps1 +=== + +Supported chips: + + * Inspur Power System power supply unit + +Author: John Wang + +Description +--- + +This driver supports Inspur Power System power supplies. This driver +is a client to the core PMBus driver. + +Usage Notes +--- + +This driver does not auto-detect devices. You will have to instantiate the +devices explicitly. Please see Documentation/i2c/instantiating-devices for +details. + +Sysfs entries +- + +The following attributes are supported: + +=== == +curr1_inputMeasured input current +curr1_label"iin" +curr1_max Maximum current +curr1_max_alarmCurrent high alarm +curr2_inputMeasured output current in mA. +curr2_label"iout1" +curr2_crit Critical maximum current +curr2_crit_alarm Current critical high alarm +curr2_max Maximum current +curr2_max_alarmCurrent high alarm + +fan1_alarm Fan 1 warning. +fan1_fault Fan 1 fault. +fan1_input Fan 1 speed in RPM. + +in1_alarm Input voltage under-voltage alarm. +in1_input Measured input voltage in mV. +in1_label "vin" +in2_input Measured output voltage in mV. +in2_label "vout1" +in2_lcrit Critical minimum output voltage +in2_lcrit_alarmOutput voltage critical low alarm +in2_maxMaximum output voltage +in2_max_alarm Output voltage high alarm +in2_minMinimum output voltage +in2_min_alarm Output voltage low alarm + +power1_alarm Input fault or alarm. +power1_input Measured input power in uW. +power1_label "pin" +power1_max Input power limit +power2_max_alarm Output power high alarm +power2_max Output power limit +power2_input Measured output power in uW. +power2_label "pout" + +temp[1-3]_inputMeasured temperature +temp[1-2]_max Maximum temperature +temp[1-3]_max_alarmTemperature high alarm + +vendor Manufacturer name +model Product model +part_numberProduct part number +serial_number Product serial number +fw_version Firmware version +hw_version Hardware version +mode Work mode. Can be set to active or + standby, when set to standby, PSU will + automatically switch between standby + and redundancy mode. +=== == diff --git a/drivers/hwmon/pmbus/Kconfig b/drivers/hwmon/pmbus/Kconfig index b6588483fae1..d62d69bb7e49 100644 --- a/drivers/hwmon/pmbus/Kconfig +++ b/drivers/hwmon/pmbus/Kconfig @@ -46,6 +46,15 @@ config SENSORS_IBM_CFFPS This driver can also be built as a module. If so, the module will be called ibm-cffps. +config SENSORS_INSPUR_IPSPS + tristate "INSPUR Power System Power Supply" + help + If you sa
Re: [PATCH v6 2/2] hwmon: pmbus: Add Inspur Power System power supply driver
On Mon, 19 Aug 2019 at 09:15, John Wang wrote: > > Add the driver to monitor Inspur Power System power supplies > with hwmon over pmbus. > > This driver adds sysfs attributes for additional power supply data, > including vendor, model, part_number, serial number, > firmware revision, hardware revision, and psu mode(active/standby). > > Signed-off-by: John Wang Reviewed-by: Joel Stanley
[PATCH V3 0/3] KVM/Hyper-V: Add Hyper-V direct tlb flush support
From: Tianyu Lan This patchset is to add Hyper-V direct tlb support in KVM. Hyper-V in L0 can delegate L1 hypervisor to handle tlb flush request from L2 guest when direct tlb flush is enabled in L1. Patch 2 introduces new cap KVM_CAP_HYPERV_DIRECT_TLBFLUSH to enable feature from user space. User space should enable this feature only when Hyper-V hypervisor capability is exposed to guest and KVM profile is hided. There is a parameter conflict between KVM and Hyper-V hypercall. We hope L2 guest doesn't use KVM hypercall when the feature is enabled. Detail please see comment of new API "KVM_CAP_HYPERV_DIRECT_TLBFLUSH" Change since v2: - Move hv assist page(hv_pa_pg) from struct kvm to struct kvm_hv. Change since v1: - Fix offset issue in the patch 1. - Update description of KVM KVM_CAP_HYPERV_DIRECT_TLBFLUSH. Tianyu Lan (2): x86/Hyper-V: Fix definition of struct hv_vp_assist_page KVM/Hyper-V: Add new KVM cap KVM_CAP_HYPERV_DIRECT_TLBFLUSH Vitaly Kuznetsov (1): KVM/Hyper-V/VMX: Add direct tlb flush support Documentation/virtual/kvm/api.txt | 13 + arch/x86/include/asm/hyperv-tlfs.h | 24 ++- arch/x86/include/asm/kvm_host.h| 4 arch/x86/kvm/vmx/evmcs.h | 2 ++ arch/x86/kvm/vmx/vmx.c | 39 ++ arch/x86/kvm/x86.c | 8 include/uapi/linux/kvm.h | 1 + 7 files changed, 86 insertions(+), 5 deletions(-) -- 2.14.5
[PATCH V3 1/3] x86/Hyper-V: Fix definition of struct hv_vp_assist_page
From: Tianyu Lan The struct hv_vp_assist_page was defined incorrectly. The "vtl_control" should be u64[3], "nested_enlightenments _control" should be a u64 and there is 7 reserved bytes following "enlighten_vmentry". This patch is to fix it. Signed-off-by: Tianyu Lan -- Change since v1: Move definition of struct hv_nested_enlightenments_control into this patch to fix offset issue. --- arch/x86/include/asm/hyperv-tlfs.h | 20 +++- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/arch/x86/include/asm/hyperv-tlfs.h b/arch/x86/include/asm/hyperv-tlfs.h index af78cd72b8f3..cf0b2a04271d 100644 --- a/arch/x86/include/asm/hyperv-tlfs.h +++ b/arch/x86/include/asm/hyperv-tlfs.h @@ -514,14 +514,24 @@ struct hv_timer_message_payload { __u64 delivery_time;/* When the message was delivered */ } __packed; +struct hv_nested_enlightenments_control { + struct { + __u32 directhypercall:1; + __u32 reserved:31; + } features; + struct { + __u32 reserved; + } hypercallControls; +} __packed; + /* Define virtual processor assist page structure. */ struct hv_vp_assist_page { __u32 apic_assist; - __u32 reserved; - __u64 vtl_control[2]; - __u64 nested_enlightenments_control[2]; - __u32 enlighten_vmentry; - __u32 padding; + __u32 reserved1; + __u64 vtl_control[3]; + struct hv_nested_enlightenments_control nested_control; + __u8 enlighten_vmentry; + __u8 reserved2[7]; __u64 current_nested_vmcs; } __packed; -- 2.14.5
[PATCH V3 2/3] KVM/Hyper-V: Add new KVM cap KVM_CAP_HYPERV_DIRECT_TLBFLUSH
From: Tianyu Lan This patch adds new KVM cap KVM_CAP_HYPERV_DIRECT_TLBFLUSH and let user space to enable direct tlb flush function when only Hyper-V hypervsior capability is exposed to VM. This patch also adds enable_direct_tlbflush callback in the struct kvm_x86_ops and platforms may use it to implement direct tlb flush support. Signed-off-by: Tianyu Lan --- Change since v1: Update description of KVM_CAP_HYPERV_DIRECT_TLBFLUSH in the KVM API doc. --- Documentation/virtual/kvm/api.txt | 13 + arch/x86/include/asm/kvm_host.h | 2 ++ arch/x86/kvm/x86.c| 8 include/uapi/linux/kvm.h | 1 + 4 files changed, 24 insertions(+) diff --git a/Documentation/virtual/kvm/api.txt b/Documentation/virtual/kvm/api.txt index 2cd6250b2896..0c6e1b25d0c8 100644 --- a/Documentation/virtual/kvm/api.txt +++ b/Documentation/virtual/kvm/api.txt @@ -5289,3 +5289,16 @@ Architectures: x86 This capability indicates that KVM supports paravirtualized Hyper-V IPI send hypercalls: HvCallSendSyntheticClusterIpi, HvCallSendSyntheticClusterIpiEx. +8.21 KVM_CAP_HYPERV_DIRECT_TLBFLUSH + +Architecture: x86 + +This capability indicates that KVM running on top of Hyper-V hypervisor +enables Direct TLB flush for its guests meaning that TLB flush +hypercalls are handled by Level 0 hypervisor (Hyper-V) bypassing KVM. +Due to the different ABI for hypercall parameters between Hyper-V and +KVM, enabling this capability effectively disables all hypercall +handling by KVM (as some KVM hypercall may be mistakenly treated as TLB +flush hypercalls by Hyper-V) so userspace should disable KVM identification +in CPUID and only exposes Hyper-V identification. In this case, guest +thinks it's running on Hyper-V and only use Hyper-V hypercalls. diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h index 0cc5b611a113..667d154e89d4 100644 --- a/arch/x86/include/asm/kvm_host.h +++ b/arch/x86/include/asm/kvm_host.h @@ -1205,6 +1205,8 @@ struct kvm_x86_ops { uint16_t (*nested_get_evmcs_version)(struct kvm_vcpu *vcpu); bool (*need_emulation_on_page_fault)(struct kvm_vcpu *vcpu); + + int (*enable_direct_tlbflush)(struct kvm_vcpu *vcpu); }; struct kvm_arch_async_pf { diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index 9d7b9e6a0939..a9d8ee7f7bf0 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -3183,6 +3183,9 @@ int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext) r = kvm_x86_ops->get_nested_state ? kvm_x86_ops->get_nested_state(NULL, NULL, 0) : 0; break; + case KVM_CAP_HYPERV_DIRECT_TLBFLUSH: + r = kvm_x86_ops->enable_direct_tlbflush ? 1 : 0; + break; default: break; } @@ -3953,6 +3956,11 @@ static int kvm_vcpu_ioctl_enable_cap(struct kvm_vcpu *vcpu, r = -EFAULT; } return r; + case KVM_CAP_HYPERV_DIRECT_TLBFLUSH: + if (!kvm_x86_ops->enable_direct_tlbflush) + return -ENOTTY; + + return kvm_x86_ops->enable_direct_tlbflush(vcpu); default: return -EINVAL; diff --git a/include/uapi/linux/kvm.h b/include/uapi/linux/kvm.h index a7c19540ce21..cb959bc925b1 100644 --- a/include/uapi/linux/kvm.h +++ b/include/uapi/linux/kvm.h @@ -996,6 +996,7 @@ struct kvm_ppc_resize_hpt { #define KVM_CAP_ARM_PTRAUTH_ADDRESS 171 #define KVM_CAP_ARM_PTRAUTH_GENERIC 172 #define KVM_CAP_PMU_EVENT_FILTER 173 +#define KVM_CAP_HYPERV_DIRECT_TLBFLUSH 174 #ifdef KVM_CAP_IRQ_ROUTING -- 2.14.5
Re: [PATCH V3 2/3] KVM/Hyper-V: Add new KVM cap KVM_CAP_HYPERV_DIRECT_TLBFLUSH
On Mon, 19 Aug 2019, lantianyu1...@gmail.com wrote: > From: Tianyu Lan > > This patch adds Same git grep command as before > new KVM cap KVM_CAP_HYPERV_DIRECT_TLBFLUSH and let baseball cap? Please do not use weird acronyms. This is text and there is not limitation on characters. > user space to enable direct tlb flush function when only Hyper-V > hypervsior capability is exposed to VM. Sorry, but I'm not understanding this sentence. > This patch also adds Once more > enable_direct_tlbflush callback in the struct kvm_x86_ops and > platforms may use it to implement direct tlb flush support. Please tell in the changelog WHY you are doing things not what. The what is obviously in the patch. So you want to explain what you are trying to achieve and why it is useful. Then you can add a short note about what you are adding, but not at the level of detail which is available from the diff itself. Thanks, tglx
Re: [PATCH V3 1/3] x86/Hyper-V: Fix definition of struct hv_vp_assist_page
On Mon, 19 Aug 2019, lantianyu1...@gmail.com wrote: > From: Tianyu Lan > > The struct hv_vp_assist_page was defined incorrectly. > The "vtl_control" should be u64[3], "nested_enlightenments s/The /The member/ > _control" should be a u64 and there is 7 reserved bytes s/is/are/ > following "enlighten_vmentry". This patch is to fix it. git grep 'This patch' Documentation/process/ Thanks, tglx
Re: [PATCH 1/3] kbuild: move KBUILD_LDS, KBUILD_VMLINUX_{OBJS,LIBS} to makefiles.rst
On Thu, Aug 15, 2019 at 1:06 AM Masahiro Yamada wrote: > > These three variables are not intended to be tweaked by users. > Move them from kbuild.rst to makefiles.rst. > > Signed-off-by: Masahiro Yamada > --- > Applied to linux-kbuild. > I will apply to linux-kbuild this > to avoid conflicts. > > > Documentation/kbuild/kbuild.rst| 14 -- > Documentation/kbuild/makefiles.rst | 14 ++ > 2 files changed, 14 insertions(+), 14 deletions(-) > > diff --git a/Documentation/kbuild/kbuild.rst b/Documentation/kbuild/kbuild.rst > index 61b2181ed3ea..62f9d86c082c 100644 > --- a/Documentation/kbuild/kbuild.rst > +++ b/Documentation/kbuild/kbuild.rst > @@ -258,17 +258,3 @@ KBUILD_BUILD_USER, KBUILD_BUILD_HOST > These two variables allow to override the user@host string displayed during > boot and in /proc/version. The default value is the output of the commands > whoami and host, respectively. > - > -KBUILD_LDS > --- > -The linker script with full path. Assigned by the top-level Makefile. > - > -KBUILD_VMLINUX_OBJS > > -All object files for vmlinux. They are linked to vmlinux in the same > -order as listed in KBUILD_VMLINUX_OBJS. > - > -KBUILD_VMLINUX_LIBS > > -All .a "lib" files for vmlinux. KBUILD_VMLINUX_OBJS and KBUILD_VMLINUX_LIBS > -together specify all the object files used to link vmlinux. > diff --git a/Documentation/kbuild/makefiles.rst > b/Documentation/kbuild/makefiles.rst > index f4f0f7ffde2b..d3448d2c8017 100644 > --- a/Documentation/kbuild/makefiles.rst > +++ b/Documentation/kbuild/makefiles.rst > @@ -995,6 +995,20 @@ When kbuild executes, the following steps are followed > (roughly): > top-level Makefile has set any other flags. This provides a > means for an architecture to override the defaults. > > +KBUILD_LDS > + > + The linker script with full path. Assigned by the top-level Makefile. > + > +KBUILD_VMLINUX_OBJS > + > + All object files for vmlinux. They are linked to vmlinux in the same > + order as listed in KBUILD_VMLINUX_OBJS. > + > +KBUILD_VMLINUX_LIBS > + > + All .a "lib" files for vmlinux. KBUILD_VMLINUX_OBJS and > + KBUILD_VMLINUX_LIBS together specify all the object files used to > + link vmlinux. > > 6.2 Add prerequisites to archheaders > > -- > 2.17.1 > -- Best Regards Masahiro Yamada
Re: [PATCH v8 2/5] arm64: Tighten the PR_{SET,GET}_TAGGED_ADDR_CTRL prctl() unused arguments
On Thu, Aug 15, 2019 at 5:44 PM Catalin Marinas wrote: > > Require that arg{3,4,5} of the PR_{SET,GET}_TAGGED_ADDR_CTRL prctl and > arg2 of the PR_GET_TAGGED_ADDR_CTRL prctl() are zero rather than ignored > for future extensions. > > Signed-off-by: Catalin Marinas Acked-by: Andrey Konovalov > --- > kernel/sys.c | 4 > 1 file changed, 4 insertions(+) > > diff --git a/kernel/sys.c b/kernel/sys.c > index c6c4d5358bd3..ec48396b4943 100644 > --- a/kernel/sys.c > +++ b/kernel/sys.c > @@ -2499,9 +2499,13 @@ SYSCALL_DEFINE5(prctl, int, option, unsigned long, > arg2, unsigned long, arg3, > error = PAC_RESET_KEYS(me, arg2); > break; > case PR_SET_TAGGED_ADDR_CTRL: > + if (arg3 || arg4 || arg5) > + return -EINVAL; > error = SET_TAGGED_ADDR_CTRL(arg2); > break; > case PR_GET_TAGGED_ADDR_CTRL: > + if (arg2 || arg3 || arg4 || arg5) > + return -EINVAL; > error = GET_TAGGED_ADDR_CTRL(); > break; > default:
Re: [PATCH v8 1/5] mm: untag user pointers in mmap/munmap/mremap/brk
On Thu, Aug 15, 2019 at 5:44 PM Catalin Marinas wrote: > > There isn't a good reason to differentiate between the user address > space layout modification syscalls and the other memory > permission/attributes ones (e.g. mprotect, madvise) w.r.t. the tagged > address ABI. Untag the user addresses on entry to these functions. > > Signed-off-by: Catalin Marinas Acked-by: Andrey Konovalov > --- > mm/mmap.c | 5 + > mm/mremap.c | 6 +- > 2 files changed, 6 insertions(+), 5 deletions(-) > > diff --git a/mm/mmap.c b/mm/mmap.c > index 7e8c3e8ae75f..b766b633b7ae 100644 > --- a/mm/mmap.c > +++ b/mm/mmap.c > @@ -201,6 +201,8 @@ SYSCALL_DEFINE1(brk, unsigned long, brk) > bool downgraded = false; > LIST_HEAD(uf); > > + brk = untagged_addr(brk); > + > if (down_write_killable(&mm->mmap_sem)) > return -EINTR; > > @@ -1573,6 +1575,8 @@ unsigned long ksys_mmap_pgoff(unsigned long addr, > unsigned long len, > struct file *file = NULL; > unsigned long retval; > > + addr = untagged_addr(addr); > + > if (!(flags & MAP_ANONYMOUS)) { > audit_mmap_fd(fd, flags); > file = fget(fd); > @@ -2874,6 +2878,7 @@ EXPORT_SYMBOL(vm_munmap); > > SYSCALL_DEFINE2(munmap, unsigned long, addr, size_t, len) > { > + addr = untagged_addr(addr); > profile_munmap(addr); > return __vm_munmap(addr, len, true); > } > diff --git a/mm/mremap.c b/mm/mremap.c > index 64c9a3b8be0a..1fc8a29fbe3f 100644 > --- a/mm/mremap.c > +++ b/mm/mremap.c > @@ -606,12 +606,8 @@ SYSCALL_DEFINE5(mremap, unsigned long, addr, unsigned > long, old_len, > LIST_HEAD(uf_unmap_early); > LIST_HEAD(uf_unmap); > > - /* > -* Architectures may interpret the tag passed to mmap as a background > -* colour for the corresponding vma. For mremap we don't allow tagged > -* new_addr to preserve similar behaviour to mmap. > -*/ > addr = untagged_addr(addr); > + new_addr = untagged_addr(new_addr); > > if (flags & ~(MREMAP_FIXED | MREMAP_MAYMOVE)) > return ret;
Re: [PATCH v8 3/5] arm64: Change the tagged_addr sysctl control semantics to only prevent the opt-in
On Thu, Aug 15, 2019 at 5:44 PM Catalin Marinas wrote: > > First rename the sysctl control to abi.tagged_addr_disabled and make it > default off (zero). When abi.tagged_addr_disabled == 1, only block the > enabling of the TBI ABI via prctl(PR_SET_TAGGED_ADDR_CTRL, > PR_TAGGED_ADDR_ENABLE). > Getting the status of the ABI or disabling it is still allowed. > > Signed-off-by: Catalin Marinas Acked-by: Andrey Konovalov > --- > arch/arm64/kernel/process.c | 17 ++--- > 1 file changed, 10 insertions(+), 7 deletions(-) > > diff --git a/arch/arm64/kernel/process.c b/arch/arm64/kernel/process.c > index 76b7c55026aa..03689c0beb34 100644 > --- a/arch/arm64/kernel/process.c > +++ b/arch/arm64/kernel/process.c > @@ -579,17 +579,22 @@ void arch_setup_new_exec(void) > /* > * Control the relaxed ABI allowing tagged user addresses into the kernel. > */ > -static unsigned int tagged_addr_prctl_allowed = 1; > +static unsigned int tagged_addr_disabled; > > long set_tagged_addr_ctrl(unsigned long arg) > { > - if (!tagged_addr_prctl_allowed) > - return -EINVAL; > if (is_compat_task()) > return -EINVAL; > if (arg & ~PR_TAGGED_ADDR_ENABLE) > return -EINVAL; > > + /* > +* Do not allow the enabling of the tagged address ABI if globally > +* disabled via sysctl abi.tagged_addr_disabled. > +*/ > + if (arg & PR_TAGGED_ADDR_ENABLE && tagged_addr_disabled) > + return -EINVAL; > + > update_thread_flag(TIF_TAGGED_ADDR, arg & PR_TAGGED_ADDR_ENABLE); > > return 0; > @@ -597,8 +602,6 @@ long set_tagged_addr_ctrl(unsigned long arg) > > long get_tagged_addr_ctrl(void) > { > - if (!tagged_addr_prctl_allowed) > - return -EINVAL; > if (is_compat_task()) > return -EINVAL; > > @@ -618,9 +621,9 @@ static int one = 1; > > static struct ctl_table tagged_addr_sysctl_table[] = { > { > - .procname = "tagged_addr", > + .procname = "tagged_addr_disabled", > .mode = 0644, > - .data = &tagged_addr_prctl_allowed, > + .data = &tagged_addr_disabled, > .maxlen = sizeof(int), > .proc_handler = proc_dointvec_minmax, > .extra1 = &zero,
Re: [PATCH v8 5/5] arm64: Relax Documentation/arm64/tagged-pointers.rst
On Thu, Aug 15, 2019 at 5:44 PM Catalin Marinas wrote: > > From: Vincenzo Frascino > > On AArch64 the TCR_EL1.TBI0 bit is set by default, allowing userspace > (EL0) to perform memory accesses through 64-bit pointers with a non-zero > top byte. However, such pointers were not allowed at the user-kernel > syscall ABI boundary. > > With the Tagged Address ABI patchset, it is now possible to pass tagged > pointers to the syscalls. Relax the requirements described in > tagged-pointers.rst to be compliant with the behaviours guaranteed by > the AArch64 Tagged Address ABI. > > Cc: Will Deacon > Cc: Andrey Konovalov > Cc: Szabolcs Nagy > Cc: Kevin Brodsky > Signed-off-by: Vincenzo Frascino > Co-developed-by: Catalin Marinas > Signed-off-by: Catalin Marinas Acked-by: Andrey Konovalov > --- > Documentation/arm64/tagged-pointers.rst | 23 --- > 1 file changed, 16 insertions(+), 7 deletions(-) > > diff --git a/Documentation/arm64/tagged-pointers.rst > b/Documentation/arm64/tagged-pointers.rst > index 2acdec3ebbeb..fd5306019e91 100644 > --- a/Documentation/arm64/tagged-pointers.rst > +++ b/Documentation/arm64/tagged-pointers.rst > @@ -20,7 +20,9 @@ Passing tagged addresses to the kernel > -- > > All interpretation of userspace memory addresses by the kernel assumes > -an address tag of 0x00. > +an address tag of 0x00, unless the application enables the AArch64 > +Tagged Address ABI explicitly > +(Documentation/arm64/tagged-address-abi.rst). > > This includes, but is not limited to, addresses found in: > > @@ -33,13 +35,15 @@ This includes, but is not limited to, addresses found in: > - the frame pointer (x29) and frame records, e.g. when interpreting > them to generate a backtrace or call graph. > > -Using non-zero address tags in any of these locations may result in an > -error code being returned, a (fatal) signal being raised, or other modes > -of failure. > +Using non-zero address tags in any of these locations when the > +userspace application did not enable the AArch64 Tagged Address ABI may > +result in an error code being returned, a (fatal) signal being raised, > +or other modes of failure. > > -For these reasons, passing non-zero address tags to the kernel via > -system calls is forbidden, and using a non-zero address tag for sp is > -strongly discouraged. > +For these reasons, when the AArch64 Tagged Address ABI is disabled, > +passing non-zero address tags to the kernel via system calls is > +forbidden, and using a non-zero address tag for sp is strongly > +discouraged. > > Programs maintaining a frame pointer and frame records that use non-zero > address tags may suffer impaired or inaccurate debug and profiling > @@ -59,6 +63,11 @@ be preserved. > The architecture prevents the use of a tagged PC, so the upper byte will > be set to a sign-extension of bit 55 on exception return. > > +This behaviour is maintained when the AArch64 Tagged Address ABI is > +enabled. In addition, with the exceptions above, the kernel will > +preserve any non-zero tags passed by the user via syscalls and stored in > +kernel data structures (e.g. set_robust_list(), sigaltstack()). > + > > Other considerations >
Re: [PATCH v8 4/5] arm64: Define Documentation/arm64/tagged-address-abi.rst
On Thu, Aug 15, 2019 at 5:44 PM Catalin Marinas wrote: > > From: Vincenzo Frascino > > On AArch64 the TCR_EL1.TBI0 bit is set by default, allowing userspace > (EL0) to perform memory accesses through 64-bit pointers with a non-zero > top byte. Introduce the document describing the relaxation of the > syscall ABI that allows userspace to pass certain tagged pointers to > kernel syscalls. > > Cc: Will Deacon > Cc: Andrey Konovalov > Cc: Szabolcs Nagy > Cc: Kevin Brodsky > Signed-off-by: Vincenzo Frascino > Co-developed-by: Catalin Marinas > Signed-off-by: Catalin Marinas Acked-by: Andrey Konovalov > --- > Documentation/arm64/tagged-address-abi.rst | 155 + > 1 file changed, 155 insertions(+) > create mode 100644 Documentation/arm64/tagged-address-abi.rst > > diff --git a/Documentation/arm64/tagged-address-abi.rst > b/Documentation/arm64/tagged-address-abi.rst > new file mode 100644 > index ..8808337775d6 > --- /dev/null > +++ b/Documentation/arm64/tagged-address-abi.rst > @@ -0,0 +1,155 @@ > +== > +AArch64 TAGGED ADDRESS ABI > +== > + > +Authors: Vincenzo Frascino > + Catalin Marinas > + > +Date: 15 August 2019 > + > +This document describes the usage and semantics of the Tagged Address > +ABI on AArch64 Linux. > + > +1. Introduction > +--- > + > +On AArch64 the TCR_EL1.TBI0 bit is set by default, allowing userspace > +(EL0) to perform memory accesses through 64-bit pointers with a non-zero > +top byte. This document describes the relaxation of the syscall ABI that > +allows userspace to pass certain tagged pointers to kernel syscalls. > + > +2. AArch64 Tagged Address ABI > +- > + > +From the kernel syscall interface perspective and for the purposes of > +this document, a "valid tagged pointer" is a pointer with a potentially > +non-zero top-byte that references an address in the user process address > +space obtained in one of the following ways: > + > +- mmap() done by the process itself (or its parent), where either: > + > + - flags have the **MAP_ANONYMOUS** bit set > + - the file descriptor refers to a regular file (including those > +returned by memfd_create()) or **/dev/zero** > + > +- brk() system call done by the process itself (i.e. the heap area > + between the initial location of the program break at process creation > + and its current location). > + > +- any memory mapped by the kernel in the address space of the process > + during creation and with the same restrictions as for mmap() above > + (e.g. data, bss, stack). > + > +The AArch64 Tagged Address ABI has two stages of relaxation depending > +how the user addresses are used by the kernel: > + > +1. User addresses not accessed by the kernel but used for address space > + management (e.g. mmap(), mprotect(), madvise()). The use of valid > + tagged pointers in this context is always allowed. > + > +2. User addresses accessed by the kernel (e.g. write()). This ABI > + relaxation is disabled by default and the application thread needs to > + explicitly enable it via **prctl()** as follows: > + > + - **PR_SET_TAGGED_ADDR_CTRL**: enable or disable the AArch64 Tagged > + Address ABI for the calling thread. > + > + The (unsigned int) arg2 argument is a bit mask describing the > + control mode used: > + > + - **PR_TAGGED_ADDR_ENABLE**: enable AArch64 Tagged Address ABI. > + Default status is disabled. > + > + Arguments arg3, arg4, and arg5 must be 0. > + > + - **PR_GET_TAGGED_ADDR_CTRL**: get the status of the AArch64 Tagged > + Address ABI for the calling thread. > + > + Arguments arg2, arg3, arg4, and arg5 must be 0. > + > + The ABI properties described above are thread-scoped, inherited on > + clone() and fork() and cleared on exec(). > + > + Calling prctl(PR_SET_TAGGED_ADDR_CTRL, PR_TAGGED_ADDR_ENABLE, 0, 0, 0) > + returns -EINVAL if the AArch64 Tagged Address ABI is globally disabled > + by sysctl abi.tagged_addr_disabled=1. The default sysctl > + abi.tagged_addr_disabled configuration is 0. > + > +When the AArch64 Tagged Address ABI is enabled for a thread, the > +following behaviours are guaranteed: > + > +- All syscalls except the cases mentioned in section 3 can accept any > + valid tagged pointer. > + > +- The syscall behaviour is undefined for invalid tagged pointers: it may > + result in an error code being returned, a (fatal) signal being raised, > + or other modes of failure. > + > +- A valid tagged pointer has the same semantics as the corresponding > + untagged pointer. > + > +A definition of the meaning of tagged pointers on AArch64 can be found > +in Documentation/arm64/tagged-pointers.rst. > + > +3. AArch64 Tagged Address ABI Exceptions > +- > + > +The following system call parameters must be untagged regardless of the > +ABI relaxation: > + > +- prctl() other than arguments poi
[PATCH v2] x86/CPU/AMD: Clear RDRAND CPUID bit on AMD family 15h/16h
From: Tom Lendacky There have been reports of RDRAND issues after resuming from suspend on some AMD family 15h and family 16h systems. This issue stems from a BIOS not performing the proper steps during resume to ensure RDRAND continues to function properly. RDRAND support is indicated by CPUID Fn0001_ECX[30]. This bit can be reset by clearing MSR C001_1004[62]. Any software that checks for RDRAND support using CPUID, including the kernel, will believe that RDRAND is not supported. Update the CPU initialization to clear the RDRAND CPUID bit for any family 15h and 16h processor that supports RDRAND. If it is known that the family 15h or family 16h system does not have an RDRAND resume issue or that the system will not be placed in suspend, the "rdrand_force" kernel parameter can be used to stop the clearing of the RDRAND CPUID bit. Additionally, update the suspend and resume path to save and restore the MSR C001_1004 value to ensure that the RDRAND CPUID setting remains in place after resuming from suspend. Note, that clearing the RDRAND CPUID bit does not prevent a processor that normally supports the RDRAND instruction from executing the RDRAND instruction. So any code that determined the support based on family and model won't #UD. Signed-off-by: Tom Lendacky --- Changes from v1: - Changed rdrand_force option to rdrand=force option - Only do this for configuratons with CONFIG_PM_SLEEP=y - Various name clarifications - Added a check to verify change in case the kernel is running virtualized - More verbose messaging --- .../admin-guide/kernel-parameters.txt | 7 ++ arch/x86/include/asm/msr-index.h | 1 + arch/x86/kernel/cpu/amd.c | 66 ++ arch/x86/power/cpu.c | 86 --- 4 files changed, 147 insertions(+), 13 deletions(-) diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt index 47d981a86e2f..4c1971960afa 100644 --- a/Documentation/admin-guide/kernel-parameters.txt +++ b/Documentation/admin-guide/kernel-parameters.txt @@ -4090,6 +4090,13 @@ Run specified binary instead of /init from the ramdisk, used for early userspace startup. See initrd. + rdrand= [X86] + force - Override the decision by the kernel to hide the + advertisement of RDRAND support (this affects + certain AMD processors because of buggy BIOS + support, specifically around the suspend/resume + path). + rdt=[HW,X86,RDT] Turn on/off individual RDT features. List is: cmt, mbmtotal, mbmlocal, l3cat, l3cdp, l2cat, l2cdp, diff --git a/arch/x86/include/asm/msr-index.h b/arch/x86/include/asm/msr-index.h index 6b4fc2788078..271d837d69a8 100644 --- a/arch/x86/include/asm/msr-index.h +++ b/arch/x86/include/asm/msr-index.h @@ -381,6 +381,7 @@ #define MSR_AMD64_PATCH_LEVEL 0x008b #define MSR_AMD64_TSC_RATIO0xc104 #define MSR_AMD64_NB_CFG 0xc001001f +#define MSR_AMD64_CPUID_FN_1 0xc0011004 #define MSR_AMD64_PATCH_LOADER 0xc0010020 #define MSR_AMD64_OSVW_ID_LENGTH 0xc0010140 #define MSR_AMD64_OSVW_STATUS 0xc0010141 diff --git a/arch/x86/kernel/cpu/amd.c b/arch/x86/kernel/cpu/amd.c index 3afe07d602dd..29f0cdfbdca5 100644 --- a/arch/x86/kernel/cpu/amd.c +++ b/arch/x86/kernel/cpu/amd.c @@ -804,6 +804,64 @@ static void init_amd_ln(struct cpuinfo_x86 *c) msr_set_bit(MSR_AMD64_DE_CFG, 31); } +static bool rdrand_force; + +static int __init rdrand_cmdline(char *str) +{ + if (!str) + return -EINVAL; + + if (!strcmp(str, "force")) + rdrand_force = true; + else + return -EINVAL; + + return 0; +} +early_param("rdrand", rdrand_cmdline); + +static void clear_rdrand_cpuid_bit(struct cpuinfo_x86 *c) +{ + /* +* Saving of the MSR used to hide the RDRAND support during +* suspend/resume is done by arch/x86/power/cpu.c, which is +* dependent on CONFIG_PM_SLEEP. +*/ + if (!IS_ENABLED(CONFIG_PM_SLEEP)) + return; + + /* +* The nordrand option can clear X86_FEATURE_RDRAND, so check for +* RDRAND support using the CPUID function directly. +*/ + if (!(cpuid_ecx(1) & BIT(30)) || rdrand_force) + return; + + msr_clear_bit(MSR_AMD64_CPUID_FN_1, 62); + + /* +* Verify that the CPUID change has occurred in case the kernel is +* running virtualized and the hypervisor doesn't support the MSR. +*/ + if (cpuid_ecx(1) & BIT(30)) { + pr_info_once("BIOS may not properly restore RDRAND after suspend, but hypervisor does not support hiding RDRA
Re: [PATCH v8 4/5] arm64: Define Documentation/arm64/tagged-address-abi.rst
On Thu, Aug 15, 2019 at 04:44:02PM +0100, Catalin Marinas wrote: > From: Vincenzo Frascino > > On AArch64 the TCR_EL1.TBI0 bit is set by default, allowing userspace > (EL0) to perform memory accesses through 64-bit pointers with a non-zero > top byte. Introduce the document describing the relaxation of the > syscall ABI that allows userspace to pass certain tagged pointers to > kernel syscalls. > > Cc: Will Deacon > Cc: Andrey Konovalov > Cc: Szabolcs Nagy > Cc: Kevin Brodsky > Signed-off-by: Vincenzo Frascino > Co-developed-by: Catalin Marinas > Signed-off-by: Catalin Marinas > --- > Documentation/arm64/tagged-address-abi.rst | 155 + > 1 file changed, 155 insertions(+) > create mode 100644 Documentation/arm64/tagged-address-abi.rst > > diff --git a/Documentation/arm64/tagged-address-abi.rst > b/Documentation/arm64/tagged-address-abi.rst > new file mode 100644 > index ..8808337775d6 > --- /dev/null > +++ b/Documentation/arm64/tagged-address-abi.rst > @@ -0,0 +1,155 @@ > +== > +AArch64 TAGGED ADDRESS ABI > +== > + > +Authors: Vincenzo Frascino > + Catalin Marinas > + > +Date: 15 August 2019 > + > +This document describes the usage and semantics of the Tagged Address > +ABI on AArch64 Linux. > + > +1. Introduction > +--- > + > +On AArch64 the TCR_EL1.TBI0 bit is set by default, allowing userspace > +(EL0) to perform memory accesses through 64-bit pointers with a non-zero > +top byte. This document describes the relaxation of the syscall ABI that > +allows userspace to pass certain tagged pointers to kernel syscalls. > + > +2. AArch64 Tagged Address ABI > +- > + > +From the kernel syscall interface perspective and for the purposes of > +this document, a "valid tagged pointer" is a pointer with a potentially > +non-zero top-byte that references an address in the user process address > +space obtained in one of the following ways: > + > +- mmap() done by the process itself (or its parent), where either: > + > + - flags have the **MAP_ANONYMOUS** bit set > + - the file descriptor refers to a regular file (including those > +returned by memfd_create()) or **/dev/zero** nit: but the markup is pretty inconsistent throughout. Why is /dev/zero bold, but not memfd_create()? I think they would both be better off in typewriter font, if that's a thing in rst. > +- brk() system call done by the process itself (i.e. the heap area > + between the initial location of the program break at process creation > + and its current location). > + > +- any memory mapped by the kernel in the address space of the process > + during creation and with the same restrictions as for mmap() above > + (e.g. data, bss, stack). > + > +The AArch64 Tagged Address ABI has two stages of relaxation depending > +how the user addresses are used by the kernel: > + > +1. User addresses not accessed by the kernel but used for address space > + management (e.g. mmap(), mprotect(), madvise()). The use of valid > + tagged pointers in this context is always allowed. > + > +2. User addresses accessed by the kernel (e.g. write()). This ABI > + relaxation is disabled by default and the application thread needs to > + explicitly enable it via **prctl()** as follows: > + > + - **PR_SET_TAGGED_ADDR_CTRL**: enable or disable the AArch64 Tagged > + Address ABI for the calling thread. > + > + The (unsigned int) arg2 argument is a bit mask describing the > + control mode used: > + > + - **PR_TAGGED_ADDR_ENABLE**: enable AArch64 Tagged Address ABI. > + Default status is disabled. > + > + Arguments arg3, arg4, and arg5 must be 0. > + > + - **PR_GET_TAGGED_ADDR_CTRL**: get the status of the AArch64 Tagged > + Address ABI for the calling thread. > + > + Arguments arg2, arg3, arg4, and arg5 must be 0. > + > + The ABI properties described above are thread-scoped, inherited on > + clone() and fork() and cleared on exec(). > + > + Calling prctl(PR_SET_TAGGED_ADDR_CTRL, PR_TAGGED_ADDR_ENABLE, 0, 0, 0) > + returns -EINVAL if the AArch64 Tagged Address ABI is globally disabled > + by sysctl abi.tagged_addr_disabled=1. The default sysctl > + abi.tagged_addr_disabled configuration is 0. > + > +When the AArch64 Tagged Address ABI is enabled for a thread, the > +following behaviours are guaranteed: > + > +- All syscalls except the cases mentioned in section 3 can accept any > + valid tagged pointer. > + > +- The syscall behaviour is undefined for invalid tagged pointers: it may > + result in an error code being returned, a (fatal) signal being raised, > + or other modes of failure. > + > +- A valid tagged pointer has the same semantics as the corresponding > + untagged pointer. nit, but I'd reword this last bullet slightly to say: - The syscall behaviour for a valid tagged pointer is the same as for the corresponding untagged pointer. Since that flows better
Re: [PATCH v8 1/5] mm: untag user pointers in mmap/munmap/mremap/brk
On Thu, Aug 15, 2019 at 04:43:59PM +0100, Catalin Marinas wrote: > There isn't a good reason to differentiate between the user address > space layout modification syscalls and the other memory > permission/attributes ones (e.g. mprotect, madvise) w.r.t. the tagged > address ABI. Untag the user addresses on entry to these functions. > > Signed-off-by: Catalin Marinas > --- > mm/mmap.c | 5 + > mm/mremap.c | 6 +- > 2 files changed, 6 insertions(+), 5 deletions(-) Acked-by: Will Deacon Andrew -- please can you pick this patch up? I'll take the rest of the series via arm64 once we've finished discussing the wording details. Thanks, Will
[PATCH v5 01/17] w1: add 1-wire master driver for IP block found in SGI ASICs
Starting with SGI Origin machines nearly every new SGI ASIC contains an 1-Wire master. They are used for attaching One-Wire prom devices, which contain information about part numbers, revision numbers, serial number etc. and MAC addresses for ethernet interfaces. This patch adds a master driver to support this IP block. It also adds an extra field dev_id to struct w1_bus_master, which could be in used in slave drivers for creating unique device names. Signed-off-by: Thomas Bogendoerfer --- drivers/w1/masters/Kconfig | 9 +++ drivers/w1/masters/Makefile | 1 + drivers/w1/masters/sgi_w1.c | 130 +++ include/linux/platform_data/sgi-w1.h | 15 include/linux/w1.h | 2 + 5 files changed, 157 insertions(+) create mode 100644 drivers/w1/masters/sgi_w1.c create mode 100644 include/linux/platform_data/sgi-w1.h diff --git a/drivers/w1/masters/Kconfig b/drivers/w1/masters/Kconfig index 7ae260577901..24b9a8e05f64 100644 --- a/drivers/w1/masters/Kconfig +++ b/drivers/w1/masters/Kconfig @@ -65,5 +65,14 @@ config HDQ_MASTER_OMAP Say Y here if you want support for the 1-wire or HDQ Interface on an OMAP processor. +config W1_MASTER_SGI + tristate "SGI ASIC driver" + help + Say Y here if you want support for your 1-wire devices using + SGI ASIC 1-Wire interface + + This support is also available as a module. If so, the module + will be called sgi_w1. + endmenu diff --git a/drivers/w1/masters/Makefile b/drivers/w1/masters/Makefile index 18954cae4256..dae629b7ab49 100644 --- a/drivers/w1/masters/Makefile +++ b/drivers/w1/masters/Makefile @@ -11,3 +11,4 @@ obj-$(CONFIG_W1_MASTER_MXC) += mxc_w1.o obj-$(CONFIG_W1_MASTER_DS1WM) += ds1wm.o obj-$(CONFIG_W1_MASTER_GPIO) += w1-gpio.o obj-$(CONFIG_HDQ_MASTER_OMAP) += omap_hdq.o +obj-$(CONFIG_W1_MASTER_SGI)+= sgi_w1.o diff --git a/drivers/w1/masters/sgi_w1.c b/drivers/w1/masters/sgi_w1.c new file mode 100644 index ..1b2d96b945be --- /dev/null +++ b/drivers/w1/masters/sgi_w1.c @@ -0,0 +1,130 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * sgi_w1.c - w1 master driver for one wire support in SGI ASICs + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#define MCR_RD_DATABIT(0) +#define MCR_DONE BIT(1) + +#define MCR_PACK(pulse, sample) (((pulse) << 10) | ((sample) << 2)) + +struct sgi_w1_device { + u32 __iomem *mcr; + struct w1_bus_master bus_master; + char dev_id[64]; +}; + +static u8 sgi_w1_wait(u32 __iomem *mcr) +{ + u32 mcr_val; + + do { + mcr_val = readl(mcr); + } while (!(mcr_val & MCR_DONE)); + + return (mcr_val & MCR_RD_DATA) ? 1 : 0; +} + +/* + * this is the low level routine to + * reset the device on the One Wire interface + * on the hardware + */ +static u8 sgi_w1_reset_bus(void *data) +{ + struct sgi_w1_device *dev = data; + u8 ret; + + writel(MCR_PACK(520, 65), dev->mcr); + ret = sgi_w1_wait(dev->mcr); + udelay(500); /* recovery time */ + return ret; +} + +/* + * this is the low level routine to read/write a bit on the One Wire + * interface on the hardware. It does write 0 if parameter bit is set + * to 0, otherwise a write 1/read. + */ +static u8 sgi_w1_touch_bit(void *data, u8 bit) +{ + struct sgi_w1_device *dev = data; + u8 ret; + + if (bit) + writel(MCR_PACK(6, 13), dev->mcr); + else + writel(MCR_PACK(80, 30), dev->mcr); + + ret = sgi_w1_wait(dev->mcr); + if (bit) + udelay(100); /* recovery */ + return ret; +} + +static int sgi_w1_probe(struct platform_device *pdev) +{ + struct sgi_w1_device *sdev; + struct sgi_w1_platform_data *pdata; + struct resource *res; + + sdev = devm_kzalloc(&pdev->dev, sizeof(struct sgi_w1_device), + GFP_KERNEL); + if (!sdev) + return -ENOMEM; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + sdev->mcr = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(sdev->mcr)) + return PTR_ERR(sdev->mcr); + + sdev->bus_master.data = sdev; + sdev->bus_master.reset_bus = sgi_w1_reset_bus; + sdev->bus_master.touch_bit = sgi_w1_touch_bit; + + pdata = dev_get_platdata(&pdev->dev); + if (pdata) { + strlcpy(sdev->dev_id, pdata->dev_id, sizeof(sdev->dev_id)); + sdev->bus_master.dev_id = sdev->dev_id; + } + + platform_set_drvdata(pdev, sdev); + + return w1_add_master_device(&sdev->bus_master); +} + +/* + * disassociate the w1 device from the driver + */ +static int sgi_w1_remove(struct platform_device *pdev) +{ + struct sgi_w1_device *sdev = platform_get_drvdata(pdev); + + w1_remove_master_device(&s
[PATCH v5 00/17] Use MFD framework for SGI IOC3 drivers
GI IOC3 ASIC includes support for ethernet, PS2 keyboard/mouse, NIC (number in a can), GPIO and a byte bus. By attaching a SuperIO chip to it, it also supports serial lines and a parallel port. The chip is used on a variety of SGI systems with different configurations. This patchset moves code out of the network driver, which doesn't belong there, into its new place a MFD driver and specific platform drivers for the different subfunctions. Changes in v5: - requested by Jakub I've splitted ioc3 ethernet driver changes into more steps to make the transition more visible; on the way there I've "checkpatched" the driver and reduced code reorderings - dropped all uint16_t and uint32_t - added nvmem API extension to the documenation file - changed to use request_irq/free_irq in serio driver - removed wrong kfree() in serio error path Changes in v4: - added w1 drivers to the series after merge in 5.3 failed because of no response from maintainer and other parts of this series won't work without that drivers - moved ip30 systemboard support to the ip30 series, which will deal with rtc oddity Lee found - converted to use devm_platform_ioremap_resource - use PLATFORM_DEVID_AUTO for serial, ethernet and serio in mfd driver - fixed reverse christmas order in ioc3-eth.c - formating issue found by Lee - re-worked irq request/free in serio driver to avoid crashes during probe/remove Changes in v3: - use 1-wire subsystem for handling proms - pci-xtalk driver uses prom information to create PCI subsystem ids for use in MFD driver - changed MFD driver to only use static declared mfd_cells - added IP30 system board setup to MFD driver - mac address is now read from ioc3-eth driver with nvmem framework Changes in v2: - fixed issue in ioc3kbd.c reported by Dmitry Torokhov - merged IP27 RTC removal and 8250 serial driver addition into main MFD patch to keep patches bisectable Thomas Bogendoerfer (17): w1: add 1-wire master driver for IP block found in SGI ASICs w1: add DS2501, DS2502, DS2505 EPROM device driver nvmem: core: add nvmem_device_find MIPS: PCI: refactor ioc3 special handling MIPS: PCI: use information from 1-wire PROM for IOC3 detection MIPS: SGI-IP27: remove ioc3 ethernet init MIPS: SGI-IP27: restructure ioc3 register access net: sgi: ioc3-eth: remove checkpatch errors/warning net: sgi: ioc3-eth: use defines for constants dealing with desc rings net: sgi: ioc3-eth: rework skb rx handling net: sgi: ioc3-eth: no need to stop queue set_multicast_list net: sgi: ioc3-eth: use dma-direct for dma allocations net: sgi: ioc3-eth: use csum_fold net: sgi: ioc3-eth: Fix IPG settings mfd: ioc3: Add driver for SGI IOC3 chip MIPS: SGI-IP27: fix readb/writeb addressing Input: add IOC3 serio driver Documentation/driver-api/nvmem.rst|2 + arch/mips/include/asm/mach-ip27/mangle-port.h |4 +- arch/mips/include/asm/pci/bridge.h|1 + arch/mips/include/asm/sn/ioc3.h | 364 +++ arch/mips/pci/pci-xtalk-bridge.c | 296 -- arch/mips/sgi-ip27/ip27-console.c |5 +- arch/mips/sgi-ip27/ip27-init.c| 13 - arch/mips/sgi-ip27/ip27-timer.c | 20 - arch/mips/sgi-ip27/ip27-xtalk.c | 38 +- drivers/input/serio/Kconfig | 10 + drivers/input/serio/Makefile |1 + drivers/input/serio/ioc3kbd.c | 160 +++ drivers/mfd/Kconfig | 13 + drivers/mfd/Makefile |1 + drivers/mfd/ioc3.c| 586 +++ drivers/net/ethernet/sgi/Kconfig |4 +- drivers/net/ethernet/sgi/ioc3-eth.c | 1405 + drivers/nvmem/core.c | 62 +- drivers/rtc/rtc-m48t35.c | 11 + drivers/tty/serial/8250/8250_ioc3.c | 98 ++ drivers/tty/serial/8250/Kconfig | 11 + drivers/tty/serial/8250/Makefile |1 + drivers/w1/masters/Kconfig|9 + drivers/w1/masters/Makefile |1 + drivers/w1/masters/sgi_w1.c | 130 +++ drivers/w1/slaves/Kconfig |6 + drivers/w1/slaves/Makefile|1 + drivers/w1/slaves/w1_ds250x.c | 293 ++ include/linux/nvmem-consumer.h|9 + include/linux/platform_data/sgi-w1.h | 15 + include/linux/w1.h|2 + 31 files changed, 2266 insertions(+), 1306 deletions(-) create mode 100644 drivers/input/serio/ioc3kbd.c create mode 100644 drivers/mfd/ioc3.c create mode 100644 drivers/tty/serial/8250/8250_ioc3.c create mode 100644 drivers/w1/masters/sgi_w1.c create mode 100644 drivers/w1/slaves/w1_ds250x.c create mode 100644 include/linux/platform_data/sgi-w1.h -- 2.13.7
[PATCH v5 08/17] net: sgi: ioc3-eth: remove checkpatch errors/warning
Before massaging the driver further fix oddities found by checkpatch like - wrong indention - comment formatting - use of printk instead or netdev_xxx/pr_xxx Signed-off-by: Thomas Bogendoerfer --- drivers/net/ethernet/sgi/ioc3-eth.c | 275 +--- 1 file changed, 130 insertions(+), 145 deletions(-) diff --git a/drivers/net/ethernet/sgi/ioc3-eth.c b/drivers/net/ethernet/sgi/ioc3-eth.c index 713d2472cb97..e81e5bb37ac6 100644 --- a/drivers/net/ethernet/sgi/ioc3-eth.c +++ b/drivers/net/ethernet/sgi/ioc3-eth.c @@ -1,9 +1,5 @@ -/* - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - * - * Driver for SGI's IOC3 based Ethernet cards as found in the PCI card. +// SPDX-License-Identifier: GPL-2.0 +/* Driver for SGI's IOC3 based Ethernet cards as found in the PCI card. * * Copyright (C) 1999, 2000, 01, 03, 06 Ralf Baechle * Copyright (C) 1995, 1999, 2000, 2001 by Silicon Graphics, Inc. @@ -39,6 +35,7 @@ #include #include #include +#include #include #include #include @@ -58,21 +55,19 @@ #include #include -#include #include #include #include #include #include -/* - * 64 RX buffers. This is tunable in the range of 16 <= x < 512. The +/* 64 RX buffers. This is tunable in the range of 16 <= x < 512. The * value must be a power of two. */ #define RX_BUFFS 64 -#define ETCSR_FD ((17data); + if (offset) skb_reserve(skb, offset); } @@ -147,15 +143,11 @@ static inline unsigned long ioc3_map(void *ptr, unsigned long vdev) } /* BEWARE: The IOC3 documentation documents the size of rx buffers as - 1644 while it's actually 1664. This one was nasty to track down ... */ + * 1644 while it's actually 1664. This one was nasty to track down ... + */ #define RX_OFFSET 10 #define RX_BUF_ALLOC_SIZE (1664 + RX_OFFSET + IOC3_CACHELINE) -/* DMA barrier to separate cached and uncached accesses. */ -#define BARRIER() \ - __asm__("sync" ::: "memory") - - #define IOC3_SIZE 0x10 static inline u32 mcr_pack(u32 pulse, u32 sample) @@ -176,7 +168,7 @@ static int nic_wait(u32 __iomem *mcr) static int nic_reset(u32 __iomem *mcr) { -int presence; + int presence; writel(mcr_pack(500, 65), mcr); presence = nic_wait(mcr); @@ -184,7 +176,7 @@ static int nic_reset(u32 __iomem *mcr) writel(mcr_pack(0, 500), mcr); nic_wait(mcr); -return presence; + return presence; } static inline int nic_read_bit(u32 __iomem *mcr) @@ -209,8 +201,7 @@ static inline void nic_write_bit(u32 __iomem *mcr, int bit) nic_wait(mcr); } -/* - * Read a byte from an iButton device +/* Read a byte from an iButton device */ static u32 nic_read_byte(u32 __iomem *mcr) { @@ -223,8 +214,7 @@ static u32 nic_read_byte(u32 __iomem *mcr) return result; } -/* - * Write a byte to an iButton device +/* Write a byte to an iButton device */ static void nic_write_byte(u32 __iomem *mcr, int byte) { @@ -253,7 +243,7 @@ static u64 nic_find(u32 __iomem *mcr, int *last) b = nic_read_bit(mcr); if (a && b) { - printk("NIC search failed (not fatal).\n"); + pr_warn("NIC search failed (not fatal).\n"); *last = 0; return 0; } @@ -264,8 +254,9 @@ static u64 nic_find(u32 __iomem *mcr, int *last) } else if (index > *last) { address &= ~(1UL << index); disc = index; - } else if ((address & (1UL << index)) == 0) + } else if ((address & (1UL << index)) == 0) { disc = index; + } nic_write_bit(mcr, address & (1UL << index)); continue; } else { @@ -293,6 +284,7 @@ static int nic_init(u32 __iomem *mcr) while (1) { u64 reg; + reg = nic_find(mcr, &save); switch (reg & 0xff) { @@ -323,16 +315,15 @@ static int nic_init(u32 __iomem *mcr) break; } - printk("Found %s NIC", type); + pr_info("Found %s NIC", type); if (type != unknown) - printk (" registration number %pM, CRC %02x", serial, crc); - printk(".\n"); + pr_cont(" registration number %pM, CRC %02x", serial, crc); + pr_cont(".\n"); return 0; } -/* - * Read the NIC (Number-In-a-Can) device used to store the MAC address on +/* Read the NIC (Number-In-a-Can) device used to store the MAC address on * SN0 / SN
[PATCH v5 15/17] mfd: ioc3: Add driver for SGI IOC3 chip
SGI IOC3 chip has integrated ethernet, keyboard and mouse interface. It also supports connecting a SuperIO chip for serial and parallel interfaces. IOC3 is used inside various SGI systemboards and add-on cards with different equipped external interfaces. Support for ethernet and serial interfaces were implemented inside the network driver. This patchset moves out the not network related parts to a new MFD driver, which takes care of card detection, setup of platform devices and interrupt distribution for the subdevices. Serial portion: Acked-by: Greg Kroah-Hartman Signed-off-by: Thomas Bogendoerfer --- arch/mips/sgi-ip27/ip27-timer.c | 20 - drivers/mfd/Kconfig | 13 + drivers/mfd/Makefile| 1 + drivers/mfd/ioc3.c | 586 +++ drivers/net/ethernet/sgi/Kconfig| 4 +- drivers/net/ethernet/sgi/ioc3-eth.c | 782 +--- drivers/tty/serial/8250/8250_ioc3.c | 98 + drivers/tty/serial/8250/Kconfig | 11 + drivers/tty/serial/8250/Makefile| 1 + 9 files changed, 913 insertions(+), 603 deletions(-) create mode 100644 drivers/mfd/ioc3.c create mode 100644 drivers/tty/serial/8250/8250_ioc3.c diff --git a/arch/mips/sgi-ip27/ip27-timer.c b/arch/mips/sgi-ip27/ip27-timer.c index 9b4b9ac621a3..5631e93ea350 100644 --- a/arch/mips/sgi-ip27/ip27-timer.c +++ b/arch/mips/sgi-ip27/ip27-timer.c @@ -188,23 +188,3 @@ void hub_rtc_init(cnodeid_t cnode) LOCAL_HUB_S(PI_RT_PEND_B, 0); } } - -static int __init sgi_ip27_rtc_devinit(void) -{ - struct resource res; - - memset(&res, 0, sizeof(res)); - res.start = XPHYSADDR(KL_CONFIG_CH_CONS_INFO(master_nasid)->memory_base + - IOC3_BYTEBUS_DEV0); - res.end = res.start + 32767; - res.flags = IORESOURCE_MEM; - - return IS_ERR(platform_device_register_simple("rtc-m48t35", -1, - &res, 1)); -} - -/* - * kludge make this a device_initcall after ioc3 resource conflicts - * are resolved - */ -late_initcall(sgi_ip27_rtc_devinit); diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig index f129f9678940..6d3908267a6a 100644 --- a/drivers/mfd/Kconfig +++ b/drivers/mfd/Kconfig @@ -2019,5 +2019,18 @@ config RAVE_SP_CORE Select this to get support for the Supervisory Processor device found on several devices in RAVE line of hardware. +config SGI_MFD_IOC3 + tristate "SGI IOC3 core driver" + depends on PCI && MIPS + select MFD_CORE + help + This option enables basic support for the SGI IOC3-based + controller cards. This option does not enable any specific + functions on such a card, but provides necessary infrastructure + for other drivers to utilize. + + If you have an SGI Origin, Octane, or a PCI IOC3 card, + then say Y. Otherwise say N. + endmenu endif diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile index f026ada68f6a..fb523eaa358a 100644 --- a/drivers/mfd/Makefile +++ b/drivers/mfd/Makefile @@ -257,3 +257,4 @@ obj-$(CONFIG_MFD_ROHM_BD70528) += rohm-bd70528.o obj-$(CONFIG_MFD_ROHM_BD718XX) += rohm-bd718x7.o obj-$(CONFIG_MFD_STMFX)+= stmfx.o +obj-$(CONFIG_SGI_MFD_IOC3) += ioc3.o diff --git a/drivers/mfd/ioc3.c b/drivers/mfd/ioc3.c new file mode 100644 index ..5bcb3461a189 --- /dev/null +++ b/drivers/mfd/ioc3.c @@ -0,0 +1,586 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * SGI IOC3 multifunction device driver + * + * Copyright (C) 2018, 2019 Thomas Bogendoerfer + * + * Based on work by: + * Stanislaw Skowronek + * Joshua Kinard + * Brent Casavant - IOC4 master driver + * Pat Gefre - IOC3 serial port IRQ demuxer + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#define IOC3_IRQ_SERIAL_A 6 +#define IOC3_IRQ_SERIAL_B 15 +#define IOC3_IRQ_KBD 22 +#define IOC3_IRQ_ETH_DOMAIN23 + +/* Bitmask for selecting which IRQs are level triggered */ +#define IOC3_LVL_MASK (BIT(IOC3_IRQ_SERIAL_A) | BIT(IOC3_IRQ_SERIAL_B)) + +#define M48T35_REG_SIZE32768 /* size of m48t35 registers */ + +/* 1.2 us latency timer (40 cycles at 33 MHz) */ +#define IOC3_LATENCY 40 + +struct ioc3_priv_data { + struct irq_domain *domain; + struct ioc3 __iomem *regs; + struct pci_dev *pdev; + int domain_irq; +}; + +static void ioc3_irq_ack(struct irq_data *d) +{ + struct ioc3_priv_data *ipd = irq_data_get_irq_chip_data(d); + unsigned int hwirq = irqd_to_hwirq(d); + + writel(BIT(hwirq), &ipd->regs->sio_ir); +} + +static void ioc3_irq_mask(struct irq_data *d) +{ + struct ioc3_priv_data *ipd = irq_data_get_irq_chip_data(d); + unsigned int hwirq = irqd_to_hwirq(d); + + writel(BIT(hwirq), &ipd->regs->sio_iec); +} + +static void ioc3_irq_unmask(struct
[PATCH v5 17/17] Input: add IOC3 serio driver
This patch adds a platform driver for supporting keyboard and mouse interface of SGI IOC3 chips. Signed-off-by: Thomas Bogendoerfer --- drivers/input/serio/Kconfig | 10 +++ drivers/input/serio/Makefile | 1 + drivers/input/serio/ioc3kbd.c | 160 ++ 3 files changed, 171 insertions(+) create mode 100644 drivers/input/serio/ioc3kbd.c diff --git a/drivers/input/serio/Kconfig b/drivers/input/serio/Kconfig index f3e18f8ef9ca..373a1646019e 100644 --- a/drivers/input/serio/Kconfig +++ b/drivers/input/serio/Kconfig @@ -165,6 +165,16 @@ config SERIO_MACEPS2 To compile this driver as a module, choose M here: the module will be called maceps2. +config SERIO_SGI_IOC3 + tristate "SGI IOC3 PS/2 controller" + depends on SGI_MFD_IOC3 + help + Say Y here if you have an SGI Onyx2, SGI Octane or IOC3 PCI card + and you want to attach and use a keyboard, mouse, or both. + + To compile this driver as a module, choose M here: the + module will be called ioc3kbd. + config SERIO_LIBPS2 tristate "PS/2 driver library" depends on SERIO_I8042 || SERIO_I8042=n diff --git a/drivers/input/serio/Makefile b/drivers/input/serio/Makefile index 67950a5ccb3f..6d97bad7b844 100644 --- a/drivers/input/serio/Makefile +++ b/drivers/input/serio/Makefile @@ -20,6 +20,7 @@ obj-$(CONFIG_HIL_MLC) += hp_sdc_mlc.o hil_mlc.o obj-$(CONFIG_SERIO_PCIPS2) += pcips2.o obj-$(CONFIG_SERIO_PS2MULT)+= ps2mult.o obj-$(CONFIG_SERIO_MACEPS2)+= maceps2.o +obj-$(CONFIG_SERIO_SGI_IOC3) += ioc3kbd.o obj-$(CONFIG_SERIO_LIBPS2) += libps2.o obj-$(CONFIG_SERIO_RAW)+= serio_raw.o obj-$(CONFIG_SERIO_AMS_DELTA) += ams_delta_serio.o diff --git a/drivers/input/serio/ioc3kbd.c b/drivers/input/serio/ioc3kbd.c new file mode 100644 index ..32df2743c27f --- /dev/null +++ b/drivers/input/serio/ioc3kbd.c @@ -0,0 +1,160 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * SGI IOC3 PS/2 controller driver for linux + * + * Copyright (C) 2019 Thomas Bogendoerfer + * + * Based on code Copyright (C) 2005 Stanislaw Skowronek + * Copyright (C) 2009 Johannes Dickgreber + */ + +#include +#include +#include +#include +#include +#include + +#include + +struct ioc3kbd_data { + struct ioc3_serioregs __iomem *regs; + struct serio *kbd, *aux; + int irq; +}; + +static int ioc3kbd_write(struct serio *dev, u8 val) +{ + struct ioc3kbd_data *d = dev->port_data; + unsigned long timeout = 0; + u32 mask; + + mask = (dev == d->aux) ? KM_CSR_M_WRT_PEND : KM_CSR_K_WRT_PEND; + while ((readl(&d->regs->km_csr) & mask) && (timeout < 1000)) { + udelay(100); + timeout++; + } + + if (timeout >= 1000) + return -ETIMEDOUT; + + writel(val, dev == d->aux ? &d->regs->m_wd : &d->regs->k_wd); + + return 0; +} + +static irqreturn_t ioc3kbd_intr(int itq, void *dev_id) +{ + struct ioc3kbd_data *d = dev_id; + u32 data_k, data_m; + + data_k = readl(&d->regs->k_rd); + data_m = readl(&d->regs->m_rd); + + if (data_k & KM_RD_VALID_0) + serio_interrupt(d->kbd, (data_k >> KM_RD_DATA_0_SHIFT) & 0xff, + 0); + if (data_k & KM_RD_VALID_1) + serio_interrupt(d->kbd, (data_k >> KM_RD_DATA_1_SHIFT) & 0xff, + 0); + if (data_k & KM_RD_VALID_2) + serio_interrupt(d->kbd, (data_k >> KM_RD_DATA_2_SHIFT) & 0xff, + 0); + if (data_m & KM_RD_VALID_0) + serio_interrupt(d->aux, (data_m >> KM_RD_DATA_0_SHIFT) & 0xff, + 0); + if (data_m & KM_RD_VALID_1) + serio_interrupt(d->aux, (data_m >> KM_RD_DATA_1_SHIFT) & 0xff, + 0); + if (data_m & KM_RD_VALID_2) + serio_interrupt(d->aux, (data_m >> KM_RD_DATA_2_SHIFT) & 0xff, + 0); + + return IRQ_HANDLED; +} + +static int ioc3kbd_probe(struct platform_device *pdev) +{ + struct ioc3_serioregs __iomem *regs; + struct device *dev = &pdev->dev; + struct ioc3kbd_data *d; + struct serio *sk, *sa; + int irq, ret; + + regs = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(regs)) + return PTR_ERR(regs); + + irq = platform_get_irq(pdev, 0); + if (irq < 0) + return -ENXIO; + + d = devm_kzalloc(dev, sizeof(*d), GFP_KERNEL); + if (!d) + return -ENOMEM; + + sk = kzalloc(sizeof(*sk), GFP_KERNEL); + if (!sk) + return -ENOMEM; + + sa = kzalloc(sizeof(*sa), GFP_KERNEL); + if (!sa) { + kfree(sk); + return -ENOMEM; + } + + sk->id.type = SERIO_8042; + sk->write = ioc3kbd_write; + snprintf
[PATCH v5 06/17] MIPS: SGI-IP27: remove ioc3 ethernet init
Removed not needed disabling of ethernet interrupts in IP27 platform code. Signed-off-by: Thomas Bogendoerfer --- arch/mips/sgi-ip27/ip27-init.c | 13 - 1 file changed, 13 deletions(-) diff --git a/arch/mips/sgi-ip27/ip27-init.c b/arch/mips/sgi-ip27/ip27-init.c index 066b33f50bcc..59d5375c9021 100644 --- a/arch/mips/sgi-ip27/ip27-init.c +++ b/arch/mips/sgi-ip27/ip27-init.c @@ -130,17 +130,6 @@ cnodeid_t get_compact_nodeid(void) return NASID_TO_COMPACT_NODEID(get_nasid()); } -static inline void ioc3_eth_init(void) -{ - struct ioc3 *ioc3; - nasid_t nid; - - nid = get_nasid(); - ioc3 = (struct ioc3 *) KL_CONFIG_CH_CONS_INFO(nid)->memory_base; - - ioc3->eier = 0; -} - extern void ip27_reboot_setup(void); void __init plat_mem_setup(void) @@ -182,8 +171,6 @@ void __init plat_mem_setup(void) panic("Kernel compiled for N mode."); #endif - ioc3_eth_init(); - ioport_resource.start = 0; ioport_resource.end = ~0UL; set_io_port_base(IO_BASE); -- 2.13.7
[PATCH v5 02/17] w1: add DS2501, DS2502, DS2505 EPROM device driver
Add a 1-Wire slave driver to support DS250x EPROM deivces. This slave driver attaches the devices to the NVMEM subsystem for an easy in-kernel usage. Signed-off-by: Thomas Bogendoerfer --- drivers/w1/slaves/Kconfig | 6 + drivers/w1/slaves/Makefile| 1 + drivers/w1/slaves/w1_ds250x.c | 293 ++ 3 files changed, 300 insertions(+) create mode 100644 drivers/w1/slaves/w1_ds250x.c diff --git a/drivers/w1/slaves/Kconfig b/drivers/w1/slaves/Kconfig index 37aaad26b373..ebed495b9e69 100644 --- a/drivers/w1/slaves/Kconfig +++ b/drivers/w1/slaves/Kconfig @@ -101,6 +101,12 @@ config W1_SLAVE_DS2438 Say Y here if you want to use a 1-wire DS2438 Smart Battery Monitor device support +config W1_SLAVE_DS250X + tristate "512b/1kb/16kb EPROM family support" + help + Say Y here if you want to use a 1-wire + 512b/1kb/16kb EPROM family device (DS250x). + config W1_SLAVE_DS2780 tristate "Dallas 2780 battery monitor chip" help diff --git a/drivers/w1/slaves/Makefile b/drivers/w1/slaves/Makefile index eab29f151413..8e9655eaa478 100644 --- a/drivers/w1/slaves/Makefile +++ b/drivers/w1/slaves/Makefile @@ -14,6 +14,7 @@ obj-$(CONFIG_W1_SLAVE_DS2431) += w1_ds2431.o obj-$(CONFIG_W1_SLAVE_DS2805) += w1_ds2805.o obj-$(CONFIG_W1_SLAVE_DS2433) += w1_ds2433.o obj-$(CONFIG_W1_SLAVE_DS2438) += w1_ds2438.o +obj-$(CONFIG_W1_SLAVE_DS250X) += w1_ds250x.o obj-$(CONFIG_W1_SLAVE_DS2780) += w1_ds2780.o obj-$(CONFIG_W1_SLAVE_DS2781) += w1_ds2781.o obj-$(CONFIG_W1_SLAVE_DS28E04) += w1_ds28e04.o diff --git a/drivers/w1/slaves/w1_ds250x.c b/drivers/w1/slaves/w1_ds250x.c new file mode 100644 index ..78da3774bbbe --- /dev/null +++ b/drivers/w1/slaves/w1_ds250x.c @@ -0,0 +1,293 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * w1_ds250x.c - w1 family 09/0b/89/91 (DS250x) driver + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#define W1_DS2501_UNW_FAMILY0x91 +#define W1_DS2501_SIZE 64 + +#define W1_DS2502_FAMILY0x09 +#define W1_DS2502_UNW_FAMILY0x89 +#define W1_DS2502_SIZE 128 + +#define W1_DS2505_FAMILY 0x0b +#define W1_DS2505_SIZE 2048 + +#define W1_PAGE_SIZE 32 + +#define W1_EXT_READ_MEMORY 0xA5 +#define W1_READ_DATA_CRC0xC3 + +#define OFF2PG(off)((off) / W1_PAGE_SIZE) + +#define CRC16_INIT 0 +#define CRC16_VALID0xb001 + +struct w1_eprom_data { + size_t size; + int (*read)(struct w1_slave *sl, int pageno); + u8 eprom[W1_DS2505_SIZE]; + DECLARE_BITMAP(page_present, W1_DS2505_SIZE / W1_PAGE_SIZE); + char nvmem_name[64]; +}; + +static int w1_ds2502_read_page(struct w1_slave *sl, int pageno) +{ + struct w1_eprom_data *data = sl->family_data; + int pgoff = pageno * W1_PAGE_SIZE; + int ret = -EIO; + u8 buf[3]; + u8 crc8; + + if (test_bit(pageno, data->page_present)) + return 0; /* page already present */ + + mutex_lock(&sl->master->bus_mutex); + + if (w1_reset_select_slave(sl)) + goto err; + + buf[0] = W1_READ_DATA_CRC; + buf[1] = pgoff & 0xff; + buf[2] = pgoff >> 8; + w1_write_block(sl->master, buf, 3); + + crc8 = w1_read_8(sl->master); + if (w1_calc_crc8(buf, 3) != crc8) + goto err; + + w1_read_block(sl->master, &data->eprom[pgoff], W1_PAGE_SIZE); + + crc8 = w1_read_8(sl->master); + if (w1_calc_crc8(&data->eprom[pgoff], W1_PAGE_SIZE) != crc8) + goto err; + + set_bit(pageno, data->page_present); /* mark page present */ + ret = 0; +err: + mutex_unlock(&sl->master->bus_mutex); + return ret; +} + +static int w1_ds2505_read_page(struct w1_slave *sl, int pageno) +{ + struct w1_eprom_data *data = sl->family_data; + int redir_retries = 16; + int pgoff, epoff; + int ret = -EIO; + u8 buf[6]; + u8 redir; + u16 crc; + + if (test_bit(pageno, data->page_present)) + return 0; /* page already present */ + + epoff = pgoff = pageno * W1_PAGE_SIZE; + mutex_lock(&sl->master->bus_mutex); + +retry: + if (w1_reset_select_slave(sl)) + goto err; + + buf[0] = W1_EXT_READ_MEMORY; + buf[1] = pgoff & 0xff; + buf[2] = pgoff >> 8; + w1_write_block(sl->master, buf, 3); + w1_read_block(sl->master, buf + 3, 3); /* redir, crc16 */ + redir = buf[3]; + crc = crc16(CRC16_INIT, buf, 6); + + if (crc != CRC16_VALID) + goto err; + + + if (redir != 0xff) { + redir_retries--; + if (redir_retries < 0) + goto err; + + pgoff = (redir ^ 0xff) * W1_PAGE_SIZE; + goto retry; + } + + w1_read_block(sl->master, &data->eprom[epoff], W1_PAGE_SIZE)
[PATCH v5 13/17] net: sgi: ioc3-eth: use csum_fold
replace open coded checksum folding by csum_fold. Signed-off-by: Thomas Bogendoerfer --- drivers/net/ethernet/sgi/ioc3-eth.c | 6 +- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/drivers/net/ethernet/sgi/ioc3-eth.c b/drivers/net/ethernet/sgi/ioc3-eth.c index 647e3926bd71..56392f0b01de 100644 --- a/drivers/net/ethernet/sgi/ioc3-eth.c +++ b/drivers/net/ethernet/sgi/ioc3-eth.c @@ -1378,16 +1378,12 @@ static netdev_tx_t ioc3_start_xmit(struct sk_buff *skb, struct net_device *dev) /* Sum up dest addr, src addr and protocol */ ehsum = eh[0] + eh[1] + eh[2] + eh[3] + eh[4] + eh[5] + eh[6]; - /* Fold ehsum. can't use csum_fold which negates also ... */ - ehsum = (ehsum & 0x) + (ehsum >> 16); - ehsum = (ehsum & 0x) + (ehsum >> 16); - /* Skip IP header; it's sum is always zero and was * already filled in by ip_output.c */ csum = csum_tcpudp_nofold(ih->saddr, ih->daddr, ih->tot_len - (ih->ihl << 2), - proto, 0x ^ ehsum); + proto, csum_fold(ehsum)); csum = (csum & 0x) + (csum >> 16); /* Fold again */ csum = (csum & 0x) + (csum >> 16); -- 2.13.7
[PATCH v5 16/17] MIPS: SGI-IP27: fix readb/writeb addressing
Our chosen byte swapping, which is what firmware already uses, is to do readl/writel by normal lw/sw intructions (data invariance). This also means we need to mangle addresses for u8 and u16 accesses. The mangling for 16bit has been done aready, but 8bit one was missing. Correcting this causes different addresses for accesses to the SuperIO and local bus of the IOC3 chip. This is fixed by changing byte order in ioc3 and m48rtc_rtc structs. Acked-by: Alexandre Belloni Signed-off-by: Thomas Bogendoerfer --- arch/mips/include/asm/mach-ip27/mangle-port.h | 4 +-- arch/mips/include/asm/sn/ioc3.h | 42 --- drivers/rtc/rtc-m48t35.c | 11 +++ drivers/tty/serial/8250/8250_ioc3.c | 4 +-- 4 files changed, 34 insertions(+), 27 deletions(-) diff --git a/arch/mips/include/asm/mach-ip27/mangle-port.h b/arch/mips/include/asm/mach-ip27/mangle-port.h index f6e4912ea062..27c56efa519f 100644 --- a/arch/mips/include/asm/mach-ip27/mangle-port.h +++ b/arch/mips/include/asm/mach-ip27/mangle-port.h @@ -8,7 +8,7 @@ #ifndef __ASM_MACH_IP27_MANGLE_PORT_H #define __ASM_MACH_IP27_MANGLE_PORT_H -#define __swizzle_addr_b(port) (port) +#define __swizzle_addr_b(port) ((port) ^ 3) #define __swizzle_addr_w(port) ((port) ^ 2) #define __swizzle_addr_l(port) (port) #define __swizzle_addr_q(port) (port) @@ -20,6 +20,6 @@ # define ioswabl(a, x) (x) # define __mem_ioswabl(a, x) cpu_to_le32(x) # define ioswabq(a, x) (x) -# define __mem_ioswabq(a, x) cpu_to_le32(x) +# define __mem_ioswabq(a, x) cpu_to_le64(x) #endif /* __ASM_MACH_IP27_MANGLE_PORT_H */ diff --git a/arch/mips/include/asm/sn/ioc3.h b/arch/mips/include/asm/sn/ioc3.h index 8ed952d93252..3865d3225780 100644 --- a/arch/mips/include/asm/sn/ioc3.h +++ b/arch/mips/include/asm/sn/ioc3.h @@ -21,50 +21,50 @@ struct ioc3_serialregs { /* SUPERIO uart register map */ struct ioc3_uartregs { + u8 iu_lcr; union { - u8 iu_rbr; /* read only, DLAB == 0 */ - u8 iu_thr; /* write only, DLAB == 0 */ - u8 iu_dll; /* DLAB == 1 */ + u8 iu_iir; /* read only */ + u8 iu_fcr; /* write only */ }; union { u8 iu_ier; /* DLAB == 0 */ u8 iu_dlm; /* DLAB == 1 */ }; union { - u8 iu_iir; /* read only */ - u8 iu_fcr; /* write only */ + u8 iu_rbr; /* read only, DLAB == 0 */ + u8 iu_thr; /* write only, DLAB == 0 */ + u8 iu_dll; /* DLAB == 1 */ }; - u8 iu_lcr; - u8 iu_mcr; - u8 iu_lsr; - u8 iu_msr; u8 iu_scr; + u8 iu_msr; + u8 iu_lsr; + u8 iu_mcr; }; struct ioc3_sioregs { u8 fill[0x141];/* starts at 0x141 */ - u8 uartc; u8 kbdcg; + u8 uartc; - u8 fill0[0x150 - 0x142 - 1]; + u8 fill0[0x151 - 0x142 - 1]; - u8 pp_data; - u8 pp_dsr; u8 pp_dcr; + u8 pp_dsr; + u8 pp_data; - u8 fill1[0x158 - 0x152 - 1]; + u8 fill1[0x159 - 0x153 - 1]; - u8 pp_fifa; - u8 pp_cfgb; u8 pp_ecr; + u8 pp_cfgb; + u8 pp_fifa; - u8 fill2[0x168 - 0x15a - 1]; + u8 fill2[0x16a - 0x15b - 1]; - u8 rtcad; u8 rtcdat; + u8 rtcad; - u8 fill3[0x170 - 0x169 - 1]; + u8 fill3[0x170 - 0x16b - 1]; struct ioc3_uartregsuartb; /* 0x20170 */ struct ioc3_uartregsuarta; /* 0x20178 */ @@ -590,10 +590,6 @@ struct ioc3_etxd { #define MIDR_DATA_MASK 0x -#if defined(CONFIG_SGI_IP27) || defined(CONFIG_SGI_IP30) -extern int bridge_alloc_irq(struct pci_dev *dev); -#endif - /* subsystem IDs supplied by card detection in pci-xtalk-bridge */ #defineIOC3_SUBSYS_IP27_BASEIO6G 0xc300 #defineIOC3_SUBSYS_IP27_MIO0xc301 diff --git a/drivers/rtc/rtc-m48t35.c b/drivers/rtc/rtc-m48t35.c index d3a75d447fce..e8194f1f01a8 100644 --- a/drivers/rtc/rtc-m48t35.c +++ b/drivers/rtc/rtc-m48t35.c @@ -20,6 +20,16 @@ struct m48t35_rtc { u8 pad[0x7ff8];/* starts at 0x7ff8 */ +#ifdef CONFIG_SGI_IP27 + u8 hour; + u8 min; + u8 sec; + u8 control; + u8 year; + u8 month; + u8 date; + u8 day; +#else u8 control; u8 sec; u8 min; @@ -28,6 +38,7 @@ struct m48t35_rtc { u8 date; u8 month; u8 year; +#endif }; #define M48T35_RTC_SET 0x80 diff --git a/drivers/tty/serial/8250/8250_ioc3.c b/drivers/tty/serial/8250/8250_ioc3.c index 2be6ed2967e0..4c405f1b9
[PATCH v5 05/17] MIPS: PCI: use information from 1-wire PROM for IOC3 detection
IOC3 chips in SGI system are conntected to a bridge ASIC, which has a 1-wire prom attached with part number information. This changeset uses this information to create PCI subsystem information, which the MFD driver uses for further platform device setup. Signed-off-by: Thomas Bogendoerfer --- arch/mips/include/asm/pci/bridge.h | 1 + arch/mips/include/asm/sn/ioc3.h| 9 +++ arch/mips/pci/pci-xtalk-bridge.c | 135 - arch/mips/sgi-ip27/ip27-xtalk.c| 38 +-- 4 files changed, 175 insertions(+), 8 deletions(-) diff --git a/arch/mips/include/asm/pci/bridge.h b/arch/mips/include/asm/pci/bridge.h index a92cd30b48c9..3bc630ff9ad4 100644 --- a/arch/mips/include/asm/pci/bridge.h +++ b/arch/mips/include/asm/pci/bridge.h @@ -807,6 +807,7 @@ struct bridge_controller { unsigned long intr_addr; struct irq_domain *domain; unsigned intpci_int[8]; + u32 ioc3_sid[8]; nasid_t nasid; }; diff --git a/arch/mips/include/asm/sn/ioc3.h b/arch/mips/include/asm/sn/ioc3.h index 25c8dccab51f..5022b0ab2074 100644 --- a/arch/mips/include/asm/sn/ioc3.h +++ b/arch/mips/include/asm/sn/ioc3.h @@ -661,4 +661,13 @@ typedef enum ioc3_subdevs_e { #define IOC3_INTA_SUBDEVS IOC3_SDB_ETHER #define IOC3_INTB_SUBDEVS (IOC3_SDB_GENERIC|IOC3_SDB_KBMS|IOC3_SDB_SERIAL|IOC3_SDB_ECPP|IOC3_SDB_RT) +/* subsystem IDs supplied by card detection in pci-xtalk-bridge */ +#defineIOC3_SUBSYS_IP27_BASEIO6G 0xc300 +#defineIOC3_SUBSYS_IP27_MIO0xc301 +#defineIOC3_SUBSYS_IP27_BASEIO 0xc302 +#defineIOC3_SUBSYS_IP29_SYSBOARD 0xc303 +#defineIOC3_SUBSYS_IP30_SYSBOARD 0xc304 +#defineIOC3_SUBSYS_MENET 0xc305 +#defineIOC3_SUBSYS_MENET4 0xc306 + #endif /* _IOC3_H */ diff --git a/arch/mips/pci/pci-xtalk-bridge.c b/arch/mips/pci/pci-xtalk-bridge.c index 7b4d40354ee7..dcf6117a17c3 100644 --- a/arch/mips/pci/pci-xtalk-bridge.c +++ b/arch/mips/pci/pci-xtalk-bridge.c @@ -11,16 +11,22 @@ #include #include #include +#include +#include #include #include #include +#include + +#define CRC16_INIT 0 +#define CRC16_VALID0xb001 /* * Most of the IOC3 PCI config register aren't present * we emulate what is needed for a normal PCI enumeration */ -static int ioc3_cfg_rd(void *addr, int where, int size, u32 *value) +static int ioc3_cfg_rd(void *addr, int where, int size, u32 *value, u32 sid) { u32 cf, shift, mask; @@ -30,6 +36,9 @@ static int ioc3_cfg_rd(void *addr, int where, int size, u32 *value) if (get_dbe(cf, (u32 *)addr)) return PCIBIOS_DEVICE_NOT_FOUND; break; + case 0x2c: + cf = sid; + break; case 0x3c: /* emulate sane interrupt pin value */ cf = 0x0100; @@ -111,7 +120,8 @@ static int pci_conf0_read_config(struct pci_bus *bus, unsigned int devfn, */ if (cf == (PCI_VENDOR_ID_SGI | (PCI_DEVICE_ID_SGI_IOC3 << 16))) { addr = &bridge->b_type0_cfg_dev[slot].f[fn].l[where >> 2]; - return ioc3_cfg_rd(addr, where, size, value); + return ioc3_cfg_rd(addr, where, size, value, + bc->ioc3_sid[slot]); } addr = &bridge->b_type0_cfg_dev[slot].f[fn].c[where ^ (4 - size)]; @@ -149,7 +159,8 @@ static int pci_conf1_read_config(struct pci_bus *bus, unsigned int devfn, */ if (cf == (PCI_VENDOR_ID_SGI | (PCI_DEVICE_ID_SGI_IOC3 << 16))) { addr = &bridge->b_type1_cfg.c[(fn << 8) | (where & ~3)]; - return ioc3_cfg_rd(addr, where, size, value); + return ioc3_cfg_rd(addr, where, size, value, + bc->ioc3_sid[slot]); } addr = &bridge->b_type1_cfg.c[(fn << 8) | (where ^ (4 - size))]; @@ -426,6 +437,117 @@ static int bridge_map_irq(const struct pci_dev *dev, u8 slot, u8 pin) return irq; } +#define IOC3_SID(sid) (PCI_VENDOR_ID_SGI << 16 | (sid)) + +static void bridge_setup_ip27_baseio6g(struct bridge_controller *bc) +{ + bc->ioc3_sid[2] = IOC3_SID(IOC3_SUBSYS_IP27_BASEIO6G); + bc->ioc3_sid[6] = IOC3_SID(IOC3_SUBSYS_IP27_MIO); +} + +static void bridge_setup_ip27_baseio(struct bridge_controller *bc) +{ + bc->ioc3_sid[2] = IOC3_SID(IOC3_SUBSYS_IP27_BASEIO); +} + +static void bridge_setup_ip29_baseio(struct bridge_controller *bc) +{ + bc->ioc3_sid[2] = IOC3_SID(IOC3_SUBSYS_IP29_SYSBOARD); +} + +static void bridge_setup_ip30_sysboard(struct bridge_controller *bc) +{ + bc->ioc3_sid[2] = IOC3_SID(IOC3_SUBSYS_IP30_SYSBOARD); +} + +static void bridge_setup_menet(struct bridge_controller *bc) +{ + bc->ioc3_sid[0] = IOC3_SID(IOC3_SUBSYS_MENET); + bc->ioc3_sid[1] = IOC3_SID(IOC3_SUBS
[PATCH v5 12/17] net: sgi: ioc3-eth: use dma-direct for dma allocations
Replace the homegrown DMA memory allocation, which only works on SGI-IP27 machines, with the generic dma allocations. Signed-off-by: Thomas Bogendoerfer --- drivers/net/ethernet/sgi/ioc3-eth.c | 107 ++-- 1 file changed, 77 insertions(+), 30 deletions(-) diff --git a/drivers/net/ethernet/sgi/ioc3-eth.c b/drivers/net/ethernet/sgi/ioc3-eth.c index 7f85a3bfef14..647e3926bd71 100644 --- a/drivers/net/ethernet/sgi/ioc3-eth.c +++ b/drivers/net/ethernet/sgi/ioc3-eth.c @@ -38,7 +38,6 @@ #include #include #include -#include #include #ifdef CONFIG_SERIAL_8250 @@ -51,6 +50,8 @@ #include #include #include +#include + #include #include @@ -66,10 +67,12 @@ #define RX_BUFFS 64 #define RX_RING_ENTRIES512 /* fixed in hardware */ #define RX_RING_MASK (RX_RING_ENTRIES - 1) +#define RX_RING_SIZE (RX_RING_ENTRIES * sizeof(u64)) /* 128 TX buffers (not tunable) */ #define TX_RING_ENTRIES128 #define TX_RING_MASK (TX_RING_ENTRIES - 1) +#define TX_RING_SIZE (TX_RING_ENTRIES * sizeof(struct ioc3_etxd)) /* BEWARE: The IOC3 documentation documents the size of rx buffers as * 1644 while it's actually 1664. This one was nasty to track down... @@ -84,9 +87,12 @@ struct ioc3_private { struct ioc3_ethregs *regs; struct ioc3 *all_regs; + struct device *dma_dev; u32 *ssram; unsigned long *rxr; /* pointer to receiver ring */ struct ioc3_etxd *txr; + dma_addr_t rxr_dma; + dma_addr_t txr_dma; struct sk_buff *rx_skbs[RX_RING_ENTRIES]; struct sk_buff *tx_skbs[TX_RING_ENTRIES]; int rx_ci; /* RX consumer index */ @@ -116,18 +122,22 @@ static void ioc3_init(struct net_device *dev); static const char ioc3_str[] = "IOC3 Ethernet"; static const struct ethtool_ops ioc3_ethtool_ops; -static inline unsigned long ioc3_map(void *ptr, unsigned long vdev) +#ifdef CONFIG_PCI_XTALK_BRIDGE +static inline unsigned long ioc3_map(dma_addr_t addr, unsigned long attr) { -#ifdef CONFIG_SGI_IP27 - vdev <<= 57; /* Shift to PCI64_ATTR_VIRTUAL */ + return (addr & ~PCI64_ATTR_BAR) | attr; +} - return vdev | (0xaUL << PCI64_ATTR_TARG_SHFT) | PCI64_ATTR_PREF | - ((unsigned long)ptr & TO_PHYS_MASK); +#define ERBAR_VAL (ERBAR_BARRIER_BIT << ERBAR_RXBARR_SHIFT) #else - return virt_to_bus(ptr); -#endif +static inline unsigned long ioc3_map(dma_addr_t addr, unsigned long attr) +{ + return addr; } +#define ERBAR_VAL 0 +#endif + #define IOC3_SIZE 0x10 static inline u32 mcr_pack(u32 pulse, u32 sample) @@ -494,6 +504,7 @@ static inline void ioc3_rx(struct net_device *dev) int rx_entry, n_entry, len; struct ioc3_erxbuf *rxb; unsigned long *rxr; + dma_addr_t d; u32 w0, err; rxr = ip->rxr; /* Ring base */ @@ -550,7 +561,9 @@ static inline void ioc3_rx(struct net_device *dev) dev->stats.rx_frame_errors++; next: ip->rx_skbs[n_entry] = new_skb; - rxr[n_entry] = cpu_to_be64(ioc3_map(rxb, 1)); + d = dma_map_single(ip->dma_dev, rxb, RX_BUF_SIZE, + DMA_FROM_DEVICE); + rxr[n_entry] = cpu_to_be64(ioc3_map(d, PCI64_ATTR_BAR)); rxb->w0 = 0;/* Clear valid flag */ n_entry = (n_entry + 1) & RX_RING_MASK; /* Update erpir */ @@ -754,6 +767,26 @@ static inline void ioc3_clean_rx_ring(struct ioc3_private *ip) } } +static inline void ioc3_tx_unmap(struct ioc3_private *ip, int entry) +{ + struct ioc3_etxd *desc; + u32 cmd, bufcnt, len; + + desc = &ip->txr[entry]; + cmd = be32_to_cpu(desc->cmd); + bufcnt = be32_to_cpu(desc->bufcnt); + if (cmd & ETXD_B1V) { + len = (bufcnt & ETXD_B1CNT_MASK) >> ETXD_B1CNT_SHIFT; + dma_unmap_single(ip->dma_dev, be64_to_cpu(desc->p1), +len, DMA_TO_DEVICE); + } + if (cmd & ETXD_B2V) { + len = (bufcnt & ETXD_B2CNT_MASK) >> ETXD_B2CNT_SHIFT; + dma_unmap_single(ip->dma_dev, be64_to_cpu(desc->p2), +len, DMA_TO_DEVICE); + } +} + static inline void ioc3_clean_tx_ring(struct ioc3_private *ip) { struct sk_buff *skb; @@ -762,6 +795,7 @@ static inline void ioc3_clean_tx_ring(struct ioc3_private *ip) for (i = 0; i < TX_RING_ENTRIES; i++) { skb = ip->tx_skbs[i]; if (skb) { + ioc3_tx_unmap(ip, i); ip->tx_skbs[i] = NULL; dev_kfree_skb_any(skb); } @@ -778,7 +812,8 @@ static void ioc3_free_rings(struct ioc3_private *ip) if (ip->txr) { ioc3_clean_tx_ring(ip); -
[PATCH v5 14/17] net: sgi: ioc3-eth: Fix IPG settings
The half/full duplex settings for inter packet gap counters/timer were reversed. Signed-off-by: Thomas Bogendoerfer --- drivers/net/ethernet/sgi/ioc3-eth.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/sgi/ioc3-eth.c b/drivers/net/ethernet/sgi/ioc3-eth.c index 56392f0b01de..25597c6194d9 100644 --- a/drivers/net/ethernet/sgi/ioc3-eth.c +++ b/drivers/net/ethernet/sgi/ioc3-eth.c @@ -80,8 +80,8 @@ #define RX_OFFSET 10 #define RX_BUF_SIZE1664 -#define ETCSR_FD ((17 << ETCSR_IPGR2_SHIFT) | (11 << ETCSR_IPGR1_SHIFT) | 21) -#define ETCSR_HD ((21 << ETCSR_IPGR2_SHIFT) | (21 << ETCSR_IPGR1_SHIFT) | 21) +#define ETCSR_FD ((21 << ETCSR_IPGR2_SHIFT) | (21 << ETCSR_IPGR1_SHIFT) | 21) +#define ETCSR_HD ((17 << ETCSR_IPGR2_SHIFT) | (11 << ETCSR_IPGR1_SHIFT) | 21) /* Private per NIC data of the driver. */ struct ioc3_private { -- 2.13.7
[PATCH v5 09/17] net: sgi: ioc3-eth: use defines for constants dealing with desc rings
Descriptor ring sizes of the IOC3 are more or less fixed size. To make clearer where there is a relation to ring sizes use defines. Signed-off-by: Thomas Bogendoerfer --- drivers/net/ethernet/sgi/ioc3-eth.c | 42 + 1 file changed, 24 insertions(+), 18 deletions(-) diff --git a/drivers/net/ethernet/sgi/ioc3-eth.c b/drivers/net/ethernet/sgi/ioc3-eth.c index e81e5bb37ac6..c875640926d6 100644 --- a/drivers/net/ethernet/sgi/ioc3-eth.c +++ b/drivers/net/ethernet/sgi/ioc3-eth.c @@ -61,10 +61,16 @@ #include #include -/* 64 RX buffers. This is tunable in the range of 16 <= x < 512. The - * value must be a power of two. +/* Number of RX buffers. This is tunable in the range of 16 <= x < 512. + * The value must be a power of two. */ -#define RX_BUFFS 64 +#define RX_BUFFS 64 +#define RX_RING_ENTRIES512 /* fixed in hardware */ +#define RX_RING_MASK (RX_RING_ENTRIES - 1) + +/* 128 TX buffers (not tunable) */ +#define TX_RING_ENTRIES128 +#define TX_RING_MASK (TX_RING_ENTRIES - 1) #define ETCSR_FD ((17 << ETCSR_IPGR2_SHIFT) | (11 << ETCSR_IPGR1_SHIFT) | 21) #define ETCSR_HD ((21 << ETCSR_IPGR2_SHIFT) | (21 << ETCSR_IPGR1_SHIFT) | 21) @@ -76,8 +82,8 @@ struct ioc3_private { u32 *ssram; unsigned long *rxr; /* pointer to receiver ring */ struct ioc3_etxd *txr; - struct sk_buff *rx_skbs[512]; - struct sk_buff *tx_skbs[128]; + struct sk_buff *rx_skbs[RX_RING_ENTRIES]; + struct sk_buff *tx_skbs[TX_RING_ENTRIES]; int rx_ci; /* RX consumer index */ int rx_pi; /* RX producer index */ int tx_ci; /* TX consumer index */ @@ -573,10 +579,10 @@ static inline void ioc3_rx(struct net_device *dev) ip->rx_skbs[n_entry] = new_skb; rxr[n_entry] = cpu_to_be64(ioc3_map(rxb, 1)); rxb->w0 = 0;/* Clear valid flag */ - n_entry = (n_entry + 1) & 511; /* Update erpir */ + n_entry = (n_entry + 1) & RX_RING_MASK; /* Update erpir */ /* Now go on to the next ring entry. */ - rx_entry = (rx_entry + 1) & 511; + rx_entry = (rx_entry + 1) & RX_RING_MASK; skb = ip->rx_skbs[rx_entry]; rxb = (struct ioc3_erxbuf *)(skb->data - RX_OFFSET); w0 = be32_to_cpu(rxb->w0); @@ -598,7 +604,7 @@ static inline void ioc3_tx(struct net_device *dev) spin_lock(&ip->ioc3_lock); etcir = readl(®s->etcir); - tx_entry = (etcir >> 7) & 127; + tx_entry = (etcir >> 7) & TX_RING_MASK; o_entry = ip->tx_ci; packets = 0; bytes = 0; @@ -610,17 +616,17 @@ static inline void ioc3_tx(struct net_device *dev) dev_consume_skb_irq(skb); ip->tx_skbs[o_entry] = NULL; - o_entry = (o_entry + 1) & 127; /* Next */ + o_entry = (o_entry + 1) & TX_RING_MASK; /* Next */ etcir = readl(®s->etcir);/* More pkts sent? */ - tx_entry = (etcir >> 7) & 127; + tx_entry = (etcir >> 7) & TX_RING_MASK; } dev->stats.tx_packets += packets; dev->stats.tx_bytes += bytes; ip->txqlen -= packets; - if (ip->txqlen < 128) + if (netif_queue_stopped(dev) && ip->txqlen < TX_RING_ENTRIES) netif_wake_queue(dev); ip->tx_ci = o_entry; @@ -765,10 +771,10 @@ static inline void ioc3_clean_rx_ring(struct ioc3_private *ip) ip->rx_skbs[ip->rx_pi] = ip->rx_skbs[ip->rx_ci]; ip->rxr[ip->rx_pi++] = ip->rxr[ip->rx_ci++]; } - ip->rx_pi &= 511; - ip->rx_ci &= 511; + ip->rx_pi &= RX_RING_MASK; + ip->rx_ci &= RX_RING_MASK; - for (i = ip->rx_ci; i != ip->rx_pi; i = (i + 1) & 511) { + for (i = ip->rx_ci; i != ip->rx_pi; i = (i + 1) & RX_RING_MASK) { skb = ip->rx_skbs[i]; rxb = (struct ioc3_erxbuf *)(skb->data - RX_OFFSET); rxb->w0 = 0; @@ -780,7 +786,7 @@ static inline void ioc3_clean_tx_ring(struct ioc3_private *ip) struct sk_buff *skb; int i; - for (i = 0; i < 128; i++) { + for (i = 0; i < TX_RING_ENTRIES; i++) { skb = ip->tx_skbs[i]; if (skb) { ip->tx_skbs[i] = NULL; @@ -812,7 +818,7 @@ static void ioc3_free_rings(struct ioc3_private *ip) if (skb) dev_kfree_skb_any(skb); - n_entry = (n_entry + 1) & 511; + n_entry = (n_entry + 1) & RX_RING_MASK; } free_page((unsigned long)ip->rxr); ip->rxr = NULL; @@ -1425,13 +1431,13 @@ static netdev_tx_t ioc3_start_xmit(
[PATCH v5 07/17] MIPS: SGI-IP27: restructure ioc3 register access
Break up the big ioc3 register struct into functional pieces to make use in sub-function drivers more straightforward. And while doing that get rid of all volatile access by using readX/writeX. Signed-off-by: Thomas Bogendoerfer --- arch/mips/include/asm/sn/ioc3.h | 359 +-- arch/mips/sgi-ip27/ip27-console.c | 5 +- drivers/net/ethernet/sgi/ioc3-eth.c | 418 3 files changed, 334 insertions(+), 448 deletions(-) diff --git a/arch/mips/include/asm/sn/ioc3.h b/arch/mips/include/asm/sn/ioc3.h index 5022b0ab2074..8ed952d93252 100644 --- a/arch/mips/include/asm/sn/ioc3.h +++ b/arch/mips/include/asm/sn/ioc3.h @@ -3,169 +3,161 @@ * Copyright (C) 1999, 2000 Ralf Baechle * Copyright (C) 1999, 2000 Silicon Graphics, Inc. */ -#ifndef _IOC3_H -#define _IOC3_H +#ifndef MIPS_SN_IOC3_H +#define MIPS_SN_IOC3_H #include +/* serial port register map */ +struct ioc3_serialregs { + u32 sscr; + u32 stpir; + u32 stcir; + u32 srpir; + u32 srcir; + u32 srtr; + u32 shadow; +}; + /* SUPERIO uart register map */ -typedef volatile struct ioc3_uartregs { +struct ioc3_uartregs { union { - volatile u8 rbr;/* read only, DLAB == 0 */ - volatile u8 thr;/* write only, DLAB == 0 */ - volatile u8 dll;/* DLAB == 1 */ - } u1; + u8 iu_rbr; /* read only, DLAB == 0 */ + u8 iu_thr; /* write only, DLAB == 0 */ + u8 iu_dll; /* DLAB == 1 */ + }; union { - volatile u8 ier;/* DLAB == 0 */ - volatile u8 dlm;/* DLAB == 1 */ - } u2; + u8 iu_ier; /* DLAB == 0 */ + u8 iu_dlm; /* DLAB == 1 */ + }; union { - volatile u8 iir;/* read only */ - volatile u8 fcr;/* write only */ - } u3; - volatile u8 iu_lcr; - volatile u8 iu_mcr; - volatile u8 iu_lsr; - volatile u8 iu_msr; - volatile u8 iu_scr; -} ioc3_uregs_t; - -#define iu_rbr u1.rbr -#define iu_thr u1.thr -#define iu_dll u1.dll -#define iu_ier u2.ier -#define iu_dlm u2.dlm -#define iu_iir u3.iir -#define iu_fcr u3.fcr + u8 iu_iir; /* read only */ + u8 iu_fcr; /* write only */ + }; + u8 iu_lcr; + u8 iu_mcr; + u8 iu_lsr; + u8 iu_msr; + u8 iu_scr; +}; struct ioc3_sioregs { - volatile u8 fill[0x141];/* starts at 0x141 */ + u8 fill[0x141];/* starts at 0x141 */ - volatile u8 uartc; - volatile u8 kbdcg; + u8 uartc; + u8 kbdcg; - volatile u8 fill0[0x150 - 0x142 - 1]; + u8 fill0[0x150 - 0x142 - 1]; - volatile u8 pp_data; - volatile u8 pp_dsr; - volatile u8 pp_dcr; + u8 pp_data; + u8 pp_dsr; + u8 pp_dcr; - volatile u8 fill1[0x158 - 0x152 - 1]; + u8 fill1[0x158 - 0x152 - 1]; - volatile u8 pp_fifa; - volatile u8 pp_cfgb; - volatile u8 pp_ecr; + u8 pp_fifa; + u8 pp_cfgb; + u8 pp_ecr; - volatile u8 fill2[0x168 - 0x15a - 1]; + u8 fill2[0x168 - 0x15a - 1]; - volatile u8 rtcad; - volatile u8 rtcdat; + u8 rtcad; + u8 rtcdat; - volatile u8 fill3[0x170 - 0x169 - 1]; + u8 fill3[0x170 - 0x169 - 1]; struct ioc3_uartregsuartb; /* 0x20170 */ struct ioc3_uartregsuarta; /* 0x20178 */ }; +struct ioc3_ethregs { + u32 emcr; /* 0x000f0 */ + u32 eisr; /* 0x000f4 */ + u32 eier; /* 0x000f8 */ + u32 ercsr; /* 0x000fc */ + u32 erbr_h; /* 0x00100 */ + u32 erbr_l; /* 0x00104 */ + u32 erbar; /* 0x00108 */ + u32 ercir; /* 0x0010c */ + u32 erpir; /* 0x00110 */ + u32 ertr; /* 0x00114 */ + u32 etcsr; /* 0x00118 */ + u32 ersr; /* 0x0011c */ + u32 etcdc; /* 0x00120 */ + u32 ebir; /* 0x00124 */ + u32 etbr_h; /* 0x00128 */ + u32 etbr_l; /* 0x0012c */ + u32 etcir; /* 0x00130 */ + u32 etpir; /* 0x00134 */ + u32 emar_h; /* 0x00138 */ + u32 emar_l; /* 0x0013c */ + u32 ehar_h; /* 0x00140 */ + u32 ehar_l; /* 0x00144 */ + u32
[PATCH v5 10/17] net: sgi: ioc3-eth: rework skb rx handling
Buffers alloacted by alloc_skb() are already cache aligned so there is no need for an extra align done by ioc3_alloc_skb. And instead of skb_put/skb_trim simply use one skb_put after frame size is known during receive. Signed-off-by: Thomas Bogendoerfer --- drivers/net/ethernet/sgi/ioc3-eth.c | 50 - 1 file changed, 11 insertions(+), 39 deletions(-) diff --git a/drivers/net/ethernet/sgi/ioc3-eth.c b/drivers/net/ethernet/sgi/ioc3-eth.c index c875640926d6..d862f28887f9 100644 --- a/drivers/net/ethernet/sgi/ioc3-eth.c +++ b/drivers/net/ethernet/sgi/ioc3-eth.c @@ -11,7 +11,6 @@ * * To do: * - * o Handle allocation failures in ioc3_alloc_skb() more gracefully. * o Handle allocation failures in ioc3_init_rings(). * o Use prefetching for large packets. What is a good lower limit for *prefetching? @@ -72,6 +71,12 @@ #define TX_RING_ENTRIES128 #define TX_RING_MASK (TX_RING_ENTRIES - 1) +/* BEWARE: The IOC3 documentation documents the size of rx buffers as + * 1644 while it's actually 1664. This one was nasty to track down... + */ +#define RX_OFFSET 10 +#define RX_BUF_SIZE1664 + #define ETCSR_FD ((17 << ETCSR_IPGR2_SHIFT) | (11 << ETCSR_IPGR1_SHIFT) | 21) #define ETCSR_HD ((21 << ETCSR_IPGR2_SHIFT) | (21 << ETCSR_IPGR1_SHIFT) | 21) @@ -111,31 +116,6 @@ static void ioc3_init(struct net_device *dev); static const char ioc3_str[] = "IOC3 Ethernet"; static const struct ethtool_ops ioc3_ethtool_ops; -/* We use this to acquire receive skb's that we can DMA directly into. */ - -#define IOC3_CACHELINE 128UL - -static inline unsigned long aligned_rx_skb_addr(unsigned long addr) -{ - return (~addr + 1) & (IOC3_CACHELINE - 1UL); -} - -static inline struct sk_buff *ioc3_alloc_skb(unsigned long length, -unsigned int gfp_mask) -{ - struct sk_buff *skb; - - skb = alloc_skb(length + IOC3_CACHELINE - 1, gfp_mask); - if (likely(skb)) { - int offset = aligned_rx_skb_addr((unsigned long)skb->data); - - if (offset) - skb_reserve(skb, offset); - } - - return skb; -} - static inline unsigned long ioc3_map(void *ptr, unsigned long vdev) { #ifdef CONFIG_SGI_IP27 @@ -148,12 +128,6 @@ static inline unsigned long ioc3_map(void *ptr, unsigned long vdev) #endif } -/* BEWARE: The IOC3 documentation documents the size of rx buffers as - * 1644 while it's actually 1664. This one was nasty to track down ... - */ -#define RX_OFFSET 10 -#define RX_BUF_ALLOC_SIZE (1664 + RX_OFFSET + IOC3_CACHELINE) - #define IOC3_SIZE 0x10 static inline u32 mcr_pack(u32 pulse, u32 sample) @@ -534,10 +508,10 @@ static inline void ioc3_rx(struct net_device *dev) err = be32_to_cpu(rxb->err);/* It's valid ... */ if (err & ERXBUF_GOODPKT) { len = ((w0 >> ERXBUF_BYTECNT_SHIFT) & 0x7ff) - 4; - skb_trim(skb, len); + skb_put(skb, len); skb->protocol = eth_type_trans(skb, dev); - new_skb = ioc3_alloc_skb(RX_BUF_ALLOC_SIZE, GFP_ATOMIC); + new_skb = alloc_skb(RX_BUF_SIZE, GFP_ATOMIC); if (!new_skb) { /* Ouch, drop packet and just recycle packet * to keep the ring filled. @@ -546,6 +520,7 @@ static inline void ioc3_rx(struct net_device *dev) new_skb = skb; goto next; } + new_skb->dev = dev; if (likely(dev->features & NETIF_F_RXCSUM)) ioc3_tcpudp_checksum(skb, @@ -556,8 +531,6 @@ static inline void ioc3_rx(struct net_device *dev) ip->rx_skbs[rx_entry] = NULL; /* Poison */ - /* Because we reserve afterwards. */ - skb_put(new_skb, (1664 + RX_OFFSET)); rxb = (struct ioc3_erxbuf *)new_skb->data; skb_reserve(new_skb, RX_OFFSET); @@ -846,16 +819,15 @@ static void ioc3_alloc_rings(struct net_device *dev) for (i = 0; i < RX_BUFFS; i++) { struct sk_buff *skb; - skb = ioc3_alloc_skb(RX_BUF_ALLOC_SIZE, GFP_ATOMIC); + skb = alloc_skb(RX_BUF_SIZE, GFP_ATOMIC); if (!skb) { show_free_areas(0, NULL); continue; } + skb->dev = dev; ip->rx_skbs[i] = skb; - /* Because we reserve afterwards. */ - skb_put(skb, (1664 + RX_OFFSET)); rxb = (struct ioc3_er
[PATCH v5 11/17] net: sgi: ioc3-eth: no need to stop queue set_multicast_list
netif_stop_queue()/netif_wake_qeue() aren't needed for changing multicast filters. Use spinlocks instead for proper protection of private struct. Signed-off-by: Thomas Bogendoerfer --- drivers/net/ethernet/sgi/ioc3-eth.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/net/ethernet/sgi/ioc3-eth.c b/drivers/net/ethernet/sgi/ioc3-eth.c index d862f28887f9..7f85a3bfef14 100644 --- a/drivers/net/ethernet/sgi/ioc3-eth.c +++ b/drivers/net/ethernet/sgi/ioc3-eth.c @@ -1542,8 +1542,7 @@ static void ioc3_set_multicast_list(struct net_device *dev) struct netdev_hw_addr *ha; u64 ehar = 0; - netif_stop_queue(dev); /* Lock out others. */ - + spin_lock_irq(&ip->ioc3_lock); if (dev->flags & IFF_PROMISC) { /* Set promiscuous. */ ip->emcr |= EMCR_PROMISC; writel(ip->emcr, ®s->emcr); @@ -1572,7 +1571,7 @@ static void ioc3_set_multicast_list(struct net_device *dev) writel(ip->ehar_l, ®s->ehar_l); } - netif_wake_queue(dev); /* Let us get going again. */ + spin_unlock_irq(&ip->ioc3_lock); } module_pci_driver(ioc3_driver); -- 2.13.7
[PATCH v5 04/17] MIPS: PCI: refactor ioc3 special handling
Refactored code to only have one ioc3 special handling for read access and one for write access. Signed-off-by: Thomas Bogendoerfer --- arch/mips/pci/pci-xtalk-bridge.c | 167 +++ 1 file changed, 62 insertions(+), 105 deletions(-) diff --git a/arch/mips/pci/pci-xtalk-bridge.c b/arch/mips/pci/pci-xtalk-bridge.c index bcf7f559789a..7b4d40354ee7 100644 --- a/arch/mips/pci/pci-xtalk-bridge.c +++ b/arch/mips/pci/pci-xtalk-bridge.c @@ -20,16 +20,50 @@ * Most of the IOC3 PCI config register aren't present * we emulate what is needed for a normal PCI enumeration */ -static u32 emulate_ioc3_cfg(int where, int size) +static int ioc3_cfg_rd(void *addr, int where, int size, u32 *value) { - if (size == 1 && where == 0x3d) - return 0x01; - else if (size == 2 && where == 0x3c) - return 0x0100; - else if (size == 4 && where == 0x3c) - return 0x0100; + u32 cf, shift, mask; - return 0; + switch (where & ~3) { + case 0x00 ... 0x10: + case 0x40 ... 0x44: + if (get_dbe(cf, (u32 *)addr)) + return PCIBIOS_DEVICE_NOT_FOUND; + break; + case 0x3c: + /* emulate sane interrupt pin value */ + cf = 0x0100; + break; + default: + cf = 0; + break; + } + shift = (where & 3) << 3; + mask = 0xU >> ((4 - size) << 3); + *value = (cf >> shift) & mask; + + return PCIBIOS_SUCCESSFUL; +} + +static int ioc3_cfg_wr(void *addr, int where, int size, u32 value) +{ + u32 cf, shift, mask, smask; + + if ((where >= 0x14 && where < 0x40) || (where >= 0x48)) + return PCIBIOS_SUCCESSFUL; + + if (get_dbe(cf, (u32 *)addr)) + return PCIBIOS_DEVICE_NOT_FOUND; + + shift = ((where & 3) << 3); + mask = (0xU >> ((4 - size) << 3)); + smask = mask << shift; + + cf = (cf & ~smask) | ((value & mask) << shift); + if (put_dbe(cf, (u32 *)addr)) + return PCIBIOS_DEVICE_NOT_FOUND; + + return PCIBIOS_SUCCESSFUL; } static void bridge_disable_swapping(struct pci_dev *dev) @@ -64,7 +98,7 @@ static int pci_conf0_read_config(struct pci_bus *bus, unsigned int devfn, int slot = PCI_SLOT(devfn); int fn = PCI_FUNC(devfn); void *addr; - u32 cf, shift, mask; + u32 cf; int res; addr = &bridge->b_type0_cfg_dev[slot].f[fn].c[PCI_VENDOR_ID]; @@ -75,8 +109,10 @@ static int pci_conf0_read_config(struct pci_bus *bus, unsigned int devfn, * IOC3 is broken beyond belief ... Don't even give the * generic PCI code a chance to look at it for real ... */ - if (cf == (PCI_VENDOR_ID_SGI | (PCI_DEVICE_ID_SGI_IOC3 << 16))) - goto is_ioc3; + if (cf == (PCI_VENDOR_ID_SGI | (PCI_DEVICE_ID_SGI_IOC3 << 16))) { + addr = &bridge->b_type0_cfg_dev[slot].f[fn].l[where >> 2]; + return ioc3_cfg_rd(addr, where, size, value); + } addr = &bridge->b_type0_cfg_dev[slot].f[fn].c[where ^ (4 - size)]; @@ -88,26 +124,6 @@ static int pci_conf0_read_config(struct pci_bus *bus, unsigned int devfn, res = get_dbe(*value, (u32 *)addr); return res ? PCIBIOS_DEVICE_NOT_FOUND : PCIBIOS_SUCCESSFUL; - -is_ioc3: - - /* -* IOC3 special handling -*/ - if ((where >= 0x14 && where < 0x40) || (where >= 0x48)) { - *value = emulate_ioc3_cfg(where, size); - return PCIBIOS_SUCCESSFUL; - } - - addr = &bridge->b_type0_cfg_dev[slot].f[fn].l[where >> 2]; - if (get_dbe(cf, (u32 *)addr)) - return PCIBIOS_DEVICE_NOT_FOUND; - - shift = ((where & 3) << 3); - mask = (0xU >> ((4 - size) << 3)); - *value = (cf >> shift) & mask; - - return PCIBIOS_SUCCESSFUL; } static int pci_conf1_read_config(struct pci_bus *bus, unsigned int devfn, @@ -119,7 +135,7 @@ static int pci_conf1_read_config(struct pci_bus *bus, unsigned int devfn, int slot = PCI_SLOT(devfn); int fn = PCI_FUNC(devfn); void *addr; - u32 cf, shift, mask; + u32 cf; int res; bridge_write(bc, b_pci_cfg, (busno << 16) | (slot << 11)); @@ -131,8 +147,10 @@ static int pci_conf1_read_config(struct pci_bus *bus, unsigned int devfn, * IOC3 is broken beyond belief ... Don't even give the * generic PCI code a chance to look at it for real ... */ - if (cf == (PCI_VENDOR_ID_SGI | (PCI_DEVICE_ID_SGI_IOC3 << 16))) - goto is_ioc3; + if (cf == (PCI_VENDOR_ID_SGI | (PCI_DEVICE_ID_SGI_IOC3 << 16))) { + addr = &bridge->b_type1_cfg.c[(fn << 8) | (where & ~3)]; + return ioc3_cfg_rd(addr, where, size, value); + } addr = &bridge->b_type1_cfg.c[(fn << 8) |
[PATCH v5 03/17] nvmem: core: add nvmem_device_find
nvmem_device_find provides a way to search for nvmem devices with the help of a match function simlair to bus_find_device. Signed-off-by: Thomas Bogendoerfer --- Documentation/driver-api/nvmem.rst | 2 ++ drivers/nvmem/core.c | 62 -- include/linux/nvmem-consumer.h | 9 ++ 3 files changed, 43 insertions(+), 30 deletions(-) diff --git a/Documentation/driver-api/nvmem.rst b/Documentation/driver-api/nvmem.rst index d9d958d5c824..287e86819640 100644 --- a/Documentation/driver-api/nvmem.rst +++ b/Documentation/driver-api/nvmem.rst @@ -129,6 +129,8 @@ To facilitate such consumers NVMEM framework provides below apis:: struct nvmem_device *nvmem_device_get(struct device *dev, const char *name); struct nvmem_device *devm_nvmem_device_get(struct device *dev, const char *name); + struct nvmem_device *nvmem_device_find(void *data, + int (*match)(struct device *dev, const void *data)); void nvmem_device_put(struct nvmem_device *nvmem); int nvmem_device_read(struct nvmem_device *nvmem, unsigned int offset, size_t bytes, void *buf); diff --git a/drivers/nvmem/core.c b/drivers/nvmem/core.c index ac5d945be88a..e591ba54758f 100644 --- a/drivers/nvmem/core.c +++ b/drivers/nvmem/core.c @@ -76,36 +76,18 @@ static struct bus_type nvmem_bus_type = { .name = "nvmem", }; +#if IS_ENABLED(CONFIG_OF) static int of_nvmem_match(struct device *dev, const void *nvmem_np) { return dev->of_node == nvmem_np; } +#endif -static struct nvmem_device *of_nvmem_find(struct device_node *nvmem_np) +static int nvmem_match_name(struct device *dev, const void *data) { - struct device *d; - - if (!nvmem_np) - return NULL; - - d = bus_find_device(&nvmem_bus_type, NULL, nvmem_np, of_nvmem_match); - - if (!d) - return NULL; + const char *name = data; - return to_nvmem_device(d); -} - -static struct nvmem_device *nvmem_find(const char *name) -{ - struct device *d; - - d = bus_find_device_by_name(&nvmem_bus_type, NULL, name); - - if (!d) - return NULL; - - return to_nvmem_device(d); + return sysfs_streq(name, dev_name(dev)); } static void nvmem_cell_drop(struct nvmem_cell *cell) @@ -537,13 +519,16 @@ int devm_nvmem_unregister(struct device *dev, struct nvmem_device *nvmem) } EXPORT_SYMBOL(devm_nvmem_unregister); -static struct nvmem_device *__nvmem_device_get(struct device_node *np, - const char *nvmem_name) +static struct nvmem_device *__nvmem_device_get(void *data, + int (*match)(struct device *dev, const void *data)) { struct nvmem_device *nvmem = NULL; + struct device *dev; mutex_lock(&nvmem_mutex); - nvmem = np ? of_nvmem_find(np) : nvmem_find(nvmem_name); + dev = bus_find_device(&nvmem_bus_type, NULL, data, match); + if (dev) + nvmem = to_nvmem_device(dev); mutex_unlock(&nvmem_mutex); if (!nvmem) return ERR_PTR(-EPROBE_DEFER); @@ -592,7 +577,7 @@ struct nvmem_device *of_nvmem_device_get(struct device_node *np, const char *id) if (!nvmem_np) return ERR_PTR(-ENOENT); - return __nvmem_device_get(nvmem_np, NULL); + return __nvmem_device_get(nvmem_np, of_nvmem_match); } EXPORT_SYMBOL_GPL(of_nvmem_device_get); #endif @@ -618,10 +603,26 @@ struct nvmem_device *nvmem_device_get(struct device *dev, const char *dev_name) } - return __nvmem_device_get(NULL, dev_name); + return __nvmem_device_get((void *)dev_name, nvmem_match_name); } EXPORT_SYMBOL_GPL(nvmem_device_get); +/** + * nvmem_device_find() - Find nvmem device with matching function + * + * @data: Data to pass to match function + * @match: Callback function to check device + * + * Return: ERR_PTR() on error or a valid pointer to a struct nvmem_device + * on success. + */ +struct nvmem_device *nvmem_device_find(void *data, + int (*match)(struct device *dev, const void *data)) +{ + return __nvmem_device_get(data, match); +} +EXPORT_SYMBOL_GPL(nvmem_device_find); + static int devm_nvmem_device_match(struct device *dev, void *res, void *data) { struct nvmem_device **nvmem = res; @@ -715,7 +716,8 @@ nvmem_cell_get_from_lookup(struct device *dev, const char *con_id) if ((strcmp(lookup->dev_id, dev_id) == 0) && (strcmp(lookup->con_id, con_id) == 0)) { /* This is the right entry. */ - nvmem = __nvmem_device_get(NULL, lookup->nvmem_name); + nvmem = __nvmem_device_get((void *)lookup->nvmem_name, + nvmem_match_name); if (IS_ERR(nvmem)) {
Re: [PATCH v7 3/7] of/platform: Add functional dependency link from DT bindings
On 8/15/19 6:50 PM, Saravana Kannan wrote: > On Wed, Aug 7, 2019 at 7:06 PM Frank Rowand wrote: >> >> On 7/23/19 5:10 PM, Saravana Kannan wrote: >>> Add device-links after the devices are created (but before they are >>> probed) by looking at common DT bindings like clocks and >>> interconnects. < very big snip (lots of comments that deserve answers) > >> >> /** >> * of_link_property - TODO: >> * dev: >> * con_np: >> * prop: >> * >> * TODO... >> * >> * Any failed attempt to create a link will NOT result in an immediate >> return. >> * of_link_property() must create all possible links even when one of more >> * attempts to create a link fail. >> >> Why? isn't one failure enough to prevent probing this device? >> Continuing to scan just results in extra work... which will be >> repeated every time device_link_check_waiting_consumers() is called > > Context: > As I said in the cover letter, avoiding unnecessary probes is just one > of the reasons for this patch. The other (arguably more important) Agree that it is more important. > reason for this patch is to make sure suppliers know that they have > consumers that are yet to be probed. That way, suppliers can leave > their resource on AND in the right state if they were left on by the > bootloader. For example, if a clock was left on and at 200 MHz, the > clock provider needs to keep that clock ON and at 200 MHz till all the > consumers are probed. > > Answer: Let's say a consumer device Z has suppliers A, B and C. If the > linking fails at A and you return immediately, then B and C could > probe and then figure that they have no more consumers (they don't see > a link to Z) and turn off their resources. And Z could fail > catastrophically. Then I think that this approach is fatally flawed in the current implementation. A device can be added by a module that is loaded. In that case the device was not present at late boot when the suppliers may turn off their resources. (I am assuming the details since I have not reviewed the patches later in the series that implement this part.) Am I missing something? If I am wrong, then I'll have more comments for your review replies for patches 2 and 3. > < another snip > > Thanks, > Saravana > -Frank
Re: [PATCH] Documentation PCI: Fix pciebus-howto.rst filename typo
On Fri, Aug 16, 2019 at 08:53:58AM -0500, Bjorn Helgaas wrote: > From: Bjorn Helgaas > > 2e6422444894 ("Documentation: PCI: convert PCIEBUS-HOWTO.txt to reST") > incorrectly renamed PCIEBUS-HOWTO.txt to picebus-howto.rst. > > Rename it to pciebus-howto.rst. > > Fixes: 2e6422444894 ("Documentation: PCI: convert PCIEBUS-HOWTO.txt to reST") > Signed-off-by: Bjorn Helgaas > --- > Documentation/PCI/index.rst| 2 +- > Documentation/PCI/{picebus-howto.rst => pciebus-howto.rst} | 0 > 2 files changed, 1 insertion(+), 1 deletion(-) > rename Documentation/PCI/{picebus-howto.rst => pciebus-howto.rst} (100%) I merged the commit that added this typo (2e6422444894), so I applied this fix to my for-linus branch for v5.3. > diff --git a/Documentation/PCI/index.rst b/Documentation/PCI/index.rst > index f4c6121868c3..6768305e4c26 100644 > --- a/Documentation/PCI/index.rst > +++ b/Documentation/PCI/index.rst > @@ -9,7 +9,7 @@ Linux PCI Bus Subsystem > :numbered: > > pci > - picebus-howto > + pciebus-howto > pci-iov-howto > msi-howto > acpi-info > diff --git a/Documentation/PCI/picebus-howto.rst > b/Documentation/PCI/pciebus-howto.rst > similarity index 100% > rename from Documentation/PCI/picebus-howto.rst > rename to Documentation/PCI/pciebus-howto.rst > -- > 2.23.0.rc1.153.gdeed80330f-goog >
Re: [PATCH v7 3/7] of/platform: Add functional dependency link from DT bindings
On Mon, Aug 19, 2019 at 10:16 AM Frank Rowand wrote: > > On 8/15/19 6:50 PM, Saravana Kannan wrote: > > On Wed, Aug 7, 2019 at 7:06 PM Frank Rowand wrote: > >> > >> On 7/23/19 5:10 PM, Saravana Kannan wrote: > >>> Add device-links after the devices are created (but before they are > >>> probed) by looking at common DT bindings like clocks and > >>> interconnects. > > > < very big snip (lots of comments that deserve answers) > > > > >> > >> /** > >> * of_link_property - TODO: > >> * dev: > >> * con_np: > >> * prop: > >> * > >> * TODO... > >> * > >> * Any failed attempt to create a link will NOT result in an immediate > >> return. > >> * of_link_property() must create all possible links even when one of more > >> * attempts to create a link fail. > >> > >> Why? isn't one failure enough to prevent probing this device? > >> Continuing to scan just results in extra work... which will be > >> repeated every time device_link_check_waiting_consumers() is called > > > > Context: > > As I said in the cover letter, avoiding unnecessary probes is just one > > of the reasons for this patch. The other (arguably more important) > > Agree that it is more important. > > > > reason for this patch is to make sure suppliers know that they have > > consumers that are yet to be probed. That way, suppliers can leave > > their resource on AND in the right state if they were left on by the > > bootloader. For example, if a clock was left on and at 200 MHz, the > > clock provider needs to keep that clock ON and at 200 MHz till all the > > consumers are probed. > > > > Answer: Let's say a consumer device Z has suppliers A, B and C. If the > > linking fails at A and you return immediately, then B and C could > > probe and then figure that they have no more consumers (they don't see > > a link to Z) and turn off their resources. And Z could fail > > catastrophically. > > Then I think that this approach is fatally flawed in the current > implementation. I'm waiting to hear how it is fatally flawed. But maybe this is just a misunderstanding of the problem? In the text below, I'm not sure if you mixing up two different things or just that your wording it a bit ambiguous. So pardon my nitpick to err on the side of clarity. > A device can be added by a module that is loaded. No, in the example I gave, of_platform_default_populate_init() would add all 3 of those devices during arch_initcall_sync(). > In that case the device > was not present at late boot when the suppliers may turn off their resources. In that case, the _drivers_ for those devices aren't present at late boot. So that they can't request to keep the resources on for their consumer devices. Since there are no consumer requests on resources, the suppliers turn off their resources at late boot (since there isn't a better location as of today). The sync_state() call back added in a subsequent patche in this series will provide the better location. > (I am assuming the details since I have not reviewed the patches later in > the series that implement this part.) > > Am I missing something? I think you are mixing up devices getting added/populated with drivers getting loaded as modules? > If I am wrong, then I'll have more comments for your review replies for > patches 2 and 3. I'll wait for more review replies? Thanks, Saravana
Re: [PATCH v7 3/7] of/platform: Add functional dependency link from DT bindings
On 8/19/19 1:49 PM, Saravana Kannan wrote: > On Mon, Aug 19, 2019 at 10:16 AM Frank Rowand wrote: >> >> On 8/15/19 6:50 PM, Saravana Kannan wrote: >>> On Wed, Aug 7, 2019 at 7:06 PM Frank Rowand wrote: On 7/23/19 5:10 PM, Saravana Kannan wrote: > Add device-links after the devices are created (but before they are > probed) by looking at common DT bindings like clocks and > interconnects. >> >> >> < very big snip (lots of comments that deserve answers) > >> >> /** * of_link_property - TODO: * dev: * con_np: * prop: * * TODO... * * Any failed attempt to create a link will NOT result in an immediate return. * of_link_property() must create all possible links even when one of more * attempts to create a link fail. Why? isn't one failure enough to prevent probing this device? Continuing to scan just results in extra work... which will be repeated every time device_link_check_waiting_consumers() is called >>> >>> Context: >>> As I said in the cover letter, avoiding unnecessary probes is just one >>> of the reasons for this patch. The other (arguably more important) >> >> Agree that it is more important. >> >> >>> reason for this patch is to make sure suppliers know that they have >>> consumers that are yet to be probed. That way, suppliers can leave >>> their resource on AND in the right state if they were left on by the >>> bootloader. For example, if a clock was left on and at 200 MHz, the >>> clock provider needs to keep that clock ON and at 200 MHz till all the >>> consumers are probed. >>> >>> Answer: Let's say a consumer device Z has suppliers A, B and C. If the >>> linking fails at A and you return immediately, then B and C could >>> probe and then figure that they have no more consumers (they don't see >>> a link to Z) and turn off their resources. And Z could fail >>> catastrophically. >> >> Then I think that this approach is fatally flawed in the current >> implementation. > > I'm waiting to hear how it is fatally flawed. But maybe this is just a > misunderstanding of the problem? Fatally flawed because it does not handle modules that add a consumer device when the module is loaded. > > In the text below, I'm not sure if you mixing up two different things > or just that your wording it a bit ambiguous. So pardon my nitpick to > err on the side of clarity. Please do nitpick. Clarity is good. > >> A device can be added by a module that is loaded. > > No, in the example I gave, of_platform_default_populate_init() would > add all 3 of those devices during arch_initcall_sync(). The example you gave does not cover all use cases. There are modules that add devices when the module is loaded. You can not ignore systems using such modules. > >> In that case the device >> was not present at late boot when the suppliers may turn off their resources. > > In that case, the _drivers_ for those devices aren't present at late > boot. So that they can't request to keep the resources on for their > consumer devices. Since there are no consumer requests on resources, > the suppliers turn off their resources at late boot (since there isn't > a better location as of today). The sync_state() call back added in a > subsequent patche in this series will provide the better location. And the sync_state() call back will not deal with modules that add consumer devices when the module is loaded, correct? > >> (I am assuming the details since I have not reviewed the patches later in >> the series that implement this part.) >> >> Am I missing something? > > I think you are mixing up devices getting added/populated with drivers > getting loaded as modules? Only some modules add devices when they are loaded. But these modules do exist. -Frank > >> If I am wrong, then I'll have more comments for your review replies for >> patches 2 and 3. > > I'll wait for more review replies? > > Thanks, > Saravana >
Re: [PATCH v5 1/6] mm/page_idle: Add per-pid idle page tracking using virtual index
On Wed, Aug 14, 2019 at 09:56:01AM +0200, Michal Hocko wrote: [snip] > > > > Can this be used to observe which library pages other processes are > > > > accessing, even if you don't have access to those processes, as long > > > > as you can map the same libraries? I realize that there are already a > > > > bunch of ways to do that with side channels and such; but if you're > > > > adding an interface that allows this by design, it seems to me like > > > > something that should be gated behind some sort of privilege check. > > > > > > Hmm, you need to be priviledged to get the pfn now and without that you > > > cannot get to any page so the new interface is weakening the rules. > > > Maybe we should limit setting the idle state to processes with the write > > > status. Or do you think that even observing idle status is useful for > > > practical side channel attacks? If yes, is that a problem of the > > > profiler which does potentially dangerous things? > > > > I suppose read-only access isn't a real problem as long as the > > profiler isn't writing the idle state in a very tight loop... but I > > don't see a usecase where you'd actually want that? As far as I can > > tell, if you can't write the idle state, being able to read it is > > pretty much useless. > > > > If the profiler only wants to profile process-private memory, then > > that should be implementable in a safe way in principle, I think, but > > since Joel said that they want to profile CoW memory as well, I think > > that's inherently somewhat dangerous. > > I cannot really say how useful that would be but I can see that > implementing ownership checks would be really non-trivial for > shared pages. Reducing the interface to exclusive pages would make it > easier as you noted but less helpful. > > Besides that the attack vector shouldn't be really much different from > the page cache access, right? So essentially can_do_mincore model. > > I guess we want to document that page idle tracking should be used with > care because it potentially opens a side channel opportunity if used > on sensitive data. I have been thinking of this, and discussing with our heap profiler folks. Not being able to track shared pages would be a limitation, but I don't see any way forward considering this security concern so maybe we have to limit what we can do. I will look into implementing this without doing the rmap but still make it work on shared pages from the point of view of the process being tracked. It just would no longer through the PTEs of *other* processes sharing the page. My current thought is to just rely on the PTE accessed bit, and not use the PageIdle flag at all. But we'd still set the PageYoung flag so that the reclaim code still sees the page as accessed. The reason I feel like avoiding the PageIdle flag is: 1. It looks like mark_page_accessed() can be called from other paths which can also result in some kind of side-channel issue if a page was shared. 2. I don't think I need the PageIdle flag since the access bit alone should let me know, although it could be a bit slower. Since previously, I did not need to check every PTE and if the PageIdle flag was already cleared, then the page was declared as idle. At least this series resulted in a bug fix and a tonne of learning, so thank you everyone! Any other thoughts? thanks, - Joel
Re: [PATCH v5 00/17] Use MFD framework for SGI IOC3 drivers
On Mon, 19 Aug 2019 18:31:23 +0200, Thomas Bogendoerfer wrote: > - requested by Jakub I've splitted ioc3 ethernet driver changes into >more steps to make the transition more visible; Thanks a lot for doing that!
Re: [PATCH v5 09/17] net: sgi: ioc3-eth: use defines for constants dealing with desc rings
On Mon, 19 Aug 2019 18:31:32 +0200, Thomas Bogendoerfer wrote: > Descriptor ring sizes of the IOC3 are more or less fixed size. To > make clearer where there is a relation to ring sizes use defines. > > Signed-off-by: Thomas Bogendoerfer Reviewed-by: Jakub Kicinski
Re: [PATCH v5 10/17] net: sgi: ioc3-eth: rework skb rx handling
On Mon, 19 Aug 2019 18:31:33 +0200, Thomas Bogendoerfer wrote: > Buffers alloacted by alloc_skb() are already cache aligned so there > is no need for an extra align done by ioc3_alloc_skb. And instead > of skb_put/skb_trim simply use one skb_put after frame size is known > during receive. > > Signed-off-by: Thomas Bogendoerfer > --- > drivers/net/ethernet/sgi/ioc3-eth.c | 50 > - > 1 file changed, 11 insertions(+), 39 deletions(-) > > diff --git a/drivers/net/ethernet/sgi/ioc3-eth.c > b/drivers/net/ethernet/sgi/ioc3-eth.c > index c875640926d6..d862f28887f9 100644 > --- a/drivers/net/ethernet/sgi/ioc3-eth.c > +++ b/drivers/net/ethernet/sgi/ioc3-eth.c > @@ -11,7 +11,6 @@ > * > * To do: > * > - * o Handle allocation failures in ioc3_alloc_skb() more gracefully. > * o Handle allocation failures in ioc3_init_rings(). > * o Use prefetching for large packets. What is a good lower limit for > *prefetching? > @@ -72,6 +71,12 @@ > #define TX_RING_ENTRIES 128 > #define TX_RING_MASK (TX_RING_ENTRIES - 1) > > +/* BEWARE: The IOC3 documentation documents the size of rx buffers as > + * 1644 while it's actually 1664. This one was nasty to track down... > + */ > +#define RX_OFFSET10 > +#define RX_BUF_SIZE 1664 > + > #define ETCSR_FD ((17 << ETCSR_IPGR2_SHIFT) | (11 << ETCSR_IPGR1_SHIFT) | > 21) > #define ETCSR_HD ((21 << ETCSR_IPGR2_SHIFT) | (21 << ETCSR_IPGR1_SHIFT) | > 21) > > @@ -111,31 +116,6 @@ static void ioc3_init(struct net_device *dev); > static const char ioc3_str[] = "IOC3 Ethernet"; > static const struct ethtool_ops ioc3_ethtool_ops; > > -/* We use this to acquire receive skb's that we can DMA directly into. */ > - > -#define IOC3_CACHELINE 128UL Is the cache line on the platform this driver works on 128B? This looks like a DMA engine alignment requirement, more than an optimization. The comment in __alloc_skb() says: /* We do our best to align skb_shared_info on a separate cache * line. It usually works because kmalloc(X > SMP_CACHE_BYTES) gives * aligned memory blocks, unless SLUB/SLAB debug is enabled. * Both skb->head and skb_shared_info are cache line aligned. */ note the "unless". > -static inline unsigned long aligned_rx_skb_addr(unsigned long addr) > -{ > - return (~addr + 1) & (IOC3_CACHELINE - 1UL); > -} > - > -static inline struct sk_buff *ioc3_alloc_skb(unsigned long length, > - unsigned int gfp_mask) > -{ > - struct sk_buff *skb; > - > - skb = alloc_skb(length + IOC3_CACHELINE - 1, gfp_mask); > - if (likely(skb)) { > - int offset = aligned_rx_skb_addr((unsigned long)skb->data); > - > - if (offset) > - skb_reserve(skb, offset); > - } > - > - return skb; > -} > - > static inline unsigned long ioc3_map(void *ptr, unsigned long vdev) > { > #ifdef CONFIG_SGI_IP27 > @@ -148,12 +128,6 @@ static inline unsigned long ioc3_map(void *ptr, unsigned > long vdev) > #endif > } > > -/* BEWARE: The IOC3 documentation documents the size of rx buffers as > - * 1644 while it's actually 1664. This one was nasty to track down ... > - */ > -#define RX_OFFSET10 > -#define RX_BUF_ALLOC_SIZE(1664 + RX_OFFSET + IOC3_CACHELINE) > - > #define IOC3_SIZE 0x10 > > static inline u32 mcr_pack(u32 pulse, u32 sample) > @@ -534,10 +508,10 @@ static inline void ioc3_rx(struct net_device *dev) > err = be32_to_cpu(rxb->err);/* It's valid ... */ > if (err & ERXBUF_GOODPKT) { > len = ((w0 >> ERXBUF_BYTECNT_SHIFT) & 0x7ff) - 4; > - skb_trim(skb, len); > + skb_put(skb, len); > skb->protocol = eth_type_trans(skb, dev); > > - new_skb = ioc3_alloc_skb(RX_BUF_ALLOC_SIZE, GFP_ATOMIC); > + new_skb = alloc_skb(RX_BUF_SIZE, GFP_ATOMIC); > if (!new_skb) { > /* Ouch, drop packet and just recycle packet >* to keep the ring filled. > @@ -546,6 +520,7 @@ static inline void ioc3_rx(struct net_device *dev) > new_skb = skb; > goto next; > } > + new_skb->dev = dev; Assigning dev pointer seems unrelated to the rest of the patch? > if (likely(dev->features & NETIF_F_RXCSUM)) > ioc3_tcpudp_checksum(skb, > @@ -556,8 +531,6 @@ static inline void ioc3_rx(struct net_device *dev) > > ip->rx_skbs[rx_entry] = NULL; /* Poison */ > > - /* Because we reserve afterwards. */ > - skb_put(new_skb, (1664 + RX_OFFSET)); > rxb = (struct ioc3_erxbuf *)new_skb->data; >
Re: [PATCH v5 11/17] net: sgi: ioc3-eth: no need to stop queue set_multicast_list
On Mon, 19 Aug 2019 18:31:34 +0200, Thomas Bogendoerfer wrote: > netif_stop_queue()/netif_wake_qeue() aren't needed for changing > multicast filters. Use spinlocks instead for proper protection > of private struct. > > Signed-off-by: Thomas Bogendoerfer > --- > drivers/net/ethernet/sgi/ioc3-eth.c | 5 ++--- > 1 file changed, 2 insertions(+), 3 deletions(-) > > diff --git a/drivers/net/ethernet/sgi/ioc3-eth.c > b/drivers/net/ethernet/sgi/ioc3-eth.c > index d862f28887f9..7f85a3bfef14 100644 > --- a/drivers/net/ethernet/sgi/ioc3-eth.c > +++ b/drivers/net/ethernet/sgi/ioc3-eth.c > @@ -1542,8 +1542,7 @@ static void ioc3_set_multicast_list(struct net_device > *dev) > struct netdev_hw_addr *ha; > u64 ehar = 0; > > - netif_stop_queue(dev); /* Lock out others. */ > - > + spin_lock_irq(&ip->ioc3_lock); What does this lock protect? 🤔 No question that stopping TX queues makes little sense, but this function is only called from ndo_set_rx_mode(), so with rtnl_lock held. I thought it may protect ip->emcr, but that one is accessed with no locking from the ioc3_timer() -> ioc3_setup_duplex() path.. > if (dev->flags & IFF_PROMISC) { /* Set promiscuous. */ > ip->emcr |= EMCR_PROMISC; > writel(ip->emcr, ®s->emcr); > @@ -1572,7 +1571,7 @@ static void ioc3_set_multicast_list(struct net_device > *dev) > writel(ip->ehar_l, ®s->ehar_l); > } > > - netif_wake_queue(dev); /* Let us get going again. */ > + spin_unlock_irq(&ip->ioc3_lock); > } > > module_pci_driver(ioc3_driver);
Re: [PATCH v5 12/17] net: sgi: ioc3-eth: use dma-direct for dma allocations
On Mon, 19 Aug 2019 18:31:35 +0200, Thomas Bogendoerfer wrote: > @@ -1386,18 +1427,24 @@ static netdev_tx_t ioc3_start_xmit(struct sk_buff > *skb, struct net_device *dev) > unsigned long b2 = (data | 0x3fffUL) + 1UL; > unsigned long s1 = b2 - data; > unsigned long s2 = data + len - b2; > + dma_addr_t d; > > desc->cmd= cpu_to_be32(len | ETXD_INTWHENDONE | > ETXD_B1V | ETXD_B2V | w0); > desc->bufcnt = cpu_to_be32((s1 << ETXD_B1CNT_SHIFT) | > (s2 << ETXD_B2CNT_SHIFT)); > - desc->p1 = cpu_to_be64(ioc3_map(skb->data, 1)); > - desc->p2 = cpu_to_be64(ioc3_map((void *)b2, 1)); > + d = dma_map_single(ip->dma_dev, skb->data, s1, DMA_TO_DEVICE); You'll need to check the DMA address with dma_mapping_error(dev, addr), otherwise static checkers will get upset. > + desc->p1 = cpu_to_be64(ioc3_map(d, PCI64_ATTR_PREF)); > + d = dma_map_single(ip->dma_dev, (void *)b2, s1, DMA_TO_DEVICE); > + desc->p2 = cpu_to_be64(ioc3_map(d, PCI64_ATTR_PREF));
Re: [PATCH v7 3/7] of/platform: Add functional dependency link from DT bindings
On Mon, Aug 19, 2019 at 2:30 PM Frank Rowand wrote: > > On 8/19/19 1:49 PM, Saravana Kannan wrote: > > On Mon, Aug 19, 2019 at 10:16 AM Frank Rowand > > wrote: > >> > >> On 8/15/19 6:50 PM, Saravana Kannan wrote: > >>> On Wed, Aug 7, 2019 at 7:06 PM Frank Rowand > >>> wrote: > > On 7/23/19 5:10 PM, Saravana Kannan wrote: > > Add device-links after the devices are created (but before they are > > probed) by looking at common DT bindings like clocks and > > interconnects. > >> > >> > >> < very big snip (lots of comments that deserve answers) > > >> > >> > > /** > * of_link_property - TODO: > * dev: > * con_np: > * prop: > * > * TODO... > * > * Any failed attempt to create a link will NOT result in an immediate > return. > * of_link_property() must create all possible links even when one of > more > * attempts to create a link fail. > > Why? isn't one failure enough to prevent probing this device? > Continuing to scan just results in extra work... which will be > repeated every time device_link_check_waiting_consumers() is called > >>> > >>> Context: > >>> As I said in the cover letter, avoiding unnecessary probes is just one > >>> of the reasons for this patch. The other (arguably more important) > >> > >> Agree that it is more important. > >> > >> > >>> reason for this patch is to make sure suppliers know that they have > >>> consumers that are yet to be probed. That way, suppliers can leave > >>> their resource on AND in the right state if they were left on by the > >>> bootloader. For example, if a clock was left on and at 200 MHz, the > >>> clock provider needs to keep that clock ON and at 200 MHz till all the > >>> consumers are probed. > >>> > >>> Answer: Let's say a consumer device Z has suppliers A, B and C. If the > >>> linking fails at A and you return immediately, then B and C could > >>> probe and then figure that they have no more consumers (they don't see > >>> a link to Z) and turn off their resources. And Z could fail > >>> catastrophically. > >> > >> Then I think that this approach is fatally flawed in the current > >> implementation. > > > > I'm waiting to hear how it is fatally flawed. But maybe this is just a > > misunderstanding of the problem? > > Fatally flawed because it does not handle modules that add a consumer > device when the module is loaded. If you are talking about modules adding child devices of the device they are managing, then that's handled correctly later in the series. If you are talking about modules adding devices that aren't defined in DT, then right, I'm not trying to handle that. The module needs to make sure it keeps the resources needed for new devices it's adding are in the right state or need to add the right device links. > > In the text below, I'm not sure if you mixing up two different things > > or just that your wording it a bit ambiguous. So pardon my nitpick to > > err on the side of clarity. > > Please do nitpick. Clarity is good. > > > > > >> A device can be added by a module that is loaded. > > > > No, in the example I gave, of_platform_default_populate_init() would > > add all 3 of those devices during arch_initcall_sync(). > > The example you gave does not cover all use cases. > > There are modules that add devices when the module is loaded. You can not > ignore systems using such modules. I'll have to agree to disagree on that. While I understand that the design should be good and I'm happy to work on that, you can't insist that a patch series shouldn't be allowed because it's only improving 99% of the cases and leaves the other 1% in the status quo. You are just going to bring the kernel development to a grinding halt. > > > >> In that case the device > >> was not present at late boot when the suppliers may turn off their > >> resources. > > > > In that case, the _drivers_ for those devices aren't present at late > > boot. So that they can't request to keep the resources on for their > > consumer devices. Since there are no consumer requests on resources, > > the suppliers turn off their resources at late boot (since there isn't > > a better location as of today). The sync_state() call back added in a > > subsequent patche in this series will provide the better location. > > And the sync_state() call back will not deal with modules that add consumer > devices when the module is loaded, correct? Depends. If it's just more devices from DT, then it'll be fine. If it's not, then the module needs to take care of the needs of devices it's adding. > > > >> (I am assuming the details since I have not reviewed the patches later in > >> the series that implement this part.) > >> > >> Am I missing something? > > > > I think you are mixing up devices getting added/populated with drivers > > getting loaded as modules? > > Only some modules add devices when they are loaded. But these modules do > exist. Out of the bill
Re: [PATCH v5 0/9] FPGA DFL updates
On Mon, Aug 19, 2019 at 01:31:33PM +0800, Wu Hao wrote: > On Mon, Aug 12, 2019 at 10:49:55AM +0800, Wu Hao wrote: > > Hi Greg, > > > > This is v5 patchset which adds more features to FPGA DFL. Marjor changes > > against v4 are sysfs related code rework to address comments on v4. > > > > Please help to take a look. Thanks! > > Hi Greg, > > Did you get a chance to take a look at this new version patchset? :) I'm not the FPGA maintainer, what about the review from the other one first? :) thanks, greg k-h
Re: [PATCH v8 18/27] mm: Introduce do_mmap_locked()
On Tue, Aug 13, 2019 at 01:52:16PM -0700, Yu-cheng Yu wrote: > There are a few places that need do_mmap() with mm->mmap_sem held. > Create an in-line function for that. > > Signed-off-by: Yu-cheng Yu > --- > include/linux/mm.h | 18 ++ > 1 file changed, 18 insertions(+) > > diff --git a/include/linux/mm.h b/include/linux/mm.h > index bc58585014c9..275c385f53c6 100644 > --- a/include/linux/mm.h > +++ b/include/linux/mm.h > @@ -2394,6 +2394,24 @@ static inline void mm_populate(unsigned long addr, > unsigned long len) > static inline void mm_populate(unsigned long addr, unsigned long len) {} > #endif > > +static inline unsigned long do_mmap_locked(struct file *file, > + unsigned long addr, unsigned long len, unsigned long prot, > + unsigned long flags, vm_flags_t vm_flags, struct list_head *uf) > +{ > + struct mm_struct *mm = current->mm; > + unsigned long populate; > + > + down_write(&mm->mmap_sem); > + addr = do_mmap(file, addr, len, prot, flags, vm_flags, 0, > +&populate, uf); > + up_write(&mm->mmap_sem); > + > + if (populate) > + mm_populate(addr, populate); > + > + return addr; > +} Any reason not to put this in cet.c, as suggested by PeterZ? All of the calls from CET have identical params except for @len, e.g. you can add 'static unsigned long cet_mmap(unsigned long len)' and bury most of the copy-paste code in there. https://lkml.kernel.org/r/20190607074707.gd3...@hirez.programming.kicks-ass.net > + > /* These take the mm semaphore themselves */ > extern int __must_check vm_brk(unsigned long, unsigned long); > extern int __must_check vm_brk_flags(unsigned long, unsigned long, unsigned > long); > -- > 2.17.1 >
Re: [PATCH v5 0/9] FPGA DFL updates
On Mon, Aug 19, 2019 at 10:51:24PM +0200, Greg KH wrote: > On Mon, Aug 19, 2019 at 01:31:33PM +0800, Wu Hao wrote: > > On Mon, Aug 12, 2019 at 10:49:55AM +0800, Wu Hao wrote: > > > Hi Greg, > > > > > > This is v5 patchset which adds more features to FPGA DFL. Marjor changes > > > against v4 are sysfs related code rework to address comments on v4. > > > > > > Please help to take a look. Thanks! > > > > Hi Greg, > > > > Did you get a chance to take a look at this new version patchset? :) > > I'm not the FPGA maintainer, what about the review from the other one > first? :) Sure! :) Hi Moritz Could you please help review these patches? Thanks! :) Thanks Hao > > thanks, > > greg k-h
[PATCH v2 0/3] arm64: KPROBES_ON_FTRACE
KPROBES_ON_FTRACE avoids much of the overhead with regular kprobes as it eliminates the need for a trap, as well as the need to emulate or single-step instructions. Applied after arm64 FTRACE_WITH_REGS: http://lists.infradead.org/pipermail/linux-arm-kernel/2019-August/674404.html Changes since v1: - make the kprobes/x86: use instruction_pointer and instruction_pointer_set as patch1 - add Masami's ACK to patch1 - add some description about KPROBES_ON_FTRACE and why we need it on arm64 - correct the log before the patch - remove the consolidation patch, make it as TODO - only adjust kprobe's addr when KPROBE_FLAG_FTRACE is set - if KPROBES_ON_FTRACE, ftrace_call_adjust() the kprobe's addr before calling ftrace_location() - update the kprobes-on-ftrace/arch-support.txt in doc Jisheng Zhang (3): kprobes/x86: use instruction_pointer and instruction_pointer_set kprobes: adjust kprobe addr for KPROBES_ON_FTRACE arm64: implement KPROBES_ON_FTRACE .../debug/kprobes-on-ftrace/arch-support.txt | 2 +- arch/arm64/Kconfig| 1 + arch/arm64/kernel/probes/Makefile | 1 + arch/arm64/kernel/probes/ftrace.c | 60 +++ arch/x86/kernel/kprobes/ftrace.c | 9 +-- kernel/kprobes.c | 10 +++- 6 files changed, 75 insertions(+), 8 deletions(-) create mode 100644 arch/arm64/kernel/probes/ftrace.c -- 2.23.0.rc1
[PATCH v2 1/3] kprobes/x86: use instruction_pointer and instruction_pointer_set
This is to make the x86 kprobe_ftrace_handler() more common so that the code could be reused in future. Signed-off-by: Jisheng Zhang Acked-by: Masami Hiramatsu --- arch/x86/kernel/kprobes/ftrace.c | 9 + 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/arch/x86/kernel/kprobes/ftrace.c b/arch/x86/kernel/kprobes/ftrace.c index 681a4b36e9bb..c2ad0b9259ca 100644 --- a/arch/x86/kernel/kprobes/ftrace.c +++ b/arch/x86/kernel/kprobes/ftrace.c @@ -28,9 +28,9 @@ void kprobe_ftrace_handler(unsigned long ip, unsigned long parent_ip, if (kprobe_running()) { kprobes_inc_nmissed_count(p); } else { - unsigned long orig_ip = regs->ip; + unsigned long orig_ip = instruction_pointer(regs); /* Kprobe handler expects regs->ip = ip + 1 as breakpoint hit */ - regs->ip = ip + sizeof(kprobe_opcode_t); + instruction_pointer_set(regs, ip + sizeof(kprobe_opcode_t)); __this_cpu_write(current_kprobe, p); kcb->kprobe_status = KPROBE_HIT_ACTIVE; @@ -39,12 +39,13 @@ void kprobe_ftrace_handler(unsigned long ip, unsigned long parent_ip, * Emulate singlestep (and also recover regs->ip) * as if there is a 5byte nop */ - regs->ip = (unsigned long)p->addr + MCOUNT_INSN_SIZE; + instruction_pointer_set(regs, + (unsigned long)p->addr + MCOUNT_INSN_SIZE); if (unlikely(p->post_handler)) { kcb->kprobe_status = KPROBE_HIT_SSDONE; p->post_handler(p, regs, 0); } - regs->ip = orig_ip; + instruction_pointer_set(regs, orig_ip); } /* * If pre_handler returns !0, it changes regs->ip. We have to -- 2.23.0.rc1
[PATCH v2 2/3] kprobes: adjust kprobe addr for KPROBES_ON_FTRACE
For KPROBES_ON_FTRACE case, we need to adjust the kprobe's addr correspondingly. Signed-off-by: Jisheng Zhang --- kernel/kprobes.c | 10 +++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/kernel/kprobes.c b/kernel/kprobes.c index 9873fc627d61..3fd2f68644da 100644 --- a/kernel/kprobes.c +++ b/kernel/kprobes.c @@ -1484,15 +1484,19 @@ static inline int check_kprobe_rereg(struct kprobe *p) int __weak arch_check_ftrace_location(struct kprobe *p) { - unsigned long ftrace_addr; + unsigned long ftrace_addr, addr = (unsigned long)p->addr; - ftrace_addr = ftrace_location((unsigned long)p->addr); +#ifdef CONFIG_KPROBES_ON_FTRACE + addr = ftrace_call_adjust(addr); +#endif + ftrace_addr = ftrace_location(addr); if (ftrace_addr) { #ifdef CONFIG_KPROBES_ON_FTRACE /* Given address is not on the instruction boundary */ - if ((unsigned long)p->addr != ftrace_addr) + if (addr != ftrace_addr) return -EILSEQ; p->flags |= KPROBE_FLAG_FTRACE; + p->addr = (kprobe_opcode_t *)addr; #else /* !CONFIG_KPROBES_ON_FTRACE */ return -EINVAL; #endif -- 2.23.0.rc1
[PATCH v2 3/3] arm64: implement KPROBES_ON_FTRACE
KPROBES_ON_FTRACE avoids much of the overhead with regular kprobes as it eliminates the need for a trap, as well as the need to emulate or single-step instructions. This patch implements KPROBES_ON_FTRACE for arm64. Tested on berlin arm64 platform. ~ # mount -t debugfs debugfs /sys/kernel/debug/ ~ # cd /sys/kernel/debug/ /sys/kernel/debug # echo 'p _do_fork' > tracing/kprobe_events before the patch: /sys/kernel/debug # cat kprobes/list ff801009fe28 k _do_fork+0x0[DISABLED] after the patch: /sys/kernel/debug # cat kprobes/list ff801009ff54 k _do_fork+0x4[DISABLED][FTRACE] Signed-off-by: Jisheng Zhang --- .../debug/kprobes-on-ftrace/arch-support.txt | 2 +- arch/arm64/Kconfig| 1 + arch/arm64/kernel/probes/Makefile | 1 + arch/arm64/kernel/probes/ftrace.c | 60 +++ 4 files changed, 63 insertions(+), 1 deletion(-) create mode 100644 arch/arm64/kernel/probes/ftrace.c diff --git a/Documentation/features/debug/kprobes-on-ftrace/arch-support.txt b/Documentation/features/debug/kprobes-on-ftrace/arch-support.txt index 68f266944d5f..e8358a38981c 100644 --- a/Documentation/features/debug/kprobes-on-ftrace/arch-support.txt +++ b/Documentation/features/debug/kprobes-on-ftrace/arch-support.txt @@ -9,7 +9,7 @@ | alpha: | TODO | | arc: | TODO | | arm: | TODO | -| arm64: | TODO | +| arm64: | ok | | c6x: | TODO | |csky: | TODO | | h8300: | TODO | diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig index 663392d1eae2..928700f15e23 100644 --- a/arch/arm64/Kconfig +++ b/arch/arm64/Kconfig @@ -167,6 +167,7 @@ config ARM64 select HAVE_STACKPROTECTOR select HAVE_SYSCALL_TRACEPOINTS select HAVE_KPROBES + select HAVE_KPROBES_ON_FTRACE select HAVE_KRETPROBES select HAVE_GENERIC_VDSO select IOMMU_DMA if IOMMU_SUPPORT diff --git a/arch/arm64/kernel/probes/Makefile b/arch/arm64/kernel/probes/Makefile index 8e4be92e25b1..4020cfc66564 100644 --- a/arch/arm64/kernel/probes/Makefile +++ b/arch/arm64/kernel/probes/Makefile @@ -4,3 +4,4 @@ obj-$(CONFIG_KPROBES) += kprobes.o decode-insn.o \ simulate-insn.o obj-$(CONFIG_UPROBES) += uprobes.o decode-insn.o \ simulate-insn.o +obj-$(CONFIG_KPROBES_ON_FTRACE)+= ftrace.o diff --git a/arch/arm64/kernel/probes/ftrace.c b/arch/arm64/kernel/probes/ftrace.c new file mode 100644 index ..52901570 --- /dev/null +++ b/arch/arm64/kernel/probes/ftrace.c @@ -0,0 +1,60 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Dynamic Ftrace based Kprobes Optimization + * + * Copyright (C) Hitachi Ltd., 2012 + * Copyright (C) 2019 Jisheng Zhang + * Synaptics Incorporated + */ + +#include + +/* Ftrace callback handler for kprobes -- called under preepmt disabed */ +void kprobe_ftrace_handler(unsigned long ip, unsigned long parent_ip, + struct ftrace_ops *ops, struct pt_regs *regs) +{ + struct kprobe *p; + struct kprobe_ctlblk *kcb; + + /* Preempt is disabled by ftrace */ + p = get_kprobe((kprobe_opcode_t *)ip); + if (unlikely(!p) || kprobe_disabled(p)) + return; + + kcb = get_kprobe_ctlblk(); + if (kprobe_running()) { + kprobes_inc_nmissed_count(p); + } else { + unsigned long orig_ip = instruction_pointer(regs); + /* Kprobe handler expects regs->pc = pc + 1 as breakpoint hit */ + instruction_pointer_set(regs, ip + sizeof(kprobe_opcode_t)); + + __this_cpu_write(current_kprobe, p); + kcb->kprobe_status = KPROBE_HIT_ACTIVE; + if (!p->pre_handler || !p->pre_handler(p, regs)) { + /* +* Emulate singlestep (and also recover regs->pc) +* as if there is a nop +*/ + instruction_pointer_set(regs, + (unsigned long)p->addr + MCOUNT_INSN_SIZE); + if (unlikely(p->post_handler)) { + kcb->kprobe_status = KPROBE_HIT_SSDONE; + p->post_handler(p, regs, 0); + } + instruction_pointer_set(regs, orig_ip); + } + /* +* If pre_handler returns !0, it changes regs->pc. We have to +* skip emulating post_handler. +*/ + __this_cpu_write(current_kprobe, NULL); + } +} +NOKPROBE_SYMBOL(kprobe_ftrace_handler); + +int arch_prepare_kprobe_ftrace(struct kprobe *p) +{ + p->ainsn.api.insn = NULL; + return 0; +} -- 2.23.0.rc1
Re: [PATCH v7 3/7] of/platform: Add functional dependency link from DT bindings
On 8/19/19 5:09 PM, Saravana Kannan wrote: > On Mon, Aug 19, 2019 at 2:30 PM Frank Rowand wrote: >> >> On 8/19/19 1:49 PM, Saravana Kannan wrote: >>> On Mon, Aug 19, 2019 at 10:16 AM Frank Rowand >>> wrote: On 8/15/19 6:50 PM, Saravana Kannan wrote: > On Wed, Aug 7, 2019 at 7:06 PM Frank Rowand > wrote: >> >> On 7/23/19 5:10 PM, Saravana Kannan wrote: >>> Add device-links after the devices are created (but before they are >>> probed) by looking at common DT bindings like clocks and >>> interconnects. < very big snip (lots of comments that deserve answers) > >> >> /** >> * of_link_property - TODO: >> * dev: >> * con_np: >> * prop: >> * >> * TODO... >> * >> * Any failed attempt to create a link will NOT result in an immediate >> return. >> * of_link_property() must create all possible links even when one of >> more >> * attempts to create a link fail. >> >> Why? isn't one failure enough to prevent probing this device? >> Continuing to scan just results in extra work... which will be >> repeated every time device_link_check_waiting_consumers() is called > > Context: > As I said in the cover letter, avoiding unnecessary probes is just one > of the reasons for this patch. The other (arguably more important) Agree that it is more important. > reason for this patch is to make sure suppliers know that they have > consumers that are yet to be probed. That way, suppliers can leave > their resource on AND in the right state if they were left on by the > bootloader. For example, if a clock was left on and at 200 MHz, the > clock provider needs to keep that clock ON and at 200 MHz till all the > consumers are probed. > > Answer: Let's say a consumer device Z has suppliers A, B and C. If the > linking fails at A and you return immediately, then B and C could > probe and then figure that they have no more consumers (they don't see > a link to Z) and turn off their resources. And Z could fail > catastrophically. Then I think that this approach is fatally flawed in the current implementation. >>> >>> I'm waiting to hear how it is fatally flawed. But maybe this is just a >>> misunderstanding of the problem? >> >> Fatally flawed because it does not handle modules that add a consumer >> device when the module is loaded. > > If you are talking about modules adding child devices of the device > they are managing, then that's handled correctly later in the series. They may or they may not. I do not know. I am not going to audit all current cases of devices being added to check that relationship and I am not going to monitor all future patches that add devices. Adding devices is an existing pattern of behavior that the new feature must be able to handle. I have not looked at patch 6 yet (the place where modules adding child devices is handled). I am guessing that patch 6 could be made more general to remove the parent child relationship restriction. > > If you are talking about modules adding devices that aren't defined in > DT, then right, I'm not trying to handle that. The module needs to > make sure it keeps the resources needed for new devices it's adding > are in the right state or need to add the right device links. I am not talking about devices that are not defined in the devicetree. > >>> In the text below, I'm not sure if you mixing up two different things >>> or just that your wording it a bit ambiguous. So pardon my nitpick to >>> err on the side of clarity. >> >> Please do nitpick. Clarity is good. >> >> >>> A device can be added by a module that is loaded. >>> >>> No, in the example I gave, of_platform_default_populate_init() would >>> add all 3 of those devices during arch_initcall_sync(). >> >> The example you gave does not cover all use cases. >> >> There are modules that add devices when the module is loaded. You can not >> ignore systems using such modules. > > I'll have to agree to disagree on that. While I understand that the > design should be good and I'm happy to work on that, you can't insist > that a patch series shouldn't be allowed because it's only improving > 99% of the cases and leaves the other 1% in the status quo. You are > just going to bring the kernel development to a grinding halt. No, you do not get to disagree on that. And you are presenting a straw man argument. You are proposing a new feature that contributes fragility and complexity to the house of cards that device instantiation and driver probing already is. The feature is clever but it is intertwined into an area that is already complex and in many cases difficult to work within. I had hoped that the feature was robust enough and generic enough to accept. The proposed feature is a hack to paper over a specific problem that you are facing. I had hoped that the
Re: [PATCH v5 15/17] mfd: ioc3: Add driver for SGI IOC3 chip
Hi, On 19/08/2019 18:31:38+0200, Thomas Bogendoerfer wrote: > diff --git a/drivers/mfd/ioc3.c b/drivers/mfd/ioc3.c > new file mode 100644 > index ..5bcb3461a189 > --- /dev/null > +++ b/drivers/mfd/ioc3.c > @@ -0,0 +1,586 @@ > +// SPDX-License-Identifier: GPL-2.0 > +/* > + * SGI IOC3 multifunction device driver > + * > + * Copyright (C) 2018, 2019 Thomas Bogendoerfer > + * > + * Based on work by: > + * Stanislaw Skowronek > + * Joshua Kinard > + * Brent Casavant - IOC4 master driver > + * Pat Gefre - IOC3 serial port IRQ demuxer > + */ > + > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include I don't think this include is necessary. -- Alexandre Belloni, Bootlin Embedded Linux and Kernel engineering https://bootlin.com