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"