Merge "msm: mdss: call wait4comp before wb kickoff"
diff --git a/Documentation/arm/msm/msm_ipc_logging.txt b/Documentation/arm/msm/msm_ipc_logging.txt
index cb330b0..9d42200 100644
--- a/Documentation/arm/msm/msm_ipc_logging.txt
+++ b/Documentation/arm/msm/msm_ipc_logging.txt
@@ -66,34 +66,71 @@
Log Space
----------
-Each context will have an associated log space, which is dynamically
-allocated from the kernel memory-space. The log space is organized as a
-list of kernel memory pages. Each page contains header information which
-is used to differentiate the log kernel page from the other kernel pages.
+Each context (Figure 1) has an associated log space, which is dynamically
+allocated from the kernel memory-space. The log space is organized as a list of
+1 or more kernel memory pages. Each page (Figure 2) contains header information
+which is used to differentiate the log kernel page from the other kernel pages.
- 0 ---------------------------------
- | magic_no = 0x52784425 |
- ---------------------------------
- | nmagic_no = 0xAD87BBDA |
- ---------------------------------
- | log_id |
- ---------------------------------
- | page_num |
- ---------------------------------
- | read_offset | write_offset |
- ---------------------------------
- | next/prev page |
- ---------------------------------
- | |
- | Data |
- | . |
- | . |
- | . |
- | |
- --------------------------------- PAGE_SIZE - 1
-This approach will support extracting the logs either from the memory dumps
-or from the live targets using DEBUGFS.
+ 0 ---------------------------------
+ | magic_no = 0x25874452 |
+ ---------------------------------
+ | nmagic_no = 0x52784425 |
+ ---------------------------------
+ | version |
+ ---------------------------------
+ | user_version |
+ ---------------------------------
+ | log_id |
+ ---------------------------------
+ | header_size |
+ ---------------------------------
+ | |
+ | |
+ | name [20 chars] |
+ | |
+ | |
+ ---------------------------------
+ | run-time data structures |
+ ---------------------------------
+ Figure 1 - Log Context Structure
+
+
+ 31 0
+ 0 ---------------------------------
+ | magic_no = 0x52784425 |
+ ---------------------------------
+ | nmagic_no = 0xAD87BBDA |
+ ---------------------------------
+ |1| page_num |
+ ---------------------------------
+ | read_offset | write_offset |
+ ---------------------------------
+ | log_id |
+ ---------------------------------
+ | start_time low word |
+ | start_time high word |
+ ---------------------------------
+ | end_time low word |
+ | end_time high word |
+ ---------------------------------
+ | context offset |
+ ---------------------------------
+ | run-time data structures |
+ . . . . .
+ ---------------------------------
+ | |
+ | Log Data |
+ . . .
+ . . .
+ | |
+ --------------------------------- PAGE_SIZE - 1
+ Figure 2 - Log Page Structure
+
+In addition to extracting logs at runtime through DebugFS, IPC Logging has been
+designed to allow extraction of logs from a memory dump. The magic numbers,
+timestamps, and context offset are all added to support the memory-dump
+extraction use case.
Design
======
@@ -149,6 +186,7 @@
*
* @max_num_pages: Number of pages of logging space required (max. 10)
* @mod_name : Name of the directory entry under DEBUGFS
+ * @user_version : Version number of user-defined message formats
*
* returns reference to context on success, NULL on failure
*/
diff --git a/Documentation/devicetree/bindings/leds/leds-qpnp.txt b/Documentation/devicetree/bindings/leds/leds-qpnp.txt
index 8078abf..8c91db0 100644
--- a/Documentation/devicetree/bindings/leds/leds-qpnp.txt
+++ b/Documentation/devicetree/bindings/leds/leds-qpnp.txt
@@ -19,7 +19,7 @@
- qcom,max-current : maximum current that the LED can sustain in mA
- linux,name : name of the led that is used in led framework
-Optional properties for each child node, WLED, Flash, MPP and RGB:
+Optional properties for each child node, WLED, Flash, MPP, RGB and KPDBL:
- qcom,in-order-command-processing : specify if user space requests leds in order
WLED is primarily used as display backlight. Display subsystem uses
@@ -121,6 +121,7 @@
for vph_pwr.
- qcom,row-src-en: specify to enable row source
- qcom,always-on: specify if the module has to be always on
+- qcom,use-blink: Use blink sysfs entry for switching into lpg mode. For optimal use, set default mode to pwm. All required lpg parameters must be supplied.
Required properties for PWM mode only:
- qcom,pwm-channel: pwm channel the led will operate on
diff --git a/Documentation/devicetree/bindings/wcnss/wcnss-wlan.txt b/Documentation/devicetree/bindings/wcnss/wcnss-wlan.txt
index 8eb9b64..2cb528c 100644
--- a/Documentation/devicetree/bindings/wcnss/wcnss-wlan.txt
+++ b/Documentation/devicetree/bindings/wcnss/wcnss-wlan.txt
@@ -27,6 +27,10 @@
should be performed during boot up.
- qcom,wlan-rx-buff-count: WLAN RX buffer count is a configurable value,
using a smaller count for this buffer will reduce the memory usage.
+=======
+- qcom,is-pronto-v3: boolean flag to determine the pronto hardware version
+in use. subsequently correct workqueue will be used by DXE engine to push frames
+in TX data path.
- qcom,wcnss-pm : <Core rail LDO#, PA rail LDO#, XO settling time,
RPM power collapse enabled, standalone power collapse enabled>
Power manager related parameter for LDO configuration.
diff --git a/Documentation/networking/ip-sysctl.txt b/Documentation/networking/ip-sysctl.txt
index 2d4a6db..4af5946 100644
--- a/Documentation/networking/ip-sysctl.txt
+++ b/Documentation/networking/ip-sysctl.txt
@@ -22,6 +22,13 @@
min_pmtu - INTEGER
default 552 - minimum discovered Path MTU
+fwmark_reflect - BOOLEAN
+ Controls the fwmark of kernel-generated IPv4 reply packets that are not
+ associated with a socket for example, TCP RSTs or ICMP echo replies).
+ If unset, these packets have a fwmark of zero. If set, they have the
+ fwmark of the packet they are replying to.
+ Default: 0
+
route/max_size - INTEGER
Maximum number of routes allowed in the kernel. Increase
this when using large numbers of interfaces and/or routes.
@@ -1048,6 +1055,13 @@
2 NDP packets are sent to userspace, where a userspace proxy
can be implemented
+fwmark_reflect - BOOLEAN
+ Controls the fwmark of kernel-generated IPv6 reply packets that are not
+ associated with a socket for example, TCP RSTs or ICMPv6 echo replies).
+ If unset, these packets have a fwmark of zero. If set, they have the
+ fwmark of the packet they are replying to.
+ Default: 0
+
conf/interface/*:
Change special settings per interface.
diff --git a/arch/arm/boot/dts/msm8226-camera-sensor-cdp.dtsi b/arch/arm/boot/dts/msm8226-camera-sensor-cdp.dtsi
index a227802..dc5324b 100644
--- a/arch/arm/boot/dts/msm8226-camera-sensor-cdp.dtsi
+++ b/arch/arm/boot/dts/msm8226-camera-sensor-cdp.dtsi
@@ -38,42 +38,6 @@
qcom,cci-master = <0>;
};
- qcom,camera@90 {
- compatible = "qcom,mt9m114";
- reg = <0x90 0x0>;
- qcom,slave-id = <0x90 0x0 0x2481>;
- qcom,csiphy-sd-index = <1>;
- qcom,csid-sd-index = <1>;
- qcom,mount-angle = <90>;
- qcom,sensor-name = "mt9m114";
- cam_vdig-supply = <&pm8226_l5>;
- cam_vana-supply = <&pm8226_l19>;
- cam_vio-supply = <&pm8226_lvs1>;
- qcom,cam-vreg-name = "cam_vdig", "cam_vio", "cam_vana";
- qcom,cam-vreg-type = <0 1 0>;
- qcom,cam-vreg-min-voltage = <1200000 0 2850000>;
- qcom,cam-vreg-max-voltage = <1200000 0 2850000>;
- qcom,cam-vreg-op-mode = <200000 0 80000>;
- qcom,gpio-no-mux = <0>;
- gpios = <&msmgpio 26 0>,
- <&msmgpio 28 0>,
- <&msmgpio 35 0>;
- qcom,gpio-reset = <1>;
- qcom,gpio-standby = <2>;
- qcom,gpio-req-tbl-num = <0 1 2>;
- qcom,gpio-req-tbl-flags = <1 0 0>;
- qcom,gpio-req-tbl-label = "CAMIF_MCLK",
- "CAM_RESET",
- "CAM_STANDBY";
- qcom,gpio-set-tbl-num = <1 1>;
- qcom,gpio-set-tbl-flags = <0 2>;
- qcom,gpio-set-tbl-delay = <1000 4000>;
- qcom,csi-lane-assign = <0x4320>;
- qcom,csi-lane-mask = <0x3>;
- qcom,sensor-position = <1>;
- qcom,sensor-mode = <1>;
- qcom,cci-master = <0>;
- };
qcom,camera@0 {
cell-index = <0>;
compatible = "qcom,camera";
@@ -139,4 +103,159 @@
qcom,cci-master = <0>;
status = "ok";
};
+
+ qcom,camera@6f {
+ compatible = "qcom,ov8825";
+ reg = <0x6f>;
+ qcom,slave-id = <0x6c 0x300a 0x8825>;
+ qcom,csiphy-sd-index = <0>;
+ qcom,csid-sd-index = <0>;
+ qcom,actuator-src = <&actuator0>;
+ qcom,led-flash-src = <&led_flash0>;
+ qcom,mount-angle = <180>;
+ qcom,sensor-name = "ov8825";
+ cam_vdig-supply = <&pm8226_l5>;
+ cam_vana-supply = <&pm8226_l19>;
+ cam_vio-supply = <&pm8226_lvs1>;
+ cam_vaf-supply = <&pm8226_l15>;
+ qcom,cam-vreg-name = "cam_vdig", "cam_vio", "cam_vana",
+ "cam_vaf";
+ qcom,cam-vreg-type = <0 1 0 0>;
+ qcom,cam-vreg-min-voltage = <1200000 0 2850000 2800000>;
+ qcom,cam-vreg-max-voltage = <1200000 0 2850000 2800000>;
+ qcom,cam-vreg-op-mode = <200000 0 80000 100000>;
+ qcom,gpio-no-mux = <0>;
+ gpios = <&msmgpio 26 0>,
+ <&msmgpio 37 0>,
+ <&msmgpio 36 0>;
+ qcom,gpio-reset = <1>;
+ qcom,gpio-standby = <2>;
+ qcom,gpio-req-tbl-num = <0 1 2>;
+ qcom,gpio-req-tbl-flags = <1 0 0>;
+ qcom,gpio-req-tbl-label = "CAMIF_MCLK",
+ "CAM_RESET1",
+ "CAM_STANDBY";
+ qcom,csi-lane-assign = <0x4320>;
+ qcom,csi-lane-mask = <0x1f>;
+ qcom,sensor-position = <0>;
+ qcom,sensor-mode = <1>;
+ qcom,cci-master = <0>;
+ };
+
+ qcom,camera@20 {
+ compatible = "qcom,imx135";
+ reg = <0x20>;
+ qcom,slave-id = <0x20 0x0016 0x0135>;
+ qcom,csiphy-sd-index = <0>;
+ qcom,csid-sd-index = <0>;
+ qcom,actuator-src = <&actuator1>;
+ qcom,mount-angle = <90>;
+ qcom,sensor-name = "imx135";
+ cam_vdig-supply = <&pm8226_l5>;
+ cam_vana-supply = <&pm8226_l19>;
+ cam_vio-supply = <&pm8226_lvs1>;
+ cam_vaf-supply = <&pm8226_l15>;
+ qcom,cam-vreg-name = "cam_vdig", "cam_vio", "cam_vana",
+ "cam_vaf";
+ qcom,cam-vreg-type = <0 1 0 0>;
+ qcom,cam-vreg-min-voltage = <1200000 0 2850000 2800000>;
+ qcom,cam-vreg-max-voltage = <1200000 0 2850000 2800000>;
+ qcom,cam-vreg-op-mode = <200000 0 80000 100000>;
+ qcom,gpio-no-mux = <0>;
+ gpios = <&msmgpio 26 0>,
+ <&msmgpio 37 0>,
+ <&msmgpio 36 0>;
+ qcom,gpio-reset = <1>;
+ qcom,gpio-standby = <2>;
+ qcom,gpio-req-tbl-num = <0 1 2>;
+ qcom,gpio-req-tbl-flags = <1 0 0>;
+ qcom,gpio-req-tbl-label = "CAMIF_MCLK",
+ "CAM_RESET1",
+ "CAM_STANDBY";
+ qcom,gpio-set-tbl-num = <1 1>;
+ qcom,gpio-set-tbl-flags = <0 2>;
+ qcom,gpio-set-tbl-delay = <1000 30000>;
+ qcom,csi-lane-assign = <0x4320>;
+ qcom,csi-lane-mask = <0x1F>;
+ qcom,sensor-position = <0>;
+ qcom,sensor-mode = <0>;
+ qcom,sensor-type = <0>;
+ qcom,cci-master = <0>;
+ status = "ok";
+ };
+
+ qcom,camera@6d {
+ compatible = "qcom,ov9724";
+ reg = <0x6d>;
+ qcom,slave-id = <0x20 0x0 0x9724>;
+ qcom,csiphy-sd-index = <1>;
+ qcom,csid-sd-index = <1>;
+ qcom,mount-angle = <0>;
+ qcom,sensor-name = "ov9724";
+ cam_vdig-supply = <&pm8226_l5>;
+ cam_vana-supply = <&pm8226_l19>;
+ cam_vio-supply = <&pm8226_lvs1>;
+ qcom,cam-vreg-name = "cam_vdig", "cam_vio", "cam_vana";
+ qcom,cam-vreg-type = <0 1 0>;
+ qcom,cam-vreg-min-voltage = <1200000 0 2850000>;
+ qcom,cam-vreg-max-voltage = <1200000 0 2850000>;
+ qcom,cam-vreg-op-mode = <200000 0 80000>;
+ qcom,gpio-no-mux = <0>;
+ gpios = <&msmgpio 26 0>,
+ <&msmgpio 28 0>,
+ <&msmgpio 35 0>;
+ qcom,gpio-reset = <1>;
+ qcom,gpio-standby = <2>;
+ qcom,gpio-req-tbl-num = <0 1 2>;
+ qcom,gpio-req-tbl-flags = <1 0 0>;
+ qcom,gpio-req-tbl-label = "CAMIF_MCLK",
+ "CAM_RESET",
+ "CAM_STANDBY";
+ qcom,gpio-set-tbl-num = <1 1>;
+ qcom,gpio-set-tbl-flags = <0 2>;
+ qcom,gpio-set-tbl-delay = <1000 4000>;
+ qcom,csi-lane-assign = <0x4320>;
+ qcom,csi-lane-mask = <0x3>;
+ qcom,sensor-position = <1>;
+ qcom,sensor-mode = <1>;
+ qcom,cci-master = <0>;
+ status = "ok";
+ };
+
+ qcom,camera@90 {
+ compatible = "qcom,mt9m114";
+ reg = <0x90 0x0>;
+ qcom,slave-id = <0x90 0x0 0x2481>;
+ qcom,csiphy-sd-index = <1>;
+ qcom,csid-sd-index = <1>;
+ qcom,mount-angle = <90>;
+ qcom,sensor-name = "mt9m114";
+ cam_vdig-supply = <&pm8226_l5>;
+ cam_vana-supply = <&pm8226_l19>;
+ cam_vio-supply = <&pm8226_lvs1>;
+ qcom,cam-vreg-name = "cam_vdig", "cam_vio", "cam_vana";
+ qcom,cam-vreg-type = <0 1 0>;
+ qcom,cam-vreg-min-voltage = <1200000 0 2850000>;
+ qcom,cam-vreg-max-voltage = <1200000 0 2850000>;
+ qcom,cam-vreg-op-mode = <200000 0 80000>;
+ qcom,gpio-no-mux = <0>;
+ gpios = <&msmgpio 26 0>,
+ <&msmgpio 28 0>,
+ <&msmgpio 35 0>;
+ qcom,gpio-reset = <1>;
+ qcom,gpio-standby = <2>;
+ qcom,gpio-req-tbl-num = <0 1 2>;
+ qcom,gpio-req-tbl-flags = <1 0 0>;
+ qcom,gpio-req-tbl-label = "CAMIF_MCLK",
+ "CAM_RESET",
+ "CAM_STANDBY";
+ qcom,gpio-set-tbl-num = <1 1>;
+ qcom,gpio-set-tbl-flags = <0 2>;
+ qcom,gpio-set-tbl-delay = <1000 4000>;
+ qcom,csi-lane-assign = <0x4320>;
+ qcom,csi-lane-mask = <0x3>;
+ qcom,sensor-position = <1>;
+ qcom,sensor-mode = <1>;
+ qcom,cci-master = <0>;
+ };
};
diff --git a/arch/arm/boot/dts/msm8226-camera-sensor-mtp.dtsi b/arch/arm/boot/dts/msm8226-camera-sensor-mtp.dtsi
index 6b305a5..1631bd6 100644
--- a/arch/arm/boot/dts/msm8226-camera-sensor-mtp.dtsi
+++ b/arch/arm/boot/dts/msm8226-camera-sensor-mtp.dtsi
@@ -98,4 +98,80 @@
qcom,cci-master = <0>;
status = "ok";
};
+
+ qcom,camera@6f {
+ compatible = "qcom,ov8825";
+ reg = <0x6f>;
+ qcom,slave-id = <0x6c 0x300a 0x8825>;
+ qcom,csiphy-sd-index = <0>;
+ qcom,csid-sd-index = <0>;
+ qcom,actuator-src = <&actuator0>;
+ qcom,led-flash-src = <&led_flash0>;
+ qcom,mount-angle = <270>;
+ qcom,sensor-name = "ov8825";
+ cam_vdig-supply = <&pm8226_l5>;
+ cam_vana-supply = <&pm8226_l19>;
+ cam_vio-supply = <&pm8226_lvs1>;
+ cam_vaf-supply = <&pm8226_l15>;
+ qcom,cam-vreg-name = "cam_vdig", "cam_vio", "cam_vana",
+ "cam_vaf";
+ qcom,cam-vreg-type = <0 1 0 0>;
+ qcom,cam-vreg-min-voltage = <1200000 0 2850000 2800000>;
+ qcom,cam-vreg-max-voltage = <1200000 0 2850000 2800000>;
+ qcom,cam-vreg-op-mode = <200000 0 80000 100000>;
+ qcom,gpio-no-mux = <0>;
+ gpios = <&msmgpio 26 0>,
+ <&msmgpio 37 0>,
+ <&msmgpio 35 0>;
+ qcom,gpio-reset = <1>;
+ qcom,gpio-standby = <2>;
+ qcom,gpio-req-tbl-num = <0 1 2>;
+ qcom,gpio-req-tbl-flags = <1 0 0>;
+ qcom,gpio-req-tbl-label = "CAMIF_MCLK",
+ "CAM_RESET1",
+ "CAM_STANDBY";
+ qcom,csi-lane-assign = <0x4320>;
+ qcom,csi-lane-mask = <0x1f>;
+ qcom,sensor-position = <0>;
+ qcom,sensor-mode = <1>;
+ qcom,cci-master = <0>;
+ };
+
+ qcom,camera@6d {
+ compatible = "qcom,ov9724";
+ reg = <0x6d>;
+ qcom,slave-id = <0x20 0x0 0x9724>;
+ qcom,csiphy-sd-index = <1>;
+ qcom,csid-sd-index = <1>;
+ qcom,mount-angle = <270>;
+ qcom,sensor-name = "ov9724";
+ cam_vdig-supply = <&pm8226_l5>;
+ cam_vana-supply = <&pm8226_l19>;
+ cam_vio-supply = <&pm8226_lvs1>;
+ qcom,cam-vreg-name = "cam_vdig", "cam_vio", "cam_vana";
+ qcom,cam-vreg-type = <0 1 0>;
+ qcom,cam-vreg-min-voltage = <1200000 0 2850000>;
+ qcom,cam-vreg-max-voltage = <1200000 0 2850000>;
+ qcom,cam-vreg-op-mode = <200000 0 80000>;
+ qcom,gpio-no-mux = <0>;
+ gpios = <&msmgpio 26 0>,
+ <&msmgpio 28 0>,
+ <&msmgpio 36 0>;
+ qcom,gpio-reset = <1>;
+ qcom,gpio-standby = <2>;
+ qcom,gpio-req-tbl-num = <0 1 2>;
+ qcom,gpio-req-tbl-flags = <1 0 0>;
+ qcom,gpio-req-tbl-label = "CAMIF_MCLK",
+ "CAM_RESET",
+ "CAM_STANDBY";
+ qcom,gpio-set-tbl-num = <1 1>;
+ qcom,gpio-set-tbl-flags = <0 2>;
+ qcom,gpio-set-tbl-delay = <1000 4000>;
+ qcom,csi-lane-assign = <0x4320>;
+ qcom,csi-lane-mask = <0x3>;
+ qcom,sensor-position = <1>;
+ qcom,sensor-mode = <1>;
+ qcom,cci-master = <0>;
+ status = "ok";
+ };
};
diff --git a/arch/arm/boot/dts/msm8226-camera-sensor-qrd.dtsi b/arch/arm/boot/dts/msm8226-camera-sensor-qrd.dtsi
index 4115959..317633b 100644
--- a/arch/arm/boot/dts/msm8226-camera-sensor-qrd.dtsi
+++ b/arch/arm/boot/dts/msm8226-camera-sensor-qrd.dtsi
@@ -104,6 +104,45 @@
qcom,cam-power-seq-delay = <1 1 5 5 10>;
};
+ qcom,camera@6f {
+ compatible = "qcom,ov8825";
+ reg = <0x6f>;
+ qcom,slave-id = <0x6c 0x300a 0x8825>;
+ qcom,csiphy-sd-index = <0>;
+ qcom,csid-sd-index = <0>;
+ qcom,actuator-src = <&actuator0>;
+ qcom,led-flash-src = <&led_flash0>;
+ qcom,eeprom-src = <&eeprom0>;
+ qcom,mount-angle = <90>;
+ qcom,sensor-name = "ov8825";
+ cam_vdig-supply = <&pm8226_l5>;
+ cam_vana-supply = <&pm8226_l19>;
+ cam_vio-supply = <&pm8226_lvs1>;
+ cam_vaf-supply = <&pm8226_l15>;
+ qcom,cam-vreg-name = "cam_vdig", "cam_vio", "cam_vana",
+ "cam_vaf";
+ qcom,cam-vreg-type = <0 1 0 0>;
+ qcom,cam-vreg-min-voltage = <1200000 0 2850000 2800000>;
+ qcom,cam-vreg-max-voltage = <1200000 0 2850000 2800000>;
+ qcom,cam-vreg-op-mode = <200000 0 80000 100000>;
+ qcom,gpio-no-mux = <0>;
+ gpios = <&msmgpio 26 0>,
+ <&msmgpio 37 0>,
+ <&msmgpio 36 0>;
+ qcom,gpio-reset = <1>;
+ qcom,gpio-standby = <2>;
+ qcom,gpio-req-tbl-num = <0 1 2>;
+ qcom,gpio-req-tbl-flags = <1 0 0>;
+ qcom,gpio-req-tbl-label = "CAMIF_MCLK",
+ "CAM_RESET1",
+ "CAM_STANDBY";
+ qcom,csi-lane-assign = <0x4320>;
+ qcom,csi-lane-mask = <0x1f>;
+ qcom,sensor-position = <0>;
+ qcom,sensor-mode = <1>;
+ qcom,cci-master = <0>;
+ };
+
actuator1: qcom,actuator@18 {
cell-index = <4>;
reg = <0x18>;
@@ -360,4 +399,129 @@
qcom,cci-master = <0>;
status = "ok";
};
+
+ qcom,camera@6c {
+ compatible = "qcom,ov12830";
+ reg = <0x6c>;
+ qcom,slave-id = <0x20 0x300a 0xc830>;
+ qcom,csiphy-sd-index = <0>;
+ qcom,csid-sd-index = <0>;
+ qcom,actuator-src = <&actuator1>;
+ qcom,led-flash-src = <&led_flash0>;
+ qcom,eeprom-src = <&eeprom1>;
+ qcom,mount-angle = <90>;
+ qcom,sensor-name = "skuf_ov12830_p12v01c";
+ cam_vdig-supply = <&pm8226_l5>;
+ cam_vana-supply = <&pm8226_l19>;
+ cam_vio-supply = <&pm8226_lvs1>;
+ cam_vaf-supply = <&pm8226_l15>;
+ qcom,cam-vreg-name = "cam_vdig", "cam_vio", "cam_vana",
+ "cam_vaf";
+ qcom,cam-vreg-type = <0 1 0 0>;
+ qcom,cam-vreg-min-voltage = <1200000 0 2850000 2800000>;
+ qcom,cam-vreg-max-voltage = <1200000 0 2850000 2800000>;
+ qcom,cam-vreg-op-mode = <120000 0 0 80000 100000>;
+ qcom,gpio-no-mux = <0>;
+ gpios = <&msmgpio 26 0>,
+ <&msmgpio 37 0>,
+ <&msmgpio 36 0>,
+ <&msmgpio 22 0>,
+ <&msmgpio 34 0>;
+ qcom,gpio-reset = <1>;
+ qcom,gpio-standby = <2>;
+ qcom,gpio-vdig = <3>;
+ qcom,gpio-af-pwdm = <4>;
+ qcom,gpio-req-tbl-num = <0 1 2 3 4>;
+ qcom,gpio-req-tbl-flags = <1 0 0 0 0>;
+ qcom,gpio-req-tbl-label = "CAMIF_MCLK",
+ "CAM_RESET1",
+ "CAM_STANDBY",
+ "CAM_VDIG",
+ "CAM_AF_PWDM";
+ qcom,csi-lane-assign = <0x4320>;
+ qcom,csi-lane-mask = <0x1f>;
+ qcom,sensor-position = <0>;
+ qcom,sensor-mode = <1>;
+ qcom,cci-master = <0>;
+ };
+
+ qcom,camera@6d {
+ compatible = "qcom,ov9724";
+ reg = <0x6d>;
+ qcom,slave-id = <0x20 0x0 0x9724>;
+ qcom,csiphy-sd-index = <1>;
+ qcom,csid-sd-index = <1>;
+ qcom,mount-angle = <270>;
+ qcom,sensor-name = "ov9724";
+ cam_vdig-supply = <&pm8226_l5>;
+ cam_vana-supply = <&pm8226_l19>;
+ cam_vio-supply = <&pm8226_lvs1>;
+ qcom,cam-vreg-name = "cam_vdig", "cam_vio", "cam_vana";
+ qcom,cam-vreg-type = <0 1 0>;
+ qcom,cam-vreg-min-voltage = <1200000 0 2850000>;
+ qcom,cam-vreg-max-voltage = <1200000 0 2850000>;
+ qcom,cam-vreg-op-mode = <200000 0 80000>;
+ qcom,gpio-no-mux = <0>;
+ gpios = <&msmgpio 26 0>,
+ <&msmgpio 28 0>,
+ <&msmgpio 35 0>;
+ qcom,gpio-reset = <1>;
+ qcom,gpio-standby = <2>;
+ qcom,gpio-req-tbl-num = <0 1 2>;
+ qcom,gpio-req-tbl-flags = <1 0 0>;
+ qcom,gpio-req-tbl-label = "CAMIF_MCLK",
+ "CAM_RESET",
+ "CAM_STANDBY";
+ qcom,gpio-set-tbl-num = <1 1>;
+ qcom,gpio-set-tbl-flags = <0 2>;
+ qcom,gpio-set-tbl-delay = <1000 4000>;
+ qcom,csi-lane-assign = <0x4320>;
+ qcom,csi-lane-mask = <0x3>;
+ qcom,sensor-position = <1>;
+ qcom,sensor-mode = <1>;
+ qcom,cci-master = <0>;
+ status = "ok";
+ };
+
+ qcom,camera@6a {
+ compatible = "ovti,ov5648";
+ reg = <0x6a>;
+ qcom,slave-id = <0x6c 0x300a 0x5648>;
+ qcom,csiphy-sd-index = <1>;
+ qcom,csid-sd-index = <1>;
+ qcom,eeprom-src = <&eeprom2>;
+ qcom,mount-angle = <270>;
+ qcom,sensor-name = "skuf_ov5648_p5v23c";
+ cam_vdig-supply = <&pm8226_l5>;
+ cam_vana-supply = <&pm8226_l19>;
+ cam_vio-supply = <&pm8226_lvs1>;
+ qcom,cam-vreg-name = "cam_vdig", "cam_vio", "cam_vana";
+ qcom,cam-vreg-type = <0 1 0>;
+ qcom,cam-vreg-min-voltage = <1200000 0 2850000>;
+ qcom,cam-vreg-max-voltage = <1200000 0 2850000>;
+ qcom,cam-vreg-op-mode = <200000 0 80000>;
+ qcom,gpio-no-mux = <0>;
+ gpios = <&msmgpio 26 0>,
+ <&msmgpio 28 0>,
+ <&msmgpio 35 0>,
+ <&msmgpio 21 0>;
+ qcom,gpio-reset = <1>;
+ qcom,gpio-standby = <2>;
+ qcom,gpio-vdig = <3>;
+ qcom,gpio-req-tbl-num = <0 1 2 3>;
+ qcom,gpio-req-tbl-flags = <1 0 0 0>;
+ qcom,gpio-req-tbl-label = "CAMIF_MCLK",
+ "CAM_RESET",
+ "CAM_STANDBY",
+ "CAM_VDIG";
+ qcom,gpio-set-tbl-num = <1 1>;
+ qcom,gpio-set-tbl-flags = <0 2>;
+ qcom,gpio-set-tbl-delay = <1000 4000>;
+ qcom,csi-lane-assign = <0x4320>;
+ qcom,csi-lane-mask = <0x3>;
+ qcom,sensor-position = <1>;
+ qcom,sensor-mode = <1>;
+ qcom,cci-master = <0>;
+ status = "ok";
+ };
};
diff --git a/arch/arm/boot/dts/msm8974-leds.dtsi b/arch/arm/boot/dts/msm8974-leds.dtsi
index 06abbd8..4be97d8 100644
--- a/arch/arm/boot/dts/msm8974-leds.dtsi
+++ b/arch/arm/boot/dts/msm8974-leds.dtsi
@@ -138,21 +138,31 @@
qcom,row-id = <0>;
qcom,row-src-en;
qcom,always-on;
+ qcom,start-idx = <1>;
+ qcom,ramp-step-ms = <120>;
+ qcom,duty-pcts = [00 00 00 00 64
+ 64 00 00 00 00];
+ qcom,use-blink;
+ qcom,in-order-command-processing;
};
qcom,kpdbl2 {
label = "kpdbl";
- linux,name = "kpdbl-lut-2";
- qcom,mode = "lpg";
+ linux,name = "kpdbl-pwm-2";
+ qcom,mode = "pwm";
qcom,pwm-channel = <9>;
qcom,pwm-us = <1000>;
- qcom,start-idx = <1>;
- qcom,duty-pcts = [00 00 00 00 64
- 64 00 00 00 00];
qcom,id = <7>;
qcom,max-current = <20>;
qcom,row-id = <1>;
qcom,row-src-en;
+ qcom,start-idx = <1>;
+ qcom,ramp-step-ms = <120>;
+ qcom,duty-pcts = [00 00 00 00 64
+ 64 00 00 00 00];
+ qcom,use-blink;
+ qcom,in-order-command-processing;
+
};
qcom,kpdbl3 {
@@ -165,6 +175,13 @@
qcom,max-current = <20>;
qcom,row-id = <2>;
qcom,row-src-en;
+ qcom,start-idx = <1>;
+ qcom,ramp-step-ms = <120>;
+ qcom,duty-pcts = [00 00 00 00 64
+ 64 00 00 00 00];
+ qcom,use-blink;
+ qcom,in-order-command-processing;
+
};
qcom,kpdbl4 {
@@ -177,6 +194,13 @@
qcom,max-current = <20>;
qcom,row-id = <3>;
qcom,row-src-en;
+ qcom,start-idx = <1>;
+ qcom,ramp-step-ms = <120>;
+ qcom,duty-pcts = [00 00 00 00 64
+ 64 00 00 00 00];
+ qcom,use-blink;
+ qcom,in-order-command-processing;
+
};
};
};
diff --git a/arch/arm/boot/dts/msm8974.dtsi b/arch/arm/boot/dts/msm8974.dtsi
index 99dbec8..495117f 100644
--- a/arch/arm/boot/dts/msm8974.dtsi
+++ b/arch/arm/boot/dts/msm8974.dtsi
@@ -214,7 +214,7 @@
interrupts = <0 44 0>;
vdd-supply = <&gdsc_venus>;
qcom,hfi = "venus";
- qcom,has-ocmem;
+ qcom,ocmem-size = <524288>; /* 512 * 1024*/
qcom,max-hw-load = <1216800>; /* 3840 x 2160 @ 30 + 1080p @ 30*/
};
diff --git a/arch/arm/mach-msm/bam_dmux.c b/arch/arm/mach-msm/bam_dmux.c
index b618cd4..89df8ed 100644
--- a/arch/arm/mach-msm/bam_dmux.c
+++ b/arch/arm/mach-msm/bam_dmux.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011-2013, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2011-2014, 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
@@ -2578,7 +2578,8 @@
}
#endif
- bam_ipc_log_txt = ipc_log_context_create(BAM_IPC_LOG_PAGES, "bam_dmux");
+ bam_ipc_log_txt = ipc_log_context_create(BAM_IPC_LOG_PAGES, "bam_dmux",
+ 0);
if (!bam_ipc_log_txt) {
pr_err("%s : unable to create IPC Logging Context", __func__);
}
diff --git a/arch/arm/mach-msm/include/mach/msm_ipc_logging.h b/arch/arm/mach-msm/include/mach/msm_ipc_logging.h
index b3bf07c..82d7785 100644
--- a/arch/arm/mach-msm/include/mach/msm_ipc_logging.h
+++ b/arch/arm/mach-msm/include/mach/msm_ipc_logging.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2014, 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
@@ -48,10 +48,12 @@
*
* @max_num_pages: Number of pages of logging space required (max. 10)
* @mod_name : Name of the directory entry under DEBUGFS
+ * @user_version : Version number of user-defined message formats
*
* returns context id on success, NULL on failure
*/
-void *ipc_log_context_create(int max_num_pages, const char *modname);
+void *ipc_log_context_create(int max_num_pages, const char *modname,
+ uint16_t user_version);
/*
* msg_encode_start: Start encoding a log message
@@ -208,7 +210,7 @@
#else
static inline void *ipc_log_context_create(int max_num_pages,
- const char *modname)
+ const char *modname, uint16_t user_version)
{ return NULL; }
static inline void msg_encode_start(struct encode_context *ectxt,
diff --git a/arch/arm/mach-msm/ipc_logging.c b/arch/arm/mach-msm/ipc_logging.c
index bad861d..e76c95c 100644
--- a/arch/arm/mach-msm/ipc_logging.c
+++ b/arch/arm/mach-msm/ipc_logging.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2014, 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
@@ -31,9 +31,11 @@
#include "ipc_logging.h"
+#define LOG_PAGE_DATA_SIZE sizeof(((struct ipc_log_page *)0)->data)
+#define LOG_PAGE_FLAG (1 << 31)
+
static LIST_HEAD(ipc_log_context_list);
-DEFINE_RWLOCK(ipc_log_context_list_lock);
-static atomic_t next_log_id = ATOMIC_INIT(0);
+static DEFINE_RWLOCK(context_list_lock_lha1);
static void *get_deserialization_func(struct ipc_log_context *ilctxt,
int type);
@@ -50,6 +52,68 @@
return pg;
}
+/**
+ * is_nd_read_empty - Returns true if no data is available to read in log
+ *
+ * @ilctxt: logging context
+ * @returns: > 1 if context is empty; 0 if not empty; <0 for failure
+ *
+ * This is for the debugfs read pointer which allows for a non-destructive read.
+ * There may still be data in the log, but it may have already been read.
+ */
+static int is_nd_read_empty(struct ipc_log_context *ilctxt)
+{
+ if (!ilctxt)
+ return -EINVAL;
+
+ return ((ilctxt->nd_read_page == ilctxt->write_page) &&
+ (ilctxt->nd_read_page->hdr.nd_read_offset ==
+ ilctxt->write_page->hdr.write_offset));
+}
+
+/**
+ * is_read_empty - Returns true if no data is available in log
+ *
+ * @ilctxt: logging context
+ * @returns: > 1 if context is empty; 0 if not empty; <0 for failure
+ *
+ * This is for the actual log contents. If it is empty, then there
+ * is no data at all in the log.
+ */
+static int is_read_empty(struct ipc_log_context *ilctxt)
+{
+ if (!ilctxt)
+ return -EINVAL;
+
+ return ((ilctxt->read_page == ilctxt->write_page) &&
+ (ilctxt->read_page->hdr.read_offset ==
+ ilctxt->write_page->hdr.write_offset));
+}
+
+/**
+ * is_nd_read_equal_read - Return true if the non-destructive read is equal to
+ * the destructive read
+ *
+ * @ilctxt: logging context
+ * @returns: true if nd read is equal to read; false otherwise
+ */
+static bool is_nd_read_equal_read(struct ipc_log_context *ilctxt)
+{
+ uint16_t read_offset;
+ uint16_t nd_read_offset;
+
+ if (ilctxt->nd_read_page == ilctxt->read_page) {
+ read_offset = ilctxt->read_page->hdr.read_offset;
+ nd_read_offset = ilctxt->nd_read_page->hdr.nd_read_offset;
+
+ if (read_offset == nd_read_offset)
+ return true;
+ }
+
+ return false;
+}
+
+
static struct ipc_log_page *get_next_page(struct ipc_log_context *ilctxt,
struct ipc_log_page *cur_pg)
{
@@ -69,64 +133,150 @@
return pg;
}
-/* If data == NULL, drop the log of size data_size*/
+/**
+ * ipc_log_read - do non-destructive read of the log
+ *
+ * @ilctxt: Logging context
+ * @data: Data pointer to receive the data
+ * @data_size: Number of bytes to read (must be <= bytes available in log)
+ *
+ * This read will update a runtime read pointer, but will not affect the actual
+ * contents of the log which allows for reading the logs continuously while
+ * debugging and if the system crashes, then the full logs can still be
+ * extracted.
+ */
static void ipc_log_read(struct ipc_log_context *ilctxt,
void *data, int data_size)
{
int bytes_to_read;
- bytes_to_read = MIN(((PAGE_SIZE - sizeof(struct ipc_log_page_header))
- - ilctxt->read_page->hdr.read_offset),
+ bytes_to_read = MIN(LOG_PAGE_DATA_SIZE
+ - ilctxt->nd_read_page->hdr.nd_read_offset,
+ data_size);
+
+ memcpy(data, (ilctxt->nd_read_page->data +
+ ilctxt->nd_read_page->hdr.nd_read_offset), bytes_to_read);
+
+ if (bytes_to_read != data_size) {
+ /* not enough space, wrap read to next page */
+ ilctxt->nd_read_page->hdr.nd_read_offset = 0;
+ ilctxt->nd_read_page = get_next_page(ilctxt,
+ ilctxt->nd_read_page);
+ BUG_ON(ilctxt->nd_read_page == NULL);
+
+ memcpy((data + bytes_to_read),
+ (ilctxt->nd_read_page->data +
+ ilctxt->nd_read_page->hdr.nd_read_offset),
+ (data_size - bytes_to_read));
+ bytes_to_read = (data_size - bytes_to_read);
+ }
+ ilctxt->nd_read_page->hdr.nd_read_offset += bytes_to_read;
+}
+
+/**
+ * ipc_log_drop - do destructive read of the log
+ *
+ * @ilctxt: Logging context
+ * @data: Data pointer to receive the data (or NULL)
+ * @data_size: Number of bytes to read (must be <= bytes available in log)
+ */
+static void ipc_log_drop(struct ipc_log_context *ilctxt, void *data,
+ int data_size)
+{
+ int bytes_to_read;
+ bool push_nd_read;
+
+ bytes_to_read = MIN(LOG_PAGE_DATA_SIZE
+ - ilctxt->read_page->hdr.read_offset,
data_size);
if (data)
memcpy(data, (ilctxt->read_page->data +
ilctxt->read_page->hdr.read_offset), bytes_to_read);
+
if (bytes_to_read != data_size) {
- ilctxt->read_page->hdr.read_offset = 0xFFFF;
- ilctxt->read_page = get_next_page(ilctxt, ilctxt->read_page);
+ /* not enough space, wrap read to next page */
+ push_nd_read = is_nd_read_equal_read(ilctxt);
+
ilctxt->read_page->hdr.read_offset = 0;
+ if (push_nd_read) {
+ ilctxt->read_page->hdr.nd_read_offset = 0;
+ ilctxt->read_page = get_next_page(ilctxt,
+ ilctxt->read_page);
+ BUG_ON(ilctxt->read_page == NULL);
+ ilctxt->nd_read_page = ilctxt->read_page;
+ } else {
+ ilctxt->read_page = get_next_page(ilctxt,
+ ilctxt->read_page);
+ BUG_ON(ilctxt->read_page == NULL);
+ }
+
if (data)
memcpy((data + bytes_to_read),
- (ilctxt->read_page->data +
+ (ilctxt->read_page->data +
ilctxt->read_page->hdr.read_offset),
- (data_size - bytes_to_read));
+ (data_size - bytes_to_read));
+
bytes_to_read = (data_size - bytes_to_read);
}
+
+ /* update non-destructive read pointer if necessary */
+ push_nd_read = is_nd_read_equal_read(ilctxt);
ilctxt->read_page->hdr.read_offset += bytes_to_read;
ilctxt->write_avail += data_size;
+
+ if (push_nd_read)
+ ilctxt->nd_read_page->hdr.nd_read_offset += bytes_to_read;
}
-/*
- * Reads a message.
+/**
+ * msg_read - Reads a message.
*
- * If a message is read successfully, then the the message context
+ * If a message is read successfully, then the message context
* will be set to:
* .hdr message header .size and .type values
* .offset beginning of message data
*
- * @ectxt Message context and if NULL, drops the message.
+ * @ilctxt Logging context
+ * @ectxt Message context
*
- * @returns 0 - no message available
- * 1 - message read
+ * @returns 0 - no message available; >0 message size; <0 error
*/
-int msg_read(struct ipc_log_context *ilctxt,
+static int msg_read(struct ipc_log_context *ilctxt,
struct encode_context *ectxt)
{
struct tsv_header hdr;
+ if (!ectxt)
+ return -EINVAL;
+
+ if (is_nd_read_empty(ilctxt))
+ return 0;
+
ipc_log_read(ilctxt, &hdr, sizeof(hdr));
- if (ectxt) {
- ectxt->hdr.type = hdr.type;
- ectxt->hdr.size = hdr.size;
- ectxt->offset = sizeof(hdr);
- ipc_log_read(ilctxt, (ectxt->buff + ectxt->offset),
- (int)hdr.size);
- } else {
- ipc_log_read(ilctxt, NULL, (int)hdr.size);
- }
+ ectxt->hdr.type = hdr.type;
+ ectxt->hdr.size = hdr.size;
+ ectxt->offset = sizeof(hdr);
+ ipc_log_read(ilctxt, (ectxt->buff + ectxt->offset),
+ (int)hdr.size);
+
return sizeof(hdr) + (int)hdr.size;
}
+/**
+ * msg_drop - Drops a message.
+ *
+ * @ilctxt Logging context
+ */
+static void msg_drop(struct ipc_log_context *ilctxt)
+{
+ struct tsv_header hdr;
+
+ if (!is_read_empty(ilctxt)) {
+ ipc_log_drop(ilctxt, &hdr, sizeof(hdr));
+ ipc_log_drop(ilctxt, NULL, (int)hdr.size);
+ }
+}
+
/*
* Commits messages to the FIFO. If the FIFO is full, then enough
* messages are dropped to create space for the new message.
@@ -142,21 +292,28 @@
return;
}
- read_lock_irqsave(&ipc_log_context_list_lock, flags);
- spin_lock(&ilctxt->ipc_log_context_lock);
- while (ilctxt->write_avail < ectxt->offset)
- msg_read(ilctxt, NULL);
+ read_lock_irqsave(&context_list_lock_lha1, flags);
+ spin_lock(&ilctxt->context_lock_lhb1);
+ while (ilctxt->write_avail <= ectxt->offset)
+ msg_drop(ilctxt);
- bytes_to_write = MIN(((PAGE_SIZE - sizeof(struct ipc_log_page_header))
- - ilctxt->write_page->hdr.write_offset),
+ bytes_to_write = MIN(LOG_PAGE_DATA_SIZE
+ - ilctxt->write_page->hdr.write_offset,
ectxt->offset);
memcpy((ilctxt->write_page->data +
ilctxt->write_page->hdr.write_offset),
ectxt->buff, bytes_to_write);
+
if (bytes_to_write != ectxt->offset) {
- ilctxt->write_page->hdr.write_offset = 0xFFFF;
+ uint64_t t_now = sched_clock();
+
+ ilctxt->write_page->hdr.write_offset += bytes_to_write;
+ ilctxt->write_page->hdr.end_time = t_now;
+
ilctxt->write_page = get_next_page(ilctxt, ilctxt->write_page);
+ BUG_ON(ilctxt->write_page == NULL);
ilctxt->write_page->hdr.write_offset = 0;
+ ilctxt->write_page->hdr.start_time = t_now;
memcpy((ilctxt->write_page->data +
ilctxt->write_page->hdr.write_offset),
(ectxt->buff + bytes_to_write),
@@ -166,8 +323,8 @@
ilctxt->write_page->hdr.write_offset += bytes_to_write;
ilctxt->write_avail -= ectxt->offset;
complete(&ilctxt->read_avail);
- spin_unlock(&ilctxt->ipc_log_context_lock);
- read_unlock_irqrestore(&ipc_log_context_list_lock, flags);
+ spin_unlock(&ilctxt->context_lock_lhb1);
+ read_unlock_irqrestore(&context_list_lock_lha1, flags);
}
EXPORT_SYMBOL(ipc_log_write);
@@ -254,7 +411,7 @@
int tsv_timestamp_write(struct encode_context *ectxt)
{
int ret;
- unsigned long long t_now = sched_clock();
+ uint64_t t_now = sched_clock();
ret = tsv_write_header(ectxt, TSV_TYPE_TIMESTAMP, sizeof(t_now));
if (ret)
@@ -370,27 +527,27 @@
dctxt.output_format = OUTPUT_DEBUGFS;
dctxt.buff = buff;
dctxt.size = size;
- read_lock_irqsave(&ipc_log_context_list_lock, flags);
- spin_lock(&ilctxt->ipc_log_context_lock);
+ read_lock_irqsave(&context_list_lock_lha1, flags);
+ spin_lock(&ilctxt->context_lock_lhb1);
while (dctxt.size >= MAX_MSG_DECODED_SIZE &&
- !is_ilctxt_empty(ilctxt)) {
+ !is_nd_read_empty(ilctxt)) {
msg_read(ilctxt, &ectxt);
deserialize_func = get_deserialization_func(ilctxt,
ectxt.hdr.type);
- spin_unlock(&ilctxt->ipc_log_context_lock);
- read_unlock_irqrestore(&ipc_log_context_list_lock, flags);
+ spin_unlock(&ilctxt->context_lock_lhb1);
+ read_unlock_irqrestore(&context_list_lock_lha1, flags);
if (deserialize_func)
deserialize_func(&ectxt, &dctxt);
else
pr_err("%s: unknown message 0x%x\n",
__func__, ectxt.hdr.type);
- read_lock_irqsave(&ipc_log_context_list_lock, flags);
- spin_lock(&ilctxt->ipc_log_context_lock);
+ read_lock_irqsave(&context_list_lock_lha1, flags);
+ spin_lock(&ilctxt->context_lock_lhb1);
}
if ((size - dctxt.size) == 0)
- init_completion(&ilctxt->read_avail);
- spin_unlock(&ilctxt->ipc_log_context_lock);
- read_unlock_irqrestore(&ipc_log_context_list_lock, flags);
+ INIT_COMPLETION(ilctxt->read_avail);
+ spin_unlock(&ilctxt->context_lock_lhb1);
+ read_unlock_irqrestore(&context_list_lock_lha1, flags);
return size - dctxt.size;
}
EXPORT_SYMBOL(ipc_log_extract);
@@ -436,7 +593,7 @@
struct decode_context *dctxt, const char *format)
{
struct tsv_header hdr;
- unsigned long long val;
+ uint64_t val;
unsigned long nanosec_rem;
tsv_read_header(ectxt, &hdr);
@@ -526,13 +683,13 @@
if (!df_info)
return -ENOSPC;
- read_lock_irqsave(&ipc_log_context_list_lock, flags);
- spin_lock(&ilctxt->ipc_log_context_lock);
+ read_lock_irqsave(&context_list_lock_lha1, flags);
+ spin_lock(&ilctxt->context_lock_lhb1);
df_info->type = type;
df_info->dfunc = dfunc;
list_add_tail(&df_info->list, &ilctxt->dfunc_info_list);
- spin_unlock(&ilctxt->ipc_log_context_lock);
- read_unlock_irqrestore(&ipc_log_context_list_lock, flags);
+ spin_unlock(&ilctxt->context_lock_lhb1);
+ read_unlock_irqrestore(&context_list_lock_lha1, flags);
return 0;
}
EXPORT_SYMBOL(add_deserialization_func);
@@ -552,12 +709,22 @@
return NULL;
}
+/**
+ * ipc_log_context_create: Create a debug log context
+ * Should not be called from atomic context
+ *
+ * @max_num_pages: Number of pages of logging space required (max. 10)
+ * @mod_name : Name of the directory entry under DEBUGFS
+ * @user_version : Version number of user-defined message formats
+ *
+ * returns context id on success, NULL on failure
+ */
void *ipc_log_context_create(int max_num_pages,
- const char *mod_name)
+ const char *mod_name, uint16_t user_version)
{
struct ipc_log_context *ctxt;
struct ipc_log_page *pg = NULL;
- int page_cnt, local_log_id;
+ int page_cnt;
unsigned long flags;
ctxt = kzalloc(sizeof(struct ipc_log_context), GFP_KERNEL);
@@ -566,41 +733,50 @@
return 0;
}
- local_log_id = atomic_add_return(1, &next_log_id);
init_completion(&ctxt->read_avail);
INIT_LIST_HEAD(&ctxt->page_list);
INIT_LIST_HEAD(&ctxt->dfunc_info_list);
- spin_lock_init(&ctxt->ipc_log_context_lock);
+ spin_lock_init(&ctxt->context_lock_lhb1);
for (page_cnt = 0; page_cnt < max_num_pages; page_cnt++) {
pg = kzalloc(sizeof(struct ipc_log_page), GFP_KERNEL);
if (!pg) {
pr_err("%s: cannot create ipc_log_page\n", __func__);
goto release_ipc_log_context;
}
+ pg->hdr.log_id = (uint64_t)(uintptr_t)ctxt;
+ pg->hdr.page_num = LOG_PAGE_FLAG | page_cnt;
+ pg->hdr.ctx_offset = (int64_t)((uint64_t)(uintptr_t)ctxt -
+ (uint64_t)(uintptr_t)&pg->hdr);
+
+ /* set magic last to signal that page init is complete */
pg->hdr.magic = IPC_LOGGING_MAGIC_NUM;
pg->hdr.nmagic = ~(IPC_LOGGING_MAGIC_NUM);
- pg->hdr.log_id = (uint32_t)local_log_id;
- pg->hdr.page_num = page_cnt;
- pg->hdr.read_offset = 0xFFFF;
- pg->hdr.write_offset = 0xFFFF;
- spin_lock_irqsave(&ctxt->ipc_log_context_lock, flags);
+
+ spin_lock_irqsave(&ctxt->context_lock_lhb1, flags);
list_add_tail(&pg->hdr.list, &ctxt->page_list);
- spin_unlock_irqrestore(&ctxt->ipc_log_context_lock, flags);
+ spin_unlock_irqrestore(&ctxt->context_lock_lhb1, flags);
}
+
+ ctxt->log_id = (uint64_t)(uintptr_t)ctxt;
+ ctxt->version = IPC_LOG_VERSION;
+ strlcpy(ctxt->name, mod_name, IPC_LOG_MAX_CONTEXT_NAME_LEN);
+ ctxt->user_version = user_version;
ctxt->first_page = get_first_page(ctxt);
ctxt->last_page = pg;
ctxt->write_page = ctxt->first_page;
ctxt->read_page = ctxt->first_page;
- ctxt->write_page->hdr.write_offset = 0;
- ctxt->read_page->hdr.read_offset = 0;
- ctxt->write_avail = max_num_pages * (PAGE_SIZE -
- sizeof(struct ipc_log_page_header));
-
+ ctxt->nd_read_page = ctxt->first_page;
+ ctxt->write_avail = max_num_pages * LOG_PAGE_DATA_SIZE;
+ ctxt->header_size = sizeof(struct ipc_log_page_header);
create_ctx_debugfs(ctxt, mod_name);
- write_lock_irqsave(&ipc_log_context_list_lock, flags);
+ /* set magic last to signal context init is complete */
+ ctxt->magic = IPC_LOG_CONTEXT_MAGIC_NUM;
+ ctxt->nmagic = ~(IPC_LOG_CONTEXT_MAGIC_NUM);
+
+ write_lock_irqsave(&context_list_lock_lha1, flags);
list_add_tail(&ctxt->list, &ipc_log_context_list);
- write_unlock_irqrestore(&ipc_log_context_list_lock, flags);
+ write_unlock_irqrestore(&context_list_lock_lha1, flags);
return (void *)ctxt;
release_ipc_log_context:
@@ -634,9 +810,9 @@
kfree(pg);
}
- write_lock_irqsave(&ipc_log_context_list_lock, flags);
+ write_lock_irqsave(&context_list_lock_lha1, flags);
list_del(&ilctxt->list);
- write_unlock_irqrestore(&ipc_log_context_list_lock, flags);
+ write_unlock_irqrestore(&context_list_lock_lha1, flags);
kfree(ilctxt);
return 0;
diff --git a/arch/arm/mach-msm/ipc_logging.h b/arch/arm/mach-msm/ipc_logging.h
index ddf194b..a765a83 100644
--- a/arch/arm/mach-msm/ipc_logging.h
+++ b/arch/arm/mach-msm/ipc_logging.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2014, 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
@@ -15,32 +15,109 @@
#include <mach/msm_ipc_logging.h>
+#define IPC_LOG_VERSION 0x0001
+#define IPC_LOG_MAX_CONTEXT_NAME_LEN 20
+
+/**
+ * struct ipc_log_page_header - Individual log page header
+ *
+ * @magic: Magic number (used for log extraction)
+ * @nmagic: Inverse of magic number (used for log extraction)
+ * @page_num: Index of page (0.. N - 1) (note top bit is always set)
+ * @read_offset: Read offset in page
+ * @write_offset: Write offset in page (or 0xFFFF if full)
+ * @log_id: ID of logging context that owns this page
+ * @start_time: Scheduler clock for first write time in page
+ * @end_time: Scheduler clock for last write time in page
+ * @ctx_offset: Signed offset from page to the logging context. Used to
+ * optimize ram-dump extraction.
+ *
+ * @list: Linked list of pages that make up a log
+ * @nd_read_offset: Non-destructive read offset used for debugfs
+ *
+ * The first part of the structure defines data that is used to extract the
+ * logs from a memory dump and elements in this section should not be changed
+ * or re-ordered. New local data structures can be added to the end of the
+ * structure since they will be ignored by the extraction tool.
+ */
struct ipc_log_page_header {
uint32_t magic;
- uint32_t nmagic; /* inverse of magic number */
- uint32_t log_id; /* owner of log */
+ uint32_t nmagic;
uint32_t page_num;
uint16_t read_offset;
uint16_t write_offset;
+ uint64_t log_id;
+ uint64_t start_time;
+ uint64_t end_time;
+ int64_t ctx_offset;
+
+ /* add local data structures after this point */
struct list_head list;
+ uint16_t nd_read_offset;
};
+/**
+ * struct ipc_log_page - Individual log page
+ *
+ * @hdr: Log page header
+ * @data: Log data
+ *
+ * Each log consists of 1 to N log pages. Data size is adjusted to always fit
+ * the structure into a single kernel page.
+ */
struct ipc_log_page {
struct ipc_log_page_header hdr;
char data[PAGE_SIZE - sizeof(struct ipc_log_page_header)];
};
+/**
+ * struct ipc_log_context - main logging context
+ *
+ * @magic: Magic number (used for log extraction)
+ * @nmagic: Inverse of magic number (used for log extraction)
+ * @version: IPC Logging version of log format
+ * @user_version: Version number for user-defined messages
+ * @header_size: Size of the log header which is used to determine the offset
+ * of ipc_log_page::data
+ * @log_id: Log ID (assigned when log is created)
+ * @name: Name of the log used to uniquely identify the log during extraction
+ *
+ * @list: List of log contexts (struct ipc_log_context)
+ * @page_list: List of log pages (struct ipc_log_page)
+ * @first_page: First page in list of logging pages
+ * @last_page: Last page in list of logging pages
+ * @write_page: Current write page
+ * @read_page: Current read page (for internal reads)
+ * @nd_read_page: Current debugfs extraction page (non-destructive)
+ *
+ * @write_avail: Number of bytes available to write in all pages
+ * @dent: Debugfs node for run-time log extraction
+ * @dfunc_info_list: List of deserialization functions
+ * @context_lock_lhb1: Lock for entire structure
+ * @read_avail: Completed when new data is added to the log
+ */
struct ipc_log_context {
+ uint32_t magic;
+ uint32_t nmagic;
+ uint32_t version;
+ uint16_t user_version;
+ uint16_t header_size;
+ uint64_t log_id;
+ char name[IPC_LOG_MAX_CONTEXT_NAME_LEN];
+
+ /* add local data structures after this point */
struct list_head list;
struct list_head page_list;
struct ipc_log_page *first_page;
struct ipc_log_page *last_page;
struct ipc_log_page *write_page;
struct ipc_log_page *read_page;
+ struct ipc_log_page *nd_read_page;
+
uint32_t write_avail;
struct dentry *dent;
struct list_head dfunc_info_list;
- spinlock_t ipc_log_context_lock;
+ spinlock_t context_lock_lhb1;
struct completion read_avail;
};
@@ -62,27 +139,13 @@
OUTPUT_DEBUGFS,
};
+#define IPC_LOG_CONTEXT_MAGIC_NUM 0x25874452
#define IPC_LOGGING_MAGIC_NUM 0x52784425
#define MIN(x, y) ((x) < (y) ? (x) : (y))
#define IS_MSG_TYPE(x) (((x) > TSV_TYPE_MSG_START) && \
((x) < TSV_TYPE_MSG_END))
#define MAX_MSG_DECODED_SIZE (MAX_MSG_SIZE*4)
-extern rwlock_t ipc_log_context_list_lock;
-
-extern int msg_read(struct ipc_log_context *ilctxt,
- struct encode_context *ectxt);
-
-static inline int is_ilctxt_empty(struct ipc_log_context *ilctxt)
-{
- if (!ilctxt)
- return -EINVAL;
-
- return ((ilctxt->read_page == ilctxt->write_page) &&
- (ilctxt->read_page->hdr.read_offset ==
- ilctxt->write_page->hdr.write_offset));
-}
-
#if (defined(CONFIG_DEBUG_FS))
void check_and_create_debugfs(void);
diff --git a/arch/arm/mach-msm/ipc_router.c b/arch/arm/mach-msm/ipc_router.c
index 6bb4011..fa95469 100644
--- a/arch/arm/mach-msm/ipc_router.c
+++ b/arch/arm/mach-msm/ipc_router.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011-2013, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2011-2014, 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
@@ -3330,7 +3330,7 @@
msm_ipc_router_debug_mask |= SMEM_LOG;
ipc_rtr_log_ctxt = ipc_log_context_create(IPC_RTR_LOG_PAGES,
- "ipc_router");
+ "ipc_router", 0);
if (!ipc_rtr_log_ctxt)
pr_err("%s: Unable to create IPC logging for IPC RTR",
__func__);
diff --git a/arch/arm/mach-msm/ipc_socket.c b/arch/arm/mach-msm/ipc_socket.c
index 5aa6c93..77943e3 100644
--- a/arch/arm/mach-msm/ipc_socket.c
+++ b/arch/arm/mach-msm/ipc_socket.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011-2013, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2011-2014, 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
@@ -626,13 +626,13 @@
{
ipc_req_resp_log_txt =
ipc_log_context_create(REQ_RESP_IPC_LOG_PAGES,
- "ipc_rtr_req_resp");
+ "ipc_rtr_req_resp", 0);
if (!ipc_req_resp_log_txt) {
pr_err("%s: Unable to create IPC logging for Req/Resp",
__func__);
}
ipc_ind_log_txt =
- ipc_log_context_create(IND_IPC_LOG_PAGES, "ipc_rtr_ind");
+ ipc_log_context_create(IND_IPC_LOG_PAGES, "ipc_rtr_ind", 0);
if (!ipc_ind_log_txt) {
pr_err("%s: Unable to create IPC logging for Indications",
__func__);
diff --git a/arch/arm/mach-msm/smd.c b/arch/arm/mach-msm/smd.c
index 32f9b3b..33fae19 100644
--- a/arch/arm/mach-msm/smd.c
+++ b/arch/arm/mach-msm/smd.c
@@ -1,7 +1,7 @@
/* arch/arm/mach-msm/smd.c
*
* Copyright (C) 2007 Google, Inc.
- * Copyright (c) 2008-2013, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2008-2014, The Linux Foundation. All rights reserved.
* Author: Brian Swetland <swetland@google.com>
*
* This software is licensed under the terms of the GNU General Public
@@ -3340,13 +3340,13 @@
if (registered)
return 0;
- smd_log_ctx = ipc_log_context_create(NUM_LOG_PAGES, "smd");
+ smd_log_ctx = ipc_log_context_create(NUM_LOG_PAGES, "smd", 0);
if (!smd_log_ctx) {
pr_err("%s: unable to create SMD logging context\n", __func__);
msm_smd_debug_mask = 0;
}
- smsm_log_ctx = ipc_log_context_create(NUM_LOG_PAGES, "smsm");
+ smsm_log_ctx = ipc_log_context_create(NUM_LOG_PAGES, "smsm", 0);
if (!smsm_log_ctx) {
pr_err("%s: unable to create SMSM logging context\n", __func__);
msm_smd_debug_mask = 0;
diff --git a/arch/arm/mach-msm/smd_pkt.c b/arch/arm/mach-msm/smd_pkt.c
index 1c44f9a..c6001a6 100644
--- a/arch/arm/mach-msm/smd_pkt.c
+++ b/arch/arm/mach-msm/smd_pkt.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2008-2013, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2008-2014, 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
@@ -101,8 +101,6 @@
SMD_PKT_STATUS = 1U << 0,
SMD_PKT_READ = 1U << 1,
SMD_PKT_WRITE = 1U << 2,
- SMD_PKT_READ_DUMP_BUFFER = 1U << 3,
- SMD_PKT_WRITE_DUMP_BUFFER = 1U << 4,
SMD_PKT_POLL = 1U << 5,
};
@@ -116,18 +114,6 @@
ipc_log_string(smd_pkt_ilctxt, "<SMD_PKT>: "x); \
} while (0)
-#define SMD_PKT_LOG_BUF(buf, cnt) \
-do { \
- char log_buf[128]; \
- int i; \
- if (smd_pkt_ilctxt) { \
- i = cnt < 16 ? cnt : 16; \
- hex_dump_to_buffer(buf, i, 16, 1, log_buf, \
- sizeof(log_buf), false); \
- ipc_log_string(smd_pkt_ilctxt, "<SMD_PKT>: %s", log_buf); \
- } \
-} while (0)
-
#define D_STATUS(x...) \
do { \
if (msm_smd_pkt_debug_mask & SMD_PKT_STATUS) \
@@ -149,24 +135,6 @@
SMD_PKT_LOG_STRING(x); \
} while (0)
-#define D_READ_DUMP_BUFFER(prestr, cnt, buf) \
-do { \
- if (msm_smd_pkt_debug_mask & SMD_PKT_READ_DUMP_BUFFER) \
- print_hex_dump(KERN_INFO, prestr, \
- DUMP_PREFIX_NONE, 16, 1, \
- buf, cnt, 1); \
- SMD_PKT_LOG_BUF(buf, cnt); \
-} while (0)
-
-#define D_WRITE_DUMP_BUFFER(prestr, cnt, buf) \
-do { \
- if (msm_smd_pkt_debug_mask & SMD_PKT_WRITE_DUMP_BUFFER) \
- print_hex_dump(KERN_INFO, prestr, \
- DUMP_PREFIX_NONE, 16, 1, \
- buf, cnt, 1); \
- SMD_PKT_LOG_BUF(buf, cnt); \
-} while (0)
-
#define D_POLL(x...) \
do { \
if (msm_smd_pkt_debug_mask & SMD_PKT_POLL) \
@@ -184,8 +152,6 @@
#define D_STATUS(x...) do {} while (0)
#define D_READ(x...) do {} while (0)
#define D_WRITE(x...) do {} while (0)
-#define D_READ_DUMP_BUFFER(prestr, cnt, buf) do {} while (0)
-#define D_WRITE_DUMP_BUFFER(prestr, cnt, buf) do {} while (0)
#define D_POLL(x...) do {} while (0)
#define E_SMD_PKT_SSR(x) do {} while (0)
#endif
@@ -432,7 +398,6 @@
return notify_reset(smd_pkt_devp);
}
} while (pkt_size != bytes_read);
- D_READ_DUMP_BUFFER("Read: ", (bytes_read > 16 ? 16 : bytes_read), buf);
mutex_unlock(&smd_pkt_devp->rx_lock);
mutex_lock(&smd_pkt_devp->ch_lock);
@@ -540,8 +505,6 @@
} while (bytes_written != count);
smd_write_end(smd_pkt_devp->ch);
mutex_unlock(&smd_pkt_devp->tx_lock);
- D_WRITE_DUMP_BUFFER("Write: ",
- (bytes_written > 16 ? 16 : bytes_written), buf);
D_WRITE("Finished %s on smd_pkt_dev id:%d %d bytes\n",
__func__, smd_pkt_devp->i, count);
@@ -1123,7 +1086,7 @@
INIT_DELAYED_WORK(&loopback_work, loopback_probe_worker);
smd_pkt_ilctxt = ipc_log_context_create(SMD_PKT_IPC_LOG_PAGE_CNT,
- "smd_pkt");
+ "smd_pkt", 0);
D_STATUS("SMD Packet Port Driver Initialized.\n");
return 0;
diff --git a/arch/arm/mach-msm/smd_tty.c b/arch/arm/mach-msm/smd_tty.c
index e1c5162..6c3232c 100644
--- a/arch/arm/mach-msm/smd_tty.c
+++ b/arch/arm/mach-msm/smd_tty.c
@@ -1,7 +1,7 @@
/* arch/arm/mach-msm/smd_tty.c
*
* Copyright (C) 2007 Google, Inc.
- * Copyright (c) 2009-2013, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2009-2014, The Linux Foundation. All rights reserved.
* Author: Brian Swetland <swetland@google.com>
*
* This software is licensed under the terms of the GNU General Public
@@ -740,7 +740,7 @@
static void smd_tty_log_init(void)
{
smd_tty_log_ctx = ipc_log_context_create(SMD_TTY_LOG_PAGES,
- "smd_tty");
+ "smd_tty", 0);
if (!smd_tty_log_ctx)
pr_err("%s: Unable to create IPC log", __func__);
}
diff --git a/arch/arm/mach-msm/smem.c b/arch/arm/mach-msm/smem.c
index 3c7cbeb..032f8b1 100644
--- a/arch/arm/mach-msm/smem.c
+++ b/arch/arm/mach-msm/smem.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2013-2014, 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
@@ -1370,7 +1370,7 @@
registered = true;
- smem_ipc_log_ctx = ipc_log_context_create(NUM_LOG_PAGES, "smem");
+ smem_ipc_log_ctx = ipc_log_context_create(NUM_LOG_PAGES, "smem", 0);
if (!smem_ipc_log_ctx) {
pr_err("%s: unable to create logging context\n", __func__);
msm_smem_debug_mask = 0;
diff --git a/arch/arm/mach-msm/smp2p.c b/arch/arm/mach-msm/smp2p.c
index 5574eae..22eb799 100644
--- a/arch/arm/mach-msm/smp2p.c
+++ b/arch/arm/mach-msm/smp2p.c
@@ -1,6 +1,6 @@
/* arch/arm/mach-msm/smp2p.c
*
- * Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2013-2014, 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
@@ -1829,7 +1829,7 @@
in_list[i].smem_edge_in = NULL;
}
- log_ctx = ipc_log_context_create(NUM_LOG_PAGES, "smp2p");
+ log_ctx = ipc_log_context_create(NUM_LOG_PAGES, "smp2p", 0);
if (!log_ctx)
SMP2P_ERR("%s: unable to create log context\n", __func__);
diff --git a/drivers/gpu/msm/adreno.c b/drivers/gpu/msm/adreno.c
index ed1ee8d..a4bd163 100644
--- a/drivers/gpu/msm/adreno.c
+++ b/drivers/gpu/msm/adreno.c
@@ -358,6 +358,10 @@
{
.flags = INPUT_DEVICE_ID_MATCH_EVBIT,
.evbit = { BIT_MASK(EV_ABS) },
+ /* assumption: MT_.._X & MT_.._Y are in the same long */
+ .absbit = { [BIT_WORD(ABS_MT_POSITION_X)] =
+ BIT_MASK(ABS_MT_POSITION_X) |
+ BIT_MASK(ABS_MT_POSITION_Y) },
},
{ },
};
diff --git a/drivers/leds/leds-qpnp.c b/drivers/leds/leds-qpnp.c
index 8774df6..059e488 100755
--- a/drivers/leds/leds-qpnp.c
+++ b/drivers/leds/leds-qpnp.c
@@ -221,6 +221,8 @@
#define KPDBL_MODULE_EN 0x80
#define KPDBL_MODULE_DIS 0x00
#define KPDBL_MODULE_EN_MASK 0x80
+#define NUM_KPDBL_LEDS 4
+#define KPDBL_MASTER_BIT_INDEX 0
/**
* enum qpnp_leds - QPNP supported led ids
@@ -432,6 +434,7 @@
* @always_on - always on row
* @lut_params - lut parameters to be used by pwm driver
* @duty_cycles - duty cycles for lut
+ * @pwm_mode - pwm mode in use
*/
struct kpdbl_config_data {
struct pwm_config_data *pwm_cfg;
@@ -441,6 +444,7 @@
bool always_on;
struct pwm_duty_cycles *duty_cycles;
struct lut_params lut_params;
+ u8 pwm_mode;
};
/**
@@ -490,8 +494,11 @@
int turn_off_delay_ms;
};
-static int num_kpbl_leds_on;
static DEFINE_MUTEX(flash_lock);
+static struct pwm_device *kpdbl_master;
+static u32 kpdbl_master_period_us;
+DECLARE_BITMAP(kpdbl_leds_in_use, NUM_KPDBL_LEDS);
+static bool is_kpdbl_master_turn_on;
static int
qpnp_led_masked_write(struct qpnp_led_data *led, u16 addr, u8 mask, u8 val)
@@ -1278,7 +1285,8 @@
if (!led->kpdbl_cfg->pwm_cfg->blinking)
led->kpdbl_cfg->pwm_cfg->mode =
led->kpdbl_cfg->pwm_cfg->default_mode;
- if (!num_kpbl_leds_on) {
+
+ if (bitmap_empty(kpdbl_leds_in_use, NUM_KPDBL_LEDS)) {
rc = qpnp_led_masked_write(led, KPDBL_ENABLE(led->base),
KPDBL_MODULE_EN_MASK, KPDBL_MODULE_EN);
if (rc) {
@@ -1288,6 +1296,33 @@
}
}
+ /* On some platforms, GPLED1 channel should always be enabled
+ * for the other GPLEDs 2/3/4 to glow. Before enabling GPLED
+ * 2/3/4, first check if GPLED1 is already enabled. If GPLED1
+ * channel is not enabled, then enable the GPLED1 channel but
+ * with a 0 brightness
+ */
+ if (!led->kpdbl_cfg->always_on &&
+ !test_bit(KPDBL_MASTER_BIT_INDEX, kpdbl_leds_in_use) &&
+ kpdbl_master) {
+ rc = pwm_config_us(kpdbl_master, 0,
+ kpdbl_master_period_us);
+ if (rc < 0) {
+ dev_err(&led->spmi_dev->dev,
+ "pwm config failed\n");
+ return rc;
+ }
+
+ rc = pwm_enable(kpdbl_master);
+ if (rc < 0) {
+ dev_err(&led->spmi_dev->dev,
+ "pwm enable failed\n");
+ return rc;
+ }
+ set_bit(KPDBL_MASTER_BIT_INDEX,
+ kpdbl_leds_in_use);
+ }
+
if (led->kpdbl_cfg->pwm_cfg->mode == PWM_MODE) {
period_us = led->kpdbl_cfg->pwm_cfg->pwm_period_us;
if (period_us > INT_MAX / NSEC_PER_USEC) {
@@ -1317,39 +1352,77 @@
return rc;
}
- num_kpbl_leds_on++;
+ set_bit(led->kpdbl_cfg->row_id, kpdbl_leds_in_use);
+
+ /* is_kpdbl_master_turn_on will be set to true when GPLED1
+ * channel is enabled and has a valid brightness value
+ */
+ if (led->kpdbl_cfg->always_on)
+ is_kpdbl_master_turn_on = true;
} else {
led->kpdbl_cfg->pwm_cfg->mode =
led->kpdbl_cfg->pwm_cfg->default_mode;
+ /* Before disabling GPLED1, check if any other GPLED 2/3/4 is
+ * on. If any of the other GPLED 2/3/4 is on, then have the
+ * GPLED1 channel enabled with 0 brightness.
+ */
if (led->kpdbl_cfg->always_on) {
- rc = pwm_config_us(led->kpdbl_cfg->pwm_cfg->pwm_dev, 0,
- led->kpdbl_cfg->pwm_cfg->pwm_period_us);
- if (rc < 0) {
- dev_err(&led->spmi_dev->dev,
+ if (bitmap_weight(kpdbl_leds_in_use,
+ NUM_KPDBL_LEDS) > 1) {
+ rc = pwm_config_us(
+ led->kpdbl_cfg->pwm_cfg->pwm_dev, 0,
+ led->kpdbl_cfg->pwm_cfg->pwm_period_us);
+ if (rc < 0) {
+ dev_err(&led->spmi_dev->dev,
"pwm config failed\n");
- return rc;
- }
+ return rc;
+ }
- rc = pwm_enable(led->kpdbl_cfg->pwm_cfg->pwm_dev);
- if (rc < 0) {
- dev_err(&led->spmi_dev->dev, "pwm enable failed\n");
- return rc;
+ rc = pwm_enable(led->kpdbl_cfg->pwm_cfg->
+ pwm_dev);
+ if (rc < 0) {
+ dev_err(&led->spmi_dev->dev,
+ "pwm enable failed\n");
+ return rc;
+ }
+ } else {
+ if (kpdbl_master) {
+ pwm_disable(kpdbl_master);
+ clear_bit(KPDBL_MASTER_BIT_INDEX,
+ kpdbl_leds_in_use);
+ rc = qpnp_led_masked_write(
+ led, KPDBL_ENABLE(led->base),
+ KPDBL_MODULE_EN_MASK,
+ KPDBL_MODULE_DIS);
+ if (rc) {
+ dev_err(&led->spmi_dev->dev,
+ "Failed to write led"
+ " enable reg\n");
+ return rc;
+ }
+ }
}
- } else
+ is_kpdbl_master_turn_on = false;
+ } else {
pwm_disable(led->kpdbl_cfg->pwm_cfg->pwm_dev);
-
- if (num_kpbl_leds_on > 0)
- num_kpbl_leds_on--;
-
- if (!num_kpbl_leds_on) {
- rc = qpnp_led_masked_write(led, KPDBL_ENABLE(led->base),
+ clear_bit(led->kpdbl_cfg->row_id, kpdbl_leds_in_use);
+ if (bitmap_weight(kpdbl_leds_in_use,
+ NUM_KPDBL_LEDS) == 1 && kpdbl_master &&
+ !is_kpdbl_master_turn_on) {
+ pwm_disable(kpdbl_master);
+ clear_bit(KPDBL_MASTER_BIT_INDEX,
+ kpdbl_leds_in_use);
+ rc = qpnp_led_masked_write(
+ led, KPDBL_ENABLE(led->base),
KPDBL_MODULE_EN_MASK, KPDBL_MODULE_DIS);
- if (rc) {
- dev_err(&led->spmi_dev->dev,
+ if (rc) {
+ dev_err(&led->spmi_dev->dev,
"Failed to write led enable reg\n");
- return rc;
+ return rc;
+ }
+ is_kpdbl_master_turn_on = false;
}
}
}
@@ -1764,7 +1837,7 @@
struct spmi_device *spmi_dev,
const char *name)
{
- int rc, start_idx, idx_len;
+ int rc, start_idx, idx_len, lut_max_size;
if (pwm_cfg->pwm_channel != -1) {
pwm_cfg->pwm_dev =
@@ -1786,14 +1859,18 @@
idx_len =
pwm_cfg->duty_cycles->num_duty_pcts;
- if (idx_len >= PWM_LUT_MAX_SIZE &&
- start_idx) {
+ if (strnstr(name, "kpdbl", sizeof("kpdbl")))
+ lut_max_size = PWM_GPLED_LUT_MAX_SIZE;
+ else
+ lut_max_size = PWM_LUT_MAX_SIZE;
+
+ if (idx_len >= lut_max_size && start_idx) {
dev_err(&spmi_dev->dev,
"Wrong LUT size or index\n");
return -EINVAL;
}
- if ((start_idx + idx_len) >
- PWM_LUT_MAX_SIZE) {
+
+ if ((start_idx + idx_len) > lut_max_size) {
dev_err(&spmi_dev->dev,
"Exceed LUT limit\n");
return -EINVAL;
@@ -1843,6 +1920,9 @@
case QPNP_ID_RGB_BLUE:
pwm_cfg = led->rgb_cfg->pwm_cfg;
break;
+ case QPNP_ID_KPDBL:
+ pwm_cfg = led->kpdbl_cfg->pwm_cfg;
+ break;
default:
dev_err(&led->spmi_dev->dev,
"Invalid LED id type for pwm_us\n");
@@ -1895,6 +1975,9 @@
case QPNP_ID_RGB_BLUE:
pwm_cfg = led->rgb_cfg->pwm_cfg;
break;
+ case QPNP_ID_KPDBL:
+ pwm_cfg = led->kpdbl_cfg->pwm_cfg;
+ break;
default:
dev_err(&led->spmi_dev->dev,
"Invalid LED id type for pause lo\n");
@@ -1947,6 +2030,9 @@
case QPNP_ID_RGB_BLUE:
pwm_cfg = led->rgb_cfg->pwm_cfg;
break;
+ case QPNP_ID_KPDBL:
+ pwm_cfg = led->kpdbl_cfg->pwm_cfg;
+ break;
default:
dev_err(&led->spmi_dev->dev,
"Invalid LED id type for pause hi\n");
@@ -1999,6 +2085,9 @@
case QPNP_ID_RGB_BLUE:
pwm_cfg = led->rgb_cfg->pwm_cfg;
break;
+ case QPNP_ID_KPDBL:
+ pwm_cfg = led->kpdbl_cfg->pwm_cfg;
+ break;
default:
dev_err(&led->spmi_dev->dev,
"Invalid LED id type for start idx\n");
@@ -2052,6 +2141,9 @@
case QPNP_ID_RGB_BLUE:
pwm_cfg = led->rgb_cfg->pwm_cfg;
break;
+ case QPNP_ID_KPDBL:
+ pwm_cfg = led->kpdbl_cfg->pwm_cfg;
+ break;
default:
dev_err(&led->spmi_dev->dev,
"Invalid LED id type for ramp step\n");
@@ -2104,6 +2196,9 @@
case QPNP_ID_RGB_BLUE:
pwm_cfg = led->rgb_cfg->pwm_cfg;
break;
+ case QPNP_ID_KPDBL:
+ pwm_cfg = led->kpdbl_cfg->pwm_cfg;
+ break;
default:
dev_err(&led->spmi_dev->dev,
"Invalid LED id type for lut flags\n");
@@ -2160,6 +2255,10 @@
pwm_cfg = led->rgb_cfg->pwm_cfg;
max_duty_pcts = PWM_LUT_MAX_SIZE;
break;
+ case QPNP_ID_KPDBL:
+ pwm_cfg = led->kpdbl_cfg->pwm_cfg;
+ max_duty_pcts = PWM_GPLED_LUT_MAX_SIZE;
+ break;
default:
dev_err(&led->spmi_dev->dev,
"Invalid LED id type for duty pcts\n");
@@ -2229,12 +2328,17 @@
pwm_cfg->blinking = true;
if (led->id == QPNP_ID_LED_MPP)
led->mpp_cfg->pwm_mode = LPG_MODE;
+ else if (led->id == QPNP_ID_KPDBL)
+ led->kpdbl_cfg->pwm_mode = LPG_MODE;
pwm_cfg->mode = LPG_MODE;
} else {
pwm_cfg->blinking = false;
pwm_cfg->mode = pwm_cfg->default_mode;
if (led->id == QPNP_ID_LED_MPP)
led->mpp_cfg->pwm_mode = pwm_cfg->default_mode;
+ else if (led->id == QPNP_ID_KPDBL)
+ led->kpdbl_cfg->pwm_mode =
+ pwm_cfg->default_mode;
}
pwm_free(pwm_cfg->pwm_dev);
qpnp_pwm_init(pwm_cfg, led->spmi_dev, led->cdev.name);
@@ -2249,6 +2353,11 @@
if (rc < 0)
dev_err(&led->spmi_dev->dev,
"MPP set brightness failed (%d)\n", rc);
+ } else if (led->id == QPNP_ID_KPDBL) {
+ rc = qpnp_kpdbl_set(led);
+ if (rc < 0)
+ dev_err(&led->spmi_dev->dev,
+ "KPDBL set brightness failed (%d)\n", rc);
}
}
mutex_unlock(&led->lock);
@@ -2278,6 +2387,9 @@
case QPNP_ID_RGB_BLUE:
led_blink(led, led->rgb_cfg->pwm_cfg);
break;
+ case QPNP_ID_KPDBL:
+ led_blink(led, led->kpdbl_cfg->pwm_cfg);
+ break;
default:
dev_err(&led->spmi_dev->dev, "Invalid LED id type for blink\n");
return -EINVAL;
@@ -2511,6 +2623,11 @@
return rc;
}
+ if (led->kpdbl_cfg->always_on) {
+ kpdbl_master = led->kpdbl_cfg->pwm_cfg->pwm_dev;
+ kpdbl_master_period_us = led->kpdbl_cfg->pwm_cfg->pwm_period_us;
+ }
+
/* dump kpdbl registers */
qpnp_dump_regs(led, kpdbl_debug_regs, ARRAY_SIZE(kpdbl_debug_regs));
@@ -2927,9 +3044,10 @@
struct device_node *node)
{
struct property *prop;
- int rc, i;
+ int rc, i, lut_max_size;
u32 val;
u8 *temp_cfg;
+ const char *led_label;
rc = of_property_read_u32(node, "qcom,pwm-channel", &val);
if (!rc)
@@ -2973,9 +3091,22 @@
goto bad_lpg_params;
}
+ rc = of_property_read_string(node, "label", &led_label);
+
+ if (rc < 0) {
+ dev_err(&spmi_dev->dev,
+ "Failure reading label, rc = %d\n", rc);
+ return rc;
+ }
+
+ if (strcmp(led_label, "kpdbl") == 0)
+ lut_max_size = PWM_GPLED_LUT_MAX_SIZE;
+ else
+ lut_max_size = PWM_LUT_MAX_SIZE;
+
pwm_cfg->duty_cycles->duty_pcts =
devm_kzalloc(&spmi_dev->dev,
- sizeof(int) * PWM_LUT_MAX_SIZE,
+ sizeof(int) * lut_max_size,
GFP_KERNEL);
if (!pwm_cfg->duty_cycles->duty_pcts) {
dev_err(&spmi_dev->dev,
@@ -2986,7 +3117,7 @@
pwm_cfg->old_duty_pcts =
devm_kzalloc(&spmi_dev->dev,
- sizeof(int) * PWM_LUT_MAX_SIZE,
+ sizeof(int) * lut_max_size,
GFP_KERNEL);
if (!pwm_cfg->old_duty_pcts) {
dev_err(&spmi_dev->dev,
@@ -3383,7 +3514,8 @@
goto fail_id_check;
}
} else if (strncmp(led_label, "kpdbl", sizeof("kpdbl")) == 0) {
- num_kpbl_leds_on = 0;
+ bitmap_zero(kpdbl_leds_in_use, NUM_KPDBL_LEDS);
+ is_kpdbl_master_turn_on = false;
rc = qpnp_get_config_kpdbl(led, temp);
if (rc < 0) {
dev_err(&led->spmi_dev->dev,
@@ -3493,6 +3625,29 @@
if (rc)
goto fail_id_check;
}
+ } else if (led->id == QPNP_ID_KPDBL) {
+ if (led->kpdbl_cfg->pwm_cfg->mode == PWM_MODE) {
+ rc = sysfs_create_group(&led->cdev.dev->kobj,
+ &pwm_attr_group);
+ if (rc)
+ goto fail_id_check;
+ }
+ if (led->kpdbl_cfg->pwm_cfg->use_blink) {
+ rc = sysfs_create_group(&led->cdev.dev->kobj,
+ &blink_attr_group);
+ if (rc)
+ goto fail_id_check;
+
+ rc = sysfs_create_group(&led->cdev.dev->kobj,
+ &lpg_attr_group);
+ if (rc)
+ goto fail_id_check;
+ } else if (led->kpdbl_cfg->pwm_cfg->mode == LPG_MODE) {
+ rc = sysfs_create_group(&led->cdev.dev->kobj,
+ &lpg_attr_group);
+ if (rc)
+ goto fail_id_check;
+ }
}
/* configure default state */
@@ -3582,6 +3737,20 @@
sysfs_remove_group(&led_array[i].cdev.dev->\
kobj, &lpg_attr_group);
break;
+ case QPNP_ID_KPDBL:
+ if (led_array[i].kpdbl_cfg->pwm_cfg->mode == PWM_MODE)
+ sysfs_remove_group(&led_array[i].cdev.dev->
+ kobj, &pwm_attr_group);
+ if (led_array[i].kpdbl_cfg->pwm_cfg->use_blink) {
+ sysfs_remove_group(&led_array[i].cdev.dev->
+ kobj, &blink_attr_group);
+ sysfs_remove_group(&led_array[i].cdev.dev->
+ kobj, &lpg_attr_group);
+ } else if (led_array[i].kpdbl_cfg->pwm_cfg->mode
+ == LPG_MODE)
+ sysfs_remove_group(&led_array[i].cdev.dev->
+ kobj, &lpg_attr_group);
+ break;
default:
dev_err(&led_array[i].spmi_dev->dev,
"Invalid LED(%d)\n",
diff --git a/drivers/media/dvb/dvb-core/dmxdev.c b/drivers/media/dvb/dvb-core/dmxdev.c
index c5da40b..56775d7 100644
--- a/drivers/media/dvb/dvb-core/dmxdev.c
+++ b/drivers/media/dvb/dvb-core/dmxdev.c
@@ -4,7 +4,7 @@
* Copyright (C) 2000 Ralph Metzler & Marcus Metzler
* for convergence integrated media GmbH
*
- * Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2012-2014, 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 Lesser General Public License
@@ -2117,6 +2117,11 @@
struct dmxdev_events_queue *events;
int ret;
+ if (!dmxdevfilter) {
+ pr_err("%s: NULL demux filter object!\n", __func__);
+ return -ENODEV;
+ }
+
if (dmxdevfilter->params.pes.output != DMX_OUT_TS_TAP) {
src = &dmxdevfilter->buffer;
events = &dmxdevfilter->events;
@@ -2170,10 +2175,18 @@
int required_space)
{
struct dmxdev_filter *dmxdevfilter = filter->priv;
- struct dvb_ringbuffer *src = &dmxdevfilter->buffer;
- struct dmxdev_events_queue *events = &dmxdevfilter->events;
+ struct dvb_ringbuffer *src;
+ struct dmxdev_events_queue *events;
int ret;
+ if (!dmxdevfilter) {
+ pr_err("%s: NULL demux filter object!\n", __func__);
+ return -ENODEV;
+ }
+
+ src = &dmxdevfilter->buffer;
+ events = &dmxdevfilter->events;
+
do {
ret = 0;
diff --git a/drivers/media/dvb/dvb-core/dvb_demux.c b/drivers/media/dvb/dvb-core/dvb_demux.c
index 65387ba..bd22e73 100644
--- a/drivers/media/dvb/dvb-core/dvb_demux.c
+++ b/drivers/media/dvb/dvb-core/dvb_demux.c
@@ -5,7 +5,7 @@
* & Marcus Metzler <marcus@convergence.de>
* for convergence integrated media GmbH
*
- * Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2012-2014, 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 Lesser General Public License
@@ -2574,7 +2574,7 @@
feed->state = DMX_STATE_FREE;
feed->filter->state = DMX_STATE_FREE;
-
+ ts_feed->priv = NULL;
dvb_demux_feed_del(feed);
feed->pid = 0xffff;
@@ -2836,6 +2836,7 @@
f->next = f->next->next;
}
+ filter->priv = NULL;
dvbdmxfilter->state = DMX_STATE_FREE;
spin_unlock_irq(&dvbdmx->lock);
mutex_unlock(&dvbdmx->mutex);
@@ -2975,7 +2976,7 @@
dvbdmxfeed->buffer = NULL;
#endif
dvbdmxfeed->state = DMX_STATE_FREE;
-
+ feed->priv = NULL;
dvb_demux_feed_del(dvbdmxfeed);
dvbdmxfeed->pid = 0xffff;
diff --git a/drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.c b/drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.c
index b4196e9..106f5eb 100644
--- a/drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.c
+++ b/drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.c
@@ -298,10 +298,8 @@
return buff->map_info.phy_addr;
QUEUE_BUFF_ERROR2:
- ion_unmap_iommu(cpp_dev->client, buff->map_info.ion_handle,
- cpp_dev->domain_num, 0);
-QUEUE_BUFF_ERROR1:
ion_free(cpp_dev->client, buff->map_info.ion_handle);
+QUEUE_BUFF_ERROR1:
buff->map_info.ion_handle = NULL;
kzfree(buff);
diff --git a/drivers/media/platform/msm/vidc/msm_vidc_common.c b/drivers/media/platform/msm/vidc/msm_vidc_common.c
index df21c26..ba17820 100644
--- a/drivers/media/platform/msm/vidc/msm_vidc_common.c
+++ b/drivers/media/platform/msm/vidc/msm_vidc_common.c
@@ -1552,7 +1552,7 @@
dprintk(VIDC_WARN,
"Failed to scale DDR bus. Performance might be impacted\n");
}
- if (core->resources.has_ocmem) {
+ if (core->resources.ocmem_size) {
if (msm_comm_scale_bus(core, inst->session_type,
OCMEM_MEM))
dprintk(VIDC_WARN,
@@ -1560,52 +1560,6 @@
}
}
-static inline unsigned long get_ocmem_requirement(u32 height, u32 width)
-{
- int num_mbs = 0;
- num_mbs = GET_NUM_MBS(height, width);
- /*TODO: This should be changes once the numbers are
- * available from firmware*/
- return 512 * 1024;
-}
-
-static int msm_comm_unset_ocmem(struct msm_vidc_core *core)
-{
- int rc = 0;
- struct hfi_device *hdev;
-
- if (!core || !core->device) {
- dprintk(VIDC_ERR, "%s invalid parameters", __func__);
- return -EINVAL;
- }
- hdev = core->device;
-
- if (core->state == VIDC_CORE_INVALID) {
- dprintk(VIDC_ERR,
- "Core is in bad state. Cannot unset ocmem\n");
- return -EIO;
- }
-
- init_completion(
- &core->completions[SYS_MSG_INDEX(RELEASE_RESOURCE_DONE)]);
-
- rc = call_hfi_op(hdev, unset_ocmem, hdev->hfi_device_data);
- if (rc) {
- dprintk(VIDC_INFO, "Failed to unset OCMEM on driver\n");
- goto release_ocmem_failed;
- }
- rc = wait_for_completion_timeout(
- &core->completions[SYS_MSG_INDEX(RELEASE_RESOURCE_DONE)],
- msecs_to_jiffies(msm_vidc_hw_rsp_timeout));
- if (!rc) {
- dprintk(VIDC_ERR, "%s: Wait interrupted or timeout: %d\n",
- __func__, SYS_MSG_INDEX(RELEASE_RESOURCE_DONE));
- rc = -EIO;
- }
-release_ocmem_failed:
- return rc;
-}
-
static int msm_comm_init_core_done(struct msm_vidc_inst *inst)
{
struct msm_vidc_core *core = inst->core;
@@ -1899,10 +1853,8 @@
struct msm_vidc_inst *inst)
{
int rc = 0;
- u32 ocmem_sz = 0;
struct hfi_device *hdev;
int num_mbs_per_sec = 0;
- int height, width;
if (!inst || !inst->core || !inst->core->device) {
dprintk(VIDC_ERR, "%s invalid parameters", __func__);
@@ -1939,31 +1891,7 @@
inst, inst->state);
goto exit;
}
- if (inst->core->resources.has_ocmem) {
- height = max(inst->prop.height[CAPTURE_PORT],
- inst->prop.height[OUTPUT_PORT]);
- width = max(inst->prop.width[CAPTURE_PORT],
- inst->prop.width[OUTPUT_PORT]);
- ocmem_sz = get_ocmem_requirement(
- height, width);
- rc = msm_comm_scale_bus(inst->core, inst->session_type,
- OCMEM_MEM);
- if (!rc) {
- mutex_lock(&inst->core->lock);
- rc = call_hfi_op(hdev, alloc_ocmem,
- hdev->hfi_device_data,
- ocmem_sz);
- mutex_unlock(&inst->core->lock);
- if (rc) {
- dprintk(VIDC_WARN,
- "Failed to allocate OCMEM. Performance will be impacted\n");
- msm_comm_unvote_buses(inst->core, OCMEM_MEM);
- }
- } else {
- dprintk(VIDC_WARN,
- "Failed to vote for OCMEM BW. Performance will be impacted\n");
- }
- }
+
rc = call_hfi_op(hdev, session_load_res, (void *) inst->session);
if (rc) {
dprintk(VIDC_ERR,
@@ -3711,12 +3639,6 @@
if (list_empty(&core->instances) &&
core->state != VIDC_CORE_UNINIT) {
if (core->state > VIDC_CORE_INIT) {
- if (core->resources.has_ocmem) {
- if (core->state != VIDC_CORE_INVALID)
- msm_comm_unset_ocmem(core);
- call_hfi_op(hdev, free_ocmem,
- hdev->hfi_device_data);
- }
dprintk(VIDC_DBG, "Calling vidc_hal_core_release\n");
rc = call_hfi_op(hdev, core_release,
hdev->hfi_device_data);
@@ -3732,7 +3654,7 @@
call_hfi_op(hdev, unload_fw, hdev->hfi_device_data);
dprintk(VIDC_DBG, "Firmware unloaded\n");
- if (core->resources.has_ocmem)
+ if (core->resources.ocmem_size)
msm_comm_unvote_buses(core, DDR_MEM|OCMEM_MEM);
else
msm_comm_unvote_buses(core, DDR_MEM);
diff --git a/drivers/media/platform/msm/vidc/msm_vidc_res_parse.c b/drivers/media/platform/msm/vidc/msm_vidc_res_parse.c
index ecfff85..10f3797 100644
--- a/drivers/media/platform/msm/vidc/msm_vidc_res_parse.c
+++ b/drivers/media/platform/msm/vidc/msm_vidc_res_parse.c
@@ -348,7 +348,7 @@
goto err_mem_alloc;
}
for (i = 0; i < num_bus_pdata; i++) {
- if (!res->has_ocmem &&
+ if (!res->ocmem_size &&
(!strcmp(bus_pdata_config_vector[i].name,
"qcom,enc-ocmem-ab-ib")
|| !strcmp(bus_pdata_config_vector[i].name,
@@ -567,9 +567,11 @@
kres = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
res->irq = kres ? kres->start : -1;
- res->has_ocmem = of_property_read_bool(pdev->dev.of_node,
- "qcom,has-ocmem");
-
+ rc = of_property_read_u32(pdev->dev.of_node,
+ "qcom,ocmem-size", &res->ocmem_size);
+ if (rc) {
+ dprintk(VIDC_INFO, "Failed to read ocmem size: %d\n", rc);
+ }
rc = msm_vidc_load_freq_table(res);
if (rc) {
dprintk(VIDC_ERR, "Failed to load freq table: %d\n", rc);
diff --git a/drivers/media/platform/msm/vidc/msm_vidc_resources.h b/drivers/media/platform/msm/vidc/msm_vidc_resources.h
index e75b410..87d4d42 100644
--- a/drivers/media/platform/msm/vidc/msm_vidc_resources.h
+++ b/drivers/media/platform/msm/vidc/msm_vidc_resources.h
@@ -74,7 +74,7 @@
struct msm_bus_scale_pdata *bus_pdata;
struct iommu_set iommu_group_set;
struct buffer_usage_set buffer_usage_set;
- bool has_ocmem;
+ uint32_t ocmem_size;
uint32_t max_load;
struct platform_device *pdev;
};
diff --git a/drivers/media/platform/msm/vidc/q6_hfi.c b/drivers/media/platform/msm/vidc/q6_hfi.c
old mode 100755
new mode 100644
index 52bbe12..4bc534c
--- a/drivers/media/platform/msm/vidc/q6_hfi.c
+++ b/drivers/media/platform/msm/vidc/q6_hfi.c
@@ -1186,14 +1186,6 @@
return 0;
}
-static int q6_hfi_unset_ocmem(void *dev)
-{
- (void)dev;
-
- /* Q6 does not support ocmem */
- return -EINVAL;
-}
-
static int q6_hfi_iommu_get_domain_partition(void *dev, u32 flags,
u32 buffer_type, int *domain, int *partition)
{
@@ -1374,7 +1366,6 @@
hdev->session_flush = q6_hfi_session_flush;
hdev->session_set_property = q6_hfi_session_set_property;
hdev->session_get_property = q6_hfi_session_get_property;
- hdev->unset_ocmem = q6_hfi_unset_ocmem;
hdev->iommu_get_domain_partition = q6_hfi_iommu_get_domain_partition;
hdev->load_fw = q6_hfi_load_fw;
hdev->unload_fw = q6_hfi_unload_fw;
diff --git a/drivers/media/platform/msm/vidc/venus_hfi.c b/drivers/media/platform/msm/vidc/venus_hfi.c
old mode 100755
new mode 100644
index fb27511..f5587fc
--- a/drivers/media/platform/msm/vidc/venus_hfi.c
+++ b/drivers/media/platform/msm/vidc/venus_hfi.c
@@ -904,115 +904,59 @@
return rc;
}
-static int venus_hfi_set_ocmem(void *dev, struct ocmem_buf *ocmem, int locked)
-{
- struct vidc_resource_hdr rhdr;
- struct venus_hfi_device *device = dev;
- int rc = 0;
- if (!device || !ocmem) {
- dprintk(VIDC_ERR, "Invalid params, core:%p, ocmem: %p\n",
- device, ocmem);
- return -EINVAL;
- }
- rhdr.resource_id = VIDC_RESOURCE_OCMEM;
- rhdr.resource_handle = (u32) &device->resources.ocmem;
- rhdr.size = ocmem->len;
- rc = venus_hfi_core_set_resource(device, &rhdr, ocmem, locked);
- if (rc) {
- dprintk(VIDC_ERR, "Failed to set OCMEM on driver\n");
- goto ocmem_set_failed;
- }
- dprintk(VIDC_DBG, "OCMEM set, addr = %lx, size: %ld\n",
- ocmem->addr, ocmem->len);
-ocmem_set_failed:
- return rc;
-}
+static DECLARE_COMPLETION(pc_prep_done);
+static DECLARE_COMPLETION(release_resources_done);
-static int venus_hfi_unset_ocmem(void *dev)
-{
- struct vidc_resource_hdr rhdr;
- struct venus_hfi_device *device = dev;
- int rc = 0;
-
- if (!device) {
- dprintk(VIDC_ERR, "%s Invalid params, device:%p\n",
- __func__, device);
- rc = -EINVAL;
- goto ocmem_unset_failed;
- }
- if (!device->resources.ocmem.buf) {
- dprintk(VIDC_INFO, "%s Trying to free OCMEM which is not set",
- __func__);
- rc = -EINVAL;
- goto ocmem_unset_failed;
- }
- rhdr.resource_id = VIDC_RESOURCE_OCMEM;
- rhdr.resource_handle = (u32) &device->resources.ocmem;
- rc = venus_hfi_core_release_resource(device, &rhdr);
- if (rc)
- dprintk(VIDC_ERR, "Failed to unset OCMEM on driver\n");
-ocmem_unset_failed:
- return rc;
-}
-
-static int __alloc_ocmem(void *dev, unsigned long size, int locked)
+static int __alloc_ocmem(struct venus_hfi_device *device)
{
int rc = 0;
struct ocmem_buf *ocmem_buffer;
- struct venus_hfi_device *device = dev;
+ unsigned long size;
- if (!device || !size) {
- dprintk(VIDC_ERR, "%s Invalid param, core: %p, size: %lu\n",
- __func__, device, size);
+ if (!device || !device->res) {
+ dprintk(VIDC_ERR, "%s Invalid param, device: 0x%p\n",
+ __func__, device);
return -EINVAL;
}
+
+ size = device->res->ocmem_size;
+ if (!size)
+ return rc;
+
ocmem_buffer = device->resources.ocmem.buf;
- if (!ocmem_buffer ||
- ocmem_buffer->len < size) {
+ if (!ocmem_buffer || ocmem_buffer->len < size) {
ocmem_buffer = ocmem_allocate(OCMEM_VIDEO, size);
if (IS_ERR_OR_NULL(ocmem_buffer)) {
dprintk(VIDC_ERR,
- "ocmem_allocate_nb failed: %d\n",
- (u32) ocmem_buffer);
+ "ocmem_allocate failed: %lu\n",
+ (unsigned long)ocmem_buffer);
rc = -ENOMEM;
+ device->resources.ocmem.buf = NULL;
goto ocmem_alloc_failed;
}
device->resources.ocmem.buf = ocmem_buffer;
- rc = venus_hfi_set_ocmem(device, ocmem_buffer, locked);
- if (rc) {
- dprintk(VIDC_ERR, "Failed to set ocmem: %d\n", rc);
- goto ocmem_set_failed;
- }
- device->ocmem_size = size;
- } else
+ } else {
dprintk(VIDC_DBG,
"OCMEM is enough. reqd: %lu, available: %lu\n",
size, ocmem_buffer->len);
-
- return rc;
-ocmem_set_failed:
- ocmem_free(OCMEM_VIDEO, device->resources.ocmem.buf);
- device->resources.ocmem.buf = NULL;
+ }
ocmem_alloc_failed:
return rc;
}
-static int venus_hfi_alloc_ocmem(void *dev, unsigned long size)
+static int __free_ocmem(struct venus_hfi_device *device)
{
- return __alloc_ocmem(dev, size, true);
-}
-
-static int venus_hfi_free_ocmem(void *dev)
-{
- struct venus_hfi_device *device = dev;
int rc = 0;
- if (!device) {
- dprintk(VIDC_ERR, "%s invalid device handle %p",
- __func__, device);
+ if (!device || !device->res) {
+ dprintk(VIDC_ERR, "%s Invalid param, device: 0x%p\n",
+ __func__, device);
return -EINVAL;
}
+ if (!device->res->ocmem_size)
+ return rc;
+
if (device->resources.ocmem.buf) {
rc = ocmem_free(OCMEM_VIDEO, device->resources.ocmem.buf);
if (rc)
@@ -1022,6 +966,147 @@
return rc;
}
+static int __set_ocmem(struct venus_hfi_device *device, bool locked)
+{
+ struct vidc_resource_hdr rhdr;
+ int rc = 0;
+ struct on_chip_mem *ocmem;
+
+ if (!device) {
+ dprintk(VIDC_ERR, "%s Invalid param, device: 0x%p\n",
+ __func__, device);
+ return -EINVAL;
+ }
+
+ ocmem = &device->resources.ocmem;
+ if (!ocmem->buf) {
+ dprintk(VIDC_ERR, "Invalid params, ocmem_buffer: 0x%p\n",
+ ocmem->buf);
+ return -EINVAL;
+ }
+
+ rhdr.resource_id = VIDC_RESOURCE_OCMEM;
+ /*
+ * This handle is just used as a cookie and not(cannot be)
+ * accessed by fw
+ */
+ rhdr.resource_handle = (u32)(unsigned long)ocmem;
+ rhdr.size = ocmem->buf->len;
+ rc = venus_hfi_core_set_resource(device, &rhdr, ocmem->buf, locked);
+ if (rc) {
+ dprintk(VIDC_ERR, "Failed to set OCMEM on driver\n");
+ goto ocmem_set_failed;
+ }
+ dprintk(VIDC_DBG, "OCMEM set, addr = %lx, size: %ld\n",
+ ocmem->buf->addr, ocmem->buf->len);
+ocmem_set_failed:
+ return rc;
+}
+
+static int __unset_ocmem(struct venus_hfi_device *device)
+{
+ struct vidc_resource_hdr rhdr;
+ int rc = 0;
+
+ if (!device) {
+ dprintk(VIDC_ERR, "%s Invalid param, device: 0x%p\n",
+ __func__, device);
+ rc = -EINVAL;
+ goto ocmem_unset_failed;
+ }
+
+ if (!device->resources.ocmem.buf) {
+ dprintk(VIDC_INFO,
+ "%s Trying to unset OCMEM which is not allocated\n",
+ __func__);
+ rc = -EINVAL;
+ goto ocmem_unset_failed;
+ }
+ rhdr.resource_id = VIDC_RESOURCE_OCMEM;
+ /*
+ * This handle is just used as a cookie and not(cannot be)
+ * accessed by fw
+ */
+ rhdr.resource_handle = (u32)(unsigned long)&device->resources.ocmem;
+ rc = venus_hfi_core_release_resource(device, &rhdr);
+ if (rc)
+ dprintk(VIDC_ERR, "Failed to unset OCMEM on driver\n");
+ocmem_unset_failed:
+ return rc;
+}
+
+static int __alloc_set_ocmem(struct venus_hfi_device *device, bool locked)
+{
+ int rc = 0;
+
+ if (!device || !device->res) {
+ dprintk(VIDC_ERR, "%s Invalid param, device: 0x%p\n",
+ __func__, device);
+ return -EINVAL;
+ }
+
+ if (!device->res->ocmem_size)
+ return rc;
+
+ rc = __alloc_ocmem(device);
+ if (rc) {
+ dprintk(VIDC_ERR, "Failed to allocate ocmem: %d\n", rc);
+ goto ocmem_alloc_failed;
+ }
+ rc = __set_ocmem(device, locked);
+ if (rc) {
+ dprintk(VIDC_ERR, "Failed to set ocmem: %d\n", rc);
+ goto ocmem_set_failed;
+ }
+ return rc;
+ocmem_set_failed:
+ __free_ocmem(device);
+ocmem_alloc_failed:
+ return rc;
+}
+
+static int __unset_free_ocmem(struct venus_hfi_device *device)
+{
+ int rc = 0;
+ if (!device || !device->res) {
+ dprintk(VIDC_ERR, "%s Invalid param, device: 0x%p\n",
+ __func__, device);
+ return -EINVAL;
+ }
+
+ if (!device->res->ocmem_size)
+ return rc;
+
+ init_completion(&release_resources_done);
+ rc = __unset_ocmem(device);
+ if (rc) {
+ dprintk(VIDC_ERR, "Failed to unset OCMEM during PC %d\n", rc);
+ goto ocmem_unset_failed;
+ }
+ rc = wait_for_completion_timeout(&release_resources_done,
+ msecs_to_jiffies(msm_vidc_hw_rsp_timeout));
+ if (!rc) {
+ dprintk(VIDC_ERR,
+ "Wait interrupted or timeout for RELEASE_RESOURCES: %d\n",
+ rc);
+ rc = -EIO;
+ goto release_resources_failed;
+ }
+
+ rc = __free_ocmem(device);
+ if (rc) {
+ dprintk(VIDC_ERR, "Failed to free OCMEM during PC\n");
+ goto ocmem_free_failed;
+ }
+ return rc;
+
+ocmem_free_failed:
+ __set_ocmem(device, true);
+release_resources_failed:
+ocmem_unset_failed:
+ return rc;
+}
+
static inline int venus_hfi_tzbsp_set_video_state(enum tzbsp_video_state state)
{
struct tzbsp_video_set_state_req cmd = {0};
@@ -1135,9 +1220,6 @@
--device->clk_cnt;
}
-static DECLARE_COMPLETION(pc_prep_done);
-static DECLARE_COMPLETION(release_resources_done);
-
static int venus_hfi_halt_axi(struct venus_hfi_device *device)
{
u32 reg;
@@ -1201,7 +1283,7 @@
dprintk(VIDC_ERR, "Failed to disable GDSC, %d", rc);
return rc;
}
- if (device->res->has_ocmem)
+ if (device->res->ocmem_size)
venus_hfi_unvote_buses(device, DDR_MEM|OCMEM_MEM);
else
venus_hfi_unvote_buses(device, DDR_MEM);
@@ -1221,7 +1303,7 @@
return -EINVAL;
}
- if (device->res->has_ocmem)
+ if (device->res->ocmem_size)
rc = venus_hfi_scale_buses(device, DDR_MEM|OCMEM_MEM);
else
rc = venus_hfi_scale_buses(device, DDR_MEM);
@@ -1292,7 +1374,7 @@
* of alloc_ocmem
*/
WARN_ON(!mutex_is_locked(&device->write_lock));
- rc = __alloc_ocmem(device, device->ocmem_size, false);
+ rc = __alloc_set_ocmem(device, false);
if (rc) {
dprintk(VIDC_ERR, "Failed to allocate OCMEM");
goto err_alloc_ocmem;
@@ -1311,7 +1393,7 @@
err_enable_clk:
regulator_disable(device->gdsc);
err_enable_gdsc:
- if (device->res->has_ocmem)
+ if (device->res->ocmem_size)
venus_hfi_unvote_buses(device, DDR_MEM|OCMEM_MEM);
else
venus_hfi_unvote_buses(device, DDR_MEM);
@@ -1934,13 +2016,26 @@
dprintk(VIDC_ERR, "invalid device");
return -ENODEV;
}
-
if (dev->hal_client) {
mutex_lock(&dev->clk_pwr_lock);
rc = venus_hfi_clk_gating_off(device);
if (rc) {
dprintk(VIDC_ERR,
- "%s : Clock enable failed\n", __func__);
+ "%s : Clock enable failed\n", __func__);
+ mutex_unlock(&dev->clk_pwr_lock);
+ return -EIO;
+ }
+ mutex_unlock(&dev->clk_pwr_lock);
+ rc = __unset_free_ocmem(dev);
+ if (rc)
+ dprintk(VIDC_ERR,
+ "Failed to unset and free OCMEM in core release, rc : %d\n",
+ rc);
+ mutex_lock(&dev->clk_pwr_lock);
+ rc = venus_hfi_clk_gating_off(device);
+ if (rc) {
+ dprintk(VIDC_ERR,
+ "%s : Clock enable failed\n", __func__);
mutex_unlock(&dev->clk_pwr_lock);
return -EIO;
}
@@ -1951,6 +2046,7 @@
dev->intr_status = 0;
mutex_unlock(&dev->clk_pwr_lock);
}
+
VENUS_SET_STATE(dev, VENUS_STATE_DEINIT);
dprintk(VIDC_INFO, "HAL exited\n");
@@ -2743,45 +2839,6 @@
return rc;
}
-static int venus_hfi_unset_free_ocmem(struct venus_hfi_device *device)
-{
- int rc = 0;
-
- if (!device) {
- dprintk(VIDC_ERR, "Invalid param: %p\n", device);
- return -EINVAL;
- }
-
- init_completion(&release_resources_done);
- rc = venus_hfi_unset_ocmem(device);
- if (rc) {
- dprintk(VIDC_ERR, "Failed to unset OCMEM during PC %d\n", rc);
- goto ocmem_unset_failed;
- }
- rc = wait_for_completion_timeout(&release_resources_done,
- msecs_to_jiffies(msm_vidc_hw_rsp_timeout));
- if (!rc) {
- dprintk(VIDC_ERR,
- "Wait interrupted or timeout for RELEASE_RESOURCES: %d\n",
- rc);
- rc = -EIO;
- goto release_resources_failed;
- }
-
- rc = venus_hfi_free_ocmem(device);
- if (rc) {
- dprintk(VIDC_ERR, "Failed to free OCMEM during PC\n");
- goto ocmem_free_failed;
- }
- return rc;
-
-ocmem_free_failed:
- venus_hfi_alloc_ocmem(device, device->ocmem_size);
-release_resources_failed:
-ocmem_unset_failed:
- return rc;
-}
-
static int venus_hfi_prepare_pc(struct venus_hfi_device *device)
{
int rc = 0;
@@ -2819,18 +2876,20 @@
}
mutex_unlock(&device->clk_pwr_lock);
- rc = venus_hfi_unset_free_ocmem(device);
+ rc = __unset_free_ocmem(device);
if (rc) {
dprintk(VIDC_ERR,
- "Failed to unset and free OCMEM for PC %d\n",
- rc);
+ "Failed to unset and free OCMEM for PC, rc : %d\n", rc);
return;
}
rc = venus_hfi_prepare_pc(device);
if (rc) {
- dprintk(VIDC_ERR, "Failed to prepare for PC %d\n", rc);
- venus_hfi_alloc_ocmem(device, device->ocmem_size);
+ dprintk(VIDC_ERR, "Failed to prepare for PC, rc : %d\n", rc);
+ rc = __alloc_set_ocmem(device, true);
+ if (rc)
+ dprintk(VIDC_WARN,
+ "Failed to re-allocate OCMEM. Performance will be impacted\n");
return;
}
@@ -2926,6 +2985,14 @@
dprintk(VIDC_DBG,
"Received HFI_MSG_SYS_RELEASE_RESOURCE\n");
complete(&release_resources_done);
+ } else if (rc == HFI_MSG_SYS_INIT_DONE) {
+ int ret = 0;
+ dprintk(VIDC_DBG,
+ "Received HFI_MSG_SYS_INIT_DONE\n");
+ ret = __alloc_set_ocmem(device, true);
+ if (ret)
+ dprintk(VIDC_WARN,
+ "Failed to allocate OCMEM. Performance will be impacted\n");
}
}
while (!venus_hfi_iface_dbgq_read(device, packet)) {
@@ -3058,7 +3125,7 @@
strlcpy(clock[VCODEC_AXI_CLK].name, "bus_clk",
sizeof(clock[VCODEC_AXI_CLK].name));
- if (res->has_ocmem) {
+ if (res->ocmem_size) {
strlcpy(clock[VCODEC_OCMEM_CLK].name, "mem_clk",
sizeof(clock[VCODEC_OCMEM_CLK].name));
}
@@ -3081,7 +3148,7 @@
}
for (i = VCODEC_CLK; i < VCODEC_MAX_CLKS; i++) {
- if (i == VCODEC_OCMEM_CLK && !res->has_ocmem)
+ if (i == VCODEC_OCMEM_CLK && !res->ocmem_size)
continue;
cl = &device->resources.clock[i];
if (!cl->clk) {
@@ -3097,7 +3164,7 @@
if (i < VCODEC_MAX_CLKS) {
for (--i; i >= VCODEC_CLK; i--) {
- if (i == VCODEC_OCMEM_CLK && !res->has_ocmem)
+ if (i == VCODEC_OCMEM_CLK && !res->ocmem_size)
continue;
cl = &device->resources.clock[i];
clk_put(cl->clk);
@@ -3116,7 +3183,7 @@
}
for (i = VCODEC_CLK; i < VCODEC_MAX_CLKS; i++) {
- if (i == VCODEC_OCMEM_CLK && !device->res->has_ocmem)
+ if (i == VCODEC_OCMEM_CLK && !device->res->ocmem_size)
continue;
clk_put(device->resources.clock[i].clk);
}
@@ -3135,7 +3202,7 @@
WARN_ON(!mutex_is_locked(&device->clk_pwr_lock));
if (device->clk_state == ENABLED_PREPARED) {
for (i = VCODEC_CLK; i < VCODEC_MAX_CLKS; i++) {
- if (i == VCODEC_OCMEM_CLK && !device->res->has_ocmem)
+ if (i == VCODEC_OCMEM_CLK && !device->res->ocmem_size)
continue;
cl = &device->resources.clock[i];
usleep(100);
@@ -3154,7 +3221,7 @@
}
}
for (i = VCODEC_CLK; i < VCODEC_MAX_CLKS; i++) {
- if (i == VCODEC_OCMEM_CLK && !device->res->has_ocmem)
+ if (i == VCODEC_OCMEM_CLK && !device->res->ocmem_size)
continue;
cl = &device->resources.clock[i];
clk_unprepare(cl->clk);
@@ -3181,7 +3248,7 @@
return 0;
}
for (i = VCODEC_CLK; i < VCODEC_MAX_CLKS; i++) {
- if (i == VCODEC_OCMEM_CLK && !device->res->has_ocmem)
+ if (i == VCODEC_OCMEM_CLK && !device->res->ocmem_size)
continue;
cl = &device->resources.clock[i];
rc = clk_prepare_enable(cl->clk);
@@ -3329,7 +3396,7 @@
goto err_init_bus;
}
- if (device->res->has_ocmem) {
+ if (device->res->ocmem_size) {
bus_info->ocmem_handle[MSM_VIDC_ENCODER] =
msm_bus_scale_register_client(
&device->res->bus_pdata[BUS_IDX_ENC_OCMEM]);
@@ -3355,59 +3422,6 @@
return -EINVAL;
}
-static int venus_hfi_ocmem_notify_handler(struct notifier_block *this,
- unsigned long event, void *data)
-{
- struct ocmem_buf *buff = data;
- struct venus_hfi_device *device;
- struct venus_resources *resources;
- struct on_chip_mem *ocmem;
- int rc = NOTIFY_DONE;
- if (event == OCMEM_ALLOC_GROW) {
- ocmem = container_of(this, struct on_chip_mem, vidc_ocmem_nb);
- if (!ocmem) {
- dprintk(VIDC_ERR, "Wrong handler passed\n");
- rc = NOTIFY_BAD;
- goto err_ocmem_notify;
- }
- resources = container_of(ocmem,
- struct venus_resources, ocmem);
- device = container_of(resources,
- struct venus_hfi_device, resources);
- if (venus_hfi_set_ocmem(device, buff, 1)) {
- dprintk(VIDC_ERR, "Failed to set ocmem: %d\n", rc);
- goto err_ocmem_notify;
- }
- rc = NOTIFY_OK;
- }
-
-err_ocmem_notify:
- return rc;
-}
-
-static void venus_hfi_ocmem_init(struct venus_hfi_device *device)
-{
- struct on_chip_mem *ocmem;
-
- ocmem = &device->resources.ocmem;
- ocmem->vidc_ocmem_nb.notifier_call = venus_hfi_ocmem_notify_handler;
- ocmem->handle =
- ocmem_notifier_register(OCMEM_VIDEO, &ocmem->vidc_ocmem_nb);
- if (IS_ERR_OR_NULL(ocmem->handle)) {
- dprintk(VIDC_WARN,
- "Failed to register OCMEM notifier. Performance might be impacted\n");
- ocmem->handle = NULL;
- }
-}
-
-static void venus_hfi_deinit_ocmem(struct venus_hfi_device *device)
-{
- if (device->resources.ocmem.handle)
- ocmem_notifier_unregister(device->resources.ocmem.handle,
- &device->resources.ocmem.vidc_ocmem_nb);
-}
-
-
static int venus_hfi_init_resources(struct venus_hfi_device *device,
struct msm_vidc_platform_resources *res)
{
@@ -3445,9 +3459,6 @@
goto err_register_iommu_domain;
}
- if (res->has_ocmem)
- venus_hfi_ocmem_init(device);
-
return rc;
err_register_iommu_domain:
@@ -3461,8 +3472,6 @@
static void venus_hfi_deinit_resources(struct venus_hfi_device *device)
{
- if (device->res->has_ocmem)
- venus_hfi_deinit_ocmem(device);
venus_hfi_deregister_iommu_domains(device);
venus_hfi_deinit_bus(device);
venus_hfi_deinit_clocks(device);
@@ -3660,10 +3669,6 @@
return -EINVAL;
}
- rc = venus_hfi_free_ocmem(device);
- if (rc)
- dprintk(VIDC_WARN, "%s - failed to free ocmem\n", __func__);
-
rc = venus_hfi_core_release(device);
if (rc) {
dprintk(VIDC_ERR, "%s - failed to release venus core rc = %d\n",
@@ -3929,9 +3934,6 @@
hdev->scale_clocks = venus_hfi_scale_clocks;
hdev->scale_bus = venus_hfi_scale_bus;
hdev->unvote_bus = venus_hfi_unvote_bus;
- hdev->unset_ocmem = venus_hfi_unset_ocmem;
- hdev->alloc_ocmem = venus_hfi_alloc_ocmem;
- hdev->free_ocmem = venus_hfi_free_ocmem;
hdev->iommu_get_domain_partition = venus_hfi_iommu_get_domain_partition;
hdev->load_fw = venus_hfi_load_fw;
hdev->unload_fw = venus_hfi_unload_fw;
diff --git a/drivers/media/platform/msm/vidc/venus_hfi.h b/drivers/media/platform/msm/vidc/venus_hfi.h
index 9169355..05d7b6a 100644
--- a/drivers/media/platform/msm/vidc/venus_hfi.h
+++ b/drivers/media/platform/msm/vidc/venus_hfi.h
@@ -196,7 +196,6 @@
u32 device_id;
u32 clk_load;
u32 bus_load[MSM_VIDC_MAX_DEVICES];
- unsigned long ocmem_size;
enum clock_state clk_state;
bool power_enabled;
enum vidc_clocks clk_gating_level;
diff --git a/drivers/media/platform/msm/vidc/vidc_hfi_api.h b/drivers/media/platform/msm/vidc/vidc_hfi_api.h
old mode 100755
new mode 100644
index 8484bb2..6cc4dee
--- a/drivers/media/platform/msm/vidc/vidc_hfi_api.h
+++ b/drivers/media/platform/msm/vidc/vidc_hfi_api.h
@@ -1156,9 +1156,6 @@
enum session_type type, enum mem_type mtype);
int (*unvote_bus)(void *dev, enum session_type type,
enum mem_type mtype);
- int (*unset_ocmem)(void *dev);
- int (*alloc_ocmem)(void *dev, unsigned long size);
- int (*free_ocmem)(void *dev);
int (*iommu_get_domain_partition)(void *dev, u32 flags, u32 buffer_type,
int *domain_num, int *partition_num);
int (*load_fw)(void *dev);
diff --git a/drivers/misc/qseecom.c b/drivers/misc/qseecom.c
index cfdaa58..3a93469 100644
--- a/drivers/misc/qseecom.c
+++ b/drivers/misc/qseecom.c
@@ -616,6 +616,25 @@
return ret;
}
+static int qseecom_perf_enable(struct qseecom_dev_handle *data)
+{
+ int ret = 0;
+ ret = qsee_vote_for_clock(data, CLK_DFAB);
+ if (ret) {
+ pr_err("Failed to vote for DFAB clock with err %d\n", ret);
+ goto perf_enable_exit;
+ }
+ ret = qsee_vote_for_clock(data, CLK_SFPB);
+ if (ret) {
+ qsee_disable_clock_vote(data, CLK_DFAB);
+ pr_err("Failed to vote for SFPB clock with err %d\n", ret);
+ goto perf_enable_exit;
+ }
+
+perf_enable_exit:
+ return ret;
+}
+
static int qseecom_scale_bus_bandwidth(struct qseecom_dev_handle *data,
void __user *argp)
{
@@ -631,10 +650,29 @@
pr_err("Invalid bandwidth mode (%d)\n", req_mode);
return ret;
}
- mutex_lock(&qsee_bw_mutex);
- ret = __qseecom_register_bus_bandwidth_needs(data, req_mode);
- mutex_unlock(&qsee_bw_mutex);
+ /*
+ * Register bus bandwidth needs if bus scaling feature is enabled;
+ * otherwise, qseecom enable/disable clocks for the client directly.
+ */
+ if (qseecom.support_bus_scaling) {
+ mutex_lock(&qsee_bw_mutex);
+ ret = __qseecom_register_bus_bandwidth_needs(data, req_mode);
+ mutex_unlock(&qsee_bw_mutex);
+ } else {
+ pr_debug("Bus scaling feature is NOT enabled\n");
+ pr_debug("request bandwidth mode %d for the client\n",
+ req_mode);
+ if (req_mode != INACTIVE) {
+ ret = qseecom_perf_enable(data);
+ if (ret)
+ pr_err("Failed to vote for clock with err %d\n",
+ ret);
+ } else {
+ qsee_disable_clock_vote(data, CLK_DFAB);
+ qsee_disable_clock_vote(data, CLK_SFPB);
+ }
+ }
return ret;
}
@@ -1294,15 +1332,9 @@
return ret;
}
} else {
- ret = qsee_vote_for_clock(data, CLK_DFAB);
+ ret = qseecom_perf_enable(data);
if (ret) {
- pr_err("Failed to vote for DFAB clock%d\n", ret);
- return ret;
- }
- ret = qsee_vote_for_clock(data, CLK_SFPB);
- if (ret) {
- qsee_disable_clock_vote(data, CLK_DFAB);
- pr_err("Failed to vote for SFPB clock%d\n", ret);
+ pr_err("Failed to vote for clocks with err %d\n", ret);
goto exit;
}
}
@@ -1872,7 +1904,6 @@
ret = __qseecom_enable_clk_scale_up(data);
if (ret) {
- kzfree(img_data);
ret = -EIO;
goto loadfw_err;
}
@@ -1882,7 +1913,6 @@
ret = scm_call(SCM_SVC_TZSCHEDULER, 1, &load_req,
sizeof(struct qseecom_load_app_ireq),
&resp, sizeof(resp));
- kzfree(img_data);
if (ret) {
pr_err("scm_call to load failed : ret %d\n", ret);
ret = -EIO;
@@ -1910,6 +1940,7 @@
}
loadfw_err:
+ kzfree(img_data);
__qseecom_disable_clk_scale_down(data);
if (qseecom.support_bus_scaling) {
mutex_lock(&qsee_bw_mutex);
@@ -2288,6 +2319,7 @@
int ret = 0;
struct qseecom_send_cmd_req req = {0, 0, 0, 0};
struct qseecom_dev_handle *data;
+ bool perf_enabled = false;
if (handle == NULL) {
pr_err("Handle is not initialized\n");
@@ -2311,11 +2343,35 @@
return ret;
}
}
+ /*
+ * On targets where crypto clock is handled by HLOS,
+ * if clk_access_cnt is zero and perf_enabled is false,
+ * then the crypto clock was not enabled before sending cmd
+ * to tz, qseecom will enable the clock to avoid service failure.
+ */
+ if (!qseecom.qsee.clk_access_cnt && !data->perf_enabled) {
+ pr_debug("ce clock is not enabled!\n");
+ ret = qseecom_perf_enable(data);
+ if (ret) {
+ pr_err("Failed to vote for clock with err %d\n",
+ ret);
+ atomic_dec(&data->ioctl_count);
+ mutex_unlock(&app_access_lock);
+ return -EINVAL;
+ }
+ perf_enabled = true;
+ }
+
ret = __qseecom_send_cmd(data, &req);
if (qseecom.support_bus_scaling)
__qseecom_add_bw_scale_down_timer(
QSEECOM_SEND_CMD_CRYPTO_TIMEOUT);
+ if (perf_enabled) {
+ qsee_disable_clock_vote(data, CLK_DFAB);
+ qsee_disable_clock_vote(data, CLK_SFPB);
+ }
+
atomic_dec(&data->ioctl_count);
mutex_unlock(&app_access_lock);
@@ -2344,16 +2400,10 @@
if (ret)
pr_err("Failed to scale bus (med) %d\n", ret);
} else {
- ret = qsee_vote_for_clock(handle->dev, CLK_DFAB);
+ ret = qseecom_perf_enable(handle->dev);
if (ret)
- pr_err("Failed to vote for DFAB clock%d\n",
- ret);
- ret = qsee_vote_for_clock(handle->dev, CLK_SFPB);
- if (ret) {
- pr_err("Failed to vote for SFPB clock%d\n",
- ret);
- qsee_disable_clock_vote(handle->dev, CLK_DFAB);
- }
+ pr_err("Failed to vote for clock with err %d\n",
+ ret);
}
} else {
if (!qseecom.support_bus_scaling) {
@@ -3420,6 +3470,7 @@
int ret = 0;
struct qseecom_dev_handle *data = file->private_data;
void __user *argp = (void __user *) arg;
+ bool perf_enabled = false;
if (!data) {
pr_err("Invalid/uninitialized device handle\n");
@@ -3493,11 +3544,33 @@
break;
}
}
+ /*
+ * On targets where crypto clock is handled by HLOS,
+ * if clk_access_cnt is zero and perf_enabled is false,
+ * then the crypto clock was not enabled before sending cmd
+ * to tz, qseecom will enable the clock to avoid service failure.
+ */
+ if (!qseecom.qsee.clk_access_cnt && !data->perf_enabled) {
+ pr_debug("ce clock is not enabled!\n");
+ ret = qseecom_perf_enable(data);
+ if (ret) {
+ pr_err("Failed to vote for clock with err %d\n",
+ ret);
+ mutex_unlock(&app_access_lock);
+ ret = -EINVAL;
+ break;
+ }
+ perf_enabled = true;
+ }
atomic_inc(&data->ioctl_count);
ret = qseecom_send_cmd(data, argp);
if (qseecom.support_bus_scaling)
__qseecom_add_bw_scale_down_timer(
QSEECOM_SEND_CMD_CRYPTO_TIMEOUT);
+ if (perf_enabled) {
+ qsee_disable_clock_vote(data, CLK_DFAB);
+ qsee_disable_clock_vote(data, CLK_SFPB);
+ }
atomic_dec(&data->ioctl_count);
wake_up_all(&data->abort_wq);
mutex_unlock(&app_access_lock);
@@ -3531,11 +3604,33 @@
break;
}
}
+ /*
+ * On targets where crypto clock is handled by HLOS,
+ * if clk_access_cnt is zero and perf_enabled is false,
+ * then the crypto clock was not enabled before sending cmd
+ * to tz, qseecom will enable the clock to avoid service failure.
+ */
+ if (!qseecom.qsee.clk_access_cnt && !data->perf_enabled) {
+ pr_debug("ce clock is not enabled!\n");
+ ret = qseecom_perf_enable(data);
+ if (ret) {
+ pr_err("Failed to vote for clock with err %d\n",
+ ret);
+ mutex_unlock(&app_access_lock);
+ ret = -EINVAL;
+ break;
+ }
+ perf_enabled = true;
+ }
atomic_inc(&data->ioctl_count);
ret = qseecom_send_modfd_cmd(data, argp);
if (qseecom.support_bus_scaling)
__qseecom_add_bw_scale_down_timer(
QSEECOM_SEND_CMD_CRYPTO_TIMEOUT);
+ if (perf_enabled) {
+ qsee_disable_clock_vote(data, CLK_DFAB);
+ qsee_disable_clock_vote(data, CLK_SFPB);
+ }
atomic_dec(&data->ioctl_count);
wake_up_all(&data->abort_wq);
mutex_unlock(&app_access_lock);
@@ -3665,12 +3760,9 @@
__qseecom_register_bus_bandwidth_needs(data, HIGH);
mutex_unlock(&qsee_bw_mutex);
} else {
- ret = qsee_vote_for_clock(data, CLK_DFAB);
+ ret = qseecom_perf_enable(data);
if (ret)
- pr_err("Fail to vote for DFAB clock%d\n", ret);
- ret = qsee_vote_for_clock(data, CLK_SFPB);
- if (ret)
- pr_err("Fail to vote for SFPB clock%d\n", ret);
+ pr_err("Fail to vote for clocks %d\n", ret);
}
atomic_dec(&data->ioctl_count);
break;
diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c
index da62cb0..939379f 100644
--- a/drivers/mmc/core/core.c
+++ b/drivers/mmc/core/core.c
@@ -616,8 +616,10 @@
(host->areq->cmd_flags & REQ_FUA))
return false;
+ mmc_host_clk_hold(host);
remainder = (host->ops->get_xfer_remain) ?
host->ops->get_xfer_remain(host) : -1;
+ mmc_host_clk_release(host);
return (remainder > 0);
}
@@ -642,6 +644,7 @@
mmc_hostname(host));
return -ENOTSUPP;
}
+ mmc_host_clk_hold(host);
err = host->ops->stop_request(host);
if (err) {
pr_err("%s: Call to host->ops->stop_request() failed (%d)\n",
@@ -676,6 +679,7 @@
goto out;
}
out:
+ mmc_host_clk_release(host);
return err;
}
diff --git a/drivers/net/wireless/wcnss/wcnss_wlan.c b/drivers/net/wireless/wcnss/wcnss_wlan.c
index 90cf441..ed6fa29 100644
--- a/drivers/net/wireless/wcnss/wcnss_wlan.c
+++ b/drivers/net/wireless/wcnss/wcnss_wlan.c
@@ -215,6 +215,7 @@
#define WCNSS_BUILD_VER_REQ (WCNSS_CTRL_MSG_START + 9)
#define WCNSS_BUILD_VER_RSP (WCNSS_CTRL_MSG_START + 10)
#define WCNSS_PM_CONFIG_REQ (WCNSS_CTRL_MSG_START + 11)
+#define WCNSS_CBC_COMPLETE_IND (WCNSS_CTRL_MSG_START + 12)
/* max 20mhz channel count */
#define WCNSS_MAX_CH_NUM 45
@@ -407,6 +408,7 @@
void __iomem *alarms_tactl;
void __iomem *fiq_reg;
int nv_downloaded;
+ int is_cbc_done;
unsigned char *fw_cal_data;
unsigned char *user_cal_data;
int fw_cal_rcvd;
@@ -1050,6 +1052,7 @@
pr_debug("wcnss: closing WCNSS SMD channel :%s",
WCNSS_CTRL_CHANNEL);
penv->nv_downloaded = 0;
+ penv->is_cbc_done = 0;
break;
default:
@@ -1241,6 +1244,14 @@
}
EXPORT_SYMBOL(wcnss_get_wlan_config);
+int wcnss_is_hw_pronto_ver3(void)
+{
+ if (penv && penv->pdev)
+ return penv->wlan_config.is_pronto_v3;
+ return 0;
+}
+EXPORT_SYMBOL(wcnss_is_hw_pronto_ver3);
+
int wcnss_device_ready(void)
{
if (penv && penv->pdev && penv->nv_downloaded &&
@@ -1250,6 +1261,15 @@
}
EXPORT_SYMBOL(wcnss_device_ready);
+int wcnss_cbc_complete(void)
+{
+ if (penv && penv->pdev && penv->is_cbc_done &&
+ !wcnss_device_is_shutdown())
+ return 1;
+ return 0;
+}
+EXPORT_SYMBOL(wcnss_cbc_complete);
+
int wcnss_device_is_shutdown(void)
{
if (penv && penv->is_shutdown)
@@ -1885,6 +1905,10 @@
pr_debug("wcnss: received WCNSS_CALDATA_DNLD_RSP from ccpu %u\n",
fw_status);
break;
+ case WCNSS_CBC_COMPLETE_IND:
+ penv->is_cbc_done = 1;
+ pr_info("wcnss: received WCNSS_CBC_COMPLETE_IND from FW\n");
+ break;
case WCNSS_CALDATA_UPLD_REQ:
extract_cal_data(len);
@@ -2316,10 +2340,14 @@
unsigned long wcnss_phys_addr;
int size = 0;
struct resource *res;
+ int is_pronto_v3;
int pil_retry = 0;
int has_pronto_hw = of_property_read_bool(pdev->dev.of_node,
"qcom,has-pronto-hw");
+ is_pronto_v3 = of_property_read_bool(pdev->dev.of_node,
+ "qcom,is-pronto-v3");
+
if (of_property_read_u32(pdev->dev.of_node,
"qcom,wlan-rx-buff-count", &penv->wlan_rx_buff_count)) {
penv->wlan_rx_buff_count = WCNSS_DEF_WLAN_RX_BUFF_COUNT;
@@ -2342,6 +2370,7 @@
}
penv->wcnss_hw_type = (has_pronto_hw) ? WCNSS_PRONTO_HW : WCNSS_RIVA_HW;
penv->wlan_config.use_48mhz_xo = has_48mhz_xo;
+ penv->wlan_config.is_pronto_v3 = is_pronto_v3;
if (WCNSS_CONFIG_UNSPECIFIED == has_autodetect_xo && has_pronto_hw) {
has_autodetect_xo = of_property_read_bool(pdev->dev.of_node,
diff --git a/drivers/slimbus/slim-msm-ngd.c b/drivers/slimbus/slim-msm-ngd.c
index b4c88cd..85e8842 100644
--- a/drivers/slimbus/slim-msm-ngd.c
+++ b/drivers/slimbus/slim-msm-ngd.c
@@ -1293,7 +1293,7 @@
/* Create IPC log context */
dev->ipc_slimbus_log = ipc_log_context_create(IPC_SLIMBUS_LOG_PAGES,
- dev_name(dev->dev));
+ dev_name(dev->dev), 0);
if (!dev->ipc_slimbus_log)
dev_err(&pdev->dev, "error creating ipc_logging context\n");
else {
diff --git a/drivers/tty/n_smux.c b/drivers/tty/n_smux.c
index e36806f..ffcfe52 100644
--- a/drivers/tty/n_smux.c
+++ b/drivers/tty/n_smux.c
@@ -1,6 +1,6 @@
/* drivers/tty/n_smux.c
*
- * Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2012-2014, The Linux Foundation. All rights reserved.
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
@@ -3905,7 +3905,7 @@
return ret;
}
- log_ctx = ipc_log_context_create(1, "smux");
+ log_ctx = ipc_log_context_create(1, "smux", 0);
if (!log_ctx) {
SMUX_ERR("%s: unable to create log context\n", __func__);
disable_ipc_logging = 1;
diff --git a/drivers/tty/serial/msm_serial_hs.c b/drivers/tty/serial/msm_serial_hs.c
index ad1ecff..8545ce9 100644
--- a/drivers/tty/serial/msm_serial_hs.c
+++ b/drivers/tty/serial/msm_serial_hs.c
@@ -3095,7 +3095,7 @@
int ret;
ipc_msm_hs_log_ctxt = ipc_log_context_create(IPC_MSM_HS_LOG_PAGES,
- "msm_serial_hs");
+ "msm_serial_hs", 0);
if (!ipc_msm_hs_log_ctxt)
MSM_HS_WARN("%s: error creating logging context", __func__);
diff --git a/include/linux/ipv6.h b/include/linux/ipv6.h
index 4effce6..07f5063 100644
--- a/include/linux/ipv6.h
+++ b/include/linux/ipv6.h
@@ -161,6 +161,7 @@
__s32 accept_ra_rt_info_max_plen;
#endif
#endif
+ __s32 accept_ra_rt_table;
__s32 proxy_ndp;
__s32 accept_source_route;
#ifdef CONFIG_IPV6_OPTIMISTIC_DAD
@@ -215,6 +216,7 @@
DEVCONF_ACCEPT_DAD,
DEVCONF_FORCE_TLLAO,
DEVCONF_ACCEPT_RA_PREFIX_ROUTE,
+ DEVCONF_ACCEPT_RA_RT_TABLE,
DEVCONF_MAX
};
diff --git a/include/linux/wcnss_wlan.h b/include/linux/wcnss_wlan.h
index e6c46d1..56ba8ab 100644
--- a/include/linux/wcnss_wlan.h
+++ b/include/linux/wcnss_wlan.h
@@ -28,6 +28,8 @@
struct wcnss_wlan_config {
int use_48mhz_xo;
+ int is_pronto_v3;
+ void __iomem *msm_wcnss_base;
};
enum {
@@ -40,6 +42,7 @@
#define HAVE_WCNSS_SUSPEND_RESUME_NOTIFY 1
#define HAVE_WCNSS_RESET_INTR 1
#define HAVE_WCNSS_CAL_DOWNLOAD 1
+#define HAVE_CBC_DONE 1
#define HAVE_WCNSS_RX_BUFF_COUNT 1
#define WLAN_MAC_ADDR_SIZE (6)
@@ -77,7 +80,9 @@
void wcnss_resume_notify(void);
void wcnss_riva_log_debug_regs(void);
void wcnss_pronto_log_debug_regs(void);
+int wcnss_is_hw_pronto_ver3(void);
int wcnss_device_ready(void);
+int wcnss_cbc_complete(void);
int wcnss_device_is_shutdown(void);
void wcnss_riva_dump_pmic_regs(void);
int wcnss_xo_auto_detect_enabled(void);
diff --git a/include/net/addrconf.h b/include/net/addrconf.h
index 757a176..f080441 100644
--- a/include/net/addrconf.h
+++ b/include/net/addrconf.h
@@ -166,6 +166,8 @@
extern int ipv6_chk_acast_addr(struct net *net, struct net_device *dev,
const struct in6_addr *addr);
+u32 addrconf_rt_table(const struct net_device *dev, u32 default_table);
+
/* Device notifier */
extern int register_inet6addr_notifier(struct notifier_block *nb);
diff --git a/include/net/inet_sock.h b/include/net/inet_sock.h
index ae17e13..1eb1829 100644
--- a/include/net/inet_sock.h
+++ b/include/net/inet_sock.h
@@ -89,6 +89,7 @@
no_srccheck: 1;
kmemcheck_bitfield_end(flags);
struct ip_options_rcu *opt;
+ u32 ir_mark;
};
static inline struct inet_request_sock *inet_rsk(const struct request_sock *sk)
@@ -96,6 +97,15 @@
return (struct inet_request_sock *)sk;
}
+static inline u32 inet_request_mark(struct sock *sk, struct sk_buff *skb)
+{
+ if (!sk->sk_mark && sock_net(sk)->ipv4.sysctl_tcp_fwmark_accept) {
+ return skb->mark;
+ } else {
+ return sk->sk_mark;
+ }
+}
+
struct inet_cork {
unsigned int flags;
__be32 addr;
diff --git a/include/net/ip.h b/include/net/ip.h
index 53af759..e36ffa1 100644
--- a/include/net/ip.h
+++ b/include/net/ip.h
@@ -238,6 +238,9 @@
extern void ip_static_sysctl_init(void);
+#define IP4_REPLY_MARK(net, mark) \
+ ((net)->ipv4.sysctl_fwmark_reflect ? (mark) : 0)
+
static inline bool ip_is_fragment(const struct iphdr *iph)
{
return (iph->frag_off & htons(IP_MF | IP_OFFSET)) != 0;
diff --git a/include/net/ipv6.h b/include/net/ipv6.h
index a5a9e4d..2161a39 100644
--- a/include/net/ipv6.h
+++ b/include/net/ipv6.h
@@ -109,6 +109,9 @@
#define IP6_MF 0x0001
+#define IP6_REPLY_MARK(net, mark) \
+ ((net)->ipv6.sysctl.fwmark_reflect ? (mark) : 0)
+
#include <net/sock.h>
/* sysctls */
diff --git a/include/net/netns/ipv4.h b/include/net/netns/ipv4.h
index bbd023a..8869426 100644
--- a/include/net/netns/ipv4.h
+++ b/include/net/netns/ipv4.h
@@ -56,6 +56,8 @@
unsigned int sysctl_ping_group_range[2];
long sysctl_tcp_mem[3];
+ int sysctl_fwmark_reflect;
+ int sysctl_tcp_fwmark_accept;
atomic_t rt_genid;
atomic_t dev_addr_genid;
diff --git a/include/net/netns/ipv6.h b/include/net/netns/ipv6.h
index 81abfcb..20b76ab 100644
--- a/include/net/netns/ipv6.h
+++ b/include/net/netns/ipv6.h
@@ -25,6 +25,7 @@
int ip6_rt_mtu_expires;
int ip6_rt_min_advmss;
int icmpv6_time;
+ int fwmark_reflect;
};
struct netns_ipv6 {
diff --git a/include/sound/q6audio-v2.h b/include/sound/q6audio-v2.h
index 8ac835c..e3e62c9 100644
--- a/include/sound/q6audio-v2.h
+++ b/include/sound/q6audio-v2.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2014, 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
@@ -32,4 +32,6 @@
int q6audio_get_port_id(u16 port_id);
+int q6audio_get_port_id_from_index(u16 port_idx);
+
#endif
diff --git a/mm/page_alloc.c b/mm/page_alloc.c
index d4c0534..7eefa94 100644
--- a/mm/page_alloc.c
+++ b/mm/page_alloc.c
@@ -657,6 +657,8 @@
int migratetype = 0;
int batch_free = 0;
int to_free = count;
+ int free = 0;
+ int cma_free = 0;
int mt = 0;
spin_lock(&zone->lock);
@@ -687,17 +689,23 @@
do {
page = list_entry(list->prev, struct page, lru);
mt = get_pageblock_migratetype(page);
+ if (likely(mt != MIGRATE_ISOLATE))
+ mt = page_private(page);
+
/* must delete as __free_one_page list manipulates */
list_del(&page->lru);
/* MIGRATE_MOVABLE list may include MIGRATE_RESERVEs */
- __free_one_page(page, zone, 0, page_private(page));
- trace_mm_page_pcpu_drain(page, 0, page_private(page));
- if (is_migrate_cma(mt))
- __mod_zone_page_state(zone,
- NR_FREE_CMA_PAGES, 1);
+ __free_one_page(page, zone, 0, mt);
+ trace_mm_page_pcpu_drain(page, 0, mt);
+ if (likely(mt != MIGRATE_ISOLATE)) {
+ free++;
+ if (is_migrate_cma(mt))
+ cma_free++;
+ }
} while (--to_free && --batch_free && !list_empty(list));
}
- __mod_zone_page_state(zone, NR_FREE_PAGES, count);
+ __mod_zone_page_state(zone, NR_FREE_PAGES, free);
+ __mod_zone_page_state(zone, NR_FREE_CMA_PAGES, cma_free);
spin_unlock(&zone->lock);
}
diff --git a/net/ipv4/icmp.c b/net/ipv4/icmp.c
index 2e109ff..ea63a57 100644
--- a/net/ipv4/icmp.c
+++ b/net/ipv4/icmp.c
@@ -335,6 +335,7 @@
struct sock *sk;
struct inet_sock *inet;
__be32 daddr;
+ u32 mark = IP4_REPLY_MARK(net, skb->mark);
if (ip_options_echo(&icmp_param->replyopts.opt.opt, skb))
return;
@@ -347,6 +348,7 @@
icmp_param->data.icmph.checksum = 0;
inet->tos = ip_hdr(skb)->tos;
+ sk->sk_mark = mark;
daddr = ipc.addr = ip_hdr(skb)->saddr;
ipc.opt = NULL;
ipc.tx_flags = 0;
@@ -358,6 +360,7 @@
memset(&fl4, 0, sizeof(fl4));
fl4.daddr = daddr;
fl4.saddr = rt->rt_spec_dst;
+ fl4.flowi4_mark = mark;
fl4.flowi4_tos = RT_TOS(ip_hdr(skb)->tos);
fl4.flowi4_proto = IPPROTO_ICMP;
security_skb_classify_flow(skb, flowi4_to_flowi(&fl4));
@@ -376,7 +379,7 @@
struct flowi4 *fl4,
struct sk_buff *skb_in,
const struct iphdr *iph,
- __be32 saddr, u8 tos,
+ __be32 saddr, u8 tos, u32 mark,
int type, int code,
struct icmp_bxm *param)
{
@@ -388,6 +391,7 @@
fl4->daddr = (param->replyopts.opt.opt.srr ?
param->replyopts.opt.opt.faddr : iph->saddr);
fl4->saddr = saddr;
+ fl4->flowi4_mark = mark;
fl4->flowi4_tos = RT_TOS(tos);
fl4->flowi4_proto = IPPROTO_ICMP;
fl4->fl4_icmp_type = type;
@@ -485,6 +489,7 @@
struct flowi4 fl4;
__be32 saddr;
u8 tos;
+ u32 mark;
struct net *net;
struct sock *sk;
@@ -581,6 +586,7 @@
tos = icmp_pointers[type].error ? ((iph->tos & IPTOS_TOS_MASK) |
IPTOS_PREC_INTERNETCONTROL) :
iph->tos;
+ mark = IP4_REPLY_MARK(net, skb_in->mark);
if (ip_options_echo(&icmp_param.replyopts.opt.opt, skb_in))
goto out_unlock;
@@ -597,11 +603,12 @@
icmp_param.skb = skb_in;
icmp_param.offset = skb_network_offset(skb_in);
inet_sk(sk)->tos = tos;
+ sk->sk_mark = mark;
ipc.addr = iph->saddr;
ipc.opt = &icmp_param.replyopts.opt;
ipc.tx_flags = 0;
- rt = icmp_route_lookup(net, &fl4, skb_in, iph, saddr, tos,
+ rt = icmp_route_lookup(net, &fl4, skb_in, iph, saddr, tos, mark,
type, code, &icmp_param);
if (IS_ERR(rt))
goto out_unlock;
diff --git a/net/ipv4/inet_connection_sock.c b/net/ipv4/inet_connection_sock.c
index b902d58..fb10d58 100644
--- a/net/ipv4/inet_connection_sock.c
+++ b/net/ipv4/inet_connection_sock.c
@@ -361,7 +361,7 @@
struct ip_options_rcu *opt = inet_rsk(req)->opt;
struct net *net = sock_net(sk);
- flowi4_init_output(fl4, sk->sk_bound_dev_if, sk->sk_mark,
+ flowi4_init_output(fl4, sk->sk_bound_dev_if, ireq->ir_mark,
RT_CONN_FLAGS(sk), RT_SCOPE_UNIVERSE,
sk->sk_protocol, inet_sk_flowi_flags(sk),
(opt && opt->opt.srr) ? opt->opt.faddr : ireq->rmt_addr,
@@ -395,7 +395,7 @@
struct rtable *rt;
fl4 = &newinet->cork.fl.u.ip4;
- flowi4_init_output(fl4, sk->sk_bound_dev_if, sk->sk_mark,
+ flowi4_init_output(fl4, sk->sk_bound_dev_if, ireq->ir_mark,
RT_CONN_FLAGS(sk), RT_SCOPE_UNIVERSE,
sk->sk_protocol, inet_sk_flowi_flags(sk),
(opt && opt->opt.srr) ? opt->opt.faddr : ireq->rmt_addr,
@@ -618,6 +618,8 @@
inet_sk(newsk)->inet_sport = inet_rsk(req)->loc_port;
newsk->sk_write_space = sk_stream_write_space;
+ newsk->sk_mark = inet_rsk(req)->ir_mark;
+
newicsk->icsk_retransmits = 0;
newicsk->icsk_backoff = 0;
newicsk->icsk_probes_out = 0;
diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c
index c8e10a5..6f72f39 100644
--- a/net/ipv4/ip_output.c
+++ b/net/ipv4/ip_output.c
@@ -1500,7 +1500,8 @@
daddr = replyopts.opt.opt.faddr;
}
- flowi4_init_output(&fl4, arg->bound_dev_if, 0,
+ flowi4_init_output(&fl4, arg->bound_dev_if,
+ IP4_REPLY_MARK(sock_net(sk), skb->mark),
RT_TOS(arg->tos),
RT_SCOPE_UNIVERSE, sk->sk_protocol,
ip_reply_arg_flowi_flags(arg),
diff --git a/net/ipv4/syncookies.c b/net/ipv4/syncookies.c
index 7f4dba3..b93b6d3 100644
--- a/net/ipv4/syncookies.c
+++ b/net/ipv4/syncookies.c
@@ -312,6 +312,7 @@
ireq->rmt_port = th->source;
ireq->loc_addr = ip_hdr(skb)->daddr;
ireq->rmt_addr = ip_hdr(skb)->saddr;
+ ireq->ir_mark = inet_request_mark(sk, skb);
ireq->ecn_ok = ecn_ok;
ireq->snd_wscale = tcp_opt.snd_wscale;
ireq->sack_ok = tcp_opt.sack_ok;
@@ -347,7 +348,7 @@
* hasn't changed since we received the original syn, but I see
* no easy way to do this.
*/
- flowi4_init_output(&fl4, 0, sk->sk_mark, RT_CONN_FLAGS(sk),
+ flowi4_init_output(&fl4, 0, ireq->ir_mark, RT_CONN_FLAGS(sk),
RT_SCOPE_UNIVERSE, IPPROTO_TCP,
inet_sk_flowi_flags(sk),
(opt && opt->srr) ? opt->faddr : ireq->rmt_addr,
diff --git a/net/ipv4/sysctl_net_ipv4.c b/net/ipv4/sysctl_net_ipv4.c
index 6bd622f..7c81e3b 100644
--- a/net/ipv4/sysctl_net_ipv4.c
+++ b/net/ipv4/sysctl_net_ipv4.c
@@ -788,6 +788,20 @@
.mode = 0644,
.proc_handler = ipv4_tcp_mem,
},
+ {
+ .procname = "fwmark_reflect",
+ .data = &init_net.ipv4.sysctl_fwmark_reflect,
+ .maxlen = sizeof(int),
+ .mode = 0644,
+ .proc_handler = proc_dointvec,
+ },
+ {
+ .procname = "tcp_fwmark_accept",
+ .data = &init_net.ipv4.sysctl_tcp_fwmark_accept,
+ .maxlen = sizeof(int),
+ .mode = 0644,
+ .proc_handler = proc_dointvec,
+ },
{ }
};
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c
index 54225b1..9640f6d 100644
--- a/net/ipv4/tcp_ipv4.c
+++ b/net/ipv4/tcp_ipv4.c
@@ -1350,6 +1350,7 @@
ireq->rmt_addr = saddr;
ireq->no_srccheck = inet_sk(sk)->transparent;
ireq->opt = tcp_v4_save_options(sk, skb);
+ ireq->ir_mark = inet_request_mark(sk, skb);
if (security_inet_conn_request(sk, skb, req))
goto drop_and_free;
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
index 5bb2847..dffd854 100644
--- a/net/ipv6/addrconf.c
+++ b/net/ipv6/addrconf.c
@@ -195,6 +195,7 @@
.accept_ra_rt_info_max_plen = 0,
#endif
#endif
+ .accept_ra_rt_table = 0,
.proxy_ndp = 0,
.accept_source_route = 0, /* we do not accept RH0 by default. */
.disable_ipv6 = 0,
@@ -230,6 +231,7 @@
.accept_ra_rt_info_max_plen = 0,
#endif
#endif
+ .accept_ra_rt_table = 0,
.proxy_ndp = 0,
.accept_source_route = 0, /* we do not accept RH0 by default. */
.disable_ipv6 = 0,
@@ -1690,6 +1692,31 @@
}
#endif
+u32 addrconf_rt_table(const struct net_device *dev, u32 default_table) {
+ /* Determines into what table to put autoconf PIO/RIO/default routes
+ * learned on this device.
+ *
+ * - If 0, use the same table for every device. This puts routes into
+ * one of RT_TABLE_{PREFIX,INFO,DFLT} depending on the type of route
+ * (but note that these three are currently all equal to
+ * RT6_TABLE_MAIN).
+ * - If > 0, use the specified table.
+ * - If < 0, put routes into table dev->ifindex + (-rt_table).
+ */
+ struct inet6_dev *idev = in6_dev_get(dev);
+ u32 table;
+ int sysctl = idev->cnf.accept_ra_rt_table;
+ if (sysctl == 0) {
+ table = default_table;
+ } else if (sysctl > 0) {
+ table = (u32) sysctl;
+ } else {
+ table = (unsigned) dev->ifindex + (-sysctl);
+ }
+ in6_dev_put(idev);
+ return table;
+}
+
/*
* Add prefix route.
*/
@@ -1699,7 +1726,7 @@
unsigned long expires, u32 flags)
{
struct fib6_config cfg = {
- .fc_table = RT6_TABLE_PREFIX,
+ .fc_table = addrconf_rt_table(dev, RT6_TABLE_PREFIX),
.fc_metric = IP6_RT_PRIO_ADDRCONF,
.fc_ifindex = dev->ifindex,
.fc_expires = expires,
@@ -1733,7 +1760,8 @@
struct rt6_info *rt = NULL;
struct fib6_table *table;
- table = fib6_get_table(dev_net(dev), RT6_TABLE_PREFIX);
+ table = fib6_get_table(dev_net(dev),
+ addrconf_rt_table(dev, RT6_TABLE_PREFIX));
if (table == NULL)
return NULL;
@@ -3922,6 +3950,7 @@
array[DEVCONF_ACCEPT_RA_RT_INFO_MAX_PLEN] = cnf->accept_ra_rt_info_max_plen;
#endif
#endif
+ array[DEVCONF_ACCEPT_RA_RT_TABLE] = cnf->accept_ra_rt_table;
array[DEVCONF_PROXY_NDP] = cnf->proxy_ndp;
array[DEVCONF_ACCEPT_SOURCE_ROUTE] = cnf->accept_source_route;
#ifdef CONFIG_IPV6_OPTIMISTIC_DAD
@@ -4550,6 +4579,13 @@
#endif
#endif
{
+ .procname = "accept_ra_rt_table",
+ .data = &ipv6_devconf.accept_ra_rt_table,
+ .maxlen = sizeof(int),
+ .mode = 0644,
+ .proc_handler = proc_dointvec,
+ },
+ {
.procname = "proxy_ndp",
.data = &ipv6_devconf.proxy_ndp,
.maxlen = sizeof(int),
diff --git a/net/ipv6/icmp.c b/net/ipv6/icmp.c
index ba0c147..b595aa6 100644
--- a/net/ipv6/icmp.c
+++ b/net/ipv6/icmp.c
@@ -396,6 +396,7 @@
int len;
int hlimit;
int err = 0;
+ u32 mark = IP6_REPLY_MARK(net, skb->mark);
if ((u8 *)hdr < skb->head ||
(skb->network_header + sizeof(*hdr)) > skb->tail)
@@ -461,6 +462,7 @@
fl6.daddr = hdr->saddr;
if (saddr)
fl6.saddr = *saddr;
+ fl6.flowi6_mark = mark;
fl6.flowi6_oif = iif;
fl6.fl6_icmp_type = type;
fl6.fl6_icmp_code = code;
@@ -469,6 +471,7 @@
sk = icmpv6_xmit_lock(net);
if (sk == NULL)
return;
+ sk->sk_mark = mark;
np = inet6_sk(sk);
if (!icmpv6_xrlim_allow(sk, type, &fl6))
@@ -543,6 +546,7 @@
struct dst_entry *dst;
int err = 0;
int hlimit;
+ u32 mark = IP6_REPLY_MARK(net, skb->mark);
saddr = &ipv6_hdr(skb)->daddr;
@@ -559,11 +563,13 @@
fl6.saddr = *saddr;
fl6.flowi6_oif = skb->dev->ifindex;
fl6.fl6_icmp_type = ICMPV6_ECHO_REPLY;
+ fl6.flowi6_mark = mark;
security_skb_classify_flow(skb, flowi6_to_flowi(&fl6));
sk = icmpv6_xmit_lock(net);
if (sk == NULL)
return;
+ sk->sk_mark = mark;
np = inet6_sk(sk);
if (!fl6.flowi6_oif && ipv6_addr_is_multicast(&fl6.daddr))
diff --git a/net/ipv6/inet6_connection_sock.c b/net/ipv6/inet6_connection_sock.c
index 21ee002..aefc8b7 100644
--- a/net/ipv6/inet6_connection_sock.c
+++ b/net/ipv6/inet6_connection_sock.c
@@ -69,7 +69,7 @@
final_p = fl6_update_dst(&fl6, np->opt, &final);
fl6.saddr = treq->loc_addr;
fl6.flowi6_oif = sk->sk_bound_dev_if;
- fl6.flowi6_mark = sk->sk_mark;
+ fl6.flowi6_mark = inet_rsk(req)->ir_mark;
fl6.fl6_dport = inet_rsk(req)->rmt_port;
fl6.fl6_sport = inet_rsk(req)->loc_port;
fl6.flowi6_uid = sock_i_uid(sk);
diff --git a/net/ipv6/ping.c b/net/ipv6/ping.c
index 8c1e9b2..7559966 100644
--- a/net/ipv6/ping.c
+++ b/net/ipv6/ping.c
@@ -159,6 +159,7 @@
fl6.flowi6_proto = IPPROTO_ICMPV6;
fl6.saddr = np->saddr;
fl6.daddr = *daddr;
+ fl6.flowi6_mark = sk->sk_mark;
fl6.fl6_icmp_type = user_icmph.icmp6_type;
fl6.fl6_icmp_code = user_icmph.icmp6_code;
fl6.flowi6_uid = sock_i_uid(sk);
diff --git a/net/ipv6/route.c b/net/ipv6/route.c
index eabab4a..3e6b53b 100644
--- a/net/ipv6/route.c
+++ b/net/ipv6/route.c
@@ -79,13 +79,13 @@
static void ip6_rt_update_pmtu(struct dst_entry *dst, u32 mtu);
#ifdef CONFIG_IPV6_ROUTE_INFO
-static struct rt6_info *rt6_add_route_info(struct net *net,
+static struct rt6_info *rt6_add_route_info(struct net_device *dev,
const struct in6_addr *prefix, int prefixlen,
- const struct in6_addr *gwaddr, int ifindex,
+ const struct in6_addr *gwaddr,
unsigned pref);
-static struct rt6_info *rt6_get_route_info(struct net *net,
+static struct rt6_info *rt6_get_route_info(struct net_device *dev,
const struct in6_addr *prefix, int prefixlen,
- const struct in6_addr *gwaddr, int ifindex);
+ const struct in6_addr *gwaddr);
#endif
static u32 *ipv6_cow_metrics(struct dst_entry *dst, unsigned long old)
@@ -575,7 +575,6 @@
int rt6_route_rcv(struct net_device *dev, u8 *opt, int len,
const struct in6_addr *gwaddr)
{
- struct net *net = dev_net(dev);
struct route_info *rinfo = (struct route_info *) opt;
struct in6_addr prefix_buf, *prefix;
unsigned int pref;
@@ -617,8 +616,7 @@
prefix = &prefix_buf;
}
- rt = rt6_get_route_info(net, prefix, rinfo->prefix_len, gwaddr,
- dev->ifindex);
+ rt = rt6_get_route_info(dev, prefix, rinfo->prefix_len, gwaddr);
if (rt && !lifetime) {
ip6_del_rt(rt);
@@ -626,8 +624,7 @@
}
if (!rt && lifetime)
- rt = rt6_add_route_info(net, prefix, rinfo->prefix_len, gwaddr, dev->ifindex,
- pref);
+ rt = rt6_add_route_info(dev, prefix, rinfo->prefix_len, gwaddr, pref);
else if (rt)
rt->rt6i_flags = RTF_ROUTEINFO |
(rt->rt6i_flags & ~RTF_PREF_MASK) | RTF_PREF(pref);
@@ -1852,15 +1849,16 @@
}
#ifdef CONFIG_IPV6_ROUTE_INFO
-static struct rt6_info *rt6_get_route_info(struct net *net,
+static struct rt6_info *rt6_get_route_info(struct net_device *dev,
const struct in6_addr *prefix, int prefixlen,
- const struct in6_addr *gwaddr, int ifindex)
+ const struct in6_addr *gwaddr)
{
struct fib6_node *fn;
struct rt6_info *rt = NULL;
struct fib6_table *table;
- table = fib6_get_table(net, RT6_TABLE_INFO);
+ table = fib6_get_table(dev_net(dev),
+ addrconf_rt_table(dev, RT6_TABLE_INFO));
if (!table)
return NULL;
@@ -1870,7 +1868,7 @@
goto out;
for (rt = fn->leaf; rt; rt = rt->dst.rt6_next) {
- if (rt->dst.dev->ifindex != ifindex)
+ if (rt->dst.dev->ifindex != dev->ifindex)
continue;
if ((rt->rt6i_flags & (RTF_ROUTEINFO|RTF_GATEWAY)) != (RTF_ROUTEINFO|RTF_GATEWAY))
continue;
@@ -1884,21 +1882,21 @@
return rt;
}
-static struct rt6_info *rt6_add_route_info(struct net *net,
+static struct rt6_info *rt6_add_route_info(struct net_device *dev,
const struct in6_addr *prefix, int prefixlen,
- const struct in6_addr *gwaddr, int ifindex,
+ const struct in6_addr *gwaddr,
unsigned pref)
{
struct fib6_config cfg = {
- .fc_table = RT6_TABLE_INFO,
+ .fc_table = addrconf_rt_table(dev, RT6_TABLE_INFO),
.fc_metric = IP6_RT_PRIO_USER,
- .fc_ifindex = ifindex,
+ .fc_ifindex = dev->ifindex,
.fc_dst_len = prefixlen,
.fc_flags = RTF_GATEWAY | RTF_ADDRCONF | RTF_ROUTEINFO |
RTF_UP | RTF_PREF(pref),
.fc_nlinfo.pid = 0,
.fc_nlinfo.nlh = NULL,
- .fc_nlinfo.nl_net = net,
+ .fc_nlinfo.nl_net = dev_net(dev),
};
cfg.fc_dst = *prefix;
@@ -1910,7 +1908,7 @@
ip6_route_add(&cfg);
- return rt6_get_route_info(net, prefix, prefixlen, gwaddr, ifindex);
+ return rt6_get_route_info(dev, prefix, prefixlen, gwaddr);
}
#endif
@@ -1919,7 +1917,8 @@
struct rt6_info *rt;
struct fib6_table *table;
- table = fib6_get_table(dev_net(dev), RT6_TABLE_DFLT);
+ table = fib6_get_table(dev_net(dev),
+ addrconf_rt_table(dev, RT6_TABLE_MAIN));
if (!table)
return NULL;
@@ -1941,7 +1940,7 @@
unsigned int pref)
{
struct fib6_config cfg = {
- .fc_table = RT6_TABLE_DFLT,
+ .fc_table = addrconf_rt_table(dev, RT6_TABLE_DFLT),
.fc_metric = IP6_RT_PRIO_USER,
.fc_ifindex = dev->ifindex,
.fc_flags = RTF_GATEWAY | RTF_ADDRCONF | RTF_DEFAULT |
@@ -1958,28 +1957,17 @@
return rt6_get_dflt_router(gwaddr, dev);
}
+
+int rt6_addrconf_purge(struct rt6_info *rt, void *arg) {
+ if (rt->rt6i_flags & (RTF_DEFAULT | RTF_ADDRCONF) &&
+ (!rt->rt6i_idev || rt->rt6i_idev->cnf.accept_ra != 2))
+ return -1;
+ return 0;
+}
+
void rt6_purge_dflt_routers(struct net *net)
{
- struct rt6_info *rt;
- struct fib6_table *table;
-
- /* NOTE: Keep consistent with rt6_get_dflt_router */
- table = fib6_get_table(net, RT6_TABLE_DFLT);
- if (!table)
- return;
-
-restart:
- read_lock_bh(&table->tb6_lock);
- for (rt = table->tb6_root.leaf; rt; rt = rt->dst.rt6_next) {
- if (rt->rt6i_flags & (RTF_DEFAULT | RTF_ADDRCONF) &&
- (!rt->rt6i_idev || rt->rt6i_idev->cnf.accept_ra != 2)) {
- dst_hold(&rt->dst);
- read_unlock_bh(&table->tb6_lock);
- ip6_del_rt(rt);
- goto restart;
- }
- }
- read_unlock_bh(&table->tb6_lock);
+ fib6_clean_all(net, rt6_addrconf_purge, 0, NULL);
}
static void rtmsg_to_fib6_config(struct net *net,
diff --git a/net/ipv6/syncookies.c b/net/ipv6/syncookies.c
index 83ee321..af939af 100644
--- a/net/ipv6/syncookies.c
+++ b/net/ipv6/syncookies.c
@@ -215,6 +215,8 @@
ipv6_addr_type(&ireq6->rmt_addr) & IPV6_ADDR_LINKLOCAL)
ireq6->iif = inet6_iif(skb);
+ ireq->ir_mark = inet_request_mark(sk, skb);
+
req->expires = 0UL;
req->retrans = 0;
ireq->ecn_ok = ecn_ok;
@@ -241,7 +243,7 @@
final_p = fl6_update_dst(&fl6, np->opt, &final);
fl6.saddr = ireq6->loc_addr;
fl6.flowi6_oif = sk->sk_bound_dev_if;
- fl6.flowi6_mark = sk->sk_mark;
+ fl6.flowi6_mark = inet_rsk(req)->ir_mark;
fl6.fl6_dport = inet_rsk(req)->rmt_port;
fl6.fl6_sport = inet_sk(sk)->inet_sport;
fl6.flowi6_uid = sock_i_uid(sk);
diff --git a/net/ipv6/sysctl_net_ipv6.c b/net/ipv6/sysctl_net_ipv6.c
index 166a57c..1f872c3 100644
--- a/net/ipv6/sysctl_net_ipv6.c
+++ b/net/ipv6/sysctl_net_ipv6.c
@@ -48,6 +48,13 @@
.mode = 0644,
.proc_handler = proc_dointvec
},
+ {
+ .procname = "fwmark_reflect",
+ .data = &init_net.ipv6.sysctl.fwmark_reflect,
+ .maxlen = sizeof(int),
+ .mode = 0644,
+ .proc_handler = proc_dointvec
+ },
{ }
};
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c
index 806fafd..a62ce59 100644
--- a/net/ipv6/tcp_ipv6.c
+++ b/net/ipv6/tcp_ipv6.c
@@ -495,7 +495,7 @@
fl6.saddr = treq->loc_addr;
fl6.flowlabel = 0;
fl6.flowi6_oif = treq->iif;
- fl6.flowi6_mark = sk->sk_mark;
+ fl6.flowi6_mark = inet_rsk(req)->ir_mark;
fl6.fl6_dport = inet_rsk(req)->rmt_port;
fl6.fl6_sport = inet_rsk(req)->loc_port;
fl6.flowi6_uid = sock_i_uid(sk);
@@ -900,6 +900,7 @@
fl6.flowi6_proto = IPPROTO_TCP;
fl6.flowi6_oif = inet6_iif(skb);
+ fl6.flowi6_mark = IP6_REPLY_MARK(net, skb->mark);
fl6.fl6_dport = t1->dest;
fl6.fl6_sport = t1->source;
security_skb_classify_flow(skb, flowi6_to_flowi(&fl6));
@@ -1146,6 +1147,7 @@
TCP_ECN_create_request(req, tcp_hdr(skb));
treq->iif = sk->sk_bound_dev_if;
+ inet_rsk(req)->ir_mark = inet_request_mark(sk, skb);
/* So that link locals have meaning */
if (!sk->sk_bound_dev_if &&
diff --git a/sound/soc/codecs/wcd9320.c b/sound/soc/codecs/wcd9320.c
index e17925f..6fac473 100644
--- a/sound/soc/codecs/wcd9320.c
+++ b/sound/soc/codecs/wcd9320.c
@@ -2157,6 +2157,8 @@
static const struct snd_kcontrol_new aif4_mad_switch =
SOC_DAPM_SINGLE("Switch", TAIKO_A_CDC_CLK_OTHR_CTL, 4, 1, 0);
+static const struct snd_kcontrol_new aif4_vi_switch =
+ SOC_DAPM_SINGLE("Switch", TAIKO_A_SPKR_PROT_EN, 3, 1, 0);
/* virtual port entries */
static int slim_tx_mixer_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
@@ -3574,7 +3576,9 @@
{"AIF1 CAP", NULL, "AIF1_CAP Mixer"},
{"AIF2 CAP", NULL, "AIF2_CAP Mixer"},
{"AIF3 CAP", NULL, "AIF3_CAP Mixer"},
- {"AIF4 VI", NULL, "SPK_OUT"},
+ /* VI Feedback */
+ {"AIF4 VI", NULL, "VIONOFF"},
+ {"VIONOFF", "Switch", "VIINPUT"},
/* MAD */
{"AIF4 MAD", NULL, "CDC_CONN"},
@@ -5244,6 +5248,15 @@
if (ret)
pr_err("%s error in close_slim_sch_tx %d\n",
__func__, ret);
+ ret = taiko_codec_enable_slim_chmask(dai, false);
+ if (ret < 0) {
+ ret = wcd9xxx_disconnect_port(core,
+ &dai->wcd9xxx_ch_list,
+ dai->grph);
+ pr_debug("%s: Disconnect RX port, ret = %d\n",
+ __func__, ret);
+ }
+
snd_soc_update_bits(codec, TAIKO_A_CDC_CLK_TX_CLK_EN_B2_CTL,
0xC, 0x0);
/*Disable V&I sensing*/
@@ -5943,6 +5956,10 @@
SND_SOC_DAPM_MIXER("LINEOUT4_PA_MIXER", SND_SOC_NOPM, 0, 0,
lineout4_pa_mix, ARRAY_SIZE(lineout4_pa_mix)),
+ SND_SOC_DAPM_SWITCH("VIONOFF", SND_SOC_NOPM, 0, 0,
+ &aif4_vi_switch),
+ SND_SOC_DAPM_INPUT("VIINPUT"),
+
};
static irqreturn_t taiko_slimbus_irq(int irq, void *data)
@@ -6777,7 +6794,9 @@
/* Clean up starts */
/* Turn off PA ramp generator */
snd_soc_write(codec, WCD9XXX_A_CDC_PA_RAMP_B1_CTL, 0x0);
- if (!mbhc->hph_pa_dac_state)
+ if (!mbhc->hph_pa_dac_state &&
+ (!(test_bit(MBHC_EVENT_PA_HPHL, &mbhc->event_state) ||
+ test_bit(MBHC_EVENT_PA_HPHR, &mbhc->event_state))))
wcd9xxx_enable_static_pa(mbhc, false);
wcd9xxx_restore_registers(codec, &taiko->reg_save_restore);
break;
diff --git a/sound/soc/msm/qdsp6v2/q6audio-v2.c b/sound/soc/msm/qdsp6v2/q6audio-v2.c
index 57ea2a7..0ff96b1 100644
--- a/sound/soc/msm/qdsp6v2/q6audio-v2.c
+++ b/sound/soc/msm/qdsp6v2/q6audio-v2.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2014, 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
@@ -80,6 +80,67 @@
}
}
+int q6audio_get_port_id_from_index(u16 port_idx)
+{
+ switch (port_idx) {
+ case IDX_PRIMARY_I2S_RX: return PRIMARY_I2S_RX;
+ case IDX_PRIMARY_I2S_TX: return PRIMARY_I2S_TX;
+ case IDX_AFE_PORT_ID_PRIMARY_PCM_RX:
+ return AFE_PORT_ID_PRIMARY_PCM_RX;
+ case IDX_AFE_PORT_ID_PRIMARY_PCM_TX:
+ return AFE_PORT_ID_PRIMARY_PCM_TX;
+ case IDX_AFE_PORT_ID_SECONDARY_PCM_RX:
+ return AFE_PORT_ID_SECONDARY_PCM_RX;
+ case IDX_AFE_PORT_ID_SECONDARY_PCM_TX:
+ return AFE_PORT_ID_SECONDARY_PCM_TX;
+ case IDX_SECONDARY_I2S_RX: return SECONDARY_I2S_RX;
+ case IDX_SECONDARY_I2S_TX: return SECONDARY_I2S_TX;
+ case IDX_MI2S_RX: return MI2S_RX;
+ case IDX_MI2S_TX: return MI2S_TX;
+ case IDX_HDMI_RX: return HDMI_RX;
+ case IDX_RSVD_2: return RSVD_2;
+ case IDX_RSVD_3: return RSVD_3;
+ case IDX_DIGI_MIC_TX: return DIGI_MIC_TX;
+ case IDX_VOICE_RECORD_RX: return VOICE_RECORD_RX;
+ case IDX_VOICE_RECORD_TX: return VOICE_RECORD_TX;
+ case IDX_VOICE_PLAYBACK_TX: return VOICE_PLAYBACK_TX;
+ case IDX_VOICE2_PLAYBACK_TX: return VOICE2_PLAYBACK_TX;
+ case IDX_SLIMBUS_0_RX: return SLIMBUS_0_RX;
+ case IDX_SLIMBUS_0_TX: return SLIMBUS_0_TX;
+ case IDX_SLIMBUS_1_RX: return SLIMBUS_1_RX;
+ case IDX_SLIMBUS_1_TX: return SLIMBUS_1_TX;
+ case IDX_SLIMBUS_2_RX: return SLIMBUS_2_RX;
+ case IDX_SLIMBUS_2_TX: return SLIMBUS_2_TX;
+ case IDX_SLIMBUS_4_TX: return SLIMBUS_4_TX;
+ case IDX_SLIMBUS_5_TX: return SLIMBUS_5_TX;
+ case IDX_INT_BT_SCO_RX: return INT_BT_SCO_RX;
+ case IDX_INT_BT_SCO_TX: return INT_BT_SCO_TX;
+ case IDX_INT_BT_A2DP_RX: return INT_BT_A2DP_RX;
+ case IDX_INT_FM_RX: return INT_FM_RX;
+ case IDX_INT_FM_TX: return INT_FM_TX;
+ case IDX_RT_PROXY_PORT_001_RX: return RT_PROXY_PORT_001_RX;
+ case IDX_RT_PROXY_PORT_001_TX: return RT_PROXY_PORT_001_TX;
+ case IDX_AFE_PORT_ID_PRIMARY_MI2S_RX:
+ return AFE_PORT_ID_PRIMARY_MI2S_RX;
+ case IDX_AFE_PORT_ID_PRIMARY_MI2S_TX:
+ return AFE_PORT_ID_PRIMARY_MI2S_TX;
+ case IDX_AFE_PORT_ID_QUATERNARY_MI2S_RX:
+ return AFE_PORT_ID_QUATERNARY_MI2S_RX;
+ case IDX_AFE_PORT_ID_QUATERNARY_MI2S_TX:
+ return AFE_PORT_ID_QUATERNARY_MI2S_TX;
+ case IDX_AFE_PORT_ID_SECONDARY_MI2S_RX:
+ return AFE_PORT_ID_SECONDARY_MI2S_RX;
+ case IDX_AFE_PORT_ID_SECONDARY_MI2S_TX:
+ return AFE_PORT_ID_SECONDARY_MI2S_TX;
+ case IDX_AFE_PORT_ID_TERTIARY_MI2S_RX:
+ return AFE_PORT_ID_TERTIARY_MI2S_RX;
+ case IDX_AFE_PORT_ID_TERTIARY_MI2S_TX:
+ return AFE_PORT_ID_TERTIARY_MI2S_TX;
+
+ default: return -EINVAL;
+ }
+}
+
int q6audio_get_port_id(u16 port_id)
{
switch (port_id) {
diff --git a/sound/soc/msm/qdsp6v2/rtac.c b/sound/soc/msm/qdsp6v2/rtac.c
index 701dfef..80c18b1 100644
--- a/sound/soc/msm/qdsp6v2/rtac.c
+++ b/sound/soc/msm/qdsp6v2/rtac.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2014, 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
@@ -24,6 +24,7 @@
#include <mach/qdsp6v2/rtac.h>
#include <sound/q6asm-v2.h>
#include <sound/q6afe-v2.h>
+#include <sound/q6audio-v2.h>
#include <sound/apr_audio-v2.h>
#include <q6voice.h>
#include "audio_acdb.h"
@@ -822,6 +823,7 @@
u32 bytes_returned = 0;
u32 port_index = 0;
u32 copp_id;
+ int port_id;
u32 payload_size;
u32 data_size = 0;
struct apr_hdr adm_params;
@@ -880,6 +882,13 @@
__func__, copp_id);
goto done;
}
+ port_id = q6audio_get_port_id_from_index(port_index);
+
+ if (port_id < 0) {
+ pr_err("%s: Could not find port id mapped for port_idx %d\n",
+ __func__, port_index);
+ goto done;
+ }
mutex_lock(&rtac_adm_apr_mutex);
if (rtac_adm_apr_data.apr_handle == NULL) {
@@ -936,7 +945,7 @@
adm_params.dest_svc = APR_SVC_ADM;
adm_params.dest_domain = APR_DOMAIN_ADSP;
adm_params.dest_port = copp_id;
- adm_params.token = copp_id;
+ adm_params.token = port_id;
adm_params.opcode = opcode;
/* fill for out-of-band */