summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Documentation/devicetree/bindings/net/neutrino_avb.txt28
-rw-r--r--arch/arm/boot/dts/qcom/apq8096-auto-dragonboard.dtsi26
-rw-r--r--arch/arm/boot/dts/qcom/msm8996-agave-adp.dtsi42
-rw-r--r--arch/arm/boot/dts/qcom/msm8996-auto-cdp.dtsi25
-rw-r--r--arch/arm/boot/dts/qcom/msm8996.dtsi4
-rw-r--r--arch/arm/boot/dts/qcom/msm8996pro.dtsi6
-rw-r--r--arch/arm64/Kconfig21
-rw-r--r--arch/arm64/configs/msm-auto-perf_defconfig5
-rw-r--r--arch/arm64/configs/msm-auto_defconfig5
-rw-r--r--arch/arm64/configs/msm-perf_defconfig2
-rw-r--r--arch/arm64/configs/msm_defconfig2
-rw-r--r--arch/arm64/include/asm/app_api.h50
-rw-r--r--arch/arm64/include/asm/elf.h2
-rw-r--r--arch/arm64/include/asm/fpsimd.h4
-rw-r--r--arch/arm64/kernel/Makefile2
-rw-r--r--arch/arm64/kernel/app_api.c135
-rw-r--r--arch/arm64/kernel/app_setting.c139
-rw-r--r--arch/arm64/kernel/entry-fpsimd.S16
-rw-r--r--arch/arm64/kernel/fpsimd.c28
-rw-r--r--drivers/leds/leds-qpnp-flash.c82
-rw-r--r--drivers/net/can/spi/rh850.c197
-rw-r--r--drivers/platform/msm/gpio-usbdetect.c142
-rw-r--r--drivers/video/fbdev/Makefile6
-rw-r--r--drivers/video/fbdev/msm/msm_dba/adv7533.c6
-rw-r--r--drivers/video/fbdev/msm/msm_dba/msm_dba_helpers.c4
-rw-r--r--include/linux/mm_types.h4
-rw-r--r--include/uapi/linux/rmnet_data.h15
-rw-r--r--kernel/sched/core.c11
-rw-r--r--mm/mmap.c9
-rw-r--r--net/rmnet_data/rmnet_data_config.c30
-rw-r--r--net/rmnet_data/rmnet_data_config.h1
-rw-r--r--net/rmnet_data/rmnet_data_vnd.c15
-rw-r--r--net/rmnet_data/rmnet_data_vnd.h4
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(&current->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);