diff options
33 files changed, 931 insertions, 137 deletions
diff --git a/Documentation/devicetree/bindings/net/neutrino_avb.txt b/Documentation/devicetree/bindings/net/neutrino_avb.txt new file mode 100644 index 000000000000..46c6a5208eba --- /dev/null +++ b/Documentation/devicetree/bindings/net/neutrino_avb.txt @@ -0,0 +1,28 @@ +* Neutrino Ethernet * +This driver implements Ethernet driver for Neutrino ethernet controller +Required properties: + - compatible: Should be "qcom,ntn_avb" + - ntn-rst-gpio: Neutrino reset GPIO + - vdd-ntn-hsic-supply: neutrino HSIC power supply + - vdd-ntn-pci-supply: PCIe core power supply + - vdd-ntn-io-supply: Neutrino IO power supply + - vdd-ntn-phy-supply: Ethernet Phy power supply + - vdd-ntn-core-supply: Neutrino core power supply + - pinctrl-names: should contain GPIO details + - pinctrl-0: Neutrino reset GPIO [this is from MSM] + - ntn-rst-delay-msec: dealy (msec) required after PCIe reset for stabilization + - ntn-rc-num: PCIe root complex number on which Neutrino is connected +Example: + qcom,ntn_avb { + compatible = "qcom,ntn_avb"; + ntn-rst-gpio = <&pm8994_gpios 13 0>; + vdd-ntn-hsic-supply = <&pm8994_l25>; + vdd-ntn-pci-supply = <&pm8994_s4>; + vdd-ntn-io-supply = <&pm8994_s4>; + vdd-ntn-phy-supply = <&pm8994_l9>; + vdd-ntn-core-supply = <&pm8994_l19>; + pinctrl-names = "default"; + pinctrl-0 = <&ntn_default>; + qcom,ntn-rst-delay-msec = <100>; + qcom,ntn-rc-num = <1>; + }; diff --git a/arch/arm/boot/dts/qcom/apq8096-auto-dragonboard.dtsi b/arch/arm/boot/dts/qcom/apq8096-auto-dragonboard.dtsi index e74aded8c9e3..b360b0a58b54 100644 --- a/arch/arm/boot/dts/qcom/apq8096-auto-dragonboard.dtsi +++ b/arch/arm/boot/dts/qcom/apq8096-auto-dragonboard.dtsi @@ -528,6 +528,19 @@ }; &soc { + qcom,ntn_avb { + compatible = "qcom,ntn_avb"; + + ntn-rst-gpio = <&pm8994_gpios 13 0>; + + vdd-ntn-hsic-supply = <&pm8994_l25>; + vdd-ntn-pci-supply = <&pm8994_s4>; + vdd-ntn-io-supply = <&pm8994_s4>; + + qcom,ntn-rst-delay-msec = <100>; + qcom,ntn-rc-num = <1>; + }; + qcom,cnss { wlan-bootstrap-gpio = <&tlmm 46 0>; wlan-en-gpio = <&pm8994_gpios 8 0>; @@ -768,11 +781,14 @@ status = "okay"; }; - gpio@cc00 { /* GPIO 13 */ - qcom,mode = <1>; /* DIGITAL OUT */ - qcom,vin-sel = <2>; /* 1.8 */ - qcom,src-sel = <0>; /* GPIO */ - qcom,master-en = <1>; /* Enable GPIO */ + gpio@cc00 { /* GPIO 13 - NTN_RST */ + qcom,mode = <1>; /* DIGITAL OUT */ + qcom,output-type = <0>; /* CMOS logic */ + qcom,pull = <5>; + qcom,vin-sel = <2>; /* 1.8 */ + qcom,out-strength = <1>; + qcom,src-sel = <0>; /* GPIO */ + qcom,master-en = <1>; /* Enable GPIO */ status = "okay"; }; diff --git a/arch/arm/boot/dts/qcom/msm8996-agave-adp.dtsi b/arch/arm/boot/dts/qcom/msm8996-agave-adp.dtsi index f54ede157a66..bec933dbdf96 100644 --- a/arch/arm/boot/dts/qcom/msm8996-agave-adp.dtsi +++ b/arch/arm/boot/dts/qcom/msm8996-agave-adp.dtsi @@ -730,6 +730,19 @@ }; &soc { + qcom,ntn_avb { + compatible = "qcom,ntn_avb"; + + ntn-rst-gpio = <&pm8994_gpios 13 0>; + + vdd-ntn-hsic-supply = <&pm8994_l25>; + vdd-ntn-pci-supply = <&pm8994_s4>; + vdd-ntn-io-supply = <&pm8994_s4>; + + qcom,ntn-rst-delay-msec = <100>; + qcom,ntn-rc-num = <1>; + }; + i2c@75ba000 { synaptics@20 { compatible = "synaptics,dsx"; @@ -895,9 +908,12 @@ asoc-codec-names = "msm-stub-codec.1"; }; - usb_detect { + usb_detect: usb_detect { compatible = "qcom,gpio-usbdetect"; - qcom,vbus-det-irq = <&pm8994_gpios 17 0>; + qcom,vbus-det-gpio = <&pm8994_gpios 17 0>; + interrupt-parent = <&spmi_bus>; + interrupts = <0x0 0x9 0x0 IRQ_TYPE_NONE>; + interrupt-names ="pmic_id_irq"; }; loopback1: qcom,msm-pcm-loopback-low-latency { @@ -1025,14 +1041,14 @@ status = "okay"; }; - gpio@cc00 { /* GPIO 13 - HPH_EN0 */ - qcom,mode = <1>; - qcom,output-type = <0>; + gpio@cc00 { /* GPIO 13 - NTN_RST */ + qcom,mode = <1>; /* DIGITAL OUT */ + qcom,output-type = <0>; /* CMOS logic */ qcom,pull = <5>; - qcom,vin-sel = <2>; + qcom,vin-sel = <2>; /* 1.8 */ qcom,out-strength = <1>; - qcom,src-sel = <2>; - qcom,master-en = <1>; + qcom,src-sel = <0>; /* GPIO */ + qcom,master-en = <1>; /* Enable GPIO */ status = "okay"; }; @@ -1086,15 +1102,7 @@ }; &usb3 { - interrupt-parent = <&usb3>; - interrupts = <0 1 2>; - #interrupt-cells = <1>; - interrupt-map-mask = <0x0 0xffffffff>; - interrupt-map = <0x0 0 &intc 0 133 0 - 0x0 1 &intc 0 180 0 - 0x0 2 &spmi_bus 0x0 0x0 0x9 0x0>; - interrupt-names = "hs_phy_irq", "pwr_event_irq", "pmic_id_irq"; - + extcon = <&usb_detect>; vbus_dwc3-supply = <&usb_otg_switch>; vdda33-supply = <&pm8994_l24>; vdda18-supply = <&pm8994_l12>; diff --git a/arch/arm/boot/dts/qcom/msm8996-auto-cdp.dtsi b/arch/arm/boot/dts/qcom/msm8996-auto-cdp.dtsi index a73dde35f446..652d0f2dc2ea 100644 --- a/arch/arm/boot/dts/qcom/msm8996-auto-cdp.dtsi +++ b/arch/arm/boot/dts/qcom/msm8996-auto-cdp.dtsi @@ -454,6 +454,19 @@ }; &soc { + qcom,ntn_avb { + compatible = "qcom,ntn_avb"; + + ntn-rst-gpio = <&pm8994_gpios 13 0>; + + vdd-ntn-hsic-supply = <&pm8994_l25>; + vdd-ntn-pci-supply = <&pm8994_s4>; + vdd-ntn-io-supply = <&pm8994_s4>; + + qcom,ntn-rst-delay-msec = <100>; + qcom,ntn-rc-num = <1>; + }; + i2c@75ba000 { synaptics@20 { compatible = "synaptics,dsx"; @@ -799,14 +812,14 @@ status = "okay"; }; - gpio@cc00 { /* GPIO 13 - HPH_EN0 */ - qcom,mode = <1>; - qcom,output-type = <0>; + gpio@cc00 { /* GPIO 13 - NTN_RST */ + qcom,mode = <1>; /* DIGITAL OUT */ + qcom,output-type = <0>; /* CMOS logic */ qcom,pull = <5>; - qcom,vin-sel = <2>; + qcom,vin-sel = <2>; /* 1.8 */ qcom,out-strength = <1>; - qcom,src-sel = <2>; - qcom,master-en = <1>; + qcom,src-sel = <0>; /* GPIO */ + qcom,master-en = <1>; /* Enable GPIO */ status = "okay"; }; diff --git a/arch/arm/boot/dts/qcom/msm8996.dtsi b/arch/arm/boot/dts/qcom/msm8996.dtsi index feb6b606c65e..95387acb928f 100644 --- a/arch/arm/boot/dts/qcom/msm8996.dtsi +++ b/arch/arm/boot/dts/qcom/msm8996.dtsi @@ -21,6 +21,10 @@ qcom,pmic-id = <0x20009 0x2000A 0x0 0x0>; interrupt-parent = <&intc>; + chosen { + bootargs = "app_setting.use_32bit_app_setting=1"; + }; + aliases { sdhc1 = &sdhc_1; /* SDC1 eMMC slot */ sdhc2 = &sdhc_2; /* SDC2 SD card slot */ diff --git a/arch/arm/boot/dts/qcom/msm8996pro.dtsi b/arch/arm/boot/dts/qcom/msm8996pro.dtsi index 59ffa3ce88cb..f554f699fb1a 100644 --- a/arch/arm/boot/dts/qcom/msm8996pro.dtsi +++ b/arch/arm/boot/dts/qcom/msm8996pro.dtsi @@ -1,4 +1,4 @@ -/* Copyright (c) 2014-2016, The Linux Foundation. All rights reserved. +/* Copyright (c) 2014-2017, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -20,6 +20,10 @@ / { model = "Qualcomm Technologies, Inc. MSM 8996pro"; qcom,msm-id = <305 0x10000>; + + chosen { + bootargs = "app_setting.use_32bit_app_setting_pro=1"; + }; }; &apc_apm { diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig index d2b79af5f575..8088529eed47 100644 --- a/arch/arm64/Kconfig +++ b/arch/arm64/Kconfig @@ -536,9 +536,20 @@ config ARM64_64K_PAGES endchoice +config MSM_APP_API + bool "API support to enable / disable app settings for MSM8996" + depends on ARCH_MSM8996 && (ENABLE_FP_SIMD_SETTINGS || MSM_APP_SETTINGS) + help + Add API support to enable / disable the app settings to be used + at runtime. These APIs are used to enable / disable app setting + when specific aarch32 or aarch64 processes are running. + + If you are not sure what to do, select 'N' here. + config ENABLE_FP_SIMD_SETTINGS bool "Enable FP(Floating Point) Settings for Qualcomm MSM8996" depends on ARCH_MSM8996 + select MSM_APP_API help Enable FP(Floating Point) and SIMD settings for the MSM8996 during the execution of the aarch32 processes and disable these settings @@ -546,6 +557,16 @@ config ENABLE_FP_SIMD_SETTINGS If you are not sure what to do, select 'N' here. +config MSM_APP_SETTINGS + bool "Support to enable / disable app settings for MSM8996" + depends on ARCH_MSM8996 + select MSM_APP_API + help + Expose an interface used by the userspace at runtime to + enable / disable the app specific settings. + + If you are not sure what to do, select 'N' here. + choice prompt "Virtual address space size" default ARM64_VA_BITS_39 if ARM64_4K_PAGES diff --git a/arch/arm64/configs/msm-auto-perf_defconfig b/arch/arm64/configs/msm-auto-perf_defconfig index f2042134a8a7..7fac2ca3b4ad 100644 --- a/arch/arm64/configs/msm-auto-perf_defconfig +++ b/arch/arm64/configs/msm-auto-perf_defconfig @@ -46,6 +46,7 @@ CONFIG_ARCH_MSM8996=y CONFIG_PCI=y CONFIG_PCI_MSM=y CONFIG_ENABLE_FP_SIMD_SETTINGS=y +CONFIG_MSM_APP_SETTINGS=y CONFIG_SCHED_MC=y CONFIG_NR_CPUS=8 CONFIG_PREEMPT=y @@ -325,6 +326,7 @@ CONFIG_SPI=y CONFIG_SPI_QUP=y CONFIG_SPI_SPIDEV=y CONFIG_SPMI=y +CONFIG_PTP_1588_CLOCK=y CONFIG_PINCTRL_MSM8996=y CONFIG_GPIOLIB=y CONFIG_GPIO_SYSFS=y @@ -470,6 +472,7 @@ CONFIG_LEDS_QPNP=y CONFIG_LEDS_QPNP_FLASH=y CONFIG_LEDS_QPNP_WLED=y CONFIG_LEDS_TRIGGERS=y +CONFIG_NOP_USB_XCEIV=y CONFIG_SWITCH=y CONFIG_RTC_CLASS=y CONFIG_RTC_DRV_QPNP=y @@ -525,6 +528,7 @@ CONFIG_MSM_IPC_ROUTER_MHI_XPRT=y CONFIG_MSM_IPC_ROUTER_GLINK_XPRT=y CONFIG_MSM_GLINK_PKT=y CONFIG_MSM_SPM=y +CONFIG_MSM_L2_SPM=y CONFIG_QCOM_SCM=y CONFIG_QCOM_SCM_XPU=y CONFIG_QCOM_WATCHDOG_V2=y @@ -539,6 +543,7 @@ CONFIG_MSM_PIL_SSR_GENERIC=y CONFIG_MSM_PIL_MSS_QDSP6V5=y CONFIG_TRACER_PKT=y CONFIG_MSM_MPM_OF=y +CONFIG_MSM_EVENT_TIMER=y CONFIG_MSM_AVTIMER=y CONFIG_MSM_RPM_RBCPR_STATS_V2_LOG=y CONFIG_MSM_RPM_LOG=y diff --git a/arch/arm64/configs/msm-auto_defconfig b/arch/arm64/configs/msm-auto_defconfig index 9bc3ee7a463c..2648ab49cdf2 100644 --- a/arch/arm64/configs/msm-auto_defconfig +++ b/arch/arm64/configs/msm-auto_defconfig @@ -43,6 +43,7 @@ CONFIG_ARCH_MSM8996=y CONFIG_PCI=y CONFIG_PCI_MSM=y CONFIG_ENABLE_FP_SIMD_SETTINGS=y +CONFIG_MSM_APP_SETTINGS=y CONFIG_SCHED_MC=y CONFIG_NR_CPUS=8 CONFIG_PREEMPT=y @@ -312,6 +313,7 @@ CONFIG_SPI=y CONFIG_SPI_QUP=y CONFIG_SPI_SPIDEV=y CONFIG_SPMI=y +CONFIG_PTP_1588_CLOCK=y CONFIG_PINCTRL_MSM8996=y CONFIG_GPIOLIB=y CONFIG_GPIO_SYSFS=y @@ -460,6 +462,7 @@ CONFIG_LEDS_QPNP_WLED=y CONFIG_LEDS_SYSCON=y CONFIG_LEDS_TRIGGERS=y CONFIG_LEDS_TRIGGER_HEARTBEAT=y +CONFIG_NOP_USB_XCEIV=y CONFIG_LEDS_TRIGGER_CPU=y CONFIG_SWITCH=y CONFIG_RTC_CLASS=y @@ -526,6 +529,7 @@ CONFIG_MSM_IPC_ROUTER_MHI_XPRT=y CONFIG_MSM_IPC_ROUTER_GLINK_XPRT=y CONFIG_MSM_GLINK_PKT=y CONFIG_MSM_SPM=y +CONFIG_MSM_L2_SPM=y CONFIG_QCOM_SCM=y CONFIG_QCOM_SCM_XPU=y CONFIG_QCOM_WATCHDOG_V2=y @@ -541,6 +545,7 @@ CONFIG_MSM_PIL_MSS_QDSP6V5=y CONFIG_TRACER_PKT=y CONFIG_QCOM_FORCE_WDOG_BITE_ON_PANIC=y CONFIG_MSM_MPM_OF=y +CONFIG_MSM_EVENT_TIMER=y CONFIG_MSM_AVTIMER=y CONFIG_QCOM_REMOTEQDSS=y CONFIG_MSM_SERVICE_NOTIFIER=y diff --git a/arch/arm64/configs/msm-perf_defconfig b/arch/arm64/configs/msm-perf_defconfig index 03c5bc89b6f5..a05cbbc8cc01 100644 --- a/arch/arm64/configs/msm-perf_defconfig +++ b/arch/arm64/configs/msm-perf_defconfig @@ -519,6 +519,7 @@ CONFIG_MSM_IPC_ROUTER_MHI_XPRT=y CONFIG_MSM_IPC_ROUTER_GLINK_XPRT=y CONFIG_MSM_GLINK_PKT=y CONFIG_MSM_SPM=y +CONFIG_MSM_L2_SPM=y CONFIG_QCOM_SCM=y CONFIG_QCOM_SCM_XPU=y CONFIG_QCOM_WATCHDOG_V2=y @@ -533,6 +534,7 @@ CONFIG_MSM_PIL_SSR_GENERIC=y CONFIG_MSM_PIL_MSS_QDSP6V5=y CONFIG_TRACER_PKT=y CONFIG_MSM_MPM_OF=y +CONFIG_MSM_EVENT_TIMER=y CONFIG_MSM_AVTIMER=y CONFIG_MSM_RPM_RBCPR_STATS_V2_LOG=y CONFIG_MSM_RPM_LOG=y diff --git a/arch/arm64/configs/msm_defconfig b/arch/arm64/configs/msm_defconfig index b4ddd9a2bed5..6d1bd1eae7f6 100644 --- a/arch/arm64/configs/msm_defconfig +++ b/arch/arm64/configs/msm_defconfig @@ -520,6 +520,7 @@ CONFIG_MSM_IPC_ROUTER_MHI_XPRT=y CONFIG_MSM_IPC_ROUTER_GLINK_XPRT=y CONFIG_MSM_GLINK_PKT=y CONFIG_MSM_SPM=y +CONFIG_MSM_L2_SPM=y CONFIG_QCOM_SCM=y CONFIG_QCOM_SCM_XPU=y CONFIG_QCOM_WATCHDOG_V2=y @@ -535,6 +536,7 @@ CONFIG_MSM_PIL_MSS_QDSP6V5=y CONFIG_TRACER_PKT=y CONFIG_QCOM_FORCE_WDOG_BITE_ON_PANIC=y CONFIG_MSM_MPM_OF=y +CONFIG_MSM_EVENT_TIMER=y CONFIG_MSM_AVTIMER=y CONFIG_QCOM_REMOTEQDSS=y CONFIG_MSM_SERVICE_NOTIFIER=y diff --git a/arch/arm64/include/asm/app_api.h b/arch/arm64/include/asm/app_api.h new file mode 100644 index 000000000000..0e6a469cd683 --- /dev/null +++ b/arch/arm64/include/asm/app_api.h @@ -0,0 +1,50 @@ +/* Copyright (c) 2016-2017, The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#ifndef __ASM_APP_API_H +#define __ASM_APP_API_H + +#include <linux/types.h> +#include <linux/sched.h> +#include <linux/fs.h> + +#define APP_SETTING_BIT 30 +#define MAX_ENTRIES 10 + +/* + * APIs to set / clear the app setting bits + * in the register. + */ +#ifdef CONFIG_MSM_APP_API +extern void set_app_setting_bit(uint32_t bit); +extern void clear_app_setting_bit(uint32_t bit); +extern void set_app_setting_bit_for_32bit_apps(void); +extern void clear_app_setting_bit_for_32bit_apps(void); +#else +static inline void set_app_setting_bit(uint32_t bit) {} +static inline void clear_app_setting_bit(uint32_t bit) {} +static inline void set_app_setting_bit_for_32bit_apps(void) {} +static inline void clear_app_setting_bit_for_32bit_apps(void) {} +#endif + +#ifdef CONFIG_MSM_APP_SETTINGS +extern void switch_app_setting_bit(struct task_struct *prev, + struct task_struct *next); +extern void switch_32bit_app_setting_bit(struct task_struct *prev, + struct task_struct *next); +extern void apply_app_setting_bit(struct file *file); +extern bool use_app_setting; +extern bool use_32bit_app_setting; +extern bool use_32bit_app_setting_pro; +#endif + +#endif diff --git a/arch/arm64/include/asm/elf.h b/arch/arm64/include/asm/elf.h index e90414a367ed..a383c288ef49 100644 --- a/arch/arm64/include/asm/elf.h +++ b/arch/arm64/include/asm/elf.h @@ -185,8 +185,6 @@ typedef compat_elf_greg_t compat_elf_gregset_t[COMPAT_ELF_NGREG]; #define compat_start_thread compat_start_thread #define COMPAT_SET_PERSONALITY(ex) \ do { \ - if (current->mm) \ - fpsimd_enable_trap(); \ set_thread_flag(TIF_32BIT); \ } while (0) diff --git a/arch/arm64/include/asm/fpsimd.h b/arch/arm64/include/asm/fpsimd.h index 355871b7022f..3efaa5cebc03 100644 --- a/arch/arm64/include/asm/fpsimd.h +++ b/arch/arm64/include/asm/fpsimd.h @@ -84,13 +84,9 @@ extern void fpsimd_load_partial_state(struct fpsimd_partial_state *state); #ifdef CONFIG_ENABLE_FP_SIMD_SETTINGS extern void fpsimd_disable_trap(void); extern void fpsimd_enable_trap(void); -extern void fpsimd_settings_disable(void); -extern void fpsimd_settings_enable(void); #else static inline void fpsimd_disable_trap(void) {} static inline void fpsimd_enable_trap(void) {} -static inline void fpsimd_settings_disable(void) {} -static inline void fpsimd_settings_enable(void) {} #endif #endif diff --git a/arch/arm64/kernel/Makefile b/arch/arm64/kernel/Makefile index f6e0269de4c7..744aa1aa0087 100644 --- a/arch/arm64/kernel/Makefile +++ b/arch/arm64/kernel/Makefile @@ -46,6 +46,8 @@ arm64-obj-$(CONFIG_ARMV8_DEPRECATED) += armv8_deprecated.o arm64-obj-$(CONFIG_ACPI) += acpi.o arm64-obj-$(CONFIG_ARM64_ACPI_PARKING_PROTOCOL) += acpi_parking_protocol.o arm64-obj-$(CONFIG_RANDOMIZE_BASE) += kaslr.o +arm64-obj-$(CONFIG_MSM_APP_API) += app_api.o +arm64-obj-$(CONFIG_MSM_APP_SETTINGS) += app_setting.o obj-y += $(arm64-obj-y) vdso/ obj-m += $(arm64-obj-m) diff --git a/arch/arm64/kernel/app_api.c b/arch/arm64/kernel/app_api.c new file mode 100644 index 000000000000..e995bbf3c7b4 --- /dev/null +++ b/arch/arm64/kernel/app_api.c @@ -0,0 +1,135 @@ +/* Copyright (c) 2016-2017, The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include <linux/bitops.h> +#include <linux/spinlock.h> +#include <linux/cpu.h> +#include <linux/export.h> + +#include <asm/app_api.h> + +static spinlock_t spinlock; +static spinlock_t spinlock_32bit_app; +static DEFINE_PER_CPU(int, app_config_applied); +static unsigned long app_config_set[NR_CPUS]; +static unsigned long app_config_clear[NR_CPUS]; + +void set_app_setting_bit(uint32_t bit) +{ + unsigned long flags; + uint64_t reg; + int cpu; + + spin_lock_irqsave(&spinlock, flags); + asm volatile("mrs %0, S3_1_C15_C15_0" : "=r" (reg)); + reg = reg | BIT(bit); + isb(); + asm volatile("msr S3_1_C15_C15_0, %0" : : "r" (reg)); + isb(); + if (bit == APP_SETTING_BIT) { + cpu = raw_smp_processor_id(); + app_config_set[cpu]++; + + this_cpu_write(app_config_applied, 1); + } + spin_unlock_irqrestore(&spinlock, flags); + +} +EXPORT_SYMBOL(set_app_setting_bit); + +void clear_app_setting_bit(uint32_t bit) +{ + unsigned long flags; + uint64_t reg; + int cpu; + + spin_lock_irqsave(&spinlock, flags); + asm volatile("mrs %0, S3_1_C15_C15_0" : "=r" (reg)); + reg = reg & ~BIT(bit); + isb(); + asm volatile("msr S3_1_C15_C15_0, %0" : : "r" (reg)); + isb(); + if (bit == APP_SETTING_BIT) { + cpu = raw_smp_processor_id(); + app_config_clear[cpu]++; + + this_cpu_write(app_config_applied, 0); + } + spin_unlock_irqrestore(&spinlock, flags); +} +EXPORT_SYMBOL(clear_app_setting_bit); + +void set_app_setting_bit_for_32bit_apps(void) +{ + unsigned long flags; + uint64_t reg; + + spin_lock_irqsave(&spinlock_32bit_app, flags); + if (use_32bit_app_setting) { + asm volatile("mrs %0, S3_0_c15_c15_0 " : "=r" (reg)); + reg = reg | BIT(24); + isb(); + asm volatile("msr S3_0_c15_c15_0, %0" : : "r" (reg)); + isb(); + asm volatile("mrs %0, S3_0_c15_c15_1 " : "=r" (reg)); + reg = reg | BIT(18) | BIT(2) | BIT(0); + isb(); + asm volatile("msr S3_0_c15_c15_1, %0" : : "r" (reg)); + isb(); + } else if (use_32bit_app_setting_pro) { + asm volatile("mrs %0, S3_0_c15_c15_1 " : "=r" (reg)); + reg = reg | BIT(18); + isb(); + asm volatile("msr S3_0_c15_c15_1, %0" : : "r" (reg)); + isb(); + } + spin_unlock_irqrestore(&spinlock_32bit_app, flags); +} +EXPORT_SYMBOL(set_app_setting_bit_for_32bit_apps); + +void clear_app_setting_bit_for_32bit_apps(void) +{ + unsigned long flags; + uint64_t reg; + + spin_lock_irqsave(&spinlock_32bit_app, flags); + if (use_32bit_app_setting) { + asm volatile("mrs %0, S3_0_c15_c15_0 " : "=r" (reg)); + reg = reg & ~BIT(24); + isb(); + asm volatile("msr S3_0_c15_c15_0, %0" : : "r" (reg)); + isb(); + asm volatile("mrs %0, S3_0_c15_c15_1 " : "=r" (reg)); + reg = reg & ~BIT(18); + reg = reg & ~BIT(2); + reg = reg & ~BIT(0); + isb(); + asm volatile("msr S3_0_c15_c15_1, %0" : : "r" (reg)); + isb(); + } else if (use_32bit_app_setting_pro) { + asm volatile("mrs %0, S3_0_c15_c15_1 " : "=r" (reg)); + reg = reg & ~BIT(18); + isb(); + asm volatile("msr S3_0_c15_c15_1, %0" : : "r" (reg)); + isb(); + } + spin_unlock_irqrestore(&spinlock_32bit_app, flags); +} +EXPORT_SYMBOL(clear_app_setting_bit_for_32bit_apps); + +static int __init init_app_api(void) +{ + spin_lock_init(&spinlock); + spin_lock_init(&spinlock_32bit_app); + return 0; +} +early_initcall(init_app_api); diff --git a/arch/arm64/kernel/app_setting.c b/arch/arm64/kernel/app_setting.c new file mode 100644 index 000000000000..0c6b00317645 --- /dev/null +++ b/arch/arm64/kernel/app_setting.c @@ -0,0 +1,139 @@ +/* Copyright (c) 2016-2017, The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include <linux/module.h> +#include <linux/cpu.h> +#include <linux/slab.h> +#include <linux/notifier.h> + +#include <asm/app_api.h> + +#define MAX_LEN 100 + +static char *lib_names[MAX_ENTRIES]; +static unsigned int count; +static struct mutex mutex; + +static char lib_str[MAX_LEN] = ""; +static struct kparam_string kps = { + .string = lib_str, + .maxlen = MAX_LEN, +}; +static int set_name(const char *str, struct kernel_param *kp); +module_param_call(lib_name, set_name, param_get_string, &kps, S_IWUSR); + +bool use_app_setting = true; +module_param(use_app_setting, bool, 0644); +MODULE_PARM_DESC(use_app_setting, "control use of app specific settings"); + +bool use_32bit_app_setting = true; +module_param(use_32bit_app_setting, bool, 0644); +MODULE_PARM_DESC(use_32bit_app_setting, "control use of 32 bit app specific settings"); + +bool use_32bit_app_setting_pro; +module_param(use_32bit_app_setting_pro, bool, 0644); +MODULE_PARM_DESC(use_32bit_app_setting_pro, "control use of 32 bit app specific settings"); + +static int set_name(const char *str, struct kernel_param *kp) +{ + int len = strlen(str); + char *name; + + if (len >= MAX_LEN) { + pr_err("app_setting: name string too long\n"); + return -ENOSPC; + } + + /* + * echo adds '\n' which we need to chop off later + */ + name = kzalloc(len + 1, GFP_KERNEL); + if (!name) + return -ENOMEM; + + strlcpy(name, str, len + 1); + + if (name[len - 1] == '\n') + name[len - 1] = '\0'; + + mutex_lock(&mutex); + if (count < MAX_ENTRIES) { + lib_names[count] = name; + /* + * mb to ensure that the new lib_names entry is present + * before updating the view presented by get_lib_names + */ + mb(); + count++; + } else { + pr_err("app_setting: set name failed. Max entries reached\n"); + kfree(name); + mutex_unlock(&mutex); + return -EPERM; + } + mutex_unlock(&mutex); + + return 0; +} + +void switch_app_setting_bit(struct task_struct *prev, struct task_struct *next) +{ + if (prev->mm && unlikely(prev->mm->app_setting)) + clear_app_setting_bit(APP_SETTING_BIT); + + if (next->mm && unlikely(next->mm->app_setting)) + set_app_setting_bit(APP_SETTING_BIT); +} +EXPORT_SYMBOL(switch_app_setting_bit); + +void switch_32bit_app_setting_bit(struct task_struct *prev, + struct task_struct *next) +{ + if (prev->mm && unlikely(is_compat_thread(task_thread_info(prev)))) + clear_app_setting_bit_for_32bit_apps(); + + if (next->mm && unlikely(is_compat_thread(task_thread_info(next)))) + set_app_setting_bit_for_32bit_apps(); +} +EXPORT_SYMBOL(switch_32bit_app_setting_bit); + +void apply_app_setting_bit(struct file *file) +{ + bool found = false; + int i; + + if (file && file->f_path.dentry) { + const char *name = file->f_path.dentry->d_name.name; + + for (i = 0; i < count; i++) { + if (unlikely(!strcmp(name, lib_names[i]))) { + found = true; + break; + } + } + if (found) { + preempt_disable(); + set_app_setting_bit(APP_SETTING_BIT); + /* This will take care of child processes as well */ + current->mm->app_setting = 1; + preempt_enable(); + } + } +} +EXPORT_SYMBOL(apply_app_setting_bit); + +static int __init app_setting_init(void) +{ + mutex_init(&mutex); + return 0; +} +module_init(app_setting_init); diff --git a/arch/arm64/kernel/entry-fpsimd.S b/arch/arm64/kernel/entry-fpsimd.S index d90efa4852b2..1ffe15459c92 100644 --- a/arch/arm64/kernel/entry-fpsimd.S +++ b/arch/arm64/kernel/entry-fpsimd.S @@ -78,22 +78,6 @@ ENTRY(fpsimd_disable_trap) msr cpacr_el1, x0 ret ENDPROC(fpsimd_disable_trap) -ENTRY(fpsimd_settings_enable) - mrs x0, s3_1_c15_c15_0 - orr x0, x0, #(1 << 31) - isb - msr s3_1_c15_c15_0, x0 - isb - ret -ENDPROC(fpsimd_settings_enable) -ENTRY(fpsimd_settings_disable) - mrs x0, s3_1_c15_c15_0 - bic x0, x0, #(1 << 31) - isb - msr s3_1_c15_c15_0, x0 - isb - ret -ENDPROC(fpsimd_settings_disable) #endif #endif diff --git a/arch/arm64/kernel/fpsimd.c b/arch/arm64/kernel/fpsimd.c index 2ab83aaf4342..790d27e3b997 100644 --- a/arch/arm64/kernel/fpsimd.c +++ b/arch/arm64/kernel/fpsimd.c @@ -20,6 +20,7 @@ #include <linux/cpu.h> #include <linux/cpu_pm.h> #include <linux/kernel.h> +#include <linux/module.h> #include <linux/init.h> #include <linux/sched.h> #include <linux/signal.h> @@ -27,6 +28,7 @@ #include <asm/fpsimd.h> #include <asm/cputype.h> +#include <asm/app_api.h> #define FPEXC_IOF (1 << 0) #define FPEXC_DZF (1 << 1) @@ -35,6 +37,8 @@ #define FPEXC_IXF (1 << 4) #define FPEXC_IDF (1 << 7) +#define FP_SIMD_BIT 31 + /* * In order to reduce the number of times the FPSIMD state is needlessly saved * and restored, we need to keep track of two things: @@ -90,11 +94,27 @@ static DEFINE_PER_CPU(struct fpsimd_state *, fpsimd_last_state); static DEFINE_PER_CPU(int, fpsimd_stg_enable); +static int fpsimd_settings = 0x1; /* default = 0x1 */ +module_param(fpsimd_settings, int, 0644); + +void fpsimd_settings_enable(void) +{ + set_app_setting_bit(FP_SIMD_BIT); +} + +void fpsimd_settings_disable(void) +{ + clear_app_setting_bit(FP_SIMD_BIT); +} + /* * Trapped FP/ASIMD access. */ void do_fpsimd_acc(unsigned int esr, struct pt_regs *regs) { + if (!fpsimd_settings) + return; + fpsimd_disable_trap(); fpsimd_settings_disable(); this_cpu_write(fpsimd_stg_enable, 0); @@ -102,6 +122,9 @@ void do_fpsimd_acc(unsigned int esr, struct pt_regs *regs) void do_fpsimd_acc_compat(unsigned int esr, struct pt_regs *regs) { + if (!fpsimd_settings) + return; + fpsimd_disable_trap(); fpsimd_settings_enable(); this_cpu_write(fpsimd_stg_enable, 1); @@ -144,7 +167,7 @@ void fpsimd_thread_switch(struct task_struct *next) if (current->mm && !test_thread_flag(TIF_FOREIGN_FPSTATE)) fpsimd_save_state(¤t->thread.fpsimd_state); - if (__this_cpu_read(fpsimd_stg_enable)) { + if (fpsimd_settings && __this_cpu_read(fpsimd_stg_enable)) { fpsimd_settings_disable(); this_cpu_write(fpsimd_stg_enable, 0); } @@ -167,6 +190,9 @@ void fpsimd_thread_switch(struct task_struct *next) set_ti_thread_flag(task_thread_info(next), TIF_FOREIGN_FPSTATE); + if (!fpsimd_settings) + return; + if (test_ti_thread_flag(task_thread_info(next), TIF_32BIT)) fpsimd_enable_trap(); else diff --git a/drivers/leds/leds-qpnp-flash.c b/drivers/leds/leds-qpnp-flash.c index cd76941b87ca..493631774936 100644 --- a/drivers/leds/leds-qpnp-flash.c +++ b/drivers/leds/leds-qpnp-flash.c @@ -226,11 +226,13 @@ struct flash_led_platform_data { }; struct qpnp_flash_led_buffer { - struct mutex debugfs_lock; /* Prevent thread concurrency */ - size_t rpos; - size_t wpos; - size_t len; - char data[0]; + struct mutex debugfs_lock; /* Prevent thread concurrency */ + size_t rpos; + size_t wpos; + size_t len; + struct qpnp_flash_led *led; + u32 buffer_cnt; + char data[0]; }; /* @@ -249,10 +251,8 @@ struct qpnp_flash_led { struct workqueue_struct *ordered_workq; struct qpnp_vadc_chip *vadc_dev; struct mutex flash_led_lock; - struct qpnp_flash_led_buffer *log; struct dentry *dbgfs_root; int num_leds; - u32 buffer_cnt; u16 base; u16 current_addr; u16 current2_addr; @@ -284,10 +284,10 @@ static int flash_led_dbgfs_file_open(struct qpnp_flash_led *led, log->wpos = 0; log->len = logbufsize - sizeof(*log); mutex_init(&log->debugfs_lock); - led->log = log; + log->led = led; - led->buffer_cnt = 1; - file->private_data = led; + log->buffer_cnt = 1; + file->private_data = log; return 0; } @@ -301,12 +301,12 @@ static int flash_led_dfs_open(struct inode *inode, struct file *file) static int flash_led_dfs_close(struct inode *inode, struct file *file) { - struct qpnp_flash_led *led = file->private_data; + struct qpnp_flash_led_buffer *log = file->private_data; - if (led && led->log) { + if (log) { file->private_data = NULL; - mutex_destroy(&led->log->debugfs_lock); - kfree(led->log); + mutex_destroy(&log->debugfs_lock); + kfree(log); } return 0; @@ -335,15 +335,21 @@ static int print_to_log(struct qpnp_flash_led_buffer *log, static ssize_t flash_led_dfs_latched_reg_read(struct file *fp, char __user *buf, size_t count, loff_t *ppos) { - struct qpnp_flash_led *led = fp->private_data; - struct qpnp_flash_led_buffer *log = led->log; + struct qpnp_flash_led_buffer *log = fp->private_data; + struct qpnp_flash_led *led; uint val; int rc = 0; size_t len; size_t ret; + if (!log) { + pr_err("error: file private data is NULL\n"); + return -EFAULT; + } + led = log->led; + mutex_lock(&log->debugfs_lock); - if ((log->rpos >= log->wpos && led->buffer_cnt == 0) || + if ((log->rpos >= log->wpos && log->buffer_cnt == 0) || ((log->len - log->wpos) < MIN_BUFFER_WRITE_LEN)) goto unlock_mutex; @@ -354,7 +360,7 @@ static ssize_t flash_led_dfs_latched_reg_read(struct file *fp, char __user *buf, INT_LATCHED_STS(led->base), rc); goto unlock_mutex; } - led->buffer_cnt--; + log->buffer_cnt--; rc = print_to_log(log, "0x%05X ", INT_LATCHED_STS(led->base)); if (rc == 0) @@ -389,18 +395,24 @@ unlock_mutex: static ssize_t flash_led_dfs_fault_reg_read(struct file *fp, char __user *buf, size_t count, loff_t *ppos) { - struct qpnp_flash_led *led = fp->private_data; - struct qpnp_flash_led_buffer *log = led->log; + struct qpnp_flash_led_buffer *log = fp->private_data; + struct qpnp_flash_led *led; int rc = 0; size_t len; size_t ret; + if (!log) { + pr_err("error: file private data is NULL\n"); + return -EFAULT; + } + led = log->led; + mutex_lock(&log->debugfs_lock); - if ((log->rpos >= log->wpos && led->buffer_cnt == 0) || + if ((log->rpos >= log->wpos && log->buffer_cnt == 0) || ((log->len - log->wpos) < MIN_BUFFER_WRITE_LEN)) goto unlock_mutex; - led->buffer_cnt--; + log->buffer_cnt--; rc = print_to_log(log, "0x%05X ", FLASH_LED_FAULT_STATUS(led->base)); if (rc == 0) @@ -442,10 +454,17 @@ static ssize_t flash_led_dfs_fault_reg_enable(struct file *file, int data; size_t ret = 0; - struct qpnp_flash_led *led = file->private_data; + struct qpnp_flash_led_buffer *log = file->private_data; + struct qpnp_flash_led *led; char *kbuf; - mutex_lock(&led->log->debugfs_lock); + if (!log) { + pr_err("error: file private data is NULL\n"); + return -EFAULT; + } + led = log->led; + + mutex_lock(&log->debugfs_lock); kbuf = kmalloc(count + 1, GFP_KERNEL); if (!kbuf) { ret = -ENOMEM; @@ -480,7 +499,7 @@ static ssize_t flash_led_dfs_fault_reg_enable(struct file *file, free_buf: kfree(kbuf); unlock_mutex: - mutex_unlock(&led->log->debugfs_lock); + mutex_unlock(&log->debugfs_lock); return ret; } @@ -492,10 +511,17 @@ static ssize_t flash_led_dfs_dbg_enable(struct file *file, int cnt = 0; int data; size_t ret = 0; - struct qpnp_flash_led *led = file->private_data; + struct qpnp_flash_led_buffer *log = file->private_data; + struct qpnp_flash_led *led; char *kbuf; - mutex_lock(&led->log->debugfs_lock); + if (!log) { + pr_err("error: file private data is NULL\n"); + return -EFAULT; + } + led = log->led; + + mutex_lock(&log->debugfs_lock); kbuf = kmalloc(count + 1, GFP_KERNEL); if (!kbuf) { ret = -ENOMEM; @@ -529,7 +555,7 @@ static ssize_t flash_led_dfs_dbg_enable(struct file *file, free_buf: kfree(kbuf); unlock_mutex: - mutex_unlock(&led->log->debugfs_lock); + mutex_unlock(&log->debugfs_lock); return ret; } diff --git a/drivers/net/can/spi/rh850.c b/drivers/net/can/spi/rh850.c index 23928547c4a9..e4e9f5d0337f 100644 --- a/drivers/net/can/spi/rh850.c +++ b/drivers/net/can/spi/rh850.c @@ -86,6 +86,18 @@ struct spi_miso { /* TLV for MISO line */ #define CMD_CAN_RECEIVE_FRAME 0x85 #define CMD_CAN_CONFIG_BIT_TIMING 0x86 +#define CMD_CAN_DATA_BUFF_ADD 0x87 +#define CMD_CAN_DATA_BUFF_REMOVE 0X88 +#define CMD_CAN_RELEASE_BUFFER 0x89 +#define CMD_CAN_DATA_BUFF_REMOVE_ALL 0x8A + +#define IOCTL_RELEASE_CAN_BUFFER (SIOCDEVPRIVATE + 0) +#define IOCTL_ENABLE_BUFFERING (SIOCDEVPRIVATE + 1) +#define IOCTL_ADD_FRAME_FILTER (SIOCDEVPRIVATE + 2) +#define IOCTL_REMOVE_FRAME_FILTER (SIOCDEVPRIVATE + 3) +#define IOCTL_DISABLE_BUFFERING (SIOCDEVPRIVATE + 5) +#define IOCTL_DISABLE_ALL_BUFFERING (SIOCDEVPRIVATE + 6) + struct can_fw_resp { u8 maj; u8 min; @@ -147,6 +159,23 @@ static struct can_bittiming_const rh850_bittiming_const = { .brp_inc = 1, }; +/* IOCTL messages */ +struct rh850_release_can_buffer { + u8 enable; +} __packed; + +struct rh850_add_can_buffer { + u8 can_if; + u32 mid; + u32 mask; +} __packed; + +struct rh850_delete_can_buffer { + u8 can_if; + u32 mid; + u32 mask; +} __packed; + static int rh850_rx_message(struct rh850_can *priv_data); static irqreturn_t rh850_irq(int irq, void *priv) @@ -513,10 +542,178 @@ static netdev_tx_t rh850_netdev_start_xmit( return NETDEV_TX_OK; } +static int rh850_send_release_can_buffer_cmd(struct net_device *netdev) +{ + char *tx_buf, *rx_buf; + int ret; + struct spi_mosi *req; + struct rh850_can *priv_data; + struct rh850_netdev_privdata *netdev_priv_data; + + netdev_priv_data = netdev_priv(netdev); + priv_data = netdev_priv_data->rh850_can; + mutex_lock(&priv_data->spi_lock); + tx_buf = priv_data->tx_buf; + rx_buf = priv_data->rx_buf; + memset(tx_buf, 0, XFER_BUFFER_SIZE); + memset(rx_buf, 0, XFER_BUFFER_SIZE); + priv_data->xfer_length = XFER_BUFFER_SIZE; + + req = (struct spi_mosi *)tx_buf; + req->cmd = CMD_CAN_RELEASE_BUFFER; + req->len = 0; + req->seq = atomic_inc_return(&priv_data->msg_seq); + + ret = rh850_do_spi_transaction(priv_data); + mutex_unlock(&priv_data->spi_lock); + + return ret; +} + +static int rh850_data_buffering(struct net_device *netdev, + struct ifreq *ifr, int cmd) +{ + char *tx_buf, *rx_buf; + int ret; + struct spi_mosi *req; + struct rh850_add_can_buffer *enable_buffering; + struct rh850_add_can_buffer *add_request; + struct rh850_can *priv_data; + struct rh850_netdev_privdata *netdev_priv_data; + + netdev_priv_data = netdev_priv(netdev); + priv_data = netdev_priv_data->rh850_can; + + mutex_lock(&priv_data->spi_lock); + tx_buf = priv_data->tx_buf; + rx_buf = priv_data->rx_buf; + memset(tx_buf, 0, XFER_BUFFER_SIZE); + memset(rx_buf, 0, XFER_BUFFER_SIZE); + priv_data->xfer_length = XFER_BUFFER_SIZE; + + add_request = ifr->ifr_data; + req = (struct spi_mosi *)tx_buf; + + if (cmd == IOCTL_ENABLE_BUFFERING) + req->cmd = CMD_CAN_DATA_BUFF_ADD; + else + req->cmd = CMD_CAN_DATA_BUFF_REMOVE; + + req->len = sizeof(struct rh850_add_can_buffer); + req->seq = atomic_inc_return(&priv_data->msg_seq); + + enable_buffering = (struct rh850_add_can_buffer *)req->data; + enable_buffering->can_if = add_request->can_if; + enable_buffering->mid = add_request->mid; + enable_buffering->mask = add_request->mask; + + ret = rh850_do_spi_transaction(priv_data); + mutex_unlock(&priv_data->spi_lock); + + return ret; +} + +static int rh850_remove_all_buffering(struct net_device *netdev) +{ + char *tx_buf, *rx_buf; + int ret; + struct spi_mosi *req; + struct rh850_can *priv_data; + struct rh850_netdev_privdata *netdev_priv_data; + + netdev_priv_data = netdev_priv(netdev); + priv_data = netdev_priv_data->rh850_can; + + mutex_lock(&priv_data->spi_lock); + tx_buf = priv_data->tx_buf; + rx_buf = priv_data->rx_buf; + memset(tx_buf, 0, XFER_BUFFER_SIZE); + memset(rx_buf, 0, XFER_BUFFER_SIZE); + priv_data->xfer_length = XFER_BUFFER_SIZE; + + req = (struct spi_mosi *)tx_buf; + req->cmd = CMD_CAN_DATA_BUFF_REMOVE_ALL; + req->len = 0; + req->seq = atomic_inc_return(&priv_data->msg_seq); + + ret = rh850_do_spi_transaction(priv_data); + mutex_unlock(&priv_data->spi_lock); + + return ret; +} + +static int rh850_frame_filter(struct net_device *netdev, + struct ifreq *ifr, int cmd) +{ + char *tx_buf, *rx_buf; + int ret; + struct spi_mosi *req; + struct can_add_filter_req *add_filter; + struct can_add_filter_req *filter_request; + struct rh850_can *priv_data; + struct rh850_netdev_privdata *netdev_priv_data; + + netdev_priv_data = netdev_priv(netdev); + priv_data = netdev_priv_data->rh850_can; + + mutex_lock(&priv_data->spi_lock); + tx_buf = priv_data->tx_buf; + rx_buf = priv_data->rx_buf; + memset(tx_buf, 0, XFER_BUFFER_SIZE); + memset(rx_buf, 0, XFER_BUFFER_SIZE); + priv_data->xfer_length = XFER_BUFFER_SIZE; + + filter_request = ifr->ifr_data; + req = (struct spi_mosi *)tx_buf; + + if (cmd == IOCTL_ADD_FRAME_FILTER) + req->cmd = CMD_CAN_ADD_FILTER; + else + req->cmd = CMD_CAN_REMOVE_FILTER; + + req->len = sizeof(struct can_add_filter_req); + req->seq = atomic_inc_return(&priv_data->msg_seq); + + add_filter = (struct can_add_filter_req *)req->data; + add_filter->can_if = filter_request->can_if; + add_filter->mid = filter_request->mid; + add_filter->mask = filter_request->mask; + + ret = rh850_do_spi_transaction(priv_data); + mutex_unlock(&priv_data->spi_lock); + + return ret; +} + +static int rh850_netdev_do_ioctl(struct net_device *netdev, + struct ifreq *ifr, int cmd) +{ + struct rh850_can *priv_data; + struct rh850_netdev_privdata *netdev_priv_data; + + netdev_priv_data = netdev_priv(netdev); + priv_data = netdev_priv_data->rh850_can; + + if (cmd == IOCTL_RELEASE_CAN_BUFFER) { + rh850_send_release_can_buffer_cmd(netdev); + } else if (cmd == IOCTL_ENABLE_BUFFERING || + cmd == IOCTL_DISABLE_BUFFERING) { + rh850_data_buffering(netdev, ifr, cmd); + } else if (cmd == IOCTL_DISABLE_ALL_BUFFERING) { + rh850_remove_all_buffering(netdev); + } else if (cmd == IOCTL_ADD_FRAME_FILTER || + cmd == IOCTL_REMOVE_FRAME_FILTER) { + rh850_frame_filter(netdev, ifr, cmd); + } + + return 0; +} + static const struct net_device_ops rh850_netdev_ops = { .ndo_open = rh850_netdev_open, .ndo_stop = rh850_netdev_close, .ndo_start_xmit = rh850_netdev_start_xmit, + .ndo_do_ioctl = rh850_netdev_do_ioctl, }; static int rh850_create_netdev(struct spi_device *spi, diff --git a/drivers/platform/msm/gpio-usbdetect.c b/drivers/platform/msm/gpio-usbdetect.c index 80e16573e0aa..789b14dcfeca 100644 --- a/drivers/platform/msm/gpio-usbdetect.c +++ b/drivers/platform/msm/gpio-usbdetect.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2013-2015, The Linux Foundation. All rights reserved. +/* Copyright (c) 2017, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -20,57 +20,101 @@ #include <linux/interrupt.h> #include <linux/of_gpio.h> #include <linux/gpio.h> -#include <linux/power_supply.h> +#include <linux/extcon.h> #include <linux/regulator/consumer.h> struct gpio_usbdetect { struct platform_device *pdev; struct regulator *vin; - struct power_supply *usb_psy; int vbus_det_irq; + int id_det_irq; int gpio; + struct extcon_dev *extcon_dev; + int vbus_state; + bool id_state; +}; + +static const unsigned int gpio_usb_extcon_table[] = { + EXTCON_USB, + EXTCON_USB_HOST, + EXTCON_USB_CC, + EXTCON_USB_SPEED, + EXTCON_NONE, }; static irqreturn_t gpio_usbdetect_vbus_irq(int irq, void *data) { struct gpio_usbdetect *usb = data; - int vbus; - union power_supply_propval pval = {0,}; - vbus = gpio_get_value(usb->gpio); - if (vbus) - pval.intval = POWER_SUPPLY_TYPE_USB; - else - pval.intval = POWER_SUPPLY_TYPE_UNKNOWN; + usb->vbus_state = gpio_get_value(usb->gpio); + if (usb->vbus_state) { + dev_dbg(&usb->pdev->dev, "setting vbus notification\n"); + extcon_set_cable_state_(usb->extcon_dev, EXTCON_USB, 1); + } else { + dev_dbg(&usb->pdev->dev, "setting vbus removed notification\n"); + extcon_set_cable_state_(usb->extcon_dev, EXTCON_USB, 0); + } + + return IRQ_HANDLED; +} + +static irqreturn_t gpio_usbdetect_id_irq(int irq, void *data) +{ + struct gpio_usbdetect *usb = data; + int ret; + + ret = irq_get_irqchip_state(irq, IRQCHIP_STATE_LINE_LEVEL, + &usb->id_state); + if (ret < 0) { + dev_err(&usb->pdev->dev, "unable to read ID IRQ LINE\n"); + return IRQ_HANDLED; + } - power_supply_set_property(usb->usb_psy, - POWER_SUPPLY_PROP_TYPE, &pval); + return IRQ_WAKE_THREAD; +} - pval.intval = vbus; - power_supply_set_property(usb->usb_psy, POWER_SUPPLY_PROP_PRESENT, - &pval); +static irqreturn_t gpio_usbdetect_id_irq_thread(int irq, void *data) +{ + struct gpio_usbdetect *usb = data; + + if (usb->id_state) { + dev_dbg(&usb->pdev->dev, "stopping usb host\n"); + extcon_set_cable_state_(usb->extcon_dev, EXTCON_USB_HOST, 0); + enable_irq(usb->vbus_det_irq); + } else { + dev_dbg(&usb->pdev->dev, "starting usb HOST\n"); + disable_irq(usb->vbus_det_irq); + extcon_set_cable_state_(usb->extcon_dev, EXTCON_USB_HOST, 1); + } return IRQ_HANDLED; } +static const u32 gpio_usb_extcon_exclusive[] = {0x3, 0}; + static int gpio_usbdetect_probe(struct platform_device *pdev) { struct gpio_usbdetect *usb; - struct power_supply *usb_psy; int rc; - unsigned long flags; - - usb_psy = power_supply_get_by_name("usb"); - if (!usb_psy) { - dev_dbg(&pdev->dev, "USB power_supply not found, deferring probe\n"); - return -EPROBE_DEFER; - } usb = devm_kzalloc(&pdev->dev, sizeof(*usb), GFP_KERNEL); if (!usb) return -ENOMEM; usb->pdev = pdev; - usb->usb_psy = usb_psy; + + usb->extcon_dev = devm_extcon_dev_allocate(&pdev->dev, + gpio_usb_extcon_table); + if (IS_ERR(usb->extcon_dev)) { + dev_err(&pdev->dev, "failed to allocate a extcon device\n"); + return PTR_ERR(usb->extcon_dev); + } + + usb->extcon_dev->mutually_exclusive = gpio_usb_extcon_exclusive; + rc = devm_extcon_dev_register(&pdev->dev, usb->extcon_dev); + if (rc) { + dev_err(&pdev->dev, "failed to register extcon device\n"); + return rc; + } if (of_get_property(pdev->dev.of_node, "vin-supply", NULL)) { usb->vin = devm_regulator_get(&pdev->dev, "vin"); @@ -94,43 +138,63 @@ static int gpio_usbdetect_probe(struct platform_device *pdev) "qcom,vbus-det-gpio", 0); if (usb->gpio < 0) { dev_err(&pdev->dev, "Failed to get gpio: %d\n", usb->gpio); - return usb->gpio; + rc = usb->gpio; + goto error; } rc = gpio_request(usb->gpio, "vbus-det-gpio"); if (rc < 0) { dev_err(&pdev->dev, "Failed to request gpio: %d\n", rc); - return rc; + goto error; } usb->vbus_det_irq = gpio_to_irq(usb->gpio); if (usb->vbus_det_irq < 0) { - if (usb->vin) - regulator_disable(usb->vin); - return usb->vbus_det_irq; + dev_err(&pdev->dev, "get vbus_det_irq failed\n"); + rc = usb->vbus_det_irq; + goto error; } - rc = devm_request_irq(&pdev->dev, usb->vbus_det_irq, - gpio_usbdetect_vbus_irq, - IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, - "vbus_det_irq", usb); + rc = devm_request_threaded_irq(&pdev->dev, usb->vbus_det_irq, + NULL, gpio_usbdetect_vbus_irq, + IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING | + IRQF_ONESHOT, "vbus_det_irq", usb); if (rc) { dev_err(&pdev->dev, "request for vbus_det_irq failed: %d\n", rc); - if (usb->vin) - regulator_disable(usb->vin); - return rc; + goto error; + } + + usb->id_det_irq = platform_get_irq_byname(pdev, "pmic_id_irq"); + if (usb->id_det_irq < 0) { + dev_err(&pdev->dev, "get id_det_irq failed\n"); + rc = usb->id_det_irq; + goto error; + } + + rc = devm_request_threaded_irq(&pdev->dev, usb->id_det_irq, + gpio_usbdetect_id_irq, + gpio_usbdetect_id_irq_thread, + IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING | + IRQF_ONESHOT, "id_det_irq", usb); + if (rc) { + dev_err(&pdev->dev, "request for id_det_irq failed: %d\n", rc); + goto error; } enable_irq_wake(usb->vbus_det_irq); + enable_irq_wake(usb->id_det_irq); dev_set_drvdata(&pdev->dev, usb); /* Read and report initial VBUS state */ - local_irq_save(flags); gpio_usbdetect_vbus_irq(usb->vbus_det_irq, usb); - local_irq_restore(flags); return 0; + +error: + if (usb->vin) + regulator_disable(usb->vin); + return rc; } static int gpio_usbdetect_remove(struct platform_device *pdev) @@ -139,6 +203,8 @@ static int gpio_usbdetect_remove(struct platform_device *pdev) disable_irq_wake(usb->vbus_det_irq); disable_irq(usb->vbus_det_irq); + disable_irq_wake(usb->id_det_irq); + disable_irq(usb->id_det_irq); if (usb->vin) regulator_disable(usb->vin); diff --git a/drivers/video/fbdev/Makefile b/drivers/video/fbdev/Makefile index f6f65ccce8e7..238e851c0705 100644 --- a/drivers/video/fbdev/Makefile +++ b/drivers/video/fbdev/Makefile @@ -126,7 +126,11 @@ obj-y += omap2/ obj-$(CONFIG_XEN_FBDEV_FRONTEND) += xen-fbfront.o obj-$(CONFIG_FB_CARMINE) += carminefb.o obj-$(CONFIG_FB_MB862XX) += mb862xx/ -obj-$(CONFIG_FB_MSM) += msm/ +ifeq ($(CONFIG_FB_MSM),y) +obj-y += msm/ +else +obj-$(CONFIG_MSM_DBA) += msm/msm_dba/ +endif obj-$(CONFIG_FB_NUC900) += nuc900fb.o obj-$(CONFIG_FB_JZ4740) += jz4740_fb.o obj-$(CONFIG_FB_PUV3_UNIGFX) += fb-puv3.o diff --git a/drivers/video/fbdev/msm/msm_dba/adv7533.c b/drivers/video/fbdev/msm/msm_dba/adv7533.c index 8503d84e0de4..3af98fcd70bb 100644 --- a/drivers/video/fbdev/msm/msm_dba/adv7533.c +++ b/drivers/video/fbdev/msm/msm_dba/adv7533.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2015-2016, The Linux Foundation. All rights reserved. +/* Copyright (c) 2015-2017, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -1539,14 +1539,14 @@ exit: static int adv7533_video_on(void *client, bool on, struct msm_dba_video_cfg *cfg, u32 flags) { - int ret = -EINVAL; + int ret = 0; u8 lanes; u8 reg_val = 0; struct adv7533 *pdata = adv7533_get_platform_data(client); if (!pdata || !cfg) { pr_err("%s: invalid platform data\n", __func__); - return ret; + return -EINVAL; } mutex_lock(&pdata->ops_mutex); diff --git a/drivers/video/fbdev/msm/msm_dba/msm_dba_helpers.c b/drivers/video/fbdev/msm/msm_dba/msm_dba_helpers.c index f6128ae01a75..a0b45bfccb3c 100644 --- a/drivers/video/fbdev/msm/msm_dba/msm_dba_helpers.c +++ b/drivers/video/fbdev/msm/msm_dba/msm_dba_helpers.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, The Linux Foundation. All rights reserved. + * Copyright (c) 2015, 2017, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -123,7 +123,7 @@ int msm_dba_helper_i2c_write_byte(struct i2c_client *client, return -EINVAL; } - pr_debug("%s: [%s:0x02%x] : W[0x%02x, 0x%02x]\n", __func__, + pr_debug("%s: [%s:0x%02x] : W[0x%02x, 0x%02x]\n", __func__, client->name, addr, reg, val); client->addr = addr; diff --git a/include/linux/mm_types.h b/include/linux/mm_types.h index ea0009064bbc..9f9e60736eba 100644 --- a/include/linux/mm_types.h +++ b/include/linux/mm_types.h @@ -522,6 +522,10 @@ struct mm_struct { #ifdef CONFIG_HUGETLB_PAGE atomic_long_t hugetlb_usage; #endif +#ifdef CONFIG_MSM_APP_SETTINGS + int app_setting; +#endif + }; static inline void mm_init_cpumask(struct mm_struct *mm) diff --git a/include/uapi/linux/rmnet_data.h b/include/uapi/linux/rmnet_data.h index 8cfe0270ef4f..7ddfa20cec32 100644 --- a/include/uapi/linux/rmnet_data.h +++ b/include/uapi/linux/rmnet_data.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2015, The Linux Foundation. All rights reserved. + * Copyright (c) 2013-2015, 2017 The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -223,8 +223,19 @@ enum rmnet_netlink_message_types_e { * uint32_t MAP Flow Handle * Returns: status code */ - RMNET_NETLINK_DEL_VND_TC_FLOW + RMNET_NETLINK_DEL_VND_TC_FLOW, + + /* + * RMNET_NETLINK_NEW_VND_WITH_NAME - Creates a new virtual network + * device node with the specified + * device name + * Args: int32_t node number + * char[] vnd_name - Use as name + * Returns: status code + */ + RMNET_NETLINK_NEW_VND_WITH_NAME }; +#define RMNET_NETLINK_NEW_VND_WITH_NAME RMNET_NETLINK_NEW_VND_WITH_NAME enum rmnet_config_endpoint_modes_e { /* Pass the frame up the stack with no modifications to skb->dev */ diff --git a/kernel/sched/core.c b/kernel/sched/core.c index 3fcadbae663d..1803feb0006c 100644 --- a/kernel/sched/core.c +++ b/kernel/sched/core.c @@ -84,6 +84,9 @@ #ifdef CONFIG_PARAVIRT #include <asm/paravirt.h> #endif +#ifdef CONFIG_MSM_APP_SETTINGS +#include <asm/app_api.h> +#endif #include "sched.h" #include "../workqueue_internal.h" @@ -2722,6 +2725,14 @@ prepare_task_switch(struct rq *rq, struct task_struct *prev, fire_sched_out_preempt_notifiers(prev, next); prepare_lock_switch(rq, next); prepare_arch_switch(next); + +#ifdef CONFIG_MSM_APP_SETTINGS + if (use_app_setting) + switch_app_setting_bit(prev, next); + + if (use_32bit_app_setting || use_32bit_app_setting_pro) + switch_32bit_app_setting_bit(prev, next); +#endif } /** diff --git a/mm/mmap.c b/mm/mmap.c index a089cca8d79a..ebc9d1923c3d 100644 --- a/mm/mmap.c +++ b/mm/mmap.c @@ -48,6 +48,10 @@ #include <asm/tlb.h> #include <asm/mmu_context.h> +#ifdef CONFIG_MSM_APP_SETTINGS +#include <asm/app_api.h> +#endif + #include "internal.h" #ifndef arch_mmap_check @@ -1297,6 +1301,11 @@ unsigned long do_mmap(struct file *file, unsigned long addr, if (!len) return -EINVAL; +#ifdef CONFIG_MSM_APP_SETTINGS + if (use_app_setting) + apply_app_setting_bit(file); +#endif + /* * Does the application expect PROT_READ to imply PROT_EXEC? * diff --git a/net/rmnet_data/rmnet_data_config.c b/net/rmnet_data/rmnet_data_config.c index fb4c60fc2203..fad084d03854 100644 --- a/net/rmnet_data/rmnet_data_config.c +++ b/net/rmnet_data/rmnet_data_config.c @@ -638,6 +638,13 @@ void rmnet_config_netlink_msg_handler(struct sk_buff *skb) rmnet_header->vnd.vnd_name); break; + case RMNET_NETLINK_NEW_VND_WITH_NAME: + resp_rmnet->crd = RMNET_NETLINK_MSG_RETURNCODE; + resp_rmnet->return_code = rmnet_create_vnd_name( + rmnet_header->vnd.id, + rmnet_header->vnd.vnd_name); + break; + case RMNET_NETLINK_FREE_VND: resp_rmnet->crd = RMNET_NETLINK_MSG_RETURNCODE; /* Please check rmnet_vnd_free_dev documentation regarding @@ -1087,11 +1094,11 @@ int rmnet_create_vnd(int id) struct net_device *dev; ASSERT_RTNL(); LOGL("(%d);", id); - return rmnet_vnd_create_dev(id, &dev, NULL); + return rmnet_vnd_create_dev(id, &dev, NULL, 0); } /** - * rmnet_create_vnd() - Create virtual network device node + * rmnet_create_vnd_prefix() - Create virtual network device node * @id: RmNet virtual device node id * @prefix: String prefix for device name * @@ -1103,7 +1110,24 @@ int rmnet_create_vnd_prefix(int id, const char *prefix) struct net_device *dev; ASSERT_RTNL(); LOGL("(%d, \"%s\");", id, prefix); - return rmnet_vnd_create_dev(id, &dev, prefix); + return rmnet_vnd_create_dev(id, &dev, prefix, 0); +} + +/** + * rmnet_create_vnd_name() - Create virtual network device node + * @id: RmNet virtual device node id + * @prefix: String prefix for device name + * + * Return: + * - result of rmnet_vnd_create_dev() + */ +int rmnet_create_vnd_name(int id, const char *name) +{ + struct net_device *dev; + + ASSERT_RTNL(); + LOGL("(%d, \"%s\");", id, name); + return rmnet_vnd_create_dev(id, &dev, name, 1); } /** diff --git a/net/rmnet_data/rmnet_data_config.h b/net/rmnet_data/rmnet_data_config.h index f19fbb378111..208c3a40c3ae 100644 --- a/net/rmnet_data/rmnet_data_config.h +++ b/net/rmnet_data/rmnet_data_config.h @@ -124,6 +124,7 @@ int rmnet_config_notify_cb(struct notifier_block *nb, unsigned long event, void *data); int rmnet_create_vnd(int id); int rmnet_create_vnd_prefix(int id, const char *name); +int rmnet_create_vnd_name(int id, const char *name); int rmnet_free_vnd(int id); struct rmnet_phys_ep_config *_rmnet_get_phys_ep_config diff --git a/net/rmnet_data/rmnet_data_vnd.c b/net/rmnet_data/rmnet_data_vnd.c index 2819da9ae3f2..ede1a54661cd 100644 --- a/net/rmnet_data/rmnet_data_vnd.c +++ b/net/rmnet_data/rmnet_data_vnd.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2016, The Linux Foundation. All rights reserved. + * Copyright (c) 2013-2017, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -565,7 +565,7 @@ int rmnet_vnd_init(void) * - RMNET_CONFIG_UNKNOWN_ERROR if register_netdevice() fails */ int rmnet_vnd_create_dev(int id, struct net_device **new_device, - const char *prefix) + const char *prefix, int use_name) { struct net_device *dev; char dev_prefix[IFNAMSIZ]; @@ -581,12 +581,15 @@ int rmnet_vnd_create_dev(int id, struct net_device **new_device, return RMNET_CONFIG_DEVICE_IN_USE; } - if (!prefix) + if (!prefix && !use_name) p = scnprintf(dev_prefix, IFNAMSIZ, "%s%%d", RMNET_DATA_DEV_NAME_STR); + else if (prefix && use_name) + p = scnprintf(dev_prefix, IFNAMSIZ, "%s", prefix); + else if (prefix && !use_name) + p = scnprintf(dev_prefix, IFNAMSIZ, "%s%%d", prefix); else - p = scnprintf(dev_prefix, IFNAMSIZ, "%s%%d", - prefix); + return RMNET_CONFIG_BAD_ARGUMENTS; if (p >= (IFNAMSIZ-1)) { LOGE("Specified prefix longer than IFNAMSIZ"); return RMNET_CONFIG_BAD_ARGUMENTS; @@ -594,7 +597,7 @@ int rmnet_vnd_create_dev(int id, struct net_device **new_device, dev = alloc_netdev(sizeof(struct rmnet_vnd_private_s), dev_prefix, - NET_NAME_ENUM, + use_name ? NET_NAME_UNKNOWN : NET_NAME_ENUM, rmnet_vnd_setup); if (!dev) { LOGE("Failed to to allocate netdev for id %d", id); diff --git a/net/rmnet_data/rmnet_data_vnd.h b/net/rmnet_data/rmnet_data_vnd.h index 22ffcfc2e08e..7a1af24fa051 100644 --- a/net/rmnet_data/rmnet_data_vnd.h +++ b/net/rmnet_data/rmnet_data_vnd.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2016, The Linux Foundation. All rights reserved. + * Copyright (c) 2013-2017, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -27,7 +27,7 @@ int rmnet_vnd_do_flow_control(struct net_device *dev, struct rmnet_logical_ep_conf_s *rmnet_vnd_get_le_config(struct net_device *dev); int rmnet_vnd_get_name(int id, char *name, int name_len); int rmnet_vnd_create_dev(int id, struct net_device **new_device, - const char *prefix); + const char *prefix, int use_name); int rmnet_vnd_free_dev(int id); int rmnet_vnd_rx_fixup(struct sk_buff *skb, struct net_device *dev); int rmnet_vnd_tx_fixup(struct sk_buff *skb, struct net_device *dev); |