diff --git a/android/GKI_VERSION b/android/GKI_VERSION
index 36a40ead11ef..da598c937dca 100644
--- a/android/GKI_VERSION
+++ b/android/GKI_VERSION
@@ -1 +1 @@
-LTS_5.4.86_ccdcd307cf7e
+LTS_5.4.86_7d99cf8c84a7
diff --git a/android/abi_gki_aarch64.xml b/android/abi_gki_aarch64.xml
index c3d6fb4f3c40..2e8113c8c557 100644
--- a/android/abi_gki_aarch64.xml
+++ b/android/abi_gki_aarch64.xml
@@ -1842,12 +1842,14 @@
+
+
@@ -3168,6 +3170,7 @@
+
@@ -3999,6 +4002,7 @@
+
@@ -4099,6 +4103,7 @@
+
@@ -8154,7 +8159,7 @@
-
+
@@ -11062,7 +11067,7 @@
-
+
@@ -17785,7 +17790,7 @@
-
+
@@ -20403,7 +20408,7 @@
-
+
@@ -20411,7 +20416,7 @@
-
+
@@ -23284,7 +23289,7 @@
-
+
@@ -23303,7 +23308,7 @@
-
+
@@ -23580,7 +23585,7 @@
-
+
@@ -23648,7 +23653,7 @@
-
+
@@ -23656,7 +23661,7 @@
-
+
@@ -25859,7 +25864,7 @@
-
+
@@ -26238,7 +26243,7 @@
-
+
@@ -26262,7 +26267,7 @@
-
+
@@ -26270,7 +26275,7 @@
-
+
@@ -26289,7 +26294,7 @@
-
+
@@ -26305,7 +26310,7 @@
-
+
@@ -26332,7 +26337,7 @@
-
+
@@ -26343,7 +26348,7 @@
-
+
@@ -28161,7 +28166,7 @@
-
+
@@ -28169,7 +28174,7 @@
-
+
@@ -28214,7 +28219,7 @@
-
+
@@ -28563,7 +28568,7 @@
-
+
@@ -30028,7 +30033,7 @@
-
+
@@ -30967,7 +30972,7 @@
-
+
@@ -31207,7 +31212,7 @@
-
+
@@ -31215,7 +31220,7 @@
-
+
@@ -31223,7 +31228,7 @@
-
+
@@ -31953,7 +31958,7 @@
-
+
@@ -31964,7 +31969,7 @@
-
+
@@ -32427,7 +32432,7 @@
-
+
@@ -32503,7 +32508,7 @@
-
+
@@ -32765,7 +32770,7 @@
-
+
@@ -51512,44 +51517,6 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
@@ -51850,6 +51817,44 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -58527,6 +58532,9 @@
+
+
+
@@ -69109,6 +69117,12 @@
+
+
+
+
+
+
@@ -108282,7 +108296,7 @@
-
+
@@ -108656,7 +108670,7 @@
-
+
@@ -108664,7 +108678,7 @@
-
+
@@ -108672,7 +108686,7 @@
-
+
@@ -108680,12 +108694,12 @@
-
+
-
+
@@ -111863,7 +111877,7 @@
-
+
@@ -111872,7 +111886,7 @@
-
+
@@ -111880,7 +111894,7 @@
-
+
@@ -111888,7 +111902,7 @@
-
+
@@ -111897,7 +111911,7 @@
-
+
@@ -111905,7 +111919,7 @@
-
+
@@ -112185,7 +112199,7 @@
-
+
@@ -112207,7 +112221,7 @@
-
+
@@ -112218,7 +112232,7 @@
-
+
@@ -112226,7 +112240,7 @@
-
+
@@ -112237,7 +112251,7 @@
-
+
@@ -112249,7 +112263,7 @@
-
+
@@ -112260,7 +112274,7 @@
-
+
@@ -112509,7 +112523,7 @@
-
+
@@ -112539,7 +112553,7 @@
-
+
@@ -112547,7 +112561,7 @@
-
+
@@ -112699,7 +112713,7 @@
-
+
@@ -112975,7 +112989,7 @@
-
+
@@ -113020,7 +113034,7 @@
-
+
@@ -113227,7 +113241,7 @@
-
+
@@ -113316,7 +113330,7 @@
-
+
@@ -113324,7 +113338,7 @@
-
+
@@ -113332,7 +113346,7 @@
-
+
@@ -113340,7 +113354,7 @@
-
+
@@ -113410,7 +113424,205 @@
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -113598,7 +113810,7 @@
-
+
@@ -113677,7 +113889,7 @@
-
+
@@ -113726,7 +113938,7 @@
-
+
@@ -113902,204 +114114,6 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
@@ -114215,7 +114229,7 @@
-
+
@@ -114226,7 +114240,7 @@
-
+
@@ -114234,7 +114248,7 @@
-
+
@@ -114684,7 +114698,7 @@
-
+
@@ -119910,6 +119924,17 @@
+
+
+
+
+
+
+
+
+
+
+
@@ -122008,57 +122033,57 @@
-
-
-
-
-
-
+
+
+
+
+
+
-
-
-
+
+
+
-
-
-
-
+
+
+
+
-
-
-
-
-
-
+
+
+
+
+
+
-
-
+
+
-
-
+
+
-
-
+
+
-
-
-
+
+
+
-
-
+
+
-
-
-
+
+
+
@@ -130106,6 +130131,10 @@
+
+
+
+
@@ -148429,7 +148458,7 @@
-
+
@@ -164408,6 +164437,8 @@
+
+
@@ -164436,6 +164467,11 @@
+
+
+
+
+
@@ -164686,13 +164722,13 @@
-
-
+
+
-
-
-
+
+
+
@@ -166173,9 +166209,9 @@
-
-
-
+
+
+
@@ -166183,9 +166219,9 @@
-
-
-
+
+
+
@@ -166381,33 +166417,33 @@
-
-
-
-
-
+
+
+
+
+
-
-
-
-
-
+
+
+
+
+
-
-
-
-
+
+
+
+
-
-
-
+
+
+
-
-
+
+
@@ -167614,7 +167650,7 @@
-
+
@@ -170267,7 +170303,7 @@
-
+
@@ -173986,7 +174022,7 @@
-
+
@@ -175900,9 +175936,15 @@
+
+
+
+
+
+
@@ -175956,7 +175998,42 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -176164,12 +176241,6 @@
-
-
-
-
-
-
@@ -176240,7 +176311,7 @@
-
+
@@ -176324,38 +176395,6 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
@@ -176370,7 +176409,7 @@
-
+
@@ -176432,9 +176471,6 @@
-
-
-
@@ -178752,7 +178788,7 @@
-
+
@@ -178781,7 +178817,7 @@
-
+
@@ -179373,7 +179409,7 @@
-
+
@@ -180333,7 +180369,7 @@
-
+
@@ -191014,6 +191050,6 @@
diff --git a/android/abi_gki_aarch64_ccdcd307cf7e.xml b/android/abi_gki_aarch64_7d99cf8c84a7.xml
similarity index 99%
rename from android/abi_gki_aarch64_ccdcd307cf7e.xml
rename to android/abi_gki_aarch64_7d99cf8c84a7.xml
index 3d06994549d6..f65ea5b69f70 100644
--- a/android/abi_gki_aarch64_ccdcd307cf7e.xml
+++ b/android/abi_gki_aarch64_7d99cf8c84a7.xml
@@ -235,10 +235,12 @@
+
+
@@ -1832,6 +1834,7 @@
+
@@ -2011,6 +2014,7 @@
+
@@ -24900,6 +24904,9 @@
+
+
+
@@ -32752,7 +32759,7 @@
-
+
@@ -33873,7 +33880,7 @@
-
+
@@ -34674,7 +34681,7 @@
-
+
@@ -37237,7 +37244,7 @@
-
+
@@ -38337,7 +38344,7 @@
-
+
@@ -38727,7 +38734,7 @@
-
+
@@ -47003,7 +47010,7 @@
-
+
@@ -49110,7 +49117,7 @@
-
+
@@ -49118,7 +49125,7 @@
-
+
@@ -49126,7 +49133,7 @@
-
+
@@ -49750,7 +49757,7 @@
-
+
@@ -55304,7 +55311,7 @@
-
+
@@ -55312,7 +55319,7 @@
-
+
@@ -55624,7 +55631,7 @@
-
+
@@ -55739,7 +55746,7 @@
-
+
@@ -55790,7 +55797,7 @@
-
+
@@ -58970,7 +58977,7 @@
-
+
@@ -59141,7 +59148,23 @@
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -59150,7 +59173,74 @@
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -59308,6 +59398,9 @@
+
+
+
@@ -59368,9 +59461,13 @@
+
+
+
+
@@ -59655,6 +59752,17 @@
+
+
+
+
+
+
+
+
+
+
+
@@ -60004,7 +60112,7 @@
-
+
@@ -60012,7 +60120,7 @@
-
+
@@ -60111,6 +60219,9 @@
+
+
+
@@ -60225,6 +60336,60 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -60246,6 +60411,44 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -60573,6 +60776,14 @@
+
+
+
+
+
+
+
+
@@ -60616,10 +60827,15 @@
+
+
+
+
+
@@ -61574,7 +61790,7 @@
-
+
@@ -61795,6 +62011,98 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -62365,11 +62673,15 @@
+
+
+
+
@@ -62697,17 +63009,6 @@
-
-
-
-
-
-
-
-
-
-
-
@@ -63209,12 +63510,15 @@
+
+
+
-
+
@@ -63222,7 +63526,7 @@
-
+
@@ -63244,6 +63548,7 @@
+
@@ -63303,12 +63608,10 @@
-
-
-
+
@@ -63505,6 +63808,58 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -63897,7 +64252,7 @@
-
+
@@ -63905,7 +64260,7 @@
-
+
@@ -63913,7 +64268,7 @@
-
+
@@ -63921,7 +64276,7 @@
-
+
@@ -63929,7 +64284,7 @@
-
+
@@ -63940,7 +64295,7 @@
-
+
@@ -63948,7 +64303,7 @@
-
+
@@ -63959,7 +64314,7 @@
-
+
@@ -63967,7 +64322,7 @@
-
+
@@ -64049,6 +64404,7 @@
+
@@ -64099,6 +64455,26 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -64145,7 +64521,89 @@
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -64236,7 +64694,7 @@
-
+
@@ -64279,6 +64737,7 @@
+
@@ -64542,10 +65001,260 @@
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -64553,7 +65262,14 @@
+
+
+
+
+
+
+
@@ -64573,6 +65289,86 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -64691,22 +65487,181 @@
-
+
+
-
-
-
-
+
-
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -64715,6 +65670,14 @@
+
+
+
+
+
+
+
+
@@ -64732,7 +65695,18 @@
+
+
+
+
+
+
+
+
+
+
+
@@ -64769,6 +65743,17 @@
+
+
+
+
+
+
+
+
+
+
+
@@ -64807,10 +65792,98 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -64855,15 +65928,90 @@
-
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -64875,11 +66023,34 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -64896,6 +66067,10 @@
+
+
+
+
@@ -65011,6 +66186,7 @@
+
@@ -65210,7 +66386,6 @@
-
@@ -65368,53 +66543,10 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
@@ -65448,296 +66580,6 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
@@ -66489,6 +67331,20 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -66506,8 +67362,8 @@
-
-
+
+
@@ -66535,20 +67391,6 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
@@ -66567,6 +67409,7 @@
+
@@ -66578,21 +67421,21 @@
-
+
-
+
-
+
-
+
@@ -66627,99 +67470,99 @@
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
@@ -66836,12 +67679,12 @@
-
+
-
+
@@ -66928,7 +67771,7 @@
-
+
@@ -67050,14 +67893,14 @@
-
+
-
+
-
+
@@ -76041,6 +76884,13 @@
+
+
+
+
+
+
+
@@ -84903,27 +85753,27 @@
-
-
-
+
+
+
-
-
+
+
-
-
-
+
+
+
-
-
+
+
-
-
-
+
+
+
@@ -84967,37 +85817,37 @@
-
-
-
-
-
-
-
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
-
-
+
+
-
-
+
+
-
-
-
+
+
+
@@ -85846,25 +86696,25 @@
-
-
-
-
+
+
+
+
-
-
-
+
+
+
-
-
+
+
-
-
-
-
+
+
+
+
@@ -85898,8 +86748,8 @@
-
-
+
+
@@ -111740,9 +112590,92 @@
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -111914,20 +112847,7 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
@@ -111999,8 +112919,232 @@
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -112574,7 +113718,7 @@
-
+
@@ -112591,7 +113735,7 @@
-
+
@@ -112599,7 +113743,7 @@
-
+
@@ -112616,7 +113760,7 @@
-
+
@@ -112818,7 +113962,7 @@
-
+
@@ -112832,7 +113976,7 @@
-
+
@@ -112854,7 +113998,7 @@
-
+
@@ -113596,12 +114740,12 @@
-
+
-
+
@@ -113673,7 +114817,7 @@
-
+
@@ -114354,7 +115498,7 @@
-
+
@@ -114388,7 +115532,7 @@
-
+
@@ -114727,7 +115871,7 @@
-
+
@@ -114868,7 +116012,7 @@
-
+
@@ -115214,7 +116358,7 @@
-
+
@@ -115244,7 +116388,7 @@
-
+
@@ -115960,7 +117104,7 @@
-
+
@@ -116367,7 +117511,7 @@
-
+
@@ -117057,7 +118201,7 @@
-
+
@@ -117187,7 +118331,7 @@
-
+
@@ -117218,7 +118362,7 @@
-
+
@@ -117227,7 +118371,7 @@
-
+
@@ -117249,7 +118393,7 @@
-
+
@@ -117260,7 +118404,7 @@
-
+
@@ -117268,7 +118412,7 @@
-
+
@@ -117279,7 +118423,7 @@
-
+
@@ -117327,7 +118471,7 @@
-
+
@@ -117408,7 +118552,7 @@
-
+
@@ -117564,7 +118708,7 @@
-
+
@@ -117578,7 +118722,7 @@
-
+
@@ -117773,7 +118917,7 @@
-
+
@@ -120195,6 +121339,18 @@
+
+
+
+
+
+
+
+
+
+
+
+
@@ -130111,8 +131267,8 @@
-
-
+
+
@@ -130968,9 +132124,274 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -130994,10 +132415,10 @@
-
+
-
+
@@ -131047,7 +132468,7 @@
-
+
@@ -131093,30 +132514,30 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
@@ -131187,7 +132608,7 @@
-
+
@@ -131278,6 +132699,13 @@
+
+
+
+
+
+
+
@@ -131285,6 +132713,10 @@
+
+
+
+
@@ -131346,9 +132778,9 @@
-
-
-
+
+
+
@@ -131850,7 +133282,6 @@
-
@@ -132044,11 +133475,11 @@
-
-
-
-
-
+
+
+
+
+
@@ -132064,89 +133495,6 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
@@ -132327,149 +133675,6 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
@@ -132847,10 +134052,8 @@
-
-
@@ -132951,34 +134154,34 @@
-
+
-
+
-
+
-
+
-
+
-
+
@@ -133026,21 +134229,21 @@
-
+
-
+
-
+
-
+
@@ -133355,7 +134558,6 @@
-
@@ -133368,9 +134570,6 @@
-
-
-
@@ -133405,13 +134604,6 @@
-
-
-
-
-
-
-
@@ -134025,195 +135217,6 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
@@ -137254,10 +138257,6 @@
-
-
-
-
@@ -137282,7 +138281,6 @@
-
@@ -137370,13 +138368,7 @@
-
-
-
-
-
-
@@ -137444,13 +138436,6 @@
-
-
-
-
-
-
-
@@ -138028,10 +139013,6 @@
-
-
-
-
@@ -139259,20 +140240,6 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/android/abi_gki_aarch64_db845c b/android/abi_gki_aarch64_db845c
index 671c62ec75aa..b77a5a8637cb 100644
--- a/android/abi_gki_aarch64_db845c
+++ b/android/abi_gki_aarch64_db845c
@@ -92,6 +92,7 @@
devm_phy_get
devm_pinctrl_register
devm_platform_ioremap_resource
+ devm_regmap_field_alloc
__devm_regmap_init_mmio_clk
devm_regulator_bulk_get
devm_regulator_get
@@ -213,6 +214,7 @@
irq_set_irq_wake
irq_to_desc
jiffies
+ jiffies_to_usecs
kfree
kfree_skb
kimage_vaddr
@@ -251,6 +253,8 @@
__netdev_alloc_skb
netif_napi_add
netif_napi_del
+ nvmem_cell_get
+ nvmem_cell_put
nvmem_cell_read
of_address_to_resource
of_alias_get_id
@@ -368,6 +372,7 @@
__register_rpmsg_driver
regmap_bulk_read
regmap_bulk_write
+ regmap_field_read
regmap_read
regmap_update_bits_base
regmap_write
@@ -1048,8 +1053,6 @@
no_llseek
nsecs_to_jiffies
ns_to_timespec
- nvmem_cell_get
- nvmem_cell_put
of_device_is_available
of_dma_configure
of_drm_find_bridge
@@ -1227,10 +1230,8 @@
of_irq_get
# required by qcom_hwspinlock.ko
- devm_regmap_field_alloc
hwspin_lock_register
hwspin_lock_unregister
- regmap_field_read
regmap_field_update_bits_base
# required by qcom_q6v5.ko
@@ -1252,7 +1253,6 @@
__memcpy_toio
# required by qcom_spmi-regulator.ko
- jiffies_to_usecs
regulator_disable_regmap
regulator_enable_regmap
regulator_is_enabled_regmap
@@ -1263,6 +1263,10 @@
rproc_get_by_child
try_wait_for_completion
+# required by qcom_tsens.ko
+ devm_thermal_zone_of_sensor_register
+ thermal_zone_get_slope
+
# required by qmi_helpers.ko
init_net
kernel_getsockname
diff --git a/android/abi_gki_aarch64_exynos b/android/abi_gki_aarch64_exynos
index ac98ae3dd488..1f795dac9b27 100644
--- a/android/abi_gki_aarch64_exynos
+++ b/android/abi_gki_aarch64_exynos
@@ -1462,6 +1462,7 @@
static_key_initialized
static_key_slow_dec
static_key_slow_inc
+ stpcpy
strcasecmp
strcat
strchr
diff --git a/android/abi_gki_aarch64_galaxy b/android/abi_gki_aarch64_galaxy
index bef65a0d87b9..b65bf734e98c 100644
--- a/android/abi_gki_aarch64_galaxy
+++ b/android/abi_gki_aarch64_galaxy
@@ -1103,9 +1103,11 @@
gpiochip_generic_free
gpiochip_generic_request
gpiochip_get_data
+ gpiochip_irqchip_add_key
gpiochip_line_is_valid
gpiochip_lock_as_irq
gpiochip_remove
+ gpiochip_set_nested_irqchip
gpiochip_unlock_as_irq
gpiod_direction_input
gpiod_direction_output
diff --git a/android/abi_gki_aarch64_qcom b/android/abi_gki_aarch64_qcom
index 65c93927312c..670cca06141c 100644
--- a/android/abi_gki_aarch64_qcom
+++ b/android/abi_gki_aarch64_qcom
@@ -45,10 +45,12 @@
backlight_device_unregister
bin2hex
__bitmap_clear
+ bitmap_find_free_region
bitmap_find_next_zero_area_off
bitmap_free
bitmap_parselist
bitmap_print_to_pagebuf
+ bitmap_release_region
__bitmap_set
__bitmap_subset
bitmap_zalloc
@@ -1803,6 +1805,7 @@
__pm_runtime_use_autosuspend
__pm_stay_awake
pm_stay_awake
+ pm_system_cancel_wakeup
pm_system_wakeup
pm_wakeup_dev_event
pm_wakeup_ws_event
@@ -2024,6 +2027,7 @@
rpmsg_set_signals
rpmsg_trysend
rpmsg_unregister_device
+ rtc_add_group
rtc_class_close
rtc_class_open
rtc_read_time
diff --git a/arch/arm/configs/vendor/monaco.config b/arch/arm/configs/vendor/monaco.config
index cf10179279a0..f3ba1baa2f05 100644
--- a/arch/arm/configs/vendor/monaco.config
+++ b/arch/arm/configs/vendor/monaco.config
@@ -430,6 +430,7 @@ CONFIG_INCREMENTAL_FS=y
CONFIG_QFMT_V2=y
# CONFIG_QFMT_V1 is not set
CONFIG_MSM_ADSPRPC=y
+CONFIG_MSM_RDBG=m
CONFIG_QSEECOM=y
CONFIG_USB_CONFIGFS_F_ACC=y
CONFIG_USB_CONFIGFS_F_AUDIO_SRC=y
diff --git a/arch/arm/configs/vendor/sdxnightjar-debug.config b/arch/arm/configs/vendor/sdxnightjar-debug.config
index 84d8a55ee6ea..82e13f7a4b1b 100644
--- a/arch/arm/configs/vendor/sdxnightjar-debug.config
+++ b/arch/arm/configs/vendor/sdxnightjar-debug.config
@@ -890,3 +890,5 @@ CONFIG_QTI_SYSTEM_PM_RPM=y
CONFIG_HARDENED_USERCOPY=y
CONFIG_STM_PROTO_BASIC=y
CONFIG_QTI_ADC_TM=y
+CONFIG_PANIC_ON_SCHED_BUG=y
+CONFIG_PANIC_ON_RT_THROTTLING=y
diff --git a/arch/arm/configs/vendor/sdxnightjar.config b/arch/arm/configs/vendor/sdxnightjar.config
index 2b5b98783c9b..9a5eeb11a235 100644
--- a/arch/arm/configs/vendor/sdxnightjar.config
+++ b/arch/arm/configs/vendor/sdxnightjar.config
@@ -64,6 +64,62 @@ CONFIG_INTERCONNECT_TEST=y
CONFIG_INTERCONNECT_QCOM=y
CONFIG_DEBUG_FS=y
CONFIG_ARCH_SDXNIGHTJAR=y
+CONFIG_ETHERNET=y
+# CONFIG_NET_VENDOR_3COM is not set
+# CONFIG_NET_VENDOR_ADAPTEC is not set
+# CONFIG_NET_VENDOR_AGERE is not set
+# CONFIG_NET_VENDOR_ALACRITECH is not set
+# CONFIG_NET_VENDOR_ALTEON is not set
+# CONFIG_ALTERA_TSE is not set
+# CONFIG_NET_VENDOR_AMAZON is not set
+# CONFIG_NET_VENDOR_AMD is not set
+# CONFIG_NET_VENDOR_AQUANTIA is not set
+# CONFIG_NET_VENDOR_ARC is not set
+CONFIG_NET_VENDOR_ATHEROS=y
+# CONFIG_ATL2 is not set
+# CONFIG_ATL1 is not set
+# CONFIG_ATL1E is not set
+# CONFIG_ATL1C is not set
+# CONFIG_ALX is not set
+# CONFIG_NET_VENDOR_AURORA is not set
+# CONFIG_NET_VENDOR_BROADCOM is not set
+# CONFIG_NET_VENDOR_BROCADE is not set
+# CONFIG_NET_VENDOR_CADENCE is not set
+# CONFIG_NET_VENDOR_CAVIUM is not set
+# CONFIG_NET_VENDOR_CHELSIO is not set
+# CONFIG_NET_VENDOR_CIRRUS is not set
+# CONFIG_NET_VENDOR_CISCO is not set
+# CONFIG_NET_VENDOR_CORTINA is not set
+# CONFIG_DM9000 is not set
+# CONFIG_DNET is not set
+# CONFIG_NET_VENDOR_DEC is not set
+# CONFIG_NET_VENDOR_DLINK is not set
+# CONFIG_NET_VENDOR_EMULEX is not set
+# CONFIG_NET_VENDOR_EZCHIP is not set
+# CONFIG_NET_VENDOR_FARADAY is not set
+# CONFIG_NET_VENDOR_GOOGLE is not set
+# CONFIG_NET_VENDOR_HISILICON is not set
+# CONFIG_NET_VENDOR_HP is not set
+# CONFIG_NET_VENDOR_HUAWEI is not set
+# CONFIG_NET_VENDOR_INTEL is not set
+# CONFIG_JME is not set
+# CONFIG_NET_VENDOR_MARVELL is not set
+# CONFIG_NET_VENDOR_MELLANOX is not set
+# CONFIG_NET_VENDOR_MICREL is not set
+# CONFIG_NET_VENDOR_MICROCHIP is not set
+# CONFIG_NET_VENDOR_MICROSEMI is not set
+# CONFIG_NET_VENDOR_MYRI is not set
+# CONFIG_FEALNX is not set
+# CONFIG_NET_VENDOR_NATSEMI is not set
+# CONFIG_NET_VENDOR_NETERION is not set
+# CONFIG_NET_VENDOR_NETRONOME is not set
+# CONFIG_NET_VENDOR_NI is not set
+# CONFIG_NET_VENDOR_NVIDIA is not set
+# CONFIG_NET_VENDOR_OKI is not set
+# CONFIG_ETHOC is not set
+# CONFIG_NET_VENDOR_PACKET_ENGINES is not set
+# CONFIG_NET_VENDOR_PENSANDO is not set
+# CONFIG_NET_VENDOR_QLOGIC is not set
CONFIG_PINCTRL_SDXNIGHTJAR=y
# CONFIG_ARCH_SDXLEMUR is not set
# CONFIG_PINCTRL_SDXLEMUR is not set
@@ -926,3 +982,19 @@ CONFIG_PCIEPORTBUS=y
CONFIG_PCIEAER=y
CONFIG_PCI_QTI=y
CONFIG_PCIEASPM_POWER_SUPERSAVE=y
+# CONFIG_WLAN_VENDOR_ADMTEK is not set
+# CONFIG_WLAN_VENDOR_ATH is not set
+# CONFIG_WLAN_VENDOR_ATMEL is not set
+# CONFIG_WLAN_VENDOR_BROADCOM is not set
+# CONFIG_WLAN_VENDOR_CISCO is not set
+# CONFIG_WLAN_VENDOR_INTEL is not set
+# CONFIG_WLAN_VENDOR_INTERSIL is not set
+# CONFIG_WLAN_VENDOR_MARVELL is not set
+# CONFIG_WLAN_VENDOR_MEDIATEK is not set
+# CONFIG_WLAN_VENDOR_RALINK is not set
+# CONFIG_WLAN_VENDOR_REALTEK is not set
+# CONFIG_WLAN_VENDOR_RSI is not set
+# CONFIG_WLAN_VENDOR_ST is not set
+# CONFIG_WLAN_VENDOR_TI is not set
+# CONFIG_WLAN_VENDOR_ZYDAS is not set
+# CONFIG_WLAN_VENDOR_QUANTENNA is not set
diff --git a/arch/arm64/configs/db845c_gki.fragment b/arch/arm64/configs/db845c_gki.fragment
index c8ca9a8110c6..2e69bf2494cb 100644
--- a/arch/arm64/configs/db845c_gki.fragment
+++ b/arch/arm64/configs/db845c_gki.fragment
@@ -12,6 +12,7 @@ CONFIG_PINCTRL_QCOM_SPMI_PMIC=m
CONFIG_PINCTRL_SDM845=m
CONFIG_POWER_RESET_QCOM_PON=m
CONFIG_SYSCON_REBOOT_MODE=m
+CONFIG_QCOM_TSENS=m
CONFIG_QCOM_WDT=m
CONFIG_PM8916_WATCHDOG=m
CONFIG_MFD_SPMI_PMIC=m
diff --git a/arch/arm64/configs/vendor/holi_GKI.config b/arch/arm64/configs/vendor/holi_GKI.config
index 7634f6b449a3..4c2a7b55c0c3 100644
--- a/arch/arm64/configs/vendor/holi_GKI.config
+++ b/arch/arm64/configs/vendor/holi_GKI.config
@@ -239,3 +239,4 @@ CONFIG_SM_GCC_BLAIR=m
CONFIG_SM_GPUCC_BLAIR=m
CONFIG_SM_DISPCC_BLAIR=m
CONFIG_SM_DEBUGCC_BLAIR=m
+CONFIG_QCOM_CX_IPEAK=m
diff --git a/arch/arm64/configs/vendor/lahaina_GKI.config b/arch/arm64/configs/vendor/lahaina_GKI.config
index 45d69f8c4c37..1d1ab64c11df 100644
--- a/arch/arm64/configs/vendor/lahaina_GKI.config
+++ b/arch/arm64/configs/vendor/lahaina_GKI.config
@@ -198,6 +198,7 @@ CONFIG_VIDEOBUF2_VMALLOC=m
CONFIG_SLIMBUS_MSM_NGD=m
CONFIG_QRTR_HAVEN=m
CONFIG_QCOM_CDSP_RM=m
+CONFIG_QCOM_SYSMON_SUBSYSTEM_STATS=m
CONFIG_QCOM_PDC=m
CONFIG_HEADER_TEST=y
CONFIG_HEADERS_INSTALL=y
diff --git a/block/elevator.c b/block/elevator.c
index 076ba7308e65..9340e2388c62 100644
--- a/block/elevator.c
+++ b/block/elevator.c
@@ -630,7 +630,10 @@ static struct elevator_type *elevator_get_default(struct request_queue *q)
{
if (q->nr_hw_queues != 1)
return NULL;
-
+#if defined(CONFIG_SDC_QTI) || defined(CONFIG_SCSI_UFSHCD_QTI)
+ if (IS_ENABLED(CONFIG_IOSCHED_BFQ))
+ return elevator_get(q, "bfq", false);
+#endif
return elevator_get(q, "mq-deadline", false);
}
diff --git a/drivers/base/core.c b/drivers/base/core.c
index d54f9df193b5..49fadbc37a85 100644
--- a/drivers/base/core.c
+++ b/drivers/base/core.c
@@ -1373,7 +1373,7 @@ static void device_links_purge(struct device *dev)
return;
mutex_lock(&wfs_lock);
- list_del(&dev->links.needs_suppliers);
+ list_del_init(&dev->links.needs_suppliers);
mutex_unlock(&wfs_lock);
/*
diff --git a/drivers/base/power/wakeup.c b/drivers/base/power/wakeup.c
index aa0ba384284a..8884c706d50d 100644
--- a/drivers/base/power/wakeup.c
+++ b/drivers/base/power/wakeup.c
@@ -925,6 +925,7 @@ void pm_system_cancel_wakeup(void)
{
atomic_dec_if_positive(&pm_abort_suspend);
}
+EXPORT_SYMBOL_GPL(pm_system_cancel_wakeup);
void pm_wakeup_clear(bool reset)
{
diff --git a/drivers/clk/qcom/clk-alpha-pll.c b/drivers/clk/qcom/clk-alpha-pll.c
index f81ef5d61313..e40f344609f8 100644
--- a/drivers/clk/qcom/clk-alpha-pll.c
+++ b/drivers/clk/qcom/clk-alpha-pll.c
@@ -276,6 +276,12 @@ EXPORT_SYMBOL_GPL(clk_alpha_pll_regs);
#define LUCID_EVO_PLL_L_VAL_MASK GENMASK(15, 0)
#define LUCID_EVO_PLL_CAL_L_VAL_MASK GENMASK(31, 16)
+/*
+ * The lucid_5lpe CPU PLL on SDX targets overloaded this field. Reading it
+ * returns PCAL_DONE and writing it asserts the latch.
+ */
+#define LUCID_5LPE_SDX_CPU_LATCH_INPUT LUCID_5LPE_PCAL_DONE
+
/* ZONDA PLL specific offsets */
#define ZONDA_PLL_OUT_MASK 0xF
#define ZONDA_STAY_IN_CFA BIT(16)
@@ -3190,6 +3196,61 @@ static int alpha_pll_lucid_5lpe_set_rate(struct clk_hw *hw, unsigned long rate,
return 0;
}
+static int alpha_pll_lucid_5lpe_sdx_cpu_set_rate(struct clk_hw *hw,
+ unsigned long rate,
+ unsigned long prate)
+{
+ struct clk_alpha_pll *pll = to_clk_alpha_pll(hw);
+ unsigned long rrate;
+ u32 regval, l;
+ u64 a;
+ int ret;
+
+ rrate = alpha_pll_round_rate(rate, prate, &l, &a, ALPHA_REG_16BIT_WIDTH);
+
+ /*
+ * Due to a limited number of bits for fractional rate programming, the
+ * rounded up rate could be marginally higher than the requested rate.
+ */
+ if (rrate > (rate + PLL_OUT_RATE_MARGIN) || rrate < rate) {
+ pr_err("Call set rate on the PLL with rounded rates!\n");
+ return -EINVAL;
+ }
+
+ regmap_write(pll->clkr.regmap, PLL_L_VAL(pll), l);
+ regmap_write(pll->clkr.regmap, PLL_ALPHA_VAL(pll), a);
+
+ /* Latch the PLL input */
+ ret = regmap_write_bits(pll->clkr.regmap, PLL_MODE(pll),
+ LUCID_5LPE_SDX_CPU_LATCH_INPUT,
+ LUCID_5LPE_SDX_CPU_LATCH_INPUT);
+ if (ret)
+ return ret;
+
+ /* Wait for 2 reference cycles before checking the ACK bit. */
+ udelay(1);
+ regmap_read(pll->clkr.regmap, PLL_MODE(pll), ®val);
+ if (!(regval & LUCID_5LPE_ALPHA_PLL_ACK_LATCH)) {
+ WARN_CLK(&pll->clkr.hw, 1,
+ "PLL latch failed. Output may be unstable!\n");
+ return -EINVAL;
+ }
+
+ /* Return the latch input to 0 */
+ ret = regmap_write_bits(pll->clkr.regmap, PLL_MODE(pll),
+ LUCID_5LPE_SDX_CPU_LATCH_INPUT, 0);
+ if (ret)
+ return ret;
+
+ if (clk_hw_is_enabled(hw)) {
+ ret = wait_for_pll_enable_lock(pll);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
+
static int clk_lucid_5lpe_pll_postdiv_set_rate(struct clk_hw *hw,
unsigned long rate, unsigned long parent_rate)
{
@@ -3331,6 +3392,25 @@ const struct clk_ops clk_alpha_pll_lucid_5lpe_ops = {
};
EXPORT_SYMBOL(clk_alpha_pll_lucid_5lpe_ops);
+const struct clk_ops clk_alpha_pll_lucid_5lpe_sdx_cpu_ops = {
+ .prepare = alpha_pll_lucid_5lpe_prepare,
+ .unprepare = clk_unprepare_regmap,
+ .pre_rate_change = clk_pre_change_regmap,
+ .post_rate_change = clk_post_change_regmap,
+ .enable = alpha_pll_lucid_5lpe_enable,
+ .disable = alpha_pll_lucid_5lpe_disable,
+ .is_enabled = alpha_pll_lucid_is_enabled,
+ .recalc_rate = alpha_pll_lucid_recalc_rate,
+ .round_rate = clk_alpha_pll_round_rate,
+ .set_rate = alpha_pll_lucid_5lpe_sdx_cpu_set_rate,
+ .debug_init = clk_common_debug_init,
+ .init = clk_lucid_pll_init,
+#ifdef CONFIG_COMMON_CLK_QCOM_DEBUG
+ .list_rate_vdd_level = clk_list_rate_vdd_level,
+#endif
+};
+EXPORT_SYMBOL(clk_alpha_pll_lucid_5lpe_sdx_cpu_ops);
+
const struct clk_ops clk_alpha_pll_fixed_lucid_ops = {
.prepare = clk_prepare_regmap,
.unprepare = clk_unprepare_regmap,
diff --git a/drivers/clk/qcom/clk-alpha-pll.h b/drivers/clk/qcom/clk-alpha-pll.h
index d5791e9cc4bf..d5f1ab60d6d1 100644
--- a/drivers/clk/qcom/clk-alpha-pll.h
+++ b/drivers/clk/qcom/clk-alpha-pll.h
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
- * Copyright (c) 2015-2016, 2018-2020 The Linux Foundation.
+ * Copyright (c) 2015-2016, 2018-2021 The Linux Foundation.
* All rights reserved.
*/
@@ -173,6 +173,7 @@ extern const struct clk_ops clk_alpha_pll_postdiv_zonda_ops;
extern const struct clk_ops clk_alpha_pll_zonda_5lpe_ops;
extern const struct clk_ops clk_alpha_pll_lucid_5lpe_ops;
+extern const struct clk_ops clk_alpha_pll_lucid_5lpe_sdx_cpu_ops;
extern const struct clk_ops clk_alpha_pll_fixed_lucid_5lpe_ops;
extern const struct clk_ops clk_alpha_pll_postdiv_lucid_5lpe_ops;
extern const struct clk_ops clk_alpha_pll_slew_ops;
diff --git a/drivers/clk/qcom/clk-cpu-sdxlemur.c b/drivers/clk/qcom/clk-cpu-sdxlemur.c
index 5c1e5d7f7c44..b2daf0519ccd 100644
--- a/drivers/clk/qcom/clk-cpu-sdxlemur.c
+++ b/drivers/clk/qcom/clk-cpu-sdxlemur.c
@@ -306,7 +306,7 @@ static struct clk_alpha_pll apcs_cpu_pll = {
.fw_name = "bi_tcxo_ao",
},
.num_parents = 1,
- .ops = &clk_alpha_pll_lucid_5lpe_ops,
+ .ops = &clk_alpha_pll_lucid_5lpe_sdx_cpu_ops,
},
.vdd_data = {
.vdd_class = &vdd_pll,
@@ -361,7 +361,6 @@ static struct regmap_config cpu_regmap_config = {
.reg_bits = 32,
.reg_stride = 4,
.val_bits = 32,
- .max_register = 0x3C,
.fast_io = true,
};
diff --git a/drivers/clk/qcom/debugcc-blair.c b/drivers/clk/qcom/debugcc-blair.c
index 998f0d4ffebf..0217171d265f 100644
--- a/drivers/clk/qcom/debugcc-blair.c
+++ b/drivers/clk/qcom/debugcc-blair.c
@@ -240,7 +240,7 @@ static const char *const gcc_debug_mux_parent_names[] = {
};
static int gcc_debug_mux_sels[] = {
- 0xBA, /* cpu_cc_debug_mux */
+ 0xBF, /* cpu_cc_debug_mux */
0x43, /* disp_cc_debug_mux */
0x67, /* gcc_ahb2phy_csi_clk */
0x68, /* gcc_ahb2phy_usb_clk */
@@ -349,7 +349,7 @@ static int gcc_debug_mux_sels[] = {
0x15B, /* gcc_video_venus_ctl_clk */
0x3F, /* gcc_video_xo_clk */
0xFB, /* gpu_cc_debug_mux */
- 0xA9, /* mc_cc_debug_mux */
+ 0xAE, /* mc_cc_debug_mux */
0x38, /* measure_only_gcc_camera_ahb_clk */
0x40, /* measure_only_gcc_camera_xo_clk */
0xBA, /* measure_only_gcc_cpuss_gnoc_clk */
diff --git a/drivers/clk/qcom/gdsc-regulator.c b/drivers/clk/qcom/gdsc-regulator.c
index d3794fbe283d..5cc91f0e5001 100644
--- a/drivers/clk/qcom/gdsc-regulator.c
+++ b/drivers/clk/qcom/gdsc-regulator.c
@@ -661,7 +661,10 @@ static struct regmap_config gdsc_regmap_config = {
void gdsc_debug_print_regs(struct regulator *regulator)
{
- struct gdsc *sc = rdev_get_drvdata(regulator->rdev);
+ struct regulator_dev *rdev = regulator->rdev;
+ struct gdsc *sc = rdev_get_drvdata(rdev);
+ struct regulator *reg;
+ const char *supply_name;
uint32_t regvals[3] = {0};
int ret;
@@ -670,6 +673,23 @@ void gdsc_debug_print_regs(struct regulator *regulator)
return;
}
+ ww_mutex_lock(&rdev->mutex, NULL);
+
+ if (rdev->open_count)
+ pr_info("%-32s EN\n", "Device-Supply");
+
+ list_for_each_entry(reg, &rdev->consumer_list, list) {
+ if (reg->supply_name)
+ supply_name = reg->supply_name;
+ else
+ supply_name = "(null)-(null)";
+
+ pr_info("%-32s %c\n", supply_name,
+ (reg->enable_count ? 'Y' : 'N'));
+ }
+
+ ww_mutex_unlock(&rdev->mutex);
+
ret = regmap_bulk_read(sc->regmap, REG_OFFSET, regvals,
gdsc_regmap_config.max_register ? 3 : 1);
if (ret) {
diff --git a/drivers/gpu/msm/adreno_a6xx_gmu.c b/drivers/gpu/msm/adreno_a6xx_gmu.c
index 13f8ea7e2c0e..acd6a97cb66c 100644
--- a/drivers/gpu/msm/adreno_a6xx_gmu.c
+++ b/drivers/gpu/msm/adreno_a6xx_gmu.c
@@ -2632,7 +2632,7 @@ int a6xx_gmu_probe(struct kgsl_device *device,
struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
struct a6xx_gmu_device *gmu = to_a6xx_gmu(adreno_dev);
struct resource *res;
- int ret;
+ int ret, i;
gmu->pdev = pdev;
@@ -2662,7 +2662,20 @@ int a6xx_gmu_probe(struct kgsl_device *device,
ret = devm_clk_bulk_get_all(&pdev->dev, &gmu->clks);
if (ret < 0)
return ret;
-
+ /*
+ * Voting for apb_pclk will enable power and clocks required for
+ * QDSS path to function. However, if CORESIGHT is not enabled,
+ * QDSS is essentially unusable. Hence, if QDSS cannot be used,
+ * don't vote for this clock.
+ */
+ if (!IS_ENABLED(CONFIG_CORESIGHT)) {
+ for (i = 0; i < ret; i++) {
+ if (!strcmp(gmu->clks[i].id, "apb_pclk")) {
+ gmu->clks[i].clk = NULL;
+ break;
+ }
+ }
+ }
gmu->num_clks = ret;
/* Set up GMU IOMMU and shared memory with GMU */
@@ -2935,6 +2948,8 @@ static int a6xx_boot(struct adreno_device *adreno_dev)
kgsl_pwrscale_wake(device);
set_bit(GMU_PRIV_GPU_STARTED, &gmu->flags);
+
+ device->pwrctrl.last_stat_updated = ktime_get();
device->state = KGSL_STATE_ACTIVE;
trace_kgsl_pwr_set_state(device, KGSL_STATE_ACTIVE);
@@ -3003,6 +3018,7 @@ static int a6xx_first_boot(struct adreno_device *adreno_dev)
set_bit(GMU_PRIV_FIRST_BOOT_DONE, &gmu->flags);
set_bit(GMU_PRIV_GPU_STARTED, &gmu->flags);
+ device->pwrctrl.last_stat_updated = ktime_get();
device->state = KGSL_STATE_ACTIVE;
trace_kgsl_pwr_set_state(device, KGSL_STATE_ACTIVE);
@@ -3264,6 +3280,8 @@ static void a6xx_gmu_touch_wakeup(struct adreno_device *adreno_dev)
kgsl_pwrscale_wake(device);
set_bit(GMU_PRIV_GPU_STARTED, &gmu->flags);
+
+ device->pwrctrl.last_stat_updated = ktime_get();
device->state = KGSL_STATE_ACTIVE;
trace_kgsl_pwr_set_state(device, KGSL_STATE_ACTIVE);
diff --git a/drivers/gpu/msm/adreno_a6xx_hwsched.c b/drivers/gpu/msm/adreno_a6xx_hwsched.c
index 433454a70619..4d8e7897e8cb 100644
--- a/drivers/gpu/msm/adreno_a6xx_hwsched.c
+++ b/drivers/gpu/msm/adreno_a6xx_hwsched.c
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
- * Copyright (c) 2020, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2020-2021, The Linux Foundation. All rights reserved.
*/
#include
@@ -500,6 +500,7 @@ static void a6xx_hwsched_touch_wakeup(struct adreno_device *adreno_dev)
set_bit(GMU_PRIV_GPU_STARTED, &gmu->flags);
+ device->pwrctrl.last_stat_updated = ktime_get();
device->state = KGSL_STATE_ACTIVE;
trace_kgsl_pwr_set_state(device, KGSL_STATE_ACTIVE);
@@ -541,6 +542,8 @@ static int a6xx_hwsched_boot(struct adreno_device *adreno_dev)
kgsl_pwrscale_wake(device);
set_bit(GMU_PRIV_GPU_STARTED, &gmu->flags);
+
+ device->pwrctrl.last_stat_updated = ktime_get();
device->state = KGSL_STATE_ACTIVE;
trace_kgsl_pwr_set_state(device, KGSL_STATE_ACTIVE);
@@ -589,6 +592,7 @@ static int a6xx_hwsched_first_boot(struct adreno_device *adreno_dev)
set_bit(GMU_PRIV_FIRST_BOOT_DONE, &gmu->flags);
set_bit(GMU_PRIV_GPU_STARTED, &gmu->flags);
+ device->pwrctrl.last_stat_updated = ktime_get();
device->state = KGSL_STATE_ACTIVE;
trace_kgsl_pwr_set_state(device, KGSL_STATE_ACTIVE);
diff --git a/drivers/gpu/msm/adreno_a6xx_rgmu.c b/drivers/gpu/msm/adreno_a6xx_rgmu.c
index 0778956378d7..4e82413092e9 100644
--- a/drivers/gpu/msm/adreno_a6xx_rgmu.c
+++ b/drivers/gpu/msm/adreno_a6xx_rgmu.c
@@ -896,6 +896,7 @@ static int a6xx_boot(struct adreno_device *adreno_dev)
set_bit(RGMU_PRIV_GPU_STARTED, &rgmu->flags);
+ device->pwrctrl.last_stat_updated = ktime_get();
device->state = KGSL_STATE_ACTIVE;
trace_kgsl_pwr_set_state(device, KGSL_STATE_ACTIVE);
@@ -934,6 +935,7 @@ static void a6xx_rgmu_touch_wakeup(struct adreno_device *adreno_dev)
set_bit(RGMU_PRIV_GPU_STARTED, &rgmu->flags);
+ device->pwrctrl.last_stat_updated = ktime_get();
device->state = KGSL_STATE_ACTIVE;
trace_kgsl_pwr_set_state(device, KGSL_STATE_ACTIVE);
@@ -1002,6 +1004,7 @@ static int a6xx_first_boot(struct adreno_device *adreno_dev)
set_bit(RGMU_PRIV_FIRST_BOOT_DONE, &rgmu->flags);
set_bit(RGMU_PRIV_GPU_STARTED, &rgmu->flags);
+ device->pwrctrl.last_stat_updated = ktime_get();
device->state = KGSL_STATE_ACTIVE;
trace_kgsl_pwr_set_state(device, KGSL_STATE_ACTIVE);
@@ -1248,12 +1251,25 @@ static int a6xx_rgmu_regulators_probe(struct a6xx_rgmu_device *rgmu)
static int a6xx_rgmu_clocks_probe(struct a6xx_rgmu_device *rgmu,
struct device_node *node)
{
- int ret;
+ int ret, i;
ret = devm_clk_bulk_get_all(&rgmu->pdev->dev, &rgmu->clks);
if (ret < 0)
return ret;
-
+ /*
+ * Voting for apb_pclk will enable power and clocks required for
+ * QDSS path to function. However, if CORESIGHT is not enabled,
+ * QDSS is essentially unusable. Hence, if QDSS cannot be used,
+ * don't vote for this clock.
+ */
+ if (!IS_ENABLED(CONFIG_CORESIGHT)) {
+ for (i = 0; i < ret; i++) {
+ if (!strcmp(rgmu->clks[i].id, "apb_pclk")) {
+ rgmu->clks[i].clk = NULL;
+ break;
+ }
+ }
+ }
rgmu->num_clks = ret;
rgmu->gpu_clk = kgsl_of_clk_by_name(rgmu->clks, ret, "core");
diff --git a/drivers/gpu/msm/adreno_dispatch.c b/drivers/gpu/msm/adreno_dispatch.c
index 7ae90d71130d..5177e74acc10 100644
--- a/drivers/gpu/msm/adreno_dispatch.c
+++ b/drivers/gpu/msm/adreno_dispatch.c
@@ -304,6 +304,9 @@ static void _retire_timestamp(struct kgsl_drawobj *drawobj)
context->id, drawobj->timestamp,
!!(drawobj->flags & KGSL_DRAWOBJ_END_OF_FRAME));
+ if (drawobj->flags & KGSL_DRAWOBJ_END_OF_FRAME)
+ atomic64_inc(&context->proc_priv->frame_count);
+
/*
* For A3xx we still get the rptr from the CP_RB_RPTR instead of
* rptr scratch out address. At this point GPU clocks turned off.
@@ -2355,6 +2358,9 @@ static void retire_cmdobj(struct adreno_device *adreno_dev,
context->id, drawobj->timestamp,
!!(drawobj->flags & KGSL_DRAWOBJ_END_OF_FRAME));
+ if (drawobj->flags & KGSL_DRAWOBJ_END_OF_FRAME)
+ atomic64_inc(&context->proc_priv->frame_count);
+
/*
* For A3xx we still get the rptr from the CP_RB_RPTR instead of
* rptr scratch out address. At this point GPU clocks turned off.
diff --git a/drivers/gpu/msm/kgsl.c b/drivers/gpu/msm/kgsl.c
index 1b344cd066db..fac02e36999b 100644
--- a/drivers/gpu/msm/kgsl.c
+++ b/drivers/gpu/msm/kgsl.c
@@ -12,6 +12,7 @@
#include
#include
#include
+#include
#include
#include
#include
@@ -335,6 +336,27 @@ static void kgsl_destroy_ion(struct kgsl_dma_buf_meta *meta)
}
#endif
+static void kgsl_process_sub_stats(struct kgsl_process_private *priv,
+ unsigned int type, uint64_t size)
+{
+#ifdef CONFIG_MM_STAT_UNRECLAIMABLE_PAGES
+ struct task_struct *task;
+ struct mm_struct *mm;
+
+ task = get_pid_task(priv->pid, PIDTYPE_PID);
+ if (task) {
+ mm = get_task_mm(task);
+ if (mm) {
+ add_mm_counter(mm, MM_UNRECLAIMABLE,
+ -(size >> PAGE_SHIFT));
+ mmput(mm);
+ }
+ put_task_struct(task);
+ }
+#endif
+ atomic64_sub(size, &priv->stats[type].cur);
+}
+
void
kgsl_mem_entry_destroy(struct kref *kref)
{
@@ -349,7 +371,7 @@ kgsl_mem_entry_destroy(struct kref *kref)
/* pull out the memtype before the flags get cleared */
memtype = kgsl_memdesc_usermem_type(&entry->memdesc);
- atomic64_sub(entry->memdesc.size, &entry->priv->stats[memtype].cur);
+ kgsl_process_sub_stats(entry->priv, memtype, entry->memdesc.size);
/* Detach from process list */
kgsl_mem_entry_detach_process(entry);
@@ -1043,6 +1065,24 @@ done:
return private;
}
+int kgsl_gpu_frame_count(pid_t pid, u64 *frame_count)
+{
+ struct kgsl_process_private *p;
+
+ if (!frame_count)
+ return -EINVAL;
+
+ p = kgsl_process_private_find(pid);
+ if (!p)
+ return -ENOENT;
+
+ *frame_count = atomic64_read(&p->frame_count);
+ kgsl_process_private_put(p);
+
+ return 0;
+}
+EXPORT_SYMBOL(kgsl_gpu_frame_count);
+
static int kgsl_close_device(struct kgsl_device *device)
{
int result = 0;
@@ -2753,10 +2793,12 @@ static void kgsl_process_add_stats(struct kgsl_process_private *priv,
if (ret > priv->stats[type].max)
priv->stats[type].max = ret;
+
+#ifdef CONFIG_MM_STAT_UNRECLAIMABLE_PAGES
+ add_mm_counter(current->mm, MM_UNRECLAIMABLE, (size >> PAGE_SHIFT));
+#endif
}
-
-
long kgsl_ioctl_gpuobj_import(struct kgsl_device_private *dev_priv,
unsigned int cmd, void *data)
{
diff --git a/drivers/gpu/msm/kgsl.h b/drivers/gpu/msm/kgsl.h
index 9e4bf99e7163..fc2cb005722c 100644
--- a/drivers/gpu/msm/kgsl.h
+++ b/drivers/gpu/msm/kgsl.h
@@ -5,12 +5,12 @@
#ifndef __KGSL_H
#define __KGSL_H
+#include
#include
#include
#include
#include
#include
-#include
#include
#include "kgsl_gmu_core.h"
diff --git a/drivers/gpu/msm/kgsl_compat.h b/drivers/gpu/msm/kgsl_compat.h
index a62c3b40d798..85e1871de6ac 100644
--- a/drivers/gpu/msm/kgsl_compat.h
+++ b/drivers/gpu/msm/kgsl_compat.h
@@ -1,12 +1,12 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
- * Copyright (c) 2013-2017,2019 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2013-2017,2019,2021 The Linux Foundation. All rights reserved.
*/
#ifndef __KGSL_COMPAT_H
#define __KGSL_COMPAT_H
+#include
#include
-#include
#ifdef CONFIG_COMPAT
diff --git a/drivers/gpu/msm/kgsl_device.h b/drivers/gpu/msm/kgsl_device.h
index e3271ccbe327..3d3cfdab5128 100644
--- a/drivers/gpu/msm/kgsl_device.h
+++ b/drivers/gpu/msm/kgsl_device.h
@@ -437,6 +437,7 @@ struct kgsl_context {
* @fd_count: Counter for the number of FDs for this process
* @ctxt_count: Count for the number of contexts for this process
* @ctxt_count_lock: Spinlock to protect ctxt_count
+ * @frame_count: Count for the number of frames processed
*/
struct kgsl_process_private {
unsigned long priv;
@@ -460,6 +461,7 @@ struct kgsl_process_private {
int fd_count;
atomic_t ctxt_count;
spinlock_t ctxt_count_lock;
+ atomic64_t frame_count;
};
/**
diff --git a/drivers/gpu/msm/kgsl_iommu.c b/drivers/gpu/msm/kgsl_iommu.c
index 38f8100e5fc2..945f2a3838e0 100644
--- a/drivers/gpu/msm/kgsl_iommu.c
+++ b/drivers/gpu/msm/kgsl_iommu.c
@@ -2511,9 +2511,10 @@ int kgsl_iommu_probe(struct kgsl_device *device)
*/
kgsl_iommu_map_globals(mmu, mmu->defaultpagetable);
kgsl_iommu_map_globals(mmu, mmu->lpac_pagetable);
-
- device->qdss_desc = kgsl_allocate_global_fixed(device,
- "qcom,gpu-qdss-stm", "gpu-qdss");
+ /* QDSS is supported only when CORESIGHT is enabled */
+ if (IS_ENABLED(CONFIG_CORESIGHT))
+ device->qdss_desc = kgsl_allocate_global_fixed(device,
+ "qcom,gpu-qdss-stm", "gpu-qdss");
device->qtimer_desc = kgsl_allocate_global_fixed(device,
"qcom,gpu-timer", "gpu-qtimer");
diff --git a/drivers/gpu/msm/kgsl_pool.c b/drivers/gpu/msm/kgsl_pool.c
index cace5bb18027..d633aed832de 100644
--- a/drivers/gpu/msm/kgsl_pool.c
+++ b/drivers/gpu/msm/kgsl_pool.c
@@ -450,6 +450,11 @@ done:
pcount++;
}
+#ifdef CONFIG_MM_STAT_UNRECLAIMABLE_PAGES
+ mod_node_page_state(page_pgdat(page), NR_UNRECLAIMABLE_PAGES,
+ (1 << order));
+#endif
+
return pcount;
eagain:
@@ -521,6 +526,11 @@ static void kgsl_pool_free_page(struct page *page)
page_order = compound_order(page);
+#ifdef CONFIG_MM_STAT_UNRECLAIMABLE_PAGES
+ mod_node_page_state(page_pgdat(page), NR_UNRECLAIMABLE_PAGES,
+ -(1 << page_order));
+#endif
+
if (!kgsl_pool_max_pages ||
(kgsl_pool_size_total() < kgsl_pool_max_pages)) {
pool = _kgsl_get_pool_from_order(page_order);
diff --git a/drivers/gpu/msm/kgsl_pwrctrl.c b/drivers/gpu/msm/kgsl_pwrctrl.c
index 2831803a1817..7003d76d933f 100644
--- a/drivers/gpu/msm/kgsl_pwrctrl.c
+++ b/drivers/gpu/msm/kgsl_pwrctrl.c
@@ -4,6 +4,7 @@
*/
#include
+#include
#include
#include
#include
@@ -1426,6 +1427,9 @@ static int _get_clocks(struct kgsl_device *device)
for (i = 0; i < KGSL_MAX_CLKS; i++) {
if (pwr->grp_clks[i] || strcmp(clocks[i], name))
continue;
+ /* apb_pclk should only be enabled if CORESIGHT is enabled */
+ if (!strcmp(name, "apb_pclk") && !IS_ENABLED(CONFIG_CORESIGHT))
+ continue;
pwr->grp_clks[i] = devm_clk_get(dev, name);
@@ -1875,6 +1879,7 @@ static int _wake(struct kgsl_device *device)
kgsl_pwrctrl_clk(device, KGSL_PWRFLAGS_ON, KGSL_STATE_ACTIVE);
device->ftbl->deassert_gbif_halt(device);
+ pwr->last_stat_updated = ktime_get();
/*
* No need to turn on/off irq here as it no longer affects
* power collapse
@@ -2255,3 +2260,42 @@ int kgsl_pwrctrl_set_default_gpu_pwrlevel(struct kgsl_device *device)
/* Request adjusted DCVS level */
return device->ftbl->gpu_clock_set(device, pwr->active_pwrlevel);
}
+
+int kgsl_gpu_num_freqs(void)
+{
+ struct kgsl_device *device = kgsl_get_device(0);
+
+ if (!device)
+ return -ENODEV;
+
+ return device->pwrctrl.num_pwrlevels;
+}
+EXPORT_SYMBOL(kgsl_gpu_num_freqs);
+
+int kgsl_gpu_stat(struct kgsl_gpu_freq_stat *stats, u32 numfreq)
+{
+ struct kgsl_device *device = kgsl_get_device(0);
+ struct kgsl_pwrctrl *pwr;
+ int i;
+
+ if (!device)
+ return -ENODEV;
+
+ pwr = &device->pwrctrl;
+
+ if (!stats || (numfreq < pwr->num_pwrlevels))
+ return -EINVAL;
+
+ mutex_lock(&device->mutex);
+ kgsl_pwrscale_update_stats(device);
+
+ for (i = 0; i < pwr->num_pwrlevels; i++) {
+ stats[i].freq = pwr->pwrlevels[i].gpu_freq;
+ stats[i].active_time = pwr->clock_times[i];
+ stats[i].idle_time = pwr->time_in_pwrlevel[i] - pwr->clock_times[i];
+ }
+ mutex_unlock(&device->mutex);
+
+ return 0;
+}
+EXPORT_SYMBOL(kgsl_gpu_stat);
diff --git a/drivers/gpu/msm/kgsl_pwrctrl.h b/drivers/gpu/msm/kgsl_pwrctrl.h
index 9b040126c57b..2786c8745bb1 100644
--- a/drivers/gpu/msm/kgsl_pwrctrl.h
+++ b/drivers/gpu/msm/kgsl_pwrctrl.h
@@ -175,6 +175,10 @@ struct kgsl_pwrctrl {
u32 minbw_timeout;
/** @ddr_qos_devfreq: Devfreq device for setting DDR qos policy */
struct devfreq *ddr_qos_devfreq;
+ /** @time_in_pwrlevel: Each pwrlevel active duration in usec */
+ u64 time_in_pwrlevel[KGSL_MAX_PWRLEVELS];
+ /** @last_stat_updated: The last time stats were updated */
+ ktime_t last_stat_updated;
};
int kgsl_pwrctrl_init(struct kgsl_device *device);
diff --git a/drivers/gpu/msm/kgsl_pwrscale.c b/drivers/gpu/msm/kgsl_pwrscale.c
index 870f090c769e..45d6e99a66cb 100644
--- a/drivers/gpu/msm/kgsl_pwrscale.c
+++ b/drivers/gpu/msm/kgsl_pwrscale.c
@@ -122,6 +122,7 @@ void kgsl_pwrscale_update_stats(struct kgsl_device *device)
if (device->state == KGSL_STATE_ACTIVE) {
struct kgsl_power_stats stats;
+ ktime_t cur_time = ktime_get();
device->ftbl->power_stats(device, &stats);
device->pwrscale.accum_stats.busy_time += stats.busy_time;
@@ -129,6 +130,9 @@ void kgsl_pwrscale_update_stats(struct kgsl_device *device)
device->pwrscale.accum_stats.ram_wait += stats.ram_wait;
pwrctrl->clock_times[pwrctrl->active_pwrlevel] +=
stats.busy_time;
+ pwrctrl->time_in_pwrlevel[pwrctrl->active_pwrlevel] +=
+ ktime_us_delta(cur_time, pwrctrl->last_stat_updated);
+ pwrctrl->last_stat_updated = cur_time;
}
}
diff --git a/drivers/gpu/msm/kgsl_sharedmem.c b/drivers/gpu/msm/kgsl_sharedmem.c
index 3343ce49fc89..8bb7bd4aadc7 100644
--- a/drivers/gpu/msm/kgsl_sharedmem.c
+++ b/drivers/gpu/msm/kgsl_sharedmem.c
@@ -952,6 +952,11 @@ static void kgsl_contiguous_free(struct kgsl_memdesc *memdesc)
atomic_long_sub(memdesc->size, &kgsl_driver.stats.coherent);
+#ifdef CONFIG_MM_STAT_UNRECLAIMABLE_PAGES
+ mod_node_page_state(page_pgdat(phys_to_page(memdesc->physaddr)),
+ NR_UNRECLAIMABLE_PAGES, -(memdesc->size >> PAGE_SHIFT));
+#endif
+
_kgsl_contiguous_free(memdesc);
}
@@ -961,6 +966,7 @@ static void kgsl_free_secure_system_pages(struct kgsl_memdesc *memdesc)
int i;
struct scatterlist *sg;
int ret = unlock_sgt(memdesc->sgt);
+ int order = get_order(PAGE_SIZE);
if (ret) {
/*
@@ -979,7 +985,11 @@ static void kgsl_free_secure_system_pages(struct kgsl_memdesc *memdesc)
for_each_sg(memdesc->sgt->sgl, sg, memdesc->sgt->nents, i) {
struct page *page = sg_page(sg);
- __free_pages(page, get_order(PAGE_SIZE));
+ __free_pages(page, order);
+#ifdef CONFIG_MM_STAT_UNRECLAIMABLE_PAGES
+ mod_node_page_state(page_pgdat(page), NR_UNRECLAIMABLE_PAGES,
+ -(1 << order));
+#endif
}
sg_free_table(memdesc->sgt);
@@ -1032,15 +1042,20 @@ static void kgsl_free_pool_pages(struct kgsl_memdesc *memdesc)
static void kgsl_free_system_pages(struct kgsl_memdesc *memdesc)
{
- int i;
+ int i, order = get_order(PAGE_SIZE);
kgsl_paged_unmap_kernel(memdesc);
WARN_ON(memdesc->hostptr);
atomic_long_sub(memdesc->size, &kgsl_driver.stats.page_alloc);
- for (i = 0; i < memdesc->page_count; i++)
- __free_pages(memdesc->pages[i], get_order(PAGE_SIZE));
+ for (i = 0; i < memdesc->page_count; i++) {
+ __free_pages(memdesc->pages[i], order);
+#ifdef CONFIG_MM_STAT_UNRECLAIMABLE_PAGES
+ mod_node_page_state(page_pgdat(memdesc->pages[i]),
+ NR_UNRECLAIMABLE_PAGES, -(1 << order));
+#endif
+ }
memdesc->page_count = 0;
kvfree(memdesc->pages);
@@ -1087,6 +1102,7 @@ static int kgsl_system_alloc_pages(u64 size, struct page ***pages,
struct scatterlist sg;
struct page **local;
int i, npages = size >> PAGE_SHIFT;
+ int order = get_order(PAGE_SIZE);
local = kvcalloc(npages, sizeof(*pages), GFP_KERNEL);
if (!local)
@@ -1098,8 +1114,13 @@ static int kgsl_system_alloc_pages(u64 size, struct page ***pages,
local[i] = alloc_pages(gfp, get_order(PAGE_SIZE));
if (!local[i]) {
- for (i = i - 1; i >= 0; i--)
- __free_pages(local[i], get_order(PAGE_SIZE));
+ for (i = i - 1; i >= 0; i--) {
+#ifdef CONFIG_MM_STAT_UNRECLAIMABLE_PAGES
+ mod_node_page_state(page_pgdat(local[i]),
+ NR_UNRECLAIMABLE_PAGES, -(1 << order));
+#endif
+ __free_pages(local[i], order);
+ }
kvfree(local);
return -ENOMEM;
}
@@ -1110,6 +1131,10 @@ static int kgsl_system_alloc_pages(u64 size, struct page ***pages,
sg_dma_address(&sg) = page_to_phys(local[i]);
dma_sync_sg_for_device(dev, &sg, 1, DMA_BIDIRECTIONAL);
+#ifdef CONFIG_MM_STAT_UNRECLAIMABLE_PAGES
+ mod_node_page_state(page_pgdat(local[i]), NR_UNRECLAIMABLE_PAGES,
+ (1 << order));
+#endif
}
*pages = local;
@@ -1256,9 +1281,14 @@ static int kgsl_alloc_contiguous(struct kgsl_device *device,
memdesc->ops = &kgsl_contiguous_ops;
ret = _kgsl_alloc_contiguous(&device->pdev->dev, memdesc, size, 0);
- if (!ret)
+ if (!ret) {
KGSL_STATS_ADD(size, &kgsl_driver.stats.coherent,
&kgsl_driver.stats.coherent_max);
+#ifdef CONFIG_MM_STAT_UNRECLAIMABLE_PAGES
+ mod_node_page_state(page_pgdat(phys_to_page(memdesc->physaddr)),
+ NR_UNRECLAIMABLE_PAGES, (size >> PAGE_SHIFT));
+#endif
+ }
return ret;
}
diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c
index d2ecc9c45255..263eca119ff0 100644
--- a/drivers/hid/hid-core.c
+++ b/drivers/hid/hid-core.c
@@ -90,7 +90,7 @@ EXPORT_SYMBOL_GPL(hid_register_report);
* Register a new field for this report.
*/
-static struct hid_field *hid_register_field(struct hid_report *report, unsigned usages, unsigned values)
+static struct hid_field *hid_register_field(struct hid_report *report, unsigned usages)
{
struct hid_field *field;
@@ -101,7 +101,7 @@ static struct hid_field *hid_register_field(struct hid_report *report, unsigned
field = kzalloc((sizeof(struct hid_field) +
usages * sizeof(struct hid_usage) +
- values * sizeof(unsigned)), GFP_KERNEL);
+ usages * sizeof(unsigned)), GFP_KERNEL);
if (!field)
return NULL;
@@ -300,7 +300,7 @@ static int hid_add_field(struct hid_parser *parser, unsigned report_type, unsign
usages = max_t(unsigned, parser->local.usage_index,
parser->global.report_count);
- field = hid_register_field(report, usages, parser->global.report_count);
+ field = hid_register_field(report, usages);
if (!field)
return 0;
diff --git a/drivers/input/misc/qcom-hv-haptics.c b/drivers/input/misc/qcom-hv-haptics.c
index f72e47b70426..734af9d8adb9 100644
--- a/drivers/input/misc/qcom-hv-haptics.c
+++ b/drivers/input/misc/qcom-hv-haptics.c
@@ -16,6 +16,7 @@
#include
#include
#include
+#include
#include
#include
#include
@@ -173,10 +174,20 @@
#define CAL_RC_CLK_AUTO_VAL 1
#define CAL_RC_CLK_MANUAL_VAL 2
+/* These registers are only applicable for PM5100 */
+#define HAP_CFG_HPWR_INTF_CTL_REG 0x80
+#define INTF_CTL_MASK GENMASK(1, 0)
+#define INTF_CTL_BOB 1
+#define INTF_CTL_BHARGER 2
+
+#define HAP_CFG_VHPWR_REG 0x84
+#define VHPWR_STEP_MV 32
+
/* version register definitions for HAPTICS_PATTERN module */
#define HAP_PTN_REVISION2_REG 0x01
#define HAP_PTN_V1 0x1
#define HAP_PTN_V2 0x2
+#define HAP_PTN_V3 0x3
/* status register definition for HAPTICS_PATTERN module */
#define HAP_PTN_FIFO_READY_STS_REG 0x08
@@ -267,10 +278,6 @@
#define F_LRA_VARIATION_HZ 5
#define NON_HBOOST_MAX_VMAX_MV 4000
-#define MAX_FIFO_SAMPLES(chip) \
- ((chip)->ptn_revision == HAP_PTN_V1 ? 104 : 640)
-#define FIFO_EMPTY_THRESHOLD(chip) \
- ((chip)->ptn_revision == HAP_PTN_V1 ? 48 : 280)
#define is_between(val, min, max) \
(((min) <= (max)) && ((min) <= (val)) && ((val) <= (max)))
#define HAP_BOOST_CLAMP_5V_REG_OFFSET(chip) \
@@ -346,6 +353,11 @@ enum custom_effect_param {
CUSTOM_DATA_LEN,
};
+enum pmic_type {
+ PM8350B,
+ PM5100,
+};
+
static const char * const src_str[] = {
"FIFO",
"DIRECT_PLAY",
@@ -495,7 +507,9 @@ struct haptics_chip {
u32 hbst_addr_base;
u8 cfg_revision;
u8 ptn_revision;
+ u8 hpwr_intf_ctl;
u16 hbst_revision;
+ enum pmic_type pmic_type;
bool fifo_empty_irq_en;
bool swr_slave_enabled;
bool clamp_at_5v;
@@ -507,6 +521,86 @@ struct haptics_reg_info {
u8 val;
};
+static inline int get_max_fifo_samples(struct haptics_chip *chip)
+{
+ int val = 0;
+
+ switch (chip->ptn_revision) {
+ case HAP_PTN_V1:
+ val = 104;
+ break;
+ case HAP_PTN_V2:
+ val = 640;
+ break;
+ case HAP_PTN_V3:
+ val = 1024;
+ break;
+ default:
+ pr_err("Invalid pattern revision\n");
+ break;
+ }
+
+ return val;
+}
+
+static int get_fifo_empty_threshold(struct haptics_chip *chip)
+{
+ int val = 0;
+
+ switch (chip->ptn_revision) {
+ case HAP_PTN_V1:
+ val = 48;
+ break;
+ case HAP_PTN_V2:
+ val = 280;
+ break;
+ case HAP_PTN_V3:
+ val = 288;
+ break;
+ default:
+ pr_err("Invalid pattern revision\n");
+ break;
+ }
+
+ return val;
+}
+
+static int get_fifo_threshold_per_bit(struct haptics_chip *chip)
+{
+ int val = -EINVAL;
+
+ switch (chip->ptn_revision) {
+ case HAP_PTN_V1:
+ val = 4;
+ break;
+ case HAP_PTN_V2:
+ val = 40;
+ break;
+ case HAP_PTN_V3:
+ val = 32;
+ break;
+ default:
+ pr_err("Invalid pattern revision\n");
+ break;
+ }
+
+ return val;
+}
+
+static bool is_haptics_external_powered(struct haptics_chip *chip)
+{
+ /* SW based explicit vote */
+ if (chip->hpwr_vreg)
+ return true;
+
+ /* Implicit voting by HW */
+ if (chip->pmic_type == PM5100)
+ return true;
+
+ /* Powered by HBOOST */
+ return false;
+}
+
static int haptics_read(struct haptics_chip *chip,
u16 base, u8 offset, u8 *val, u32 length)
{
@@ -890,7 +984,7 @@ static int haptics_get_closeloop_lra_period_v2(
rc_clk_cal = ((val[0] & CAL_RC_CLK_MASK) >> CAL_RC_CLK_SHIFT);
/* read auto resonance calibration result */
- if (in_boot) {
+ if (in_boot && (chip->pmic_type == PM8350B)) {
if (chip->hap_cfg_nvmem == NULL) {
dev_dbg(chip->dev, "nvmem device for hap_cfg is not defined\n");
return -EINVAL;
@@ -1164,6 +1258,9 @@ static int haptics_boost_vreg_enable(struct haptics_chip *chip, bool en)
int rc;
u8 val;
+ if (is_haptics_external_powered(chip))
+ return 0;
+
if (chip->hap_cfg_nvmem == NULL) {
dev_dbg(chip->dev, "nvmem device for hap_cfg is not defined\n");
return 0;
@@ -1208,6 +1305,9 @@ static bool is_boost_vreg_enabled_in_open_loop(struct haptics_chip *chip)
int rc;
u8 val;
+ if (is_haptics_external_powered(chip))
+ return false;
+
rc = haptics_read(chip, chip->hbst_addr_base,
HAP_BOOST_HW_CTRL_FOLLOW_REG, &val, 1);
if (!rc && !(val & FOLLOW_HW_EN_BIT)) {
@@ -1229,6 +1329,8 @@ static int haptics_wait_hboost_ready(struct haptics_chip *chip)
int i, rc;
u8 val;
+ if (is_haptics_external_powered(chip))
+ return 0;
/*
* Wait ~20ms until hBoost is ready, otherwise
* bail out and return -EBUSY
@@ -1325,7 +1427,7 @@ static int haptics_open_loop_drive_config(struct haptics_chip *chip, bool en)
u8 val;
if ((is_boost_vreg_enabled_in_open_loop(chip) ||
- chip->hpwr_vreg != NULL) && en) {
+ is_haptics_external_powered(chip)) && en) {
/* Force VREG_RDY */
rc = haptics_masked_write(chip, chip->cfg_addr_base,
HAP_CFG_VSET_CFG_REG, FORCE_VREG_RDY_BIT,
@@ -1357,7 +1459,7 @@ static int haptics_open_loop_drive_config(struct haptics_chip *chip, bool en)
dev_dbg(chip->dev, "Toggle CAL_EN in open-loop-VREG playing\n");
}
- } else if (chip->hpwr_vreg == NULL) {
+ } else if (!is_haptics_external_powered(chip)) {
rc = haptics_masked_write(chip, chip->cfg_addr_base,
HAP_CFG_VSET_CFG_REG,
FORCE_VREG_RDY_BIT, 0);
@@ -1619,16 +1721,16 @@ static int haptics_get_available_fifo_memory(struct haptics_chip *chip)
if (rc < 0)
return rc;
- if (fill > MAX_FIFO_SAMPLES(chip)) {
+ if (fill > get_max_fifo_samples(chip)) {
dev_err(chip->dev, "Filled FIFO number %d exceed the max %d\n",
- fill, MAX_FIFO_SAMPLES(chip));
+ fill, get_max_fifo_samples(chip));
return -EINVAL;
- } else if (fill == MAX_FIFO_SAMPLES(chip)) {
+ } else if (fill == get_max_fifo_samples(chip)) {
dev_err(chip->dev, "no FIFO space available\n");
return -EBUSY;
}
- available = MAX_FIFO_SAMPLES(chip) - fill;
+ available = get_max_fifo_samples(chip) - fill;
return available;
}
@@ -1717,12 +1819,16 @@ static int haptics_set_fifo_empty_threshold(struct haptics_chip *chip,
u8 reg, thresh_per_bit;
int rc;
+ rc = get_fifo_threshold_per_bit(chip);
+ if (rc < 0)
+ return rc;
+
+ thresh_per_bit = rc;
+
reg = (chip->ptn_revision == HAP_PTN_V1) ?
HAP_PTN_V1_FIFO_EMPTY_CFG_REG : HAP_PTN_V2_FIFO_EMPTY_CFG_REG;
- thresh_per_bit = (chip->ptn_revision == HAP_PTN_V1) ?
- HAP_PTN_V1_FIFO_THRESH_LSB : HAP_PTN_V2_FIFO_THRESH_LSB;
- rc = haptics_masked_write(chip, chip->ptn_addr_base,
- reg, EMPTY_THRESH_MASK, thresh / thresh_per_bit);
+ rc = haptics_masked_write(chip, chip->ptn_addr_base, reg,
+ EMPTY_THRESH_MASK, (thresh / thresh_per_bit));
if (rc < 0)
dev_err(chip->dev, "Set FIFO empty threshold failed, rc=%d\n",
rc);
@@ -1782,7 +1888,7 @@ static int haptics_set_fifo(struct haptics_chip *chip, struct fifo_cfg *fifo)
if (chip->ptn_revision == HAP_PTN_V1 &&
fifo->period_per_s > F_8KHZ &&
- fifo->num_s > MAX_FIFO_SAMPLES(chip)) {
+ fifo->num_s > get_max_fifo_samples(chip)) {
dev_err(chip->dev, "PM8350B v1 doesn't support playing long FIFO pattern higher than 8 KHz play rate\n");
return -EINVAL;
}
@@ -1808,7 +1914,7 @@ static int haptics_set_fifo(struct haptics_chip *chip, struct fifo_cfg *fifo)
* more than MAX_FIFO_SAMPLES samples, the rest will be
* written if any FIFO memory is available after playing.
*/
- num = min_t(u32, fifo->num_s, MAX_FIFO_SAMPLES(chip));
+ num = min_t(u32, fifo->num_s, get_max_fifo_samples(chip));
available = haptics_get_available_fifo_memory(chip);
if (available < 0)
return available;
@@ -1861,7 +1967,7 @@ static int haptics_load_constant_effect(struct haptics_chip *chip, u8 amplitude)
play->effect = NULL;
/* Fix Vmax to (hpwr_vreg_mv - hdrm_mv) in non-HBOOST regulator case */
- if (chip->hpwr_vreg) {
+ if (is_haptics_external_powered(chip)) {
rc = haptics_get_vmax_headroom_mv(chip, &hdrm_mv);
if (rc < 0)
goto unlock;
@@ -2199,7 +2305,7 @@ static u8 get_direct_play_max_amplitude(struct haptics_chip *chip)
u32 amplitude = DIRECT_PLAY_MAX_AMPLITUDE, hdrm_mv;
int rc;
- if (chip->hpwr_vreg) {
+ if (is_haptics_external_powered(chip)) {
rc = haptics_get_vmax_headroom_mv(chip, &hdrm_mv);
if (rc < 0)
return 0;
@@ -2477,12 +2583,15 @@ static int haptics_hw_init(struct haptics_chip *chip)
if (rc < 0)
return rc;
- rc = haptics_read(chip, chip->hbst_addr_base,
- HAP_BOOST_CLAMP_5V_REG_OFFSET(chip), val, 1);
- if (rc < 0)
- return rc;
+ if (!is_haptics_external_powered(chip)) {
+ rc = haptics_read(chip, chip->hbst_addr_base,
+ HAP_BOOST_CLAMP_5V_REG_OFFSET(chip), val, 1);
+ if (rc < 0)
+ return rc;
+
+ chip->clamp_at_5v = val[0] & CLAMP_5V_BIT;
+ }
- chip->clamp_at_5v = val[0] & CLAMP_5V_BIT;
/* Config VMAX */
rc = haptics_set_vmax_mv(chip, config->vmax_mv);
if (rc < 0)
@@ -2506,8 +2615,29 @@ static int haptics_hw_init(struct haptics_chip *chip)
if (rc < 0)
return rc;
- /* Force VREG_RDY if non-HBoost is used for powering haptics */
- if (chip->hpwr_vreg) {
+ if ((chip->pmic_type == PM5100) && !chip->hpwr_vreg) {
+ /* Indicates if HPWR is BOB or Bharger */
+ rc = haptics_read(chip, chip->cfg_addr_base,
+ HAP_CFG_HPWR_INTF_CTL_REG, val, 1);
+ if (rc < 0)
+ return rc;
+
+ chip->hpwr_intf_ctl = val[0] & INTF_CTL_MASK;
+
+ /* Read HPWR voltage to adjust the VMAX */
+ if (chip->hpwr_voltage_mv == 0 &&
+ chip->hpwr_intf_ctl == INTF_CTL_BOB) {
+ rc = haptics_read(chip, chip->cfg_addr_base,
+ HAP_CFG_VHPWR_REG, val, 1);
+ if (rc < 0)
+ return rc;
+
+ chip->hpwr_voltage_mv = val[0] * VHPWR_STEP_MV;
+ }
+ }
+
+ if (is_haptics_external_powered(chip)) {
+ /* Force VREG_RDY if non-HBoost is used for powering haptics */
rc = haptics_masked_write(chip, chip->cfg_addr_base,
HAP_CFG_VSET_CFG_REG, FORCE_VREG_RDY_BIT,
FORCE_VREG_RDY_BIT);
@@ -2597,9 +2727,9 @@ static irqreturn_t fifo_empty_irq_handler(int irq, void *data)
* memory, defer the stop into erase() function.
*/
num = haptics_get_available_fifo_memory(chip);
- if (num != MAX_FIFO_SAMPLES(chip)) {
+ if (num != get_max_fifo_samples(chip)) {
dev_dbg(chip->dev, "%d FIFO samples still in playing\n",
- MAX_FIFO_SAMPLES(chip) - num);
+ get_max_fifo_samples(chip) - num);
goto unlock;
}
@@ -3686,14 +3816,21 @@ static int haptics_get_revision(struct haptics_chip *chip)
return rc;
chip->ptn_revision = val[0];
- rc = haptics_read(chip, chip->hbst_addr_base,
- HAP_BOOST_REVISION1, val, 2);
- if (rc < 0)
- return rc;
- chip->hbst_revision = (val[1] << 8) | val[0];
- dev_dbg(chip->dev, "haptics revision: HAP_CFG %#x, HAP_PTN %#x, HAP_HBST %#x\n",
- chip->cfg_revision, chip->ptn_revision, chip->hbst_revision);
+ if (is_haptics_external_powered(chip)) {
+ dev_dbg(chip->dev, "haptics revision: HAP_CFG %#x, HAP_PTN %#x\n",
+ chip->cfg_revision, chip->ptn_revision);
+ } else {
+ rc = haptics_read(chip, chip->hbst_addr_base,
+ HAP_BOOST_REVISION1, val, 2);
+ if (rc < 0)
+ return rc;
+
+ chip->hbst_revision = (val[1] << 8) | val[0];
+ dev_dbg(chip->dev, "haptics revision: HAP_CFG %#x, HAP_PTN %#x, HAP_HBST %#x\n",
+ chip->cfg_revision, chip->ptn_revision, chip->hbst_revision);
+ }
+
return 0;
}
@@ -3791,13 +3928,14 @@ static int haptics_parse_dt(struct haptics_chip *chip)
chip->ptn_addr_base = be32_to_cpu(*addr);
addr = of_get_address(node, 2, NULL, NULL);
- if (!addr) {
+ if (!addr && !is_haptics_external_powered(chip)) {
dev_err(chip->dev, "Read HAPTICS_HBOOST address failed\n");
rc = -EINVAL;
goto free_pbs;
+ } else if (addr != NULL) {
+ chip->hbst_addr_base = be32_to_cpu(*addr);
}
- chip->hbst_addr_base = be32_to_cpu(*addr);
rc = haptics_get_revision(chip);
if (rc < 0) {
dev_err(chip->dev, "Get revision failed, rc=%d\n", rc);
@@ -3820,12 +3958,12 @@ static int haptics_parse_dt(struct haptics_chip *chip)
goto free_pbs;
}
- config->fifo_empty_thresh = FIFO_EMPTY_THRESHOLD(chip);
+ config->fifo_empty_thresh = get_fifo_empty_threshold(chip);
of_property_read_u32(node, "qcom,fifo-empty-threshold",
&config->fifo_empty_thresh);
- if (config->fifo_empty_thresh >= MAX_FIFO_SAMPLES(chip)) {
+ if (config->fifo_empty_thresh >= get_max_fifo_samples(chip)) {
dev_err(chip->dev, "FIFO empty threshold (%d) should be less than %d\n",
- config->fifo_empty_thresh, MAX_FIFO_SAMPLES(chip));
+ config->fifo_empty_thresh, get_max_fifo_samples(chip));
rc = -EINVAL;
goto free_pbs;
}
@@ -4044,7 +4182,7 @@ static u32 get_lra_impedance_capable_max(struct haptics_chip *chip)
if (chip->clamp_at_5v)
mohms = MAX_IMPEDANCE_MOHM / 2;
- if (chip->hpwr_vreg)
+ if (is_haptics_external_powered(chip))
mohms = (chip->hpwr_voltage_mv * 1000) / MIN_ISC_MA;
dev_dbg(chip->dev, "LRA impedance capable max: %u mohms\n", mohms);
@@ -4210,7 +4348,7 @@ static int haptics_detect_lra_frequency(struct haptics_chip *chip)
goto restore;
/* Fix Vmax to (hpwr_vreg_mv - hdrm_mv) in non-HBOOST regulator case */
- if (chip->hpwr_vreg)
+ if (is_haptics_external_powered(chip))
vmax_mv = chip->hpwr_voltage_mv - LRA_CALIBRATION_VMAX_HDRM_MV;
rc = haptics_set_vmax_mv(chip, vmax_mv);
@@ -4401,6 +4539,9 @@ static int haptics_probe(struct platform_device *pdev)
return -ENXIO;
}
+ chip->pmic_type =
+ (enum pmic_type)(uintptr_t)of_device_get_match_data(chip->dev);
+
rc = haptics_parse_dt(chip);
if (rc < 0) {
dev_err(chip->dev, "Parse device-tree failed, rc = %d\n", rc);
@@ -4572,8 +4713,18 @@ static const struct dev_pm_ops haptics_pm_ops = {
};
static const struct of_device_id haptics_match_table[] = {
- { .compatible = "qcom,hv-haptics" },
- { .compatible = "qcom,pm8350b-haptics" },
+ {
+ .compatible = "qcom,hv-haptics",
+ .data = (void *)PM8350B,
+ },
+ {
+ .compatible = "qcom,pm8350b-haptics",
+ .data = (void *)PM8350B,
+ },
+ {
+ .compatible = "qcom,pm5100-haptics",
+ .data = (void *)PM5100,
+ },
{},
};
diff --git a/drivers/mmc/host/sdhci-msm.c b/drivers/mmc/host/sdhci-msm.c
index 99c9357c4b05..9b30ce9562b9 100644
--- a/drivers/mmc/host/sdhci-msm.c
+++ b/drivers/mmc/host/sdhci-msm.c
@@ -20,6 +20,7 @@
#include
#include
#include
+#include
#include "sdhci-pltfm.h"
#include "cqhci.h"
@@ -4379,6 +4380,13 @@ static int sdhci_msm_probe(struct platform_device *pdev)
}
}
+ /* Toggle wlan_en pin to reset SDIO card to correct state */
+ if (host->mmc->pm_caps & MMC_PM_KEEP_POWER) {
+ pinctrl_pm_select_sleep_state(&pdev->dev);
+ mdelay(1);
+ pinctrl_pm_select_default_state(&pdev->dev);
+ }
+
/* Reset the vendor spec register to power on reset state */
writel_relaxed(CORE_VENDOR_SPEC_POR_VAL,
host->ioaddr + msm_offset->core_vendor_spec);
diff --git a/drivers/mtd/devices/msm_qpic_nand.c b/drivers/mtd/devices/msm_qpic_nand.c
index 7de758780067..e93965cd1ee8 100644
--- a/drivers/mtd/devices/msm_qpic_nand.c
+++ b/drivers/mtd/devices/msm_qpic_nand.c
@@ -2941,7 +2941,14 @@ static int msm_nand_read_partial_page(struct mtd_info *mtd,
no_copy = false;
ops->datbuf = no_copy ? actual_buf : bounce_buf;
- if (info->nand_chip.caps & MSM_NAND_CAP_PAGE_SCOPE_READ)
+
+ /*
+ * Do a Pagescope read only if PAGE_SCOPE_READ is enabled
+ * and request length is greater than codeword size or
+ * the page offset is not aligned to start of the page.
+ */
+ if ((info->nand_chip.caps & MSM_NAND_CAP_PAGE_SCOPE_READ) &&
+ ((len > ONE_CODEWORD_SIZE) || (offset != 0)))
err = msm_nand_read_pagescope(mtd, aligned_from, ops);
else {
if ((len <= ONE_CODEWORD_SIZE) && (offset == 0))
diff --git a/drivers/net/wireless/cnss/cnss_pci.c b/drivers/net/wireless/cnss/cnss_pci.c
index bef8ef6ee5b0..16e290819962 100644
--- a/drivers/net/wireless/cnss/cnss_pci.c
+++ b/drivers/net/wireless/cnss/cnss_pci.c
@@ -79,9 +79,9 @@
#define WLAN_BOOTSTRAP_GPIO_NAME "wlan-bootstrap-gpio"
#define PM_OPTIONS 0
#define PM_OPTIONS_SUSPEND_LINK_DOWN \
- (MSM_PCIE_CONFIG_NO_CFG_RESTORE | MSM_PCIE_CONFIG_LINKDOWN)
+ (PM_OPTIONS | MSM_PCIE_CONFIG_LINKDOWN)
#define PM_OPTIONS_RESUME_LINK_DOWN \
- (MSM_PCIE_CONFIG_NO_CFG_RESTORE)
+ (PM_OPTIONS)
#define SOC_SWREG_VOLT_MAX 1200000
#define SOC_SWREG_VOLT_MIN 1200000
@@ -231,6 +231,7 @@ static struct cnss_data {
bool pci_register_again;
bool notify_modem_status;
struct pci_saved_state *saved_state;
+ struct pci_saved_state *default_state;
u16 revision_id;
bool recovery_in_progress;
atomic_t fw_available;
@@ -1518,7 +1519,7 @@ int cnss_pci_load_and_free_saved_state(struct pci_dev *dev,
int cnss_msm_pcie_shadow_control(struct pci_dev *dev, bool enable)
{
- return msm_pcie_shadow_control(dev, enable);
+ return 0;
}
int cnss_msm_pcie_deregister_event(struct msm_pcie_register_event *reg)
@@ -1528,7 +1529,12 @@ int cnss_msm_pcie_deregister_event(struct msm_pcie_register_event *reg)
int cnss_msm_pcie_recover_config(struct pci_dev *dev)
{
- return msm_pcie_recover_config(dev);
+ if (penv->saved_state)
+ cnss_pci_load_and_free_saved_state(dev, &penv->saved_state);
+ else
+ pci_load_saved_state(dev, penv->default_state);
+
+ pci_restore_state(dev);
}
int cnss_msm_pcie_register_event(struct msm_pcie_register_event *reg)
@@ -1661,6 +1667,8 @@ static int cnss_wlan_pci_probe(struct pci_dev *pdev,
if (penv->pcie_link_state) {
pci_save_state(pdev);
penv->saved_state = cnss_pci_store_saved_state(pdev);
+ /* Save default config space */
+ penv->default_state = cnss_pci_store_saved_state(pdev);
ret = cnss_msm_pcie_pm_control(MSM_PCIE_SUSPEND,
cnss_get_pci_dev_bus_number(pdev),
@@ -1734,6 +1742,9 @@ static void cnss_wlan_pci_remove(struct pci_dev *pdev)
if (!penv)
return;
+ if (penv->default_state)
+ pci_load_and_free_saved_state(penv->pdev, &penv->default_state);
+
dev = &penv->pldev->dev;
cnss_pcie_reset_platform_ops(dev);
device_remove_file(dev, &dev_attr_wlan_setup);
diff --git a/drivers/net/wireless/cnss2/main.c b/drivers/net/wireless/cnss2/main.c
index 2ab4c521c83c..9707beef230f 100644
--- a/drivers/net/wireless/cnss2/main.c
+++ b/drivers/net/wireless/cnss2/main.c
@@ -3053,6 +3053,10 @@ static void cnss_init_control_params(struct cnss_plat_data *plat_priv)
plat_priv->ctrl_params.qmi_timeout = CNSS_QMI_TIMEOUT_DEFAULT;
plat_priv->ctrl_params.bdf_type = CNSS_BDF_TYPE_DEFAULT;
plat_priv->ctrl_params.time_sync_period = CNSS_TIME_SYNC_PERIOD_DEFAULT;
+ /* Set adsp_pc_enabled default value to true as ADSP pc is always
+ * enabled by default
+ */
+ plat_priv->adsp_pc_enabled = true;
}
static void cnss_get_pm_domain_info(struct cnss_plat_data *plat_priv)
diff --git a/drivers/net/wireless/cnss2/main.h b/drivers/net/wireless/cnss2/main.h
index 0c9ef48b3255..97115c84b1a8 100644
--- a/drivers/net/wireless/cnss2/main.h
+++ b/drivers/net/wireless/cnss2/main.h
@@ -505,6 +505,7 @@ struct cnss_plat_data {
u32 is_converged_dt;
struct device_node *dev_node;
u64 feature_list;
+ bool adsp_pc_enabled;
};
#ifdef CONFIG_ARCH_QCOM
diff --git a/drivers/net/wireless/cnss2/pci.c b/drivers/net/wireless/cnss2/pci.c
index e061547285df..55fb99a8d6de 100644
--- a/drivers/net/wireless/cnss2/pci.c
+++ b/drivers/net/wireless/cnss2/pci.c
@@ -1802,6 +1802,13 @@ static int cnss_wlan_adsp_pc_enable(struct cnss_pci_data *pci_priv,
struct pci_dev *pci_dev = pci_priv->pci_dev;
int ret = 0;
u32 pm_options = PM_OPTIONS_DEFAULT;
+ struct cnss_plat_data *plat_priv = pci_priv->plat_priv;
+
+ if (plat_priv->adsp_pc_enabled == control) {
+ cnss_pr_dbg("ADSP power collapse already %s\n",
+ control ? "Enabled" : "Disabled");
+ return 0;
+ }
if (control)
pm_options &= ~MSM_PCIE_CONFIG_NO_DRV_PC;
@@ -1814,6 +1821,7 @@ static int cnss_wlan_adsp_pc_enable(struct cnss_pci_data *pci_priv,
return ret;
cnss_pr_dbg("%s ADSP power collapse\n", control ? "Enable" : "Disable");
+ plat_priv->adsp_pc_enabled = control;
return 0;
}
#else
@@ -2978,6 +2986,7 @@ int cnss_pci_unregister_driver_hdlr(struct cnss_pci_data *pci_priv)
static bool cnss_pci_is_drv_supported(struct cnss_pci_data *pci_priv)
{
struct pci_dev *root_port = pci_find_pcie_root_port(pci_priv->pci_dev);
+ struct cnss_plat_data *plat_priv = pci_priv->plat_priv;
struct device_node *root_of_node;
bool drv_supported = false;
@@ -2997,6 +3006,9 @@ static bool cnss_pci_is_drv_supported(struct cnss_pci_data *pci_priv)
drv_supported ? "supported" : "not supported");
pci_priv->drv_supported = drv_supported;
+ if (drv_supported)
+ plat_priv->cap.cap_flag |= CNSS_HAS_DRV_SUPPORT;
+
return drv_supported;
}
diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c
index a9fc831eba60..bc4618ae9c5f 100644
--- a/drivers/net/wireless/mac80211_hwsim.c
+++ b/drivers/net/wireless/mac80211_hwsim.c
@@ -4041,7 +4041,7 @@ static void hwsim_virtio_rx_work(struct work_struct *work)
}
vq = hwsim_vqs[HWSIM_VQ_RX];
sg_init_one(sg, skb->head, skb_end_offset(skb));
- err = virtqueue_add_inbuf(vq, sg, 1, skb, GFP_KERNEL);
+ err = virtqueue_add_inbuf(vq, sg, 1, skb, GFP_ATOMIC);
if (WARN(err, "virtqueue_add_inbuf returned %d\n", err))
nlmsg_free(skb);
else
diff --git a/drivers/regulator/qpnp-regulator.c b/drivers/regulator/qpnp-regulator.c
index a78029d978da..b9cc97dd5d0d 100644
--- a/drivers/regulator/qpnp-regulator.c
+++ b/drivers/regulator/qpnp-regulator.c
@@ -53,6 +53,9 @@ enum qpnp_regulator_logical_type {
QPNP_REGULATOR_LOGICAL_TYPE_ULT_HO_SMPS,
QPNP_REGULATOR_LOGICAL_TYPE_ULT_LDO,
QPNP_REGULATOR_LOGICAL_TYPE_FTSMPS2,
+ QPNP_REGULATOR_LOGICAL_TYPE_FTSMPS3,
+ QPNP_REGULATOR_LOGICAL_TYPE_LDO_510,
+ QPNP_REGULATOR_LOGICAL_TYPE_HFSMPS,
};
enum qpnp_regulator_type {
@@ -103,6 +106,17 @@ enum qpnp_regulator_subtype {
QPNP_REGULATOR_SUBTYPE_ULT_HF_CTL2 = 0x0E,
QPNP_REGULATOR_SUBTYPE_ULT_HF_CTL3 = 0x0F,
QPNP_REGULATOR_SUBTYPE_ULT_HF_CTL4 = 0x10,
+ QPNP_REGULATOR_SUBTYPE_HFSMPS_510 = 0x0A,
+ QPNP_REGULATOR_SUBTYPE_FTSMPS_510 = 0x0B,
+ QPNP_REGULATOR_SUBTYPE_LV_P150_510 = 0x71,
+ QPNP_REGULATOR_SUBTYPE_LV_P300_510 = 0x72,
+ QPNP_REGULATOR_SUBTYPE_LV_P600_510 = 0x73,
+ QPNP_REGULATOR_SUBTYPE_N300_510 = 0x6A,
+ QPNP_REGULATOR_SUBTYPE_N600_510 = 0x6B,
+ QPNP_REGULATOR_SUBTYPE_N1200_510 = 0x6C,
+ QPNP_REGULATOR_SUBTYPE_MV_P50_510 = 0x7A,
+ QPNP_REGULATOR_SUBTYPE_MV_P150_510 = 0x7B,
+ QPNP_REGULATOR_SUBTYPE_MV_P600_510 = 0x7D,
};
/* First common register layout used by older devices */
@@ -130,6 +144,11 @@ enum qpnp_common2_regulator_registers {
QPNP_COMMON2_REG_STEP_CTRL = 0x61,
};
+enum qpnp_common3_regulator_registers {
+ QPNP_COMMON3_REG_STEP_CTRL = 0x3C,
+};
+
+
enum qpnp_ldo_registers {
QPNP_LDO_REG_SOFT_START = 0x4C,
};
@@ -191,6 +210,15 @@ enum qpnp_common2_control_register_index {
#define QPNP_COMMON2_MODE_MASK 0x07
+/* Third common regulator mode register values */
+#define QPNP_COMMON3_MODE_BYPASS 2
+#define QPNP_COMMON3_MODE_RETENTION 3
+#define QPNP_COMMON3_MODE_LPM 4
+#define QPNP_COMMON3_MODE_AUTO 6
+#define QPNP_COMMON3_MODE_HPM 7
+
+#define QPNP_COMMON3_MODE_MASK 0x07
+
/* Common regulator pull down control register layout */
#define QPNP_COMMON_PULL_DOWN_ENABLE_MASK 0x80
@@ -251,6 +279,9 @@ enum qpnp_common2_control_register_index {
#define QPNP_FTSMPS2_STEP_MARGIN_NUM 10
#define QPNP_FTSMPS2_STEP_MARGIN_DEN 11
+/* slew_rate has units of uV/us. */
+#define QPNP_COMMON3_FTSMPS3_SLEW_RATE_38p4 38400
+
/*
* This voltage in uV is returned by get_voltage functions when there is no way
* to determine the current voltage level. It is needed because the regulator
@@ -451,6 +482,26 @@ static struct qpnp_voltage_range ftsmps426_ranges[] = {
VOLTAGE_RANGE(0, 0, 320000, 1352000, 1352000, 4000),
};
+static struct qpnp_voltage_range pldo_510_ranges[] = {
+ VOLTAGE_RANGE(0, 1504000, 1504000, 2000000, 2000000, 8000),
+};
+
+static struct qpnp_voltage_range mv_pldo_510_ranges[] = {
+ VOLTAGE_RANGE(0, 1504000, 1504000, 3544000, 3544000, 8000),
+};
+
+static struct qpnp_voltage_range nldo_510_ranges[] = {
+ VOLTAGE_RANGE(0, 320000, 320000, 1304000, 1304000, 8000),
+};
+
+static struct qpnp_voltage_range hfsmps510_ranges[] = {
+ VOLTAGE_RANGE(0, 320000, 320000, 2040000, 2040000, 8000),
+};
+
+static struct qpnp_voltage_range ftsmps510_ranges[] = {
+ VOLTAGE_RANGE(0, 300000, 300000, 1372000, 1372000, 4000),
+};
+
static struct qpnp_voltage_set_points pldo_set_points = SET_POINTS(pldo_ranges);
static struct qpnp_voltage_set_points nldo1_set_points
= SET_POINTS(nldo1_ranges);
@@ -479,6 +530,16 @@ static struct qpnp_voltage_set_points ult_pldo_set_points
= SET_POINTS(ult_pldo_ranges);
static struct qpnp_voltage_set_points ftsmps426_set_points
= SET_POINTS(ftsmps426_ranges);
+static struct qpnp_voltage_set_points pldo_510_set_points
+ = SET_POINTS(pldo_510_ranges);
+static struct qpnp_voltage_set_points mv_pldo_510_set_points
+ = SET_POINTS(mv_pldo_510_ranges);
+static struct qpnp_voltage_set_points nldo_510_set_points
+ = SET_POINTS(nldo_510_ranges);
+static struct qpnp_voltage_set_points hfsmps510_set_points
+ = SET_POINTS(hfsmps510_ranges);
+static struct qpnp_voltage_set_points ftsmps510_set_points
+ = SET_POINTS(ftsmps510_ranges);
static struct qpnp_voltage_set_points none_set_points;
static struct qpnp_voltage_set_points *all_set_points[] = {
@@ -497,6 +558,11 @@ static struct qpnp_voltage_set_points *all_set_points[] = {
&ult_nldo_set_points,
&ult_pldo_set_points,
&ftsmps426_set_points,
+ &pldo_510_set_points,
+ &mv_pldo_510_set_points,
+ &nldo_510_set_points,
+ &hfsmps510_set_points,
+ &ftsmps510_set_points,
};
/* Determines which label to add to a debug print statement. */
@@ -1212,12 +1278,27 @@ static int qpnp_regulator_common2_set_mode(struct regulator_dev *rdev,
* ensures that AUTO mode is re-asserted after switching away from
* forced HPM if it was configured initially.
*/
- if (mode == REGULATOR_MODE_NORMAL)
- val = QPNP_COMMON2_MODE_HPM;
- else if (vreg->init_mode == QPNP_COMMON2_MODE_HPM)
- val = QPNP_COMMON2_MODE_LPM;
- else
- val = vreg->init_mode;
+ if ((vreg->logical_type == QPNP_REGULATOR_LOGICAL_TYPE_FTSMPS3) ||
+ (vreg->logical_type == QPNP_REGULATOR_LOGICAL_TYPE_HFSMPS) ||
+ (vreg->logical_type == QPNP_REGULATOR_LOGICAL_TYPE_LDO_510)) {
+ if (mode == REGULATOR_MODE_NORMAL)
+ val = QPNP_COMMON3_MODE_HPM;
+ else if (vreg->init_mode == QPNP_COMMON3_MODE_HPM &&
+ vreg->logical_type !=
+ QPNP_REGULATOR_LOGICAL_TYPE_FTSMPS3)
+ val = QPNP_COMMON3_MODE_LPM;
+ else if (vreg->init_mode == QPNP_COMMON3_MODE_HPM)
+ val = QPNP_COMMON3_MODE_RETENTION;
+ else
+ val = vreg->init_mode;
+ } else {
+ if (mode == REGULATOR_MODE_NORMAL)
+ val = QPNP_COMMON2_MODE_HPM;
+ else if (vreg->init_mode == QPNP_COMMON2_MODE_HPM)
+ val = QPNP_COMMON2_MODE_LPM;
+ else
+ val = vreg->init_mode;
+ }
rc = qpnp_vreg_write_optimized(vreg, QPNP_COMMON2_REG_MODE, &val,
&vreg->ctrl_reg[QPNP_COMMON2_IDX_MODE], 1);
@@ -1335,6 +1416,18 @@ static const char * const qpnp_common2_mode_label[] = {
[QPNP_COMMON2_MODE_HPM] = "HPM",
};
+static const char * const qpnp_common3_mode_label[] = {
+ [0] = "RSV",
+ [1] = "RSV",
+ [2] = "RSV",
+ [QPNP_COMMON3_MODE_BYPASS] = "BYP",
+ [QPNP_COMMON3_MODE_RETENTION] = "RET",
+ [QPNP_COMMON3_MODE_LPM] = "LPM",
+ [QPNP_COMMON3_MODE_AUTO] = "AUTO",
+ [QPNP_COMMON3_MODE_HPM] = "HPM",
+};
+
+
static void qpnp_vreg_show_state(struct regulator_dev *rdev,
enum qpnp_regulator_action action)
{
@@ -1495,6 +1588,16 @@ static void qpnp_vreg_show_state(struct regulator_dev *rdev,
action_label, vreg->rdesc.name, enable_label, uV,
mode_label);
break;
+ case QPNP_REGULATOR_LOGICAL_TYPE_HFSMPS:
+ case QPNP_REGULATOR_LOGICAL_TYPE_FTSMPS3:
+ case QPNP_REGULATOR_LOGICAL_TYPE_LDO_510:
+ mode_reg = vreg->ctrl_reg[QPNP_COMMON_IDX_MODE];
+ mode_label = qpnp_common3_mode_label[mode_reg
+ & QPNP_COMMON3_MODE_MASK];
+ pr_info("%s %-11s: %s, v=%7d uV, mode=%s\n",
+ action_label, vreg->rdesc.name, enable_label, uV,
+ mode_label);
+ break;
default:
break;
}
@@ -1618,6 +1721,45 @@ static struct regulator_ops qpnp_ftsmps426_ops = {
.enable_time = qpnp_regulator_common_enable_time,
};
+static struct regulator_ops qpnp_hfsmps510_ops = {
+ .enable = qpnp_regulator_common_enable,
+ .disable = qpnp_regulator_common_disable,
+ .is_enabled = qpnp_regulator_common_is_enabled,
+ .set_voltage = qpnp_regulator_common2_set_voltage,
+ .get_voltage = qpnp_regulator_common2_get_voltage,
+ .list_voltage = qpnp_regulator_common_list_voltage,
+ .set_mode = qpnp_regulator_common2_set_mode,
+ .get_mode = qpnp_regulator_common2_get_mode,
+ .get_optimum_mode = qpnp_regulator_common_get_optimum_mode,
+ .enable_time = qpnp_regulator_common_enable_time,
+};
+
+static struct regulator_ops qpnp_ftsmps510_ops = {
+ .enable = qpnp_regulator_common_enable,
+ .disable = qpnp_regulator_common_disable,
+ .is_enabled = qpnp_regulator_common_is_enabled,
+ .set_voltage = qpnp_regulator_common2_set_voltage,
+ .get_voltage = qpnp_regulator_common2_get_voltage,
+ .list_voltage = qpnp_regulator_common_list_voltage,
+ .set_mode = qpnp_regulator_common2_set_mode,
+ .get_mode = qpnp_regulator_common2_get_mode,
+ .get_optimum_mode = qpnp_regulator_common_get_optimum_mode,
+ .enable_time = qpnp_regulator_common_enable_time,
+};
+
+static struct regulator_ops qpnp_ldo_510_ops = {
+ .enable = qpnp_regulator_common_enable,
+ .disable = qpnp_regulator_common_disable,
+ .is_enabled = qpnp_regulator_common_is_enabled,
+ .set_voltage = qpnp_regulator_common2_set_voltage,
+ .get_voltage = qpnp_regulator_common2_get_voltage,
+ .list_voltage = qpnp_regulator_common_list_voltage,
+ .set_mode = qpnp_regulator_common2_set_mode,
+ .get_mode = qpnp_regulator_common2_get_mode,
+ .get_optimum_mode = qpnp_regulator_common_get_optimum_mode,
+ .enable_time = qpnp_regulator_common_enable_time,
+};
+
/* Maximum possible digital major revision value */
#define INF 0xFF
@@ -1679,8 +1821,27 @@ static const struct qpnp_regulator_mapping supported_regulators[] = {
10000),
QPNP_VREG_MAP(ULT_LDO, P50, 0, INF, ULT_LDO, ult_ldo, ult_pldo,
5000),
- QPNP_VREG_MAP(FTS, FTS426, 0, INF, FTSMPS2, ftsmps426, ftsmps426,
+ QPNP_VREG_MAP(FTS, FTS426, 0, INF, FTSMPS2, ftsmps426, ftsmps426,
100000),
+ QPNP_VREG_MAP(LDO, LV_P150_510, 0, INF, LDO_510, ldo_510, pldo_510,
+ 10000),
+ QPNP_VREG_MAP(LDO, LV_P300_510, 0, INF, LDO_510, ldo_510, pldo_510,
+ 10000),
+ QPNP_VREG_MAP(LDO, LV_P600_510, 0, INF, LDO_510, ldo_510, pldo_510,
+ 10000),
+ QPNP_VREG_MAP(LDO, MV_P50_510, 0, INF, LDO_510, ldo_510, mv_pldo_510,
+ 10000),
+ QPNP_VREG_MAP(LDO, MV_P150_510, 0, INF, LDO_510, ldo_510, mv_pldo_510,
+ 10000),
+ QPNP_VREG_MAP(LDO, MV_P600_510, 0, INF, LDO_510, ldo_510, mv_pldo_510,
+ 10000),
+ QPNP_VREG_MAP(LDO, N300_510, 0, INF, LDO_510, ldo_510, nldo_510, 10000),
+ QPNP_VREG_MAP(LDO, N600_510, 0, INF, LDO_510, ldo_510, nldo_510, 10000),
+ QPNP_VREG_MAP(LDO, N1200_510, 0, INF, LDO_510, ldo_510, nldo_510, 10000),
+ QPNP_VREG_MAP(BUCK, HFSMPS_510, 0, INF, HFSMPS, hfsmps510, hfsmps510,
+ 100000),
+ QPNP_VREG_MAP(FTS, FTSMPS_510, 0, INF, FTSMPS3, ftsmps510, ftsmps510,
+ 100000),
};
static int qpnp_regulator_match(struct qpnp_regulator *vreg)
@@ -1792,10 +1953,18 @@ static int qpnp_regulator_ftsmps2_init_slew_rate(struct qpnp_regulator *vreg)
int i, rc, delay;
u8 reg = 0;
- rc = qpnp_vreg_read(vreg, QPNP_COMMON2_REG_STEP_CTRL, ®, 1);
- if (rc) {
- vreg_err(vreg, "spmi read failed, rc=%d\n", rc);
- return rc;
+ if (vreg->logical_type == QPNP_REGULATOR_LOGICAL_TYPE_FTSMPS3) {
+ rc = qpnp_vreg_read(vreg, QPNP_COMMON3_REG_STEP_CTRL, ®, 1);
+ if (rc) {
+ vreg_err(vreg, "spmi read failed, rc=%d\n", rc);
+ return rc;
+ }
+ } else {
+ rc = qpnp_vreg_read(vreg, QPNP_COMMON2_REG_STEP_CTRL, ®, 1);
+ if (rc) {
+ vreg_err(vreg, "spmi read failed, rc=%d\n", rc);
+ return rc;
+ }
}
/*
@@ -1817,14 +1986,18 @@ static int qpnp_regulator_ftsmps2_init_slew_rate(struct qpnp_regulator *vreg)
delay = (reg & QPNP_FTSMPS2_STEP_CTRL_DELAY_MASK)
>> QPNP_FTSMPS2_STEP_CTRL_DELAY_SHIFT;
- /* slew_rate has units of uV/us. */
- vreg->slew_rate = QPNP_FTSMPS2_CLOCK_RATE * range->step_uV;
- vreg->slew_rate /= 1000 * (QPNP_FTSMPS2_STEP_DELAY << delay);
- vreg->slew_rate = vreg->slew_rate * QPNP_FTSMPS2_STEP_MARGIN_NUM
- / QPNP_FTSMPS2_STEP_MARGIN_DEN;
+ if (vreg->logical_type == QPNP_REGULATOR_LOGICAL_TYPE_FTSMPS3) {
+ vreg->slew_rate = QPNP_COMMON3_FTSMPS3_SLEW_RATE_38p4 >> delay;
+ } else {
+ /* slew_rate has units of uV/us. */
+ vreg->slew_rate = QPNP_FTSMPS2_CLOCK_RATE * range->step_uV;
+ vreg->slew_rate /= 1000 * (QPNP_FTSMPS2_STEP_DELAY << delay);
+ vreg->slew_rate = vreg->slew_rate * QPNP_FTSMPS2_STEP_MARGIN_NUM
+ / QPNP_FTSMPS2_STEP_MARGIN_DEN;
- /* Ensure that the slew rate is greater than 0. */
- vreg->slew_rate = max(vreg->slew_rate, 1);
+ /* Ensure that the slew rate is greater than 0. */
+ vreg->slew_rate = max(vreg->slew_rate, 1);
+ }
return rc;
}
@@ -1905,6 +2078,35 @@ static int qpnp_regulator_init_registers(struct qpnp_regulator *vreg,
= QPNP_COMMON2_MODE_LPM;
}
+ if (type == QPNP_REGULATOR_LOGICAL_TYPE_FTSMPS3 ||
+ type == QPNP_REGULATOR_LOGICAL_TYPE_HFSMPS ||
+ type == QPNP_REGULATOR_LOGICAL_TYPE_LDO_510) {
+ if (pdata->hpm_enable == QPNP_REGULATOR_ENABLE)
+ ctrl_reg[QPNP_COMMON2_IDX_MODE]
+ = QPNP_COMMON3_MODE_HPM;
+ else if (pdata->auto_mode_enable == QPNP_REGULATOR_ENABLE
+ && type == QPNP_REGULATOR_LOGICAL_TYPE_HFSMPS)
+ ctrl_reg[QPNP_COMMON2_IDX_MODE]
+ = QPNP_COMMON3_MODE_AUTO;
+ else if (pdata->hpm_enable == QPNP_REGULATOR_DISABLE
+ && ctrl_reg[QPNP_COMMON2_IDX_MODE]
+ == QPNP_COMMON3_MODE_HPM &&
+ type != QPNP_REGULATOR_LOGICAL_TYPE_FTSMPS3)
+ ctrl_reg[QPNP_COMMON2_IDX_MODE]
+ = QPNP_COMMON3_MODE_LPM;
+ else if (pdata->hpm_enable == QPNP_REGULATOR_DISABLE
+ && ctrl_reg[QPNP_COMMON2_IDX_MODE]
+ == QPNP_COMMON3_MODE_HPM)
+ ctrl_reg[QPNP_COMMON2_IDX_MODE]
+ = QPNP_COMMON3_MODE_RETENTION;
+ else if (pdata->auto_mode_enable == QPNP_REGULATOR_DISABLE
+ && ctrl_reg[QPNP_COMMON2_IDX_MODE]
+ == QPNP_COMMON2_MODE_AUTO &&
+ type == QPNP_REGULATOR_LOGICAL_TYPE_HFSMPS)
+ ctrl_reg[QPNP_COMMON2_IDX_MODE]
+ = QPNP_COMMON2_MODE_LPM;
+ }
+
/* Set up mode pin control. */
if ((type == QPNP_REGULATOR_LOGICAL_TYPE_SMPS
|| type == QPNP_REGULATOR_LOGICAL_TYPE_LDO)
@@ -2068,8 +2270,9 @@ static int qpnp_regulator_init_registers(struct qpnp_regulator *vreg,
}
}
- /* Calculate the slew rate for FTSMPS2 regulators. */
- if (type == QPNP_REGULATOR_LOGICAL_TYPE_FTSMPS2) {
+ /* Calculate the slew rate for FTSMPS2 and FTSMPS3 regulators. */
+ if (type == QPNP_REGULATOR_LOGICAL_TYPE_FTSMPS2 ||
+ type == QPNP_REGULATOR_LOGICAL_TYPE_FTSMPS3) {
rc = qpnp_regulator_ftsmps2_init_slew_rate(vreg);
if (rc) {
vreg_err(vreg, "failed to initialize step rate, rc=%d\n",
diff --git a/drivers/remoteproc/remoteproc_core.c b/drivers/remoteproc/remoteproc_core.c
index ce92ae227aa1..a08568c85126 100644
--- a/drivers/remoteproc/remoteproc_core.c
+++ b/drivers/remoteproc/remoteproc_core.c
@@ -445,7 +445,7 @@ static void rproc_rvdev_release(struct device *dev)
/**
* rproc_handle_vdev() - handle a vdev fw resource
* @rproc: the remote processor
- * @rsc: the vring resource descriptor
+ * ptr: the vring resource descriptor
* @avail: size of available data (for sanity checking the image)
*
* This resource entry requests the host to statically register a virtio
@@ -469,9 +469,10 @@ static void rproc_rvdev_release(struct device *dev)
*
* Returns 0 on success, or an appropriate error code otherwise
*/
-static int rproc_handle_vdev(struct rproc *rproc, struct fw_rsc_vdev *rsc,
+static int rproc_handle_vdev(struct rproc *rproc, void *ptr,
int offset, int avail)
{
+ struct fw_rsc_vdev *rsc = ptr;
struct device *dev = &rproc->dev;
struct rproc_vdev *rvdev;
int i, ret;
@@ -587,7 +588,7 @@ void rproc_vdev_release(struct kref *ref)
/**
* rproc_handle_trace() - handle a shared trace buffer resource
* @rproc: the remote processor
- * @rsc: the trace resource descriptor
+ * @ptr: the trace resource descriptor
* @avail: size of available data (for sanity checking the image)
*
* In case the remote processor dumps trace logs into memory,
@@ -600,9 +601,10 @@ void rproc_vdev_release(struct kref *ref)
*
* Returns 0 on success, or an appropriate error code otherwise
*/
-static int rproc_handle_trace(struct rproc *rproc, struct fw_rsc_trace *rsc,
+static int rproc_handle_trace(struct rproc *rproc, void *ptr,
int offset, int avail)
{
+ struct fw_rsc_trace *rsc = ptr;
struct rproc_debug_trace *trace;
struct device *dev = &rproc->dev;
char name[15];
@@ -652,7 +654,7 @@ static int rproc_handle_trace(struct rproc *rproc, struct fw_rsc_trace *rsc,
/**
* rproc_handle_devmem() - handle devmem resource entry
* @rproc: remote processor handle
- * @rsc: the devmem resource entry
+ * @ptr: the devmem resource entry
* @avail: size of available data (for sanity checking the image)
*
* Remote processors commonly need to access certain on-chip peripherals.
@@ -674,9 +676,10 @@ static int rproc_handle_trace(struct rproc *rproc, struct fw_rsc_trace *rsc,
* and not allow firmwares to request access to physical addresses that
* are outside those ranges.
*/
-static int rproc_handle_devmem(struct rproc *rproc, struct fw_rsc_devmem *rsc,
+static int rproc_handle_devmem(struct rproc *rproc, void *ptr,
int offset, int avail)
{
+ struct fw_rsc_devmem *rsc = ptr;
struct rproc_mem_entry *mapping;
struct device *dev = &rproc->dev;
int ret;
@@ -853,7 +856,7 @@ static int rproc_release_carveout(struct rproc *rproc,
/**
* rproc_handle_carveout() - handle phys contig memory allocation requests
* @rproc: rproc handle
- * @rsc: the resource entry
+ * @ptr: the resource entry
* @avail: size of available data (for image validation)
*
* This function will handle firmware requests for allocation of physically
@@ -869,9 +872,9 @@ static int rproc_release_carveout(struct rproc *rproc,
* pressure is important; it may have a substantial impact on performance.
*/
static int rproc_handle_carveout(struct rproc *rproc,
- struct fw_rsc_carveout *rsc,
- int offset, int avail)
+ void *ptr, int offset, int avail)
{
+ struct fw_rsc_carveout *rsc = ptr;
struct rproc_mem_entry *carveout;
struct device *dev = &rproc->dev;
@@ -1028,10 +1031,10 @@ EXPORT_SYMBOL(rproc_of_resm_mem_entry_init);
* enum fw_resource_type.
*/
static rproc_handle_resource_t rproc_loading_handlers[RSC_LAST] = {
- [RSC_CARVEOUT] = (rproc_handle_resource_t)rproc_handle_carveout,
- [RSC_DEVMEM] = (rproc_handle_resource_t)rproc_handle_devmem,
- [RSC_TRACE] = (rproc_handle_resource_t)rproc_handle_trace,
- [RSC_VDEV] = (rproc_handle_resource_t)rproc_handle_vdev,
+ [RSC_CARVEOUT] = rproc_handle_carveout,
+ [RSC_DEVMEM] = rproc_handle_devmem,
+ [RSC_TRACE] = rproc_handle_trace,
+ [RSC_VDEV] = rproc_handle_vdev,
};
/* handle firmware resource entries before booting the remote processor */
diff --git a/drivers/scsi/ufs/ufs-mediatek.c b/drivers/scsi/ufs/ufs-mediatek.c
index e22f91695b04..6ac8f1e39796 100644
--- a/drivers/scsi/ufs/ufs-mediatek.c
+++ b/drivers/scsi/ufs/ufs-mediatek.c
@@ -582,7 +582,7 @@ static void ufs_mtk_vreg_set_lpm(struct ufs_hba *hba, bool lpm)
if (!hba->vreg_info.vccq2 || !hba->vreg_info.vcc)
return;
- if (lpm & !hba->vreg_info.vcc->enabled)
+ if (lpm && !hba->vreg_info.vcc->enabled)
regulator_set_mode(hba->vreg_info.vccq2->reg,
REGULATOR_MODE_IDLE);
else if (!lpm)
diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index 0f0a05af8945..cb4c80ab7cf5 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -9077,7 +9077,8 @@ int ufshcd_system_suspend(struct ufs_hba *hba)
(ufs_get_pm_lvl_to_dev_pwr_mode(hba->spm_lvl) ==
hba->curr_dev_pwr_mode) &&
(ufs_get_pm_lvl_to_link_pwr_state(hba->spm_lvl) ==
- hba->uic_link_state))
+ hba->uic_link_state) &&
+ !hba->dev_info.b_rpm_dev_flush_capable)
goto out;
if (pm_runtime_suspended(hba->dev)) {
@@ -9274,6 +9275,7 @@ void ufshcd_remove(struct ufs_hba *hba)
ufs_bsg_remove(hba);
ufs_sysfs_remove_nodes(hba->dev);
scsi_remove_host(hba->host);
+ destroy_workqueue(hba->eh_wq);
/* disable interrupts */
ufshcd_disable_intr(hba, hba->intr_mask);
ufshcd_hba_stop(hba, true);
@@ -9546,6 +9548,7 @@ out_remove_scsi_host:
exit_gating:
ufshcd_exit_clk_scaling(hba);
ufshcd_exit_clk_gating(hba);
+ destroy_workqueue(hba->eh_wq);
out_disable:
hba->is_irq_enabled = false;
ufshcd_hba_exit(hba);
diff --git a/drivers/scsi/ufs/ufshcd.h b/drivers/scsi/ufs/ufshcd.h
index 91aee90ec047..db44c7ca098e 100644
--- a/drivers/scsi/ufs/ufshcd.h
+++ b/drivers/scsi/ufs/ufshcd.h
@@ -1462,6 +1462,10 @@ static inline void ufshcd_vops_device_reset(struct ufs_hba *hba)
if (hba->vops && hba->vops->device_reset) {
hba->vops->device_reset(hba);
ufshcd_set_ufs_dev_active(hba);
+ if (ufshcd_is_wb_allowed(hba)) {
+ hba->wb_enabled = false;
+ hba->wb_buf_flush_enabled = false;
+ }
ufshcd_update_reg_hist(&hba->ufs_stats.dev_reset, 0);
}
}
diff --git a/drivers/soc/qcom/Kconfig b/drivers/soc/qcom/Kconfig
index 69e47acd8f51..89f4f2b7ee52 100644
--- a/drivers/soc/qcom/Kconfig
+++ b/drivers/soc/qcom/Kconfig
@@ -1050,6 +1050,16 @@ config CDSPRM_VTCM_DYNAMIC_DEBUG
enabled, the vtcm partition details are sent to the CDSP via rpmsg
channel.
+config QCOM_SYSMON_SUBSYSTEM_STATS
+ tristate "Qualcomm Technologies SysMon DSP subsystem stats"
+ depends on QCOM_SMEM
+ help
+ sysMon subsystem stats driver exposes API to query DSP
+ subsystem's load and power statistics stored in SMEM.
+ SMEM region for each DSP subsystem is updated periodically
+ by the respective subsystem. Power stats gets updated after
+ DSP clock change event.
+
config QCOM_WDT_CORE
tristate "Qualcomm Technologies, Inc. Watchdog Support"
depends on ARCH_QCOM
@@ -1062,6 +1072,15 @@ config QCOM_WDT_CORE
watchdog module must be loaded along with this for watchdog
functionality.
+config QCOM_CX_IPEAK
+ tristate "Common driver to handle Cx iPeak limitation"
+ help
+ Cx ipeak HW module is used to limit the current drawn by various
+ subsystem blocks on Cx power rail. Each client needs to set their
+ bit in tcsr register if it is going to cross its own threshold.
+ If all clients are going to cross their thresholds then Cx ipeak
+ hw module will raise an interrupt to cDSP block to throttle cDSP fmax.
+
config QCOM_SOC_WATCHDOG
tristate "Qualcomm Technologies, Inc. Soc Watchdog"
depends on QCOM_WDT_CORE
diff --git a/drivers/soc/qcom/Makefile b/drivers/soc/qcom/Makefile
index d6fbdcb8fb12..9e3889984ba3 100644
--- a/drivers/soc/qcom/Makefile
+++ b/drivers/soc/qcom/Makefile
@@ -109,6 +109,7 @@ endif
obj-$(CONFIG_QTI_SYS_PM_VX) += sys_pm_vx.o
obj-$(CONFIG_ICNSS2) += icnss2/
obj-$(CONFIG_QTI_PLH_SCMI_CLIENT) += plh_scmi.o
+obj-$(CONFIG_QCOM_SYSMON_SUBSYSTEM_STATS) += sysmon_subsystem_stats.o
obj-$(CONFIG_QTI_HW_MEMLAT_SCMI_CLIENT) += memlat_scmi.o
obj-$(CONFIG_QTI_HW_MEMLAT) += rimps_memlat.o
obj-$(CONFIG_QTI_HW_MEMLAT_LOG) += rimps_log.o
@@ -120,6 +121,7 @@ obj-$(CONFIG_MSM_SLATECOM_INTERFACE) += slatecom_interface.o
obj-$(CONFIG_QCOM_AOP_SET_DDR) += aop-set-ddr.o
obj-$(CONFIG_CPU_V7) += idle-v7.o
obj-$(CONFIG_DUMP_XBL_LOG) += dump_boot_log.o
+obj-$(CONFIG_QCOM_CX_IPEAK) += cx_ipeak.o
# GNSS driver
obj-$(CONFIG_GNSS_SIRF) += gnsssirf/
obj-$(CONFIG_MSM_SEB) += slate_events_bridge.o
diff --git a/drivers/soc/qcom/cx_ipeak.c b/drivers/soc/qcom/cx_ipeak.c
new file mode 100644
index 000000000000..72d7ecac9b02
--- /dev/null
+++ b/drivers/soc/qcom/cx_ipeak.c
@@ -0,0 +1,545 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 2018-2021, The Linux Foundation. All rights reserved.
+ */
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include
+
+#define TCSR_CXIP_LM_VOTE_FEATURE_ENABLE_OFFSET 0x10
+
+/* v1 register set */
+#define TCSR_CXIP_LM_VOTE_BYPASS_OFFSET 0x4
+#define TCSR_CXIP_LM_VOTE_CLEAR_OFFSET 0x8
+#define TCSR_CXIP_LM_VOTE_SET_OFFSET 0xC
+#define TCSR_CXIP_LM_TRS_OFFSET 0x24
+
+/* v2 register set */
+#define TCSR_CXIP_LM_VOTE_CLIENTx_BYPASS_OFFSET 0x4
+#define TCSR_CXIP_LM_DANGER_OFFSET 0x24
+
+#define CXIP_CLIENT_OFFSET 0x1000
+#define CXIP_CLIENT10_OFFSET 0x3000
+#define CXIP_VICTIM_OFFSET 0xB000
+
+#define CXIP_POLL_TIMEOUT_US (50 * 1000)
+
+#define CXIP_VICTIMS 3
+#define VICTIM_ENTRIES 3
+
+struct cx_ipeak_client;
+
+struct cx_ipeak_core_ops {
+ int (*update)(struct cx_ipeak_client *client, bool vote);
+ struct cx_ipeak_client* (*register_client)(int client_id);
+};
+
+static struct cx_ipeak_victims {
+ u32 client_id;
+ u32 victim_id;
+ u32 freq_limit;
+ void *data;
+ cx_ipeak_victim_fn victim_cb;
+ struct cx_ipeak_client *client;
+} victim_list[CXIP_VICTIMS];
+
+static struct cx_ipeak_device {
+ struct platform_device *pdev;
+ struct mutex vote_lock;
+ struct mutex throttle_lock;
+ void __iomem *tcsr_vptr;
+ struct cx_ipeak_core_ops *core_ops;
+ u32 victims_count;
+ int danger_intr_num;
+ int safe_intr_num;
+} device_ipeak;
+
+struct cx_ipeak_client {
+ u32 vote_count;
+ unsigned int offset;
+ u32 client_id;
+ bool danger_assert;
+ struct cx_ipeak_device *dev;
+};
+
+
+/**
+ * cx_ipeak_register() - allocate client structure and fill device private and
+ * offset details.
+ * @dev_node: device node of the client
+ * @client_name: property name of the client
+ *
+ * Allocate client memory and fill the structure with device private and bit
+ *
+ */
+struct cx_ipeak_client *cx_ipeak_register(struct device_node *dev_node,
+ const char *client_name)
+{
+ struct of_phandle_args cx_spec;
+ struct cx_ipeak_client *client = NULL;
+ int ret;
+
+ ret = of_parse_phandle_with_args(dev_node, client_name,
+ "#size-cells", 0, &cx_spec);
+ if (ret)
+ return ERR_PTR(-EINVAL);
+
+ if (!of_device_is_available(cx_spec.np))
+ return NULL;
+
+ if (device_ipeak.tcsr_vptr == NULL)
+ return ERR_PTR(-EPROBE_DEFER);
+
+ if (cx_spec.args[0] > 31)
+ return ERR_PTR(-EINVAL);
+
+ if (device_ipeak.core_ops)
+ client = device_ipeak.core_ops->register_client
+ (cx_spec.args[0]);
+
+ client->client_id = cx_spec.args[0];
+
+ return client;
+}
+EXPORT_SYMBOL(cx_ipeak_register);
+
+static struct cx_ipeak_client *cx_ipeak_register_v1(int client_id)
+{
+ struct cx_ipeak_client *client;
+ unsigned int reg_enable, reg_bypass;
+ void __iomem *vptr = device_ipeak.tcsr_vptr;
+
+ reg_enable = readl_relaxed(device_ipeak.tcsr_vptr +
+ TCSR_CXIP_LM_VOTE_FEATURE_ENABLE_OFFSET);
+ reg_bypass = readl_relaxed(vptr +
+ TCSR_CXIP_LM_VOTE_BYPASS_OFFSET) &
+ BIT(client_id);
+ if (!reg_enable || reg_bypass)
+ return NULL;
+
+ client = kzalloc(sizeof(*client), GFP_KERNEL);
+ if (!client)
+ return ERR_PTR(-ENOMEM);
+
+ client->offset = BIT(client_id);
+ client->dev = &device_ipeak;
+
+ return client;
+}
+
+static struct cx_ipeak_client *cx_ipeak_register_v2(int client_id)
+{
+ unsigned int reg_bypass, reg_enable;
+ struct cx_ipeak_client *client;
+ unsigned int client_offset = 0;
+ void __iomem *vptr = device_ipeak.tcsr_vptr;
+ int i;
+
+ for (i = 0; i <= client_id; i++)
+ client_offset += CXIP_CLIENT_OFFSET;
+
+ if (client_id >= 10)
+ client_offset += CXIP_CLIENT10_OFFSET;
+
+ reg_enable = readl_relaxed(device_ipeak.tcsr_vptr +
+ TCSR_CXIP_LM_VOTE_FEATURE_ENABLE_OFFSET);
+ reg_bypass = readl_relaxed(vptr + client_offset +
+ TCSR_CXIP_LM_VOTE_CLIENTx_BYPASS_OFFSET) &
+ BIT(0);
+
+ if (!reg_enable || reg_bypass)
+ return NULL;
+
+ client = kzalloc(sizeof(*client), GFP_KERNEL);
+ if (!client)
+ return ERR_PTR(-ENOMEM);
+
+ client->offset = client_offset;
+ client->dev = &device_ipeak;
+
+ return client;
+}
+
+/**
+ * cx_ipeak_victim_register - victim registration API to handle
+ * the cx ipeak hw interrupts (danger/safe) to throttle freq.
+ * @client: cx ipeak client
+ * @victim_cb: callback function of victim
+ * @data: data to be passed to victim while handling irq
+ */
+int cx_ipeak_victim_register(struct cx_ipeak_client *client,
+ cx_ipeak_victim_fn victim_cb, void *data)
+{
+ int i = 0;
+
+ if (!victim_cb)
+ return -EINVAL;
+
+ for (i = 0; i < device_ipeak.victims_count; i++)
+ if (client->client_id == victim_list[i].client_id) {
+ victim_list[i].victim_cb = victim_cb;
+ victim_list[i].data = data;
+ victim_list[i].client = client;
+ return 0;
+ }
+
+ return -ENOENT;
+}
+EXPORT_SYMBOL(cx_ipeak_victim_register);
+
+/**
+ * cx_ipeak_victim_unregister - unregister victim client from
+ * cx_ipeak driver.
+ * @client: cx ipeak client
+ */
+
+void cx_ipeak_victim_unregister(struct cx_ipeak_client *client)
+{
+ int i = 0;
+
+ for (i = 0; i < device_ipeak.victims_count; i++)
+ if (client->client_id == victim_list[i].client_id) {
+ victim_list[i].victim_cb = NULL;
+ victim_list[i].data = NULL;
+ victim_list[i].client = NULL;
+ }
+}
+EXPORT_SYMBOL(cx_ipeak_victim_unregister);
+
+/**
+ * cx_ipeak_update() - Set/Clear client vote for Cx iPeak limit
+ * manager to throttle cDSP.
+ * @client: client handle.
+ * @vote: True to set the vote and False for reset.
+ *
+ * Receives vote from each client and decides whether to throttle cDSP or not.
+ * This function is NOP for the targets which does not support TCSR Cx iPeak.
+ */
+int cx_ipeak_update(struct cx_ipeak_client *client, bool vote)
+{
+ /* Check for client and device availability and proceed */
+ if (!client)
+ return 0;
+
+ if (!client->dev || !client->dev->core_ops || !client->dev->tcsr_vptr)
+ return -EINVAL;
+
+ return client->dev->core_ops->update(client, vote);
+}
+EXPORT_SYMBOL(cx_ipeak_update);
+
+static int cx_ipeak_update_v1(struct cx_ipeak_client *client, bool vote)
+{
+ unsigned int reg_val;
+ int ret = 0;
+
+ mutex_lock(&client->dev->vote_lock);
+
+ if (vote) {
+ if (client->vote_count == 0) {
+ writel_relaxed(client->offset,
+ client->dev->tcsr_vptr +
+ TCSR_CXIP_LM_VOTE_SET_OFFSET);
+ /*
+ * Do a dummy read to give enough time for TRS register
+ * to become 1 when the last client votes.
+ */
+ readl_relaxed(client->dev->tcsr_vptr +
+ TCSR_CXIP_LM_TRS_OFFSET);
+
+ ret = readl_poll_timeout(client->dev->tcsr_vptr +
+ TCSR_CXIP_LM_TRS_OFFSET,
+ reg_val, !reg_val, 0,
+ CXIP_POLL_TIMEOUT_US);
+ if (ret) {
+ writel_relaxed(client->offset,
+ client->dev->tcsr_vptr +
+ TCSR_CXIP_LM_VOTE_CLEAR_OFFSET);
+ goto done;
+ }
+ }
+ client->vote_count++;
+ } else {
+ if (client->vote_count > 0) {
+ client->vote_count--;
+ if (client->vote_count == 0) {
+ writel_relaxed(client->offset,
+ client->dev->tcsr_vptr +
+ TCSR_CXIP_LM_VOTE_CLEAR_OFFSET);
+ }
+ } else
+ ret = -EINVAL;
+ }
+
+done:
+ mutex_unlock(&client->dev->vote_lock);
+ return ret;
+}
+
+static int cx_ipeak_update_v2(struct cx_ipeak_client *client, bool vote)
+{
+ u32 reg_val;
+ int ret = 0;
+
+ mutex_lock(&client->dev->vote_lock);
+
+ if (vote) {
+ if (client->vote_count == 0) {
+ writel_relaxed(BIT(0),
+ client->dev->tcsr_vptr +
+ client->offset);
+
+ ret = readl_poll_timeout(
+ client->dev->tcsr_vptr +
+ TCSR_CXIP_LM_DANGER_OFFSET,
+ reg_val, !reg_val ||
+ client->danger_assert,
+ 0, CXIP_POLL_TIMEOUT_US);
+ /*
+ * If poll exits due to danger assert condition return
+ * error to client to avoid voting.
+ */
+ if (client->danger_assert)
+ ret = -ETIMEDOUT;
+
+ if (ret) {
+ writel_relaxed(0,
+ client->dev->tcsr_vptr +
+ client->offset);
+ goto done;
+ }
+ }
+ client->vote_count++;
+ } else {
+ if (client->vote_count > 0) {
+ client->vote_count--;
+ if (client->vote_count == 0) {
+ writel_relaxed(0,
+ client->dev->tcsr_vptr +
+ client->offset);
+ }
+ } else {
+ ret = -EINVAL;
+ }
+ }
+
+done:
+ mutex_unlock(&client->dev->vote_lock);
+ return ret;
+}
+
+static irqreturn_t cx_ipeak_irq_soft_handler(int irq, void *data)
+{
+ int i;
+ irqreturn_t ret = IRQ_NONE;
+
+ mutex_lock(&device_ipeak.throttle_lock);
+
+ for (i = 0; i < device_ipeak.victims_count; i++) {
+ cx_ipeak_victim_fn victim_cb = victim_list[i].victim_cb;
+ struct cx_ipeak_client *victim_client = victim_list[i].client;
+
+ if (!victim_cb || !victim_client)
+ continue;
+
+ if (irq == device_ipeak.danger_intr_num) {
+
+ victim_client->danger_assert = true;
+
+ /*
+ * To set frequency limit at victim client
+ * side in danger interrupt case
+ */
+
+ ret = victim_cb(victim_list[i].data,
+ victim_list[i].freq_limit);
+
+ if (ret) {
+ dev_err(&device_ipeak.pdev->dev,
+ "Unable to throttle client:%d freq:%d\n",
+ victim_list[i].client_id,
+ victim_list[i].freq_limit);
+ victim_client->danger_assert = false;
+ ret = IRQ_HANDLED;
+ goto done;
+ }
+
+ writel_relaxed(1, (device_ipeak.tcsr_vptr +
+ CXIP_VICTIM_OFFSET +
+ ((victim_list[i].victim_id)*
+ CXIP_CLIENT_OFFSET)));
+
+ ret = IRQ_HANDLED;
+ } else if (irq == device_ipeak.safe_intr_num) {
+ victim_client->danger_assert = false;
+ /*
+ * To remove frequency limit at victim client
+ * side in safe interrupt case
+ */
+ ret = victim_cb(victim_list[i].data, 0);
+
+ if (ret)
+ dev_err(&device_ipeak.pdev->dev, "Unable to remove freq limit client:%d\n",
+ victim_list[i].client_id);
+
+ writel_relaxed(0, (device_ipeak.tcsr_vptr +
+ CXIP_VICTIM_OFFSET +
+ ((victim_list[i].victim_id)*
+ CXIP_CLIENT_OFFSET)));
+ ret = IRQ_HANDLED;
+ }
+ }
+done:
+ mutex_unlock(&device_ipeak.throttle_lock);
+ return ret;
+}
+
+int cx_ipeak_request_irq(struct platform_device *pdev, const char *name,
+ irq_handler_t handler, irq_handler_t thread_fn, void *data)
+{
+ int ret, num = platform_get_irq_byname(pdev, name);
+
+ if (num < 0)
+ return num;
+
+ ret = devm_request_threaded_irq(&pdev->dev, num, handler, thread_fn,
+ IRQF_ONESHOT | IRQF_TRIGGER_RISING, name, data);
+
+ if (ret)
+ dev_err(&pdev->dev, "Unable to get interrupt %s: %d\n",
+ name, ret);
+
+ return ret ? ret : num;
+}
+
+/**
+ * cx_ipeak_unregister() - unregister client
+ * @client: client address to free
+ *
+ * Free the client memory
+ */
+void cx_ipeak_unregister(struct cx_ipeak_client *client)
+{
+ kfree(client);
+}
+EXPORT_SYMBOL(cx_ipeak_unregister);
+
+struct cx_ipeak_core_ops core_ops_v1 = {
+ .update = cx_ipeak_update_v1,
+ .register_client = cx_ipeak_register_v1,
+};
+
+struct cx_ipeak_core_ops core_ops_v2 = {
+ .update = cx_ipeak_update_v2,
+ .register_client = cx_ipeak_register_v2,
+};
+
+static int cx_ipeak_probe(struct platform_device *pdev)
+{
+ struct resource *res;
+ int i, ret, count;
+ u32 victim_en;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ device_ipeak.tcsr_vptr = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(device_ipeak.tcsr_vptr))
+ return PTR_ERR(device_ipeak.tcsr_vptr);
+
+ if (of_device_is_compatible(pdev->dev.of_node, "qcom,cx-ipeak-v1"))
+ device_ipeak.core_ops = &core_ops_v1;
+ else if (of_device_is_compatible(pdev->dev.of_node,
+ "qcom,cx-ipeak-v2"))
+ device_ipeak.core_ops = &core_ops_v2;
+ else
+ device_ipeak.core_ops = NULL;
+
+ victim_en = of_property_read_bool(pdev->dev.of_node,
+ "victims_table");
+
+ if (victim_en) {
+ count = of_property_count_u32_elems(pdev->dev.of_node,
+ "victims_table");
+
+ if (((count%VICTIM_ENTRIES) != 0) ||
+ ((count/VICTIM_ENTRIES) > CXIP_VICTIMS))
+ return -EINVAL;
+
+ for (i = 0; i < (count/VICTIM_ENTRIES); i++) {
+ ret = of_property_read_u32_index(pdev->dev.of_node,
+ "victims_table", i*VICTIM_ENTRIES,
+ &victim_list[i].client_id);
+
+ if (ret)
+ return ret;
+
+ ret = of_property_read_u32_index(pdev->dev.of_node,
+ "victims_table", (i*VICTIM_ENTRIES) + 1,
+ &victim_list[i].victim_id);
+
+ if (ret)
+ return ret;
+
+ ret = of_property_read_u32_index(pdev->dev.of_node,
+ "victims_table", (i*VICTIM_ENTRIES) + 2,
+ &victim_list[i].freq_limit);
+
+ if (ret)
+ return ret;
+
+ device_ipeak.victims_count++;
+ }
+
+ device_ipeak.danger_intr_num = cx_ipeak_request_irq(pdev,
+ "cx_ipeak_danger", NULL,
+ cx_ipeak_irq_soft_handler, NULL);
+
+ if (device_ipeak.danger_intr_num < 0)
+ return device_ipeak.danger_intr_num;
+
+ device_ipeak.safe_intr_num = cx_ipeak_request_irq(pdev,
+ "cx_ipeak_safe", NULL,
+ cx_ipeak_irq_soft_handler, NULL);
+
+ if (device_ipeak.safe_intr_num < 0)
+ return device_ipeak.safe_intr_num;
+
+ }
+
+ device_ipeak.pdev = pdev;
+ mutex_init(&device_ipeak.vote_lock);
+ mutex_init(&device_ipeak.throttle_lock);
+ return 0;
+}
+
+static const struct of_device_id cx_ipeak_match_table[] = {
+ { .compatible = "qcom,cx-ipeak-v1"},
+ { .compatible = "qcom,cx-ipeak-v2"},
+ {}
+};
+
+static struct platform_driver cx_ipeak_platform_driver = {
+ .probe = cx_ipeak_probe,
+ .driver = {
+ .name = "cx_ipeak",
+ .of_match_table = cx_ipeak_match_table,
+ .suppress_bind_attrs = true,
+ }
+};
+
+static int __init cx_ipeak_init(void)
+{
+ return platform_driver_register(&cx_ipeak_platform_driver);
+}
+
+arch_initcall(cx_ipeak_init);
+
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/soc/qcom/icnss2/power.c b/drivers/soc/qcom/icnss2/power.c
index fe19f1f90315..86b33c5a5ad9 100644
--- a/drivers/soc/qcom/icnss2/power.c
+++ b/drivers/soc/qcom/icnss2/power.c
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
- * Copyright (c) 2015-2020, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2015-2021, The Linux Foundation. All rights reserved.
*/
#include
#include
@@ -26,6 +26,7 @@ static struct icnss_vreg_cfg icnss_adrestea_vreg_list[] = {
{"vdd-1.3-rfa", 1304000, 1304000, 0, 0, 0, false, true},
{"vdd-3.3-ch1", 3312000, 3312000, 0, 0, 0, false, true},
{"vdd-3.3-ch0", 3312000, 3312000, 0, 0, 0, false, true},
+ {"vdd-smps", 984000, 984000, 0, 0, 0, false, true},
};
static struct icnss_clk_cfg icnss_clk_list[] = {
diff --git a/drivers/soc/qcom/icnss2/qmi.c b/drivers/soc/qcom/icnss2/qmi.c
index 54f1d9d7bbda..95b58adcf92e 100644
--- a/drivers/soc/qcom/icnss2/qmi.c
+++ b/drivers/soc/qcom/icnss2/qmi.c
@@ -1350,6 +1350,10 @@ int wlfw_wlan_mode_send_sync_msg(struct icnss_priv *priv,
mode == QMI_WLFW_OFF_V01)
return 0;
+ if (!test_bit(ICNSS_MODE_ON, &priv->state) &&
+ mode == QMI_WLFW_OFF_V01)
+ return 0;
+
icnss_pr_dbg("Sending Mode request, state: 0x%lx, mode: %d\n",
priv->state, mode);
diff --git a/drivers/soc/qcom/mem-offline.c b/drivers/soc/qcom/mem-offline.c
index 99743264e4ea..296c84a2dd46 100644
--- a/drivers/soc/qcom/mem-offline.c
+++ b/drivers/soc/qcom/mem-offline.c
@@ -49,6 +49,7 @@ static bool is_rpm_controller;
static bool has_pend_offline_req;
static atomic_long_t totalram_pages_with_offline = ATOMIC_INIT(0);
static struct workqueue_struct *migrate_wq;
+static unsigned long movable_bitmap;
#define MODULE_CLASS_NAME "mem-offline"
#define MIGRATE_TIMEOUT_SEC (20)
@@ -752,6 +753,63 @@ static int mem_event_callback(struct notifier_block *self,
return NOTIFY_OK;
}
+static int update_movable_bitmap(void)
+{
+ struct device_node *node;
+ struct property *prop;
+ int len, num_cells, num_entries;
+ u64 base, size, end, section_size;
+ u64 movable_start, movable_end;
+ int nr_address_cells, nr_size_cells;
+ const __be32 *pos;
+
+ node = of_find_node_by_name(of_root, "memory");
+ if (!node) {
+ pr_err("mem-offine: memory node not found in DT\n");
+ return -EINVAL;
+ }
+
+ nr_address_cells = of_n_addr_cells(of_root);
+ nr_size_cells = of_n_size_cells(of_root);
+
+ prop = of_find_property(node, "reg", &len);
+
+ num_cells = len / sizeof(__be32);
+ num_entries = num_cells / (nr_address_cells + nr_size_cells);
+
+ pos = prop->value;
+
+ section_size = MIN_MEMORY_BLOCK_SIZE;
+ movable_start = memblock_end_of_DRAM();
+ movable_end = bootloader_memory_limit - 1;
+
+ while (num_entries--) {
+ u64 new_base, new_end;
+ u64 new_start_bitmap, bitmap_size;
+
+ base = of_read_number(pos, nr_address_cells);
+ size = of_read_number(pos + nr_address_cells, nr_size_cells);
+ pos += nr_address_cells + nr_size_cells;
+ end = base + size;
+
+ if (end <= movable_start)
+ continue;
+
+ if (base < movable_start)
+ new_base = movable_start;
+ else
+ new_base = base;
+ new_end = end;
+
+ new_start_bitmap = (new_base - movable_start) / section_size;
+ bitmap_size = (new_end - new_base) / section_size;
+ bitmap_set(&movable_bitmap, new_start_bitmap, bitmap_size);
+ }
+
+ pr_debug("mem-offline: movable_bitmap is %lx\n", movable_bitmap);
+ return 0;
+}
+
static int mem_online_remaining_blocks(void)
{
unsigned long memblock_end_pfn = __phys_to_pfn(memblock_end_of_DRAM());
@@ -760,6 +818,7 @@ static int mem_online_remaining_blocks(void)
unsigned int nid;
phys_addr_t phys_addr;
int fail = 0;
+ int ret;
block_size = memory_block_size_bytes();
sections_per_block = block_size / MIN_MEMORY_BLOCK_SIZE;
@@ -771,8 +830,17 @@ static int mem_online_remaining_blocks(void)
pr_info("mem-offline: System booted with no zone movable memory blocks. Cannot perform memory offlining\n");
return -EINVAL;
}
+
+ ret = update_movable_bitmap();
+ if (ret < 0)
+ return -ENODEV;
+
for (memblock = start_section_nr; memblock <= end_section_nr;
memblock += sections_per_block) {
+
+ if (!test_bit(memblock - start_section_nr, &movable_bitmap))
+ continue;
+
pfn = section_nr_to_pfn(memblock);
phys_addr = __pfn_to_phys(pfn);
diff --git a/drivers/soc/qcom/sysmon_subsystem_stats.c b/drivers/soc/qcom/sysmon_subsystem_stats.c
new file mode 100644
index 000000000000..14ff0b7b650d
--- /dev/null
+++ b/drivers/soc/qcom/sysmon_subsystem_stats.c
@@ -0,0 +1,89 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 2021, The Linux Foundation. All rights reserved.
+ */
+
+#include
+#include
+#include
+#include
+#include
+
+#define SYSMON_SMEM_ID 634
+#define SYSMON_POWER_STATS_VERSIONID 0x1
+#define SYSMON_POWER_STATS_FEATUREID 0x3
+
+/**
+ * sysmon_stats_query_power_residency() - * API to query requested
+ * DSP subsystem power residency.On success, returns power residency
+ * statistics in the given sysmon_smem_power_stats structure.
+ */
+int sysmon_stats_query_power_residency(enum dsp_id_t dsp_id,
+ struct sysmon_smem_power_stats *sysmon_power_stats)
+{
+ u32 featureId;
+ int err = 0;
+ int feature, size_rcvd;
+ size_t size;
+ char *smem_pointer = NULL;
+ int size_of_u32 = sizeof(u32);
+
+ if (!sysmon_power_stats || !dsp_id) {
+ pr_err("%s: Null pointer received/invalid dsp ID\n", __func__);
+ return -EINVAL;
+ }
+
+ smem_pointer = qcom_smem_get(dsp_id, SYSMON_SMEM_ID, &size);
+
+ if (IS_ERR_OR_NULL(smem_pointer) || !size) {
+ pr_err("Failed to fetch data from SMEM for ID %d: %d\n",
+ dsp_id, PTR_ERR(smem_pointer));
+ return -ENOMEM;
+ }
+
+ featureId = *(unsigned int *)smem_pointer;
+
+ feature = featureId >> 28;
+ size_rcvd = (featureId >> 16) & 0xFFF;
+
+ while (size != 0) {
+ switch (feature) {
+
+ case SYSMON_POWER_STATS_FEATUREID:
+
+ if (!IS_ERR_OR_NULL(smem_pointer + size_of_u32)) {
+ memcpy(sysmon_power_stats, (smem_pointer + size_of_u32),
+ sizeof(struct sysmon_smem_power_stats));
+ size = 0;
+ } else {
+ pr_err("%s: Requested feature not found\n", __func__);
+ size = 0;
+ return -ENOMEM;
+ }
+ break;
+ default:
+
+ if (!IS_ERR_OR_NULL(smem_pointer + size_rcvd)
+ && (size > size_rcvd)) {
+
+ featureId = *(unsigned int *)(smem_pointer + size_rcvd);
+
+ smem_pointer += size_rcvd;
+ size = size - size_rcvd;
+
+ feature = featureId >> 28;
+ size_rcvd = (featureId >> 16) & 0xFFF;
+ } else {
+ pr_err("%s: Requested feature not found\n", __func__);
+ size = 0;
+ return -ENOMEM;
+ }
+ break;
+ }
+ }
+ return err;
+}
+EXPORT_SYMBOL(sysmon_stats_query_power_residency);
+
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("Qualcomm Technologies, Inc. Sysmon subsystem Stats driver");
diff --git a/drivers/tty/serial/msm_geni_serial.c b/drivers/tty/serial/msm_geni_serial.c
index c5559fbc0ca9..21dbdc0075f1 100644
--- a/drivers/tty/serial/msm_geni_serial.c
+++ b/drivers/tty/serial/msm_geni_serial.c
@@ -30,6 +30,7 @@
/* UART specific GENI registers */
#define SE_UART_LOOPBACK_CFG (0x22C)
+#define SE_GENI_CFG_REG80 (0x240)
#define SE_UART_TX_TRANS_CFG (0x25C)
#define SE_UART_TX_WORD_LEN (0x268)
#define SE_UART_TX_STOP_BIT_LEN (0x26C)
@@ -258,6 +259,7 @@ static int msm_geni_serial_runtime_resume(struct device *dev);
static int msm_geni_serial_runtime_suspend(struct device *dev);
static int msm_geni_serial_get_ver_info(struct uart_port *uport);
static bool handle_rx_dma_xfer(u32 s_irq_status, struct uart_port *uport);
+static void msm_geni_serial_allow_rx(struct msm_geni_serial_port *port);
static int uart_line_id;
#define GET_DEV_PORT(uport) \
@@ -308,6 +310,7 @@ static void msm_geni_update_uart_error_code(struct msm_geni_serial_port *port,
static void msm_geni_serial_enable_interrupts(struct uart_port *uport)
{
unsigned int geni_m_irq_en, geni_s_irq_en;
+ unsigned int geni_dma_tx_irq_en, geni_dma_rx_irq_en;
struct msm_geni_serial_port *port = GET_DEV_PORT(uport);
geni_m_irq_en = geni_read_reg_nolog(uport->membase,
@@ -326,12 +329,28 @@ static void msm_geni_serial_enable_interrupts(struct uart_port *uport)
geni_write_reg_nolog(DMA_RX_IRQ_BITS, uport->membase,
SE_DMA_RX_IRQ_EN_SET);
}
+
+ if (!uart_console(uport)) {
+ geni_m_irq_en = geni_read_reg_nolog(uport->membase,
+ SE_GENI_M_IRQ_EN);
+ geni_s_irq_en = geni_read_reg_nolog(uport->membase,
+ SE_GENI_S_IRQ_EN);
+ geni_dma_tx_irq_en = geni_read_reg_nolog(uport->membase,
+ SE_DMA_TX_IRQ_EN);
+ geni_dma_rx_irq_en = geni_read_reg_nolog(uport->membase,
+ SE_DMA_RX_IRQ_EN);
+ IPC_LOG_MSG(port->ipc_log_misc,
+ "%s: M_IRQ_EN:0x%x S_IRQ_EN:0x%x TX_IRQ_EN:0x%x RX_IRQ_EN:0x%x\n",
+ __func__, geni_m_irq_en, geni_s_irq_en,
+ geni_dma_tx_irq_en, geni_dma_rx_irq_en);
+ }
}
/* Try disabling interrupts in order to do polling in an atomic contexts. */
static bool msm_serial_try_disable_interrupts(struct uart_port *uport)
{
unsigned int geni_m_irq_en, geni_s_irq_en;
+ unsigned int geni_dma_tx_irq_en, geni_dma_rx_irq_en;
struct msm_geni_serial_port *port = GET_DEV_PORT(uport);
/*
@@ -356,6 +375,21 @@ static bool msm_serial_try_disable_interrupts(struct uart_port *uport)
SE_DMA_RX_IRQ_EN_CLR);
}
+ if (!uart_console(uport)) {
+ geni_m_irq_en = geni_read_reg_nolog(uport->membase,
+ SE_GENI_M_IRQ_EN);
+ geni_s_irq_en = geni_read_reg_nolog(uport->membase,
+ SE_GENI_S_IRQ_EN);
+ geni_dma_tx_irq_en = geni_read_reg_nolog(uport->membase,
+ SE_DMA_TX_IRQ_EN);
+ geni_dma_rx_irq_en = geni_read_reg_nolog(uport->membase,
+ SE_DMA_RX_IRQ_EN);
+ IPC_LOG_MSG(port->ipc_log_misc,
+ "%s: M_IRQ_EN:0x%x S_IRQ_EN:0x%x TX_IRQ_EN:0x%x RX_IRQ_EN:0x%x\n",
+ __func__, geni_m_irq_en, geni_s_irq_en,
+ geni_dma_tx_irq_en, geni_dma_rx_irq_en);
+ }
+
return true;
}
@@ -375,6 +409,8 @@ static bool geni_wait_for_cmd_done(struct uart_port *uport, bool is_irq_masked)
* We need to do polling if spinlock is taken
* by framework as we cannot rely on ISR.
*/
+ if (!uart_console(uport))
+ IPC_LOG_MSG(msm_port->ipc_log_misc, "%s polling:%d\n", __func__, is_irq_masked);
if (is_irq_masked) {
/*
* Polling is done for 1000 iterrations with
@@ -1028,6 +1064,9 @@ static void msm_geni_serial_console_write(struct console *co, const char *s,
"%s: tx abort failed 0x%x\n", __func__,
geni_read_reg_nolog(uport->membase,
SE_GENI_STATUS));
+ msm_geni_serial_allow_rx(port);
+ geni_write_reg(FORCE_DEFAULT, uport->membase,
+ GENI_FORCE_DEFAULT_REG);
}
msm_geni_serial_enable_interrupts(uport);
@@ -1181,6 +1220,9 @@ static int msm_geni_serial_prep_dma_tx(struct uart_port *uport)
SE_GENI_STATUS));
msm_geni_update_uart_error_code(msm_port, UART_ERROR_TX_ABORT_FAIL);
}
+ msm_geni_serial_allow_rx(msm_port);
+ geni_write_reg(FORCE_DEFAULT, uport->membase,
+ GENI_FORCE_DEFAULT_REG);
}
if (msm_port->xfer_mode == SE_DMA) {
@@ -1225,6 +1267,13 @@ static void msm_geni_serial_start_tx(struct uart_port *uport)
unsigned int geni_ios;
static unsigned int ios_log_limit;
+ /* when start_tx is called with UART clocks OFF return. */
+ if (uart_console(uport) && msm_port->is_clock_off) {
+ IPC_LOG_MSG(msm_port->console_log,
+ "%s. Console in suspend state\n", __func__);
+ return;
+ }
+
if (!uart_console(uport) && !pm_runtime_active(uport->dev)) {
IPC_LOG_MSG(msm_port->ipc_log_misc,
"%s.Putting in async RPM vote\n", __func__);
@@ -1328,6 +1377,9 @@ static void stop_tx_sequencer(struct uart_port *uport)
geni_read_reg_nolog(uport->membase, SE_GENI_STATUS));
msm_geni_update_uart_error_code(port, UART_ERROR_TX_ABORT_FAIL);
}
+ msm_geni_serial_allow_rx(port);
+ geni_write_reg(FORCE_DEFAULT, uport->membase,
+ GENI_FORCE_DEFAULT_REG);
}
if (port->xfer_mode == SE_DMA) {
@@ -1608,6 +1660,9 @@ static int stop_rx_sequencer(struct uart_port *uport)
geni_se_dump_dbg_regs(&port->serial_rsc,
uport->membase, port->ipc_log_misc);
}
+ msm_geni_serial_allow_rx(port);
+ geni_write_reg(FORCE_DEFAULT, uport->membase,
+ GENI_FORCE_DEFAULT_REG);
if (port->xfer_mode == SE_DMA) {
port->s_cmd_done = false;
@@ -2168,9 +2223,9 @@ static void msm_geni_serial_handle_isr(struct uart_port *uport,
if (m_irq_status || s_irq_status ||
dma_tx_status || dma_rx_status)
IPC_LOG_MSG(msm_port->ipc_log_irqstatus,
- "%s: sirq:0x%x mirq:0x%x dma_txirq:0x%x dma_rxirq:0x%x\n",
+ "%s: sirq:0x%x mirq:0x%x dma_txirq:0x%x dma_rxirq:0x%x is_irq_masked:%d\n",
__func__, s_irq_status, m_irq_status,
- dma_tx_status, dma_rx_status);
+ dma_tx_status, dma_rx_status, is_irq_masked);
m_cmd_done = handle_tx_dma_xfer(m_irq_status, uport);
s_cmd_done = handle_rx_dma_xfer(s_irq_status, uport);
}
@@ -2351,6 +2406,8 @@ static int msm_geni_serial_port_setup(struct uart_port *uport)
SE_GENI_RX_PACKING_CFG0);
geni_write_reg_nolog(cfg1, uport->membase,
SE_GENI_RX_PACKING_CFG1);
+ geni_write_reg_nolog(0x431c, uport->membase,
+ SE_GENI_CFG_REG80);
if (!msm_port->rx_fifo) {
ret = -ENOMEM;
goto exit_portsetup;
@@ -2618,7 +2675,10 @@ static void msm_geni_serial_set_termios(struct uart_port *uport,
}
if (!uart_console(uport)) {
- int ret = msm_geni_serial_power_on(uport);
+ int ret;
+
+ IPC_LOG_MSG(port->ipc_log_misc, "%s: start\n", __func__);
+ ret = msm_geni_serial_power_on(uport);
if (ret) {
IPC_LOG_MSG(port->ipc_log_misc,
@@ -3562,6 +3622,7 @@ static int msm_geni_serial_sys_suspend(struct device *dev)
if (uart_console(uport) || port->pm_auto_suspend_disable) {
uart_suspend_port((struct uart_driver *)uport->private_data,
uport);
+ IPC_LOG_MSG(port->console_log, "%s\n", __func__);
} else {
struct uart_state *state = uport->state;
struct tty_port *tty_port = &state->port;
@@ -3593,6 +3654,7 @@ static int msm_geni_serial_sys_resume(struct device *dev)
port->pm_auto_suspend_disable) {
uart_resume_port((struct uart_driver *)uport->private_data,
uport);
+ IPC_LOG_MSG(port->console_log, "%s\n", __func__);
}
return 0;
}
diff --git a/fs/aio.c b/fs/aio.c
index 47bb7b5685ba..51dd01b578c5 100644
--- a/fs/aio.c
+++ b/fs/aio.c
@@ -71,12 +71,6 @@ struct aio_ring {
struct io_event io_events[0];
}; /* 128 bytes + ring size */
-/*
- * Plugging is meant to work with larger batches of IOs. If we don't
- * have more than the below, then don't bother setting up a plug.
- */
-#define AIO_PLUG_THRESHOLD 2
-
#define AIO_RING_PAGES 8
struct kioctx_table {
@@ -1932,8 +1926,7 @@ SYSCALL_DEFINE3(io_submit, aio_context_t, ctx_id, long, nr,
if (nr > ctx->nr_events)
nr = ctx->nr_events;
- if (nr > AIO_PLUG_THRESHOLD)
- blk_start_plug(&plug);
+ blk_start_plug(&plug);
for (i = 0; i < nr; i++) {
struct iocb __user *user_iocb;
@@ -1946,8 +1939,7 @@ SYSCALL_DEFINE3(io_submit, aio_context_t, ctx_id, long, nr,
if (ret)
break;
}
- if (nr > AIO_PLUG_THRESHOLD)
- blk_finish_plug(&plug);
+ blk_finish_plug(&plug);
percpu_ref_put(&ctx->users);
return i ? i : ret;
@@ -1974,8 +1966,7 @@ COMPAT_SYSCALL_DEFINE3(io_submit, compat_aio_context_t, ctx_id,
if (nr > ctx->nr_events)
nr = ctx->nr_events;
- if (nr > AIO_PLUG_THRESHOLD)
- blk_start_plug(&plug);
+ blk_start_plug(&plug);
for (i = 0; i < nr; i++) {
compat_uptr_t user_iocb;
@@ -1988,8 +1979,7 @@ COMPAT_SYSCALL_DEFINE3(io_submit, compat_aio_context_t, ctx_id,
if (ret)
break;
}
- if (nr > AIO_PLUG_THRESHOLD)
- blk_finish_plug(&plug);
+ blk_finish_plug(&plug);
percpu_ref_put(&ctx->users);
return i ? i : ret;
diff --git a/fs/fuse/OWNERS b/fs/fuse/OWNERS
new file mode 100644
index 000000000000..6c04da7a65d5
--- /dev/null
+++ b/fs/fuse/OWNERS
@@ -0,0 +1,2 @@
+# include OWNERS from the authoritative android-mainline branch
+include kernel/common:android-mainline:/fs/fuse/OWNERS
diff --git a/fs/incfs/format.c b/fs/incfs/format.c
index 193cd8f23792..d326415fc6de 100644
--- a/fs/incfs/format.c
+++ b/fs/incfs/format.c
@@ -549,7 +549,6 @@ int incfs_read_file_header(struct backing_file_context *bfc,
if (!bfc || !first_md_off)
return -EFAULT;
- LOCK_REQUIRED(bfc->bc_mutex);
bytes_read = incfs_kread(bfc, &fh, sizeof(fh), 0);
if (bytes_read < 0)
return bytes_read;
diff --git a/fs/incfs/main.c b/fs/incfs/main.c
index 7c4ec4fa13d8..0fde230d5337 100644
--- a/fs/incfs/main.c
+++ b/fs/incfs/main.c
@@ -30,8 +30,18 @@ static ssize_t corefs_show(struct kobject *kobj,
static struct kobj_attribute corefs_attr = __ATTR_RO(corefs);
+static ssize_t mounter_context_for_backing_rw_show(struct kobject *kobj,
+ struct kobj_attribute *attr, char *buff)
+{
+ return snprintf(buff, PAGE_SIZE, "supported\n");
+}
+
+static struct kobj_attribute mounter_context_for_backing_rw_attr =
+ __ATTR_RO(mounter_context_for_backing_rw);
+
static struct attribute *attributes[] = {
&corefs_attr.attr,
+ &mounter_context_for_backing_rw_attr.attr,
NULL,
};
diff --git a/include/dt-bindings/msm/msm-camera.h b/include/dt-bindings/msm/msm-camera.h
index a1eca27a755c..0a5aadce4eb7 100644
--- a/include/dt-bindings/msm/msm-camera.h
+++ b/include/dt-bindings/msm/msm-camera.h
@@ -94,4 +94,9 @@
#define CAM_CPAS_RT_OT_FUSE 9
#define CAM_CPAS_FUSE_FEATURE_MAX 10
+/* Flash type*/
+#define CAM_FLASH_TYPE_GPIO 0
+#define CAM_FLASH_TYPE_I2C 1
+#define CAM_FLASH_TYPE_PMIC 2
+
#endif
diff --git a/include/linux/msm_kgsl.h b/include/linux/msm_kgsl.h
new file mode 100644
index 000000000000..e5950b135dda
--- /dev/null
+++ b/include/linux/msm_kgsl.h
@@ -0,0 +1,52 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (c) 2021, The Linux Foundation. All rights reserved.
+ */
+#ifndef _MSM_KGSL_H
+#define _MSM_KGSL_H
+
+/**
+ * struct kgsl_gpu_freq_stat - Per GPU freq stat struct
+ * @freq: GPU frequency in Hz
+ * @active_time: GPU busy time in usecs
+ * @idle_time: GPU idle time in usec
+ */
+struct kgsl_gpu_freq_stat {
+ u32 freq;
+ u64 active_time;
+ u64 idle_time;
+};
+
+/**
+ * kgsl_gpu_num_freqs - Get number of available GPU frequencies
+ *
+ * Return: number of available frequencies on success or negative error
+ * on failure
+ */
+int kgsl_gpu_num_freqs(void);
+
+/**
+ * kgsl_gpu_stat - Get per GPU freq stats
+ * @stats: Array of struct kgsl_gpu_freq_stat to hold stats
+ * @numfreq: Number of entries in @stats
+ *
+ * This function will populate @stats with per freq stats.
+ * Number of entries in @stats array must be greater or
+ * equal to value returned by function kgsl_gpu_num_freqs
+ *
+ * Return: 0 on success or negative error on failure
+ */
+int kgsl_gpu_stat(struct kgsl_gpu_freq_stat *stats, u32 numfreq);
+
+/**
+ * kgsl_gpu_frame_count - Get number of frames already processed by GPU
+ * @pid: pid of the process for which frame count is required
+ * @frame_count: pointer to a u64 to store frame count
+ *
+ * Return: zero on success and number of frames processed corresponding
+ * to @pid in @frame_count or negative error on failure
+ */
+int kgsl_gpu_frame_count(pid_t pid, u64 *frame_count);
+
+#endif /* _MSM_KGSL_H */
+
diff --git a/include/linux/soc/qcom/sysmon_subsystem_stats.h b/include/linux/soc/qcom/sysmon_subsystem_stats.h
new file mode 100644
index 000000000000..7e8840ef1e9a
--- /dev/null
+++ b/include/linux/soc/qcom/sysmon_subsystem_stats.h
@@ -0,0 +1,62 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (c) 2021, The Linux Foundation. All rights reserved.
+ */
+
+/*
+ * This header is for sysmon subsystem stats query API's in drivers.
+ */
+
+#ifndef __QCOM_SYSMON_SUBSYSTEM_STATS_H__
+#define __QCOM_SYSMON_SUBSYSTEM_STATS_H__
+
+/*
+ * @struct sysmon_smem_power_stats_t
+ * @brief Structure type to hold DSP power statistics.
+ */
+struct sysmon_smem_power_stats {
+ u32 clk_arr[8];
+ /**< Core clock frequency(KHz) array */
+
+ u32 active_time[8];
+ /**< Active time(seconds) array corresponding to core clock array */
+
+ u32 pc_time;
+ /**< DSP LPM(Low Power Mode) time(seconds) */
+
+ u32 lpi_time;
+ /**< DSP LPI(Low Power Island Mode) time(seconds) */
+};
+
+/*
+ * @enum dsp_id_t
+ * @brief Enum to hold SMEM HOST ID for DSP subsystems.
+ */
+enum dsp_id_t {
+ ADSP = 2,
+ SLPI,
+ CDSP = 5
+};
+
+/**
+ * API to query requested DSP subsystem power residency.
+ * On success, returns power residency statistics in the given
+ * sysmon_smem_power_stats structure.
+ * @arg: DSP_ID
+.* 2 - ADSP
+ * 3 - SLPI
+ * 5 - CDSP
+ *sysmon_smem_power_stats
+ * u32 clk_arr[8];
+ * u32 active_time[8];
+ * u32 pc_time;
+ * u32 lpi_time;
+ *@return SUCCESS (0) if Query is succssful
+ * FAILURE (Non-zero) if Query could not be processed.
+ *
+ */
+
+int sysmon_stats_query_power_residency(enum dsp_id_t dsp_id,
+ struct sysmon_smem_power_stats *sysmon_power_stats);
+
+#endif
diff --git a/include/net/cnss2.h b/include/net/cnss2.h
index cbcfac90f960..2cbfd3136d82 100644
--- a/include/net/cnss2.h
+++ b/include/net/cnss2.h
@@ -29,6 +29,7 @@ enum cnss_bus_width_type {
enum cnss_platform_cap_flag {
CNSS_HAS_EXTERNAL_SWREG = 0x01,
CNSS_HAS_UART_ACCESS = 0x02,
+ CNSS_HAS_DRV_SUPPORT = 0x04,
};
struct cnss_platform_cap {
diff --git a/include/net/udp.h b/include/net/udp.h
index e55d5f765807..9ab282cbff20 100644
--- a/include/net/udp.h
+++ b/include/net/udp.h
@@ -171,7 +171,7 @@ struct sk_buff *udp_gro_receive(struct list_head *head, struct sk_buff *skb,
int udp_gro_complete(struct sk_buff *skb, int nhoff, udp_lookup_t lookup);
struct sk_buff *__udp_gso_segment(struct sk_buff *gso_skb,
- netdev_features_t features);
+ netdev_features_t features, bool is_ipv6);
static inline struct udphdr *udp_gro_udphdr(struct sk_buff *skb)
{
diff --git a/include/soc/qcom/cx_ipeak.h b/include/soc/qcom/cx_ipeak.h
new file mode 100644
index 000000000000..e07ac81fe127
--- /dev/null
+++ b/include/soc/qcom/cx_ipeak.h
@@ -0,0 +1,55 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (c) 2018, 2021 The Linux Foundation. All rights reserved.
+ */
+
+#ifndef __SOC_COM_CX_IPEAK_H
+#define __SOC_COM_CX_IPEAK_H
+
+typedef int (*cx_ipeak_victim_fn)(void *data, u32 freq_limit);
+
+struct device_node;
+struct cx_ipeak_client;
+
+#if IS_ENABLED(CONFIG_QCOM_CX_IPEAK)
+
+struct cx_ipeak_client *cx_ipeak_register(struct device_node *dev_node,
+ const char *client_name);
+void cx_ipeak_unregister(struct cx_ipeak_client *client);
+int cx_ipeak_update(struct cx_ipeak_client *ipeak_client, bool vote);
+int cx_ipeak_victim_register(struct cx_ipeak_client *client,
+ cx_ipeak_victim_fn victim_cb, void *data);
+void cx_ipeak_victim_unregister(struct cx_ipeak_client *client);
+
+#else
+
+static inline struct cx_ipeak_client *cx_ipeak_register(
+ struct device_node *dev_node,
+ const char *client_name)
+{
+ return NULL;
+}
+
+static inline void cx_ipeak_unregister(struct cx_ipeak_client *client)
+{
+}
+
+static inline int cx_ipeak_update(struct cx_ipeak_client *ipeak_client,
+ bool vote)
+{
+ return 0;
+}
+
+static inline int cx_ipeak_victim_register(struct cx_ipeak_client *client,
+ cx_ipeak_victim_fn victim_cb, void *data)
+{
+ return 0;
+}
+
+static inline void cx_ipeak_victim_unregister(struct cx_ipeak_client *client)
+{
+}
+
+#endif
+
+#endif /*__SOC_COM_CX_IPEAK_H*/
diff --git a/kernel/.gitignore b/kernel/.gitignore
index 34d1e77ee9df..16670321c138 100644
--- a/kernel/.gitignore
+++ b/kernel/.gitignore
@@ -1,6 +1,7 @@
#
# Generated files
#
+config_data
kheaders.md5
timeconst.h
hz.bc
diff --git a/kernel/Makefile b/kernel/Makefile
index 08652a850458..9e02af6edfd3 100644
--- a/kernel/Makefile
+++ b/kernel/Makefile
@@ -128,10 +128,15 @@ KCOV_INSTRUMENT_stackleak.o := n
$(obj)/configs.o: $(obj)/config_data.gz
-targets += config_data.gz
-$(obj)/config_data.gz: $(KCONFIG_CONFIG) FORCE
+targets += config_data config_data.gz
+$(obj)/config_data.gz: $(obj)/config_data FORCE
$(call if_changed,gzip)
+filechk_cat = cat $<
+
+$(obj)/config_data: $(KCONFIG_CONFIG) FORCE
+ $(call filechk,cat)
+
$(obj)/kheaders.o: $(obj)/kheaders_data.tar.xz
quiet_cmd_genikh = CHK $(obj)/kheaders_data.tar.xz
diff --git a/kernel/sched/core.c b/kernel/sched/core.c
index b3e2892c3c39..5ee5789c14fb 100644
--- a/kernel/sched/core.c
+++ b/kernel/sched/core.c
@@ -3870,6 +3870,9 @@ void scheduler_tick(void)
if (curr->sched_class == &fair_sched_class)
check_for_migration(rq, curr);
+ if (idle_cpu(cpu) && is_reserved(cpu))
+ clear_reserved(cpu);
+
trace_android_vh_scheduler_tick(rq);
}
diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c
index 73caf93f23c0..5959bd691e4a 100644
--- a/kernel/sched/fair.c
+++ b/kernel/sched/fair.c
@@ -6302,22 +6302,22 @@ static int select_idle_cpu(struct task_struct *p, struct sched_domain *sd, int t
static int
select_idle_capacity(struct task_struct *p, struct sched_domain *sd, int target)
{
- unsigned long best_cap = 0;
+ unsigned long task_util, best_cap = 0;
int cpu, best_cpu = -1;
struct cpumask *cpus;
- sync_entity_load_avg(&p->se);
-
cpus = this_cpu_cpumask_var_ptr(select_idle_mask);
cpumask_and(cpus, sched_domain_span(sd), p->cpus_ptr);
+ task_util = uclamp_task_util(p);
+
for_each_cpu_wrap(cpu, cpus, target) {
unsigned long cpu_cap = capacity_of(cpu);
if ((!available_idle_cpu(cpu) && !sched_idle_cpu(cpu)) ||
cpu_isolated(target))
continue;
- if (task_fits_capacity(p, cpu_cap, cpu))
+ if (fits_capacity(task_util, cpu_cap))
return cpu;
if (cpu_cap > best_cap) {
@@ -6329,14 +6329,60 @@ select_idle_capacity(struct task_struct *p, struct sched_domain *sd, int target)
return best_cpu;
}
+static inline bool asym_fits_capacity(int task_util, int cpu)
+{
+ if (static_branch_unlikely(&sched_asym_cpucapacity))
+ return fits_capacity(task_util, capacity_of(cpu));
+
+ return true;
+}
+
/*
* Try and locate an idle core/thread in the LLC cache domain.
*/
static int select_idle_sibling(struct task_struct *p, int prev, int target)
{
struct sched_domain *sd;
+ unsigned long task_util;
int i, recent_used_cpu;
+ /*
+ * On asymmetric system, update task utilization because we will check
+ * that the task fits with cpu's capacity.
+ */
+ if (static_branch_unlikely(&sched_asym_cpucapacity)) {
+ sync_entity_load_avg(&p->se);
+ task_util = uclamp_task_util(p);
+ }
+
+ if ((available_idle_cpu(target) || sched_idle_cpu(target)) &&
+ asym_fits_capacity(task_util, target))
+ return target;
+
+ /*
+ * If the previous CPU is cache affine and idle, don't be stupid:
+ */
+ if (prev != target && cpus_share_cache(prev, target) &&
+ (available_idle_cpu(prev) || sched_idle_cpu(prev)) &&
+ asym_fits_capacity(task_util, prev))
+ return prev;
+
+ /* Check a recently used CPU as a potential idle candidate: */
+ recent_used_cpu = p->recent_used_cpu;
+ if (recent_used_cpu != prev &&
+ recent_used_cpu != target &&
+ cpus_share_cache(recent_used_cpu, target) &&
+ (available_idle_cpu(recent_used_cpu) || sched_idle_cpu(recent_used_cpu)) &&
+ cpumask_test_cpu(p->recent_used_cpu, p->cpus_ptr) &&
+ asym_fits_capacity(task_util, recent_used_cpu)) {
+ /*
+ * Replace recent_used_cpu with prev as it is a potential
+ * candidate for the next wake:
+ */
+ p->recent_used_cpu = prev;
+ return recent_used_cpu;
+ }
+
/*
* For asymmetric CPU capacity systems, our domain of interest is
* sd_asym_cpucapacity rather than sd_llc.
@@ -6351,39 +6397,10 @@ static int select_idle_sibling(struct task_struct *p, int prev, int target)
* SD_ASYM_CPUCAPACITY. These should follow the usual symmetric
* capacity path.
*/
- if (!sd)
- goto symmetric;
-
- i = select_idle_capacity(p, sd, target);
- return ((unsigned)i < nr_cpumask_bits) ? i : target;
- }
-
-symmetric:
- if ((available_idle_cpu(target) || sched_idle_cpu(target)) &&
- !cpu_isolated(target))
- return target;
-
- /*
- * If the previous CPU is cache affine and idle, don't be stupid:
- */
- if (prev != target && cpus_share_cache(prev, target) &&
- ((available_idle_cpu(prev) || sched_idle_cpu(prev)) &&
- !cpu_isolated(prev)))
- return prev;
-
- /* Check a recently used CPU as a potential idle candidate: */
- recent_used_cpu = p->recent_used_cpu;
- if (recent_used_cpu != prev &&
- recent_used_cpu != target &&
- cpus_share_cache(recent_used_cpu, target) &&
- (available_idle_cpu(recent_used_cpu) || sched_idle_cpu(recent_used_cpu)) &&
- cpumask_test_cpu(p->recent_used_cpu, p->cpus_ptr)) {
- /*
- * Replace recent_used_cpu with prev as it is a potential
- * candidate for the next wake:
- */
- p->recent_used_cpu = prev;
- return recent_used_cpu;
+ if (sd) {
+ i = select_idle_capacity(p, sd, target);
+ return ((unsigned)i < nr_cpumask_bits) ? i : target;
+ }
}
sd = rcu_dereference(per_cpu(sd_llc, target));
diff --git a/mm/cma.c b/mm/cma.c
index 24a010f4bb84..8f2c1b0edfa6 100644
--- a/mm/cma.c
+++ b/mm/cma.c
@@ -36,7 +36,6 @@
struct cma cma_areas[MAX_CMA_AREAS];
unsigned cma_area_count;
-static DEFINE_MUTEX(cma_mutex);
phys_addr_t cma_get_base(const struct cma *cma)
{
@@ -508,10 +507,9 @@ struct page *cma_alloc(struct cma *cma, size_t count, unsigned int align,
mutex_unlock(&cma->lock);
pfn = cma->base_pfn + (bitmap_no << cma->order_per_bit);
- mutex_lock(&cma_mutex);
ret = alloc_contig_range(pfn, pfn + count, MIGRATE_CMA,
GFP_KERNEL | (no_warn ? __GFP_NOWARN : 0));
- mutex_unlock(&cma_mutex);
+
if (ret == 0) {
page = pfn_to_page(pfn);
break;
diff --git a/net/core/ethtool.c b/net/core/ethtool.c
index cd9bc67381b2..99ce0ccc66df 100644
--- a/net/core/ethtool.c
+++ b/net/core/ethtool.c
@@ -92,6 +92,7 @@ static const char netdev_features_strings[NETDEV_FEATURE_COUNT][ETH_GSTRING_LEN]
[NETIF_F_GSO_SCTP_BIT] = "tx-sctp-segmentation",
[NETIF_F_GSO_ESP_BIT] = "tx-esp-segmentation",
[NETIF_F_GSO_UDP_L4_BIT] = "tx-udp-segmentation",
+ [NETIF_F_GSO_FRAGLIST_BIT] = "tx-gso-list",
[NETIF_F_FCOE_CRC_BIT] = "tx-checksum-fcoe-crc",
[NETIF_F_SCTP_CRC_BIT] = "tx-checksum-sctp",
diff --git a/net/core/skbuff.c b/net/core/skbuff.c
index b87b6334f689..edc9be5aa823 100644
--- a/net/core/skbuff.c
+++ b/net/core/skbuff.c
@@ -3649,7 +3649,8 @@ struct sk_buff *skb_segment_list(struct sk_buff *skb,
unsigned int delta_truesize = 0;
unsigned int delta_len = 0;
struct sk_buff *tail = NULL;
- struct sk_buff *nskb;
+ struct sk_buff *nskb, *tmp;
+ int err;
skb_push(skb, -skb_network_offset(skb) + offset);
@@ -3659,11 +3660,28 @@ struct sk_buff *skb_segment_list(struct sk_buff *skb,
nskb = list_skb;
list_skb = list_skb->next;
+ err = 0;
+ if (skb_shared(nskb)) {
+ tmp = skb_clone(nskb, GFP_ATOMIC);
+ if (tmp) {
+ consume_skb(nskb);
+ nskb = tmp;
+ err = skb_unclone(nskb, GFP_ATOMIC);
+ } else {
+ err = -ENOMEM;
+ }
+ }
+
if (!tail)
skb->next = nskb;
else
tail->next = nskb;
+ if (unlikely(err)) {
+ nskb->next = list_skb;
+ goto err_linearize;
+ }
+
tail = nskb;
delta_len += nskb->len;
diff --git a/net/ipv4/udp_offload.c b/net/ipv4/udp_offload.c
index 9298b0ebc4ff..fd60e5cd1519 100644
--- a/net/ipv4/udp_offload.c
+++ b/net/ipv4/udp_offload.c
@@ -184,8 +184,67 @@ out_unlock:
}
EXPORT_SYMBOL(skb_udp_tunnel_segment);
+static void __udpv4_gso_segment_csum(struct sk_buff *seg,
+ __be32 *oldip, __be32 *newip,
+ __be16 *oldport, __be16 *newport)
+{
+ struct udphdr *uh;
+ struct iphdr *iph;
+
+ if (*oldip == *newip && *oldport == *newport)
+ return;
+
+ uh = udp_hdr(seg);
+ iph = ip_hdr(seg);
+
+ if (uh->check) {
+ inet_proto_csum_replace4(&uh->check, seg, *oldip, *newip,
+ true);
+ inet_proto_csum_replace2(&uh->check, seg, *oldport, *newport,
+ false);
+ if (!uh->check)
+ uh->check = CSUM_MANGLED_0;
+ }
+ *oldport = *newport;
+
+ csum_replace4(&iph->check, *oldip, *newip);
+ *oldip = *newip;
+}
+
+static struct sk_buff *__udpv4_gso_segment_list_csum(struct sk_buff *segs)
+{
+ struct sk_buff *seg;
+ struct udphdr *uh, *uh2;
+ struct iphdr *iph, *iph2;
+
+ seg = segs;
+ uh = udp_hdr(seg);
+ iph = ip_hdr(seg);
+
+ if ((udp_hdr(seg)->dest == udp_hdr(seg->next)->dest) &&
+ (udp_hdr(seg)->source == udp_hdr(seg->next)->source) &&
+ (ip_hdr(seg)->daddr == ip_hdr(seg->next)->daddr) &&
+ (ip_hdr(seg)->saddr == ip_hdr(seg->next)->saddr))
+ return segs;
+
+ while ((seg = seg->next)) {
+ uh2 = udp_hdr(seg);
+ iph2 = ip_hdr(seg);
+
+ __udpv4_gso_segment_csum(seg,
+ &iph2->saddr, &iph->saddr,
+ &uh2->source, &uh->source);
+ __udpv4_gso_segment_csum(seg,
+ &iph2->daddr, &iph->daddr,
+ &uh2->dest, &uh->dest);
+ }
+
+ return segs;
+}
+
static struct sk_buff *__udp_gso_segment_list(struct sk_buff *skb,
- netdev_features_t features)
+ netdev_features_t features,
+ bool is_ipv6)
{
unsigned int mss = skb_shinfo(skb)->gso_size;
@@ -195,11 +254,11 @@ static struct sk_buff *__udp_gso_segment_list(struct sk_buff *skb,
udp_hdr(skb)->len = htons(sizeof(struct udphdr) + mss);
- return skb;
+ return is_ipv6 ? skb : __udpv4_gso_segment_list_csum(skb);
}
struct sk_buff *__udp_gso_segment(struct sk_buff *gso_skb,
- netdev_features_t features)
+ netdev_features_t features, bool is_ipv6)
{
struct sock *sk = gso_skb->sk;
unsigned int sum_truesize = 0;
@@ -211,7 +270,7 @@ struct sk_buff *__udp_gso_segment(struct sk_buff *gso_skb,
__be16 newlen;
if (skb_shinfo(gso_skb)->gso_type & SKB_GSO_FRAGLIST)
- return __udp_gso_segment_list(gso_skb, features);
+ return __udp_gso_segment_list(gso_skb, features, is_ipv6);
mss = skb_shinfo(gso_skb)->gso_size;
if (gso_skb->len <= sizeof(*uh) + mss)
@@ -325,7 +384,7 @@ static struct sk_buff *udp4_ufo_fragment(struct sk_buff *skb,
goto out;
if (skb_shinfo(skb)->gso_type & SKB_GSO_UDP_L4)
- return __udp_gso_segment(skb, features);
+ return __udp_gso_segment(skb, features, false);
mss = skb_shinfo(skb)->gso_size;
if (unlikely(skb->len <= mss))
diff --git a/net/ipv6/udp_offload.c b/net/ipv6/udp_offload.c
index 7a46bd33fa2f..6e06c90fa318 100644
--- a/net/ipv6/udp_offload.c
+++ b/net/ipv6/udp_offload.c
@@ -46,7 +46,7 @@ static struct sk_buff *udp6_ufo_fragment(struct sk_buff *skb,
goto out;
if (skb_shinfo(skb)->gso_type & SKB_GSO_UDP_L4)
- return __udp_gso_segment(skb, features);
+ return __udp_gso_segment(skb, features, true);
/* Do software UFO. Complete and fill in the UDP checksum as HW cannot
* do checksum of UDP packets sent as multiple IP fragments.
diff --git a/net/xfrm/xfrm_compat.c b/net/xfrm/xfrm_compat.c
index c1dee0696dfb..aacbf250a25e 100644
--- a/net/xfrm/xfrm_compat.c
+++ b/net/xfrm/xfrm_compat.c
@@ -234,6 +234,7 @@ static int xfrm_xlate64_attr(struct sk_buff *dst, const struct nlattr *src)
case XFRMA_PAD:
/* Ignore */
return 0;
+ case XFRMA_UNSPEC:
case XFRMA_ALG_AUTH:
case XFRMA_ALG_CRYPT:
case XFRMA_ALG_COMP:
@@ -387,7 +388,7 @@ static int xfrm_attr_cpy32(void *dst, size_t *pos, const struct nlattr *src,
memcpy(nla, src, nla_attr_size(copy_len));
nla->nla_len = nla_attr_size(payload);
- *pos += nla_attr_size(payload);
+ *pos += nla_attr_size(copy_len);
nlmsg->nlmsg_len += nla->nla_len;
memset(dst + *pos, 0, payload - copy_len);
@@ -563,7 +564,7 @@ static struct nlmsghdr *xfrm_user_rcv_msg_compat(const struct nlmsghdr *h32,
return NULL;
len += NLMSG_HDRLEN;
- h64 = kvmalloc(len, GFP_KERNEL | __GFP_ZERO);
+ h64 = kvmalloc(len, GFP_KERNEL);
if (!h64)
return ERR_PTR(-ENOMEM);
diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c
index 83a8cbf2a37a..8bb052bb137e 100644
--- a/net/xfrm/xfrm_state.c
+++ b/net/xfrm/xfrm_state.c
@@ -2381,8 +2381,10 @@ int xfrm_user_policy(struct sock *sk, int optname, u8 __user *optval, int optlen
if (in_compat_syscall()) {
struct xfrm_translator *xtr = xfrm_get_translator();
- if (!xtr)
+ if (!xtr) {
+ kfree(data);
return -EOPNOTSUPP;
+ }
err = xtr->xlate_user_policy_sockptr(&data, optlen);
xfrm_put_translator(xtr);
diff --git a/scripts/adjust_autoksyms.sh b/scripts/adjust_autoksyms.sh
index 7028a5a56d66..d8997d4f9273 100755
--- a/scripts/adjust_autoksyms.sh
+++ b/scripts/adjust_autoksyms.sh
@@ -34,9 +34,6 @@ case "$KBUILD_VERBOSE" in
;;
esac
-# We need access to CONFIG_ symbols
-. include/config/auto.conf
-
# Generate a new symbol list file
$CONFIG_SHELL $srctree/scripts/gen_autoksyms.sh "$new_ksyms_file"