diff --git a/.gitignore b/.gitignore index 794a4014b840..72378676d52e 100644 --- a/.gitignore +++ b/.gitignore @@ -125,7 +125,6 @@ GTAGS # id-utils files ID -*.orig *~ \#*# diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt index cd592f5248e6..ad50049a2131 100644 --- a/Documentation/admin-guide/kernel-parameters.txt +++ b/Documentation/admin-guide/kernel-parameters.txt @@ -4165,6 +4165,16 @@ printk.time= Show timing data prefixed to each printk message line Format: (1/Y/y=enable, 0/N/n=disable) + proc_mem.force_override= [KNL] + Format: {always | ptrace | never} + Traditionally /proc/pid/mem allows memory permissions to be + overridden without restrictions. This option may be set to + restrict that. Can be one of: + - 'always': traditional behavior always allows mem overrides. + - 'ptrace': only allow mem overrides for active ptracers. + - 'never': never allow mem overrides. + If not specified, default is the CONFIG_PROC_MEM_* choice. + processor.max_cstate= [HW,ACPI] Limit processor to maximum C-state max_cstate=9 overrides any DMI blacklist limit. diff --git a/Documentation/arm64/silicon-errata.rst b/Documentation/arm64/silicon-errata.rst index b0b0ac52ecc4..4898ecf547c1 100644 --- a/Documentation/arm64/silicon-errata.rst +++ b/Documentation/arm64/silicon-errata.rst @@ -112,6 +112,8 @@ stable kernels. +----------------+-----------------+-----------------+-----------------------------+ | ARM | Cortex-A710 | #3324338 | ARM64_ERRATUM_3194386 | +----------------+-----------------+-----------------+-----------------------------+ +| ARM | Cortex-A715 | #3456084 | ARM64_ERRATUM_3194386 | ++----------------+-----------------+-----------------+-----------------------------+ | ARM | Cortex-A720 | #3456091 | ARM64_ERRATUM_3194386 | +----------------+-----------------+-----------------+-----------------------------+ | ARM | Cortex-A725 | #3456106 | ARM64_ERRATUM_3194386 | @@ -140,6 +142,8 @@ stable kernels. +----------------+-----------------+-----------------+-----------------------------+ | ARM | Neoverse-N2 | #3324339 | ARM64_ERRATUM_3194386 | +----------------+-----------------+-----------------+-----------------------------+ +| ARM | Neoverse-N3 | #3456111 | ARM64_ERRATUM_3194386 | ++----------------+-----------------+-----------------+-----------------------------+ | ARM | Neoverse-V1 | #3324341 | ARM64_ERRATUM_3194386 | +----------------+-----------------+-----------------+-----------------------------+ | ARM | Neoverse-V2 | #3324336 | ARM64_ERRATUM_3194386 | diff --git a/Documentation/driver-api/ipmi.rst b/Documentation/driver-api/ipmi.rst index bc281f10ce4b..0bfeeeeb17c8 100644 --- a/Documentation/driver-api/ipmi.rst +++ b/Documentation/driver-api/ipmi.rst @@ -519,7 +519,7 @@ at module load time (for a module) with:: alerts_broken The addresses are normal I2C addresses. The adapter is the string -name of the adapter, as shown in /sys/class/i2c-adapter/i2c-/name. +name of the adapter, as shown in /sys/bus/i2c/devices/i2c-/name. It is *NOT* i2c- itself. Also, the comparison is done ignoring spaces, so if the name is "This is an I2C chip" you can say adapter_name=ThisisanI2cchip. This is because it's hard to pass in diff --git a/Makefile b/Makefile index 6603e04c5ff0..0cc517013c06 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ # SPDX-License-Identifier: GPL-2.0 VERSION = 5 PATCHLEVEL = 10 -SUBLEVEL = 226 +SUBLEVEL = 228 EXTRAVERSION = NAME = Dare mighty things diff --git a/android/abi_gki_aarch64.xml b/android/abi_gki_aarch64.xml index 86f118c8f763..7d86b22d013b 100755 --- a/android/abi_gki_aarch64.xml +++ b/android/abi_gki_aarch64.xml @@ -235,6 +235,7 @@ + @@ -580,6 +581,7 @@ + @@ -932,6 +934,7 @@ + @@ -988,6 +991,7 @@ + @@ -4459,6 +4463,7 @@ + @@ -6758,6 +6763,7 @@ + @@ -7205,6 +7211,8 @@ + + @@ -15665,89 +15673,6 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -22762,7 +22687,7 @@ - + @@ -25759,66 +25684,66 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -26807,27 +26732,27 @@ - + - + - + - + - + - + - + - + @@ -28192,21 +28117,21 @@ - + - + - + - + - + - + @@ -35026,24 +34951,24 @@ - + - + - + - + - + - + - + @@ -47347,21 +47272,21 @@ - + - + - + - + - + - + @@ -69214,14 +69139,7 @@ - - - - - - - - + @@ -90613,711 +90531,711 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -94617,7 +94535,6 @@ - @@ -117456,15 +117373,15 @@ - - - - - - - - - + + + + + + + + + @@ -117612,9 +117529,9 @@ - - - + + + @@ -117704,10 +117621,10 @@ - - - - + + + + @@ -117826,21 +117743,21 @@ - - - - + + + + - - - - + + + + - - - + + + @@ -117958,8 +117875,8 @@ - - + + @@ -118012,9 +117929,9 @@ - - - + + + @@ -118077,9 +117994,9 @@ - - - + + + @@ -118182,9 +118099,9 @@ - - - + + + @@ -118209,13 +118126,13 @@ - - - - - - - + + + + + + + @@ -118661,6 +118578,11 @@ + + + + + @@ -118748,8 +118670,8 @@ - - + + @@ -118788,10 +118710,10 @@ - - - - + + + + @@ -120490,10 +120412,10 @@ - - - - + + + + @@ -120518,12 +120440,12 @@ - - - - - - + + + + + + @@ -120542,9 +120464,9 @@ - - - + + + @@ -120857,6 +120779,15 @@ + + + + + + + + + @@ -121596,9 +121527,9 @@ - - - + + + @@ -121993,10 +121924,10 @@ - - - - + + + + @@ -122724,15 +122655,15 @@ - + - + - + @@ -122781,6 +122712,7 @@ + @@ -122904,7 +122836,7 @@ - + @@ -122966,7 +122898,7 @@ - + @@ -123314,45 +123246,45 @@ - - - + + + - - - - - - - - - - - - - - - - - - - - - - - - - + - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -123502,22 +123434,29 @@ - - - - - - + + + + + + + + + + + + + - - - - + + + + @@ -123581,9 +123520,9 @@ - - - + + + @@ -123811,6 +123750,10 @@ + + + + @@ -123868,8 +123811,8 @@ - - + + @@ -124797,15 +124740,15 @@ - - - + + + - - - - + + + + @@ -124949,8 +124892,8 @@ - - + + @@ -125352,10 +125295,10 @@ - - - - + + + + @@ -125415,8 +125358,8 @@ - - + + @@ -125977,8 +125920,8 @@ - - + + @@ -126272,9 +126215,9 @@ - - - + + + @@ -126806,8 +126749,8 @@ - - + + @@ -126914,10 +126857,10 @@ - - - - + + + + @@ -127114,11 +127057,11 @@ - - - - - + + + + + @@ -127210,14 +127153,14 @@ - - + + - - - - + + + + @@ -127587,17 +127530,17 @@ - - - - + + + + - - - - + + + + @@ -127616,9 +127559,9 @@ - - - + + + @@ -127636,11 +127579,11 @@ - - - - - + + + + + @@ -127745,8 +127688,8 @@ - - + + @@ -127755,9 +127698,9 @@ - - - + + + @@ -127768,54 +127711,54 @@ - - - - - - + + + + + + - - - + + + - - - + + + - - - - - - - + + + + + + + - - + + - - - + + + - - - - + + + + - - - - + + + + @@ -127855,38 +127798,38 @@ - - + + - - - - + + + + - - + + - - - + + + - - - + + + - - - + + + - - - + + + @@ -127932,42 +127875,42 @@ - - + + - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + @@ -127980,34 +127923,34 @@ - - - - + + + + - - - - + + + + - - - - - + + + + + - - - - - + + + + + - - + + @@ -128018,10 +127961,10 @@ - - - - + + + + @@ -128136,19 +128079,19 @@ - - - + + + - - - + + + - - - + + + @@ -128190,9 +128133,9 @@ - - - + + + @@ -128223,10 +128166,10 @@ - - - - + + + + @@ -128385,55 +128328,55 @@ - - - - + + + + - - - + + + - - - - + + + + - - - - - + + + + + - - - - - + + + + + - - - - + + + + - - - - + + + + - - - - - + + + + + @@ -128448,15 +128391,15 @@ - - - - + + + + - - - + + + @@ -128586,17 +128529,17 @@ - - - - + + + + - - - - - + + + + + @@ -128726,10 +128669,10 @@ - - - - + + + + @@ -129611,131 +129554,131 @@ - - + + - - - + + + - - - + + + - - - - + + + + - - + + - - - + + + - - + + - - - - + + + + - - - - + + + + - - - + + + - - - + + + - - + + - - + + - - - - - + + + + + - - - + + + - - - - - + + + + + - - - - - + + + + + - - - + + + - - - - + + + + - - - - + + + + - - - + + + @@ -130265,8 +130208,8 @@ - - + + @@ -132539,9 +132482,9 @@ - - - + + + @@ -132593,11 +132536,11 @@ - - - - - + + + + + @@ -132629,8 +132572,8 @@ - - + + @@ -132723,13 +132666,13 @@ - - - + + + - - + + @@ -132759,12 +132702,12 @@ - - + + - - + + @@ -132836,11 +132779,11 @@ - - - - - + + + + + @@ -132966,10 +132909,10 @@ - - - - + + + + @@ -133053,8 +132996,8 @@ - - + + @@ -133300,34 +133243,34 @@ - - - - - - + + + + + + - - - + + + - - - + + + - - + + @@ -133375,8 +133318,8 @@ - - + + @@ -133607,8 +133550,8 @@ - - + + @@ -133683,8 +133626,8 @@ - - + + @@ -133827,8 +133770,8 @@ - - + + @@ -133881,7 +133824,7 @@ - + @@ -133962,9 +133905,9 @@ - - - + + + @@ -133975,8 +133918,8 @@ - - + + @@ -134353,8 +134296,8 @@ - - + + @@ -134591,12 +134534,12 @@ - - + + - - + + @@ -134605,22 +134548,22 @@ - - - - + + + + - - - - + + + + - - - + + + @@ -134630,8 +134573,8 @@ - - + + @@ -135167,26 +135110,26 @@ - - - - - - + + + + + + - - - + + + - - + + @@ -135357,16 +135300,16 @@ - - - + + + - - - - - + + + + + @@ -135455,10 +135398,10 @@ - - - - + + + + @@ -135480,18 +135423,18 @@ - - + + - - - - + + + + @@ -135499,12 +135442,12 @@ - - + + - - + + @@ -135512,10 +135455,10 @@ - - - - + + + + @@ -135555,20 +135498,20 @@ - - - - - - + + + + + + - - + + - - + + @@ -135577,24 +135520,24 @@ - - - + + + - - - + + + - - - - + + + + - - + + @@ -135655,8 +135598,8 @@ - - + + @@ -135700,11 +135643,11 @@ - + - - + + @@ -136045,8 +135988,8 @@ - - + + @@ -136443,22 +136386,22 @@ - - - - - + + + + + - - - - + + + + - - - + + + @@ -136565,7 +136508,7 @@ - + @@ -136610,9 +136553,9 @@ - - - + + + @@ -136689,12 +136632,12 @@ - - + + - - + + @@ -136703,8 +136646,8 @@ - - + + @@ -136854,15 +136797,15 @@ - - - + + + - - - - + + + + @@ -136895,14 +136838,14 @@ - - - - + + + + - - + + @@ -137232,14 +137175,14 @@ - - - - + + + + - - + + @@ -137707,8 +137650,8 @@ - - + + @@ -137746,7 +137689,7 @@ - + @@ -137895,11 +137838,11 @@ - - - - - + + + + + @@ -138493,12 +138436,12 @@ - - - - - - + + + + + + @@ -138676,9 +138619,9 @@ - - - + + + @@ -138797,11 +138740,11 @@ - - - - - + + + + + @@ -138826,8 +138769,8 @@ - - + + @@ -138837,12 +138780,12 @@ - - + + - - + + @@ -139552,14 +139495,14 @@ - - - + + + - - - + + + @@ -139568,10 +139511,10 @@ - - - - + + + + @@ -140198,8 +140141,8 @@ - - + + @@ -140233,8 +140176,8 @@ - - + + @@ -140585,8 +140528,8 @@ - - + + @@ -140607,9 +140550,9 @@ - - - + + + @@ -140697,11 +140640,11 @@ - - - - - + + + + + @@ -140723,17 +140666,17 @@ - - + + - - + + - - - + + + @@ -140817,12 +140760,12 @@ - - - - - - + + + + + + @@ -140866,20 +140809,20 @@ - - - - + + + + - - - - + + + + - - + + @@ -140888,15 +140831,15 @@ - - - - - - - - - + + + + + + + + + @@ -141418,8 +141361,8 @@ - - + + @@ -141497,10 +141440,10 @@ - - - - + + + + @@ -141517,8 +141460,8 @@ - - + + @@ -141876,6 +141819,10 @@ + + + + @@ -142012,10 +141959,10 @@ - + - + @@ -142248,8 +142195,8 @@ - - + + @@ -142281,8 +142228,8 @@ - - + + @@ -142796,13 +142743,13 @@ - - - + + + - - + + @@ -143237,12 +143184,12 @@ - - - - - - + + + + + + @@ -143519,7 +143466,7 @@ - + @@ -143773,24 +143720,24 @@ - - + + - - + + - - + + - - + + - - + + @@ -143802,9 +143749,9 @@ - - - + + + @@ -143812,9 +143759,9 @@ - - - + + + @@ -143835,10 +143782,10 @@ - - - - + + + + @@ -144008,86 +143955,86 @@ - - + + - - + + - - - + + + - - - + + + - - - + + + - - - - + + + + - - - - + + + + - - + + - - + + - - + + - - - - + + + + - - + + - - + + - - + + - - + + - - + + - - + + - - - + + + @@ -144886,9 +144833,9 @@ - - - + + + @@ -144918,9 +144865,9 @@ - - - + + + @@ -144928,9 +144875,9 @@ - - - + + + @@ -145159,10 +145106,10 @@ - - - - + + + + @@ -146262,19 +146209,19 @@ - - - + + + - - - + + + - - - + + + @@ -146282,14 +146229,14 @@ - - - + + + - - - + + + @@ -146297,9 +146244,9 @@ - - - + + + @@ -146312,9 +146259,9 @@ - - - + + + @@ -146643,16 +146590,16 @@ - - - - - + + + + + - - - + + + @@ -147583,7 +147530,7 @@ - + @@ -147594,8 +147541,8 @@ - - + + @@ -147762,8 +147709,8 @@ - - + + @@ -147860,10 +147807,10 @@ - - - - + + + + @@ -147910,9 +147857,9 @@ - - - + + + @@ -147923,8 +147870,8 @@ - - + + @@ -147941,8 +147888,8 @@ - - + + @@ -148127,9 +148074,9 @@ - - - + + + @@ -148681,21 +148628,21 @@ - - - + + + - - - + + + - - - - - + + + + + @@ -148711,71 +148658,71 @@ - - + + - - - + + + - - - + + + - - - - - - + + + + + + - - - - - - + + + + + + - - + + - - - + + + - - - + + + - - - - - - - + + + + + + + - - - + + + - - - + + + - - + + @@ -148788,9 +148735,9 @@ - - - + + + @@ -148838,32 +148785,32 @@ - - - + + + - - - + + + - - - + + + - - + + - - - + + + - - + + @@ -148871,19 +148818,19 @@ - - - - - + + + + + - - - - - - + + + + + + @@ -148893,17 +148840,17 @@ - - + + - - + + - - - + + + @@ -148916,12 +148863,12 @@ - - + + - - + + @@ -148929,12 +148876,12 @@ - - + + - - + + @@ -149029,39 +148976,39 @@ - - - + + + - - + + - - + + - - + + - - + + - - + + - - + + - - - - + + + + @@ -149076,19 +149023,19 @@ - - + + - - - - - + + + + + @@ -149219,8 +149166,8 @@ - - + + @@ -149270,13 +149217,13 @@ - - + + - - - + + + @@ -149378,6 +149325,8 @@ + + @@ -149445,8 +149394,8 @@ - - + + @@ -149493,9 +149442,9 @@ - - - + + + @@ -149503,44 +149452,44 @@ - - + + - - - + + + - - + + - - + + - - + + - - - + + + - - - - + + + + - - + + @@ -149584,80 +149533,80 @@ - - + + - - + + - - - + + + - - - - + + + + - - - - + + + + - - + + - - + + - - - + + + - - - + + + - - - - + + + + - - - - + + + + - - + + - - + + - - + + - - - + + + - - + + @@ -149680,7 +149629,7 @@ - + @@ -149800,10 +149749,10 @@ - - - - + + + + @@ -150014,9 +149963,9 @@ - - - + + + @@ -150054,18 +150003,18 @@ - - - + + + - - - + + + - - + + @@ -150073,147 +150022,147 @@ - - - + + + - - - + + + - - + + - - - + + + - - + + - - - + + + - - - - + + + + - - + + - - + + - - - + + + - - - - - - - - + + + + + + + + - - - - - - - - + + + + + + + + - - + + - - - + + + - - - + + + - - - + + + - - - + + + - - + + - - - + + + - - - + + + - - + + - - + + - - - - - - - - + + + + + + + + - - - - - - - - + + + + + + + + - - - - - - - - + + + + + + + + @@ -151121,16 +151070,16 @@ - - - - + + + + - - - - + + + + @@ -151470,22 +151419,22 @@ - - - - + + + + - - - - + + + + - - - - + + + + @@ -151556,23 +151505,23 @@ - - - - + + + + - - - - + + + + - - - - - + + + + + @@ -151759,12 +151708,12 @@ - - + + - - + + @@ -151936,47 +151885,47 @@ - - + + - + - - - - + + + + - - + + - - + + - - - - + + + + - - - - + + + + - - + + - - - - + + + + @@ -152016,9 +151965,9 @@ - - - + + + @@ -152067,9 +152016,9 @@ - - - + + + @@ -152091,9 +152040,9 @@ - - - + + + @@ -152168,8 +152117,8 @@ - - + + diff --git a/android/abi_gki_aarch64.xml.allowed_breaks b/android/abi_gki_aarch64.xml.allowed_breaks new file mode 100644 index 000000000000..ec5854913f72 --- /dev/null +++ b/android/abi_gki_aarch64.xml.allowed_breaks @@ -0,0 +1,127 @@ +# How to use this file: http://go/approve-abi-break +# ABI freeze commit: 870488eb0745645feff5bddfd44fe538660b9cf8 + +type 'struct xhci_hcd' changed + member 'u64 android_kabi_reserved1' was removed + member 'union { struct xhci_vendor_ops* vendor_ops; struct { u64 android_kabi_reserved1; }; union { }; }' was added + +type 'struct xhci_hcd' changed + member changed from 'union { struct xhci_vendor_ops* vendor_ops; struct { u64 android_kabi_reserved1; } __UNIQUE_ID_android_kabi_hide315; union { }; }' to 'union { struct xhci_vendor_ops* vendor_ops; struct { u64 android_kabi_reserved1; }; union { }; }' + type changed from 'union { struct xhci_vendor_ops* vendor_ops; struct { u64 android_kabi_reserved1; } __UNIQUE_ID_android_kabi_hide315; union { }; }' to 'union { struct xhci_vendor_ops* vendor_ops; struct { u64 android_kabi_reserved1; }; union { }; }' + member 'struct { u64 android_kabi_reserved1; } __UNIQUE_ID_android_kabi_hide315' was removed + member 'struct { u64 android_kabi_reserved1; }' was added + +type 'struct spi_controller' changed + member changed from 'u8 unused_native_cs' to 's8 unused_native_cs' + type changed from 'u8' = '__u8' = 'unsigned char' to 's8' = '__s8' = 'signed char' + resolved type changed from 'unsigned char' to 'signed char' + member changed from 'u8 max_native_cs' to 's8 max_native_cs' + type changed from 'u8' = '__u8' = 'unsigned char' to 's8' = '__s8' = 'signed char' + resolved type changed from 'unsigned char' to 'signed char' + +type 'struct xhci_hcd' changed + member changed from 'union { struct xhci_vendor_ops* vendor_ops; struct { u64 android_kabi_reserved1; } __UNIQUE_ID_android_kabi_hide316; union { }; }' to 'union { struct xhci_vendor_ops* vendor_ops; struct { u64 android_kabi_reserved1; }; union { }; }' + type changed from 'union { struct xhci_vendor_ops* vendor_ops; struct { u64 android_kabi_reserved1; } __UNIQUE_ID_android_kabi_hide316; union { }; }' to 'union { struct xhci_vendor_ops* vendor_ops; struct { u64 android_kabi_reserved1; }; union { }; }' + member 'struct { u64 android_kabi_reserved1; } __UNIQUE_ID_android_kabi_hide316' was removed + member 'struct { u64 android_kabi_reserved1; }' was added + +type 'struct ehci_hcd' changed + member 'unsigned int is_aspeed' was added + +type 'struct fscrypt_mode' changed + byte size changed from 32 to 40 + member 'int security_strength' was added + 3 members ('int ivsize' .. 'enum blk_crypto_mode_num blk_crypto_mode') changed + offset changed by 32 + +type 'struct sock' changed + member 'u64 android_kabi_reserved1' was removed + member 'union { spinlock_t sk_peer_lock; struct { u64 android_kabi_reserved1; }; union { }; }' was added + +type 'struct bpf_map' changed + member changed from 'u64 writecnt' to 'atomic64_t writecnt' + type changed from 'u64' = '__u64' = 'long long unsigned int' to 'atomic64_t' = 'struct { s64 counter; }' + resolved type changed from 'long long unsigned int' to 'struct { s64 counter; }' + +type 'struct fib_rules_ops' changed + member changed from 'bool(* suppress)(struct fib_rule*, struct fib_lookup_arg*)' to 'bool(* suppress)(struct fib_rule*, int, struct fib_lookup_arg*)' + type changed from 'bool(*)(struct fib_rule*, struct fib_lookup_arg*)' to 'bool(*)(struct fib_rule*, int, struct fib_lookup_arg*)' + pointed-to type changed from 'bool(struct fib_rule*, struct fib_lookup_arg*)' to 'bool(struct fib_rule*, int, struct fib_lookup_arg*)' + parameter 2 type changed from 'struct fib_lookup_arg*' to 'int' + parameter 3 of type 'struct fib_lookup_arg*' was added + +type 'struct snd_pcm_runtime' changed + byte size changed from 768 to 824 + member 'struct mutex buffer_mutex' was added + member 'atomic_t buffer_accessing' was added + +type 'struct gpio_irq_chip' changed + member 'u64 android_kabi_reserved1' was removed + member 'union { bool initialized; struct { u64 android_kabi_reserved1; }; union { }; }' was added + +function symbol changed from 'int hex_to_bin(char)' to 'int hex_to_bin(unsigned char)' + type changed from 'int(char)' to 'int(unsigned char)' + parameter 1 type changed from 'char' to 'unsigned char' + +1 variable symbol(s) removed + 'struct tracepoint __tracepoint_android_vh_record_percpu_rwsem_lock_starttime' + +1 function symbol(s) removed + 'int __traceiter_android_vh_record_percpu_rwsem_lock_starttime(void*, struct task_struct*, unsigned long int)' + +type 'struct fscrypt_info' changed + member changed from 'struct key* ci_master_key' to 'struct fscrypt_master_key* ci_master_key' + type changed from 'struct key*' to 'struct fscrypt_master_key*' + pointed-to type changed from 'struct key' to 'struct fscrypt_master_key' + +type 'struct tcp_sock' changed + member 'u32 max_packets_seq' was removed + member 'u32 cwnd_usage_seq' was added + +type 'struct iphdr' changed + member '__be32 saddr' was removed + member '__be32 daddr' was removed + member 'union { struct { __be32 saddr; __be32 daddr; }; struct { __be32 saddr; __be32 daddr; } addrs; }' was added + +type 'struct super_block' changed + member changed from 'struct key* s_master_keys' to 'struct fscrypt_keyring* s_master_keys' + type changed from 'struct key*' to 'struct fscrypt_keyring*' + pointed-to type changed from 'struct key' to 'struct fscrypt_keyring' + +type 'struct sk_buff' changed + member 'u64 android_kabi_reserved1' was removed + member 'union { struct { __u8 scm_io_uring; __u8 android_kabi_reserved1_padding1; __u16 android_kabi_reserved1_padding2; __u32 android_kabi_reserved1_padding3; }; struct { u64 android_kabi_reserved1; }; union { }; }' was added + +type 'struct task_struct' changed + member 'u64 android_kabi_reserved1' was removed + member 'union { void* pf_io_worker; struct { u64 android_kabi_reserved1; }; union { }; }' was added + +type 'struct anon_vma' changed + byte size changed from 104 to 120 + member 'unsigned long int num_children' was added + member 'unsigned long int num_active_vmas' was added + +function symbol changed from 'struct irq_domain* __irq_domain_add(struct fwnode_handle*, int, irq_hw_number_t, int, const struct irq_domain_ops*, void*)' to 'struct irq_domain* __irq_domain_add(struct fwnode_handle*, unsigned int, irq_hw_number_t, int, const struct irq_domain_ops*, void*)' + type changed from 'struct irq_domain*(struct fwnode_handle*, int, irq_hw_number_t, int, const struct irq_domain_ops*, void*)' to 'struct irq_domain*(struct fwnode_handle*, unsigned int, irq_hw_number_t, int, const struct irq_domain_ops*, void*)' + parameter 2 type changed from 'int' to 'unsigned int' + +function symbol changed from 'is_ashmem_file' to 'int is_ashmem_file(struct file*)' + CRC changed from 0x4bef6e5f to 0x94fc40b5 + +type 'struct perf_event' changed + member 'unsigned int group_generation' was added + +type 'struct ipv6_devconf' changed + member 'u64 android_kabi_reserved1' was removed + member 'union { struct { __s32 accept_ra_min_lft; u32 padding; }; struct { u64 android_kabi_reserved1; }; union { }; }' was added + +type 'struct clk_core' changed + byte size changed from 248 to 264 + member 'struct hlist_node rpm_node' was added + 30 members ('struct device_node* of_node' .. 'struct kref ref') changed + offset changed by 128 + +type 'enum binder_work_type' changed + enumerator 'BINDER_WORK_FROZEN_BINDER' (9) was added + ... 1 other enumerator(s) added + diff --git a/android/abi_gki_aarch64_honor b/android/abi_gki_aarch64_honor index ddd1a800c132..2b8846775837 100644 --- a/android/abi_gki_aarch64_honor +++ b/android/abi_gki_aarch64_honor @@ -1,7 +1,13 @@ [abi_symbol_list] + arch_vma_name + _vm_normal_page + pmd_clear_bad + __pmd_trans_huge_lock __traceiter_android_rvh_dma_buf_stats_teardown __traceiter_android_vh_tune_fault_around_bytes + __traceiter_android_vh_io_statistics __traceiter_android_vh_do_swap_page_spf __tracepoint_android_rvh_dma_buf_stats_teardown __tracepoint_android_vh_tune_fault_around_bytes + __tracepoint_android_vh_io_statistics __tracepoint_android_vh_do_swap_page_spf diff --git a/android/abi_gki_aarch64_zebra b/android/abi_gki_aarch64_zebra index 59367a252ab5..cc3b7d631be6 100644 --- a/android/abi_gki_aarch64_zebra +++ b/android/abi_gki_aarch64_zebra @@ -2,3 +2,5 @@ __traceiter_android_vh_wakeup_bypass __tracepoint_android_vh_wakeup_bypass tty_termios_hw_change + usb_bus_idr + usb_bus_idr_lock diff --git a/arch/arm/boot/dts/bcm2837-rpi-cm3-io3.dts b/arch/arm/boot/dts/bcm2837-rpi-cm3-io3.dts index 3dfce4312dfc..a2ef43c2105a 100644 --- a/arch/arm/boot/dts/bcm2837-rpi-cm3-io3.dts +++ b/arch/arm/boot/dts/bcm2837-rpi-cm3-io3.dts @@ -77,7 +77,7 @@ &gpio { }; &hdmi { - hpd-gpios = <&expgpio 1 GPIO_ACTIVE_LOW>; + hpd-gpios = <&expgpio 0 GPIO_ACTIVE_LOW>; power-domains = <&power RPI_POWER_DOMAIN_HDMI>; status = "okay"; }; diff --git a/arch/arm/boot/dts/imx7d-zii-rmu2.dts b/arch/arm/boot/dts/imx7d-zii-rmu2.dts index 1065941807e8..ce59342e55aa 100644 --- a/arch/arm/boot/dts/imx7d-zii-rmu2.dts +++ b/arch/arm/boot/dts/imx7d-zii-rmu2.dts @@ -350,7 +350,7 @@ MX7D_PAD_SD3_RESET_B__SD3_RESET_B 0x59 &iomuxc_lpsr { pinctrl_enet1_phy_interrupt: enet1phyinterruptgrp { - fsl,phy = < + fsl,pins = < MX7D_PAD_LPSR_GPIO1_IO02__GPIO1_IO2 0x08 >; }; diff --git a/arch/arm/boot/dts/sam9x60.dtsi b/arch/arm/boot/dts/sam9x60.dtsi index e1e0dec8cc1f..5e569cf1cccf 100644 --- a/arch/arm/boot/dts/sam9x60.dtsi +++ b/arch/arm/boot/dts/sam9x60.dtsi @@ -692,7 +692,7 @@ rtt: rtt@fffffe20 { compatible = "microchip,sam9x60-rtt", "atmel,at91sam9260-rtt"; reg = <0xfffffe20 0x20>; interrupts = <1 IRQ_TYPE_LEVEL_HIGH 7>; - clocks = <&clk32k 0>; + clocks = <&clk32k 1>; }; pit: timer@fffffe40 { @@ -718,7 +718,7 @@ rtc: rtc@fffffea8 { compatible = "microchip,sam9x60-rtc", "atmel,at91sam9x5-rtc"; reg = <0xfffffea8 0x100>; interrupts = <1 IRQ_TYPE_LEVEL_HIGH 7>; - clocks = <&clk32k 0>; + clocks = <&clk32k 1>; }; watchdog: watchdog@ffffff80 { diff --git a/arch/arm/mach-realview/platsmp-dt.c b/arch/arm/mach-realview/platsmp-dt.c index 5ae783767a5d..083e6a6f7520 100644 --- a/arch/arm/mach-realview/platsmp-dt.c +++ b/arch/arm/mach-realview/platsmp-dt.c @@ -66,6 +66,7 @@ static void __init realview_smp_prepare_cpus(unsigned int max_cpus) return; } map = syscon_node_to_regmap(np); + of_node_put(np); if (IS_ERR(map)) { pr_err("PLATSMP: No syscon regmap\n"); return; diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig index df43271bc6fa..1d4c89a6c9d3 100644 --- a/arch/arm64/Kconfig +++ b/arch/arm64/Kconfig @@ -782,6 +782,7 @@ config ARM64_ERRATUM_3194386 * ARM Cortex-A78C erratum 3324346 * ARM Cortex-A78C erratum 3324347 * ARM Cortex-A710 erratam 3324338 + * ARM Cortex-A715 errartum 3456084 * ARM Cortex-A720 erratum 3456091 * ARM Cortex-A725 erratum 3456106 * ARM Cortex-X1 erratum 3324344 @@ -792,6 +793,7 @@ config ARM64_ERRATUM_3194386 * ARM Cortex-X925 erratum 3324334 * ARM Neoverse-N1 erratum 3324349 * ARM Neoverse N2 erratum 3324339 + * ARM Neoverse-N3 erratum 3456111 * ARM Neoverse-V1 erratum 3324341 * ARM Neoverse V2 erratum 3324336 * ARM Neoverse-V3 erratum 3312417 diff --git a/arch/arm64/Makefile b/arch/arm64/Makefile index 07c5e0fc006f..0995e337b307 100644 --- a/arch/arm64/Makefile +++ b/arch/arm64/Makefile @@ -10,7 +10,7 @@ # # Copyright (C) 1995-2001 by Russell King -LDFLAGS_vmlinux :=--no-undefined -X +LDFLAGS_vmlinux :=--no-undefined -X --pic-veneer ifeq ($(CONFIG_RELOCATABLE), y) # Pass --no-apply-dynamic-relocs to restore pre-binutils-2.27 behaviour diff --git a/arch/arm64/boot/dts/rockchip/rk3399-pinebook-pro.dts b/arch/arm64/boot/dts/rockchip/rk3399-pinebook-pro.dts index 913ba25ea72f..015e004bf275 100644 --- a/arch/arm64/boot/dts/rockchip/rk3399-pinebook-pro.dts +++ b/arch/arm64/boot/dts/rockchip/rk3399-pinebook-pro.dts @@ -25,12 +25,12 @@ chosen { backlight: edp-backlight { compatible = "pwm-backlight"; power-supply = <&vcc_12v>; - pwms = <&pwm0 0 740740 0>; + pwms = <&pwm0 0 125000 0>; }; bat: battery { compatible = "simple-battery"; - charge-full-design-microamp-hours = <9800000>; + charge-full-design-microamp-hours = <10000000>; voltage-max-design-microvolt = <4350000>; voltage-min-design-microvolt = <3000000>; }; diff --git a/arch/arm64/boot/dts/rockchip/rk3399-puma.dtsi b/arch/arm64/boot/dts/rockchip/rk3399-puma.dtsi index 0cf656824e23..40457a2a5cf2 100644 --- a/arch/arm64/boot/dts/rockchip/rk3399-puma.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3399-puma.dtsi @@ -148,6 +148,22 @@ &emmc_phy { drive-impedance-ohm = <33>; }; +&gpio3 { + /* + * The Qseven BIOS_DISABLE signal on the RK3399-Q7 keeps the on-module + * eMMC and SPI flash powered-down initially (in fact it keeps the + * reset signal asserted). BIOS_DISABLE_OVERRIDE pin allows to override + * that signal so that eMMC and SPI can be used regardless of the state + * of the signal. + */ + bios-disable-override-hog { + gpios = ; + gpio-hog; + line-name = "bios_disable_override"; + output-high; + }; +}; + &gmac { assigned-clocks = <&cru SCLK_RMII_SRC>; assigned-clock-parents = <&clkin_gmac>; @@ -437,9 +453,14 @@ &pcie_clkreqn_cpm { &pinctrl { pinctrl-names = "default"; - pinctrl-0 = <&q7_thermal_pin>; + pinctrl-0 = <&q7_thermal_pin &bios_disable_override_hog_pin>; gpios { + bios_disable_override_hog_pin: bios-disable-override-hog-pin { + rockchip,pins = + <3 RK_PD5 RK_FUNC_GPIO &pcfg_pull_down>; + }; + q7_thermal_pin: q7-thermal-pin { rockchip,pins = <0 RK_PA3 RK_FUNC_GPIO &pcfg_pull_up>; diff --git a/arch/arm64/include/asm/cputype.h b/arch/arm64/include/asm/cputype.h index 91890e9fcb6c..d8305b4657d2 100644 --- a/arch/arm64/include/asm/cputype.h +++ b/arch/arm64/include/asm/cputype.h @@ -81,6 +81,7 @@ #define ARM_CPU_PART_CORTEX_A510 0xD46 #define ARM_CPU_PART_CORTEX_A520 0xD80 #define ARM_CPU_PART_CORTEX_A710 0xD47 +#define ARM_CPU_PART_CORTEX_A715 0xD4D #define ARM_CPU_PART_CORTEX_X2 0xD48 #define ARM_CPU_PART_NEOVERSE_N2 0xD49 #define ARM_CPU_PART_CORTEX_A78C 0xD4B @@ -92,6 +93,7 @@ #define ARM_CPU_PART_NEOVERSE_V3 0xD84 #define ARM_CPU_PART_CORTEX_X925 0xD85 #define ARM_CPU_PART_CORTEX_A725 0xD87 +#define ARM_CPU_PART_NEOVERSE_N3 0xD8E #define APM_CPU_PART_POTENZA 0x000 @@ -141,6 +143,7 @@ #define MIDR_CORTEX_A510 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A510) #define MIDR_CORTEX_A520 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A520) #define MIDR_CORTEX_A710 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A710) +#define MIDR_CORTEX_A715 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A715) #define MIDR_CORTEX_X2 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_X2) #define MIDR_NEOVERSE_N2 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_NEOVERSE_N2) #define MIDR_CORTEX_A78C MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A78C) @@ -152,6 +155,7 @@ #define MIDR_NEOVERSE_V3 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_NEOVERSE_V3) #define MIDR_CORTEX_X925 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_X925) #define MIDR_CORTEX_A725 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A725) +#define MIDR_NEOVERSE_N3 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_NEOVERSE_N3) #define MIDR_THUNDERX MIDR_CPU_MODEL(ARM_CPU_IMP_CAVIUM, CAVIUM_CPU_PART_THUNDERX) #define MIDR_THUNDERX_81XX MIDR_CPU_MODEL(ARM_CPU_IMP_CAVIUM, CAVIUM_CPU_PART_THUNDERX_81XX) #define MIDR_THUNDERX_83XX MIDR_CPU_MODEL(ARM_CPU_IMP_CAVIUM, CAVIUM_CPU_PART_THUNDERX_83XX) diff --git a/arch/arm64/include/asm/uprobes.h b/arch/arm64/include/asm/uprobes.h index 315eef654e39..98f29a43bfe8 100644 --- a/arch/arm64/include/asm/uprobes.h +++ b/arch/arm64/include/asm/uprobes.h @@ -10,11 +10,9 @@ #include #include -#define MAX_UINSN_BYTES AARCH64_INSN_SIZE - -#define UPROBE_SWBP_INSN BRK64_OPCODE_UPROBES +#define UPROBE_SWBP_INSN cpu_to_le32(BRK64_OPCODE_UPROBES) #define UPROBE_SWBP_INSN_SIZE AARCH64_INSN_SIZE -#define UPROBE_XOL_SLOT_BYTES MAX_UINSN_BYTES +#define UPROBE_XOL_SLOT_BYTES AARCH64_INSN_SIZE typedef u32 uprobe_opcode_t; @@ -23,8 +21,8 @@ struct arch_uprobe_task { struct arch_uprobe { union { - u8 insn[MAX_UINSN_BYTES]; - u8 ixol[MAX_UINSN_BYTES]; + __le32 insn; + __le32 ixol; }; struct arch_probe_insn api; bool simulate; diff --git a/arch/arm64/kernel/cpu_errata.c b/arch/arm64/kernel/cpu_errata.c index b4435b8187cd..4d2159d3a822 100644 --- a/arch/arm64/kernel/cpu_errata.c +++ b/arch/arm64/kernel/cpu_errata.c @@ -373,6 +373,7 @@ static const struct midr_range erratum_spec_ssbs_list[] = { MIDR_ALL_VERSIONS(MIDR_CORTEX_A78), MIDR_ALL_VERSIONS(MIDR_CORTEX_A78C), MIDR_ALL_VERSIONS(MIDR_CORTEX_A710), + MIDR_ALL_VERSIONS(MIDR_CORTEX_A715), MIDR_ALL_VERSIONS(MIDR_CORTEX_A720), MIDR_ALL_VERSIONS(MIDR_CORTEX_A725), MIDR_ALL_VERSIONS(MIDR_CORTEX_X1), @@ -383,6 +384,7 @@ static const struct midr_range erratum_spec_ssbs_list[] = { MIDR_ALL_VERSIONS(MIDR_CORTEX_X925), MIDR_ALL_VERSIONS(MIDR_NEOVERSE_N1), MIDR_ALL_VERSIONS(MIDR_NEOVERSE_N2), + MIDR_ALL_VERSIONS(MIDR_NEOVERSE_N3), MIDR_ALL_VERSIONS(MIDR_NEOVERSE_V1), MIDR_ALL_VERSIONS(MIDR_NEOVERSE_V2), MIDR_ALL_VERSIONS(MIDR_NEOVERSE_V3), diff --git a/arch/arm64/kernel/probes/decode-insn.c b/arch/arm64/kernel/probes/decode-insn.c index 104101f633b1..492e50a6ddbf 100644 --- a/arch/arm64/kernel/probes/decode-insn.c +++ b/arch/arm64/kernel/probes/decode-insn.c @@ -99,10 +99,6 @@ arm_probe_decode_insn(probe_opcode_t insn, struct arch_probe_insn *api) aarch64_insn_is_blr(insn) || aarch64_insn_is_ret(insn)) { api->handler = simulate_br_blr_ret; - } else if (aarch64_insn_is_ldr_lit(insn)) { - api->handler = simulate_ldr_literal; - } else if (aarch64_insn_is_ldrsw_lit(insn)) { - api->handler = simulate_ldrsw_literal; } else { /* * Instruction cannot be stepped out-of-line and we don't @@ -140,6 +136,17 @@ arm_kprobe_decode_insn(kprobe_opcode_t *addr, struct arch_specific_insn *asi) probe_opcode_t insn = le32_to_cpu(*addr); probe_opcode_t *scan_end = NULL; unsigned long size = 0, offset = 0; + struct arch_probe_insn *api = &asi->api; + + if (aarch64_insn_is_ldr_lit(insn)) { + api->handler = simulate_ldr_literal; + decoded = INSN_GOOD_NO_SLOT; + } else if (aarch64_insn_is_ldrsw_lit(insn)) { + api->handler = simulate_ldrsw_literal; + decoded = INSN_GOOD_NO_SLOT; + } else { + decoded = arm_probe_decode_insn(insn, &asi->api); + } /* * If there's a symbol defined in front of and near enough to @@ -157,7 +164,6 @@ arm_kprobe_decode_insn(kprobe_opcode_t *addr, struct arch_specific_insn *asi) else scan_end = addr - MAX_ATOMIC_CONTEXT_SIZE; } - decoded = arm_probe_decode_insn(insn, &asi->api); if (decoded != INSN_REJECTED && scan_end) if (is_probed_address_atomic(addr - 1, scan_end)) diff --git a/arch/arm64/kernel/probes/simulate-insn.c b/arch/arm64/kernel/probes/simulate-insn.c index 25f67ec59635..7d63423eafc2 100644 --- a/arch/arm64/kernel/probes/simulate-insn.c +++ b/arch/arm64/kernel/probes/simulate-insn.c @@ -170,17 +170,15 @@ simulate_tbz_tbnz(u32 opcode, long addr, struct pt_regs *regs) void __kprobes simulate_ldr_literal(u32 opcode, long addr, struct pt_regs *regs) { - u64 *load_addr; + unsigned long load_addr; int xn = opcode & 0x1f; - int disp; - disp = ldr_displacement(opcode); - load_addr = (u64 *) (addr + disp); + load_addr = addr + ldr_displacement(opcode); if (opcode & (1 << 30)) /* x0-x30 */ - set_x_reg(regs, xn, *load_addr); + set_x_reg(regs, xn, READ_ONCE(*(u64 *)load_addr)); else /* w0-w30 */ - set_w_reg(regs, xn, *load_addr); + set_w_reg(regs, xn, READ_ONCE(*(u32 *)load_addr)); instruction_pointer_set(regs, instruction_pointer(regs) + 4); } @@ -188,14 +186,12 @@ simulate_ldr_literal(u32 opcode, long addr, struct pt_regs *regs) void __kprobes simulate_ldrsw_literal(u32 opcode, long addr, struct pt_regs *regs) { - s32 *load_addr; + unsigned long load_addr; int xn = opcode & 0x1f; - int disp; - disp = ldr_displacement(opcode); - load_addr = (s32 *) (addr + disp); + load_addr = addr + ldr_displacement(opcode); - set_x_reg(regs, xn, *load_addr); + set_x_reg(regs, xn, READ_ONCE(*(s32 *)load_addr)); instruction_pointer_set(regs, instruction_pointer(regs) + 4); } diff --git a/arch/arm64/kernel/probes/uprobes.c b/arch/arm64/kernel/probes/uprobes.c index 2c247634552b..8a02c549e57f 100644 --- a/arch/arm64/kernel/probes/uprobes.c +++ b/arch/arm64/kernel/probes/uprobes.c @@ -42,7 +42,7 @@ int arch_uprobe_analyze_insn(struct arch_uprobe *auprobe, struct mm_struct *mm, else if (!IS_ALIGNED(addr, AARCH64_INSN_SIZE)) return -EINVAL; - insn = *(probe_opcode_t *)(&auprobe->insn[0]); + insn = le32_to_cpu(auprobe->insn); switch (arm_probe_decode_insn(insn, &auprobe->api)) { case INSN_REJECTED: @@ -108,7 +108,7 @@ bool arch_uprobe_skip_sstep(struct arch_uprobe *auprobe, struct pt_regs *regs) if (!auprobe->simulate) return false; - insn = *(probe_opcode_t *)(&auprobe->insn[0]); + insn = le32_to_cpu(auprobe->insn); addr = instruction_pointer(regs); if (auprobe->api.handler) diff --git a/arch/m68k/kernel/process.c b/arch/m68k/kernel/process.c index da83cc83e791..8c2656371a87 100644 --- a/arch/m68k/kernel/process.c +++ b/arch/m68k/kernel/process.c @@ -116,7 +116,7 @@ asmlinkage int m68k_clone(struct pt_regs *regs) { /* regs will be equal to current_pt_regs() */ struct kernel_clone_args args = { - .flags = regs->d1 & ~CSIGNAL, + .flags = (u32)(regs->d1) & ~CSIGNAL, .pidfd = (int __user *)regs->d3, .child_tid = (int __user *)regs->d4, .parent_tid = (int __user *)regs->d3, diff --git a/arch/microblaze/mm/init.c b/arch/microblaze/mm/init.c index 45da639bd22c..a2cd139c5eb4 100644 --- a/arch/microblaze/mm/init.c +++ b/arch/microblaze/mm/init.c @@ -245,11 +245,6 @@ asmlinkage void __init mmu_init(void) { unsigned int kstart, ksize; - if (!memblock.reserved.cnt) { - pr_emerg("Error memory count\n"); - machine_restart(NULL); - } - if ((u32) memblock.memory.regions[0].size < 0x400000) { pr_emerg("Memory must be greater than 4MB\n"); machine_restart(NULL); diff --git a/arch/parisc/kernel/entry.S b/arch/parisc/kernel/entry.S index 25bef679290f..b86ba022136e 100644 --- a/arch/parisc/kernel/entry.S +++ b/arch/parisc/kernel/entry.S @@ -1071,8 +1071,7 @@ ENTRY_CFI(intr_save) /* for os_hpmc */ STREG %r16, PT_ISR(%r29) STREG %r17, PT_IOR(%r29) -#if 0 && defined(CONFIG_64BIT) - /* Revisit when we have 64-bit code above 4Gb */ +#if defined(CONFIG_64BIT) b,n intr_save2 skip_save_ior: @@ -1080,8 +1079,7 @@ skip_save_ior: * need to adjust iasq/iaoq here in the same way we adjusted isr/ior * above. */ - extrd,u,* %r8,PSW_W_BIT,1,%r1 - cmpib,COND(=),n 1,%r1,intr_save2 + bb,COND(>=),n %r8,PSW_W_BIT,intr_save2 LDREG PT_IASQ0(%r29), %r16 LDREG PT_IAOQ0(%r29), %r17 /* adjust iasq/iaoq */ diff --git a/arch/parisc/kernel/syscall.S b/arch/parisc/kernel/syscall.S index 4e53515cf81f..2fb0f0ac980c 100644 --- a/arch/parisc/kernel/syscall.S +++ b/arch/parisc/kernel/syscall.S @@ -217,10 +217,10 @@ linux_gateway_entry: #ifdef CONFIG_64BIT ldil L%sys_call_table, %r1 - or,= %r2,%r2,%r2 - addil L%(sys_call_table64-sys_call_table), %r1 + or,ev %r2,%r2,%r2 + ldil L%sys_call_table64, %r1 ldo R%sys_call_table(%r1), %r19 - or,= %r2,%r2,%r2 + or,ev %r2,%r2,%r2 ldo R%sys_call_table64(%r1), %r19 #else load32 sys_call_table, %r19 @@ -355,10 +355,10 @@ tracesys_next: extrd,u %r19,63,1,%r2 /* W hidden in bottom bit */ ldil L%sys_call_table, %r1 - or,= %r2,%r2,%r2 - addil L%(sys_call_table64-sys_call_table), %r1 + or,ev %r2,%r2,%r2 + ldil L%sys_call_table64, %r1 ldo R%sys_call_table(%r1), %r19 - or,= %r2,%r2,%r2 + or,ev %r2,%r2,%r2 ldo R%sys_call_table64(%r1), %r19 #else load32 sys_call_table, %r19 @@ -931,6 +931,8 @@ ENTRY(sys_call_table) END(sys_call_table) #ifdef CONFIG_64BIT +#undef __SYSCALL_WITH_COMPAT +#define __SYSCALL_WITH_COMPAT(nr, native, compat) __SYSCALL(nr, native) .align 8 ENTRY(sys_call_table64) #include /* 64-bit native syscalls */ diff --git a/arch/powerpc/kernel/setup-common.c b/arch/powerpc/kernel/setup-common.c index 1e417c3eedfe..b99b35ba2412 100644 --- a/arch/powerpc/kernel/setup-common.c +++ b/arch/powerpc/kernel/setup-common.c @@ -908,6 +908,7 @@ void __init setup_arch(char **cmdline_p) mem_topology_setup(); /* Set max_mapnr before paging_init() */ set_max_mapnr(max_pfn); + high_memory = (void *)__va(max_low_pfn * PAGE_SIZE); /* * Release secondary cpus out of their spinloops at 0x60 now that diff --git a/arch/powerpc/mm/mem.c b/arch/powerpc/mm/mem.c index 08e3422eb792..cd6a68a64d87 100644 --- a/arch/powerpc/mm/mem.c +++ b/arch/powerpc/mm/mem.c @@ -292,8 +292,6 @@ void __init mem_init(void) swiotlb_init(0); #endif - high_memory = (void *) __va(max_low_pfn * PAGE_SIZE); - kasan_late_init(); memblock_free_all(); diff --git a/arch/powerpc/mm/numa.c b/arch/powerpc/mm/numa.c index ce8569e16f0c..96b3e31ee0f3 100644 --- a/arch/powerpc/mm/numa.c +++ b/arch/powerpc/mm/numa.c @@ -1177,6 +1177,9 @@ void __init mem_topology_setup(void) { int cpu; + max_low_pfn = max_pfn = memblock_end_of_DRAM() >> PAGE_SHIFT; + min_low_pfn = MEMORY_START >> PAGE_SHIFT; + /* * Linux/mm assumes node 0 to be online at boot. However this is not * true on PowerPC, where node 0 is similar to any other node, it @@ -1221,9 +1224,6 @@ void __init initmem_init(void) { int nid; - max_low_pfn = memblock_end_of_DRAM() >> PAGE_SHIFT; - max_pfn = max_low_pfn; - memblock_dump_all(); for_each_online_node(nid) { diff --git a/arch/riscv/Kconfig b/arch/riscv/Kconfig index 70271db83383..57753b477ea2 100644 --- a/arch/riscv/Kconfig +++ b/arch/riscv/Kconfig @@ -193,6 +193,11 @@ config GENERIC_HWEIGHT config FIX_EARLYCON_MEM def_bool MMU +config ILLEGAL_POINTER_VALUE + hex + default 0 if 32BIT + default 0xdead000000000000 if 64BIT + config PGTABLE_LEVELS int default 3 if 64BIT diff --git a/arch/riscv/kernel/perf_callchain.c b/arch/riscv/kernel/perf_callchain.c index fb02811df714..3c0a43cb1c33 100644 --- a/arch/riscv/kernel/perf_callchain.c +++ b/arch/riscv/kernel/perf_callchain.c @@ -71,7 +71,7 @@ void perf_callchain_user(struct perf_callchain_entry_ctx *entry, perf_callchain_store(entry, regs->epc); fp = user_backtrace(entry, fp, regs->ra); - while (fp && !(fp & 0x3) && entry->nr < entry->max_stack) + while (fp && !(fp & 0x7) && entry->nr < entry->max_stack) fp = user_backtrace(entry, fp, 0); } diff --git a/arch/s390/include/asm/facility.h b/arch/s390/include/asm/facility.h index 68c476b20b57..c7031d9ada29 100644 --- a/arch/s390/include/asm/facility.h +++ b/arch/s390/include/asm/facility.h @@ -53,8 +53,10 @@ static inline int test_facility(unsigned long nr) unsigned long facilities_als[] = { FACILITIES_ALS }; if (__builtin_constant_p(nr) && nr < sizeof(facilities_als) * 8) { - if (__test_facility(nr, &facilities_als)) - return 1; + if (__test_facility(nr, &facilities_als)) { + if (!__is_defined(__DECOMPRESSOR)) + return 1; + } } return __test_facility(nr, &S390_lowcore.stfle_fac_list); } diff --git a/arch/s390/include/asm/perf_event.h b/arch/s390/include/asm/perf_event.h index b9da71632827..ea340b901839 100644 --- a/arch/s390/include/asm/perf_event.h +++ b/arch/s390/include/asm/perf_event.h @@ -75,6 +75,7 @@ struct perf_sf_sde_regs { #define SAMPLE_FREQ_MODE(hwc) (SAMPL_FLAGS(hwc) & PERF_CPUM_SF_FREQ_MODE) #define perf_arch_fetch_caller_regs(regs, __ip) do { \ + (regs)->psw.mask = 0; \ (regs)->psw.addr = (__ip); \ (regs)->gprs[15] = (unsigned long)__builtin_frame_address(0) - \ offsetof(struct stack_frame, back_chain); \ diff --git a/arch/s390/kernel/perf_cpum_sf.c b/arch/s390/kernel/perf_cpum_sf.c index bcd31e0b4edb..a9e05f4d0a48 100644 --- a/arch/s390/kernel/perf_cpum_sf.c +++ b/arch/s390/kernel/perf_cpum_sf.c @@ -1432,7 +1432,7 @@ static int aux_output_begin(struct perf_output_handle *handle, unsigned long head, base, offset; struct hws_trailer_entry *te; - if (WARN_ON_ONCE(handle->head & ~PAGE_MASK)) + if (handle->head & ~PAGE_MASK) return -EINVAL; aux->head = handle->head >> PAGE_SHIFT; @@ -1613,7 +1613,7 @@ static void hw_collect_aux(struct cpu_hw_sf *cpuhw) unsigned long num_sdb; aux = perf_get_aux(handle); - if (WARN_ON_ONCE(!aux)) + if (!aux) return; /* Inform user space new data arrived */ @@ -1635,7 +1635,7 @@ static void hw_collect_aux(struct cpu_hw_sf *cpuhw) __func__); break; } - if (WARN_ON_ONCE(!aux)) + if (!aux) return; /* Update head and alert_mark to new position */ @@ -1870,12 +1870,8 @@ static void cpumsf_pmu_start(struct perf_event *event, int flags) { struct cpu_hw_sf *cpuhw = this_cpu_ptr(&cpu_hw_sf); - if (WARN_ON_ONCE(!(event->hw.state & PERF_HES_STOPPED))) + if (!(event->hw.state & PERF_HES_STOPPED)) return; - - if (flags & PERF_EF_RELOAD) - WARN_ON_ONCE(!(event->hw.state & PERF_HES_UPTODATE)); - perf_pmu_disable(event->pmu); event->hw.state = 0; cpuhw->lsctl.cs = 1; diff --git a/arch/s390/kvm/diag.c b/arch/s390/kvm/diag.c index 5b8ec1c447e1..01582fb5ad65 100644 --- a/arch/s390/kvm/diag.c +++ b/arch/s390/kvm/diag.c @@ -77,7 +77,7 @@ static int __diag_page_ref_service(struct kvm_vcpu *vcpu) vcpu->stat.diagnose_258++; if (vcpu->run->s.regs.gprs[rx] & 7) return kvm_s390_inject_program_int(vcpu, PGM_SPECIFICATION); - rc = read_guest(vcpu, vcpu->run->s.regs.gprs[rx], rx, &parm, sizeof(parm)); + rc = read_guest_real(vcpu, vcpu->run->s.regs.gprs[rx], &parm, sizeof(parm)); if (rc) return kvm_s390_inject_prog_cond(vcpu, rc); if (parm.parm_version != 2 || parm.parm_len < 5 || parm.code != 0x258) diff --git a/arch/s390/kvm/gaccess.c b/arch/s390/kvm/gaccess.c index b9f85b2dc053..5a880e254524 100644 --- a/arch/s390/kvm/gaccess.c +++ b/arch/s390/kvm/gaccess.c @@ -794,46 +794,102 @@ static int low_address_protection_enabled(struct kvm_vcpu *vcpu, return 1; } -static int guest_page_range(struct kvm_vcpu *vcpu, unsigned long ga, u8 ar, - unsigned long *pages, unsigned long nr_pages, - const union asce asce, enum gacc_mode mode) +/** + * guest_range_to_gpas() - Calculate guest physical addresses of page fragments + * covering a logical range + * @vcpu: virtual cpu + * @ga: guest address, start of range + * @ar: access register + * @gpas: output argument, may be NULL + * @len: length of range in bytes + * @asce: address-space-control element to use for translation + * @mode: access mode + * + * Translate a logical range to a series of guest absolute addresses, + * such that the concatenation of page fragments starting at each gpa make up + * the whole range. + * The translation is performed as if done by the cpu for the given @asce, @ar, + * @mode and state of the @vcpu. + * If the translation causes an exception, its program interruption code is + * returned and the &struct kvm_s390_pgm_info pgm member of @vcpu is modified + * such that a subsequent call to kvm_s390_inject_prog_vcpu() will inject + * a correct exception into the guest. + * The resulting gpas are stored into @gpas, unless it is NULL. + * + * Note: All fragments except the first one start at the beginning of a page. + * When deriving the boundaries of a fragment from a gpa, all but the last + * fragment end at the end of the page. + * + * Return: + * * 0 - success + * * <0 - translation could not be performed, for example if guest + * memory could not be accessed + * * >0 - an access exception occurred. In this case the returned value + * is the program interruption code and the contents of pgm may + * be used to inject an exception into the guest. + */ +static int guest_range_to_gpas(struct kvm_vcpu *vcpu, unsigned long ga, u8 ar, + unsigned long *gpas, unsigned long len, + const union asce asce, enum gacc_mode mode) { psw_t *psw = &vcpu->arch.sie_block->gpsw; + unsigned int offset = offset_in_page(ga); + unsigned int fragment_len; int lap_enabled, rc = 0; enum prot_type prot; + unsigned long gpa; lap_enabled = low_address_protection_enabled(vcpu, asce); - while (nr_pages) { + while (min(PAGE_SIZE - offset, len) > 0) { + fragment_len = min(PAGE_SIZE - offset, len); ga = kvm_s390_logical_to_effective(vcpu, ga); if (mode == GACC_STORE && lap_enabled && is_low_address(ga)) return trans_exc(vcpu, PGM_PROTECTION, ga, ar, mode, PROT_TYPE_LA); - ga &= PAGE_MASK; if (psw_bits(*psw).dat) { - rc = guest_translate(vcpu, ga, pages, asce, mode, &prot); + rc = guest_translate(vcpu, ga, &gpa, asce, mode, &prot); if (rc < 0) return rc; } else { - *pages = kvm_s390_real_to_abs(vcpu, ga); - if (kvm_is_error_gpa(vcpu->kvm, *pages)) + gpa = kvm_s390_real_to_abs(vcpu, ga); + if (kvm_is_error_gpa(vcpu->kvm, gpa)) rc = PGM_ADDRESSING; } if (rc) return trans_exc(vcpu, rc, ga, ar, mode, prot); - ga += PAGE_SIZE; - pages++; - nr_pages--; + if (gpas) + *gpas++ = gpa; + offset = 0; + ga += fragment_len; + len -= fragment_len; } return 0; } +static int access_guest_page(struct kvm *kvm, enum gacc_mode mode, gpa_t gpa, + void *data, unsigned int len) +{ + const unsigned int offset = offset_in_page(gpa); + const gfn_t gfn = gpa_to_gfn(gpa); + int rc; + + if (!gfn_to_memslot(kvm, gfn)) + return PGM_ADDRESSING; + if (mode == GACC_STORE) + rc = kvm_write_guest_page(kvm, gfn, data, offset, len); + else + rc = kvm_read_guest_page(kvm, gfn, data, offset, len); + return rc; +} + int access_guest(struct kvm_vcpu *vcpu, unsigned long ga, u8 ar, void *data, unsigned long len, enum gacc_mode mode) { psw_t *psw = &vcpu->arch.sie_block->gpsw; - unsigned long _len, nr_pages, gpa, idx; - unsigned long pages_array[2]; - unsigned long *pages; + unsigned long nr_pages, idx; + unsigned long gpa_array[2]; + unsigned int fragment_len; + unsigned long *gpas; int need_ipte_lock; union asce asce; int rc; @@ -845,50 +901,45 @@ int access_guest(struct kvm_vcpu *vcpu, unsigned long ga, u8 ar, void *data, if (rc) return rc; nr_pages = (((ga & ~PAGE_MASK) + len - 1) >> PAGE_SHIFT) + 1; - pages = pages_array; - if (nr_pages > ARRAY_SIZE(pages_array)) - pages = vmalloc(array_size(nr_pages, sizeof(unsigned long))); - if (!pages) + gpas = gpa_array; + if (nr_pages > ARRAY_SIZE(gpa_array)) + gpas = vmalloc(array_size(nr_pages, sizeof(unsigned long))); + if (!gpas) return -ENOMEM; need_ipte_lock = psw_bits(*psw).dat && !asce.r; if (need_ipte_lock) ipte_lock(vcpu); - rc = guest_page_range(vcpu, ga, ar, pages, nr_pages, asce, mode); + rc = guest_range_to_gpas(vcpu, ga, ar, gpas, len, asce, mode); for (idx = 0; idx < nr_pages && !rc; idx++) { - gpa = *(pages + idx) + (ga & ~PAGE_MASK); - _len = min(PAGE_SIZE - (gpa & ~PAGE_MASK), len); - if (mode == GACC_STORE) - rc = kvm_write_guest(vcpu->kvm, gpa, data, _len); - else - rc = kvm_read_guest(vcpu->kvm, gpa, data, _len); - len -= _len; - ga += _len; - data += _len; + fragment_len = min(PAGE_SIZE - offset_in_page(gpas[idx]), len); + rc = access_guest_page(vcpu->kvm, mode, gpas[idx], data, fragment_len); + len -= fragment_len; + data += fragment_len; } if (need_ipte_lock) ipte_unlock(vcpu); - if (nr_pages > ARRAY_SIZE(pages_array)) - vfree(pages); + if (nr_pages > ARRAY_SIZE(gpa_array)) + vfree(gpas); return rc; } int access_guest_real(struct kvm_vcpu *vcpu, unsigned long gra, void *data, unsigned long len, enum gacc_mode mode) { - unsigned long _len, gpa; + unsigned int fragment_len; + unsigned long gpa; int rc = 0; while (len && !rc) { gpa = kvm_s390_real_to_abs(vcpu, gra); - _len = min(PAGE_SIZE - (gpa & ~PAGE_MASK), len); - if (mode) - rc = write_guest_abs(vcpu, gpa, data, _len); - else - rc = read_guest_abs(vcpu, gpa, data, _len); - len -= _len; - gra += _len; - data += _len; + fragment_len = min(PAGE_SIZE - offset_in_page(gpa), len); + rc = access_guest_page(vcpu->kvm, mode, gpa, data, fragment_len); + len -= fragment_len; + gra += fragment_len; + data += fragment_len; } + if (rc > 0) + vcpu->arch.pgm.code = rc; return rc; } @@ -904,8 +955,6 @@ int access_guest_real(struct kvm_vcpu *vcpu, unsigned long gra, int guest_translate_address(struct kvm_vcpu *vcpu, unsigned long gva, u8 ar, unsigned long *gpa, enum gacc_mode mode) { - psw_t *psw = &vcpu->arch.sie_block->gpsw; - enum prot_type prot; union asce asce; int rc; @@ -913,23 +962,7 @@ int guest_translate_address(struct kvm_vcpu *vcpu, unsigned long gva, u8 ar, rc = get_vcpu_asce(vcpu, &asce, gva, ar, mode); if (rc) return rc; - if (is_low_address(gva) && low_address_protection_enabled(vcpu, asce)) { - if (mode == GACC_STORE) - return trans_exc(vcpu, PGM_PROTECTION, gva, 0, - mode, PROT_TYPE_LA); - } - - if (psw_bits(*psw).dat && !asce.r) { /* Use DAT? */ - rc = guest_translate(vcpu, gva, gpa, asce, mode, &prot); - if (rc > 0) - return trans_exc(vcpu, rc, gva, 0, mode, prot); - } else { - *gpa = kvm_s390_real_to_abs(vcpu, gva); - if (kvm_is_error_gpa(vcpu->kvm, *gpa)) - return trans_exc(vcpu, rc, gva, PGM_ADDRESSING, mode, 0); - } - - return rc; + return guest_range_to_gpas(vcpu, gva, ar, gpa, 1, asce, mode); } /** @@ -938,17 +971,14 @@ int guest_translate_address(struct kvm_vcpu *vcpu, unsigned long gva, u8 ar, int check_gva_range(struct kvm_vcpu *vcpu, unsigned long gva, u8 ar, unsigned long length, enum gacc_mode mode) { - unsigned long gpa; - unsigned long currlen; + union asce asce; int rc = 0; + rc = get_vcpu_asce(vcpu, &asce, gva, ar, mode); + if (rc) + return rc; ipte_lock(vcpu); - while (length > 0 && !rc) { - currlen = min(length, PAGE_SIZE - (gva % PAGE_SIZE)); - rc = guest_translate_address(vcpu, gva, ar, &gpa, mode); - gva += currlen; - length -= currlen; - } + rc = guest_range_to_gpas(vcpu, gva, ar, NULL, length, asce, mode); ipte_unlock(vcpu); return rc; diff --git a/arch/s390/kvm/gaccess.h b/arch/s390/kvm/gaccess.h index 7c72a5e3449f..8ed2d6c7404f 100644 --- a/arch/s390/kvm/gaccess.h +++ b/arch/s390/kvm/gaccess.h @@ -344,11 +344,12 @@ int read_guest_abs(struct kvm_vcpu *vcpu, unsigned long gpa, void *data, * @len: number of bytes to copy * * Copy @len bytes from @data (kernel space) to @gra (guest real address). - * It is up to the caller to ensure that the entire guest memory range is - * valid memory before calling this function. * Guest low address and key protection are not checked. * - * Returns zero on success or -EFAULT on error. + * Returns zero on success, -EFAULT when copying from @data failed, or + * PGM_ADRESSING in case @gra is outside a memslot. In this case, pgm check info + * is also stored to allow injecting into the guest (if applicable) using + * kvm_s390_inject_prog_cond(). * * If an error occurs data may have been copied partially to guest memory. */ @@ -367,11 +368,12 @@ int write_guest_real(struct kvm_vcpu *vcpu, unsigned long gra, void *data, * @len: number of bytes to copy * * Copy @len bytes from @gra (guest real address) to @data (kernel space). - * It is up to the caller to ensure that the entire guest memory range is - * valid memory before calling this function. * Guest key protection is not checked. * - * Returns zero on success or -EFAULT on error. + * Returns zero on success, -EFAULT when copying to @data failed, or + * PGM_ADRESSING in case @gra is outside a memslot. In this case, pgm check info + * is also stored to allow injecting into the guest (if applicable) using + * kvm_s390_inject_prog_cond(). * * If an error occurs data may have been copied partially to kernel space. */ diff --git a/arch/s390/mm/cmm.c b/arch/s390/mm/cmm.c index 1141c8d5c0d0..9b4304fa37bf 100644 --- a/arch/s390/mm/cmm.c +++ b/arch/s390/mm/cmm.c @@ -95,11 +95,12 @@ static long cmm_alloc_pages(long nr, long *counter, (*counter)++; spin_unlock(&cmm_lock); nr--; + cond_resched(); } return nr; } -static long cmm_free_pages(long nr, long *counter, struct cmm_page_array **list) +static long __cmm_free_pages(long nr, long *counter, struct cmm_page_array **list) { struct cmm_page_array *pa; unsigned long addr; @@ -123,6 +124,21 @@ static long cmm_free_pages(long nr, long *counter, struct cmm_page_array **list) return nr; } +static long cmm_free_pages(long nr, long *counter, struct cmm_page_array **list) +{ + long inc = 0; + + while (nr) { + inc = min(256L, nr); + nr -= inc; + inc = __cmm_free_pages(inc, counter, list); + if (inc) + break; + cond_resched(); + } + return nr + inc; +} + static int cmm_oom_notify(struct notifier_block *self, unsigned long dummy, void *parm) { diff --git a/arch/x86/entry/entry.S b/arch/x86/entry/entry.S index 09e99d13fc0b..f4419afc7147 100644 --- a/arch/x86/entry/entry.S +++ b/arch/x86/entry/entry.S @@ -9,6 +9,8 @@ #include #include #include +#include +#include .pushsection .noinstr.text, "ax" @@ -17,6 +19,9 @@ SYM_FUNC_START(entry_ibpb) movl $PRED_CMD_IBPB, %eax xorl %edx, %edx wrmsr + + /* Make sure IBPB clears return stack preductions too. */ + FILL_RETURN_BUFFER %rax, RSB_CLEAR_LOOPS, X86_BUG_IBPB_NO_RET RET SYM_FUNC_END(entry_ibpb) /* For KVM */ diff --git a/arch/x86/entry/entry_32.S b/arch/x86/entry/entry_32.S index 97d422f31c77..c524aa3f094a 100644 --- a/arch/x86/entry/entry_32.S +++ b/arch/x86/entry/entry_32.S @@ -939,6 +939,8 @@ SYM_FUNC_START(entry_SYSENTER_32) /* Now ready to switch the cr3 */ SWITCH_TO_USER_CR3 scratch_reg=%eax + /* Clobbers ZF */ + CLEAR_CPU_BUFFERS /* * Restore all flags except IF. (We restore IF separately because @@ -949,7 +951,6 @@ SYM_FUNC_START(entry_SYSENTER_32) BUG_IF_WRONG_CR3 no_user_check=1 popfl popl %eax - CLEAR_CPU_BUFFERS /* * Return back to the vDSO, which will pop ecx and edx. @@ -1221,7 +1222,6 @@ SYM_CODE_START(asm_exc_nmi) /* Not on SYSENTER stack. */ call exc_nmi - CLEAR_CPU_BUFFERS jmp .Lnmi_return .Lnmi_from_sysenter_stack: @@ -1242,6 +1242,7 @@ SYM_CODE_START(asm_exc_nmi) CHECK_AND_APPLY_ESPFIX RESTORE_ALL_NMI cr3_reg=%edi pop=4 + CLEAR_CPU_BUFFERS jmp .Lirq_return #ifdef CONFIG_X86_ESPFIX32 @@ -1283,6 +1284,7 @@ SYM_CODE_START(asm_exc_nmi) * 1 - orig_ax */ lss (1+5+6)*4(%esp), %esp # back to espfix stack + CLEAR_CPU_BUFFERS jmp .Lirq_return #endif SYM_CODE_END(asm_exc_nmi) diff --git a/arch/x86/events/intel/pt.c b/arch/x86/events/intel/pt.c index da7e8c2b5347..1e31ff3d9940 100644 --- a/arch/x86/events/intel/pt.c +++ b/arch/x86/events/intel/pt.c @@ -1586,6 +1586,7 @@ static void pt_event_stop(struct perf_event *event, int mode) * see comment in intel_pt_interrupt(). */ WRITE_ONCE(pt->handle_nmi, 0); + barrier(); pt_config_stop(event); @@ -1637,11 +1638,10 @@ static long pt_event_snapshot_aux(struct perf_event *event, return 0; /* - * Here, handle_nmi tells us if the tracing is on + * There is no PT interrupt in this mode, so stop the trace and it will + * remain stopped while the buffer is copied. */ - if (READ_ONCE(pt->handle_nmi)) - pt_config_stop(event); - + pt_config_stop(event); pt_read_offset(buf); pt_update_head(pt); @@ -1653,11 +1653,10 @@ static long pt_event_snapshot_aux(struct perf_event *event, ret = perf_output_copy_aux(&pt->handle, handle, from, to); /* - * If the tracing was on when we turned up, restart it. - * Compiler barrier not needed as we couldn't have been - * preempted by anything that touches pt->handle_nmi. + * Here, handle_nmi tells us if the tracing was on. + * If the tracing was on, restart it. */ - if (pt->handle_nmi) + if (READ_ONCE(pt->handle_nmi)) pt_config_start(event); return ret; diff --git a/arch/x86/include/asm/cpufeatures.h b/arch/x86/include/asm/cpufeatures.h index e1bc2bad8cff..23f563493e81 100644 --- a/arch/x86/include/asm/cpufeatures.h +++ b/arch/x86/include/asm/cpufeatures.h @@ -217,7 +217,7 @@ #define X86_FEATURE_SPEC_STORE_BYPASS_DISABLE ( 7*32+23) /* "" Disable Speculative Store Bypass. */ #define X86_FEATURE_LS_CFG_SSBD ( 7*32+24) /* "" AMD SSBD implementation via LS_CFG MSR */ #define X86_FEATURE_IBRS ( 7*32+25) /* Indirect Branch Restricted Speculation */ -#define X86_FEATURE_IBPB ( 7*32+26) /* Indirect Branch Prediction Barrier */ +#define X86_FEATURE_IBPB ( 7*32+26) /* "ibpb" Indirect Branch Prediction Barrier without a guaranteed RSB flush */ #define X86_FEATURE_STIBP ( 7*32+27) /* Single Thread Indirect Branch Predictors */ #define X86_FEATURE_ZEN ( 7*32+28) /* "" CPU is AMD family 0x17 or above (Zen) */ #define X86_FEATURE_L1TF_PTEINV ( 7*32+29) /* "" L1TF workaround PTE inversion */ @@ -324,6 +324,7 @@ #define X86_FEATURE_VIRT_SSBD (13*32+25) /* Virtualized Speculative Store Bypass Disable */ #define X86_FEATURE_AMD_SSB_NO (13*32+26) /* "" Speculative Store Bypass is fixed in hardware. */ #define X86_FEATURE_BTC_NO (13*32+29) /* "" Not vulnerable to Branch Type Confusion */ +#define X86_FEATURE_AMD_IBPB_RET (13*32+30) /* "" IBPB clears return address predictor */ /* Thermal and Power Management Leaf, CPUID level 0x00000006 (EAX), word 14 */ #define X86_FEATURE_DTHERM (14*32+ 0) /* Digital Thermal Sensor */ @@ -455,4 +456,6 @@ #define X86_BUG_SRSO X86_BUG(1*32 + 0) /* AMD SRSO bug */ #define X86_BUG_DIV0 X86_BUG(1*32 + 1) /* AMD DIV0 speculation bug */ #define X86_BUG_RFDS X86_BUG(1*32 + 2) /* CPU is vulnerable to Register File Data Sampling */ +#define X86_BUG_BHI X86_BUG(1*32 + 3) /* CPU is affected by Branch History Injection */ +#define X86_BUG_IBPB_NO_RET X86_BUG(1*32 + 4) /* "ibpb_no_ret" IBPB omits return target predictions */ #endif /* _ASM_X86_CPUFEATURES_H */ diff --git a/arch/x86/include/asm/syscall.h b/arch/x86/include/asm/syscall.h index 7cbf733d11af..e8a28380d0ad 100644 --- a/arch/x86/include/asm/syscall.h +++ b/arch/x86/include/asm/syscall.h @@ -85,7 +85,12 @@ static inline void syscall_get_arguments(struct task_struct *task, struct pt_regs *regs, unsigned long *args) { - memcpy(args, ®s->bx, 6 * sizeof(args[0])); + args[0] = regs->bx; + args[1] = regs->cx; + args[2] = regs->dx; + args[3] = regs->si; + args[4] = regs->di; + args[5] = regs->bp; } static inline void syscall_set_arguments(struct task_struct *task, diff --git a/arch/x86/kernel/apic/apic.c b/arch/x86/kernel/apic/apic.c index 25eb69f26e03..3a3878817c20 100644 --- a/arch/x86/kernel/apic/apic.c +++ b/arch/x86/kernel/apic/apic.c @@ -491,7 +491,19 @@ static int lapic_timer_shutdown(struct clock_event_device *evt) v = apic_read(APIC_LVTT); v |= (APIC_LVT_MASKED | LOCAL_TIMER_VECTOR); apic_write(APIC_LVTT, v); - apic_write(APIC_TMICT, 0); + + /* + * Setting APIC_LVT_MASKED (above) should be enough to tell + * the hardware that this timer will never fire. But AMD + * erratum 411 and some Intel CPU behavior circa 2024 say + * otherwise. Time for belt and suspenders programming: mask + * the timer _and_ zero the counter registers: + */ + if (v & APIC_LVT_TIMER_TSCDEADLINE) + wrmsrl(MSR_IA32_TSC_DEADLINE, 0); + else + apic_write(APIC_TMICT, 0); + return 0; } diff --git a/arch/x86/kernel/cpu/bugs.c b/arch/x86/kernel/cpu/bugs.c index d6e14190cf80..0b7f6bcbb8ea 100644 --- a/arch/x86/kernel/cpu/bugs.c +++ b/arch/x86/kernel/cpu/bugs.c @@ -1061,7 +1061,24 @@ static void __init retbleed_select_mitigation(void) case RETBLEED_MITIGATION_IBPB: setup_force_cpu_cap(X86_FEATURE_ENTRY_IBPB); + + /* + * IBPB on entry already obviates the need for + * software-based untraining so clear those in case some + * other mitigation like SRSO has selected them. + */ + setup_clear_cpu_cap(X86_FEATURE_UNRET); + setup_clear_cpu_cap(X86_FEATURE_RETHUNK); + mitigate_smt = true; + + /* + * There is no need for RSB filling: entry_ibpb() ensures + * all predictions, including the RSB, are invalidated, + * regardless of IBPB implementation. + */ + setup_clear_cpu_cap(X86_FEATURE_RSB_VMEXIT); + break; default: @@ -2453,6 +2470,14 @@ static void __init srso_select_mitigation(void) if (has_microcode) { setup_force_cpu_cap(X86_FEATURE_ENTRY_IBPB); srso_mitigation = SRSO_MITIGATION_IBPB; + + /* + * IBPB on entry already obviates the need for + * software-based untraining so clear those in case some + * other mitigation like Retbleed has selected them. + */ + setup_clear_cpu_cap(X86_FEATURE_UNRET); + setup_clear_cpu_cap(X86_FEATURE_RETHUNK); } } else { pr_err("WARNING: kernel not compiled with CPU_IBPB_ENTRY.\n"); @@ -2465,6 +2490,13 @@ static void __init srso_select_mitigation(void) if (!boot_cpu_has(X86_FEATURE_ENTRY_IBPB) && has_microcode) { setup_force_cpu_cap(X86_FEATURE_IBPB_ON_VMEXIT); srso_mitigation = SRSO_MITIGATION_IBPB_ON_VMEXIT; + + /* + * There is no need for RSB filling: entry_ibpb() ensures + * all predictions, including the RSB, are invalidated, + * regardless of IBPB implementation. + */ + setup_clear_cpu_cap(X86_FEATURE_RSB_VMEXIT); } } else { pr_err("WARNING: kernel not compiled with CPU_SRSO.\n"); diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c index a496a9867f4b..bdcf1e9375ee 100644 --- a/arch/x86/kernel/cpu/common.c +++ b/arch/x86/kernel/cpu/common.c @@ -1335,6 +1335,9 @@ static void __init cpu_set_bug_bits(struct cpuinfo_x86 *c) if (vulnerable_to_rfds(ia32_cap)) setup_force_cpu_bug(X86_BUG_RFDS); + if (cpu_has(c, X86_FEATURE_AMD_IBPB) && !cpu_has(c, X86_FEATURE_AMD_IBPB_RET)) + setup_force_cpu_bug(X86_BUG_IBPB_NO_RET); + if (cpu_matches(cpu_vuln_whitelist, NO_MELTDOWN)) return; diff --git a/arch/x86/kernel/cpu/mshyperv.c b/arch/x86/kernel/cpu/mshyperv.c index 021cd067733e..a91aad434d03 100644 --- a/arch/x86/kernel/cpu/mshyperv.c +++ b/arch/x86/kernel/cpu/mshyperv.c @@ -275,6 +275,7 @@ static void __init ms_hyperv_init_platform(void) ms_hyperv.misc_features & HV_FEATURE_FREQUENCY_MSRS_AVAILABLE) { x86_platform.calibrate_tsc = hv_get_tsc_khz; x86_platform.calibrate_cpu = hv_get_tsc_khz; + setup_force_cpu_cap(X86_FEATURE_TSC_KNOWN_FREQ); } if (ms_hyperv.hints & HV_X64_ENLIGHTENED_VMCS_RECOMMENDED) { diff --git a/arch/x86/kernel/cpu/resctrl/core.c b/arch/x86/kernel/cpu/resctrl/core.c index 4ccb9039f595..32005e229c03 100644 --- a/arch/x86/kernel/cpu/resctrl/core.c +++ b/arch/x86/kernel/cpu/resctrl/core.c @@ -251,7 +251,7 @@ static inline bool rdt_get_mb_table(struct rdt_resource *r) return false; } -static bool __get_mem_config_intel(struct rdt_resource *r) +static __init bool __get_mem_config_intel(struct rdt_resource *r) { union cpuid_0x10_3_eax eax; union cpuid_0x10_x_edx edx; @@ -285,7 +285,7 @@ static bool __get_mem_config_intel(struct rdt_resource *r) return true; } -static bool __rdt_get_mem_config_amd(struct rdt_resource *r) +static __init bool __rdt_get_mem_config_amd(struct rdt_resource *r) { union cpuid_0x10_3_eax eax; union cpuid_0x10_x_edx edx; diff --git a/arch/x86/kernel/kprobes/core.c b/arch/x86/kernel/kprobes/core.c index e7edc9e4c6cd..6d59c8e7719b 100644 --- a/arch/x86/kernel/kprobes/core.c +++ b/arch/x86/kernel/kprobes/core.c @@ -194,17 +194,10 @@ static unsigned long __recover_probed_insn(kprobe_opcode_t *buf, unsigned long addr) { struct kprobe *kp; - unsigned long faddr; + bool faddr; kp = get_kprobe((void *)addr); - faddr = ftrace_location(addr); - /* - * Addresses inside the ftrace location are refused by - * arch_check_ftrace_location(). Something went terribly wrong - * if such an address is checked here. - */ - if (WARN_ON(faddr && faddr != addr)) - return 0UL; + faddr = ftrace_location(addr) == addr; /* * Use the current code if it is not modified by Kprobe * and it cannot be modified by ftrace. diff --git a/arch/x86/mm/init.c b/arch/x86/mm/init.c index 8f67fed039a1..bb265741f955 100644 --- a/arch/x86/mm/init.c +++ b/arch/x86/mm/init.c @@ -263,21 +263,17 @@ static void __init probe_page_size_mask(void) } } -#define INTEL_MATCH(_model) { .vendor = X86_VENDOR_INTEL, \ - .family = 6, \ - .model = _model, \ - } /* * INVLPG may not properly flush Global entries * on these CPUs when PCIDs are enabled. */ static const struct x86_cpu_id invlpg_miss_ids[] = { - INTEL_MATCH(INTEL_FAM6_ALDERLAKE ), - INTEL_MATCH(INTEL_FAM6_ALDERLAKE_L ), - INTEL_MATCH(INTEL_FAM6_ALDERLAKE_N ), - INTEL_MATCH(INTEL_FAM6_RAPTORLAKE ), - INTEL_MATCH(INTEL_FAM6_RAPTORLAKE_P), - INTEL_MATCH(INTEL_FAM6_RAPTORLAKE_S), + X86_MATCH_INTEL_FAM6_MODEL(ALDERLAKE, 0), + X86_MATCH_INTEL_FAM6_MODEL(ALDERLAKE_L, 0), + X86_MATCH_INTEL_FAM6_MODEL(ALDERLAKE_N, 0), + X86_MATCH_INTEL_FAM6_MODEL(RAPTORLAKE, 0), + X86_MATCH_INTEL_FAM6_MODEL(RAPTORLAKE_P, 0), + X86_MATCH_INTEL_FAM6_MODEL(RAPTORLAKE_S, 0), {} }; diff --git a/arch/x86/xen/setup.c b/arch/x86/xen/setup.c index 1f80dd3a2dd4..629c94d1ab24 100644 --- a/arch/x86/xen/setup.c +++ b/arch/x86/xen/setup.c @@ -856,7 +856,7 @@ char * __init xen_memory_setup(void) * to relocating (and even reusing) pages with kernel text or data. */ if (xen_is_e820_reserved(__pa_symbol(_text), - __pa_symbol(__bss_stop) - __pa_symbol(_text))) { + __pa_symbol(_end) - __pa_symbol(_text))) { xen_raw_console_write("Xen hypervisor allocated kernel memory conflicts with E820 map\n"); BUG(); } diff --git a/block/bfq-iosched.c b/block/bfq-iosched.c index 7e12d364e5d0..0247a7191fca 100644 --- a/block/bfq-iosched.c +++ b/block/bfq-iosched.c @@ -2616,8 +2616,12 @@ bfq_setup_cooperator(struct bfq_data *bfqd, struct bfq_queue *bfqq, struct bfq_queue *in_service_bfqq, *new_bfqq; /* if a merge has already been setup, then proceed with that first */ - if (bfqq->new_bfqq) - return bfqq->new_bfqq; + new_bfqq = bfqq->new_bfqq; + if (new_bfqq) { + while (new_bfqq->new_bfqq) + new_bfqq = new_bfqq->new_bfqq; + return new_bfqq; + } /* * Do not perform queue merging if the device is non @@ -2770,10 +2774,12 @@ void bfq_release_process_ref(struct bfq_data *bfqd, struct bfq_queue *bfqq) bfq_put_queue(bfqq); } -static void -bfq_merge_bfqqs(struct bfq_data *bfqd, struct bfq_io_cq *bic, - struct bfq_queue *bfqq, struct bfq_queue *new_bfqq) +static struct bfq_queue *bfq_merge_bfqqs(struct bfq_data *bfqd, + struct bfq_io_cq *bic, + struct bfq_queue *bfqq) { + struct bfq_queue *new_bfqq = bfqq->new_bfqq; + bfq_log_bfqq(bfqd, bfqq, "merging with queue %lu", (unsigned long)new_bfqq->pid); /* Save weight raising and idle window of the merged queues */ @@ -2841,6 +2847,8 @@ bfq_merge_bfqqs(struct bfq_data *bfqd, struct bfq_io_cq *bic, new_bfqq->pid = -1; bfqq->bic = NULL; bfq_release_process_ref(bfqd, bfqq); + + return new_bfqq; } static bool bfq_allow_bio_merge(struct request_queue *q, struct request *rq, @@ -2876,14 +2884,8 @@ static bool bfq_allow_bio_merge(struct request_queue *q, struct request *rq, * fulfilled, i.e., bic can be redirected to new_bfqq * and bfqq can be put. */ - bfq_merge_bfqqs(bfqd, bfqd->bio_bic, bfqq, - new_bfqq); - /* - * If we get here, bio will be queued into new_queue, - * so use new_bfqq to decide whether bio and rq can be - * merged. - */ - bfqq = new_bfqq; + while (bfqq != new_bfqq) + bfqq = bfq_merge_bfqqs(bfqd, bfqd->bio_bic, bfqq); /* * Change also bqfd->bio_bfqq, as @@ -5437,6 +5439,7 @@ static bool __bfq_insert_request(struct bfq_data *bfqd, struct request *rq) bool waiting, idle_timer_disabled = false; if (new_bfqq) { + struct bfq_queue *old_bfqq = bfqq; /* * Release the request's reference to the old bfqq * and make sure one is taken to the shared queue. @@ -5452,18 +5455,18 @@ static bool __bfq_insert_request(struct bfq_data *bfqd, struct request *rq) * then complete the merge and redirect it to * new_bfqq. */ - if (bic_to_bfqq(RQ_BIC(rq), 1) == bfqq) - bfq_merge_bfqqs(bfqd, RQ_BIC(rq), - bfqq, new_bfqq); + if (bic_to_bfqq(RQ_BIC(rq), 1) == bfqq) { + while (bfqq != new_bfqq) + bfqq = bfq_merge_bfqqs(bfqd, RQ_BIC(rq), bfqq); + } - bfq_clear_bfqq_just_created(bfqq); + bfq_clear_bfqq_just_created(old_bfqq); /* * rq is about to be enqueued into new_bfqq, * release rq reference on bfqq */ - bfq_put_queue(bfqq); + bfq_put_queue(old_bfqq); rq->elv.priv[1] = new_bfqq; - bfqq = new_bfqq; } bfq_update_io_thinktime(bfqd, bfqq); @@ -6004,7 +6007,7 @@ bfq_split_bfqq(struct bfq_io_cq *bic, struct bfq_queue *bfqq) { bfq_log_bfqq(bfqq->bfqd, bfqq, "splitting queue"); - if (bfqq_process_refs(bfqq) == 1) { + if (bfqq_process_refs(bfqq) == 1 && !bfqq->new_bfqq) { bfqq->pid = current->pid; bfq_clear_bfqq_coop(bfqq); bfq_clear_bfqq_split_coop(bfqq); @@ -6189,7 +6192,8 @@ static struct bfq_queue *bfq_init_rq(struct request *rq) * addition, if the queue has also just been split, we have to * resume its state. */ - if (likely(bfqq != &bfqd->oom_bfqq) && bfqq_process_refs(bfqq) == 1) { + if (likely(bfqq != &bfqd->oom_bfqq) && !bfqq->new_bfqq && + bfqq_process_refs(bfqq) == 1) { bfqq->bic = bic; if (split) { /* diff --git a/block/blk-iocost.c b/block/blk-iocost.c index fe5b0c79e541..7d56506eb8ff 100644 --- a/block/blk-iocost.c +++ b/block/blk-iocost.c @@ -2022,7 +2022,7 @@ static void ioc_forgive_debts(struct ioc *ioc, u64 usage_us_sum, int nr_debtors, struct ioc_now *now) { struct ioc_gq *iocg; - u64 dur, usage_pct, nr_cycles; + u64 dur, usage_pct, nr_cycles, nr_cycles_shift; /* if no debtor, reset the cycle */ if (!nr_debtors) { @@ -2084,10 +2084,12 @@ static void ioc_forgive_debts(struct ioc *ioc, u64 usage_us_sum, int nr_debtors, old_debt = iocg->abs_vdebt; old_delay = iocg->delay; + nr_cycles_shift = min_t(u64, nr_cycles, BITS_PER_LONG - 1); if (iocg->abs_vdebt) - iocg->abs_vdebt = iocg->abs_vdebt >> nr_cycles ?: 1; + iocg->abs_vdebt = iocg->abs_vdebt >> nr_cycles_shift ?: 1; + if (iocg->delay) - iocg->delay = iocg->delay >> nr_cycles ?: 1; + iocg->delay = iocg->delay >> nr_cycles_shift ?: 1; iocg_kick_waitq(iocg, true, now); diff --git a/block/blk-rq-qos.c b/block/blk-rq-qos.c index e83af7bc7591..26dd3e7bd00d 100644 --- a/block/blk-rq-qos.c +++ b/block/blk-rq-qos.c @@ -225,8 +225,8 @@ static int rq_qos_wake_function(struct wait_queue_entry *curr, data->got_token = true; smp_wmb(); - list_del_init(&curr->entry); wake_up_process(data->task); + list_del_init_careful(&curr->entry); return 1; } diff --git a/block/partitions/core.c b/block/partitions/core.c index e3d61ec4a5a6..45fe4317fffa 100644 --- a/block/partitions/core.c +++ b/block/partitions/core.c @@ -691,9 +691,11 @@ static bool blk_add_partition(struct gendisk *disk, struct block_device *bdev, part = add_partition(disk, p, from, size, state->parts[p].flags, &state->parts[p].info); - if (IS_ERR(part) && PTR_ERR(part) != -ENXIO) { - printk(KERN_ERR " %s: p%d could not be added: %ld\n", - disk->disk_name, p, -PTR_ERR(part)); + if (IS_ERR(part)) { + if (PTR_ERR(part) != -ENXIO) { + printk(KERN_ERR " %s: p%d could not be added: %pe\n", + disk->disk_name, p, part); + } return true; } diff --git a/drivers/acpi/acpica/dbconvert.c b/drivers/acpi/acpica/dbconvert.c index 2b84ac093698..8dbab6932049 100644 --- a/drivers/acpi/acpica/dbconvert.c +++ b/drivers/acpi/acpica/dbconvert.c @@ -174,6 +174,8 @@ acpi_status acpi_db_convert_to_package(char *string, union acpi_object *object) elements = ACPI_ALLOCATE_ZEROED(DB_DEFAULT_PKG_ELEMENTS * sizeof(union acpi_object)); + if (!elements) + return (AE_NO_MEMORY); this = string; for (i = 0; i < (DB_DEFAULT_PKG_ELEMENTS - 1); i++) { diff --git a/drivers/acpi/acpica/exprep.c b/drivers/acpi/acpica/exprep.c index 4a0f03157e08..ab500f31c96e 100644 --- a/drivers/acpi/acpica/exprep.c +++ b/drivers/acpi/acpica/exprep.c @@ -437,6 +437,9 @@ acpi_status acpi_ex_prep_field_value(struct acpi_create_field_info *info) if (info->connection_node) { second_desc = info->connection_node->object; + if (second_desc == NULL) { + break; + } if (!(second_desc->common.flags & AOPOBJ_DATA_VALID)) { status = acpi_ds_get_buffer_arguments(second_desc); diff --git a/drivers/acpi/acpica/psargs.c b/drivers/acpi/acpica/psargs.c index 3b40db4ad9f3..7a1120262a14 100644 --- a/drivers/acpi/acpica/psargs.c +++ b/drivers/acpi/acpica/psargs.c @@ -25,6 +25,8 @@ acpi_ps_get_next_package_length(struct acpi_parse_state *parser_state); static union acpi_parse_object *acpi_ps_get_next_field(struct acpi_parse_state *parser_state); +static void acpi_ps_free_field_list(union acpi_parse_object *start); + /******************************************************************************* * * FUNCTION: acpi_ps_get_next_package_length @@ -683,6 +685,39 @@ static union acpi_parse_object *acpi_ps_get_next_field(struct acpi_parse_state return_PTR(field); } +/******************************************************************************* + * + * FUNCTION: acpi_ps_free_field_list + * + * PARAMETERS: start - First Op in field list + * + * RETURN: None. + * + * DESCRIPTION: Free all Op objects inside a field list. + * + ******************************************************************************/ + +static void acpi_ps_free_field_list(union acpi_parse_object *start) +{ + union acpi_parse_object *cur = start; + union acpi_parse_object *next; + union acpi_parse_object *arg; + + while (cur) { + next = cur->common.next; + + /* AML_INT_CONNECTION_OP can have a single argument */ + + arg = acpi_ps_get_arg(cur, 0); + if (arg) { + acpi_ps_free_op(arg); + } + + acpi_ps_free_op(cur); + cur = next; + } +} + /******************************************************************************* * * FUNCTION: acpi_ps_get_next_arg @@ -751,6 +786,10 @@ acpi_ps_get_next_arg(struct acpi_walk_state *walk_state, while (parser_state->aml < parser_state->pkg_end) { field = acpi_ps_get_next_field(parser_state); if (!field) { + if (arg) { + acpi_ps_free_field_list(arg); + } + return_ACPI_STATUS(AE_NO_MEMORY); } @@ -820,6 +859,10 @@ acpi_ps_get_next_arg(struct acpi_walk_state *walk_state, acpi_ps_get_next_namepath(walk_state, parser_state, arg, ACPI_NOT_METHOD_CALL); + if (ACPI_FAILURE(status)) { + acpi_ps_free_op(arg); + return_ACPI_STATUS(status); + } } else { /* Single complex argument, nothing returned */ @@ -854,6 +897,10 @@ acpi_ps_get_next_arg(struct acpi_walk_state *walk_state, acpi_ps_get_next_namepath(walk_state, parser_state, arg, ACPI_POSSIBLE_METHOD_CALL); + if (ACPI_FAILURE(status)) { + acpi_ps_free_op(arg); + return_ACPI_STATUS(status); + } if (arg->common.aml_opcode == AML_INT_METHODCALL_OP) { diff --git a/drivers/acpi/battery.c b/drivers/acpi/battery.c index 2e1462b8929c..f9fb092f33a2 100644 --- a/drivers/acpi/battery.c +++ b/drivers/acpi/battery.c @@ -695,27 +695,34 @@ static LIST_HEAD(acpi_battery_list); static LIST_HEAD(battery_hook_list); static DEFINE_MUTEX(hook_mutex); -static void __battery_hook_unregister(struct acpi_battery_hook *hook, int lock) +static void battery_hook_unregister_unlocked(struct acpi_battery_hook *hook) { struct acpi_battery *battery; + /* * In order to remove a hook, we first need to * de-register all the batteries that are registered. */ - if (lock) - mutex_lock(&hook_mutex); list_for_each_entry(battery, &acpi_battery_list, list) { hook->remove_battery(battery->bat); } - list_del(&hook->list); - if (lock) - mutex_unlock(&hook_mutex); + list_del_init(&hook->list); + pr_info("extension unregistered: %s\n", hook->name); } void battery_hook_unregister(struct acpi_battery_hook *hook) { - __battery_hook_unregister(hook, 1); + mutex_lock(&hook_mutex); + /* + * Ignore already unregistered battery hooks. This might happen + * if a battery hook was previously unloaded due to an error when + * adding a new battery. + */ + if (!list_empty(&hook->list)) + battery_hook_unregister_unlocked(hook); + + mutex_unlock(&hook_mutex); } EXPORT_SYMBOL_GPL(battery_hook_unregister); @@ -724,7 +731,6 @@ void battery_hook_register(struct acpi_battery_hook *hook) struct acpi_battery *battery; mutex_lock(&hook_mutex); - INIT_LIST_HEAD(&hook->list); list_add(&hook->list, &battery_hook_list); /* * Now that the driver is registered, we need @@ -741,7 +747,7 @@ void battery_hook_register(struct acpi_battery_hook *hook) * hooks. */ pr_err("extension failed to load: %s", hook->name); - __battery_hook_unregister(hook, 0); + battery_hook_unregister_unlocked(hook); goto end; } } @@ -778,7 +784,7 @@ static void battery_hook_add_battery(struct acpi_battery *battery) */ pr_err("error in extension, unloading: %s", hook_node->name); - __battery_hook_unregister(hook_node, 0); + battery_hook_unregister_unlocked(hook_node); } } mutex_unlock(&hook_mutex); @@ -811,7 +817,7 @@ static void __exit battery_hook_exit(void) * need to remove the hooks. */ list_for_each_entry_safe(hook, ptr, &battery_hook_list, list) { - __battery_hook_unregister(hook, 1); + battery_hook_unregister(hook); } mutex_destroy(&hook_mutex); } diff --git a/drivers/acpi/device_sysfs.c b/drivers/acpi/device_sysfs.c index 566067a855a1..57ee8314dfb8 100644 --- a/drivers/acpi/device_sysfs.c +++ b/drivers/acpi/device_sysfs.c @@ -533,8 +533,9 @@ int acpi_device_setup_files(struct acpi_device *dev) * If device has _STR, 'description' file is created */ if (acpi_has_method(dev->handle, "_STR")) { - status = acpi_evaluate_object(dev->handle, "_STR", - NULL, &buffer); + status = acpi_evaluate_object_typed(dev->handle, "_STR", + NULL, &buffer, + ACPI_TYPE_BUFFER); if (ACPI_FAILURE(status)) buffer.pointer = NULL; dev->pnp.str_obj = buffer.pointer; diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c index 01a6400c3234..b20206316fbe 100644 --- a/drivers/acpi/ec.c +++ b/drivers/acpi/ec.c @@ -786,6 +786,9 @@ static int acpi_ec_transaction_unlocked(struct acpi_ec *ec, unsigned long tmp; int ret = 0; + if (t->rdata) + memset(t->rdata, 0, t->rlen); + /* start transaction */ spin_lock_irqsave(&ec->lock, tmp); /* Enable GPE for command processing (IBF=0/OBF=1) */ @@ -822,8 +825,6 @@ static int acpi_ec_transaction(struct acpi_ec *ec, struct transaction *t) if (!ec || (!t) || (t->wlen && !t->wdata) || (t->rlen && !t->rdata)) return -EINVAL; - if (t->rdata) - memset(t->rdata, 0, t->rlen); mutex_lock(&ec->mutex); if (ec->global_lock) { @@ -850,7 +851,7 @@ static int acpi_ec_burst_enable(struct acpi_ec *ec) .wdata = NULL, .rdata = &d, .wlen = 0, .rlen = 1}; - return acpi_ec_transaction(ec, &t); + return acpi_ec_transaction_unlocked(ec, &t); } static int acpi_ec_burst_disable(struct acpi_ec *ec) @@ -860,7 +861,7 @@ static int acpi_ec_burst_disable(struct acpi_ec *ec) .wlen = 0, .rlen = 0}; return (acpi_ec_read_status(ec) & ACPI_EC_FLAG_BURST) ? - acpi_ec_transaction(ec, &t) : 0; + acpi_ec_transaction_unlocked(ec, &t) : 0; } static int acpi_ec_read(struct acpi_ec *ec, u8 address, u8 *data) @@ -876,6 +877,19 @@ static int acpi_ec_read(struct acpi_ec *ec, u8 address, u8 *data) return result; } +static int acpi_ec_read_unlocked(struct acpi_ec *ec, u8 address, u8 *data) +{ + int result; + u8 d; + struct transaction t = {.command = ACPI_EC_COMMAND_READ, + .wdata = &address, .rdata = &d, + .wlen = 1, .rlen = 1}; + + result = acpi_ec_transaction_unlocked(ec, &t); + *data = d; + return result; +} + static int acpi_ec_write(struct acpi_ec *ec, u8 address, u8 data) { u8 wdata[2] = { address, data }; @@ -886,6 +900,16 @@ static int acpi_ec_write(struct acpi_ec *ec, u8 address, u8 data) return acpi_ec_transaction(ec, &t); } +static int acpi_ec_write_unlocked(struct acpi_ec *ec, u8 address, u8 data) +{ + u8 wdata[2] = { address, data }; + struct transaction t = {.command = ACPI_EC_COMMAND_WRITE, + .wdata = wdata, .rdata = NULL, + .wlen = 2, .rlen = 0}; + + return acpi_ec_transaction_unlocked(ec, &t); +} + int ec_read(u8 addr, u8 *val) { int err; @@ -1306,6 +1330,7 @@ acpi_ec_space_handler(u32 function, acpi_physical_address address, struct acpi_ec *ec = handler_context; int result = 0, i, bytes = bits / 8; u8 *value = (u8 *)value64; + u32 glk; if ((address > 0xFF) || !value || !handler_context) return AE_BAD_PARAMETER; @@ -1313,13 +1338,25 @@ acpi_ec_space_handler(u32 function, acpi_physical_address address, if (function != ACPI_READ && function != ACPI_WRITE) return AE_BAD_PARAMETER; + mutex_lock(&ec->mutex); + + if (ec->global_lock) { + acpi_status status; + + status = acpi_acquire_global_lock(ACPI_EC_UDELAY_GLK, &glk); + if (ACPI_FAILURE(status)) { + result = -ENODEV; + goto unlock; + } + } + if (ec->busy_polling || bits > 8) acpi_ec_burst_enable(ec); for (i = 0; i < bytes; ++i, ++address, ++value) { result = (function == ACPI_READ) ? - acpi_ec_read(ec, address, value) : - acpi_ec_write(ec, address, *value); + acpi_ec_read_unlocked(ec, address, value) : + acpi_ec_write_unlocked(ec, address, *value); if (result < 0) break; } @@ -1327,6 +1364,12 @@ acpi_ec_space_handler(u32 function, acpi_physical_address address, if (ec->busy_polling || bits > 8) acpi_ec_burst_disable(ec); + if (ec->global_lock) + acpi_release_global_lock(glk); + +unlock: + mutex_unlock(&ec->mutex); + switch (result) { case -EINVAL: return AE_BAD_PARAMETER; diff --git a/drivers/acpi/pmic/tps68470_pmic.c b/drivers/acpi/pmic/tps68470_pmic.c index ebd03e472955..0d1a82eeb4b0 100644 --- a/drivers/acpi/pmic/tps68470_pmic.c +++ b/drivers/acpi/pmic/tps68470_pmic.c @@ -376,10 +376,8 @@ static int tps68470_pmic_opregion_probe(struct platform_device *pdev) struct tps68470_pmic_opregion *opregion; acpi_status status; - if (!dev || !tps68470_regmap) { - dev_warn(dev, "dev or regmap is NULL\n"); - return -EINVAL; - } + if (!tps68470_regmap) + return dev_err_probe(dev, -EINVAL, "regmap is missing\n"); if (!handle) { dev_warn(dev, "acpi handle is NULL\n"); diff --git a/drivers/acpi/resource.c b/drivers/acpi/resource.c index aa92ec4fe721..520acfcbf9db 100644 --- a/drivers/acpi/resource.c +++ b/drivers/acpi/resource.c @@ -442,6 +442,13 @@ static const struct dmi_system_id asus_laptop[] = { DMI_MATCH(DMI_BOARD_NAME, "B2402CBA"), }, }, + { + /* Asus Vivobook X1704VAP */ + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), + DMI_MATCH(DMI_BOARD_NAME, "X1704VAP"), + }, + }, { /* TongFang GMxXGxx/TUXEDO Polaris 15 Gen5 AMD */ .matches = { @@ -455,6 +462,12 @@ static const struct dmi_system_id asus_laptop[] = { DMI_MATCH(DMI_BOARD_NAME, "B1402CVA"), }, }, + { + /* TongFang GMxXGxX/TUXEDO Polaris 15 Gen5 AMD */ + .matches = { + DMI_MATCH(DMI_BOARD_NAME, "GMxXGxX"), + }, + }, { /* TongFang GMxXGxx sold as Eluktronics Inc. RP-15 */ .matches = { @@ -481,6 +494,13 @@ static const struct dmi_system_id asus_laptop[] = { DMI_MATCH(DMI_BOARD_NAME, "GXxHRXx"), }, }, + { + /* Asus ExpertBook B2502CVA */ + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), + DMI_MATCH(DMI_BOARD_NAME, "B2502CVA"), + }, + }, { /* TongFang GMxHGxx/TUXEDO Stellaris Slim Gen1 AMD */ .matches = { diff --git a/drivers/android/binder.c b/drivers/android/binder.c index d86f1ad27110..0eddff10c203 100644 --- a/drivers/android/binder.c +++ b/drivers/android/binder.c @@ -1283,6 +1283,10 @@ static void binder_cleanup_ref_olocked(struct binder_ref *ref) binder_dequeue_work(ref->proc, &ref->death->work); binder_stats_deleted(BINDER_STAT_DEATH); } + + if (ref->freeze) + binder_dequeue_work(ref->proc, &ref->freeze->work); + binder_stats_deleted(BINDER_STAT_REF); } @@ -3832,7 +3836,6 @@ binder_request_freeze_notification(struct binder_proc *proc, { struct binder_ref_freeze *freeze; struct binder_ref *ref; - bool is_frozen; freeze = kzalloc(sizeof(*freeze), GFP_KERNEL); if (!freeze) @@ -3848,31 +3851,30 @@ binder_request_freeze_notification(struct binder_proc *proc, } binder_node_lock(ref->node); - - if (ref->freeze || !ref->node->proc) { - binder_user_error("%d:%d invalid BC_REQUEST_FREEZE_NOTIFICATION %s\n", - proc->pid, thread->pid, - ref->freeze ? "already set" : "dead node"); + if (ref->freeze) { + binder_user_error("%d:%d BC_REQUEST_FREEZE_NOTIFICATION already set\n", + proc->pid, thread->pid); binder_node_unlock(ref->node); binder_proc_unlock(proc); kfree(freeze); return -EINVAL; } - binder_inner_proc_lock(ref->node->proc); - is_frozen = ref->node->proc->is_frozen; - binder_inner_proc_unlock(ref->node->proc); INIT_LIST_HEAD(&freeze->work.entry); freeze->cookie = handle_cookie->cookie; freeze->work.type = BINDER_WORK_FROZEN_BINDER; - freeze->is_frozen = is_frozen; - ref->freeze = freeze; - binder_inner_proc_lock(proc); - binder_enqueue_work_ilocked(&ref->freeze->work, &proc->todo); - binder_wakeup_proc_ilocked(proc); - binder_inner_proc_unlock(proc); + if (ref->node->proc) { + binder_inner_proc_lock(ref->node->proc); + freeze->is_frozen = ref->node->proc->is_frozen; + binder_inner_proc_unlock(ref->node->proc); + + binder_inner_proc_lock(proc); + binder_enqueue_work_ilocked(&freeze->work, &proc->todo); + binder_wakeup_proc_ilocked(proc); + binder_inner_proc_unlock(proc); + } binder_node_unlock(ref->node); binder_proc_unlock(proc); @@ -5145,6 +5147,15 @@ static void binder_release_work(struct binder_proc *proc, } break; case BINDER_WORK_NODE: break; + case BINDER_WORK_CLEAR_FREEZE_NOTIFICATION: { + struct binder_ref_freeze *freeze; + + freeze = container_of(w, struct binder_ref_freeze, work); + binder_debug(BINDER_DEBUG_DEAD_TRANSACTION, + "undelivered freeze notification, %016llx\n", + (u64)freeze->cookie); + kfree(freeze); + } break; default: pr_err("unexpected work type, %d, not freed\n", wtype); @@ -5558,6 +5569,7 @@ static bool binder_txns_pending_ilocked(struct binder_proc *proc) static void binder_add_freeze_work(struct binder_proc *proc, bool is_frozen) { + struct binder_node *prev = NULL; struct rb_node *n; struct binder_ref *ref; @@ -5566,7 +5578,10 @@ static void binder_add_freeze_work(struct binder_proc *proc, bool is_frozen) struct binder_node *node; node = rb_entry(n, struct binder_node, rb_node); + binder_inc_node_tmpref_ilocked(node); binder_inner_proc_unlock(proc); + if (prev) + binder_put_node(prev); binder_node_lock(node); hlist_for_each_entry(ref, &node->refs, node_entry) { /* @@ -5592,10 +5607,15 @@ static void binder_add_freeze_work(struct binder_proc *proc, bool is_frozen) } binder_inner_proc_unlock(ref->proc); } + prev = node; binder_node_unlock(node); binder_inner_proc_lock(proc); + if (proc->is_dead) + break; } binder_inner_proc_unlock(proc); + if (prev) + binder_put_node(prev); } static int binder_ioctl_freeze(struct binder_freeze_info *info, @@ -6258,6 +6278,7 @@ static void binder_deferred_release(struct binder_proc *proc) binder_release_work(proc, &proc->todo); binder_release_work(proc, &proc->delivered_death); + binder_release_work(proc, &proc_wrapper(proc)->delivered_freeze); binder_debug(BINDER_DEBUG_OPEN_CLOSE, "%s: %d threads %d, nodes %d (ref %d), refs %d, active transactions %d\n", @@ -6391,6 +6412,12 @@ static void print_binder_work_ilocked(struct seq_file *m, case BINDER_WORK_CLEAR_DEATH_NOTIFICATION: seq_printf(m, "%shas cleared death notification\n", prefix); break; + case BINDER_WORK_FROZEN_BINDER: + seq_printf(m, "%shas frozen binder\n", prefix); + break; + case BINDER_WORK_CLEAR_FREEZE_NOTIFICATION: + seq_printf(m, "%shas cleared freeze notification\n", prefix); + break; default: seq_printf(m, "%sunknown work: type %d\n", prefix, w->type); break; @@ -6540,6 +6567,10 @@ static void print_binder_proc(struct seq_file *m, seq_puts(m, " has delivered dead binder\n"); break; } + list_for_each_entry(w, &proc_wrapper(proc)->delivered_freeze, entry) { + seq_puts(m, " has delivered freeze binder\n"); + break; + } binder_inner_proc_unlock(proc); if (!print_all && m->count == header_pos) m->count = start_pos; diff --git a/drivers/android/vendor_hooks.c b/drivers/android/vendor_hooks.c index 92488977dadc..67ff78c73fe9 100644 --- a/drivers/android/vendor_hooks.c +++ b/drivers/android/vendor_hooks.c @@ -566,3 +566,4 @@ EXPORT_SYMBOL_GPL(GKI_struct_gic_chip_data); #include const struct swap_slots_cache *GKI_struct_swap_slots_cache; EXPORT_SYMBOL_GPL(GKI_struct_swap_slots_cache); +EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_io_statistics); diff --git a/drivers/ata/sata_sil.c b/drivers/ata/sata_sil.c index 75321f1ceba5..fc438c4518fb 100644 --- a/drivers/ata/sata_sil.c +++ b/drivers/ata/sata_sil.c @@ -128,7 +128,7 @@ static const struct pci_device_id sil_pci_tbl[] = { static const struct sil_drivelist { const char *product; unsigned int quirk; -} sil_blacklist [] = { +} sil_quirks[] = { { "ST320012AS", SIL_QUIRK_MOD15WRITE }, { "ST330013AS", SIL_QUIRK_MOD15WRITE }, { "ST340017AS", SIL_QUIRK_MOD15WRITE }, @@ -601,8 +601,8 @@ static void sil_thaw(struct ata_port *ap) * list, and apply the fixups to only the specific * devices/hosts/firmwares that need it. * - * 20040111 - Seagate drives affected by the Mod15Write bug are blacklisted - * The Maxtor quirk is in the blacklist, but I'm keeping the original + * 20040111 - Seagate drives affected by the Mod15Write bug are quirked + * The Maxtor quirk is in sil_quirks, but I'm keeping the original * pessimistic fix for the following reasons... * - There seems to be less info on it, only one device gleaned off the * Windows driver, maybe only one is affected. More info would be greatly @@ -621,9 +621,9 @@ static void sil_dev_config(struct ata_device *dev) ata_id_c_string(dev->id, model_num, ATA_ID_PROD, sizeof(model_num)); - for (n = 0; sil_blacklist[n].product; n++) - if (!strcmp(sil_blacklist[n].product, model_num)) { - quirks = sil_blacklist[n].quirk; + for (n = 0; sil_quirks[n].product; n++) + if (!strcmp(sil_quirks[n].product, model_num)) { + quirks = sil_quirks[n].quirk; break; } diff --git a/drivers/base/bus.c b/drivers/base/bus.c index df85e928b97f..47ab755aee94 100644 --- a/drivers/base/bus.c +++ b/drivers/base/bus.c @@ -104,7 +104,8 @@ static ssize_t bus_attr_show(struct kobject *kobj, struct attribute *attr, { struct bus_attribute *bus_attr = to_bus_attr(attr); struct subsys_private *subsys_priv = to_subsys_private(kobj); - ssize_t ret = 0; + /* return -EIO for reading a bus attribute without show() */ + ssize_t ret = -EIO; if (bus_attr->show) ret = bus_attr->show(subsys_priv->bus, buf); @@ -116,7 +117,8 @@ static ssize_t bus_attr_store(struct kobject *kobj, struct attribute *attr, { struct bus_attribute *bus_attr = to_bus_attr(attr); struct subsys_private *subsys_priv = to_subsys_private(kobj); - ssize_t ret = 0; + /* return -EIO for writing a bus attribute without store() */ + ssize_t ret = -EIO; if (bus_attr->store) ret = bus_attr->store(subsys_priv->bus, buf, count); diff --git a/drivers/base/firmware_loader/main.c b/drivers/base/firmware_loader/main.c index 9dbfdf9a5645..29753bd53f9c 100644 --- a/drivers/base/firmware_loader/main.c +++ b/drivers/base/firmware_loader/main.c @@ -787,6 +787,26 @@ static void fw_abort_batch_reqs(struct firmware *fw) mutex_unlock(&fw_lock); } +/* + * Reject firmware file names with ".." path components. + * There are drivers that construct firmware file names from device-supplied + * strings, and we don't want some device to be able to tell us "I would like to + * be sent my firmware from ../../../etc/shadow, please". + * + * Search for ".." surrounded by either '/' or start/end of string. + * + * This intentionally only looks at the firmware name, not at the firmware base + * directory or at symlink contents. + */ +static bool name_contains_dotdot(const char *name) +{ + size_t name_len = strlen(name); + + return strcmp(name, "..") == 0 || strncmp(name, "../", 3) == 0 || + strstr(name, "/../") != NULL || + (name_len >= 3 && strcmp(name+name_len-3, "/..") == 0); +} + /* called from request_firmware() and request_firmware_work_func() */ static int _request_firmware(const struct firmware **firmware_p, const char *name, @@ -805,6 +825,14 @@ _request_firmware(const struct firmware **firmware_p, const char *name, goto out; } + if (name_contains_dotdot(name)) { + dev_warn(device, + "Firmware load for '%s' refused, path contains '..' component\n", + name); + ret = -EINVAL; + goto out; + } + ret = _request_firmware_prepare(&fw, name, device, buf, size, offset, opt_flags); if (ret <= 0) /* error or already assigned */ @@ -860,6 +888,8 @@ _request_firmware(const struct firmware **firmware_p, const char *name, * @name will be used as $FIRMWARE in the uevent environment and * should be distinctive enough not to be confused with any other * firmware image for this or any other device. + * It must not contain any ".." path components - "foo/bar..bin" is + * allowed, but "foo/../bar.bin" is not. * * Caller must hold the reference count of @device. * diff --git a/drivers/block/aoe/aoecmd.c b/drivers/block/aoe/aoecmd.c index c805909c8e77..833ccf2cd5df 100644 --- a/drivers/block/aoe/aoecmd.c +++ b/drivers/block/aoe/aoecmd.c @@ -362,6 +362,7 @@ ata_rw_frameinit(struct frame *f) } ah->cmdstat = ATA_CMD_PIO_READ | writebit | extbit; + dev_hold(t->ifp->nd); skb->dev = t->ifp->nd; } @@ -402,6 +403,8 @@ aoecmd_ata_rw(struct aoedev *d) __skb_queue_head_init(&queue); __skb_queue_tail(&queue, skb); aoenet_xmit(&queue); + } else { + dev_put(f->t->ifp->nd); } return 1; } @@ -484,10 +487,13 @@ resend(struct aoedev *d, struct frame *f) memcpy(h->dst, t->addr, sizeof h->dst); memcpy(h->src, t->ifp->nd->dev_addr, sizeof h->src); + dev_hold(t->ifp->nd); skb->dev = t->ifp->nd; skb = skb_clone(skb, GFP_ATOMIC); - if (skb == NULL) + if (skb == NULL) { + dev_put(t->ifp->nd); return; + } f->sent = ktime_get(); __skb_queue_head_init(&queue); __skb_queue_tail(&queue, skb); @@ -618,6 +624,8 @@ probe(struct aoetgt *t) __skb_queue_head_init(&queue); __skb_queue_tail(&queue, skb); aoenet_xmit(&queue); + } else { + dev_put(f->t->ifp->nd); } } @@ -1403,6 +1411,7 @@ aoecmd_ata_id(struct aoedev *d) ah->cmdstat = ATA_CMD_ID_ATA; ah->lba3 = 0xa0; + dev_hold(t->ifp->nd); skb->dev = t->ifp->nd; d->rttavg = RTTAVG_INIT; @@ -1412,6 +1421,8 @@ aoecmd_ata_id(struct aoedev *d) skb = skb_clone(skb, GFP_ATOMIC); if (skb) f->sent = ktime_get(); + else + dev_put(t->ifp->nd); return skb; } diff --git a/drivers/block/drbd/drbd_main.c b/drivers/block/drbd/drbd_main.c index 420bdaf8c356..28ee47d71f1c 100644 --- a/drivers/block/drbd/drbd_main.c +++ b/drivers/block/drbd/drbd_main.c @@ -3429,10 +3429,12 @@ void drbd_uuid_new_current(struct drbd_device *device) __must_hold(local) void drbd_uuid_set_bm(struct drbd_device *device, u64 val) __must_hold(local) { unsigned long flags; - if (device->ldev->md.uuid[UI_BITMAP] == 0 && val == 0) - return; - spin_lock_irqsave(&device->ldev->md.uuid_lock, flags); + if (device->ldev->md.uuid[UI_BITMAP] == 0 && val == 0) { + spin_unlock_irqrestore(&device->ldev->md.uuid_lock, flags); + return; + } + if (val == 0) { drbd_uuid_move_history(device); device->ldev->md.uuid[UI_HISTORY_START] = device->ldev->md.uuid[UI_BITMAP]; diff --git a/drivers/block/drbd/drbd_state.c b/drivers/block/drbd/drbd_state.c index 5fbaea6b77b1..2c954bb70bff 100644 --- a/drivers/block/drbd/drbd_state.c +++ b/drivers/block/drbd/drbd_state.c @@ -876,7 +876,7 @@ is_valid_state(struct drbd_device *device, union drbd_state ns) ns.disk == D_OUTDATED) rv = SS_CONNECTED_OUTDATES; - else if ((ns.conn == C_VERIFY_S || ns.conn == C_VERIFY_T) && + else if (nc && (ns.conn == C_VERIFY_S || ns.conn == C_VERIFY_T) && (nc->verify_alg[0] == 0)) rv = SS_NO_VERIFY_ALG; diff --git a/drivers/bluetooth/btmrvl_sdio.c b/drivers/bluetooth/btmrvl_sdio.c index 33d58b30c5ac..6e40a984ba7b 100644 --- a/drivers/bluetooth/btmrvl_sdio.c +++ b/drivers/bluetooth/btmrvl_sdio.c @@ -105,7 +105,7 @@ static int btmrvl_sdio_probe_of(struct device *dev, } else { ret = devm_request_irq(dev, cfg->irq_bt, btmrvl_wake_irq_bt, - 0, "bt_wake", card); + IRQF_NO_AUTOEN, "bt_wake", card); if (ret) { dev_err(dev, "Failed to request irq_bt %d (%d)\n", @@ -114,7 +114,6 @@ static int btmrvl_sdio_probe_of(struct device *dev, /* Configure wakeup (enabled by default) */ device_init_wakeup(dev, true); - disable_irq(cfg->irq_bt); } } diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c index b0d97c9ffd26..d34c7758b93d 100644 --- a/drivers/bluetooth/btusb.c +++ b/drivers/bluetooth/btusb.c @@ -928,7 +928,15 @@ static int btusb_submit_intr_urb(struct hci_dev *hdev, gfp_t mem_flags) if (!urb) return -ENOMEM; - size = le16_to_cpu(data->intr_ep->wMaxPacketSize); + if (le16_to_cpu(data->udev->descriptor.idVendor) == 0x0a12 && + le16_to_cpu(data->udev->descriptor.idProduct) == 0x0001) + /* Fake CSR devices don't seem to support sort-transter */ + size = le16_to_cpu(data->intr_ep->wMaxPacketSize); + else + /* Use maximum HCI Event size so the USB stack handles + * ZPL/short-transfer automatically. + */ + size = HCI_MAX_EVENT_SIZE; buf = kmalloc(size, mem_flags); if (!buf) { diff --git a/drivers/bus/arm-integrator-lm.c b/drivers/bus/arm-integrator-lm.c index 845b6c43fef8..0c9bcbbeb484 100644 --- a/drivers/bus/arm-integrator-lm.c +++ b/drivers/bus/arm-integrator-lm.c @@ -84,6 +84,7 @@ static int integrator_ap_lm_probe(struct platform_device *pdev) return -ENODEV; } map = syscon_node_to_regmap(syscon); + of_node_put(syscon); if (IS_ERR(map)) { dev_err(dev, "could not find Integrator/AP system controller\n"); diff --git a/drivers/char/hw_random/cctrng.c b/drivers/char/hw_random/cctrng.c index 7a293f2147a0..9c61807dfe13 100644 --- a/drivers/char/hw_random/cctrng.c +++ b/drivers/char/hw_random/cctrng.c @@ -679,6 +679,7 @@ static int __maybe_unused cctrng_resume(struct device *dev) /* wait for Cryptocell reset completion */ if (!cctrng_wait_for_reset_completion(drvdata)) { dev_err(dev, "Cryptocell reset not completed"); + clk_disable_unprepare(drvdata->clk); return -EBUSY; } diff --git a/drivers/char/hw_random/mtk-rng.c b/drivers/char/hw_random/mtk-rng.c index 6c00ea008555..3e00506543b6 100644 --- a/drivers/char/hw_random/mtk-rng.c +++ b/drivers/char/hw_random/mtk-rng.c @@ -142,7 +142,7 @@ static int mtk_rng_probe(struct platform_device *pdev) dev_set_drvdata(&pdev->dev, priv); pm_runtime_set_autosuspend_delay(&pdev->dev, RNG_AUTOSUSPEND_TIMEOUT); pm_runtime_use_autosuspend(&pdev->dev); - pm_runtime_enable(&pdev->dev); + devm_pm_runtime_enable(&pdev->dev); dev_info(&pdev->dev, "registered RNG driver\n"); diff --git a/drivers/char/tpm/tpm-dev-common.c b/drivers/char/tpm/tpm-dev-common.c index b99e1941c52c..fde81ecbd6a3 100644 --- a/drivers/char/tpm/tpm-dev-common.c +++ b/drivers/char/tpm/tpm-dev-common.c @@ -48,6 +48,8 @@ static ssize_t tpm_dev_transmit(struct tpm_chip *chip, struct tpm_space *space, if (!ret) ret = tpm2_commit_space(chip, space, buf, &len); + else + tpm2_flush_space(chip); out_rc: return ret ? ret : len; diff --git a/drivers/char/tpm/tpm2-space.c b/drivers/char/tpm/tpm2-space.c index ffb35f0154c1..c57404c6b98c 100644 --- a/drivers/char/tpm/tpm2-space.c +++ b/drivers/char/tpm/tpm2-space.c @@ -166,6 +166,9 @@ void tpm2_flush_space(struct tpm_chip *chip) struct tpm_space *space = &chip->work_space; int i; + if (!space) + return; + for (i = 0; i < ARRAY_SIZE(space->context_tbl); i++) if (space->context_tbl[i] && ~space->context_tbl[i]) tpm2_flush_context(chip, space->context_tbl[i]); diff --git a/drivers/char/virtio_console.c b/drivers/char/virtio_console.c index 6d361420ffe8..1734b4341585 100644 --- a/drivers/char/virtio_console.c +++ b/drivers/char/virtio_console.c @@ -2049,25 +2049,27 @@ static int virtcons_probe(struct virtio_device *vdev) multiport = true; } - err = init_vqs(portdev); - if (err < 0) { - dev_err(&vdev->dev, "Error %d initializing vqs\n", err); - goto free_chrdev; - } - spin_lock_init(&portdev->ports_lock); INIT_LIST_HEAD(&portdev->ports); INIT_LIST_HEAD(&portdev->list); - virtio_device_ready(portdev->vdev); - INIT_WORK(&portdev->config_work, &config_work_handler); INIT_WORK(&portdev->control_work, &control_work_handler); if (multiport) { spin_lock_init(&portdev->c_ivq_lock); spin_lock_init(&portdev->c_ovq_lock); + } + err = init_vqs(portdev); + if (err < 0) { + dev_err(&vdev->dev, "Error %d initializing vqs\n", err); + goto free_chrdev; + } + + virtio_device_ready(portdev->vdev); + + if (multiport) { err = fill_queue(portdev->c_ivq, &portdev->c_ivq_lock); if (err < 0) { dev_err(&vdev->dev, diff --git a/drivers/clk/bcm/clk-bcm53573-ilp.c b/drivers/clk/bcm/clk-bcm53573-ilp.c index 84f2af736ee8..83ef41d618be 100644 --- a/drivers/clk/bcm/clk-bcm53573-ilp.c +++ b/drivers/clk/bcm/clk-bcm53573-ilp.c @@ -112,7 +112,7 @@ static void bcm53573_ilp_init(struct device_node *np) goto err_free_ilp; } - ilp->regmap = syscon_node_to_regmap(of_get_parent(np)); + ilp->regmap = syscon_node_to_regmap(np->parent); if (IS_ERR(ilp->regmap)) { err = PTR_ERR(ilp->regmap); goto err_free_ilp; diff --git a/drivers/clk/imx/clk-imx7d.c b/drivers/clk/imx/clk-imx7d.c index 3f6fd7ef2a68..0e68e5f2d7e7 100644 --- a/drivers/clk/imx/clk-imx7d.c +++ b/drivers/clk/imx/clk-imx7d.c @@ -498,9 +498,9 @@ static void __init imx7d_clocks_init(struct device_node *ccm_node) hws[IMX7D_ENET_AXI_ROOT_SRC] = imx_clk_hw_mux2_flags("enet_axi_src", base + 0x8900, 24, 3, enet_axi_sel, ARRAY_SIZE(enet_axi_sel), CLK_SET_PARENT_GATE); hws[IMX7D_NAND_USDHC_BUS_ROOT_SRC] = imx_clk_hw_mux2_flags("nand_usdhc_src", base + 0x8980, 24, 3, nand_usdhc_bus_sel, ARRAY_SIZE(nand_usdhc_bus_sel), CLK_SET_PARENT_GATE); hws[IMX7D_DRAM_PHYM_ROOT_SRC] = imx_clk_hw_mux2_flags("dram_phym_src", base + 0x9800, 24, 1, dram_phym_sel, ARRAY_SIZE(dram_phym_sel), CLK_SET_PARENT_GATE); - hws[IMX7D_DRAM_ROOT_SRC] = imx_clk_hw_mux2_flags("dram_src", base + 0x9880, 24, 1, dram_sel, ARRAY_SIZE(dram_sel), CLK_SET_PARENT_GATE); + hws[IMX7D_DRAM_ROOT_SRC] = imx_clk_hw_mux2("dram_src", base + 0x9880, 24, 1, dram_sel, ARRAY_SIZE(dram_sel)); hws[IMX7D_DRAM_PHYM_ALT_ROOT_SRC] = imx_clk_hw_mux2_flags("dram_phym_alt_src", base + 0xa000, 24, 3, dram_phym_alt_sel, ARRAY_SIZE(dram_phym_alt_sel), CLK_SET_PARENT_GATE); - hws[IMX7D_DRAM_ALT_ROOT_SRC] = imx_clk_hw_mux2_flags("dram_alt_src", base + 0xa080, 24, 3, dram_alt_sel, ARRAY_SIZE(dram_alt_sel), CLK_SET_PARENT_GATE); + hws[IMX7D_DRAM_ALT_ROOT_SRC] = imx_clk_hw_mux2("dram_alt_src", base + 0xa080, 24, 3, dram_alt_sel, ARRAY_SIZE(dram_alt_sel)); hws[IMX7D_USB_HSIC_ROOT_SRC] = imx_clk_hw_mux2_flags("usb_hsic_src", base + 0xa100, 24, 3, usb_hsic_sel, ARRAY_SIZE(usb_hsic_sel), CLK_SET_PARENT_GATE); hws[IMX7D_PCIE_CTRL_ROOT_SRC] = imx_clk_hw_mux2_flags("pcie_ctrl_src", base + 0xa180, 24, 3, pcie_ctrl_sel, ARRAY_SIZE(pcie_ctrl_sel), CLK_SET_PARENT_GATE); hws[IMX7D_PCIE_PHY_ROOT_SRC] = imx_clk_hw_mux2_flags("pcie_phy_src", base + 0xa200, 24, 3, pcie_phy_sel, ARRAY_SIZE(pcie_phy_sel), CLK_SET_PARENT_GATE); diff --git a/drivers/clk/imx/clk-imx8mp.c b/drivers/clk/imx/clk-imx8mp.c index 148572852e70..56d45caa603f 100644 --- a/drivers/clk/imx/clk-imx8mp.c +++ b/drivers/clk/imx/clk-imx8mp.c @@ -579,8 +579,8 @@ static int imx8mp_clocks_probe(struct platform_device *pdev) hws[IMX8MP_CLK_IPG_ROOT] = imx_clk_hw_divider2("ipg_root", "ahb_root", ccm_base + 0x9080, 0, 1); hws[IMX8MP_CLK_IPG_AUDIO_ROOT] = imx_clk_hw_divider2("ipg_audio_root", "audio_ahb", ccm_base + 0x9180, 0, 1); - hws[IMX8MP_CLK_DRAM_ALT] = imx8m_clk_hw_composite("dram_alt", imx8mp_dram_alt_sels, ccm_base + 0xa000); - hws[IMX8MP_CLK_DRAM_APB] = imx8m_clk_hw_composite_critical("dram_apb", imx8mp_dram_apb_sels, ccm_base + 0xa080); + hws[IMX8MP_CLK_DRAM_ALT] = imx8m_clk_hw_fw_managed_composite("dram_alt", imx8mp_dram_alt_sels, ccm_base + 0xa000); + hws[IMX8MP_CLK_DRAM_APB] = imx8m_clk_hw_fw_managed_composite_critical("dram_apb", imx8mp_dram_apb_sels, ccm_base + 0xa080); hws[IMX8MP_CLK_VPU_G1] = imx8m_clk_hw_composite("vpu_g1", imx8mp_vpu_g1_sels, ccm_base + 0xa100); hws[IMX8MP_CLK_VPU_G2] = imx8m_clk_hw_composite("vpu_g2", imx8mp_vpu_g2_sels, ccm_base + 0xa180); hws[IMX8MP_CLK_CAN1] = imx8m_clk_hw_composite("can1", imx8mp_can1_sels, ccm_base + 0xa200); diff --git a/drivers/clk/qcom/dispcc-sm8250.c b/drivers/clk/qcom/dispcc-sm8250.c index 07a98d3f882d..bbdd27946bf1 100644 --- a/drivers/clk/qcom/dispcc-sm8250.c +++ b/drivers/clk/qcom/dispcc-sm8250.c @@ -665,6 +665,7 @@ static struct clk_branch disp_cc_mdss_dp_link1_intf_clk = { .hw = &disp_cc_mdss_dp_link1_div_clk_src.clkr.hw, }, .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, .ops = &clk_branch2_ops, }, }, @@ -700,6 +701,7 @@ static struct clk_branch disp_cc_mdss_dp_link_intf_clk = { .hw = &disp_cc_mdss_dp_link_div_clk_src.clkr.hw, }, .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, .ops = &clk_branch2_ops, }, }, @@ -825,6 +827,7 @@ static struct clk_branch disp_cc_mdss_mdp_lut_clk = { .hw = &disp_cc_mdss_mdp_clk_src.clkr.hw, }, .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, .ops = &clk_branch2_ops, }, }, diff --git a/drivers/clk/qcom/gcc-sm8250.c b/drivers/clk/qcom/gcc-sm8250.c index 70723e4dab00..4b36f83fb31b 100644 --- a/drivers/clk/qcom/gcc-sm8250.c +++ b/drivers/clk/qcom/gcc-sm8250.c @@ -3229,7 +3229,7 @@ static struct gdsc pcie_0_gdsc = { .pd = { .name = "pcie_0_gdsc", }, - .pwrsts = PWRSTS_OFF_ON, + .pwrsts = PWRSTS_RET_ON, }; static struct gdsc pcie_1_gdsc = { @@ -3237,7 +3237,7 @@ static struct gdsc pcie_1_gdsc = { .pd = { .name = "pcie_1_gdsc", }, - .pwrsts = PWRSTS_OFF_ON, + .pwrsts = PWRSTS_RET_ON, }; static struct gdsc pcie_2_gdsc = { @@ -3245,7 +3245,7 @@ static struct gdsc pcie_2_gdsc = { .pd = { .name = "pcie_2_gdsc", }, - .pwrsts = PWRSTS_OFF_ON, + .pwrsts = PWRSTS_RET_ON, }; static struct gdsc ufs_card_gdsc = { diff --git a/drivers/clk/rockchip/clk-rk3228.c b/drivers/clk/rockchip/clk-rk3228.c index 47d6482dda9d..a2b4d5487514 100644 --- a/drivers/clk/rockchip/clk-rk3228.c +++ b/drivers/clk/rockchip/clk-rk3228.c @@ -408,7 +408,7 @@ static struct rockchip_clk_branch rk3228_clk_branches[] __initdata = { RK2928_CLKSEL_CON(29), 0, 3, DFLAGS), DIV(0, "sclk_vop_pre", "sclk_vop_src", 0, RK2928_CLKSEL_CON(27), 8, 8, DFLAGS), - MUX(DCLK_VOP, "dclk_vop", mux_dclk_vop_p, 0, + MUX(DCLK_VOP, "dclk_vop", mux_dclk_vop_p, CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT, RK2928_CLKSEL_CON(27), 1, 1, MFLAGS), FACTOR(0, "xin12m", "xin24m", 0, 1, 2), diff --git a/drivers/clk/rockchip/clk.c b/drivers/clk/rockchip/clk.c index b443169dd408..09683c97e6cc 100644 --- a/drivers/clk/rockchip/clk.c +++ b/drivers/clk/rockchip/clk.c @@ -442,12 +442,13 @@ void rockchip_clk_register_branches(struct rockchip_clk_provider *ctx, struct rockchip_clk_branch *list, unsigned int nr_clk) { - struct clk *clk = NULL; + struct clk *clk; unsigned int idx; unsigned long flags; for (idx = 0; idx < nr_clk; idx++, list++) { flags = list->flags; + clk = NULL; /* catch simple muxes */ switch (list->branch_type) { diff --git a/drivers/clk/ti/clk-dra7-atl.c b/drivers/clk/ti/clk-dra7-atl.c index 62508e74a47a..fc266c0ab629 100644 --- a/drivers/clk/ti/clk-dra7-atl.c +++ b/drivers/clk/ti/clk-dra7-atl.c @@ -258,6 +258,7 @@ static int of_dra7_atl_clk_probe(struct platform_device *pdev) } clk = of_clk_get_from_provider(&clkspec); + of_node_put(clkspec.np); if (IS_ERR(clk)) { pr_err("%s: failed to get atl clock %d from provider\n", __func__, i); diff --git a/drivers/clocksource/timer-qcom.c b/drivers/clocksource/timer-qcom.c index b4afe3a67583..eac4c95c6127 100644 --- a/drivers/clocksource/timer-qcom.c +++ b/drivers/clocksource/timer-qcom.c @@ -233,6 +233,7 @@ static int __init msm_dt_timer_init(struct device_node *np) } if (of_property_read_u32(np, "clock-frequency", &freq)) { + iounmap(cpu0_base); pr_err("Unknown frequency\n"); return -EINVAL; } @@ -243,7 +244,11 @@ static int __init msm_dt_timer_init(struct device_node *np) freq /= 4; writel_relaxed(DGT_CLK_CTL_DIV_4, source_base + DGT_CLK_CTL); - return msm_timer_init(freq, 32, irq, !!percpu_offset); + ret = msm_timer_init(freq, 32, irq, !!percpu_offset); + if (ret) + iounmap(cpu0_base); + + return ret; } TIMER_OF_DECLARE(kpss_timer, "qcom,kpss-timer", msm_dt_timer_init); TIMER_OF_DECLARE(scss_timer, "qcom,scss-timer", msm_dt_timer_init); diff --git a/drivers/cpufreq/ti-cpufreq.c b/drivers/cpufreq/ti-cpufreq.c index 8f9fdd864391..0d100f869ae1 100644 --- a/drivers/cpufreq/ti-cpufreq.c +++ b/drivers/cpufreq/ti-cpufreq.c @@ -53,6 +53,9 @@ struct ti_cpufreq_soc_data { unsigned long efuse_shift; unsigned long rev_offset; bool multi_regulator; +/* Backward compatibility hack: Might have missing syscon */ +#define TI_QUIRK_SYSCON_MAY_BE_MISSING 0x1 + u8 quirks; }; struct ti_cpufreq_data { @@ -156,6 +159,7 @@ static struct ti_cpufreq_soc_data omap34xx_soc_data = { .efuse_mask = BIT(3), .rev_offset = OMAP3_CONTROL_IDCODE - OMAP3_SYSCON_BASE, .multi_regulator = false, + .quirks = TI_QUIRK_SYSCON_MAY_BE_MISSING, }; /* @@ -183,6 +187,7 @@ static struct ti_cpufreq_soc_data omap36xx_soc_data = { .efuse_mask = BIT(9), .rev_offset = OMAP3_CONTROL_IDCODE - OMAP3_SYSCON_BASE, .multi_regulator = true, + .quirks = TI_QUIRK_SYSCON_MAY_BE_MISSING, }; /* @@ -197,6 +202,7 @@ static struct ti_cpufreq_soc_data am3517_soc_data = { .efuse_mask = 0, .rev_offset = OMAP3_CONTROL_IDCODE - OMAP3_SYSCON_BASE, .multi_regulator = false, + .quirks = TI_QUIRK_SYSCON_MAY_BE_MISSING, }; @@ -216,7 +222,7 @@ static int ti_cpufreq_get_efuse(struct ti_cpufreq_data *opp_data, ret = regmap_read(opp_data->syscon, opp_data->soc_data->efuse_offset, &efuse); - if (ret == -EIO) { + if (opp_data->soc_data->quirks & TI_QUIRK_SYSCON_MAY_BE_MISSING && ret == -EIO) { /* not a syscon register! */ void __iomem *regs = ioremap(OMAP3_SYSCON_BASE + opp_data->soc_data->efuse_offset, 4); @@ -257,7 +263,7 @@ static int ti_cpufreq_get_rev(struct ti_cpufreq_data *opp_data, ret = regmap_read(opp_data->syscon, opp_data->soc_data->rev_offset, &revision); - if (ret == -EIO) { + if (opp_data->soc_data->quirks & TI_QUIRK_SYSCON_MAY_BE_MISSING && ret == -EIO) { /* not a syscon register! */ void __iomem *regs = ioremap(OMAP3_SYSCON_BASE + opp_data->soc_data->rev_offset, 4); diff --git a/drivers/crypto/ccp/sev-dev.c b/drivers/crypto/ccp/sev-dev.c index 055cbb2ad75e..b6bba46b330f 100644 --- a/drivers/crypto/ccp/sev-dev.c +++ b/drivers/crypto/ccp/sev-dev.c @@ -1129,6 +1129,8 @@ void sev_pci_init(void) return; err: + sev_dev_destroy(psp_master); + psp_master->sev_data = NULL; } diff --git a/drivers/firmware/efi/libstub/tpm.c b/drivers/firmware/efi/libstub/tpm.c index 7acbac16eae0..95da291c3083 100644 --- a/drivers/firmware/efi/libstub/tpm.c +++ b/drivers/firmware/efi/libstub/tpm.c @@ -115,7 +115,7 @@ void efi_retrieve_tpm2_eventlog(void) } /* Allocate space for the logs and copy them. */ - status = efi_bs_call(allocate_pool, EFI_LOADER_DATA, + status = efi_bs_call(allocate_pool, EFI_ACPI_RECLAIM_MEMORY, sizeof(*log_tbl) + log_size, (void **)&log_tbl); if (status != EFI_SUCCESS) { diff --git a/drivers/firmware/tegra/bpmp.c b/drivers/firmware/tegra/bpmp.c index 5654c5e9862b..ff9a73585cdc 100644 --- a/drivers/firmware/tegra/bpmp.c +++ b/drivers/firmware/tegra/bpmp.c @@ -25,12 +25,6 @@ #define MSG_RING BIT(1) #define TAG_SZ 32 -static inline struct tegra_bpmp * -mbox_client_to_bpmp(struct mbox_client *client) -{ - return container_of(client, struct tegra_bpmp, mbox.client); -} - static inline const struct tegra_bpmp_ops * channel_to_ops(struct tegra_bpmp_channel *channel) { diff --git a/drivers/gpio/gpio-aspeed.c b/drivers/gpio/gpio-aspeed.c index bbd04a63fb12..a70c499c2a19 100644 --- a/drivers/gpio/gpio-aspeed.c +++ b/drivers/gpio/gpio-aspeed.c @@ -404,6 +404,8 @@ static void __aspeed_gpio_set(struct gpio_chip *gc, unsigned int offset, gpio->dcache[GPIO_BANK(offset)] = reg; iowrite32(reg, addr); + /* Flush write */ + ioread32(addr); } static void aspeed_gpio_set(struct gpio_chip *gc, unsigned int offset, @@ -1157,7 +1159,7 @@ static int __init aspeed_gpio_probe(struct platform_device *pdev) if (!gpio_id) return -EINVAL; - gpio->clk = of_clk_get(pdev->dev.of_node, 0); + gpio->clk = devm_clk_get_enabled(&pdev->dev, NULL); if (IS_ERR(gpio->clk)) { dev_warn(&pdev->dev, "Failed to get clock from devicetree, debouncing disabled\n"); diff --git a/drivers/gpio/gpio-davinci.c b/drivers/gpio/gpio-davinci.c index 33623bcfc886..62ad1d818a31 100644 --- a/drivers/gpio/gpio-davinci.c +++ b/drivers/gpio/gpio-davinci.c @@ -293,7 +293,7 @@ static int davinci_gpio_probe(struct platform_device *pdev) * serve as EDMA event triggers. */ -static void gpio_irq_disable(struct irq_data *d) +static void gpio_irq_mask(struct irq_data *d) { struct davinci_gpio_regs __iomem *g = irq2regs(d); uintptr_t mask = (uintptr_t)irq_data_get_irq_handler_data(d); @@ -302,7 +302,7 @@ static void gpio_irq_disable(struct irq_data *d) writel_relaxed(mask, &g->clr_rising); } -static void gpio_irq_enable(struct irq_data *d) +static void gpio_irq_unmask(struct irq_data *d) { struct davinci_gpio_regs __iomem *g = irq2regs(d); uintptr_t mask = (uintptr_t)irq_data_get_irq_handler_data(d); @@ -328,8 +328,8 @@ static int gpio_irq_type(struct irq_data *d, unsigned trigger) static struct irq_chip gpio_irqchip = { .name = "GPIO", - .irq_enable = gpio_irq_enable, - .irq_disable = gpio_irq_disable, + .irq_unmask = gpio_irq_unmask, + .irq_mask = gpio_irq_mask, .irq_set_type = gpio_irq_type, .flags = IRQCHIP_SET_TYPE_MASKED | IRQCHIP_SKIP_SET_WAKE, }; diff --git a/drivers/gpio/gpiolib-cdev.c b/drivers/gpio/gpiolib-cdev.c index 95861916deff..56eb2be71e25 100644 --- a/drivers/gpio/gpiolib-cdev.c +++ b/drivers/gpio/gpiolib-cdev.c @@ -1110,15 +1110,18 @@ static long linereq_set_config_unlocked(struct linereq *lr, for (i = 0; i < lr->num_lines; i++) { desc = lr->lines[i].desc; flags = gpio_v2_line_config_flags(lc, i); + /* + * Lines not explicitly reconfigured as input or output + * are left unchanged. + */ + if (!(flags & GPIO_V2_LINE_DIRECTION_FLAGS)) + continue; + polarity_change = (!!test_bit(FLAG_ACTIVE_LOW, &desc->flags) != ((flags & GPIO_V2_LINE_FLAG_ACTIVE_LOW) != 0)); gpio_v2_line_config_flags_to_desc_flags(flags, &desc->flags); - /* - * Lines have to be requested explicitly for input - * or output, else the line will be treated "as is". - */ if (flags & GPIO_V2_LINE_FLAG_OUTPUT) { int val = gpio_v2_line_config_output_value(lc, i); @@ -1126,7 +1129,7 @@ static long linereq_set_config_unlocked(struct linereq *lr, ret = gpiod_direction_output(desc, val); if (ret) return ret; - } else if (flags & GPIO_V2_LINE_FLAG_INPUT) { + } else { ret = gpiod_direction_input(desc); if (ret) return ret; diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index 6b3481d09716..1ded55b63b0a 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -4,6 +4,7 @@ #include #include #include +#include #include #include #include @@ -147,7 +148,7 @@ struct gpio_desc *gpiochip_get_desc(struct gpio_chip *gc, if (hwnum >= gdev->ngpio) return ERR_PTR(-EINVAL); - return &gdev->descs[hwnum]; + return &gdev->descs[array_index_nospec(hwnum, gdev->ngpio)]; } EXPORT_SYMBOL_GPL(gpiochip_get_desc); diff --git a/drivers/gpu/drm/amd/amdgpu/atombios_encoders.c b/drivers/gpu/drm/amd/amdgpu/atombios_encoders.c index 8339c8c3a328..9030f7151171 100644 --- a/drivers/gpu/drm/amd/amdgpu/atombios_encoders.c +++ b/drivers/gpu/drm/amd/amdgpu/atombios_encoders.c @@ -2098,23 +2098,29 @@ amdgpu_atombios_encoder_get_lcd_info(struct amdgpu_encoder *encoder) fake_edid_record = (ATOM_FAKE_EDID_PATCH_RECORD *)record; if (fake_edid_record->ucFakeEDIDLength) { struct edid *edid; - int edid_size = - max((int)EDID_LENGTH, (int)fake_edid_record->ucFakeEDIDLength); - edid = kmalloc(edid_size, GFP_KERNEL); - if (edid) { - memcpy((u8 *)edid, (u8 *)&fake_edid_record->ucFakeEDIDString[0], - fake_edid_record->ucFakeEDIDLength); + int edid_size; + if (fake_edid_record->ucFakeEDIDLength == 128) + edid_size = fake_edid_record->ucFakeEDIDLength; + else + edid_size = fake_edid_record->ucFakeEDIDLength * 128; + edid = kmemdup(&fake_edid_record->ucFakeEDIDString[0], + edid_size, GFP_KERNEL); + if (edid) { if (drm_edid_is_valid(edid)) { adev->mode_info.bios_hardcoded_edid = edid; adev->mode_info.bios_hardcoded_edid_size = edid_size; - } else + } else { kfree(edid); + } } + record += struct_size(fake_edid_record, + ucFakeEDIDString, + edid_size); + } else { + /* empty fake edid record must be 3 bytes long */ + record += sizeof(ATOM_FAKE_EDID_PATCH_RECORD) + 1; } - record += fake_edid_record->ucFakeEDIDLength ? - fake_edid_record->ucFakeEDIDLength + 2 : - sizeof(ATOM_FAKE_EDID_PATCH_RECORD); break; case LCD_PANEL_RESOLUTION_RECORD_TYPE: panel_res_record = (ATOM_PANEL_RESOLUTION_PATCH_RECORD *)record; diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c index acef2227d992..432c24f3c798 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c @@ -1250,6 +1250,10 @@ static const struct amdgpu_gfxoff_quirk amdgpu_gfxoff_quirk_list[] = { { 0x1002, 0x15dd, 0x1002, 0x15dd, 0xc6 }, /* Apple MacBook Pro (15-inch, 2019) Radeon Pro Vega 20 4 GB */ { 0x1002, 0x69af, 0x106b, 0x019a, 0xc0 }, + /* https://bbs.openkylin.top/t/topic/171497 */ + { 0x1002, 0x15d8, 0x19e5, 0x3e14, 0xc2 }, + /* HP 705G4 DM with R5 2400G */ + { 0x1002, 0x15dd, 0x103c, 0x8464, 0xd6 }, { 0, 0, 0, 0, 0 }, }; diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c index 767b3d31c720..509c5556692a 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c @@ -201,7 +201,7 @@ static bool validate_dsc_caps_on_connector(struct amdgpu_dm_connector *aconnecto aconnector->dsc_aux = &aconnector->mst_port->dm_dp_aux.aux; /* synaptics cascaded MST hub case */ - if (!aconnector->dsc_aux && is_synaptics_cascaded_panamera(aconnector->dc_link, port)) + if (is_synaptics_cascaded_panamera(aconnector->dc_link, port)) aconnector->dsc_aux = port->mgr->aux; if (!aconnector->dsc_aux) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 272252cd0500..84fb1377ec93 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -1258,7 +1258,7 @@ bool dc_validate_seamless_boot_timing(const struct dc *dc, if (crtc_timing->pix_clk_100hz != pix_clk_100hz) return false; - if (!se->funcs->dp_get_pixel_format) + if (!se || !se->funcs->dp_get_pixel_format) return false; if (!se->funcs->dp_get_pixel_format( @@ -2614,7 +2614,8 @@ static void commit_planes_for_stream(struct dc *dc, dc->hwss.pipe_control_lock(dc, top_pipe_to_program, false); if ((update_type != UPDATE_TYPE_FAST) && stream->update_flags.bits.dsc_changed) - if (top_pipe_to_program->stream_res.tg->funcs->lock_doublebuffer_enable) { + if (top_pipe_to_program && + top_pipe_to_program->stream_res.tg->funcs->lock_doublebuffer_enable) { top_pipe_to_program->stream_res.tg->funcs->wait_for_state( top_pipe_to_program->stream_res.tg, CRTC_STATE_VACTIVE); @@ -3082,7 +3083,8 @@ void dc_allow_idle_optimizations(struct dc *dc, bool allow) if (allow == dc->idle_optimizations_allowed) return; - if (dc->hwss.apply_idle_power_optimizations && dc->hwss.apply_idle_power_optimizations(dc, allow)) + if (dc->hwss.apply_idle_power_optimizations && dc->clk_mgr != NULL && + dc->hwss.apply_idle_power_optimizations(dc, allow)) dc->idle_optimizations_allowed = allow; } diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index 0a13c06eea44..3af9591baa76 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -1697,6 +1697,8 @@ static bool are_stream_backends_same( bool dc_is_stream_unchanged( struct dc_stream_state *old_stream, struct dc_stream_state *stream) { + if (!old_stream || !stream) + return false; if (!are_stream_backends_same(old_stream, stream)) return false; diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_cm_common.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_cm_common.c index bd9bc51983fe..da7aeb9c4632 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_cm_common.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_cm_common.c @@ -560,6 +560,8 @@ bool cm_helper_translate_curve_to_degamma_hw_format( i += increment) { if (j == hw_points - 1) break; + if (i >= TRANSFER_FUNC_POINTS) + return false; rgb_resulted[j].red = output_tf->tf_pts.red[i]; rgb_resulted[j].green = output_tf->tf_pts.green[i]; rgb_resulted[j].blue = output_tf->tf_pts.blue[i]; diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_cm_common.c b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_cm_common.c index e0df9b0065f9..62c02adae7e7 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_cm_common.c +++ b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_cm_common.c @@ -178,6 +178,8 @@ bool cm3_helper_translate_curve_to_hw_format( i += increment) { if (j == hw_points - 1) break; + if (i >= TRANSFER_FUNC_POINTS) + return false; rgb_resulted[j].red = output_tf->tf_pts.red[i]; rgb_resulted[j].green = output_tf->tf_pts.green[i]; rgb_resulted[j].blue = output_tf->tf_pts.blue[i]; @@ -355,6 +357,8 @@ bool cm3_helper_translate_curve_to_degamma_hw_format( i += increment) { if (j == hw_points - 1) break; + if (i >= TRANSFER_FUNC_POINTS) + return false; rgb_resulted[j].red = output_tf->tf_pts.red[i]; rgb_resulted[j].green = output_tf->tf_pts.green[i]; rgb_resulted[j].blue = output_tf->tf_pts.blue[i]; diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn20/display_rq_dlg_calc_20v2.c b/drivers/gpu/drm/amd/display/dc/dml/dcn20/display_rq_dlg_calc_20v2.c index b1208088a1df..665e34643f5f 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dcn20/display_rq_dlg_calc_20v2.c +++ b/drivers/gpu/drm/amd/display/dc/dml/dcn20/display_rq_dlg_calc_20v2.c @@ -78,7 +78,7 @@ static void calculate_ttu_cursor(struct display_mode_lib *mode_lib, static unsigned int get_bytes_per_element(enum source_format_class source_format, bool is_chroma) { - unsigned int ret_val = 0; + unsigned int ret_val = 1; if (source_format == dm_444_16) { if (!is_chroma) diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn21/display_rq_dlg_calc_21.c b/drivers/gpu/drm/amd/display/dc/dml/dcn21/display_rq_dlg_calc_21.c index bca9406b03b3..d9984d285d34 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dcn21/display_rq_dlg_calc_21.c +++ b/drivers/gpu/drm/amd/display/dc/dml/dcn21/display_rq_dlg_calc_21.c @@ -53,7 +53,7 @@ static void calculate_ttu_cursor( static unsigned int get_bytes_per_element(enum source_format_class source_format, bool is_chroma) { - unsigned int ret_val = 0; + unsigned int ret_val = 1; if (source_format == dm_444_16) { if (!is_chroma) diff --git a/drivers/gpu/drm/amd/display/modules/freesync/freesync.c b/drivers/gpu/drm/amd/display/modules/freesync/freesync.c index 627d578175cf..6725ce27662c 100644 --- a/drivers/gpu/drm/amd/display/modules/freesync/freesync.c +++ b/drivers/gpu/drm/amd/display/modules/freesync/freesync.c @@ -131,7 +131,7 @@ static unsigned int calc_v_total_from_refresh( v_total = div64_u64(div64_u64(((unsigned long long)( frame_duration_in_ns) * (stream->timing.pix_clk_100hz / 10)), - stream->timing.h_total), 1000000); + stream->timing.h_total) + 500000, 1000000); /* v_total cannot be less than nominal */ if (v_total < stream->timing.v_total) { diff --git a/drivers/gpu/drm/amd/include/atombios.h b/drivers/gpu/drm/amd/include/atombios.h index 8ba21747b40a..c9f70accd46d 100644 --- a/drivers/gpu/drm/amd/include/atombios.h +++ b/drivers/gpu/drm/amd/include/atombios.h @@ -4107,7 +4107,7 @@ typedef struct _ATOM_FAKE_EDID_PATCH_RECORD { UCHAR ucRecordType; UCHAR ucFakeEDIDLength; // = 128 means EDID length is 128 bytes, otherwise the EDID length = ucFakeEDIDLength*128 - UCHAR ucFakeEDIDString[1]; // This actually has ucFakeEdidLength elements. + UCHAR ucFakeEDIDString[]; // This actually has ucFakeEdidLength elements. } ATOM_FAKE_EDID_PATCH_RECORD; typedef struct _ATOM_PANEL_RESOLUTION_PATCH_RECORD diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/processpptables.c b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/processpptables.c index 6606511891e3..04bf14cdefad 100644 --- a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/processpptables.c +++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/processpptables.c @@ -1189,6 +1189,8 @@ static int init_overdrive_limits(struct pp_hwmgr *hwmgr, fw_info = smu_atom_get_data_table(hwmgr->adev, GetIndexIntoMasterTable(DATA, FirmwareInfo), &size, &frev, &crev); + PP_ASSERT_WITH_CODE(fw_info != NULL, + "Missing firmware info!", return -EINVAL); if ((fw_info->ucTableFormatRevision == 1) && (le16_to_cpu(fw_info->usStructureSize) >= sizeof(ATOM_FIRMWARE_INFO_V1_4))) diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_kms.c b/drivers/gpu/drm/arm/display/komeda/komeda_kms.c index 1f6682032ca4..ac8b7fb20d8f 100644 --- a/drivers/gpu/drm/arm/display/komeda/komeda_kms.c +++ b/drivers/gpu/drm/arm/display/komeda/komeda_kms.c @@ -142,6 +142,7 @@ static int komeda_crtc_normalize_zpos(struct drm_crtc *crtc, struct drm_plane *plane; struct list_head zorder_list; int order = 0, err; + u32 slave_zpos = 0; DRM_DEBUG_ATOMIC("[CRTC:%d:%s] calculating normalized zpos values\n", crtc->base.id, crtc->name); @@ -181,10 +182,13 @@ static int komeda_crtc_normalize_zpos(struct drm_crtc *crtc, plane_st->zpos, plane_st->normalized_zpos); /* calculate max slave zorder */ - if (has_bit(drm_plane_index(plane), kcrtc->slave_planes)) + if (has_bit(drm_plane_index(plane), kcrtc->slave_planes)) { + slave_zpos = plane_st->normalized_zpos; + if (to_kplane_st(plane_st)->layer_split) + slave_zpos++; kcrtc_st->max_slave_zorder = - max(plane_st->normalized_zpos, - kcrtc_st->max_slave_zorder); + max(slave_zpos, kcrtc_st->max_slave_zorder); + } } crtc_st->zpos_changed = true; diff --git a/drivers/gpu/drm/drm_atomic_uapi.c b/drivers/gpu/drm/drm_atomic_uapi.c index b6062833370f..f6d8bee10fa0 100644 --- a/drivers/gpu/drm/drm_atomic_uapi.c +++ b/drivers/gpu/drm/drm_atomic_uapi.c @@ -584,7 +584,7 @@ static int drm_atomic_plane_set_property(struct drm_plane *plane, &state->fb_damage_clips, val, -1, - sizeof(struct drm_rect), + sizeof(struct drm_mode_rect), &replaced); return ret; } else if (plane->funcs->atomic_set_property) { diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c index 4ed3fc28d4da..5d2cbff02df1 100644 --- a/drivers/gpu/drm/drm_crtc.c +++ b/drivers/gpu/drm/drm_crtc.c @@ -754,6 +754,7 @@ int drm_mode_setcrtc(struct drm_device *dev, void *data, connector_set = NULL; fb = NULL; mode = NULL; + num_connectors = 0; DRM_MODESET_LOCK_ALL_END(dev, ctx, ret); diff --git a/drivers/gpu/drm/drm_print.c b/drivers/gpu/drm/drm_print.c index 111b932cf2a9..02fdf001b047 100644 --- a/drivers/gpu/drm/drm_print.c +++ b/drivers/gpu/drm/drm_print.c @@ -78,8 +78,9 @@ void __drm_puts_coredump(struct drm_printer *p, const char *str) copy = iterator->remain; /* Copy out the bit of the string that we need */ - memcpy(iterator->data, - str + (iterator->start - iterator->offset), copy); + if (iterator->data) + memcpy(iterator->data, + str + (iterator->start - iterator->offset), copy); iterator->offset = iterator->start + copy; iterator->remain -= copy; @@ -88,7 +89,8 @@ void __drm_puts_coredump(struct drm_printer *p, const char *str) len = min_t(ssize_t, strlen(str), iterator->remain); - memcpy(iterator->data + pos, str, len); + if (iterator->data) + memcpy(iterator->data + pos, str, len); iterator->offset += len; iterator->remain -= len; @@ -118,8 +120,9 @@ void __drm_printfn_coredump(struct drm_printer *p, struct va_format *vaf) if ((iterator->offset >= iterator->start) && (len < iterator->remain)) { ssize_t pos = iterator->offset - iterator->start; - snprintf(((char *) iterator->data) + pos, - iterator->remain, "%pV", vaf); + if (iterator->data) + snprintf(((char *) iterator->data) + pos, + iterator->remain, "%pV", vaf); iterator->offset += len; iterator->remain -= len; diff --git a/drivers/gpu/drm/exynos/exynos_drm_gsc.c b/drivers/gpu/drm/exynos/exynos_drm_gsc.c index bcf830c5b8ea..1bc2afcf9f08 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_gsc.c +++ b/drivers/gpu/drm/exynos/exynos_drm_gsc.c @@ -1169,7 +1169,7 @@ static int gsc_bind(struct device *dev, struct device *master, void *data) struct exynos_drm_ipp *ipp = &ctx->ipp; ctx->drm_dev = drm_dev; - ctx->drm_dev = drm_dev; + ipp->drm_dev = drm_dev; exynos_drm_register_dma(drm_dev, dev, &ctx->dma_priv); exynos_drm_ipp_register(dev, ipp, &ipp_funcs, diff --git a/drivers/gpu/drm/msm/adreno/a2xx_gpu.c b/drivers/gpu/drm/msm/adreno/a2xx_gpu.c index 64ee63dcdb7c..caa791eb746f 100644 --- a/drivers/gpu/drm/msm/adreno/a2xx_gpu.c +++ b/drivers/gpu/drm/msm/adreno/a2xx_gpu.c @@ -12,7 +12,6 @@ static bool a2xx_idle(struct msm_gpu *gpu); static void a2xx_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit) { - struct msm_drm_private *priv = gpu->dev->dev_private; struct msm_ringbuffer *ring = submit->ring; unsigned int i; @@ -23,7 +22,7 @@ static void a2xx_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit) break; case MSM_SUBMIT_CMD_CTX_RESTORE_BUF: /* ignore if there has not been a ctx switch: */ - if (priv->lastctx == submit->queue->ctx) + if (gpu->cur_ctx_seqno == submit->queue->ctx->seqno) break; fallthrough; case MSM_SUBMIT_CMD_BUF: diff --git a/drivers/gpu/drm/msm/adreno/a3xx_gpu.c b/drivers/gpu/drm/msm/adreno/a3xx_gpu.c index f29c77d9cd42..7e5d0afa05db 100644 --- a/drivers/gpu/drm/msm/adreno/a3xx_gpu.c +++ b/drivers/gpu/drm/msm/adreno/a3xx_gpu.c @@ -30,7 +30,6 @@ static bool a3xx_idle(struct msm_gpu *gpu); static void a3xx_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit) { - struct msm_drm_private *priv = gpu->dev->dev_private; struct msm_ringbuffer *ring = submit->ring; unsigned int i; @@ -41,7 +40,7 @@ static void a3xx_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit) break; case MSM_SUBMIT_CMD_CTX_RESTORE_BUF: /* ignore if there has not been a ctx switch: */ - if (priv->lastctx == submit->queue->ctx) + if (gpu->cur_ctx_seqno == submit->queue->ctx->seqno) break; fallthrough; case MSM_SUBMIT_CMD_BUF: diff --git a/drivers/gpu/drm/msm/adreno/a4xx_gpu.c b/drivers/gpu/drm/msm/adreno/a4xx_gpu.c index 2b93b33b05e4..f6d22fba9c1b 100644 --- a/drivers/gpu/drm/msm/adreno/a4xx_gpu.c +++ b/drivers/gpu/drm/msm/adreno/a4xx_gpu.c @@ -24,7 +24,6 @@ static bool a4xx_idle(struct msm_gpu *gpu); static void a4xx_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit) { - struct msm_drm_private *priv = gpu->dev->dev_private; struct msm_ringbuffer *ring = submit->ring; unsigned int i; @@ -35,7 +34,7 @@ static void a4xx_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit) break; case MSM_SUBMIT_CMD_CTX_RESTORE_BUF: /* ignore if there has not been a ctx switch: */ - if (priv->lastctx == submit->queue->ctx) + if (gpu->cur_ctx_seqno == submit->queue->ctx->seqno) break; fallthrough; case MSM_SUBMIT_CMD_BUF: diff --git a/drivers/gpu/drm/msm/adreno/a5xx_gpu.c b/drivers/gpu/drm/msm/adreno/a5xx_gpu.c index 9ae0e60ecac3..e0cf42323cf9 100644 --- a/drivers/gpu/drm/msm/adreno/a5xx_gpu.c +++ b/drivers/gpu/drm/msm/adreno/a5xx_gpu.c @@ -56,7 +56,8 @@ void a5xx_flush(struct msm_gpu *gpu, struct msm_ringbuffer *ring, static void a5xx_submit_in_rb(struct msm_gpu *gpu, struct msm_gem_submit *submit) { - struct msm_drm_private *priv = gpu->dev->dev_private; + struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu); + struct a5xx_gpu *a5xx_gpu = to_a5xx_gpu(adreno_gpu); struct msm_ringbuffer *ring = submit->ring; struct msm_gem_object *obj; uint32_t *ptr, dwords; @@ -67,7 +68,7 @@ static void a5xx_submit_in_rb(struct msm_gpu *gpu, struct msm_gem_submit *submit case MSM_SUBMIT_CMD_IB_TARGET_BUF: break; case MSM_SUBMIT_CMD_CTX_RESTORE_BUF: - if (priv->lastctx == submit->queue->ctx) + if (gpu->cur_ctx_seqno == submit->queue->ctx->seqno) break; fallthrough; case MSM_SUBMIT_CMD_BUF: @@ -101,6 +102,7 @@ static void a5xx_submit_in_rb(struct msm_gpu *gpu, struct msm_gem_submit *submit } } + a5xx_gpu->last_seqno[ring->id] = submit->seqno; a5xx_flush(gpu, ring, true); a5xx_preempt_trigger(gpu); @@ -117,12 +119,11 @@ static void a5xx_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit) { struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu); struct a5xx_gpu *a5xx_gpu = to_a5xx_gpu(adreno_gpu); - struct msm_drm_private *priv = gpu->dev->dev_private; struct msm_ringbuffer *ring = submit->ring; unsigned int i, ibs = 0; if (IS_ENABLED(CONFIG_DRM_MSM_GPU_SUDO) && submit->in_rb) { - priv->lastctx = NULL; + gpu->cur_ctx_seqno = 0; a5xx_submit_in_rb(gpu, submit); return; } @@ -143,9 +144,13 @@ static void a5xx_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit) OUT_PKT7(ring, CP_SET_PROTECTED_MODE, 1); OUT_RING(ring, 1); - /* Enable local preemption for finegrain preemption */ + /* + * Disable local preemption by default because it requires + * user-space to be aware of it and provide additional handling + * to restore rendering state or do various flushes on switch. + */ OUT_PKT7(ring, CP_PREEMPT_ENABLE_LOCAL, 1); - OUT_RING(ring, 0x1); + OUT_RING(ring, 0x0); /* Allow CP_CONTEXT_SWITCH_YIELD packets in the IB2 */ OUT_PKT7(ring, CP_YIELD_ENABLE, 1); @@ -157,7 +162,7 @@ static void a5xx_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit) case MSM_SUBMIT_CMD_IB_TARGET_BUF: break; case MSM_SUBMIT_CMD_CTX_RESTORE_BUF: - if (priv->lastctx == submit->queue->ctx) + if (gpu->cur_ctx_seqno == submit->queue->ctx->seqno) break; fallthrough; case MSM_SUBMIT_CMD_BUF: @@ -189,6 +194,7 @@ static void a5xx_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit) /* Write the fence to the scratch register */ OUT_PKT4(ring, REG_A5XX_CP_SCRATCH_REG(2), 1); OUT_RING(ring, submit->seqno); + a5xx_gpu->last_seqno[ring->id] = submit->seqno; /* * Execute a CACHE_FLUSH_TS event. This will ensure that the diff --git a/drivers/gpu/drm/msm/adreno/a5xx_gpu.h b/drivers/gpu/drm/msm/adreno/a5xx_gpu.h index c7187bcc5e90..9c0d701fe4b8 100644 --- a/drivers/gpu/drm/msm/adreno/a5xx_gpu.h +++ b/drivers/gpu/drm/msm/adreno/a5xx_gpu.h @@ -34,8 +34,10 @@ struct a5xx_gpu { struct drm_gem_object *preempt_counters_bo[MSM_GPU_MAX_RINGS]; struct a5xx_preempt_record *preempt[MSM_GPU_MAX_RINGS]; uint64_t preempt_iova[MSM_GPU_MAX_RINGS]; + uint32_t last_seqno[MSM_GPU_MAX_RINGS]; atomic_t preempt_state; + spinlock_t preempt_start_lock; struct timer_list preempt_timer; struct drm_gem_object *shadow_bo; diff --git a/drivers/gpu/drm/msm/adreno/a5xx_preempt.c b/drivers/gpu/drm/msm/adreno/a5xx_preempt.c index b8e71ad6f8d8..8976c30df1a2 100644 --- a/drivers/gpu/drm/msm/adreno/a5xx_preempt.c +++ b/drivers/gpu/drm/msm/adreno/a5xx_preempt.c @@ -55,6 +55,8 @@ static inline void update_wptr(struct msm_gpu *gpu, struct msm_ringbuffer *ring) /* Return the highest priority ringbuffer with something in it */ static struct msm_ringbuffer *get_next_ring(struct msm_gpu *gpu) { + struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu); + struct a5xx_gpu *a5xx_gpu = to_a5xx_gpu(adreno_gpu); unsigned long flags; int i; @@ -64,6 +66,8 @@ static struct msm_ringbuffer *get_next_ring(struct msm_gpu *gpu) spin_lock_irqsave(&ring->preempt_lock, flags); empty = (get_wptr(ring) == gpu->funcs->get_rptr(gpu, ring)); + if (!empty && ring == a5xx_gpu->cur_ring) + empty = ring->memptrs->fence == a5xx_gpu->last_seqno[i]; spin_unlock_irqrestore(&ring->preempt_lock, flags); if (!empty) @@ -98,12 +102,19 @@ void a5xx_preempt_trigger(struct msm_gpu *gpu) if (gpu->nr_rings == 1) return; + /* + * Serialize preemption start to ensure that we always make + * decision on latest state. Otherwise we can get stuck in + * lower priority or empty ring. + */ + spin_lock_irqsave(&a5xx_gpu->preempt_start_lock, flags); + /* * Try to start preemption by moving from NONE to START. If * unsuccessful, a preemption is already in flight */ if (!try_preempt_state(a5xx_gpu, PREEMPT_NONE, PREEMPT_START)) - return; + goto out; /* Get the next ring to preempt to */ ring = get_next_ring(gpu); @@ -128,9 +139,11 @@ void a5xx_preempt_trigger(struct msm_gpu *gpu) set_preempt_state(a5xx_gpu, PREEMPT_ABORT); update_wptr(gpu, a5xx_gpu->cur_ring); set_preempt_state(a5xx_gpu, PREEMPT_NONE); - return; + goto out; } + spin_unlock_irqrestore(&a5xx_gpu->preempt_start_lock, flags); + /* Make sure the wptr doesn't update while we're in motion */ spin_lock_irqsave(&ring->preempt_lock, flags); a5xx_gpu->preempt[ring->id]->wptr = get_wptr(ring); @@ -154,6 +167,10 @@ void a5xx_preempt_trigger(struct msm_gpu *gpu) /* And actually start the preemption */ gpu_write(gpu, REG_A5XX_CP_CONTEXT_SWITCH_CNTL, 1); + return; + +out: + spin_unlock_irqrestore(&a5xx_gpu->preempt_start_lock, flags); } void a5xx_preempt_irq(struct msm_gpu *gpu) @@ -191,6 +208,12 @@ void a5xx_preempt_irq(struct msm_gpu *gpu) update_wptr(gpu, a5xx_gpu->cur_ring); set_preempt_state(a5xx_gpu, PREEMPT_NONE); + + /* + * Try to trigger preemption again in case there was a submit or + * retire during ring switch + */ + a5xx_preempt_trigger(gpu); } void a5xx_preempt_hw_init(struct msm_gpu *gpu) @@ -207,6 +230,8 @@ void a5xx_preempt_hw_init(struct msm_gpu *gpu) return; for (i = 0; i < gpu->nr_rings; i++) { + a5xx_gpu->preempt[i]->data = 0; + a5xx_gpu->preempt[i]->info = 0; a5xx_gpu->preempt[i]->wptr = 0; a5xx_gpu->preempt[i]->rptr = 0; a5xx_gpu->preempt[i]->rbase = gpu->rb[i]->iova; @@ -303,5 +328,6 @@ void a5xx_preempt_init(struct msm_gpu *gpu) } } + spin_lock_init(&a5xx_gpu->preempt_start_lock); timer_setup(&a5xx_gpu->preempt_timer, a5xx_preempt_timer, 0); } diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c index 29b40acedb38..a78f47a788f7 100644 --- a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c +++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c @@ -99,7 +99,7 @@ static void a6xx_set_pagetable(struct a6xx_gpu *a6xx_gpu, u32 asid; u64 memptr = rbmemptr(ring, ttbr0); - if (ctx->seqno == a6xx_gpu->cur_ctx_seqno) + if (ctx->seqno == a6xx_gpu->base.base.cur_ctx_seqno) return; if (msm_iommu_pagetable_params(ctx->aspace->mmu, &ttbr, &asid)) @@ -131,14 +131,11 @@ static void a6xx_set_pagetable(struct a6xx_gpu *a6xx_gpu, OUT_PKT7(ring, CP_EVENT_WRITE, 1); OUT_RING(ring, 0x31); - - a6xx_gpu->cur_ctx_seqno = ctx->seqno; } static void a6xx_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit) { unsigned int index = submit->seqno % MSM_GPU_SUBMIT_STATS_COUNT; - struct msm_drm_private *priv = gpu->dev->dev_private; struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu); struct a6xx_gpu *a6xx_gpu = to_a6xx_gpu(adreno_gpu); struct msm_ringbuffer *ring = submit->ring; @@ -170,7 +167,7 @@ static void a6xx_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit) case MSM_SUBMIT_CMD_IB_TARGET_BUF: break; case MSM_SUBMIT_CMD_CTX_RESTORE_BUF: - if (priv->lastctx == submit->queue->ctx) + if (gpu->cur_ctx_seqno == submit->queue->ctx->seqno) break; fallthrough; case MSM_SUBMIT_CMD_BUF: @@ -887,7 +884,7 @@ static int a6xx_hw_init(struct msm_gpu *gpu) /* Always come up on rb 0 */ a6xx_gpu->cur_ring = gpu->rb[0]; - a6xx_gpu->cur_ctx_seqno = 0; + gpu->cur_ctx_seqno = 0; /* Enable the SQE_to start the CP engine */ gpu_write(gpu, REG_A6XX_CP_SQE_CNTL, 1); diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gpu.h b/drivers/gpu/drm/msm/adreno/a6xx_gpu.h index f923edbd5daa..189daaf77744 100644 --- a/drivers/gpu/drm/msm/adreno/a6xx_gpu.h +++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu.h @@ -20,16 +20,6 @@ struct a6xx_gpu { struct msm_ringbuffer *cur_ring; - /** - * cur_ctx_seqno: - * - * The ctx->seqno value of the context with current pgtables - * installed. Tracked by seqno rather than pointer value to - * avoid dangling pointers, and cases where a ctx can be freed - * and a new one created with the same address. - */ - int cur_ctx_seqno; - struct a6xx_gmu gmu; struct drm_gem_object *shadow_bo; diff --git a/drivers/gpu/drm/msm/adreno/adreno_gpu.c b/drivers/gpu/drm/msm/adreno/adreno_gpu.c index 11a6a41b4910..773bd463ad47 100644 --- a/drivers/gpu/drm/msm/adreno/adreno_gpu.c +++ b/drivers/gpu/drm/msm/adreno/adreno_gpu.c @@ -93,7 +93,7 @@ static int zap_shader_load_mdt(struct msm_gpu *gpu, const char *fwname, * was a bad idea, and is only provided for backwards * compatibility for older targets. */ - return -ENODEV; + return -ENOENT; } if (IS_ERR(fw)) { @@ -308,7 +308,7 @@ adreno_request_fw(struct adreno_gpu *adreno_gpu, const char *fwname) ret = request_firmware_direct(&fw, fwname, drm->dev); if (!ret) { DRM_DEV_INFO(drm->dev, "loaded %s from legacy location\n", - newname); + fwname); adreno_gpu->fwloc = FW_LOCATION_LEGACY; goto out; } else if (adreno_gpu->fwloc != FW_LOCATION_UNKNOWN) { diff --git a/drivers/gpu/drm/msm/disp/mdp5/mdp5_smp.c b/drivers/gpu/drm/msm/disp/mdp5/mdp5_smp.c index d7fa2c49e741..45820ac1a525 100644 --- a/drivers/gpu/drm/msm/disp/mdp5/mdp5_smp.c +++ b/drivers/gpu/drm/msm/disp/mdp5/mdp5_smp.c @@ -356,7 +356,7 @@ void mdp5_smp_dump(struct mdp5_smp *smp, struct drm_printer *p) drm_printf(p, "%s:%d\t%d\t%s\n", pipe2name(pipe), j, inuse, - plane ? plane->name : NULL); + plane ? plane->name : "(null)"); total += inuse; } diff --git a/drivers/gpu/drm/msm/dsi/dsi_host.c b/drivers/gpu/drm/msm/dsi/dsi_host.c index fb7792ca39e2..b69099b533bf 100644 --- a/drivers/gpu/drm/msm/dsi/dsi_host.c +++ b/drivers/gpu/drm/msm/dsi/dsi_host.c @@ -685,7 +685,7 @@ static u32 dsi_get_pclk_rate(struct msm_dsi_host *msm_host, bool is_dual_dsi) struct drm_display_mode *mode = msm_host->mode; u32 pclk_rate; - pclk_rate = mode->clock * 1000; + pclk_rate = mode->clock * 1000u; /* * For dual DSI mode, the current DRM mode has the complete width of the diff --git a/drivers/gpu/drm/msm/msm_debugfs.c b/drivers/gpu/drm/msm/msm_debugfs.c index 7a7ccad65c92..97cbb850ad6d 100644 --- a/drivers/gpu/drm/msm/msm_debugfs.c +++ b/drivers/gpu/drm/msm/msm_debugfs.c @@ -113,6 +113,11 @@ static int msm_gem_show(struct drm_device *dev, struct seq_file *m) { struct msm_drm_private *priv = dev->dev_private; struct msm_gpu *gpu = priv->gpu; + int ret; + + ret = mutex_lock_interruptible(&priv->mm_lock); + if (ret) + return ret; if (gpu) { seq_printf(m, "Active Objects (%s):\n", gpu->name); @@ -122,6 +127,8 @@ static int msm_gem_show(struct drm_device *dev, struct seq_file *m) seq_printf(m, "Inactive Objects:\n"); msm_gem_describe_objects(&priv->inactive_list, m); + mutex_unlock(&priv->mm_lock); + return 0; } diff --git a/drivers/gpu/drm/msm/msm_drv.c b/drivers/gpu/drm/msm/msm_drv.c index 087efcb1f34c..d7a7113dcafa 100644 --- a/drivers/gpu/drm/msm/msm_drv.c +++ b/drivers/gpu/drm/msm/msm_drv.c @@ -7,6 +7,7 @@ #include #include +#include #include #include @@ -442,6 +443,12 @@ static int msm_drm_init(struct device *dev, struct drm_driver *drv) init_llist_head(&priv->free_list); INIT_LIST_HEAD(&priv->inactive_list); + mutex_init(&priv->mm_lock); + + /* Teach lockdep about lock ordering wrt. shrinker: */ + fs_reclaim_acquire(GFP_KERNEL); + might_lock(&priv->mm_lock); + fs_reclaim_release(GFP_KERNEL); drm_mode_config_init(ddev); @@ -619,14 +626,8 @@ static void context_close(struct msm_file_private *ctx) static void msm_postclose(struct drm_device *dev, struct drm_file *file) { - struct msm_drm_private *priv = dev->dev_private; struct msm_file_private *ctx = file->driver_priv; - mutex_lock(&dev->struct_mutex); - if (ctx == priv->lastctx) - priv->lastctx = NULL; - mutex_unlock(&dev->struct_mutex); - context_close(ctx); } diff --git a/drivers/gpu/drm/msm/msm_drv.h b/drivers/gpu/drm/msm/msm_drv.h index 1fe809add8f6..52da60bbf6b3 100644 --- a/drivers/gpu/drm/msm/msm_drv.h +++ b/drivers/gpu/drm/msm/msm_drv.h @@ -165,7 +165,7 @@ struct msm_drm_private { /* when we have more than one 'msm_gpu' these need to be an array: */ struct msm_gpu *gpu; - struct msm_file_private *lastctx; + /* gpu is only set on open(), but we need this info earlier */ bool is_a2xx; @@ -175,8 +175,19 @@ struct msm_drm_private { struct msm_rd_state *hangrd; /* debugfs to dump hanging submits */ struct msm_perf_state *perf; - /* list of GEM objects: */ + /* + * List of inactive GEM objects. Every bo is either in the inactive_list + * or gpu->active_list (for the gpu it is active on[1]) + * + * These lists are protected by mm_lock. If struct_mutex is involved, it + * should be aquired prior to mm_lock. One should *not* hold mm_lock in + * get_pages()/vmap()/etc paths, as they can trigger the shrinker. + * + * [1] if someone ever added support for the old 2d cores, there could be + * more than one gpu object + */ struct list_head inactive_list; + struct mutex mm_lock; /* worker for delayed free of objects: */ struct work_struct free_work; diff --git a/drivers/gpu/drm/msm/msm_gem.c b/drivers/gpu/drm/msm/msm_gem.c index 9c05bf6c4551..d0201909ee7a 100644 --- a/drivers/gpu/drm/msm/msm_gem.c +++ b/drivers/gpu/drm/msm/msm_gem.c @@ -745,13 +745,17 @@ int msm_gem_sync_object(struct drm_gem_object *obj, void msm_gem_active_get(struct drm_gem_object *obj, struct msm_gpu *gpu) { struct msm_gem_object *msm_obj = to_msm_bo(obj); - WARN_ON(!mutex_is_locked(&obj->dev->struct_mutex)); + struct msm_drm_private *priv = obj->dev->dev_private; + + might_sleep(); WARN_ON(msm_obj->madv != MSM_MADV_WILLNEED); if (!atomic_fetch_inc(&msm_obj->active_count)) { + mutex_lock(&priv->mm_lock); msm_obj->gpu = gpu; list_del_init(&msm_obj->mm_list); list_add_tail(&msm_obj->mm_list, &gpu->active_list); + mutex_unlock(&priv->mm_lock); } } @@ -760,12 +764,14 @@ void msm_gem_active_put(struct drm_gem_object *obj) struct msm_gem_object *msm_obj = to_msm_bo(obj); struct msm_drm_private *priv = obj->dev->dev_private; - WARN_ON(!mutex_is_locked(&obj->dev->struct_mutex)); + might_sleep(); if (!atomic_dec_return(&msm_obj->active_count)) { + mutex_lock(&priv->mm_lock); msm_obj->gpu = NULL; list_del_init(&msm_obj->mm_list); list_add_tail(&msm_obj->mm_list, &priv->inactive_list); + mutex_unlock(&priv->mm_lock); } } @@ -921,13 +927,16 @@ static void free_object(struct msm_gem_object *msm_obj) { struct drm_gem_object *obj = &msm_obj->base; struct drm_device *dev = obj->dev; + struct msm_drm_private *priv = dev->dev_private; WARN_ON(!mutex_is_locked(&dev->struct_mutex)); /* object should not be on active list: */ WARN_ON(is_active(msm_obj)); + mutex_lock(&priv->mm_lock); list_del(&msm_obj->mm_list); + mutex_unlock(&priv->mm_lock); mutex_lock(&msm_obj->lock); @@ -1103,14 +1112,9 @@ static struct drm_gem_object *_msm_gem_new(struct drm_device *dev, mapping_set_gfp_mask(obj->filp->f_mapping, GFP_HIGHUSER); } - if (struct_mutex_locked) { - WARN_ON(!mutex_is_locked(&dev->struct_mutex)); - list_add_tail(&msm_obj->mm_list, &priv->inactive_list); - } else { - mutex_lock(&dev->struct_mutex); - list_add_tail(&msm_obj->mm_list, &priv->inactive_list); - mutex_unlock(&dev->struct_mutex); - } + mutex_lock(&priv->mm_lock); + list_add_tail(&msm_obj->mm_list, &priv->inactive_list); + mutex_unlock(&priv->mm_lock); return obj; @@ -1174,9 +1178,9 @@ struct drm_gem_object *msm_gem_import(struct drm_device *dev, mutex_unlock(&msm_obj->lock); - mutex_lock(&dev->struct_mutex); + mutex_lock(&priv->mm_lock); list_add_tail(&msm_obj->mm_list, &priv->inactive_list); - mutex_unlock(&dev->struct_mutex); + mutex_unlock(&priv->mm_lock); return obj; diff --git a/drivers/gpu/drm/msm/msm_gem_shrinker.c b/drivers/gpu/drm/msm/msm_gem_shrinker.c index 482576d7a39a..c41b84a3a484 100644 --- a/drivers/gpu/drm/msm/msm_gem_shrinker.c +++ b/drivers/gpu/drm/msm/msm_gem_shrinker.c @@ -51,11 +51,15 @@ msm_gem_shrinker_count(struct shrinker *shrinker, struct shrink_control *sc) if (!msm_gem_shrinker_lock(dev, &unlock)) return 0; + mutex_lock(&priv->mm_lock); + list_for_each_entry(msm_obj, &priv->inactive_list, mm_list) { if (is_purgeable(msm_obj)) count += msm_obj->base.size >> PAGE_SHIFT; } + mutex_unlock(&priv->mm_lock); + if (unlock) mutex_unlock(&dev->struct_mutex); @@ -75,6 +79,8 @@ msm_gem_shrinker_scan(struct shrinker *shrinker, struct shrink_control *sc) if (!msm_gem_shrinker_lock(dev, &unlock)) return SHRINK_STOP; + mutex_lock(&priv->mm_lock); + list_for_each_entry(msm_obj, &priv->inactive_list, mm_list) { if (freed >= sc->nr_to_scan) break; @@ -84,6 +90,8 @@ msm_gem_shrinker_scan(struct shrinker *shrinker, struct shrink_control *sc) } } + mutex_unlock(&priv->mm_lock); + if (unlock) mutex_unlock(&dev->struct_mutex); @@ -106,6 +114,8 @@ msm_gem_shrinker_vmap(struct notifier_block *nb, unsigned long event, void *ptr) if (!msm_gem_shrinker_lock(dev, &unlock)) return NOTIFY_DONE; + mutex_lock(&priv->mm_lock); + list_for_each_entry(msm_obj, &priv->inactive_list, mm_list) { if (is_vunmapable(msm_obj)) { msm_gem_vunmap(&msm_obj->base, OBJ_LOCK_SHRINKER); @@ -118,6 +128,8 @@ msm_gem_shrinker_vmap(struct notifier_block *nb, unsigned long event, void *ptr) } } + mutex_unlock(&priv->mm_lock); + if (unlock) mutex_unlock(&dev->struct_mutex); diff --git a/drivers/gpu/drm/msm/msm_gpu.c b/drivers/gpu/drm/msm/msm_gpu.c index 90c26da10902..c5f3c561ecc6 100644 --- a/drivers/gpu/drm/msm/msm_gpu.c +++ b/drivers/gpu/drm/msm/msm_gpu.c @@ -795,7 +795,7 @@ void msm_gpu_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit) } gpu->funcs->submit(gpu, submit); - priv->lastctx = submit->queue->ctx; + gpu->cur_ctx_seqno = submit->queue->ctx->seqno; hangcheck_timer_reset(gpu); } diff --git a/drivers/gpu/drm/msm/msm_gpu.h b/drivers/gpu/drm/msm/msm_gpu.h index 6c9e1fdc1a76..b1feaae50b9e 100644 --- a/drivers/gpu/drm/msm/msm_gpu.h +++ b/drivers/gpu/drm/msm/msm_gpu.h @@ -94,7 +94,21 @@ struct msm_gpu { struct msm_ringbuffer *rb[MSM_GPU_MAX_RINGS]; int nr_rings; - /* list of GEM active objects: */ + /** + * cur_ctx_seqno: + * + * The ctx->seqno value of the last context to submit rendering, + * and the one with current pgtables installed (for generations + * that support per-context pgtables). Tracked by seqno rather + * than pointer value to avoid dangling pointers, and cases where + * a ctx can be freed and a new one created with the same address. + */ + int cur_ctx_seqno; + + /* + * List of GEM active objects on this gpu. Protected by + * msm_drm_private::mm_lock + */ struct list_head active_list; /* does gpu need hw_init? */ diff --git a/drivers/gpu/drm/nouveau/nouveau_dmem.c b/drivers/gpu/drm/nouveau/nouveau_dmem.c index 5e72e6cb2f84..56729fc39733 100644 --- a/drivers/gpu/drm/nouveau/nouveau_dmem.c +++ b/drivers/gpu/drm/nouveau/nouveau_dmem.c @@ -149,7 +149,7 @@ static vm_fault_t nouveau_dmem_fault_copy_one(struct nouveau_drm *drm, if (!spage || !(args->src[0] & MIGRATE_PFN_MIGRATE)) return 0; - dpage = alloc_page_vma(GFP_HIGHUSER, vmf->vma, vmf->address); + dpage = alloc_page_vma(GFP_HIGHUSER | __GFP_ZERO, vmf->vma, vmf->address); if (!dpage) return VM_FAULT_SIGBUS; lock_page(dpage); diff --git a/drivers/gpu/drm/omapdrm/dss/dispc.c b/drivers/gpu/drm/omapdrm/dss/dispc.c index 48593932bddf..e06c2c131061 100644 --- a/drivers/gpu/drm/omapdrm/dss/dispc.c +++ b/drivers/gpu/drm/omapdrm/dss/dispc.c @@ -2077,9 +2077,8 @@ static s32 pixinc(int pixels, u8 ps) return 1 + (pixels - 1) * ps; else if (pixels < 0) return 1 - (-pixels + 1) * ps; - else - BUG(); - return 0; + + BUG(); } static void calc_offset(u16 screen_width, u16 width, diff --git a/drivers/gpu/drm/omapdrm/omap_drv.c b/drivers/gpu/drm/omapdrm/omap_drv.c index 53d5e184ee77..8c664ef0cf62 100644 --- a/drivers/gpu/drm/omapdrm/omap_drv.c +++ b/drivers/gpu/drm/omapdrm/omap_drv.c @@ -600,6 +600,10 @@ static int omapdrm_init(struct omap_drm_private *priv, struct device *dev) soc = soc_device_match(omapdrm_soc_devices); priv->omaprev = soc ? (unsigned int)soc->data : 0; priv->wq = alloc_ordered_workqueue("omapdrm", 0); + if (!priv->wq) { + ret = -ENOMEM; + goto err_alloc_workqueue; + } mutex_init(&priv->list_lock); INIT_LIST_HEAD(&priv->obj_list); @@ -649,6 +653,7 @@ static int omapdrm_init(struct omap_drm_private *priv, struct device *dev) err_gem_deinit: omap_gem_deinit(ddev); destroy_workqueue(priv->wq); +err_alloc_workqueue: omap_disconnect_pipelines(ddev); omap_crtc_pre_uninit(priv); drm_dev_put(ddev); diff --git a/drivers/gpu/drm/radeon/atombios.h b/drivers/gpu/drm/radeon/atombios.h index 4b86e8b45009..e3f496464764 100644 --- a/drivers/gpu/drm/radeon/atombios.h +++ b/drivers/gpu/drm/radeon/atombios.h @@ -3615,7 +3615,7 @@ typedef struct _ATOM_FAKE_EDID_PATCH_RECORD { UCHAR ucRecordType; UCHAR ucFakeEDIDLength; - UCHAR ucFakeEDIDString[1]; // This actually has ucFakeEdidLength elements. + UCHAR ucFakeEDIDString[]; // This actually has ucFakeEdidLength elements. } ATOM_FAKE_EDID_PATCH_RECORD; typedef struct _ATOM_PANEL_RESOLUTION_PATCH_RECORD diff --git a/drivers/gpu/drm/radeon/evergreen_cs.c b/drivers/gpu/drm/radeon/evergreen_cs.c index c410cad28f19..468efa5ac8fc 100644 --- a/drivers/gpu/drm/radeon/evergreen_cs.c +++ b/drivers/gpu/drm/radeon/evergreen_cs.c @@ -396,7 +396,7 @@ static int evergreen_cs_track_validate_cb(struct radeon_cs_parser *p, unsigned i struct evergreen_cs_track *track = p->track; struct eg_surface surf; unsigned pitch, slice, mslice; - unsigned long offset; + u64 offset; int r; mslice = G_028C6C_SLICE_MAX(track->cb_color_view[id]) + 1; @@ -434,14 +434,14 @@ static int evergreen_cs_track_validate_cb(struct radeon_cs_parser *p, unsigned i return r; } - offset = track->cb_color_bo_offset[id] << 8; + offset = (u64)track->cb_color_bo_offset[id] << 8; if (offset & (surf.base_align - 1)) { - dev_warn(p->dev, "%s:%d cb[%d] bo base %ld not aligned with %ld\n", + dev_warn(p->dev, "%s:%d cb[%d] bo base %llu not aligned with %ld\n", __func__, __LINE__, id, offset, surf.base_align); return -EINVAL; } - offset += surf.layer_size * mslice; + offset += (u64)surf.layer_size * mslice; if (offset > radeon_bo_size(track->cb_color_bo[id])) { /* old ddx are broken they allocate bo with w*h*bpp but * program slice with ALIGN(h, 8), catch this and patch @@ -449,14 +449,14 @@ static int evergreen_cs_track_validate_cb(struct radeon_cs_parser *p, unsigned i */ if (!surf.mode) { uint32_t *ib = p->ib.ptr; - unsigned long tmp, nby, bsize, size, min = 0; + u64 tmp, nby, bsize, size, min = 0; /* find the height the ddx wants */ if (surf.nby > 8) { min = surf.nby - 8; } bsize = radeon_bo_size(track->cb_color_bo[id]); - tmp = track->cb_color_bo_offset[id] << 8; + tmp = (u64)track->cb_color_bo_offset[id] << 8; for (nby = surf.nby; nby > min; nby--) { size = nby * surf.nbx * surf.bpe * surf.nsamples; if ((tmp + size * mslice) <= bsize) { @@ -468,7 +468,7 @@ static int evergreen_cs_track_validate_cb(struct radeon_cs_parser *p, unsigned i slice = ((nby * surf.nbx) / 64) - 1; if (!evergreen_surface_check(p, &surf, "cb")) { /* check if this one works */ - tmp += surf.layer_size * mslice; + tmp += (u64)surf.layer_size * mslice; if (tmp <= bsize) { ib[track->cb_color_slice_idx[id]] = slice; goto old_ddx_ok; @@ -477,9 +477,9 @@ static int evergreen_cs_track_validate_cb(struct radeon_cs_parser *p, unsigned i } } dev_warn(p->dev, "%s:%d cb[%d] bo too small (layer size %d, " - "offset %d, max layer %d, bo size %ld, slice %d)\n", + "offset %llu, max layer %d, bo size %ld, slice %d)\n", __func__, __LINE__, id, surf.layer_size, - track->cb_color_bo_offset[id] << 8, mslice, + (u64)track->cb_color_bo_offset[id] << 8, mslice, radeon_bo_size(track->cb_color_bo[id]), slice); dev_warn(p->dev, "%s:%d problematic surf: (%d %d) (%d %d %d %d %d %d %d)\n", __func__, __LINE__, surf.nbx, surf.nby, @@ -563,7 +563,7 @@ static int evergreen_cs_track_validate_stencil(struct radeon_cs_parser *p) struct evergreen_cs_track *track = p->track; struct eg_surface surf; unsigned pitch, slice, mslice; - unsigned long offset; + u64 offset; int r; mslice = G_028008_SLICE_MAX(track->db_depth_view) + 1; @@ -609,18 +609,18 @@ static int evergreen_cs_track_validate_stencil(struct radeon_cs_parser *p) return r; } - offset = track->db_s_read_offset << 8; + offset = (u64)track->db_s_read_offset << 8; if (offset & (surf.base_align - 1)) { - dev_warn(p->dev, "%s:%d stencil read bo base %ld not aligned with %ld\n", + dev_warn(p->dev, "%s:%d stencil read bo base %llu not aligned with %ld\n", __func__, __LINE__, offset, surf.base_align); return -EINVAL; } - offset += surf.layer_size * mslice; + offset += (u64)surf.layer_size * mslice; if (offset > radeon_bo_size(track->db_s_read_bo)) { dev_warn(p->dev, "%s:%d stencil read bo too small (layer size %d, " - "offset %ld, max layer %d, bo size %ld)\n", + "offset %llu, max layer %d, bo size %ld)\n", __func__, __LINE__, surf.layer_size, - (unsigned long)track->db_s_read_offset << 8, mslice, + (u64)track->db_s_read_offset << 8, mslice, radeon_bo_size(track->db_s_read_bo)); dev_warn(p->dev, "%s:%d stencil invalid (0x%08x 0x%08x 0x%08x 0x%08x)\n", __func__, __LINE__, track->db_depth_size, @@ -628,18 +628,18 @@ static int evergreen_cs_track_validate_stencil(struct radeon_cs_parser *p) return -EINVAL; } - offset = track->db_s_write_offset << 8; + offset = (u64)track->db_s_write_offset << 8; if (offset & (surf.base_align - 1)) { - dev_warn(p->dev, "%s:%d stencil write bo base %ld not aligned with %ld\n", + dev_warn(p->dev, "%s:%d stencil write bo base %llu not aligned with %ld\n", __func__, __LINE__, offset, surf.base_align); return -EINVAL; } - offset += surf.layer_size * mslice; + offset += (u64)surf.layer_size * mslice; if (offset > radeon_bo_size(track->db_s_write_bo)) { dev_warn(p->dev, "%s:%d stencil write bo too small (layer size %d, " - "offset %ld, max layer %d, bo size %ld)\n", + "offset %llu, max layer %d, bo size %ld)\n", __func__, __LINE__, surf.layer_size, - (unsigned long)track->db_s_write_offset << 8, mslice, + (u64)track->db_s_write_offset << 8, mslice, radeon_bo_size(track->db_s_write_bo)); return -EINVAL; } @@ -660,7 +660,7 @@ static int evergreen_cs_track_validate_depth(struct radeon_cs_parser *p) struct evergreen_cs_track *track = p->track; struct eg_surface surf; unsigned pitch, slice, mslice; - unsigned long offset; + u64 offset; int r; mslice = G_028008_SLICE_MAX(track->db_depth_view) + 1; @@ -707,34 +707,34 @@ static int evergreen_cs_track_validate_depth(struct radeon_cs_parser *p) return r; } - offset = track->db_z_read_offset << 8; + offset = (u64)track->db_z_read_offset << 8; if (offset & (surf.base_align - 1)) { - dev_warn(p->dev, "%s:%d stencil read bo base %ld not aligned with %ld\n", + dev_warn(p->dev, "%s:%d stencil read bo base %llu not aligned with %ld\n", __func__, __LINE__, offset, surf.base_align); return -EINVAL; } - offset += surf.layer_size * mslice; + offset += (u64)surf.layer_size * mslice; if (offset > radeon_bo_size(track->db_z_read_bo)) { dev_warn(p->dev, "%s:%d depth read bo too small (layer size %d, " - "offset %ld, max layer %d, bo size %ld)\n", + "offset %llu, max layer %d, bo size %ld)\n", __func__, __LINE__, surf.layer_size, - (unsigned long)track->db_z_read_offset << 8, mslice, + (u64)track->db_z_read_offset << 8, mslice, radeon_bo_size(track->db_z_read_bo)); return -EINVAL; } - offset = track->db_z_write_offset << 8; + offset = (u64)track->db_z_write_offset << 8; if (offset & (surf.base_align - 1)) { - dev_warn(p->dev, "%s:%d stencil write bo base %ld not aligned with %ld\n", + dev_warn(p->dev, "%s:%d stencil write bo base %llu not aligned with %ld\n", __func__, __LINE__, offset, surf.base_align); return -EINVAL; } - offset += surf.layer_size * mslice; + offset += (u64)surf.layer_size * mslice; if (offset > radeon_bo_size(track->db_z_write_bo)) { dev_warn(p->dev, "%s:%d depth write bo too small (layer size %d, " - "offset %ld, max layer %d, bo size %ld)\n", + "offset %llu, max layer %d, bo size %ld)\n", __func__, __LINE__, surf.layer_size, - (unsigned long)track->db_z_write_offset << 8, mslice, + (u64)track->db_z_write_offset << 8, mslice, radeon_bo_size(track->db_z_write_bo)); return -EINVAL; } diff --git a/drivers/gpu/drm/radeon/r100.c b/drivers/gpu/drm/radeon/r100.c index 6e4600c21697..654155b440e5 100644 --- a/drivers/gpu/drm/radeon/r100.c +++ b/drivers/gpu/drm/radeon/r100.c @@ -1005,45 +1005,65 @@ static int r100_cp_init_microcode(struct radeon_device *rdev) DRM_DEBUG_KMS("\n"); - if ((rdev->family == CHIP_R100) || (rdev->family == CHIP_RV100) || - (rdev->family == CHIP_RV200) || (rdev->family == CHIP_RS100) || - (rdev->family == CHIP_RS200)) { + switch (rdev->family) { + case CHIP_R100: + case CHIP_RV100: + case CHIP_RV200: + case CHIP_RS100: + case CHIP_RS200: DRM_INFO("Loading R100 Microcode\n"); fw_name = FIRMWARE_R100; - } else if ((rdev->family == CHIP_R200) || - (rdev->family == CHIP_RV250) || - (rdev->family == CHIP_RV280) || - (rdev->family == CHIP_RS300)) { + break; + + case CHIP_R200: + case CHIP_RV250: + case CHIP_RV280: + case CHIP_RS300: DRM_INFO("Loading R200 Microcode\n"); fw_name = FIRMWARE_R200; - } else if ((rdev->family == CHIP_R300) || - (rdev->family == CHIP_R350) || - (rdev->family == CHIP_RV350) || - (rdev->family == CHIP_RV380) || - (rdev->family == CHIP_RS400) || - (rdev->family == CHIP_RS480)) { + break; + + case CHIP_R300: + case CHIP_R350: + case CHIP_RV350: + case CHIP_RV380: + case CHIP_RS400: + case CHIP_RS480: DRM_INFO("Loading R300 Microcode\n"); fw_name = FIRMWARE_R300; - } else if ((rdev->family == CHIP_R420) || - (rdev->family == CHIP_R423) || - (rdev->family == CHIP_RV410)) { + break; + + case CHIP_R420: + case CHIP_R423: + case CHIP_RV410: DRM_INFO("Loading R400 Microcode\n"); fw_name = FIRMWARE_R420; - } else if ((rdev->family == CHIP_RS690) || - (rdev->family == CHIP_RS740)) { + break; + + case CHIP_RS690: + case CHIP_RS740: DRM_INFO("Loading RS690/RS740 Microcode\n"); fw_name = FIRMWARE_RS690; - } else if (rdev->family == CHIP_RS600) { + break; + + case CHIP_RS600: DRM_INFO("Loading RS600 Microcode\n"); fw_name = FIRMWARE_RS600; - } else if ((rdev->family == CHIP_RV515) || - (rdev->family == CHIP_R520) || - (rdev->family == CHIP_RV530) || - (rdev->family == CHIP_R580) || - (rdev->family == CHIP_RV560) || - (rdev->family == CHIP_RV570)) { + break; + + case CHIP_RV515: + case CHIP_R520: + case CHIP_RV530: + case CHIP_R580: + case CHIP_RV560: + case CHIP_RV570: DRM_INFO("Loading R500 Microcode\n"); fw_name = FIRMWARE_R520; + break; + + default: + DRM_ERROR("Unsupported Radeon family %u\n", rdev->family); + return -EINVAL; } err = request_firmware(&rdev->me_fw, fw_name, rdev->dev); diff --git a/drivers/gpu/drm/radeon/radeon_atombios.c b/drivers/gpu/drm/radeon/radeon_atombios.c index aca6e5cfae53..b5ce63ca3f05 100644 --- a/drivers/gpu/drm/radeon/radeon_atombios.c +++ b/drivers/gpu/drm/radeon/radeon_atombios.c @@ -1720,23 +1720,29 @@ struct radeon_encoder_atom_dig *radeon_atombios_get_lvds_info(struct fake_edid_record = (ATOM_FAKE_EDID_PATCH_RECORD *)record; if (fake_edid_record->ucFakeEDIDLength) { struct edid *edid; - int edid_size = - max((int)EDID_LENGTH, (int)fake_edid_record->ucFakeEDIDLength); - edid = kmalloc(edid_size, GFP_KERNEL); - if (edid) { - memcpy((u8 *)edid, (u8 *)&fake_edid_record->ucFakeEDIDString[0], - fake_edid_record->ucFakeEDIDLength); + int edid_size; + if (fake_edid_record->ucFakeEDIDLength == 128) + edid_size = fake_edid_record->ucFakeEDIDLength; + else + edid_size = fake_edid_record->ucFakeEDIDLength * 128; + edid = kmemdup(&fake_edid_record->ucFakeEDIDString[0], + edid_size, GFP_KERNEL); + if (edid) { if (drm_edid_is_valid(edid)) { rdev->mode_info.bios_hardcoded_edid = edid; rdev->mode_info.bios_hardcoded_edid_size = edid_size; - } else + } else { kfree(edid); + } } + record += struct_size(fake_edid_record, + ucFakeEDIDString, + edid_size); + } else { + /* empty fake edid record must be 3 bytes long */ + record += sizeof(ATOM_FAKE_EDID_PATCH_RECORD) + 1; } - record += fake_edid_record->ucFakeEDIDLength ? - fake_edid_record->ucFakeEDIDLength + 2 : - sizeof(ATOM_FAKE_EDID_PATCH_RECORD); break; case LCD_PANEL_RESOLUTION_RECORD_TYPE: panel_res_record = (ATOM_PANEL_RESOLUTION_PATCH_RECORD *)record; diff --git a/drivers/gpu/drm/radeon/radeon_encoders.c b/drivers/gpu/drm/radeon/radeon_encoders.c index ced022fae19d..ca01a813c819 100644 --- a/drivers/gpu/drm/radeon/radeon_encoders.c +++ b/drivers/gpu/drm/radeon/radeon_encoders.c @@ -47,7 +47,7 @@ static uint32_t radeon_encoder_clones(struct drm_encoder *encoder) struct radeon_device *rdev = dev->dev_private; struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); struct drm_encoder *clone_encoder; - uint32_t index_mask = 0; + uint32_t index_mask = drm_encoder_mask(encoder); int count; /* DIG routing gets problematic */ diff --git a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c index 515e6f187dc7..91e28fcdd22e 100644 --- a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c +++ b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c @@ -389,6 +389,8 @@ static void dw_hdmi_rk3328_setup_hpd(struct dw_hdmi *dw_hdmi, void *data) HIWORD_UPDATE(RK3328_HDMI_SDAIN_MSK | RK3328_HDMI_SCLIN_MSK, RK3328_HDMI_SDAIN_MSK | RK3328_HDMI_SCLIN_MSK | RK3328_HDMI_HPD_IOE)); + + dw_hdmi_rk3328_read_hpd(dw_hdmi, data); } static const struct dw_hdmi_phy_ops rk3228_hdmi_phy_ops = { diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c index 682d78fab9a5..b4517e338f5e 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c @@ -9,6 +9,7 @@ #include #include #include +#include #include #include #include @@ -65,6 +66,9 @@ #define VOP_REG_SET(vop, group, name, v) \ vop_reg_set(vop, &vop->data->group->name, 0, ~0, v, #name) +#define VOP_HAS_REG(vop, group, name) \ + (!!(vop->data->group->name.mask)) + #define VOP_INTR_SET_TYPE(vop, name, type, v) \ do { \ int i, reg = 0, mask = 0; \ @@ -370,8 +374,8 @@ static void scl_vop_cal_scl_fac(struct vop *vop, const struct vop_win_data *win, if (info->is_yuv) is_yuv = true; - if (dst_w > 3840) { - DRM_DEV_ERROR(vop->dev, "Maximum dst width (3840) exceeded\n"); + if (dst_w > 4096) { + DRM_DEV_ERROR(vop->dev, "Maximum dst width (4096) exceeded\n"); return; } @@ -1200,17 +1204,22 @@ static bool vop_dsp_lut_is_enabled(struct vop *vop) return vop_read_reg(vop, 0, &vop->data->common->dsp_lut_en); } +static u32 vop_lut_buffer_index(struct vop *vop) +{ + return vop_read_reg(vop, 0, &vop->data->common->lut_buffer_index); +} + static void vop_crtc_write_gamma_lut(struct vop *vop, struct drm_crtc *crtc) { struct drm_color_lut *lut = crtc->state->gamma_lut->data; - unsigned int i; + unsigned int i, bpc = ilog2(vop->data->lut_size); for (i = 0; i < crtc->gamma_size; i++) { u32 word; - word = (drm_color_lut_extract(lut[i].red, 10) << 20) | - (drm_color_lut_extract(lut[i].green, 10) << 10) | - drm_color_lut_extract(lut[i].blue, 10); + word = (drm_color_lut_extract(lut[i].red, bpc) << (2 * bpc)) | + (drm_color_lut_extract(lut[i].green, bpc) << bpc) | + drm_color_lut_extract(lut[i].blue, bpc); writel(word, vop->lut_regs + i * 4); } } @@ -1220,38 +1229,66 @@ static void vop_crtc_gamma_set(struct vop *vop, struct drm_crtc *crtc, { struct drm_crtc_state *state = crtc->state; unsigned int idle; + u32 lut_idx, old_idx; int ret; if (!vop->lut_regs) return; - /* - * To disable gamma (gamma_lut is null) or to write - * an update to the LUT, clear dsp_lut_en. - */ - spin_lock(&vop->reg_lock); - VOP_REG_SET(vop, common, dsp_lut_en, 0); - vop_cfg_done(vop); - spin_unlock(&vop->reg_lock); - /* - * In order to write the LUT to the internal memory, - * we need to first make sure the dsp_lut_en bit is cleared. - */ - ret = readx_poll_timeout(vop_dsp_lut_is_enabled, vop, - idle, !idle, 5, 30 * 1000); - if (ret) { - DRM_DEV_ERROR(vop->dev, "display LUT RAM enable timeout!\n"); - return; + if (!state->gamma_lut || !VOP_HAS_REG(vop, common, update_gamma_lut)) { + /* + * To disable gamma (gamma_lut is null) or to write + * an update to the LUT, clear dsp_lut_en. + */ + spin_lock(&vop->reg_lock); + VOP_REG_SET(vop, common, dsp_lut_en, 0); + vop_cfg_done(vop); + spin_unlock(&vop->reg_lock); + + /* + * In order to write the LUT to the internal memory, + * we need to first make sure the dsp_lut_en bit is cleared. + */ + ret = readx_poll_timeout(vop_dsp_lut_is_enabled, vop, + idle, !idle, 5, 30 * 1000); + if (ret) { + DRM_DEV_ERROR(vop->dev, "display LUT RAM enable timeout!\n"); + return; + } + + if (!state->gamma_lut) + return; + } else { + /* + * On RK3399 the gamma LUT can updated without clearing dsp_lut_en, + * by setting update_gamma_lut then waiting for lut_buffer_index change + */ + old_idx = vop_lut_buffer_index(vop); } - if (!state->gamma_lut) - return; - spin_lock(&vop->reg_lock); vop_crtc_write_gamma_lut(vop, crtc); VOP_REG_SET(vop, common, dsp_lut_en, 1); + VOP_REG_SET(vop, common, update_gamma_lut, 1); vop_cfg_done(vop); spin_unlock(&vop->reg_lock); + + if (VOP_HAS_REG(vop, common, update_gamma_lut)) { + ret = readx_poll_timeout(vop_lut_buffer_index, vop, + lut_idx, lut_idx != old_idx, 5, 30 * 1000); + if (ret) { + DRM_DEV_ERROR(vop->dev, "gamma LUT update timeout!\n"); + return; + } + + /* + * update_gamma_lut is auto cleared by HW, but write 0 to clear the bit + * in our backup of the regs. + */ + spin_lock(&vop->reg_lock); + VOP_REG_SET(vop, common, update_gamma_lut, 0); + spin_unlock(&vop->reg_lock); + } } static void vop_crtc_atomic_begin(struct drm_crtc *crtc, @@ -1295,14 +1332,6 @@ static void vop_crtc_atomic_enable(struct drm_crtc *crtc, return; } - /* - * If we have a GAMMA LUT in the state, then let's make sure - * it's updated. We might be coming out of suspend, - * which means the LUT internal memory needs to be re-written. - */ - if (crtc->state->gamma_lut) - vop_crtc_gamma_set(vop, crtc, old_state); - mutex_lock(&vop->vop_lock); WARN_ON(vop->event); @@ -1393,6 +1422,14 @@ static void vop_crtc_atomic_enable(struct drm_crtc *crtc, VOP_REG_SET(vop, common, standby, 0); mutex_unlock(&vop->vop_lock); + + /* + * If we have a GAMMA LUT in the state, then let's make sure + * it's updated. We might be coming out of suspend, + * which means the LUT internal memory needs to be re-written. + */ + if (crtc->state->gamma_lut) + vop_crtc_gamma_set(vop, crtc, old_state); } static bool vop_fs_irq_is_pending(struct vop *vop) @@ -1486,6 +1523,10 @@ static void vop_crtc_atomic_flush(struct drm_crtc *crtc, VOP_AFBC_SET(vop, enable, s->enable_afbc); vop_cfg_done(vop); + /* Ack the DMA transfer of the previous frame (RK3066). */ + if (VOP_HAS_REG(vop, common, dma_stop)) + VOP_REG_SET(vop, common, dma_stop, 0); + spin_unlock(&vop->reg_lock); /* @@ -2119,8 +2160,8 @@ static int vop_bind(struct device *dev, struct device *master, void *data) res = platform_get_resource(pdev, IORESOURCE_MEM, 1); if (res) { - if (!vop_data->lut_size) { - DRM_DEV_ERROR(dev, "no gamma LUT size defined\n"); + if (vop_data->lut_size != 1024 && vop_data->lut_size != 256) { + DRM_DEV_ERROR(dev, "unsupported gamma LUT size %d\n", vop_data->lut_size); return -EINVAL; } vop->lut_regs = devm_ioremap_resource(dev, res); diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.h b/drivers/gpu/drm/rockchip/rockchip_drm_vop.h index 857d97cdc67c..32d1783be01d 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.h +++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.h @@ -99,8 +99,11 @@ struct vop_common { struct vop_reg dither_down_en; struct vop_reg dither_up; struct vop_reg dsp_lut_en; + struct vop_reg update_gamma_lut; + struct vop_reg lut_buffer_index; struct vop_reg gate_en; struct vop_reg mmu_en; + struct vop_reg dma_stop; struct vop_reg out_mode; struct vop_reg standby; }; diff --git a/drivers/gpu/drm/rockchip/rockchip_vop_reg.c b/drivers/gpu/drm/rockchip/rockchip_vop_reg.c index 39e1e1ebea92..b43b684bee86 100644 --- a/drivers/gpu/drm/rockchip/rockchip_vop_reg.c +++ b/drivers/gpu/drm/rockchip/rockchip_vop_reg.c @@ -401,6 +401,7 @@ static const struct vop_output rk3066_output = { }; static const struct vop_common rk3066_common = { + .dma_stop = VOP_REG(RK3066_SYS_CTRL0, 0x1, 0), .standby = VOP_REG(RK3066_SYS_CTRL0, 0x1, 1), .out_mode = VOP_REG(RK3066_DSP_CTRL0, 0xf, 0), .cfg_done = VOP_REG(RK3066_REG_CFG_DONE, 0x1, 0), @@ -836,6 +837,24 @@ static const struct vop_output rk3399_output = { .mipi_dual_channel_en = VOP_REG(RK3288_SYS_CTRL, 0x1, 3), }; +static const struct vop_common rk3399_common = { + .standby = VOP_REG_SYNC(RK3399_SYS_CTRL, 0x1, 22), + .gate_en = VOP_REG(RK3399_SYS_CTRL, 0x1, 23), + .mmu_en = VOP_REG(RK3399_SYS_CTRL, 0x1, 20), + .dither_down_sel = VOP_REG(RK3399_DSP_CTRL1, 0x1, 4), + .dither_down_mode = VOP_REG(RK3399_DSP_CTRL1, 0x1, 3), + .dither_down_en = VOP_REG(RK3399_DSP_CTRL1, 0x1, 2), + .pre_dither_down = VOP_REG(RK3399_DSP_CTRL1, 0x1, 1), + .dither_up = VOP_REG(RK3399_DSP_CTRL1, 0x1, 6), + .dsp_lut_en = VOP_REG(RK3399_DSP_CTRL1, 0x1, 0), + .update_gamma_lut = VOP_REG(RK3399_DSP_CTRL1, 0x1, 7), + .lut_buffer_index = VOP_REG(RK3399_DBG_POST_REG1, 0x1, 1), + .data_blank = VOP_REG(RK3399_DSP_CTRL0, 0x1, 19), + .dsp_blank = VOP_REG(RK3399_DSP_CTRL0, 0x3, 18), + .out_mode = VOP_REG(RK3399_DSP_CTRL0, 0xf, 0), + .cfg_done = VOP_REG_SYNC(RK3399_REG_CFG_DONE, 0x1, 0), +}; + static const struct vop_yuv2yuv_phy rk3399_yuv2yuv_win01_data = { .y2r_coefficients = { VOP_REG(RK3399_WIN0_YUV2YUV_Y2R + 0, 0xffff, 0), @@ -917,7 +936,7 @@ static const struct vop_data rk3399_vop_big = { .version = VOP_VERSION(3, 5), .feature = VOP_FEATURE_OUTPUT_RGB10, .intr = &rk3366_vop_intr, - .common = &rk3288_common, + .common = &rk3399_common, .modeset = &rk3288_modeset, .output = &rk3399_output, .afbc = &rk3399_vop_afbc, @@ -925,6 +944,7 @@ static const struct vop_data rk3399_vop_big = { .win = rk3399_vop_win_data, .win_size = ARRAY_SIZE(rk3399_vop_win_data), .win_yuv2yuv = rk3399_vop_big_win_yuv2yuv_data, + .lut_size = 1024, }; static const struct vop_win_data rk3399_vop_lit_win_data[] = { @@ -943,13 +963,14 @@ static const struct vop_win_yuv2yuv_data rk3399_vop_lit_win_yuv2yuv_data[] = { static const struct vop_data rk3399_vop_lit = { .version = VOP_VERSION(3, 6), .intr = &rk3366_vop_intr, - .common = &rk3288_common, + .common = &rk3399_common, .modeset = &rk3288_modeset, .output = &rk3399_output, .misc = &rk3368_misc, .win = rk3399_vop_lit_win_data, .win_size = ARRAY_SIZE(rk3399_vop_lit_win_data), .win_yuv2yuv = rk3399_vop_lit_win_yuv2yuv_data, + .lut_size = 256, }; static const struct vop_win_data rk3228_vop_win_data[] = { diff --git a/drivers/gpu/drm/rockchip/rockchip_vop_reg.h b/drivers/gpu/drm/rockchip/rockchip_vop_reg.h index 6e9fa5815d4d..9f410a4ece7b 100644 --- a/drivers/gpu/drm/rockchip/rockchip_vop_reg.h +++ b/drivers/gpu/drm/rockchip/rockchip_vop_reg.h @@ -628,6 +628,7 @@ #define RK3399_YUV2YUV_WIN 0x02c0 #define RK3399_YUV2YUV_POST 0x02c4 #define RK3399_AUTO_GATING_EN 0x02cc +#define RK3399_DBG_POST_REG1 0x036c #define RK3399_WIN0_CSC_COE 0x03a0 #define RK3399_WIN1_CSC_COE 0x03c0 #define RK3399_WIN2_CSC_COE 0x03e0 diff --git a/drivers/gpu/drm/scheduler/sched_entity.c b/drivers/gpu/drm/scheduler/sched_entity.c index 3f7f761df4cd..750d91370c8a 100644 --- a/drivers/gpu/drm/scheduler/sched_entity.c +++ b/drivers/gpu/drm/scheduler/sched_entity.c @@ -96,8 +96,10 @@ void drm_sched_entity_modify_sched(struct drm_sched_entity *entity, { WARN_ON(!num_sched_list || !sched_list); + spin_lock(&entity->rq_lock); entity->sched_list = sched_list; entity->num_sched_list = num_sched_list; + spin_unlock(&entity->rq_lock); } EXPORT_SYMBOL(drm_sched_entity_modify_sched); diff --git a/drivers/gpu/drm/stm/drv.c b/drivers/gpu/drm/stm/drv.c index 411103f013e2..08c50e68cfca 100644 --- a/drivers/gpu/drm/stm/drv.c +++ b/drivers/gpu/drm/stm/drv.c @@ -195,12 +195,14 @@ static int stm_drm_platform_probe(struct platform_device *pdev) ret = drm_dev_register(ddev, 0); if (ret) - goto err_put; + goto err_unload; drm_fbdev_generic_setup(ddev, 16); return 0; +err_unload: + drv_unload(ddev); err_put: drm_dev_put(ddev); diff --git a/drivers/gpu/drm/vboxvideo/hgsmi_base.c b/drivers/gpu/drm/vboxvideo/hgsmi_base.c index 361d3193258e..7edc9cf6a606 100644 --- a/drivers/gpu/drm/vboxvideo/hgsmi_base.c +++ b/drivers/gpu/drm/vboxvideo/hgsmi_base.c @@ -135,7 +135,15 @@ int hgsmi_update_pointer_shape(struct gen_pool *ctx, u32 flags, flags |= VBOX_MOUSE_POINTER_VISIBLE; } - p = hgsmi_buffer_alloc(ctx, sizeof(*p) + pixel_len, HGSMI_CH_VBVA, + /* + * The 4 extra bytes come from switching struct vbva_mouse_pointer_shape + * from having a 4 bytes fixed array at the end to using a proper VLA + * at the end. These 4 extra bytes were not subtracted from sizeof(*p) + * before the switch to the VLA, so this way the behavior is unchanged. + * Chances are these 4 extra bytes are not necessary but they are kept + * to avoid regressions. + */ + p = hgsmi_buffer_alloc(ctx, sizeof(*p) + pixel_len + 4, HGSMI_CH_VBVA, VBVA_MOUSE_POINTER_SHAPE); if (!p) return -ENOMEM; diff --git a/drivers/gpu/drm/vboxvideo/vboxvideo.h b/drivers/gpu/drm/vboxvideo/vboxvideo.h index a5de40fe1a76..bed285fe083c 100644 --- a/drivers/gpu/drm/vboxvideo/vboxvideo.h +++ b/drivers/gpu/drm/vboxvideo/vboxvideo.h @@ -351,10 +351,8 @@ struct vbva_mouse_pointer_shape { * Bytes in the gap between the AND and the XOR mask are undefined. * XOR mask scanlines have no gap between them and size of XOR mask is: * xor_len = width * 4 * height. - * - * Preallocate 4 bytes for accessing actual data as p->data. */ - u8 data[4]; + u8 data[]; } __packed; /* pointer is visible */ diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c index 0e963fd7db17..73cbb94ff456 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c @@ -1402,6 +1402,7 @@ static struct drm_framebuffer *vmw_kms_fb_create(struct drm_device *dev, DRM_ERROR("Surface size cannot exceed %dx%d", dev_priv->texture_max_width, dev_priv->texture_max_height); + ret = -EINVAL; goto err_out; } diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index 2be8ed476d00..50a5b45ad42d 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c @@ -1658,7 +1658,7 @@ u8 *hid_alloc_report_buf(struct hid_report *report, gfp_t flags) u32 len = hid_report_len(report) + 7; - return kmalloc(len, flags); + return kzalloc(len, flags); } EXPORT_SYMBOL_GPL(hid_alloc_report_buf); diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h index dbec6231a4f6..921fcec7553c 100644 --- a/drivers/hid/hid-ids.h +++ b/drivers/hid/hid-ids.h @@ -966,6 +966,8 @@ #define USB_DEVICE_ID_PLANTRONICS_BLACKWIRE_3220_SERIES 0xc056 #define USB_DEVICE_ID_PLANTRONICS_BLACKWIRE_3215_SERIES 0xc057 #define USB_DEVICE_ID_PLANTRONICS_BLACKWIRE_3225_SERIES 0xc058 +#define USB_DEVICE_ID_PLANTRONICS_BLACKWIRE_3325_SERIES 0x430c +#define USB_DEVICE_ID_PLANTRONICS_ENCOREPRO_500_SERIES 0x431e #define USB_VENDOR_ID_PANASONIC 0x04da #define USB_DEVICE_ID_PANABOARD_UBT780 0x1044 diff --git a/drivers/hid/hid-plantronics.c b/drivers/hid/hid-plantronics.c index 3d414ae194ac..25cfd964dc25 100644 --- a/drivers/hid/hid-plantronics.c +++ b/drivers/hid/hid-plantronics.c @@ -38,8 +38,10 @@ (usage->hid & HID_USAGE_PAGE) == HID_UP_CONSUMER) #define PLT_QUIRK_DOUBLE_VOLUME_KEYS BIT(0) +#define PLT_QUIRK_FOLLOWED_OPPOSITE_VOLUME_KEYS BIT(1) #define PLT_DOUBLE_KEY_TIMEOUT 5 /* ms */ +#define PLT_FOLLOWED_OPPOSITE_KEY_TIMEOUT 220 /* ms */ struct plt_drv_data { unsigned long device_type; @@ -137,6 +139,21 @@ static int plantronics_event(struct hid_device *hdev, struct hid_field *field, drv_data->last_volume_key_ts = cur_ts; } + if (drv_data->quirks & PLT_QUIRK_FOLLOWED_OPPOSITE_VOLUME_KEYS) { + unsigned long prev_ts, cur_ts; + + /* Usages are filtered in plantronics_usages. */ + + if (!value) /* Handle key presses only. */ + return 0; + + prev_ts = drv_data->last_volume_key_ts; + cur_ts = jiffies; + if (jiffies_to_msecs(cur_ts - prev_ts) <= PLT_FOLLOWED_OPPOSITE_KEY_TIMEOUT) + return 1; /* Ignore the followed opposite volume key. */ + + drv_data->last_volume_key_ts = cur_ts; + } return 0; } @@ -210,6 +227,12 @@ static const struct hid_device_id plantronics_devices[] = { { HID_USB_DEVICE(USB_VENDOR_ID_PLANTRONICS, USB_DEVICE_ID_PLANTRONICS_BLACKWIRE_3225_SERIES), .driver_data = PLT_QUIRK_DOUBLE_VOLUME_KEYS }, + { HID_USB_DEVICE(USB_VENDOR_ID_PLANTRONICS, + USB_DEVICE_ID_PLANTRONICS_BLACKWIRE_3325_SERIES), + .driver_data = PLT_QUIRK_FOLLOWED_OPPOSITE_VOLUME_KEYS }, + { HID_USB_DEVICE(USB_VENDOR_ID_PLANTRONICS, + USB_DEVICE_ID_PLANTRONICS_ENCOREPRO_500_SERIES), + .driver_data = PLT_QUIRK_FOLLOWED_OPPOSITE_VOLUME_KEYS }, { HID_USB_DEVICE(USB_VENDOR_ID_PLANTRONICS, HID_ANY_ID) }, { } }; diff --git a/drivers/hid/intel-ish-hid/ishtp-fw-loader.c b/drivers/hid/intel-ish-hid/ishtp-fw-loader.c index b6d6d119035c..1bb5316c2a8b 100644 --- a/drivers/hid/intel-ish-hid/ishtp-fw-loader.c +++ b/drivers/hid/intel-ish-hid/ishtp-fw-loader.c @@ -630,7 +630,7 @@ static int ish_fw_xfer_direct_dma(struct ishtp_cl_data *client_data, const struct firmware *fw, const struct shim_fw_info fw_info) { - int rv; + int rv = 0; void *dma_buf; dma_addr_t dma_buf_phy; u32 fragment_offset, fragment_size, payload_max_size; diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig index 1ea76676e41f..58bb87022afc 100644 --- a/drivers/hwmon/Kconfig +++ b/drivers/hwmon/Kconfig @@ -178,6 +178,7 @@ config SENSORS_ADM9240 tristate "Analog Devices ADM9240 and compatibles" depends on I2C select HWMON_VID + select REGMAP_I2C help If you say yes here you get support for Analog Devices ADM9240, Dallas DS1780, National Semiconductor LM81 sensor chips. @@ -1878,6 +1879,7 @@ config SENSORS_TMP421 config SENSORS_TMP513 tristate "Texas Instruments TMP513 and compatibles" depends on I2C + select REGMAP_I2C help If you say yes here you get support for Texas Instruments TMP512, and TMP513 temperature and power supply sensor chips. diff --git a/drivers/hwmon/max16065.c b/drivers/hwmon/max16065.c index a26226e7bc37..6a09ab606fcb 100644 --- a/drivers/hwmon/max16065.c +++ b/drivers/hwmon/max16065.c @@ -114,9 +114,10 @@ static inline int LIMIT_TO_MV(int limit, int range) return limit * range / 256; } -static inline int MV_TO_LIMIT(int mv, int range) +static inline int MV_TO_LIMIT(unsigned long mv, int range) { - return clamp_val(DIV_ROUND_CLOSEST(mv * 256, range), 0, 255); + mv = clamp_val(mv, 0, ULONG_MAX / 256); + return DIV_ROUND_CLOSEST(clamp_val(mv * 256, 0, range * 255), range); } static inline int ADC_TO_CURR(int adc, int gain) diff --git a/drivers/hwmon/ntc_thermistor.c b/drivers/hwmon/ntc_thermistor.c index 3aad62a0e661..7e20beb8b11f 100644 --- a/drivers/hwmon/ntc_thermistor.c +++ b/drivers/hwmon/ntc_thermistor.c @@ -58,6 +58,7 @@ static const struct platform_device_id ntc_thermistor_id[] = { [NTC_NCP21WB473] = { "ncp21wb473", TYPE_NCPXXWB473 }, [NTC_LAST] = { }, }; +MODULE_DEVICE_TABLE(platform, ntc_thermistor_id); /* * A compensation table should be sorted by the values of .ohm diff --git a/drivers/hwmon/pmbus/pmbus.h b/drivers/hwmon/pmbus/pmbus.h index de27837e8527..a46c479962b0 100644 --- a/drivers/hwmon/pmbus/pmbus.h +++ b/drivers/hwmon/pmbus/pmbus.h @@ -409,6 +409,12 @@ enum pmbus_sensor_classes { enum pmbus_data_format { linear = 0, direct, vid }; enum vrm_version { vr11 = 0, vr12, vr13, imvp9, amd625mv }; +/* PMBus revision identifiers */ +#define PMBUS_REV_10 0x00 /* PMBus revision 1.0 */ +#define PMBUS_REV_11 0x11 /* PMBus revision 1.1 */ +#define PMBUS_REV_12 0x22 /* PMBus revision 1.2 */ +#define PMBUS_REV_13 0x33 /* PMBus revision 1.3 */ + struct pmbus_driver_info { int pages; /* Total number of pages */ u8 phases[PMBUS_PAGES]; /* Number of phases per page */ @@ -438,6 +444,8 @@ struct pmbus_driver_info { int (*read_byte_data)(struct i2c_client *client, int page, int reg); int (*read_word_data)(struct i2c_client *client, int page, int phase, int reg); + int (*write_byte_data)(struct i2c_client *client, int page, int reg, + u8 byte); int (*write_word_data)(struct i2c_client *client, int page, int reg, u16 word); int (*write_byte)(struct i2c_client *client, int page, u8 value); diff --git a/drivers/hwmon/pmbus/pmbus_core.c b/drivers/hwmon/pmbus/pmbus_core.c index 117e3ce9c76a..b795c90a46d9 100644 --- a/drivers/hwmon/pmbus/pmbus_core.c +++ b/drivers/hwmon/pmbus/pmbus_core.c @@ -82,6 +82,8 @@ struct pmbus_data { u32 flags; /* from platform data */ + u8 revision; /* The PMBus revision the device is compliant with */ + int exponent[PMBUS_PAGES]; /* linear mode: exponent for output voltages */ @@ -265,6 +267,24 @@ static int _pmbus_write_word_data(struct i2c_client *client, int page, int reg, return pmbus_write_word_data(client, page, reg, word); } +/* + * _pmbus_write_byte_data() is similar to pmbus_write_byte_data(), but checks if + * a device specific mapping function exists and calls it if necessary. + */ +static int _pmbus_write_byte_data(struct i2c_client *client, int page, int reg, u8 value) +{ + struct pmbus_data *data = i2c_get_clientdata(client); + const struct pmbus_driver_info *info = data->info; + int status; + + if (info->write_byte_data) { + status = info->write_byte_data(client, page, reg, value); + if (status != -ENODATA) + return status; + } + return pmbus_write_byte_data(client, page, reg, value); +} + int pmbus_update_fan(struct i2c_client *client, int page, int id, u8 config, u8 mask, u16 command) { @@ -279,7 +299,7 @@ int pmbus_update_fan(struct i2c_client *client, int page, int id, to = (from & ~mask) | (config & mask); if (to != from) { - rv = pmbus_write_byte_data(client, page, + rv = _pmbus_write_byte_data(client, page, pmbus_fan_config_registers[id], to); if (rv < 0) return rv; @@ -386,7 +406,7 @@ int pmbus_update_byte_data(struct i2c_client *client, int page, u8 reg, tmp = (rv & ~mask) | (value & mask); if (tmp != rv) - rv = pmbus_write_byte_data(client, page, reg, tmp); + rv = _pmbus_write_byte_data(client, page, reg, tmp); return rv; } @@ -899,9 +919,14 @@ static int pmbus_get_boolean(struct i2c_client *client, struct pmbus_boolean *b, regval = status & mask; if (regval) { - ret = pmbus_write_byte_data(client, page, reg, regval); - if (ret) - goto unlock; + if (data->revision >= PMBUS_REV_12) { + ret = _pmbus_write_byte_data(client, page, reg, regval); + if (ret) + goto unlock; + } else { + pmbus_clear_fault_page(client, page); + } + } if (s1 && s2) { s64 v1, v2; @@ -2222,6 +2247,10 @@ static int pmbus_init_common(struct i2c_client *client, struct pmbus_data *data, if (ret > 0 && (ret & PB_WP_ANY)) data->flags |= PMBUS_WRITE_PROTECTED | PMBUS_SKIP_STATUS_CHECK; + ret = i2c_smbus_read_byte_data(client, PMBUS_REVISION); + if (ret >= 0) + data->revision = ret; + if (data->info->pages) pmbus_clear_faults(client); else diff --git a/drivers/hwtracing/coresight/coresight-tmc-etr.c b/drivers/hwtracing/coresight/coresight-tmc-etr.c index 497499a9d09e..25e2167a2ee0 100644 --- a/drivers/hwtracing/coresight/coresight-tmc-etr.c +++ b/drivers/hwtracing/coresight/coresight-tmc-etr.c @@ -280,6 +280,7 @@ void tmc_free_sg_table(struct tmc_sg_table *sg_table) { tmc_free_table_pages(sg_table); tmc_free_data_pages(sg_table); + kfree(sg_table); } EXPORT_SYMBOL_GPL(tmc_free_sg_table); @@ -394,7 +395,6 @@ struct tmc_sg_table *tmc_alloc_sg_table(struct device *dev, rc = tmc_alloc_table_pages(sg_table); if (rc) { tmc_free_sg_table(sg_table); - kfree(sg_table); return ERR_PTR(rc); } diff --git a/drivers/i2c/busses/i2c-aspeed.c b/drivers/i2c/busses/i2c-aspeed.c index b915dfcff00d..c2f86fc4c224 100644 --- a/drivers/i2c/busses/i2c-aspeed.c +++ b/drivers/i2c/busses/i2c-aspeed.c @@ -172,6 +172,13 @@ struct aspeed_i2c_bus { static int aspeed_i2c_reset(struct aspeed_i2c_bus *bus); +/* precondition: bus.lock has been acquired. */ +static void aspeed_i2c_do_stop(struct aspeed_i2c_bus *bus) +{ + bus->master_state = ASPEED_I2C_MASTER_STOP; + writel(ASPEED_I2CD_M_STOP_CMD, bus->base + ASPEED_I2C_CMD_REG); +} + static int aspeed_i2c_recover_bus(struct aspeed_i2c_bus *bus) { unsigned long time_left, flags; @@ -189,7 +196,7 @@ static int aspeed_i2c_recover_bus(struct aspeed_i2c_bus *bus) command); reinit_completion(&bus->cmd_complete); - writel(ASPEED_I2CD_M_STOP_CMD, bus->base + ASPEED_I2C_CMD_REG); + aspeed_i2c_do_stop(bus); spin_unlock_irqrestore(&bus->lock, flags); time_left = wait_for_completion_timeout( @@ -385,13 +392,6 @@ static void aspeed_i2c_do_start(struct aspeed_i2c_bus *bus) writel(command, bus->base + ASPEED_I2C_CMD_REG); } -/* precondition: bus.lock has been acquired. */ -static void aspeed_i2c_do_stop(struct aspeed_i2c_bus *bus) -{ - bus->master_state = ASPEED_I2C_MASTER_STOP; - writel(ASPEED_I2CD_M_STOP_CMD, bus->base + ASPEED_I2C_CMD_REG); -} - /* precondition: bus.lock has been acquired. */ static void aspeed_i2c_next_msg_or_stop(struct aspeed_i2c_bus *bus) { diff --git a/drivers/i2c/busses/i2c-i801.c b/drivers/i2c/busses/i2c-i801.c index 4baa9bce02b6..3d5ef84482b2 100644 --- a/drivers/i2c/busses/i2c-i801.c +++ b/drivers/i2c/busses/i2c-i801.c @@ -1895,8 +1895,15 @@ static int i801_probe(struct pci_dev *dev, const struct pci_device_id *id) i801_add_tco(priv); + /* + * adapter.name is used by platform code to find the main I801 adapter + * to instantiante i2c_clients, do not change. + */ snprintf(priv->adapter.name, sizeof(priv->adapter.name), - "SMBus I801 adapter at %04lx", priv->smba); + "SMBus %s adapter at %04lx", + (priv->features & FEATURE_IDF) ? "I801 IDF" : "I801", + priv->smba); + err = i2c_add_adapter(&priv->adapter); if (err) { platform_device_unregister(priv->tco_pdev); diff --git a/drivers/i2c/busses/i2c-isch.c b/drivers/i2c/busses/i2c-isch.c index 2dc7ada06ac5..d283e6bb1ff8 100644 --- a/drivers/i2c/busses/i2c-isch.c +++ b/drivers/i2c/busses/i2c-isch.c @@ -99,8 +99,7 @@ static int sch_transaction(void) if (retries > MAX_RETRIES) { dev_err(&sch_adapter.dev, "SMBus Timeout!\n"); result = -ETIMEDOUT; - } - if (temp & 0x04) { + } else if (temp & 0x04) { result = -EIO; dev_dbg(&sch_adapter.dev, "Bus collision! SMBus may be " "locked until next hard reset. (sorry!)\n"); diff --git a/drivers/i2c/busses/i2c-qcom-geni.c b/drivers/i2c/busses/i2c-qcom-geni.c index 86f028febce3..8758983a3ce1 100644 --- a/drivers/i2c/busses/i2c-qcom-geni.c +++ b/drivers/i2c/busses/i2c-qcom-geni.c @@ -569,15 +569,13 @@ static int geni_i2c_probe(struct platform_device *pdev) init_completion(&gi2c->done); spin_lock_init(&gi2c->lock); platform_set_drvdata(pdev, gi2c); - ret = devm_request_irq(dev, gi2c->irq, geni_i2c_irq, 0, + ret = devm_request_irq(dev, gi2c->irq, geni_i2c_irq, IRQF_NO_AUTOEN, dev_name(dev), gi2c); if (ret) { dev_err(dev, "Request_irq failed:%d: err:%d\n", gi2c->irq, ret); return ret; } - /* Disable the interrupt so that the system can enter low-power mode */ - disable_irq(gi2c->irq); i2c_set_adapdata(&gi2c->adap, gi2c); gi2c->adap.dev.parent = dev; gi2c->adap.dev.of_node = dev->of_node; diff --git a/drivers/i2c/busses/i2c-stm32f7.c b/drivers/i2c/busses/i2c-stm32f7.c index 7b9272f9cc21..0b4e73e63820 100644 --- a/drivers/i2c/busses/i2c-stm32f7.c +++ b/drivers/i2c/busses/i2c-stm32f7.c @@ -2278,7 +2278,7 @@ static int __maybe_unused stm32f7_i2c_runtime_suspend(struct device *dev) struct stm32f7_i2c_dev *i2c_dev = dev_get_drvdata(dev); if (!stm32f7_i2c_is_slave_registered(i2c_dev)) - clk_disable_unprepare(i2c_dev->clk); + clk_disable(i2c_dev->clk); return 0; } @@ -2289,9 +2289,9 @@ static int __maybe_unused stm32f7_i2c_runtime_resume(struct device *dev) int ret; if (!stm32f7_i2c_is_slave_registered(i2c_dev)) { - ret = clk_prepare_enable(i2c_dev->clk); + ret = clk_enable(i2c_dev->clk); if (ret) { - dev_err(dev, "failed to prepare_enable clock\n"); + dev_err(dev, "failed to enable clock\n"); return ret; } } diff --git a/drivers/i2c/busses/i2c-xiic.c b/drivers/i2c/busses/i2c-xiic.c index 568e97c3896d..caa27411cf6f 100644 --- a/drivers/i2c/busses/i2c-xiic.c +++ b/drivers/i2c/busses/i2c-xiic.c @@ -23,7 +23,7 @@ #include #include #include -#include +#include #include #include #include @@ -48,7 +48,7 @@ enum xiic_endian { * struct xiic_i2c - Internal representation of the XIIC I2C bus * @dev: Pointer to device structure * @base: Memory base of the HW registers - * @wait: Wait queue for callers + * @completion: Completion for callers * @adap: Kernel adapter representation * @tx_msg: Messages from above to be sent * @lock: Mutual exclusion @@ -64,7 +64,7 @@ enum xiic_endian { struct xiic_i2c { struct device *dev; void __iomem *base; - wait_queue_head_t wait; + struct completion completion; struct i2c_adapter adap; struct i2c_msg *tx_msg; struct mutex lock; @@ -160,6 +160,9 @@ struct xiic_i2c { #define XIIC_PM_TIMEOUT 1000 /* ms */ /* timeout waiting for the controller to respond */ #define XIIC_I2C_TIMEOUT (msecs_to_jiffies(1000)) +/* timeout waiting for the controller finish transfers */ +#define XIIC_XFER_TIMEOUT (msecs_to_jiffies(10000)) + /* * The following constant is used for the device global interrupt enable * register, to enable all interrupts for the device, this is the only bit @@ -170,7 +173,7 @@ struct xiic_i2c { #define xiic_tx_space(i2c) ((i2c)->tx_msg->len - (i2c)->tx_pos) #define xiic_rx_space(i2c) ((i2c)->rx_msg->len - (i2c)->rx_pos) -static int xiic_start_xfer(struct xiic_i2c *i2c); +static int xiic_start_xfer(struct xiic_i2c *i2c, struct i2c_msg *msgs, int num); static void __xiic_start_xfer(struct xiic_i2c *i2c); /* @@ -367,7 +370,7 @@ static void xiic_wakeup(struct xiic_i2c *i2c, int code) i2c->rx_msg = NULL; i2c->nmsgs = 0; i2c->state = code; - wake_up(&i2c->wait); + complete(&i2c->completion); } static irqreturn_t xiic_process(int irq, void *dev_id) @@ -491,14 +494,17 @@ static irqreturn_t xiic_process(int irq, void *dev_id) goto out; } - xiic_fill_tx_fifo(i2c); - - /* current message sent and there is space in the fifo */ - if (!xiic_tx_space(i2c) && xiic_tx_fifo_space(i2c) >= 2) { + if (xiic_tx_space(i2c)) { + xiic_fill_tx_fifo(i2c); + } else { + /* current message fully written */ dev_dbg(i2c->adap.dev.parent, "%s end of message sent, nmsgs: %d\n", __func__, i2c->nmsgs); - if (i2c->nmsgs > 1) { + /* Don't move onto the next message until the TX FIFO empties, + * to ensure that a NAK is not missed. + */ + if (i2c->nmsgs > 1 && (pend & XIIC_INTR_TX_EMPTY_MASK)) { i2c->nmsgs--; i2c->tx_msg++; xfer_more = 1; @@ -509,11 +515,7 @@ static irqreturn_t xiic_process(int irq, void *dev_id) "%s Got TX IRQ but no more to do...\n", __func__); } - } else if (!xiic_tx_space(i2c) && (i2c->nmsgs == 1)) - /* current frame is sent and is last, - * make sure to disable tx half - */ - xiic_irq_dis(i2c, XIIC_INTR_TX_HALF_MASK); + } } out: dev_dbg(i2c->adap.dev.parent, "%s clr: 0x%x\n", __func__, clr); @@ -537,23 +539,11 @@ static int xiic_bus_busy(struct xiic_i2c *i2c) return (sr & XIIC_SR_BUS_BUSY_MASK) ? -EBUSY : 0; } -static int xiic_busy(struct xiic_i2c *i2c) +static int xiic_wait_not_busy(struct xiic_i2c *i2c) { int tries = 3; int err; - if (i2c->tx_msg) - return -EBUSY; - - /* In single master mode bus can only be busy, when in use by this - * driver. If the register indicates bus being busy for some reason we - * should ignore it, since bus will never be released and i2c will be - * stuck forever. - */ - if (i2c->singlemaster) { - return 0; - } - /* for instance if previous transfer was terminated due to TX error * it might be that the bus is on it's way to become available * give it at most 3 ms to wake @@ -701,15 +691,52 @@ static void __xiic_start_xfer(struct xiic_i2c *i2c) } -static int xiic_start_xfer(struct xiic_i2c *i2c) +static int xiic_start_xfer(struct xiic_i2c *i2c, struct i2c_msg *msgs, int num) { int ret; + mutex_lock(&i2c->lock); + if (i2c->tx_msg || i2c->rx_msg) { + dev_err(i2c->adap.dev.parent, + "cannot start a transfer while busy\n"); + ret = -EBUSY; + goto out; + } + + /* In single master mode bus can only be busy, when in use by this + * driver. If the register indicates bus being busy for some reason we + * should ignore it, since bus will never be released and i2c will be + * stuck forever. + */ + if (!i2c->singlemaster) { + ret = xiic_wait_not_busy(i2c); + if (ret) { + /* If the bus is stuck in a busy state, such as due to spurious low + * pulses on the bus causing a false start condition to be detected, + * then try to recover by re-initializing the controller and check + * again if the bus is still busy. + */ + dev_warn(i2c->adap.dev.parent, "I2C bus busy timeout, reinitializing\n"); + ret = xiic_reinit(i2c); + if (ret) + goto out; + ret = xiic_wait_not_busy(i2c); + if (ret) + goto out; + } + } + + i2c->tx_msg = msgs; + i2c->rx_msg = NULL; + i2c->nmsgs = num; + init_completion(&i2c->completion); + ret = xiic_reinit(i2c); if (!ret) __xiic_start_xfer(i2c); +out: mutex_unlock(&i2c->lock); return ret; @@ -727,30 +754,26 @@ static int xiic_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num) if (err < 0) return err; - err = xiic_busy(i2c); - if (err) + err = xiic_start_xfer(i2c, msgs, num); + if (err < 0) goto out; - i2c->tx_msg = msgs; - i2c->nmsgs = num; - - err = xiic_start_xfer(i2c); - if (err < 0) { - dev_err(adap->dev.parent, "Error xiic_start_xfer\n"); - goto out; - } - - if (wait_event_timeout(i2c->wait, (i2c->state == STATE_ERROR) || - (i2c->state == STATE_DONE), HZ)) { - err = (i2c->state == STATE_DONE) ? num : -EIO; - goto out; - } else { + err = wait_for_completion_timeout(&i2c->completion, XIIC_XFER_TIMEOUT); + mutex_lock(&i2c->lock); + if (err == 0) { /* Timeout */ i2c->tx_msg = NULL; i2c->rx_msg = NULL; i2c->nmsgs = 0; err = -ETIMEDOUT; - goto out; + } else if (err < 0) { /* Completion error */ + i2c->tx_msg = NULL; + i2c->rx_msg = NULL; + i2c->nmsgs = 0; + } else { + err = (i2c->state == STATE_DONE) ? num : -EIO; } + mutex_unlock(&i2c->lock); + out: pm_runtime_mark_last_busy(i2c->dev); pm_runtime_put_autosuspend(i2c->dev); @@ -813,19 +836,12 @@ static int xiic_i2c_probe(struct platform_device *pdev) DRIVER_NAME " %s", pdev->name); mutex_init(&i2c->lock); - init_waitqueue_head(&i2c->wait); - i2c->clk = devm_clk_get(&pdev->dev, NULL); - if (IS_ERR(i2c->clk)) { - if (PTR_ERR(i2c->clk) != -EPROBE_DEFER) - dev_err(&pdev->dev, "input clock not found.\n"); - return PTR_ERR(i2c->clk); - } - ret = clk_prepare_enable(i2c->clk); - if (ret) { - dev_err(&pdev->dev, "Unable to enable clock.\n"); - return ret; - } + i2c->clk = devm_clk_get_enabled(&pdev->dev, NULL); + if (IS_ERR(i2c->clk)) + return dev_err_probe(&pdev->dev, PTR_ERR(i2c->clk), + "failed to enable input clock.\n"); + i2c->dev = &pdev->dev; pm_runtime_set_autosuspend_delay(i2c->dev, XIIC_PM_TIMEOUT); pm_runtime_use_autosuspend(i2c->dev); @@ -837,7 +853,7 @@ static int xiic_i2c_probe(struct platform_device *pdev) if (ret < 0) { dev_err(&pdev->dev, "Cannot claim IRQ\n"); - goto err_clk_dis; + goto err_pm_disable; } i2c->singlemaster = @@ -858,14 +874,14 @@ static int xiic_i2c_probe(struct platform_device *pdev) ret = xiic_reinit(i2c); if (ret < 0) { dev_err(&pdev->dev, "Cannot xiic_reinit\n"); - goto err_clk_dis; + goto err_pm_disable; } /* add i2c adapter to i2c tree */ ret = i2c_add_adapter(&i2c->adap); if (ret) { xiic_deinit(i2c); - goto err_clk_dis; + goto err_pm_disable; } if (pdata) { @@ -876,10 +892,10 @@ static int xiic_i2c_probe(struct platform_device *pdev) return 0; -err_clk_dis: - pm_runtime_set_suspended(&pdev->dev); +err_pm_disable: pm_runtime_disable(&pdev->dev); - clk_disable_unprepare(i2c->clk); + pm_runtime_set_suspended(&pdev->dev); + return ret; } @@ -897,7 +913,6 @@ static int xiic_i2c_remove(struct platform_device *pdev) xiic_deinit(i2c); pm_runtime_put_sync(i2c->dev); - clk_disable_unprepare(i2c->clk); pm_runtime_disable(&pdev->dev); pm_runtime_set_suspended(&pdev->dev); pm_runtime_dont_use_autosuspend(&pdev->dev); diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig index 4b5014875b7e..210807b06734 100644 --- a/drivers/iio/adc/Kconfig +++ b/drivers/iio/adc/Kconfig @@ -1146,6 +1146,8 @@ config TI_ADS8344 config TI_ADS8688 tristate "Texas Instruments ADS8688" depends on SPI && OF + select IIO_BUFFER + select IIO_TRIGGERED_BUFFER help If you say yes here you get support for Texas Instruments ADS8684 and and ADS8688 ADC chips @@ -1156,6 +1158,8 @@ config TI_ADS8688 config TI_ADS124S08 tristate "Texas Instruments ADS124S08" depends on SPI && OF + select IIO_BUFFER + select IIO_TRIGGERED_BUFFER help If you say yes here you get support for Texas Instruments ADS124S08 and ADS124S06 ADC chips diff --git a/drivers/iio/adc/ad7606.c b/drivers/iio/adc/ad7606.c index ee7b108688b3..141c75be27e1 100644 --- a/drivers/iio/adc/ad7606.c +++ b/drivers/iio/adc/ad7606.c @@ -238,9 +238,9 @@ static int ad7606_write_os_hw(struct iio_dev *indio_dev, int val) struct ad7606_state *st = iio_priv(indio_dev); DECLARE_BITMAP(values, 3); - values[0] = val; + values[0] = val & GENMASK(2, 0); - gpiod_set_array_value(ARRAY_SIZE(values), st->gpio_os->desc, + gpiod_set_array_value(st->gpio_os->ndescs, st->gpio_os->desc, st->gpio_os->info, values); /* AD7616 requires a reset to update value */ @@ -445,7 +445,7 @@ static int ad7606_request_gpios(struct ad7606_state *st) return PTR_ERR(st->gpio_range); st->gpio_standby = devm_gpiod_get_optional(dev, "standby", - GPIOD_OUT_HIGH); + GPIOD_OUT_LOW); if (IS_ERR(st->gpio_standby)) return PTR_ERR(st->gpio_standby); @@ -704,7 +704,7 @@ static int ad7606_suspend(struct device *dev) if (st->gpio_standby) { gpiod_set_value(st->gpio_range, 1); - gpiod_set_value(st->gpio_standby, 0); + gpiod_set_value(st->gpio_standby, 1); } return 0; diff --git a/drivers/iio/adc/ad7606_spi.c b/drivers/iio/adc/ad7606_spi.c index 29945ad07dca..e1ad2cd61b7f 100644 --- a/drivers/iio/adc/ad7606_spi.c +++ b/drivers/iio/adc/ad7606_spi.c @@ -249,8 +249,9 @@ static int ad7616_sw_mode_config(struct iio_dev *indio_dev) static int ad7606B_sw_mode_config(struct iio_dev *indio_dev) { struct ad7606_state *st = iio_priv(indio_dev); - unsigned long os[3] = {1}; + DECLARE_BITMAP(os, 3); + bitmap_fill(os, 3); /* * Software mode is enabled when all three oversampling * pins are set to high. If oversampling gpios are defined @@ -258,7 +259,7 @@ static int ad7606B_sw_mode_config(struct iio_dev *indio_dev) * otherwise, they must be hardwired to VDD */ if (st->gpio_os) { - gpiod_set_array_value(ARRAY_SIZE(os), + gpiod_set_array_value(st->gpio_os->ndescs, st->gpio_os->desc, st->gpio_os->info, os); } /* OS of 128 and 256 are available only in software mode */ diff --git a/drivers/iio/common/hid-sensors/hid-sensor-trigger.c b/drivers/iio/common/hid-sensors/hid-sensor-trigger.c index ff375790b7e8..ab4d9a335b7c 100644 --- a/drivers/iio/common/hid-sensors/hid-sensor-trigger.c +++ b/drivers/iio/common/hid-sensors/hid-sensor-trigger.c @@ -35,7 +35,7 @@ static ssize_t _hid_sensor_set_report_latency(struct device *dev, latency = integer * 1000 + fract / 1000; ret = hid_sensor_set_report_latency(attrb, latency); if (ret < 0) - return len; + return ret; attrb->latency_ms = hid_sensor_get_report_latency(attrb); diff --git a/drivers/iio/dac/Kconfig b/drivers/iio/dac/Kconfig index dae8d27e772d..cd11c1737ae1 100644 --- a/drivers/iio/dac/Kconfig +++ b/drivers/iio/dac/Kconfig @@ -191,6 +191,7 @@ config AD5764 config AD5770R tristate "Analog Devices AD5770R IDAC driver" depends on SPI_MASTER + select REGMAP_SPI help Say yes here to build support for Analog Devices AD5770R Digital to Analog Converter. @@ -271,6 +272,7 @@ config LPC18XX_DAC config LTC1660 tristate "Linear Technology LTC1660/LTC1665 DAC SPI driver" depends on SPI + select REGMAP_SPI help Say yes here to build support for Linear Technology LTC1660 and LTC1665 Digital to Analog Converters. @@ -357,6 +359,7 @@ config STM32_DAC config STM32_DAC_CORE tristate + select REGMAP_MMIO config TI_DAC082S085 tristate "Texas Instruments 8/10/12-bit 2/4-channel DAC driver" diff --git a/drivers/iio/light/opt3001.c b/drivers/iio/light/opt3001.c index ff776259734a..ff01fc9fc0b2 100644 --- a/drivers/iio/light/opt3001.c +++ b/drivers/iio/light/opt3001.c @@ -138,6 +138,10 @@ static const struct opt3001_scale opt3001_scales[] = { .val = 20966, .val2 = 400000, }, + { + .val = 41932, + .val2 = 800000, + }, { .val = 83865, .val2 = 600000, diff --git a/drivers/iio/light/veml6030.c b/drivers/iio/light/veml6030.c index de85c9b30be1..f859cdb3094c 100644 --- a/drivers/iio/light/veml6030.c +++ b/drivers/iio/light/veml6030.c @@ -99,9 +99,8 @@ static const char * const period_values[] = { static ssize_t in_illuminance_period_available_show(struct device *dev, struct device_attribute *attr, char *buf) { + struct veml6030_data *data = iio_priv(dev_to_iio_dev(dev)); int ret, reg, x; - struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev)); - struct veml6030_data *data = iio_priv(indio_dev); ret = regmap_read(data->regmap, VEML6030_REG_ALS_CONF, ®); if (ret) { @@ -780,7 +779,7 @@ static int veml6030_hw_init(struct iio_dev *indio_dev) /* Cache currently active measurement parameters */ data->cur_gain = 3; - data->cur_resolution = 4608; + data->cur_resolution = 5376; data->cur_integration_time = 3; return ret; diff --git a/drivers/iio/magnetometer/ak8975.c b/drivers/iio/magnetometer/ak8975.c index 3774e5975f77..fd3a6cd16bcf 100644 --- a/drivers/iio/magnetometer/ak8975.c +++ b/drivers/iio/magnetometer/ak8975.c @@ -661,22 +661,8 @@ static int ak8975_start_read_axis(struct ak8975_data *data, if (ret < 0) return ret; - /* This will be executed only for non-interrupt based waiting case */ - if (ret & data->def->ctrl_masks[ST1_DRDY]) { - ret = i2c_smbus_read_byte_data(client, - data->def->ctrl_regs[ST2]); - if (ret < 0) { - dev_err(&client->dev, "Error in reading ST2\n"); - return ret; - } - if (ret & (data->def->ctrl_masks[ST2_DERR] | - data->def->ctrl_masks[ST2_HOFL])) { - dev_err(&client->dev, "ST2 status error 0x%x\n", ret); - return -EINVAL; - } - } - - return 0; + /* Return with zero if the data is ready. */ + return !data->def->ctrl_regs[ST1_DRDY]; } /* Retrieve raw flux value for one of the x, y, or z axis. */ @@ -703,6 +689,20 @@ static int ak8975_read_axis(struct iio_dev *indio_dev, int index, int *val) if (ret < 0) goto exit; + /* Read out ST2 for release lock on measurment data. */ + ret = i2c_smbus_read_byte_data(client, data->def->ctrl_regs[ST2]); + if (ret < 0) { + dev_err(&client->dev, "Error in reading ST2\n"); + goto exit; + } + + if (ret & (data->def->ctrl_masks[ST2_DERR] | + data->def->ctrl_masks[ST2_HOFL])) { + dev_err(&client->dev, "ST2 status error 0x%x\n", ret); + ret = -EINVAL; + goto exit; + } + mutex_unlock(&data->lock); pm_runtime_mark_last_busy(&data->client->dev); diff --git a/drivers/iio/proximity/Kconfig b/drivers/iio/proximity/Kconfig index 12672a0e89ed..e6857223d5a7 100644 --- a/drivers/iio/proximity/Kconfig +++ b/drivers/iio/proximity/Kconfig @@ -49,6 +49,8 @@ config LIDAR_LITE_V2 config MB1232 tristate "MaxSonar I2CXL family ultrasonic sensors" depends on I2C + select IIO_BUFFER + select IIO_TRIGGERED_BUFFER help Say Y to build a driver for the ultrasonic sensors I2CXL of MaxBotix which have an i2c interface. It can be used to measure diff --git a/drivers/infiniband/core/iwcm.c b/drivers/infiniband/core/iwcm.c index 7a6747850aea..44362f693df9 100644 --- a/drivers/infiniband/core/iwcm.c +++ b/drivers/infiniband/core/iwcm.c @@ -1192,7 +1192,7 @@ static int __init iw_cm_init(void) if (ret) return ret; - iwcm_wq = alloc_ordered_workqueue("iw_cm_wq", 0); + iwcm_wq = alloc_ordered_workqueue("iw_cm_wq", WQ_MEM_RECLAIM); if (!iwcm_wq) goto err_alloc; diff --git a/drivers/infiniband/core/mad.c b/drivers/infiniband/core/mad.c index 9355e521d9f4..521c3d050be2 100644 --- a/drivers/infiniband/core/mad.c +++ b/drivers/infiniband/core/mad.c @@ -2631,14 +2631,16 @@ static int retry_send(struct ib_mad_send_wr_private *mad_send_wr) static void timeout_sends(struct work_struct *work) { + struct ib_mad_send_wr_private *mad_send_wr, *n; struct ib_mad_agent_private *mad_agent_priv; - struct ib_mad_send_wr_private *mad_send_wr; struct ib_mad_send_wc mad_send_wc; + struct list_head local_list; unsigned long flags, delay; mad_agent_priv = container_of(work, struct ib_mad_agent_private, timed_work.work); mad_send_wc.vendor_err = 0; + INIT_LIST_HEAD(&local_list); spin_lock_irqsave(&mad_agent_priv->lock, flags); while (!list_empty(&mad_agent_priv->wait_list)) { @@ -2656,13 +2658,16 @@ static void timeout_sends(struct work_struct *work) break; } - list_del(&mad_send_wr->agent_list); + list_del_init(&mad_send_wr->agent_list); if (mad_send_wr->status == IB_WC_SUCCESS && !retry_send(mad_send_wr)) continue; - spin_unlock_irqrestore(&mad_agent_priv->lock, flags); + list_add_tail(&mad_send_wr->agent_list, &local_list); + } + spin_unlock_irqrestore(&mad_agent_priv->lock, flags); + list_for_each_entry_safe(mad_send_wr, n, &local_list, agent_list) { if (mad_send_wr->status == IB_WC_SUCCESS) mad_send_wc.status = IB_WC_RESP_TIMEOUT_ERR; else @@ -2670,11 +2675,8 @@ static void timeout_sends(struct work_struct *work) mad_send_wc.send_buf = &mad_send_wr->send_buf; mad_agent_priv->agent.send_handler(&mad_agent_priv->agent, &mad_send_wc); - deref_mad_agent(mad_agent_priv); - spin_lock_irqsave(&mad_agent_priv->lock, flags); } - spin_unlock_irqrestore(&mad_agent_priv->lock, flags); } /* diff --git a/drivers/infiniband/hw/bnxt_re/qplib_fp.h b/drivers/infiniband/hw/bnxt_re/qplib_fp.h index f112f013df7d..01cb48caa9db 100644 --- a/drivers/infiniband/hw/bnxt_re/qplib_fp.h +++ b/drivers/infiniband/hw/bnxt_re/qplib_fp.h @@ -167,7 +167,7 @@ struct bnxt_qplib_swqe { }; u32 q_key; u32 dst_qp; - u16 avid; + u32 avid; } send; /* Send Raw Ethernet and QP1 */ diff --git a/drivers/infiniband/hw/bnxt_re/qplib_rcfw.c b/drivers/infiniband/hw/bnxt_re/qplib_rcfw.c index 2b0c3a86293c..148f2c51a946 100644 --- a/drivers/infiniband/hw/bnxt_re/qplib_rcfw.c +++ b/drivers/infiniband/hw/bnxt_re/qplib_rcfw.c @@ -245,7 +245,7 @@ int bnxt_qplib_rcfw_send_message(struct bnxt_qplib_rcfw *rcfw, /* failed with status */ dev_err(&rcfw->pdev->dev, "cmdq[%#x]=%#x status %#x\n", cookie, opcode, evnt->status); - rc = -EFAULT; + rc = -EIO; } return rc; diff --git a/drivers/infiniband/hw/bnxt_re/qplib_res.c b/drivers/infiniband/hw/bnxt_re/qplib_res.c index 123ea759f282..af23e57fc78e 100644 --- a/drivers/infiniband/hw/bnxt_re/qplib_res.c +++ b/drivers/infiniband/hw/bnxt_re/qplib_res.c @@ -243,6 +243,8 @@ int bnxt_qplib_alloc_init_hwq(struct bnxt_qplib_hwq *hwq, sginfo.pgsize = npde * pg_size; sginfo.npages = 1; rc = __alloc_pbl(res, &hwq->pbl[PBL_LVL_0], &sginfo); + if (rc) + goto fail; /* Alloc PBL pages */ sginfo.npages = npbl; @@ -254,22 +256,9 @@ int bnxt_qplib_alloc_init_hwq(struct bnxt_qplib_hwq *hwq, dst_virt_ptr = (dma_addr_t **)hwq->pbl[PBL_LVL_0].pg_arr; src_phys_ptr = hwq->pbl[PBL_LVL_1].pg_map_arr; - if (hwq_attr->type == HWQ_TYPE_MR) { - /* For MR it is expected that we supply only 1 contigous - * page i.e only 1 entry in the PDL that will contain - * all the PBLs for the user supplied memory region - */ - for (i = 0; i < hwq->pbl[PBL_LVL_1].pg_count; - i++) - dst_virt_ptr[0][i] = src_phys_ptr[i] | - flag; - } else { - for (i = 0; i < hwq->pbl[PBL_LVL_1].pg_count; - i++) - dst_virt_ptr[PTR_PG(i)][PTR_IDX(i)] = - src_phys_ptr[i] | - PTU_PDE_VALID; - } + for (i = 0; i < hwq->pbl[PBL_LVL_1].pg_count; i++) + dst_virt_ptr[0][i] = src_phys_ptr[i] | flag; + /* Alloc or init PTEs */ rc = __alloc_pbl(res, &hwq->pbl[PBL_LVL_2], hwq_attr->sginfo); diff --git a/drivers/infiniband/hw/cxgb4/cm.c b/drivers/infiniband/hw/cxgb4/cm.c index 8c54b1be0442..b607c1782738 100644 --- a/drivers/infiniband/hw/cxgb4/cm.c +++ b/drivers/infiniband/hw/cxgb4/cm.c @@ -1222,6 +1222,8 @@ static int act_establish(struct c4iw_dev *dev, struct sk_buff *skb) int ret; ep = lookup_atid(t, atid); + if (!ep) + return -EINVAL; pr_debug("ep %p tid %u snd_isn %u rcv_isn %u\n", ep, tid, be32_to_cpu(req->snd_isn), be32_to_cpu(req->rcv_isn)); @@ -2084,7 +2086,7 @@ static int import_ep(struct c4iw_ep *ep, int iptype, __u8 *peer_ip, err = -ENOMEM; if (n->dev->flags & IFF_LOOPBACK) { if (iptype == 4) - pdev = ip_dev_find(&init_net, *(__be32 *)peer_ip); + pdev = __ip_dev_find(&init_net, *(__be32 *)peer_ip, false); else if (IS_ENABLED(CONFIG_IPV6)) for_each_netdev(&init_net, pdev) { if (ipv6_chk_addr(&init_net, @@ -2099,12 +2101,12 @@ static int import_ep(struct c4iw_ep *ep, int iptype, __u8 *peer_ip, err = -ENODEV; goto out; } + if (is_vlan_dev(pdev)) + pdev = vlan_dev_real_dev(pdev); ep->l2t = cxgb4_l2t_get(cdev->rdev.lldi.l2t, n, pdev, rt_tos2priority(tos)); - if (!ep->l2t) { - dev_put(pdev); + if (!ep->l2t) goto out; - } ep->mtu = pdev->mtu; ep->tx_chan = cxgb4_port_chan(pdev); ep->smac_idx = ((struct port_info *)netdev_priv(pdev))->smt_idx; @@ -2117,7 +2119,6 @@ static int import_ep(struct c4iw_ep *ep, int iptype, __u8 *peer_ip, ep->rss_qid = cdev->rdev.lldi.rxq_ids[ cxgb4_port_idx(pdev) * step]; set_tcp_window(ep, (struct port_info *)netdev_priv(pdev)); - dev_put(pdev); } else { pdev = get_real_dev(n->dev); ep->l2t = cxgb4_l2t_get(cdev->rdev.lldi.l2t, @@ -2279,6 +2280,9 @@ static int act_open_rpl(struct c4iw_dev *dev, struct sk_buff *skb) int ret = 0; ep = lookup_atid(t, atid); + if (!ep) + return -EINVAL; + la = (struct sockaddr_in *)&ep->com.local_addr; ra = (struct sockaddr_in *)&ep->com.remote_addr; la6 = (struct sockaddr_in6 *)&ep->com.local_addr; diff --git a/drivers/infiniband/hw/hns/hns_roce_hem.c b/drivers/infiniband/hw/hns/hns_roce_hem.c index 854b41c14774..61ec96b3a89d 100644 --- a/drivers/infiniband/hw/hns/hns_roce_hem.c +++ b/drivers/infiniband/hw/hns/hns_roce_hem.c @@ -959,7 +959,7 @@ void hns_roce_cleanup_hem(struct hns_roce_dev *hr_dev) hns_roce_cleanup_hem_table(hr_dev, &hr_dev->mr_table.mtpt_table); } -struct roce_hem_item { +struct hns_roce_hem_item { struct list_head list; /* link all hems in the same bt level */ struct list_head sibling; /* link all hems in last hop for mtt */ void *addr; @@ -969,21 +969,26 @@ struct roce_hem_item { int end; /* end buf offset in this hem */ }; -static struct roce_hem_item *hem_list_alloc_item(struct hns_roce_dev *hr_dev, - int start, int end, - int count, bool exist_bt, - int bt_level) +/* All HEM items are linked in a tree structure */ +struct hns_roce_hem_head { + struct list_head branch[HNS_ROCE_MAX_BT_REGION]; + struct list_head root; + struct list_head leaf; +}; + +static struct hns_roce_hem_item * +hem_list_alloc_item(struct hns_roce_dev *hr_dev, int start, int end, int count, + bool exist_bt, int bt_level) { - struct roce_hem_item *hem; + struct hns_roce_hem_item *hem; hem = kzalloc(sizeof(*hem), GFP_KERNEL); if (!hem) return NULL; if (exist_bt) { - hem->addr = dma_alloc_coherent(hr_dev->dev, - count * BA_BYTE_LEN, - &hem->dma_addr, GFP_KERNEL); + hem->addr = dma_alloc_coherent(hr_dev->dev, count * BA_BYTE_LEN, + &hem->dma_addr, GFP_KERNEL); if (!hem->addr) { kfree(hem); return NULL; @@ -1000,7 +1005,7 @@ static struct roce_hem_item *hem_list_alloc_item(struct hns_roce_dev *hr_dev, } static void hem_list_free_item(struct hns_roce_dev *hr_dev, - struct roce_hem_item *hem, bool exist_bt) + struct hns_roce_hem_item *hem, bool exist_bt) { if (exist_bt) dma_free_coherent(hr_dev->dev, hem->count * BA_BYTE_LEN, @@ -1011,7 +1016,7 @@ static void hem_list_free_item(struct hns_roce_dev *hr_dev, static void hem_list_free_all(struct hns_roce_dev *hr_dev, struct list_head *head, bool exist_bt) { - struct roce_hem_item *hem, *temp_hem; + struct hns_roce_hem_item *hem, *temp_hem; list_for_each_entry_safe(hem, temp_hem, head, list) { list_del(&hem->list); @@ -1027,24 +1032,24 @@ static void hem_list_link_bt(struct hns_roce_dev *hr_dev, void *base_addr, /* assign L0 table address to hem from root bt */ static void hem_list_assign_bt(struct hns_roce_dev *hr_dev, - struct roce_hem_item *hem, void *cpu_addr, + struct hns_roce_hem_item *hem, void *cpu_addr, u64 phy_addr) { hem->addr = cpu_addr; hem->dma_addr = (dma_addr_t)phy_addr; } -static inline bool hem_list_page_is_in_range(struct roce_hem_item *hem, +static inline bool hem_list_page_is_in_range(struct hns_roce_hem_item *hem, int offset) { return (hem->start <= offset && offset <= hem->end); } -static struct roce_hem_item *hem_list_search_item(struct list_head *ba_list, - int page_offset) +static struct hns_roce_hem_item *hem_list_search_item(struct list_head *ba_list, + int page_offset) { - struct roce_hem_item *hem, *temp_hem; - struct roce_hem_item *found = NULL; + struct hns_roce_hem_item *hem, *temp_hem; + struct hns_roce_hem_item *found = NULL; list_for_each_entry_safe(hem, temp_hem, ba_list, list) { if (hem_list_page_is_in_range(hem, page_offset)) { @@ -1074,9 +1079,9 @@ static bool hem_list_is_bottom_bt(int hopnum, int bt_level) * @bt_level: base address table level * @unit: ba entries per bt page */ -static u32 hem_list_calc_ba_range(int hopnum, int bt_level, int unit) +static u64 hem_list_calc_ba_range(int hopnum, int bt_level, int unit) { - u32 step; + u64 step; int max; int i; @@ -1112,7 +1117,7 @@ int hns_roce_hem_list_calc_root_ba(const struct hns_roce_buf_region *regions, { struct hns_roce_buf_region *r; int total = 0; - int step; + u64 step; int i; for (i = 0; i < region_cnt; i++) { @@ -1134,16 +1139,16 @@ static int hem_list_alloc_mid_bt(struct hns_roce_dev *hr_dev, int offset, struct list_head *mid_bt, struct list_head *btm_bt) { - struct roce_hem_item *hem_ptrs[HNS_ROCE_MAX_BT_LEVEL] = { NULL }; + struct hns_roce_hem_item *hem_ptrs[HNS_ROCE_MAX_BT_LEVEL] = { NULL }; struct list_head temp_list[HNS_ROCE_MAX_BT_LEVEL]; - struct roce_hem_item *cur, *pre; + struct hns_roce_hem_item *cur, *pre; const int hopnum = r->hopnum; int start_aligned; int distance; int ret = 0; int max_ofs; int level; - u32 step; + u64 step; int end; if (hopnum <= 1) @@ -1167,10 +1172,12 @@ static int hem_list_alloc_mid_bt(struct hns_roce_dev *hr_dev, /* config L1 bt to last bt and link them to corresponding parent */ for (level = 1; level < hopnum; level++) { - cur = hem_list_search_item(&mid_bt[level], offset); - if (cur) { - hem_ptrs[level] = cur; - continue; + if (!hem_list_is_bottom_bt(hopnum, level)) { + cur = hem_list_search_item(&mid_bt[level], offset); + if (cur) { + hem_ptrs[level] = cur; + continue; + } } step = hem_list_calc_ba_range(hopnum, level, unit); @@ -1180,7 +1187,7 @@ static int hem_list_alloc_mid_bt(struct hns_roce_dev *hr_dev, } start_aligned = (distance / step) * step + r->offset; - end = min_t(int, start_aligned + step - 1, max_ofs); + end = min_t(u64, start_aligned + step - 1, max_ofs); cur = hem_list_alloc_item(hr_dev, start_aligned, end, unit, true, level); if (!cur) { @@ -1214,52 +1221,96 @@ static int hem_list_alloc_mid_bt(struct hns_roce_dev *hr_dev, return ret; } -static int hem_list_alloc_root_bt(struct hns_roce_dev *hr_dev, - struct hns_roce_hem_list *hem_list, int unit, - const struct hns_roce_buf_region *regions, - int region_cnt) +static struct hns_roce_hem_item * +alloc_root_hem(struct hns_roce_dev *hr_dev, int unit, int *max_ba_num, + const struct hns_roce_buf_region *regions, int region_cnt) { - struct list_head temp_list[HNS_ROCE_MAX_BT_REGION]; - struct roce_hem_item *hem, *temp_hem, *root_hem; const struct hns_roce_buf_region *r; - struct list_head temp_root; - struct list_head temp_btm; - void *cpu_base; - u64 phy_base; - int ret = 0; + struct hns_roce_hem_item *hem; int ba_num; int offset; - int total; - int step; - int i; - - r = ®ions[0]; - root_hem = hem_list_search_item(&hem_list->root_bt, r->offset); - if (root_hem) - return 0; ba_num = hns_roce_hem_list_calc_root_ba(regions, region_cnt, unit); if (ba_num < 1) - return -ENOMEM; + return ERR_PTR(-ENOMEM); - INIT_LIST_HEAD(&temp_root); - offset = r->offset; + if (ba_num > unit) + return ERR_PTR(-ENOBUFS); + + offset = regions[0].offset; /* indicate to last region */ r = ®ions[region_cnt - 1]; - root_hem = hem_list_alloc_item(hr_dev, offset, r->offset + r->count - 1, - ba_num, true, 0); + hem = hem_list_alloc_item(hr_dev, offset, r->offset + r->count - 1, + ba_num, true, 0); + if (!hem) + return ERR_PTR(-ENOMEM); + + *max_ba_num = ba_num; + + return hem; +} + +static int alloc_fake_root_bt(struct hns_roce_dev *hr_dev, void *cpu_base, + u64 phy_base, const struct hns_roce_buf_region *r, + struct list_head *branch_head, + struct list_head *leaf_head) +{ + struct hns_roce_hem_item *hem; + + hem = hem_list_alloc_item(hr_dev, r->offset, r->offset + r->count - 1, + r->count, false, 0); + if (!hem) + return -ENOMEM; + + hem_list_assign_bt(hr_dev, hem, cpu_base, phy_base); + list_add(&hem->list, branch_head); + list_add(&hem->sibling, leaf_head); + + return r->count; +} + +static int setup_middle_bt(struct hns_roce_dev *hr_dev, void *cpu_base, + int unit, const struct hns_roce_buf_region *r, + const struct list_head *branch_head) +{ + struct hns_roce_hem_item *hem, *temp_hem; + int total = 0; + int offset; + u64 step; + + step = hem_list_calc_ba_range(r->hopnum, 1, unit); + if (step < 1) + return -EINVAL; + + /* if exist mid bt, link L1 to L0 */ + list_for_each_entry_safe(hem, temp_hem, branch_head, list) { + offset = (hem->start - r->offset) / step * BA_BYTE_LEN; + hem_list_link_bt(hr_dev, cpu_base + offset, hem->dma_addr); + total++; + } + + return total; +} + +static int +setup_root_hem(struct hns_roce_dev *hr_dev, struct hns_roce_hem_list *hem_list, + int unit, int max_ba_num, struct hns_roce_hem_head *head, + const struct hns_roce_buf_region *regions, int region_cnt) +{ + const struct hns_roce_buf_region *r; + struct hns_roce_hem_item *root_hem; + void *cpu_base; + u64 phy_base; + int i, total; + int ret; + + root_hem = list_first_entry(&head->root, + struct hns_roce_hem_item, list); if (!root_hem) return -ENOMEM; - list_add(&root_hem->list, &temp_root); - - hem_list->root_ba = root_hem->dma_addr; - - INIT_LIST_HEAD(&temp_btm); - for (i = 0; i < region_cnt; i++) - INIT_LIST_HEAD(&temp_list[i]); total = 0; - for (i = 0; i < region_cnt && total < ba_num; i++) { + for (i = 0; i < region_cnt && total < max_ba_num; i++) { r = ®ions[i]; if (!r->count) continue; @@ -1271,48 +1322,64 @@ static int hem_list_alloc_root_bt(struct hns_roce_dev *hr_dev, /* if hopnum is 0 or 1, cut a new fake hem from the root bt * which's address share to all regions. */ - if (hem_list_is_bottom_bt(r->hopnum, 0)) { - hem = hem_list_alloc_item(hr_dev, r->offset, - r->offset + r->count - 1, - r->count, false, 0); - if (!hem) { - ret = -ENOMEM; - goto err_exit; - } - hem_list_assign_bt(hr_dev, hem, cpu_base, phy_base); - list_add(&hem->list, &temp_list[i]); - list_add(&hem->sibling, &temp_btm); - total += r->count; - } else { - step = hem_list_calc_ba_range(r->hopnum, 1, unit); - if (step < 1) { - ret = -EINVAL; - goto err_exit; - } - /* if exist mid bt, link L1 to L0 */ - list_for_each_entry_safe(hem, temp_hem, - &hem_list->mid_bt[i][1], list) { - offset = (hem->start - r->offset) / step * - BA_BYTE_LEN; - hem_list_link_bt(hr_dev, cpu_base + offset, - hem->dma_addr); - total++; - } - } + if (hem_list_is_bottom_bt(r->hopnum, 0)) + ret = alloc_fake_root_bt(hr_dev, cpu_base, phy_base, r, + &head->branch[i], &head->leaf); + else + ret = setup_middle_bt(hr_dev, cpu_base, unit, r, + &hem_list->mid_bt[i][1]); + + if (ret < 0) + return ret; + + total += ret; } - list_splice(&temp_btm, &hem_list->btm_bt); - list_splice(&temp_root, &hem_list->root_bt); + list_splice(&head->leaf, &hem_list->btm_bt); + list_splice(&head->root, &hem_list->root_bt); for (i = 0; i < region_cnt; i++) - list_splice(&temp_list[i], &hem_list->mid_bt[i][0]); + list_splice(&head->branch[i], &hem_list->mid_bt[i][0]); return 0; +} -err_exit: +static int hem_list_alloc_root_bt(struct hns_roce_dev *hr_dev, + struct hns_roce_hem_list *hem_list, int unit, + const struct hns_roce_buf_region *regions, + int region_cnt) +{ + struct hns_roce_hem_item *root_hem; + struct hns_roce_hem_head head; + int max_ba_num; + int ret; + int i; + + root_hem = hem_list_search_item(&hem_list->root_bt, regions[0].offset); + if (root_hem) + return 0; + + max_ba_num = 0; + root_hem = alloc_root_hem(hr_dev, unit, &max_ba_num, regions, + region_cnt); + if (IS_ERR(root_hem)) + return PTR_ERR(root_hem); + + /* List head for storing all allocated HEM items */ + INIT_LIST_HEAD(&head.root); + INIT_LIST_HEAD(&head.leaf); for (i = 0; i < region_cnt; i++) - hem_list_free_all(hr_dev, &temp_list[i], false); + INIT_LIST_HEAD(&head.branch[i]); - hem_list_free_all(hr_dev, &temp_root, true); + hem_list->root_ba = root_hem->dma_addr; + list_add(&root_hem->list, &head.root); + ret = setup_root_hem(hr_dev, hem_list, unit, max_ba_num, &head, regions, + region_cnt); + if (ret) { + for (i = 0; i < region_cnt; i++) + hem_list_free_all(hr_dev, &head.branch[i], false); + + hem_list_free_all(hr_dev, &head.root, true); + } return ret; } @@ -1398,7 +1465,7 @@ void *hns_roce_hem_list_find_mtt(struct hns_roce_dev *hr_dev, int offset, int *mtt_cnt, u64 *phy_addr) { struct list_head *head = &hem_list->btm_bt; - struct roce_hem_item *hem, *temp_hem; + struct hns_roce_hem_item *hem, *temp_hem; void *cpu_base = NULL; u64 phy_base = 0; int nr = 0; diff --git a/drivers/infiniband/hw/hns/hns_roce_mr.c b/drivers/infiniband/hw/hns/hns_roce_mr.c index 7e93c9b4a33f..5f038bd5571d 100644 --- a/drivers/infiniband/hw/hns/hns_roce_mr.c +++ b/drivers/infiniband/hw/hns/hns_roce_mr.c @@ -633,30 +633,26 @@ int hns_roce_dealloc_mw(struct ib_mw *ibmw) } static int mtr_map_region(struct hns_roce_dev *hr_dev, struct hns_roce_mtr *mtr, - dma_addr_t *pages, struct hns_roce_buf_region *region) + struct hns_roce_buf_region *region, dma_addr_t *pages, + int max_count) { + int count, npage; + int offset, end; __le64 *mtts; - int offset; - int count; - int npage; u64 addr; - int end; int i; - /* if hopnum is 0, buffer cannot store BAs, so skip write mtt */ - if (!region->hopnum) - return 0; - offset = region->offset; end = offset + region->count; npage = 0; - while (offset < end) { + while (offset < end && npage < max_count) { + count = 0; mtts = hns_roce_hem_list_find_mtt(hr_dev, &mtr->hem_list, offset, &count, NULL); if (!mtts) return -ENOBUFS; - for (i = 0; i < count; i++) { + for (i = 0; i < count && npage < max_count; i++) { if (hr_dev->hw_rev == HNS_ROCE_HW_VER1) addr = to_hr_hw_page_addr(pages[npage]); else @@ -668,7 +664,7 @@ static int mtr_map_region(struct hns_roce_dev *hr_dev, struct hns_roce_mtr *mtr, offset += count; } - return 0; + return npage; } static inline bool mtr_has_mtt(struct hns_roce_buf_attr *attr) @@ -835,8 +831,8 @@ int hns_roce_mtr_map(struct hns_roce_dev *hr_dev, struct hns_roce_mtr *mtr, { struct ib_device *ibdev = &hr_dev->ib_dev; struct hns_roce_buf_region *r; - unsigned int i; - int err; + unsigned int i, mapped_cnt; + int ret = 0; /* * Only use the first page address as root ba when hopnum is 0, this @@ -847,26 +843,42 @@ int hns_roce_mtr_map(struct hns_roce_dev *hr_dev, struct hns_roce_mtr *mtr, return 0; } - for (i = 0; i < mtr->hem_cfg.region_count; i++) { + for (i = 0, mapped_cnt = 0; i < mtr->hem_cfg.region_count && + mapped_cnt < page_cnt; i++) { r = &mtr->hem_cfg.region[i]; + /* if hopnum is 0, no need to map pages in this region */ + if (!r->hopnum) { + mapped_cnt += r->count; + continue; + } + if (r->offset + r->count > page_cnt) { - err = -EINVAL; + ret = -EINVAL; ibdev_err(ibdev, "failed to check mtr%u end %u + %u, max %u.\n", i, r->offset, r->count, page_cnt); - return err; + return ret; } - err = mtr_map_region(hr_dev, mtr, &pages[r->offset], r); - if (err) { + ret = mtr_map_region(hr_dev, mtr, r, &pages[r->offset], + page_cnt - mapped_cnt); + if (ret < 0) { ibdev_err(ibdev, "failed to map mtr%u offset %u, ret = %d.\n", - i, r->offset, err); - return err; + i, r->offset, ret); + return ret; } + mapped_cnt += ret; + ret = 0; } - return 0; + if (mapped_cnt < page_cnt) { + ret = -ENOBUFS; + ibdev_err(ibdev, "failed to map mtr pages count: %u < %u.\n", + mapped_cnt, page_cnt); + } + + return ret; } int hns_roce_mtr_find(struct hns_roce_dev *hr_dev, struct hns_roce_mtr *mtr, diff --git a/drivers/infiniband/hw/hns/hns_roce_qp.c b/drivers/infiniband/hw/hns/hns_roce_qp.c index 1a6de9a9e57c..0cd2f778cdff 100644 --- a/drivers/infiniband/hw/hns/hns_roce_qp.c +++ b/drivers/infiniband/hw/hns/hns_roce_qp.c @@ -1287,19 +1287,19 @@ void hns_roce_lock_cqs(struct hns_roce_cq *send_cq, struct hns_roce_cq *recv_cq) __acquire(&send_cq->lock); __acquire(&recv_cq->lock); } else if (unlikely(send_cq != NULL && recv_cq == NULL)) { - spin_lock_irq(&send_cq->lock); + spin_lock(&send_cq->lock); __acquire(&recv_cq->lock); } else if (unlikely(send_cq == NULL && recv_cq != NULL)) { - spin_lock_irq(&recv_cq->lock); + spin_lock(&recv_cq->lock); __acquire(&send_cq->lock); } else if (send_cq == recv_cq) { - spin_lock_irq(&send_cq->lock); + spin_lock(&send_cq->lock); __acquire(&recv_cq->lock); } else if (send_cq->cqn < recv_cq->cqn) { - spin_lock_irq(&send_cq->lock); + spin_lock(&send_cq->lock); spin_lock_nested(&recv_cq->lock, SINGLE_DEPTH_NESTING); } else { - spin_lock_irq(&recv_cq->lock); + spin_lock(&recv_cq->lock); spin_lock_nested(&send_cq->lock, SINGLE_DEPTH_NESTING); } } @@ -1319,13 +1319,13 @@ void hns_roce_unlock_cqs(struct hns_roce_cq *send_cq, spin_unlock(&recv_cq->lock); } else if (send_cq == recv_cq) { __release(&recv_cq->lock); - spin_unlock_irq(&send_cq->lock); + spin_unlock(&send_cq->lock); } else if (send_cq->cqn < recv_cq->cqn) { spin_unlock(&recv_cq->lock); - spin_unlock_irq(&send_cq->lock); + spin_unlock(&send_cq->lock); } else { spin_unlock(&send_cq->lock); - spin_unlock_irq(&recv_cq->lock); + spin_unlock(&recv_cq->lock); } } diff --git a/drivers/infiniband/sw/rxe/rxe_comp.c b/drivers/infiniband/sw/rxe/rxe_comp.c index 0a1e6393250b..a54d80004342 100644 --- a/drivers/infiniband/sw/rxe/rxe_comp.c +++ b/drivers/infiniband/sw/rxe/rxe_comp.c @@ -123,12 +123,12 @@ void rxe_comp_queue_pkt(struct rxe_qp *qp, struct sk_buff *skb) { int must_sched; - skb_queue_tail(&qp->resp_pkts, skb); - - must_sched = skb_queue_len(&qp->resp_pkts) > 1; + must_sched = skb_queue_len(&qp->resp_pkts) > 0; if (must_sched != 0) rxe_counter_inc(SKB_TO_PKT(skb)->rxe, RXE_CNT_COMPLETER_SCHED); + skb_queue_tail(&qp->resp_pkts, skb); + rxe_run_task(&qp->comp.task, must_sched); } diff --git a/drivers/input/keyboard/adp5589-keys.c b/drivers/input/keyboard/adp5589-keys.c index eb0e9cd66bcb..15a00aad7c7f 100644 --- a/drivers/input/keyboard/adp5589-keys.c +++ b/drivers/input/keyboard/adp5589-keys.c @@ -390,10 +390,17 @@ static int adp5589_gpio_get_value(struct gpio_chip *chip, unsigned off) struct adp5589_kpad *kpad = gpiochip_get_data(chip); unsigned int bank = kpad->var->bank(kpad->gpiomap[off]); unsigned int bit = kpad->var->bit(kpad->gpiomap[off]); + int val; - return !!(adp5589_read(kpad->client, - kpad->var->reg(ADP5589_GPI_STATUS_A) + bank) & - bit); + mutex_lock(&kpad->gpio_lock); + if (kpad->dir[bank] & bit) + val = kpad->dat_out[bank]; + else + val = adp5589_read(kpad->client, + kpad->var->reg(ADP5589_GPI_STATUS_A) + bank); + mutex_unlock(&kpad->gpio_lock); + + return !!(val & bit); } static void adp5589_gpio_set_value(struct gpio_chip *chip, diff --git a/drivers/input/mouse/synaptics.c b/drivers/input/mouse/synaptics.c index e2c130832c15..82504b0ce01b 100644 --- a/drivers/input/mouse/synaptics.c +++ b/drivers/input/mouse/synaptics.c @@ -187,6 +187,7 @@ static const char * const smbus_pnp_ids[] = { "LEN2054", /* E480 */ "LEN2055", /* E580 */ "LEN2068", /* T14 Gen 1 */ + "SYN3015", /* HP EliteBook 840 G2 */ "SYN3052", /* HP EliteBook 840 G4 */ "SYN3221", /* HP 15-ay000 */ "SYN323d", /* HP Spectre X360 13-w013dx */ diff --git a/drivers/input/rmi4/rmi_driver.c b/drivers/input/rmi4/rmi_driver.c index aa32371f04af..ef9ea295f9e0 100644 --- a/drivers/input/rmi4/rmi_driver.c +++ b/drivers/input/rmi4/rmi_driver.c @@ -978,12 +978,12 @@ static int rmi_driver_remove(struct device *dev) rmi_disable_irq(rmi_dev, false); - irq_domain_remove(data->irqdomain); - data->irqdomain = NULL; - rmi_f34_remove_sysfs(rmi_dev); rmi_free_function_list(rmi_dev); + irq_domain_remove(data->irqdomain); + data->irqdomain = NULL; + return 0; } diff --git a/drivers/input/serio/i8042-acpipnpio.h b/drivers/input/serio/i8042-acpipnpio.h index 91edfb88a218..9dc8ed9bc5c0 100644 --- a/drivers/input/serio/i8042-acpipnpio.h +++ b/drivers/input/serio/i8042-acpipnpio.h @@ -617,6 +617,15 @@ static const struct dmi_system_id i8042_dmi_quirk_table[] __initconst = { }, .driver_data = (void *)(SERIO_QUIRK_NOMUX) }, + { + /* Fujitsu Lifebook E756 */ + /* https://bugzilla.suse.com/show_bug.cgi?id=1229056 */ + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"), + DMI_MATCH(DMI_PRODUCT_NAME, "LIFEBOOK E756"), + }, + .driver_data = (void *)(SERIO_QUIRK_NOMUX) + }, { /* Fujitsu Lifebook E5411 */ .matches = { @@ -1109,6 +1118,43 @@ static const struct dmi_system_id i8042_dmi_quirk_table[] __initconst = { }, .driver_data = (void *)(SERIO_QUIRK_NOLOOP) }, + /* + * Some TongFang barebones have touchpad and/or keyboard issues after + * suspend fixable with nomux + reset + noloop + nopnp. Luckily, none of + * them have an external PS/2 port so this can safely be set for all of + * them. + * TongFang barebones come with board_vendor and/or system_vendor set to + * a different value for each individual reseller. The only somewhat + * universal way to identify them is by board_name. + */ + { + .matches = { + DMI_MATCH(DMI_BOARD_NAME, "GM6XGxX"), + }, + .driver_data = (void *)(SERIO_QUIRK_NOMUX | SERIO_QUIRK_RESET_ALWAYS | + SERIO_QUIRK_NOLOOP | SERIO_QUIRK_NOPNP) + }, + { + .matches = { + DMI_MATCH(DMI_BOARD_NAME, "GMxXGxx"), + }, + .driver_data = (void *)(SERIO_QUIRK_NOMUX | SERIO_QUIRK_RESET_ALWAYS | + SERIO_QUIRK_NOLOOP | SERIO_QUIRK_NOPNP) + }, + { + .matches = { + DMI_MATCH(DMI_BOARD_NAME, "GMxXGxX"), + }, + .driver_data = (void *)(SERIO_QUIRK_NOMUX | SERIO_QUIRK_RESET_ALWAYS | + SERIO_QUIRK_NOLOOP | SERIO_QUIRK_NOPNP) + }, + { + .matches = { + DMI_MATCH(DMI_BOARD_NAME, "GMxHGxx"), + }, + .driver_data = (void *)(SERIO_QUIRK_NOMUX | SERIO_QUIRK_RESET_ALWAYS | + SERIO_QUIRK_NOLOOP | SERIO_QUIRK_NOPNP) + }, /* * A lot of modern Clevo barebones have touchpad and/or keyboard issues * after suspend fixable with nomux + reset + noloop + nopnp. Luckily, diff --git a/drivers/input/touchscreen/ads7846.c b/drivers/input/touchscreen/ads7846.c index 1753288cedde..08a1eac2dfa2 100644 --- a/drivers/input/touchscreen/ads7846.c +++ b/drivers/input/touchscreen/ads7846.c @@ -819,7 +819,7 @@ static void ads7846_read_state(struct ads7846 *ts) m = &ts->msg[msg_idx]; error = spi_sync(ts->spi, m); if (error) { - dev_err(&ts->spi->dev, "spi_sync --> %d\n", error); + dev_err_ratelimited(&ts->spi->dev, "spi_sync --> %d\n", error); packet->ignore = true; return; } diff --git a/drivers/input/touchscreen/goodix.c b/drivers/input/touchscreen/goodix.c index 53792a1b6ac3..440091064803 100644 --- a/drivers/input/touchscreen/goodix.c +++ b/drivers/input/touchscreen/goodix.c @@ -23,6 +23,7 @@ #include #include #include +#include #include #include #include @@ -718,21 +719,6 @@ static int goodix_reset(struct goodix_ts_data *ts) } #ifdef ACPI_GPIO_SUPPORT -#include -#include - -static const struct x86_cpu_id baytrail_cpu_ids[] = { - { X86_VENDOR_INTEL, 6, INTEL_FAM6_ATOM_SILVERMONT, X86_FEATURE_ANY, }, - {} -}; - -static inline bool is_byt(void) -{ - const struct x86_cpu_id *id = x86_match_cpu(baytrail_cpu_ids); - - return !!id; -} - static const struct acpi_gpio_params first_gpio = { 0, 0, false }; static const struct acpi_gpio_params second_gpio = { 1, 0, false }; @@ -816,7 +802,7 @@ static int goodix_add_acpi_gpio_mappings(struct goodix_ts_data *ts) dev_info(dev, "Using ACPI INTI and INTO methods for IRQ pin access\n"); ts->irq_pin_access_method = IRQ_PIN_ACCESS_ACPI_METHOD; gpio_mapping = acpi_goodix_reset_only_gpios; - } else if (is_byt() && ts->gpio_count == 2 && ts->gpio_int_idx == -1) { + } else if (soc_intel_is_byt() && ts->gpio_count == 2 && ts->gpio_int_idx == -1) { dev_info(dev, "No ACPI GpioInt resource, assuming that the GPIO order is reset, int\n"); ts->irq_pin_access_method = IRQ_PIN_ACCESS_ACPI_GPIO; gpio_mapping = acpi_goodix_int_last_gpios; diff --git a/drivers/interconnect/qcom/sm8250.c b/drivers/interconnect/qcom/sm8250.c index 40820043c8d3..cc558fec74e3 100644 --- a/drivers/interconnect/qcom/sm8250.c +++ b/drivers/interconnect/qcom/sm8250.c @@ -643,6 +643,7 @@ static struct platform_driver qnoc_driver = { .driver = { .name = "qnoc-sm8250", .of_match_table = qnoc_of_match, + .sync_state = icc_sync_state, }, }; module_platform_driver(qnoc_driver); diff --git a/drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c b/drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c index 7470e7211b01..27abc4148803 100644 --- a/drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c +++ b/drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c @@ -223,6 +223,13 @@ static int qcom_smmu_cfg_probe(struct arm_smmu_device *smmu) u32 smr; int i; + /* + * MSM8998 LPASS SMMU reports 13 context banks, but accessing + * the last context bank crashes the system. + */ + if (of_device_is_compatible(smmu->dev->of_node, "qcom,msm8998-smmu-v2") && smmu->num_context_banks == 13) + smmu->num_context_banks = 12; + /* * Some platforms support more than the Arm SMMU architected maximum of * 128 stream matching groups. For unknown reasons, the additional diff --git a/drivers/iommu/intel/dmar.c b/drivers/iommu/intel/dmar.c index 72b380e17a1b..68153e6329b5 100644 --- a/drivers/iommu/intel/dmar.c +++ b/drivers/iommu/intel/dmar.c @@ -1193,9 +1193,7 @@ static void free_iommu(struct intel_iommu *iommu) */ static inline void reclaim_free_desc(struct q_inval *qi) { - while (qi->desc_status[qi->free_tail] == QI_DONE || - qi->desc_status[qi->free_tail] == QI_ABORT) { - qi->desc_status[qi->free_tail] = QI_FREE; + while (qi->desc_status[qi->free_tail] == QI_FREE && qi->free_tail != qi->free_head) { qi->free_tail = (qi->free_tail + 1) % QI_LENGTH; qi->free_cnt++; } @@ -1350,8 +1348,16 @@ int qi_submit_sync(struct intel_iommu *iommu, struct qi_desc *desc, raw_spin_lock(&qi->q_lock); } - for (i = 0; i < count; i++) - qi->desc_status[(index + i) % QI_LENGTH] = QI_DONE; + /* + * The reclaim code can free descriptors from multiple submissions + * starting from the tail of the queue. When count == 0, the + * status of the standalone wait descriptor at the tail of the queue + * must be set to QI_FREE to allow the reclaim code to proceed. + * It is also possible that descriptors from one of the previous + * submissions has to be reclaimed by a subsequent submission. + */ + for (i = 0; i <= count; i++) + qi->desc_status[(index + i) % QI_LENGTH] = QI_FREE; reclaim_free_desc(qi); raw_spin_unlock_irqrestore(&qi->q_lock, flags); diff --git a/drivers/iommu/intel/iommu.c b/drivers/iommu/intel/iommu.c index 6be92e0afdb0..c694ecbd304e 100644 --- a/drivers/iommu/intel/iommu.c +++ b/drivers/iommu/intel/iommu.c @@ -1847,10 +1847,10 @@ static int iommu_init_domains(struct intel_iommu *iommu) * entry for first-level or pass-through translation modes should * be programmed with a domain id different from those used for * second-level or nested translation. We reserve a domain id for - * this purpose. + * this purpose. This domain id is also used for identity domain + * in legacy mode. */ - if (sm_supported(iommu)) - set_bit(FLPT_DEFAULT_DID, iommu->domain_ids); + set_bit(FLPT_DEFAULT_DID, iommu->domain_ids); return 0; } diff --git a/drivers/irqchip/irq-gic-v3-its.c b/drivers/irqchip/irq-gic-v3-its.c index 6788e38f8e6a..3eb4bd4472bc 100644 --- a/drivers/irqchip/irq-gic-v3-its.c +++ b/drivers/irqchip/irq-gic-v3-its.c @@ -779,6 +779,7 @@ static struct its_vpe *its_build_vmapp_cmd(struct its_node *its, struct its_cmd_block *cmd, struct its_cmd_desc *desc) { + struct its_vpe *vpe = valid_vpe(its, desc->its_vmapp_cmd.vpe); unsigned long vpt_addr, vconf_addr; u64 target; bool alloc; @@ -788,9 +789,14 @@ static struct its_vpe *its_build_vmapp_cmd(struct its_node *its, its_encode_valid(cmd, desc->its_vmapp_cmd.valid); if (!desc->its_vmapp_cmd.valid) { + alloc = !atomic_dec_return(&desc->its_vmapp_cmd.vpe->vmapp_count); if (is_v4_1(its)) { - alloc = !atomic_dec_return(&desc->its_vmapp_cmd.vpe->vmapp_count); its_encode_alloc(cmd, alloc); + /* + * Unmapping a VPE is self-synchronizing on GICv4.1, + * no need to issue a VSYNC. + */ + vpe = NULL; } goto out; @@ -803,13 +809,13 @@ static struct its_vpe *its_build_vmapp_cmd(struct its_node *its, its_encode_vpt_addr(cmd, vpt_addr); its_encode_vpt_size(cmd, LPI_NRBITS - 1); + alloc = !atomic_fetch_inc(&desc->its_vmapp_cmd.vpe->vmapp_count); + if (!is_v4_1(its)) goto out; vconf_addr = virt_to_phys(page_address(desc->its_vmapp_cmd.vpe->its_vm->vprop_page)); - alloc = !atomic_fetch_inc(&desc->its_vmapp_cmd.vpe->vmapp_count); - its_encode_alloc(cmd, alloc); /* We can only signal PTZ when alloc==1. Why do we have two bits? */ @@ -820,7 +826,7 @@ static struct its_vpe *its_build_vmapp_cmd(struct its_node *its, out: its_fixup_cmd(cmd); - return valid_vpe(its, desc->its_vmapp_cmd.vpe); + return vpe; } static struct its_vpe *its_build_vmapti_cmd(struct its_node *its, @@ -3796,6 +3802,13 @@ static int its_vpe_set_affinity(struct irq_data *d, unsigned long flags; int from, cpu; + /* + * Check if we're racing against a VPE being destroyed, for + * which we don't want to allow a VMOVP. + */ + if (!atomic_read(&vpe->vmapp_count)) + return -EINVAL; + /* * Changing affinity is mega expensive, so let's be as lazy as * we can and only do it if we really have to. Also, if mapped @@ -4432,9 +4445,8 @@ static int its_vpe_init(struct its_vpe *vpe) raw_spin_lock_init(&vpe->vpe_lock); vpe->vpe_id = vpe_id; vpe->vpt_page = vpt_page; - if (gic_rdists->has_rvpeid) - atomic_set(&vpe->vmapp_count, 0); - else + atomic_set(&vpe->vmapp_count, 0); + if (!gic_rdists->has_rvpeid) vpe->vpe_proxy_event = -1; return 0; diff --git a/drivers/mailbox/bcm2835-mailbox.c b/drivers/mailbox/bcm2835-mailbox.c index 39761d190545..5c33c01a9d26 100644 --- a/drivers/mailbox/bcm2835-mailbox.c +++ b/drivers/mailbox/bcm2835-mailbox.c @@ -146,7 +146,8 @@ static int bcm2835_mbox_probe(struct platform_device *pdev) spin_lock_init(&mbox->lock); ret = devm_request_irq(dev, irq_of_parse_and_map(dev->of_node, 0), - bcm2835_mbox_irq, 0, dev_name(dev), mbox); + bcm2835_mbox_irq, IRQF_NO_SUSPEND, dev_name(dev), + mbox); if (ret) { dev_err(dev, "Failed to register a mailbox IRQ handler: %d\n", ret); diff --git a/drivers/mailbox/rockchip-mailbox.c b/drivers/mailbox/rockchip-mailbox.c index 979acc810f30..ca50f7f176f6 100644 --- a/drivers/mailbox/rockchip-mailbox.c +++ b/drivers/mailbox/rockchip-mailbox.c @@ -159,7 +159,7 @@ static const struct of_device_id rockchip_mbox_of_match[] = { { .compatible = "rockchip,rk3368-mailbox", .data = &rk3368_drv_data}, { }, }; -MODULE_DEVICE_TABLE(of, rockchp_mbox_of_match); +MODULE_DEVICE_TABLE(of, rockchip_mbox_of_match); static int rockchip_mbox_probe(struct platform_device *pdev) { diff --git a/drivers/md/dm-rq.c b/drivers/md/dm-rq.c index 4833f4b20b2c..6f9e76aad6a1 100644 --- a/drivers/md/dm-rq.c +++ b/drivers/md/dm-rq.c @@ -496,8 +496,10 @@ static blk_status_t dm_mq_queue_rq(struct blk_mq_hw_ctx *hctx, map = dm_get_live_table(md, &srcu_idx); if (unlikely(!map)) { + DMERR_LIMIT("%s: mapping table unavailable, erroring io", + dm_device_name(md)); dm_put_live_table(md, srcu_idx); - return BLK_STS_RESOURCE; + return BLK_STS_IOERR; } ti = dm_table_find_target(map, 0); dm_put_live_table(md, srcu_idx); diff --git a/drivers/md/dm.c b/drivers/md/dm.c index 8aa162eb4c06..cdef45991b2a 100644 --- a/drivers/md/dm.c +++ b/drivers/md/dm.c @@ -1697,10 +1697,15 @@ static blk_qc_t dm_submit_bio(struct bio *bio) struct dm_table *map; map = dm_get_live_table(md, &srcu_idx); + if (unlikely(!map)) { + DMERR_LIMIT("%s: mapping table unavailable, erroring io", + dm_device_name(md)); + bio_io_error(bio); + goto out; + } - /* If suspended, or map not yet available, queue this IO for later */ - if (unlikely(test_bit(DMF_BLOCK_IO_FOR_SUSPEND, &md->flags)) || - unlikely(!map)) { + /* If suspended, queue this IO for later */ + if (unlikely(test_bit(DMF_BLOCK_IO_FOR_SUSPEND, &md->flags))) { if (bio->bi_opf & REQ_NOWAIT) bio_wouldblock_error(bio); else if (bio->bi_opf & REQ_RAHEAD) diff --git a/drivers/media/common/videobuf2/videobuf2-core.c b/drivers/media/common/videobuf2/videobuf2-core.c index 3bafde87a125..78ad2b278da4 100644 --- a/drivers/media/common/videobuf2/videobuf2-core.c +++ b/drivers/media/common/videobuf2/videobuf2-core.c @@ -301,6 +301,10 @@ static void __vb2_plane_dmabuf_put(struct vb2_buffer *vb, struct vb2_plane *p) p->mem_priv = NULL; p->dbuf = NULL; p->dbuf_mapped = 0; + p->bytesused = 0; + p->length = 0; + p->m.fd = 0; + p->data_offset = 0; } /* @@ -1278,10 +1282,6 @@ static int __prepare_dmabuf(struct vb2_buffer *vb) /* Release previously acquired memory if present */ __vb2_plane_dmabuf_put(vb, &vb->planes[plane]); - vb->planes[plane].bytesused = 0; - vb->planes[plane].length = 0; - vb->planes[plane].m.fd = 0; - vb->planes[plane].data_offset = 0; /* Acquire each plane's memory */ mem_priv = call_ptr_memop(vb, attach_dmabuf, diff --git a/drivers/media/dvb-frontends/rtl2830.c b/drivers/media/dvb-frontends/rtl2830.c index e6b8367c8cce..84c00c6894d3 100644 --- a/drivers/media/dvb-frontends/rtl2830.c +++ b/drivers/media/dvb-frontends/rtl2830.c @@ -609,7 +609,7 @@ static int rtl2830_pid_filter(struct dvb_frontend *fe, u8 index, u16 pid, int on index, pid, onoff); /* skip invalid PIDs (0x2000) */ - if (pid > 0x1fff || index > 32) + if (pid > 0x1fff || index >= 32) return 0; if (onoff) diff --git a/drivers/media/dvb-frontends/rtl2832.c b/drivers/media/dvb-frontends/rtl2832.c index e5bffaaeed38..1c3e572cad3f 100644 --- a/drivers/media/dvb-frontends/rtl2832.c +++ b/drivers/media/dvb-frontends/rtl2832.c @@ -982,7 +982,7 @@ static int rtl2832_pid_filter(struct dvb_frontend *fe, u8 index, u16 pid, index, pid, onoff, dev->slave_ts); /* skip invalid PIDs (0x2000) */ - if (pid > 0x1fff || index > 32) + if (pid > 0x1fff || index >= 32) return 0; if (onoff) diff --git a/drivers/media/platform/qcom/venus/core.c b/drivers/media/platform/qcom/venus/core.c index 5f7ac2807e5f..c757cab6b335 100644 --- a/drivers/media/platform/qcom/venus/core.c +++ b/drivers/media/platform/qcom/venus/core.c @@ -366,6 +366,7 @@ static int venus_remove(struct platform_device *pdev) struct device *dev = core->dev; int ret; + cancel_delayed_work_sync(&core->work); ret = pm_runtime_get_sync(dev); WARN_ON(ret < 0); diff --git a/drivers/media/platform/sunxi/sun4i-csi/sun4i_csi.c b/drivers/media/platform/sunxi/sun4i-csi/sun4i_csi.c index 64f25921463e..1efaa1d0948b 100644 --- a/drivers/media/platform/sunxi/sun4i-csi/sun4i_csi.c +++ b/drivers/media/platform/sunxi/sun4i-csi/sun4i_csi.c @@ -40,6 +40,10 @@ static const struct media_entity_operations sun4i_csi_video_entity_ops = { .link_validate = v4l2_subdev_link_validate, }; +static const struct media_entity_operations sun4i_csi_subdev_entity_ops = { + .link_validate = v4l2_subdev_link_validate, +}; + static int sun4i_csi_notify_bound(struct v4l2_async_notifier *notifier, struct v4l2_subdev *subdev, struct v4l2_async_subdev *asd) @@ -245,6 +249,7 @@ static int sun4i_csi_probe(struct platform_device *pdev) v4l2_subdev_init(subdev, &sun4i_csi_subdev_ops); subdev->flags = V4L2_SUBDEV_FL_HAS_DEVNODE | V4L2_SUBDEV_FL_HAS_EVENTS; subdev->entity.function = MEDIA_ENT_F_VID_IF_BRIDGE; + subdev->entity.ops = &sun4i_csi_subdev_entity_ops; subdev->owner = THIS_MODULE; snprintf(subdev->name, sizeof(subdev->name), "sun4i-csi-0"); v4l2_set_subdevdata(subdev, csi); diff --git a/drivers/media/usb/usbtv/usbtv-video.c b/drivers/media/usb/usbtv/usbtv-video.c index 3b4a2e769230..f2aaec0f77c8 100644 --- a/drivers/media/usb/usbtv/usbtv-video.c +++ b/drivers/media/usb/usbtv/usbtv-video.c @@ -959,15 +959,8 @@ int usbtv_video_init(struct usbtv *usbtv) void usbtv_video_free(struct usbtv *usbtv) { - mutex_lock(&usbtv->vb2q_lock); - mutex_lock(&usbtv->v4l2_lock); - - usbtv_stop(usbtv); vb2_video_unregister_device(&usbtv->vdev); v4l2_device_disconnect(&usbtv->v4l2_dev); - mutex_unlock(&usbtv->v4l2_lock); - mutex_unlock(&usbtv->vb2q_lock); - v4l2_device_put(&usbtv->v4l2_dev); } diff --git a/drivers/media/usb/uvc/uvc_driver.c b/drivers/media/usb/uvc/uvc_driver.c index cfbc7595cd0b..519fd648f26c 100644 --- a/drivers/media/usb/uvc/uvc_driver.c +++ b/drivers/media/usb/uvc/uvc_driver.c @@ -661,7 +661,7 @@ static int uvc_parse_format(struct uvc_device *dev, /* Parse the frame descriptors. Only uncompressed, MJPEG and frame * based formats have frame descriptors. */ - while (buflen > 2 && buffer[1] == USB_DT_CS_INTERFACE && + while (ftype && buflen > 2 && buffer[1] == USB_DT_CS_INTERFACE && buffer[2] == ftype) { frame = &format->frame[format->nframes]; if (ftype != UVC_VS_FRAME_FRAME_BASED) diff --git a/drivers/mtd/devices/powernv_flash.c b/drivers/mtd/devices/powernv_flash.c index 0b757d9ba2f6..0ab64a1cec09 100644 --- a/drivers/mtd/devices/powernv_flash.c +++ b/drivers/mtd/devices/powernv_flash.c @@ -204,6 +204,9 @@ static int powernv_flash_set_driver_info(struct device *dev, * get them */ mtd->name = devm_kasprintf(dev, GFP_KERNEL, "%pOFP", dev->of_node); + if (!mtd->name) + return -ENOMEM; + mtd->type = MTD_NORFLASH; mtd->flags = MTD_WRITEABLE; mtd->size = size; diff --git a/drivers/mtd/devices/slram.c b/drivers/mtd/devices/slram.c index 28131a127d06..8297b366a066 100644 --- a/drivers/mtd/devices/slram.c +++ b/drivers/mtd/devices/slram.c @@ -296,10 +296,12 @@ static int __init init_slram(void) T("slram: devname = %s\n", devname); if ((!map) || (!(devstart = strsep(&map, ",")))) { E("slram: No devicestart specified.\n"); + break; } T("slram: devstart = %s\n", devstart); if ((!map) || (!(devlength = strsep(&map, ",")))) { E("slram: No devicelength / -end specified.\n"); + break; } T("slram: devlength = %s\n", devlength); if (parse_cmdline(devname, devstart, devlength) != 0) { diff --git a/drivers/net/bareudp.c b/drivers/net/bareudp.c index 53ef48588e59..e01dd36af62c 100644 --- a/drivers/net/bareudp.c +++ b/drivers/net/bareudp.c @@ -139,6 +139,7 @@ static int bareudp_udp_encap_recv(struct sock *sk, struct sk_buff *skb) skb->dev = bareudp->dev; oiph = skb_network_header(skb); skb_reset_network_header(skb); + skb_reset_mac_header(skb); if (!ipv6_mod_enabled() || family == AF_INET) err = IP_ECN_decapsulate(oiph, skb); @@ -294,6 +295,9 @@ static int bareudp_xmit_skb(struct sk_buff *skb, struct net_device *dev, __be32 saddr; int err; + if (!skb_vlan_inet_prepare(skb, skb->protocol != htons(ETH_P_TEB))) + return -EINVAL; + if (!sock) return -ESHUTDOWN; @@ -357,6 +361,9 @@ static int bareudp6_xmit_skb(struct sk_buff *skb, struct net_device *dev, __be16 sport; int err; + if (!skb_vlan_inet_prepare(skb, skb->protocol != htons(ETH_P_TEB))) + return -EINVAL; + if (!sock) return -ESHUTDOWN; diff --git a/drivers/net/can/m_can/m_can.c b/drivers/net/can/m_can/m_can.c index 19a19a7b7deb..6181ac277b62 100644 --- a/drivers/net/can/m_can/m_can.c +++ b/drivers/net/can/m_can/m_can.c @@ -21,6 +21,7 @@ #include #include #include +#include #include "m_can.h" @@ -1426,7 +1427,6 @@ static int m_can_close(struct net_device *dev) napi_disable(&cdev->napi); m_can_stop(dev); - m_can_clk_stop(cdev); free_irq(dev->irq, dev); if (cdev->is_peripheral) { @@ -1438,6 +1438,9 @@ static int m_can_close(struct net_device *dev) close_candev(dev); can_led_event(dev, CAN_LED_EVENT_STOP); + m_can_clk_stop(cdev); + phy_power_off(cdev->transceiver); + return 0; } @@ -1624,10 +1627,14 @@ static int m_can_open(struct net_device *dev) struct m_can_classdev *cdev = netdev_priv(dev); int err; - err = m_can_clk_start(cdev); + err = phy_power_on(cdev->transceiver); if (err) return err; + err = m_can_clk_start(cdev); + if (err) + goto out_phy_power_off; + /* open the can device */ err = open_candev(dev); if (err) { @@ -1679,6 +1686,8 @@ static int m_can_open(struct net_device *dev) close_candev(dev); exit_disable_clks: m_can_clk_stop(cdev); +out_phy_power_off: + phy_power_off(cdev->transceiver); return err; } diff --git a/drivers/net/can/m_can/m_can.h b/drivers/net/can/m_can/m_can.h index b2699a7c9997..8cad1235afa0 100644 --- a/drivers/net/can/m_can/m_can.h +++ b/drivers/net/can/m_can/m_can.h @@ -27,6 +27,7 @@ #include #include #include +#include /* m_can lec values */ enum m_can_lec_type { @@ -80,6 +81,7 @@ struct m_can_classdev { struct workqueue_struct *tx_wq; struct work_struct tx_work; struct sk_buff *tx_skb; + struct phy *transceiver; struct can_bittiming_const *bit_timing; struct can_bittiming_const *data_timing; diff --git a/drivers/net/can/m_can/m_can_platform.c b/drivers/net/can/m_can/m_can_platform.c index 161cb9be018c..dbebb9bba545 100644 --- a/drivers/net/can/m_can/m_can_platform.c +++ b/drivers/net/can/m_can/m_can_platform.c @@ -6,6 +6,7 @@ // Copyright (C) 2018-19 Texas Instruments Incorporated - http://www.ti.com/ #include +#include #include "m_can.h" @@ -60,6 +61,7 @@ static int m_can_plat_probe(struct platform_device *pdev) struct resource *res; void __iomem *addr; void __iomem *mram_addr; + struct phy *transceiver; int irq, ret = 0; mcan_class = m_can_class_allocate_dev(&pdev->dev); @@ -99,6 +101,16 @@ static int m_can_plat_probe(struct platform_device *pdev) goto probe_fail; } + transceiver = devm_phy_optional_get(&pdev->dev, NULL); + if (IS_ERR(transceiver)) { + ret = PTR_ERR(transceiver); + dev_err_probe(&pdev->dev, ret, "failed to get phy\n"); + goto probe_fail; + } + + if (transceiver) + mcan_class->can.bitrate_max = transceiver->attrs.max_link_rate; + priv->base = addr; priv->mram_base = mram_addr; @@ -106,6 +118,7 @@ static int m_can_plat_probe(struct platform_device *pdev) mcan_class->pm_clock_support = 1; mcan_class->can.clock.freq = clk_get_rate(mcan_class->cclk); mcan_class->dev = &pdev->dev; + mcan_class->transceiver = transceiver; mcan_class->ops = &m_can_plat_ops; diff --git a/drivers/net/dsa/b53/b53_common.c b/drivers/net/dsa/b53/b53_common.c index c43a99ad75d3..53a20c42ee3c 100644 --- a/drivers/net/dsa/b53/b53_common.c +++ b/drivers/net/dsa/b53/b53_common.c @@ -27,6 +27,7 @@ #include #include #include +#include #include #include "b53_regs.h" @@ -224,6 +225,9 @@ static const struct b53_mib_desc b53_mibs_58xx[] = { #define B53_MIBS_58XX_SIZE ARRAY_SIZE(b53_mibs_58xx) +#define B53_MAX_MTU_25 (1536 - ETH_HLEN - VLAN_HLEN - ETH_FCS_LEN) +#define B53_MAX_MTU (9720 - ETH_HLEN - VLAN_HLEN - ETH_FCS_LEN) + static int b53_do_vlan_op(struct b53_device *dev, u8 op) { unsigned int i; @@ -2180,20 +2184,25 @@ static int b53_change_mtu(struct dsa_switch *ds, int port, int mtu) bool allow_10_100; if (is5325(dev) || is5365(dev)) - return -EOPNOTSUPP; + return 0; if (!dsa_is_cpu_port(ds, port)) return 0; - enable_jumbo = (mtu >= JMS_MIN_SIZE); - allow_10_100 = (dev->chip_id == BCM583XX_DEVICE_ID); + enable_jumbo = (mtu > ETH_DATA_LEN); + allow_10_100 = !is63xx(dev); return b53_set_jumbo(dev, enable_jumbo, allow_10_100); } static int b53_get_max_mtu(struct dsa_switch *ds, int port) { - return JMS_MAX_SIZE; + struct b53_device *dev = ds->priv; + + if (is5325(dev) || is5365(dev)) + return B53_MAX_MTU_25; + + return B53_MAX_MTU; } static const struct dsa_switch_ops b53_switch_ops = { diff --git a/drivers/net/dsa/lan9303-core.c b/drivers/net/dsa/lan9303-core.c index f5ab0bff4ac2..6598d019eb7b 100644 --- a/drivers/net/dsa/lan9303-core.c +++ b/drivers/net/dsa/lan9303-core.c @@ -6,6 +6,7 @@ #include #include #include +#include #include #include #include @@ -819,6 +820,8 @@ static void lan9303_handle_reset(struct lan9303 *chip) if (!chip->reset_gpio) return; + gpiod_set_value_cansleep(chip->reset_gpio, 1); + if (chip->reset_duration != 0) msleep(chip->reset_duration); @@ -844,8 +847,34 @@ static int lan9303_disable_processing(struct lan9303 *chip) static int lan9303_check_device(struct lan9303 *chip) { int ret; + int err; u32 reg; + /* In I2C-managed configurations this polling loop will clash with + * switch's reading of EEPROM right after reset and this behaviour is + * not configurable. While lan9303_read() already has quite long retry + * timeout, seems not all cases are being detected as arbitration error. + * + * According to datasheet, EEPROM loader has 30ms timeout (in case of + * missing EEPROM). + * + * Loading of the largest supported EEPROM is expected to take at least + * 5.9s. + */ + err = read_poll_timeout(lan9303_read, ret, + !ret && reg & LAN9303_HW_CFG_READY, + 20000, 6000000, false, + chip->regmap, LAN9303_HW_CFG, ®); + if (ret) { + dev_err(chip->dev, "failed to read HW_CFG reg: %pe\n", + ERR_PTR(ret)); + return ret; + } + if (err) { + dev_err(chip->dev, "HW_CFG not ready: 0x%08x\n", reg); + return err; + } + ret = lan9303_read(chip->regmap, LAN9303_CHIP_REV, ®); if (ret) { dev_err(chip->dev, "failed to read chip revision register: %d\n", diff --git a/drivers/net/ethernet/aeroflex/greth.c b/drivers/net/ethernet/aeroflex/greth.c index 0d56cb4f5dd9..c84b9acc319f 100644 --- a/drivers/net/ethernet/aeroflex/greth.c +++ b/drivers/net/ethernet/aeroflex/greth.c @@ -484,7 +484,7 @@ greth_start_xmit_gbit(struct sk_buff *skb, struct net_device *dev) if (unlikely(skb->len > MAX_FRAME_SIZE)) { dev->stats.tx_errors++; - goto out; + goto len_error; } /* Save skb pointer. */ @@ -575,6 +575,7 @@ greth_start_xmit_gbit(struct sk_buff *skb, struct net_device *dev) map_error: if (net_ratelimit()) dev_warn(greth->dev, "Could not create TX DMA mapping\n"); +len_error: dev_kfree_skb(skb); out: return err; diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_ethtool.c b/drivers/net/ethernet/aquantia/atlantic/aq_ethtool.c index 1d512e6a89f5..c6d9da0bb010 100644 --- a/drivers/net/ethernet/aquantia/atlantic/aq_ethtool.c +++ b/drivers/net/ethernet/aquantia/atlantic/aq_ethtool.c @@ -256,7 +256,7 @@ static void aq_ethtool_get_strings(struct net_device *ndev, const int rx_stat_cnt = ARRAY_SIZE(aq_ethtool_queue_rx_stat_names); const int tx_stat_cnt = ARRAY_SIZE(aq_ethtool_queue_tx_stat_names); char tc_string[8]; - int tc; + unsigned int tc; memset(tc_string, 0, sizeof(tc_string)); memcpy(p, aq_ethtool_stat_names, @@ -265,7 +265,7 @@ static void aq_ethtool_get_strings(struct net_device *ndev, for (tc = 0; tc < cfg->tcs; tc++) { if (cfg->is_qos) - snprintf(tc_string, 8, "TC%d ", tc); + snprintf(tc_string, 8, "TC%u ", tc); for (i = 0; i < cfg->vecs; i++) { for (si = 0; si < rx_stat_cnt; si++) { diff --git a/drivers/net/ethernet/broadcom/bcmsysport.c b/drivers/net/ethernet/broadcom/bcmsysport.c index 82d369d9f7a5..ae1cf2ead9a9 100644 --- a/drivers/net/ethernet/broadcom/bcmsysport.c +++ b/drivers/net/ethernet/broadcom/bcmsysport.c @@ -1343,6 +1343,7 @@ static netdev_tx_t bcm_sysport_xmit(struct sk_buff *skb, netif_err(priv, tx_err, dev, "DMA map failed at %p (len=%d)\n", skb->data, skb_len); ret = NETDEV_TX_OK; + dev_kfree_skb_any(skb); goto out; } diff --git a/drivers/net/ethernet/cadence/macb_main.c b/drivers/net/ethernet/cadence/macb_main.c index 70d57ef95fb1..c3a8f6fc05ae 100644 --- a/drivers/net/ethernet/cadence/macb_main.c +++ b/drivers/net/ethernet/cadence/macb_main.c @@ -742,9 +742,6 @@ static int macb_mdiobus_register(struct macb *bp) { struct device_node *child, *np = bp->pdev->dev.of_node; - if (of_phy_is_fixed_link(np)) - return mdiobus_register(bp->mii_bus); - /* Only create the PHY from the device tree if at least one PHY is * described. Otherwise scan the entire MDIO bus. We do this to support * old device tree that did not follow the best practices and did not @@ -765,8 +762,19 @@ static int macb_mdiobus_register(struct macb *bp) static int macb_mii_init(struct macb *bp) { + struct device_node *child, *np = bp->pdev->dev.of_node; int err = -ENXIO; + /* With fixed-link, we don't need to register the MDIO bus, + * except if we have a child named "mdio" in the device tree. + * In that case, some devices may be attached to the MACB's MDIO bus. + */ + child = of_get_child_by_name(np, "mdio"); + if (child) + of_node_put(child); + else if (of_phy_is_fixed_link(np)) + return macb_mii_probe(bp->dev); + /* Enable management port */ macb_writel(bp, NCR, MACB_BIT(MPE)); diff --git a/drivers/net/ethernet/cortina/gemini.c b/drivers/net/ethernet/cortina/gemini.c index fa46854fd697..04a034cd5183 100644 --- a/drivers/net/ethernet/cortina/gemini.c +++ b/drivers/net/ethernet/cortina/gemini.c @@ -80,8 +80,7 @@ MODULE_PARM_DESC(debug, "Debug level (0=none,...,16=all)"); #define GMAC0_IRQ4_8 (GMAC0_MIB_INT_BIT | GMAC0_RX_OVERRUN_INT_BIT) #define GMAC_OFFLOAD_FEATURES (NETIF_F_SG | NETIF_F_IP_CSUM | \ - NETIF_F_IPV6_CSUM | NETIF_F_RXCSUM | \ - NETIF_F_TSO | NETIF_F_TSO_ECN | NETIF_F_TSO6) + NETIF_F_IPV6_CSUM | NETIF_F_RXCSUM) /** * struct gmac_queue_page - page buffer per-page info @@ -1149,23 +1148,13 @@ static int gmac_map_tx_bufs(struct net_device *netdev, struct sk_buff *skb, struct gmac_txdesc *txd; skb_frag_t *skb_frag; dma_addr_t mapping; - unsigned short mtu; void *buffer; int ret; - mtu = ETH_HLEN; - mtu += netdev->mtu; - if (skb->protocol == htons(ETH_P_8021Q)) - mtu += VLAN_HLEN; - + /* TODO: implement proper TSO using MTU in word3 */ word1 = skb->len; word3 = SOF_BIT; - if (word1 > mtu) { - word1 |= TSS_MTU_ENABLE_BIT; - word3 |= mtu; - } - if (skb->len >= ETH_FRAME_LEN) { /* Hardware offloaded checksumming isn't working on frames * bigger than 1514 bytes. A hypothesis about this is that the diff --git a/drivers/net/ethernet/faraday/ftgmac100.c b/drivers/net/ethernet/faraday/ftgmac100.c index 969af4dd6405..bc9a7f2d2350 100644 --- a/drivers/net/ethernet/faraday/ftgmac100.c +++ b/drivers/net/ethernet/faraday/ftgmac100.c @@ -569,7 +569,7 @@ static bool ftgmac100_rx_packet(struct ftgmac100 *priv, int *processed) (*processed)++; return true; - drop: +drop: /* Clean rxdes0 (which resets own bit) */ rxdes->rxdes0 = cpu_to_le32(status & priv->rxdes0_edorr_mask); priv->rx_pointer = ftgmac100_next_rx_pointer(priv, pointer); @@ -653,6 +653,11 @@ static bool ftgmac100_tx_complete_packet(struct ftgmac100 *priv) ftgmac100_free_tx_packet(priv, pointer, skb, txdes, ctl_stat); txdes->txdes0 = cpu_to_le32(ctl_stat & priv->txdes0_edotr_mask); + /* Ensure the descriptor config is visible before setting the tx + * pointer. + */ + smp_wmb(); + priv->tx_clean_pointer = ftgmac100_next_tx_pointer(priv, pointer); return true; @@ -806,6 +811,11 @@ static netdev_tx_t ftgmac100_hard_start_xmit(struct sk_buff *skb, dma_wmb(); first->txdes0 = cpu_to_le32(f_ctl_stat); + /* Ensure the descriptor config is visible before setting the tx + * pointer. + */ + smp_wmb(); + /* Update next TX pointer */ priv->tx_pointer = pointer; @@ -826,7 +836,7 @@ static netdev_tx_t ftgmac100_hard_start_xmit(struct sk_buff *skb, return NETDEV_TX_OK; - dma_err: +dma_err: if (net_ratelimit()) netdev_err(netdev, "map tx fragment failed\n"); @@ -848,7 +858,7 @@ static netdev_tx_t ftgmac100_hard_start_xmit(struct sk_buff *skb, * last fragment, so we know ftgmac100_free_tx_packet() * hasn't freed the skb yet. */ - drop: +drop: /* Drop the packet */ dev_kfree_skb_any(skb); netdev->stats.tx_dropped++; @@ -1419,7 +1429,7 @@ static void ftgmac100_reset_task(struct work_struct *work) ftgmac100_init_all(priv, true); netdev_dbg(netdev, "Reset done !\n"); - bail: +bail: if (priv->mii_bus) mutex_unlock(&priv->mii_bus->mdio_lock); if (netdev->phydev) @@ -1490,15 +1500,15 @@ static int ftgmac100_open(struct net_device *netdev) return 0; - err_ncsi: +err_ncsi: napi_disable(&priv->napi); netif_stop_queue(netdev); - err_alloc: +err_alloc: ftgmac100_free_buffers(priv); free_irq(netdev->irq, netdev); - err_irq: +err_irq: netif_napi_del(&priv->napi); - err_hw: +err_hw: iowrite32(0, priv->base + FTGMAC100_OFFSET_IER); ftgmac100_free_rings(priv); return err; diff --git a/drivers/net/ethernet/faraday/ftgmac100.h b/drivers/net/ethernet/faraday/ftgmac100.h index 63b3e02fab16..4968f6f0bdbc 100644 --- a/drivers/net/ethernet/faraday/ftgmac100.h +++ b/drivers/net/ethernet/faraday/ftgmac100.h @@ -84,7 +84,7 @@ FTGMAC100_INT_RPKT_BUF) /* All the interrupts we care about */ -#define FTGMAC100_INT_ALL (FTGMAC100_INT_RPKT_BUF | \ +#define FTGMAC100_INT_ALL (FTGMAC100_INT_RXTX | \ FTGMAC100_INT_BAD) /* diff --git a/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c b/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c index 90bd5583ac34..cf7e9b26a0e3 100644 --- a/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c +++ b/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c @@ -2155,12 +2155,12 @@ static netdev_tx_t dpaa_start_xmit(struct sk_buff *skb, struct net_device *net_dev) { const int queue_mapping = skb_get_queue_mapping(skb); - bool nonlinear = skb_is_nonlinear(skb); struct rtnl_link_stats64 *percpu_stats; struct dpaa_percpu_priv *percpu_priv; struct netdev_queue *txq; struct dpaa_priv *priv; struct qm_fd fd; + bool nonlinear; int offset = 0; int err = 0; @@ -2170,6 +2170,13 @@ dpaa_start_xmit(struct sk_buff *skb, struct net_device *net_dev) qm_fd_clear_fd(&fd); + /* Packet data is always read as 32-bit words, so zero out any part of + * the skb which might be sent if we have to pad the packet + */ + if (__skb_put_padto(skb, ETH_ZLEN, false)) + goto enomem; + + nonlinear = skb_is_nonlinear(skb); if (!nonlinear) { /* We're going to store the skb backpointer at the beginning * of the data buffer, so we need a privately owned skb diff --git a/drivers/net/ethernet/freescale/enetc/enetc.c b/drivers/net/ethernet/freescale/enetc/enetc.c index 5f9603d4c049..18c862124667 100644 --- a/drivers/net/ethernet/freescale/enetc/enetc.c +++ b/drivers/net/ethernet/freescale/enetc/enetc.c @@ -1333,12 +1333,11 @@ static int enetc_setup_irqs(struct enetc_ndev_priv *priv) snprintf(v->name, sizeof(v->name), "%s-rxtx%d", priv->ndev->name, i); - err = request_irq(irq, enetc_msix, 0, v->name, v); + err = request_irq(irq, enetc_msix, IRQF_NO_AUTOEN, v->name, v); if (err) { dev_err(priv->dev, "request_irq() failed!\n"); goto irq_err; } - disable_irq(irq); v->tbier_base = hw->reg + ENETC_BDR(TX, 0, ENETC_TBIER); v->rbier = hw->reg + ENETC_BDR(RX, i, ENETC_RBIER); diff --git a/drivers/net/ethernet/hisilicon/hip04_eth.c b/drivers/net/ethernet/hisilicon/hip04_eth.c index e53512f6878a..09acd839a72c 100644 --- a/drivers/net/ethernet/hisilicon/hip04_eth.c +++ b/drivers/net/ethernet/hisilicon/hip04_eth.c @@ -943,6 +943,7 @@ static int hip04_mac_probe(struct platform_device *pdev) priv->tx_coalesce_timer.function = tx_done; priv->map = syscon_node_to_regmap(arg.np); + of_node_put(arg.np); if (IS_ERR(priv->map)) { dev_warn(d, "no syscon hisilicon,hip04-ppe\n"); ret = PTR_ERR(priv->map); diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.c b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.c index 1f44a6463f45..5929ac50e351 100644 --- a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.c +++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.c @@ -933,6 +933,7 @@ static int hns_mac_get_info(struct hns_mac_cb *mac_cb) mac_cb->cpld_ctrl = NULL; } else { syscon = syscon_node_to_regmap(cpld_args.np); + of_node_put(cpld_args.np); if (IS_ERR_OR_NULL(syscon)) { dev_dbg(mac_cb->dev, "no cpld-syscon found!\n"); mac_cb->cpld_ctrl = NULL; diff --git a/drivers/net/ethernet/hisilicon/hns_mdio.c b/drivers/net/ethernet/hisilicon/hns_mdio.c index 883d0d7c6858..229288dbe708 100644 --- a/drivers/net/ethernet/hisilicon/hns_mdio.c +++ b/drivers/net/ethernet/hisilicon/hns_mdio.c @@ -497,6 +497,7 @@ static int hns_mdio_probe(struct platform_device *pdev) MDIO_SC_RESET_ST; } } + of_node_put(reg_args.np); } else { dev_warn(&pdev->dev, "find syscon ret = %#x\n", ret); mdio_dev->subctrl_vbase = NULL; diff --git a/drivers/net/ethernet/ibm/emac/mal.c b/drivers/net/ethernet/ibm/emac/mal.c index 075c07303f16..b095d5057b5e 100644 --- a/drivers/net/ethernet/ibm/emac/mal.c +++ b/drivers/net/ethernet/ibm/emac/mal.c @@ -576,7 +576,7 @@ static int mal_probe(struct platform_device *ofdev) printk(KERN_ERR "%pOF: Support for 405EZ not enabled!\n", ofdev->dev.of_node); err = -ENODEV; - goto fail; + goto fail_unmap; #endif } diff --git a/drivers/net/ethernet/intel/ice/ice_sched.c b/drivers/net/ethernet/intel/ice/ice_sched.c index 44a228530253..f5bfb662f1df 100644 --- a/drivers/net/ethernet/intel/ice/ice_sched.c +++ b/drivers/net/ethernet/intel/ice/ice_sched.c @@ -27,9 +27,8 @@ ice_sched_add_root_node(struct ice_port_info *pi, if (!root) return ICE_ERR_NO_MEMORY; - /* coverity[suspicious_sizeof] */ root->children = devm_kcalloc(ice_hw_to_dev(hw), hw->max_children[0], - sizeof(*root), GFP_KERNEL); + sizeof(*root->children), GFP_KERNEL); if (!root->children) { devm_kfree(ice_hw_to_dev(hw), root); return ICE_ERR_NO_MEMORY; @@ -181,10 +180,9 @@ ice_sched_add_node(struct ice_port_info *pi, u8 layer, if (!node) return ICE_ERR_NO_MEMORY; if (hw->max_children[layer]) { - /* coverity[suspicious_sizeof] */ node->children = devm_kcalloc(ice_hw_to_dev(hw), hw->max_children[layer], - sizeof(*node), GFP_KERNEL); + sizeof(*node->children), GFP_KERNEL); if (!node->children) { devm_kfree(ice_hw_to_dev(hw), node); return ICE_ERR_NO_MEMORY; diff --git a/drivers/net/ethernet/intel/ice/ice_switch.c b/drivers/net/ethernet/intel/ice/ice_switch.c index 0155c45d9d7f..68d756e86ca1 100644 --- a/drivers/net/ethernet/intel/ice/ice_switch.c +++ b/drivers/net/ethernet/intel/ice/ice_switch.c @@ -1259,7 +1259,7 @@ ice_add_update_vsi_list(struct ice_hw *hw, /* A rule already exists with the new VSI being added */ if (test_bit(vsi_handle, m_entry->vsi_list_info->vsi_map)) - return 0; + return -EEXIST; /* Update the previously created VSI list set with * the new VSI ID passed in @@ -2789,8 +2789,6 @@ ice_replay_vsi_fltr(struct ice_hw *hw, u16 vsi_handle, u8 recp_id, if (!itr->vsi_list_info || !test_bit(vsi_handle, itr->vsi_list_info->vsi_map)) continue; - /* Clearing it so that the logic can add it back */ - clear_bit(vsi_handle, itr->vsi_list_info->vsi_map); f_entry.fltr_info.vsi_handle = vsi_handle; f_entry.fltr_info.fltr_act = ICE_FWD_TO_VSI; /* update the src in case it is VSI num */ diff --git a/drivers/net/ethernet/intel/igb/igb_main.c b/drivers/net/ethernet/intel/igb/igb_main.c index e2c38e5232dc..17cdda3fe415 100644 --- a/drivers/net/ethernet/intel/igb/igb_main.c +++ b/drivers/net/ethernet/intel/igb/igb_main.c @@ -9536,6 +9536,10 @@ static void igb_io_resume(struct pci_dev *pdev) struct igb_adapter *adapter = netdev_priv(netdev); if (netif_running(netdev)) { + if (!test_bit(__IGB_DOWN, &adapter->state)) { + dev_dbg(&pdev->dev, "Resuming from non-fatal error, do nothing.\n"); + return; + } if (igb_up(adapter)) { dev_err(&pdev->dev, "igb_up failed after reset\n"); return; diff --git a/drivers/net/ethernet/jme.c b/drivers/net/ethernet/jme.c index e9efe074edc1..80858206c514 100644 --- a/drivers/net/ethernet/jme.c +++ b/drivers/net/ethernet/jme.c @@ -947,15 +947,13 @@ jme_udpsum(struct sk_buff *skb) if (skb->protocol != htons(ETH_P_IP)) return csum; skb_set_network_header(skb, ETH_HLEN); - if ((ip_hdr(skb)->protocol != IPPROTO_UDP) || - (skb->len < (ETH_HLEN + - (ip_hdr(skb)->ihl << 2) + - sizeof(struct udphdr)))) { + + if (ip_hdr(skb)->protocol != IPPROTO_UDP || + skb->len < (ETH_HLEN + ip_hdrlen(skb) + sizeof(struct udphdr))) { skb_reset_network_header(skb); return csum; } - skb_set_transport_header(skb, - ETH_HLEN + (ip_hdr(skb)->ihl << 2)); + skb_set_transport_header(skb, ETH_HLEN + ip_hdrlen(skb)); csum = udp_hdr(skb)->check; skb_reset_transport_header(skb); skb_reset_network_header(skb); diff --git a/drivers/net/ethernet/lantiq_etop.c b/drivers/net/ethernet/lantiq_etop.c index 1d7c0b872c59..45155023a298 100644 --- a/drivers/net/ethernet/lantiq_etop.c +++ b/drivers/net/ethernet/lantiq_etop.c @@ -464,7 +464,9 @@ ltq_etop_tx(struct sk_buff *skb, struct net_device *dev) unsigned long flags; u32 byte_offset; - len = skb->len < ETH_ZLEN ? ETH_ZLEN : skb->len; + if (skb_put_padto(skb, ETH_ZLEN)) + return NETDEV_TX_OK; + len = skb->len; if ((desc->ctl & (LTQ_DMA_OWN | LTQ_DMA_C)) || ch->skb[ch->dma.desc]) { netdev_err(dev, "tx ring full\n"); diff --git a/drivers/net/ethernet/marvell/mvpp2/mvpp2.h b/drivers/net/ethernet/marvell/mvpp2/mvpp2.h index e999ac2de34e..40a9d10c56cd 100644 --- a/drivers/net/ethernet/marvell/mvpp2/mvpp2.h +++ b/drivers/net/ethernet/marvell/mvpp2/mvpp2.h @@ -999,7 +999,7 @@ struct mvpp2 { unsigned int max_port_rxqs; /* Workqueue to gather hardware statistics */ - char queue_name[30]; + char queue_name[31]; struct workqueue_struct *stats_queue; /* Debugfs root entry */ diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c b/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c index 1fdb42899a9f..1e61f31a689a 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c @@ -127,6 +127,10 @@ void mlx5e_build_ptys2ethtool_map(void) ETHTOOL_LINK_MODE_100000baseKR4_Full_BIT); MLX5_BUILD_PTYS2ETHTOOL_CONFIG(MLX5E_100GBASE_LR4, legacy, ETHTOOL_LINK_MODE_100000baseLR4_ER4_Full_BIT); + MLX5_BUILD_PTYS2ETHTOOL_CONFIG(MLX5E_100BASE_TX, legacy, + ETHTOOL_LINK_MODE_100baseT_Full_BIT); + MLX5_BUILD_PTYS2ETHTOOL_CONFIG(MLX5E_1000BASE_T, legacy, + ETHTOOL_LINK_MODE_1000baseT_Full_BIT); MLX5_BUILD_PTYS2ETHTOOL_CONFIG(MLX5E_10GBASE_T, legacy, ETHTOOL_LINK_MODE_10000baseT_Full_BIT); MLX5_BUILD_PTYS2ETHTOOL_CONFIG(MLX5E_25GBASE_CR, legacy, diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_tx.c b/drivers/net/ethernet/mellanox/mlx5/core/en_tx.c index 373668068071..9b1e43ff8ae1 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_tx.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_tx.c @@ -601,7 +601,6 @@ mlx5e_sq_xmit_mpwqe(struct mlx5e_txqsq *sq, struct sk_buff *skb, return; err_unmap: - mlx5e_dma_unmap_wqe_err(sq, 1); sq->stats->dropped++; dev_kfree_skb_any(skb); } diff --git a/drivers/net/ethernet/mellanox/mlx5/core/lib/pci_vsc.c b/drivers/net/ethernet/mellanox/mlx5/core/lib/pci_vsc.c index 6b774e0c2766..c14f9529c25f 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/lib/pci_vsc.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/lib/pci_vsc.c @@ -24,6 +24,11 @@ pci_write_config_dword((dev)->pdev, (dev)->vsc_addr + (offset), (val)) #define VSC_MAX_RETRIES 2048 +/* Reading VSC registers can take relatively long time. + * Yield the cpu every 128 registers read. + */ +#define VSC_GW_READ_BLOCK_COUNT 128 + enum { VSC_CTRL_OFFSET = 0x4, VSC_COUNTER_OFFSET = 0x8, @@ -269,6 +274,7 @@ int mlx5_vsc_gw_read_block_fast(struct mlx5_core_dev *dev, u32 *data, { unsigned int next_read_addr = 0; unsigned int read_addr = 0; + unsigned int count = 0; while (read_addr < length) { if (mlx5_vsc_gw_read_fast(dev, read_addr, &next_read_addr, @@ -276,6 +282,10 @@ int mlx5_vsc_gw_read_block_fast(struct mlx5_core_dev *dev, u32 *data, return read_addr; read_addr = next_read_addr; + if (++count == VSC_GW_READ_BLOCK_COUNT) { + cond_resched(); + count = 0; + } } return length; } diff --git a/drivers/net/ethernet/mellanox/mlx5/core/main.c b/drivers/net/ethernet/mellanox/mlx5/core/main.c index 35e11cb883c9..f76a4860032c 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/main.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/main.c @@ -1600,6 +1600,7 @@ static const struct pci_device_id mlx5_core_pci_table[] = { { PCI_VDEVICE(MELLANOX, 0xa2d2) }, /* BlueField integrated ConnectX-5 network controller */ { PCI_VDEVICE(MELLANOX, 0xa2d3), MLX5_PCI_DEV_IS_VF}, /* BlueField integrated ConnectX-5 network controller VF */ { PCI_VDEVICE(MELLANOX, 0xa2d6) }, /* BlueField-2 integrated ConnectX-6 Dx network controller */ + { PCI_VDEVICE(MELLANOX, 0xa2dc) }, /* BlueField-3 integrated ConnectX-7 network controller */ { 0, } }; diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c index 5ab230aab2cd..4a4d171e4f5b 100644 --- a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c +++ b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c @@ -2631,8 +2631,8 @@ nfp_net_prepare_vector(struct nfp_net *nn, struct nfp_net_r_vector *r_vec, snprintf(r_vec->name, sizeof(r_vec->name), "%s-rxtx-%d", nfp_net_name(nn), idx); - err = request_irq(r_vec->irq_vector, r_vec->handler, 0, r_vec->name, - r_vec); + err = request_irq(r_vec->irq_vector, r_vec->handler, IRQF_NO_AUTOEN, + r_vec->name, r_vec); if (err) { if (nn->dp.netdev) netif_napi_del(&r_vec->napi); @@ -2642,7 +2642,6 @@ nfp_net_prepare_vector(struct nfp_net *nn, struct nfp_net_r_vector *r_vec, nn_err(nn, "Error requesting IRQ %d\n", r_vec->irq_vector); return err; } - disable_irq(r_vec->irq_vector); irq_set_affinity_hint(r_vec->irq_vector, &r_vec->affinity_mask); diff --git a/drivers/net/ethernet/realtek/r8169_main.c b/drivers/net/ethernet/realtek/r8169_main.c index 4c588fc43eb9..e9296d63450d 100644 --- a/drivers/net/ethernet/realtek/r8169_main.c +++ b/drivers/net/ethernet/realtek/r8169_main.c @@ -569,7 +569,34 @@ struct rtl8169_counters { __le64 rx_broadcast; __le32 rx_multicast; __le16 tx_aborted; - __le16 tx_underun; + __le16 tx_underrun; + /* new since RTL8125 */ + __le64 tx_octets; + __le64 rx_octets; + __le64 rx_multicast64; + __le64 tx_unicast64; + __le64 tx_broadcast64; + __le64 tx_multicast64; + __le32 tx_pause_on; + __le32 tx_pause_off; + __le32 tx_pause_all; + __le32 tx_deferred; + __le32 tx_late_collision; + __le32 tx_all_collision; + __le32 tx_aborted32; + __le32 align_errors32; + __le32 rx_frame_too_long; + __le32 rx_runt; + __le32 rx_pause_on; + __le32 rx_pause_off; + __le32 rx_pause_all; + __le32 rx_unknown_opcode; + __le32 rx_mac_error; + __le32 tx_underrun32; + __le32 rx_mac_missed; + __le32 rx_tcam_dropped; + __le32 tdu; + __le32 rdu; }; struct rtl8169_tc_offsets { @@ -1670,7 +1697,7 @@ static void rtl8169_get_ethtool_stats(struct net_device *dev, data[9] = le64_to_cpu(counters->rx_broadcast); data[10] = le32_to_cpu(counters->rx_multicast); data[11] = le16_to_cpu(counters->tx_aborted); - data[12] = le16_to_cpu(counters->tx_underun); + data[12] = le16_to_cpu(counters->tx_underrun); } static void rtl8169_get_strings(struct net_device *dev, u32 stringset, u8 *data) diff --git a/drivers/net/ethernet/realtek/r8169_phy_config.c b/drivers/net/ethernet/realtek/r8169_phy_config.c index e18a76f5049f..f8f6f2ce3db3 100644 --- a/drivers/net/ethernet/realtek/r8169_phy_config.c +++ b/drivers/net/ethernet/realtek/r8169_phy_config.c @@ -1263,6 +1263,7 @@ static void rtl8125a_2_hw_phy_config(struct rtl8169_private *tp, phy_modify_paged(phydev, 0xa86, 0x15, 0x0001, 0x0000); rtl8168g_enable_gphy_10m(phydev); + rtl8168g_disable_aldps(phydev); rtl8125a_config_eee_phy(phydev); } @@ -1302,6 +1303,7 @@ static void rtl8125b_hw_phy_config(struct rtl8169_private *tp, phy_modify_paged(phydev, 0xbf8, 0x12, 0xe000, 0xa000); rtl8125_legacy_force_mode(phydev); + rtl8168g_disable_aldps(phydev); rtl8125b_config_eee_phy(phydev); } diff --git a/drivers/net/ethernet/seeq/ether3.c b/drivers/net/ethernet/seeq/ether3.c index 65c98837ec45..3d4a86bf8fd1 100644 --- a/drivers/net/ethernet/seeq/ether3.c +++ b/drivers/net/ethernet/seeq/ether3.c @@ -845,9 +845,11 @@ static void ether3_remove(struct expansion_card *ec) { struct net_device *dev = ecard_get_drvdata(ec); + ether3_outw(priv(dev)->regs.config2 |= CFG2_CTRLO, REG_CONFIG2); ecard_set_drvdata(ec, NULL); unregister_netdev(dev); + del_timer_sync(&priv(dev)->timer); free_netdev(dev); ecard_release_resources(ec); } diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c index 4da1a80de722..3539c1542eb8 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c @@ -363,6 +363,7 @@ static int tc_setup_cbs(struct stmmac_priv *priv, return ret; priv->plat->tx_queues_cfg[queue].mode_to_use = MTL_QUEUE_DCB; + return 0; } /* Final adjustments for HW */ diff --git a/drivers/net/geneve.c b/drivers/net/geneve.c index 8ce1ad52edf1..be1180e2b26d 100644 --- a/drivers/net/geneve.c +++ b/drivers/net/geneve.c @@ -54,6 +54,7 @@ struct geneve_config { bool use_udp6_rx_checksums; bool ttl_inherit; enum ifla_geneve_df df; + bool inner_proto_inherit; }; /* Pseudo network device */ @@ -249,17 +250,24 @@ static void geneve_rx(struct geneve_dev *geneve, struct geneve_sock *gs, } } - skb_reset_mac_header(skb); - skb->protocol = eth_type_trans(skb, geneve->dev); - skb_postpull_rcsum(skb, eth_hdr(skb), ETH_HLEN); - if (tun_dst) skb_dst_set(skb, &tun_dst->dst); - /* Ignore packet loops (and multicast echo) */ - if (ether_addr_equal(eth_hdr(skb)->h_source, geneve->dev->dev_addr)) { - geneve->dev->stats.rx_errors++; - goto drop; + if (gnvh->proto_type == htons(ETH_P_TEB)) { + skb_reset_mac_header(skb); + skb->protocol = eth_type_trans(skb, geneve->dev); + skb_postpull_rcsum(skb, eth_hdr(skb), ETH_HLEN); + + /* Ignore packet loops (and multicast echo) */ + if (ether_addr_equal(eth_hdr(skb)->h_source, + geneve->dev->dev_addr)) { + geneve->dev->stats.rx_errors++; + goto drop; + } + } else { + skb_reset_mac_header(skb); + skb->dev = geneve->dev; + skb->pkt_type = PACKET_HOST; } oiph = skb_network_header(skb); @@ -343,6 +351,7 @@ static int geneve_udp_encap_recv(struct sock *sk, struct sk_buff *skb) struct genevehdr *geneveh; struct geneve_dev *geneve; struct geneve_sock *gs; + __be16 inner_proto; int opts_len; /* Need UDP and Geneve header to be present */ @@ -354,7 +363,11 @@ static int geneve_udp_encap_recv(struct sock *sk, struct sk_buff *skb) if (unlikely(geneveh->ver != GENEVE_VER)) goto drop; - if (unlikely(geneveh->proto_type != htons(ETH_P_TEB))) + inner_proto = geneveh->proto_type; + + if (unlikely((inner_proto != htons(ETH_P_TEB) && + inner_proto != htons(ETH_P_IP) && + inner_proto != htons(ETH_P_IPV6)))) goto drop; gs = rcu_dereference_sk_user_data(sk); @@ -365,9 +378,14 @@ static int geneve_udp_encap_recv(struct sock *sk, struct sk_buff *skb) if (!geneve) goto drop; + if (unlikely((!geneve->cfg.inner_proto_inherit && + inner_proto != htons(ETH_P_TEB)))) { + geneve->dev->stats.rx_dropped++; + goto drop; + } + opts_len = geneveh->opt_len * 4; - if (iptunnel_pull_header(skb, GENEVE_BASE_HLEN + opts_len, - htons(ETH_P_TEB), + if (iptunnel_pull_header(skb, GENEVE_BASE_HLEN + opts_len, inner_proto, !net_eq(geneve->net, dev_net(geneve->dev)))) { geneve->dev->stats.rx_dropped++; goto drop; @@ -714,7 +732,8 @@ static int geneve_stop(struct net_device *dev) } static void geneve_build_header(struct genevehdr *geneveh, - const struct ip_tunnel_info *info) + const struct ip_tunnel_info *info, + __be16 inner_proto) { geneveh->ver = GENEVE_VER; geneveh->opt_len = info->options_len / 4; @@ -722,7 +741,7 @@ static void geneve_build_header(struct genevehdr *geneveh, geneveh->critical = !!(info->key.tun_flags & TUNNEL_CRIT_OPT); geneveh->rsvd1 = 0; tunnel_id_to_vni(info->key.tun_id, geneveh->vni); - geneveh->proto_type = htons(ETH_P_TEB); + geneveh->proto_type = inner_proto; geneveh->rsvd2 = 0; if (info->key.tun_flags & TUNNEL_GENEVE_OPT) @@ -731,10 +750,12 @@ static void geneve_build_header(struct genevehdr *geneveh, static int geneve_build_skb(struct dst_entry *dst, struct sk_buff *skb, const struct ip_tunnel_info *info, - bool xnet, int ip_hdr_len) + bool xnet, int ip_hdr_len, + bool inner_proto_inherit) { bool udp_sum = !!(info->key.tun_flags & TUNNEL_CSUM); struct genevehdr *gnvh; + __be16 inner_proto; int min_headroom; int err; @@ -752,8 +773,9 @@ static int geneve_build_skb(struct dst_entry *dst, struct sk_buff *skb, goto free_dst; gnvh = __skb_push(skb, sizeof(*gnvh) + info->options_len); - geneve_build_header(gnvh, info); - skb_set_inner_protocol(skb, htons(ETH_P_TEB)); + inner_proto = inner_proto_inherit ? skb->protocol : htons(ETH_P_TEB); + geneve_build_header(gnvh, info, inner_proto); + skb_set_inner_protocol(skb, inner_proto); return 0; free_dst: @@ -876,6 +898,7 @@ static int geneve_xmit_skb(struct sk_buff *skb, struct net_device *dev, struct geneve_dev *geneve, const struct ip_tunnel_info *info) { + bool inner_proto_inherit = geneve->cfg.inner_proto_inherit; bool xnet = !net_eq(geneve->net, dev_net(geneve->dev)); struct geneve_sock *gs4 = rcu_dereference(geneve->sock4); const struct ip_tunnel_key *key = &info->key; @@ -887,7 +910,7 @@ static int geneve_xmit_skb(struct sk_buff *skb, struct net_device *dev, __be16 sport; int err; - if (!skb_vlan_inet_prepare(skb)) + if (!skb_vlan_inet_prepare(skb, inner_proto_inherit)) return -EINVAL; sport = udp_flow_src_port(geneve->net, skb, 1, USHRT_MAX, true); @@ -959,7 +982,8 @@ static int geneve_xmit_skb(struct sk_buff *skb, struct net_device *dev, } } - err = geneve_build_skb(&rt->dst, skb, info, xnet, sizeof(struct iphdr)); + err = geneve_build_skb(&rt->dst, skb, info, xnet, sizeof(struct iphdr), + inner_proto_inherit); if (unlikely(err)) return err; @@ -975,6 +999,7 @@ static int geneve6_xmit_skb(struct sk_buff *skb, struct net_device *dev, struct geneve_dev *geneve, const struct ip_tunnel_info *info) { + bool inner_proto_inherit = geneve->cfg.inner_proto_inherit; bool xnet = !net_eq(geneve->net, dev_net(geneve->dev)); struct geneve_sock *gs6 = rcu_dereference(geneve->sock6); const struct ip_tunnel_key *key = &info->key; @@ -984,7 +1009,7 @@ static int geneve6_xmit_skb(struct sk_buff *skb, struct net_device *dev, __be16 sport; int err; - if (!skb_vlan_inet_prepare(skb)) + if (!skb_vlan_inet_prepare(skb, inner_proto_inherit)) return -EINVAL; sport = udp_flow_src_port(geneve->net, skb, 1, USHRT_MAX, true); @@ -1038,7 +1063,8 @@ static int geneve6_xmit_skb(struct sk_buff *skb, struct net_device *dev, ttl = key->ttl; ttl = ttl ? : ip6_dst_hoplimit(dst); } - err = geneve_build_skb(dst, skb, info, xnet, sizeof(struct ipv6hdr)); + err = geneve_build_skb(dst, skb, info, xnet, sizeof(struct ipv6hdr), + inner_proto_inherit); if (unlikely(err)) return err; @@ -1237,6 +1263,7 @@ static void geneve_setup(struct net_device *dev) } static const struct nla_policy geneve_policy[IFLA_GENEVE_MAX + 1] = { + [IFLA_GENEVE_UNSPEC] = { .strict_start_type = IFLA_GENEVE_INNER_PROTO_INHERIT }, [IFLA_GENEVE_ID] = { .type = NLA_U32 }, [IFLA_GENEVE_REMOTE] = { .len = sizeof_field(struct iphdr, daddr) }, [IFLA_GENEVE_REMOTE6] = { .len = sizeof(struct in6_addr) }, @@ -1250,6 +1277,7 @@ static const struct nla_policy geneve_policy[IFLA_GENEVE_MAX + 1] = { [IFLA_GENEVE_UDP_ZERO_CSUM6_RX] = { .type = NLA_U8 }, [IFLA_GENEVE_TTL_INHERIT] = { .type = NLA_U8 }, [IFLA_GENEVE_DF] = { .type = NLA_U8 }, + [IFLA_GENEVE_INNER_PROTO_INHERIT] = { .type = NLA_FLAG }, }; static int geneve_validate(struct nlattr *tb[], struct nlattr *data[], @@ -1387,6 +1415,14 @@ static int geneve_configure(struct net *net, struct net_device *dev, dst_cache_reset(&geneve->cfg.info.dst_cache); memcpy(&geneve->cfg, cfg, sizeof(*cfg)); + if (geneve->cfg.inner_proto_inherit) { + dev->header_ops = NULL; + dev->type = ARPHRD_NONE; + dev->hard_header_len = 0; + dev->addr_len = 0; + dev->flags = IFF_NOARP; + } + err = register_netdevice(dev); if (err) return err; @@ -1560,10 +1596,18 @@ static int geneve_nl2info(struct nlattr *tb[], struct nlattr *data[], #endif } + if (data[IFLA_GENEVE_INNER_PROTO_INHERIT]) { + if (changelink) { + attrtype = IFLA_GENEVE_INNER_PROTO_INHERIT; + goto change_notsup; + } + cfg->inner_proto_inherit = true; + } + return 0; change_notsup: NL_SET_ERR_MSG_ATTR(extack, data[attrtype], - "Changing VNI, Port, endpoint IP address family, external, and UDP checksum attributes are not supported"); + "Changing VNI, Port, endpoint IP address family, external, inner_proto_inherit, and UDP checksum attributes are not supported"); return -EOPNOTSUPP; } @@ -1739,6 +1783,7 @@ static size_t geneve_get_size(const struct net_device *dev) nla_total_size(sizeof(__u8)) + /* IFLA_GENEVE_UDP_ZERO_CSUM6_TX */ nla_total_size(sizeof(__u8)) + /* IFLA_GENEVE_UDP_ZERO_CSUM6_RX */ nla_total_size(sizeof(__u8)) + /* IFLA_GENEVE_TTL_INHERIT */ + nla_total_size(0) + /* IFLA_GENEVE_INNER_PROTO_INHERIT */ 0; } @@ -1798,6 +1843,10 @@ static int geneve_fill_info(struct sk_buff *skb, const struct net_device *dev) if (nla_put_u8(skb, IFLA_GENEVE_TTL_INHERIT, ttl_inherit)) goto nla_put_failure; + if (geneve->cfg.inner_proto_inherit && + nla_put_flag(skb, IFLA_GENEVE_INNER_PROTO_INHERIT)) + goto nla_put_failure; + return 0; nla_put_failure: diff --git a/drivers/net/ieee802154/Kconfig b/drivers/net/ieee802154/Kconfig index 0f7c6dc2ed15..26f393a0507c 100644 --- a/drivers/net/ieee802154/Kconfig +++ b/drivers/net/ieee802154/Kconfig @@ -108,6 +108,7 @@ config IEEE802154_CA8210_DEBUGFS config IEEE802154_MCR20A tristate "MCR20A transceiver driver" + select REGMAP_SPI depends on IEEE802154_DRIVERS && MAC802154 depends on SPI help diff --git a/drivers/net/ieee802154/mcr20a.c b/drivers/net/ieee802154/mcr20a.c index 383231b85464..16474990dc01 100644 --- a/drivers/net/ieee802154/mcr20a.c +++ b/drivers/net/ieee802154/mcr20a.c @@ -1311,16 +1311,13 @@ mcr20a_probe(struct spi_device *spi) irq_type = IRQF_TRIGGER_FALLING; ret = devm_request_irq(&spi->dev, spi->irq, mcr20a_irq_isr, - irq_type, dev_name(&spi->dev), lp); + irq_type | IRQF_NO_AUTOEN, dev_name(&spi->dev), lp); if (ret) { dev_err(&spi->dev, "could not request_irq for mcr20a\n"); ret = -ENODEV; goto free_dev; } - /* disable_irq by default and wait for starting hardware */ - disable_irq(spi->irq); - ret = ieee802154_register_hw(hw); if (ret) { dev_crit(&spi->dev, "ieee802154_register_hw failed\n"); diff --git a/drivers/net/phy/bcm84881.c b/drivers/net/phy/bcm84881.c index 9717a1626f3f..37a64a37b2ae 100644 --- a/drivers/net/phy/bcm84881.c +++ b/drivers/net/phy/bcm84881.c @@ -120,7 +120,7 @@ static int bcm84881_aneg_done(struct phy_device *phydev) bmsr = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_AN_C22 + MII_BMSR); if (bmsr < 0) - return val; + return bmsr; return !!(val & MDIO_AN_STAT1_COMPLETE) && !!(bmsr & BMSR_ANEGCOMPLETE); @@ -146,7 +146,7 @@ static int bcm84881_read_status(struct phy_device *phydev) bmsr = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_AN_C22 + MII_BMSR); if (bmsr < 0) - return val; + return bmsr; phydev->autoneg_complete = !!(val & MDIO_AN_STAT1_COMPLETE) && !!(bmsr & BMSR_ANEGCOMPLETE); diff --git a/drivers/net/phy/dp83869.c b/drivers/net/phy/dp83869.c index 65b69ff35e40..01b593e0bb4a 100644 --- a/drivers/net/phy/dp83869.c +++ b/drivers/net/phy/dp83869.c @@ -610,7 +610,6 @@ static int dp83869_configure_fiber(struct phy_device *phydev, phydev->supported); linkmode_set_bit(ETHTOOL_LINK_MODE_FIBRE_BIT, phydev->supported); - linkmode_set_bit(ADVERTISED_FIBRE, phydev->advertising); if (dp83869->mode == DP83869_RGMII_1000_BASE) { linkmode_set_bit(ETHTOOL_LINK_MODE_1000baseX_Full_BIT, diff --git a/drivers/net/phy/vitesse.c b/drivers/net/phy/vitesse.c index bb680352708a..3f594c8784e2 100644 --- a/drivers/net/phy/vitesse.c +++ b/drivers/net/phy/vitesse.c @@ -232,16 +232,6 @@ static int vsc739x_config_init(struct phy_device *phydev) return 0; } -static int vsc73xx_config_aneg(struct phy_device *phydev) -{ - /* The VSC73xx switches does not like to be instructed to - * do autonegotiation in any way, it prefers that you just go - * with the power-on/reset defaults. Writing some registers will - * just make autonegotiation permanently fail. - */ - return 0; -} - /* This adds a skew for both TX and RX clocks, so the skew should only be * applied to "rgmii-id" interfaces. It may not work as expected * on "rgmii-txid", "rgmii-rxid" or "rgmii" interfaces. */ @@ -424,7 +414,6 @@ static struct phy_driver vsc82xx_driver[] = { .phy_id_mask = 0x000ffff0, /* PHY_GBIT_FEATURES */ .config_init = vsc738x_config_init, - .config_aneg = vsc73xx_config_aneg, .read_page = vsc73xx_read_page, .write_page = vsc73xx_write_page, }, { @@ -433,7 +422,6 @@ static struct phy_driver vsc82xx_driver[] = { .phy_id_mask = 0x000ffff0, /* PHY_GBIT_FEATURES */ .config_init = vsc738x_config_init, - .config_aneg = vsc73xx_config_aneg, .read_page = vsc73xx_read_page, .write_page = vsc73xx_write_page, }, { @@ -442,7 +430,6 @@ static struct phy_driver vsc82xx_driver[] = { .phy_id_mask = 0x000ffff0, /* PHY_GBIT_FEATURES */ .config_init = vsc739x_config_init, - .config_aneg = vsc73xx_config_aneg, .read_page = vsc73xx_read_page, .write_page = vsc73xx_write_page, }, { @@ -451,7 +438,6 @@ static struct phy_driver vsc82xx_driver[] = { .phy_id_mask = 0x000ffff0, /* PHY_GBIT_FEATURES */ .config_init = vsc739x_config_init, - .config_aneg = vsc73xx_config_aneg, .read_page = vsc73xx_read_page, .write_page = vsc73xx_write_page, }, { diff --git a/drivers/net/ppp/ppp_async.c b/drivers/net/ppp/ppp_async.c index aada8a3c1821..164c11df8192 100644 --- a/drivers/net/ppp/ppp_async.c +++ b/drivers/net/ppp/ppp_async.c @@ -552,7 +552,7 @@ ppp_async_encode(struct asyncppp *ap) * and 7 (code-reject) must be sent as though no options * had been negotiated. */ - islcp = proto == PPP_LCP && 1 <= data[2] && data[2] <= 7; + islcp = proto == PPP_LCP && count >= 3 && 1 <= data[2] && data[2] <= 7; if (i == 0) { if (islcp) diff --git a/drivers/net/slip/slhc.c b/drivers/net/slip/slhc.c index f78ceba42e57..603a29f3905b 100644 --- a/drivers/net/slip/slhc.c +++ b/drivers/net/slip/slhc.c @@ -643,46 +643,57 @@ slhc_uncompress(struct slcompress *comp, unsigned char *icp, int isize) int slhc_remember(struct slcompress *comp, unsigned char *icp, int isize) { - struct cstate *cs; - unsigned ihl; - + const struct tcphdr *th; unsigned char index; + struct iphdr *iph; + struct cstate *cs; + unsigned int ihl; - if(isize < 20) { - /* The packet is shorter than a legal IP header */ + /* The packet is shorter than a legal IP header. + * Also make sure isize is positive. + */ + if (isize < (int)sizeof(struct iphdr)) { +runt: comp->sls_i_runt++; - return slhc_toss( comp ); + return slhc_toss(comp); } + iph = (struct iphdr *)icp; /* Peek at the IP header's IHL field to find its length */ - ihl = icp[0] & 0xf; - if(ihl < 20 / 4){ - /* The IP header length field is too small */ - comp->sls_i_runt++; - return slhc_toss( comp ); - } - index = icp[9]; - icp[9] = IPPROTO_TCP; + ihl = iph->ihl; + /* The IP header length field is too small, + * or packet is shorter than the IP header followed + * by minimal tcp header. + */ + if (ihl < 5 || isize < ihl * 4 + sizeof(struct tcphdr)) + goto runt; + + index = iph->protocol; + iph->protocol = IPPROTO_TCP; if (ip_fast_csum(icp, ihl)) { /* Bad IP header checksum; discard */ comp->sls_i_badcheck++; - return slhc_toss( comp ); + return slhc_toss(comp); } - if(index > comp->rslot_limit) { + if (index > comp->rslot_limit) { comp->sls_i_error++; return slhc_toss(comp); } - + th = (struct tcphdr *)(icp + ihl * 4); + if (th->doff < sizeof(struct tcphdr) / 4) + goto runt; + if (isize < ihl * 4 + th->doff * 4) + goto runt; /* Update local state */ cs = &comp->rstate[comp->recv_current = index]; comp->flags &=~ SLF_TOSS; - memcpy(&cs->cs_ip,icp,20); - memcpy(&cs->cs_tcp,icp + ihl*4,20); + memcpy(&cs->cs_ip, iph, sizeof(*iph)); + memcpy(&cs->cs_tcp, th, sizeof(*th)); if (ihl > 5) - memcpy(cs->cs_ipopt, icp + sizeof(struct iphdr), (ihl - 5) * 4); - if (cs->cs_tcp.doff > 5) - memcpy(cs->cs_tcpopt, icp + ihl*4 + sizeof(struct tcphdr), (cs->cs_tcp.doff - 5) * 4); - cs->cs_hsize = ihl*2 + cs->cs_tcp.doff*2; + memcpy(cs->cs_ipopt, &iph[1], (ihl - 5) * 4); + if (th->doff > 5) + memcpy(cs->cs_tcpopt, &th[1], (th->doff - 5) * 4); + cs->cs_hsize = ihl*2 + th->doff*2; cs->initialized = true; /* Put headers back on packet * Neither header checksum is recalculated diff --git a/drivers/net/usb/ipheth.c b/drivers/net/usb/ipheth.c index 4485388dcff2..bb3d4c5dadfc 100644 --- a/drivers/net/usb/ipheth.c +++ b/drivers/net/usb/ipheth.c @@ -253,13 +253,14 @@ static int ipheth_carrier_set(struct ipheth_device *dev) 0x02, /* index */ dev->ctrl_buf, IPHETH_CTRL_BUF_SIZE, IPHETH_CTRL_TIMEOUT); - if (retval < 0) { + if (retval <= 0) { dev_err(&dev->intf->dev, "%s: usb_control_msg: %d\n", __func__, retval); return retval; } - if (dev->ctrl_buf[0] == IPHETH_CARRIER_ON) { + if ((retval == 1 && dev->ctrl_buf[0] == IPHETH_CARRIER_ON) || + (retval >= 2 && dev->ctrl_buf[1] == IPHETH_CARRIER_ON)) { netif_carrier_on(dev->net); if (dev->tx_urb->status != -EINPROGRESS) netif_wake_queue(dev->net); diff --git a/drivers/net/vrf.c b/drivers/net/vrf.c index 8ab0b5a8dfef..9aa4ce49856c 100644 --- a/drivers/net/vrf.c +++ b/drivers/net/vrf.c @@ -1337,8 +1337,8 @@ static struct sk_buff *vrf_ip6_rcv(struct net_device *vrf_dev, /* loopback, multicast & non-ND link-local traffic; do not push through * packet taps again. Reset pkt_type for upper layers to process skb. - * For strict packets with a source LLA, determine the dst using the - * original ifindex. + * For non-loopback strict packets, determine the dst using the original + * ifindex. */ if (skb->pkt_type == PACKET_LOOPBACK || (need_strict && !is_ndisc)) { skb->dev = vrf_dev; @@ -1347,7 +1347,7 @@ static struct sk_buff *vrf_ip6_rcv(struct net_device *vrf_dev, if (skb->pkt_type == PACKET_LOOPBACK) skb->pkt_type = PACKET_HOST; - else if (ipv6_addr_type(&ipv6_hdr(skb)->saddr) & IPV6_ADDR_LINKLOCAL) + else vrf_ip6_input_dst(skb, vrf_dev, orig_iif); goto out; diff --git a/drivers/net/wireless/ath/ath11k/dp_rx.c b/drivers/net/wireless/ath/ath11k/dp_rx.c index 6c4b84282e44..720c94806e1a 100644 --- a/drivers/net/wireless/ath/ath11k/dp_rx.c +++ b/drivers/net/wireless/ath/ath11k/dp_rx.c @@ -2621,7 +2621,7 @@ int ath11k_dp_process_rx(struct ath11k_base *ab, int ring_id, if (push_reason != HAL_REO_DEST_RING_PUSH_REASON_ROUTING_INSTRUCTION) { dev_kfree_skb_any(msdu); - ab->soc_stats.hal_reo_error[dp->reo_dst_ring[ring_id].ring_id]++; + ab->soc_stats.hal_reo_error[ring_id]++; continue; } diff --git a/drivers/net/wireless/ath/ath9k/debug.c b/drivers/net/wireless/ath/ath9k/debug.c index 8d98347e0ddf..8631258b1ea7 100644 --- a/drivers/net/wireless/ath/ath9k/debug.c +++ b/drivers/net/wireless/ath/ath9k/debug.c @@ -1316,11 +1316,11 @@ void ath9k_get_et_stats(struct ieee80211_hw *hw, struct ath_softc *sc = hw->priv; int i = 0; - data[i++] = (sc->debug.stats.txstats[PR_QNUM(IEEE80211_AC_BE)].tx_pkts_all + + data[i++] = ((u64)sc->debug.stats.txstats[PR_QNUM(IEEE80211_AC_BE)].tx_pkts_all + sc->debug.stats.txstats[PR_QNUM(IEEE80211_AC_BK)].tx_pkts_all + sc->debug.stats.txstats[PR_QNUM(IEEE80211_AC_VI)].tx_pkts_all + sc->debug.stats.txstats[PR_QNUM(IEEE80211_AC_VO)].tx_pkts_all); - data[i++] = (sc->debug.stats.txstats[PR_QNUM(IEEE80211_AC_BE)].tx_bytes_all + + data[i++] = ((u64)sc->debug.stats.txstats[PR_QNUM(IEEE80211_AC_BE)].tx_bytes_all + sc->debug.stats.txstats[PR_QNUM(IEEE80211_AC_BK)].tx_bytes_all + sc->debug.stats.txstats[PR_QNUM(IEEE80211_AC_VI)].tx_bytes_all + sc->debug.stats.txstats[PR_QNUM(IEEE80211_AC_VO)].tx_bytes_all); diff --git a/drivers/net/wireless/ath/ath9k/hif_usb.c b/drivers/net/wireless/ath/ath9k/hif_usb.c index e0130beb304d..6c73c0c0b82a 100644 --- a/drivers/net/wireless/ath/ath9k/hif_usb.c +++ b/drivers/net/wireless/ath/ath9k/hif_usb.c @@ -718,8 +718,7 @@ static void ath9k_hif_usb_rx_cb(struct urb *urb) } resubmit: - skb_reset_tail_pointer(skb); - skb_trim(skb, 0); + __skb_set_length(skb, 0); usb_anchor_urb(urb, &hif_dev->rx_submitted); ret = usb_submit_urb(urb, GFP_ATOMIC); @@ -756,8 +755,7 @@ static void ath9k_hif_usb_reg_in_cb(struct urb *urb) case -ESHUTDOWN: goto free_skb; default: - skb_reset_tail_pointer(skb); - skb_trim(skb, 0); + __skb_set_length(skb, 0); goto resubmit; } diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c index 08008b0c0637..fa784d835290 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c @@ -4747,6 +4747,10 @@ static void iwl_mvm_flush_no_vif(struct iwl_mvm *mvm, u32 queues, bool drop) int i; if (!iwl_mvm_has_new_tx_api(mvm)) { + /* we can't ask the firmware anything if it is dead */ + if (test_bit(IWL_MVM_STATUS_HW_RESTART_REQUESTED, + &mvm->status)) + return; if (drop) { mutex_lock(&mvm->mutex); iwl_mvm_flush_tx_path(mvm, @@ -4828,8 +4832,11 @@ static void iwl_mvm_mac_flush(struct ieee80211_hw *hw, /* this can take a while, and we may need/want other operations * to succeed while doing this, so do it without the mutex held + * If the firmware is dead, this can't work... */ - if (!drop && !iwl_mvm_has_new_tx_api(mvm)) + if (!drop && !iwl_mvm_has_new_tx_api(mvm) && + !test_bit(IWL_MVM_STATUS_HW_RESTART_REQUESTED, + &mvm->status)) iwl_trans_wait_tx_queues_empty(mvm->trans, msk); } diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info-gen3.c b/drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info-gen3.c index 56f63f5f5dd3..2afa5c91bc76 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info-gen3.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info-gen3.c @@ -111,7 +111,8 @@ iwl_pcie_ctxt_info_dbg_enable(struct iwl_trans *trans, } break; default: - IWL_ERR(trans, "WRT: Invalid buffer destination\n"); + IWL_DEBUG_FW(trans, "WRT: Invalid buffer destination (%d)\n", + le32_to_cpu(fw_mon_cfg->buf_location)); } out: if (dbg_flags) diff --git a/drivers/net/wireless/marvell/mwifiex/fw.h b/drivers/net/wireless/marvell/mwifiex/fw.h index 96c42b979e9b..284671618e9c 100644 --- a/drivers/net/wireless/marvell/mwifiex/fw.h +++ b/drivers/net/wireless/marvell/mwifiex/fw.h @@ -1593,7 +1593,7 @@ struct host_cmd_ds_802_11_scan_rsp { struct host_cmd_ds_802_11_scan_ext { u32 reserved; - u8 tlv_buffer[1]; + u8 tlv_buffer[]; } __packed; struct mwifiex_ie_types_bss_mode { diff --git a/drivers/net/wireless/marvell/mwifiex/scan.c b/drivers/net/wireless/marvell/mwifiex/scan.c index 78ef40e315b5..7f949aa77268 100644 --- a/drivers/net/wireless/marvell/mwifiex/scan.c +++ b/drivers/net/wireless/marvell/mwifiex/scan.c @@ -2561,8 +2561,7 @@ int mwifiex_ret_802_11_scan_ext(struct mwifiex_private *priv, ext_scan_resp = &resp->params.ext_scan; tlv = (void *)ext_scan_resp->tlv_buffer; - buf_left = le16_to_cpu(resp->size) - (sizeof(*ext_scan_resp) + S_DS_GEN - - 1); + buf_left = le16_to_cpu(resp->size) - (sizeof(*ext_scan_resp) + S_DS_GEN); while (buf_left >= sizeof(struct mwifiex_ie_types_header)) { type = le16_to_cpu(tlv->type); diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/main.c b/drivers/net/wireless/mediatek/mt76/mt7915/main.c index e78d3efa3fdf..6495d2edf7dc 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/main.c +++ b/drivers/net/wireless/mediatek/mt76/mt7915/main.c @@ -401,8 +401,7 @@ static void mt7915_configure_filter(struct ieee80211_hw *hw, MT76_FILTER(CONTROL, MT_WF_RFCR_DROP_CTS | MT_WF_RFCR_DROP_RTS | - MT_WF_RFCR_DROP_CTL_RSV | - MT_WF_RFCR_DROP_NDPA); + MT_WF_RFCR_DROP_CTL_RSV); *total_flags = flags; mt76_wr(dev, MT_WF_RFCR(band), phy->rxfilter); diff --git a/drivers/net/wireless/microchip/wilc1000/hif.c b/drivers/net/wireless/microchip/wilc1000/hif.c index 3f167bf4eef3..5f363653ed9d 100644 --- a/drivers/net/wireless/microchip/wilc1000/hif.c +++ b/drivers/net/wireless/microchip/wilc1000/hif.c @@ -366,6 +366,7 @@ void *wilc_parse_join_bss_param(struct cfg80211_bss *bss, struct wilc_join_bss_param *param; u8 rates_len = 0; int ies_len; + u64 ies_tsf; int ret; param = kzalloc(sizeof(*param), GFP_KERNEL); @@ -381,6 +382,7 @@ void *wilc_parse_join_bss_param(struct cfg80211_bss *bss, return NULL; } ies_len = ies->len; + ies_tsf = ies->tsf; rcu_read_unlock(); param->beacon_period = cpu_to_le16(bss->beacon_interval); @@ -436,7 +438,7 @@ void *wilc_parse_join_bss_param(struct cfg80211_bss *bss, IEEE80211_P2P_ATTR_ABSENCE_NOTICE, (u8 *)&noa_attr, sizeof(noa_attr)); if (ret > 0) { - param->tsf_lo = cpu_to_le32(ies->tsf); + param->tsf_lo = cpu_to_le32(ies_tsf); param->noa_enabled = 1; param->idx = noa_attr.index; if (noa_attr.oppps_ctwindow & IEEE80211_P2P_OPPPS_ENABLE_BIT) { diff --git a/drivers/net/wireless/realtek/rtw88/Kconfig b/drivers/net/wireless/realtek/rtw88/Kconfig index e3d7cb6c1290..5c18da555681 100644 --- a/drivers/net/wireless/realtek/rtw88/Kconfig +++ b/drivers/net/wireless/realtek/rtw88/Kconfig @@ -12,6 +12,7 @@ if RTW88 config RTW88_CORE tristate + select WANT_DEV_COREDUMP config RTW88_PCI tristate diff --git a/drivers/net/wireless/realtek/rtw88/main.c b/drivers/net/wireless/realtek/rtw88/main.c index 2ef1416899f0..91eea38f62cd 100644 --- a/drivers/net/wireless/realtek/rtw88/main.c +++ b/drivers/net/wireless/realtek/rtw88/main.c @@ -1007,20 +1007,21 @@ static int rtw_wait_firmware_completion(struct rtw_dev *rtwdev) { struct rtw_chip_info *chip = rtwdev->chip; struct rtw_fw_state *fw; + int ret = 0; fw = &rtwdev->fw; wait_for_completion(&fw->completion); if (!fw->firmware) - return -EINVAL; + ret = -EINVAL; if (chip->wow_fw_name) { fw = &rtwdev->wow_fw; wait_for_completion(&fw->completion); if (!fw->firmware) - return -EINVAL; + ret = -EINVAL; } - return 0; + return ret; } static int rtw_power_on(struct rtw_dev *rtwdev) diff --git a/drivers/net/wireless/realtek/rtw88/rtw8822c.c b/drivers/net/wireless/realtek/rtw88/rtw8822c.c index cee586335552..abed17e4c8c7 100644 --- a/drivers/net/wireless/realtek/rtw88/rtw8822c.c +++ b/drivers/net/wireless/realtek/rtw88/rtw8822c.c @@ -1813,12 +1813,14 @@ static void query_phy_status_page1(struct rtw_dev *rtwdev, u8 *phy_status, else rxsc = GET_PHY_STAT_P1_HT_RXSC(phy_status); - if (rxsc >= 9 && rxsc <= 12) - bw = RTW_CHANNEL_WIDTH_40; - else if (rxsc >= 13) - bw = RTW_CHANNEL_WIDTH_80; - else + if (rxsc == 0) + bw = rtwdev->hal.current_band_width; + else if (rxsc >= 1 && rxsc <= 8) bw = RTW_CHANNEL_WIDTH_20; + else if (rxsc >= 9 && rxsc <= 12) + bw = RTW_CHANNEL_WIDTH_40; + else + bw = RTW_CHANNEL_WIDTH_80; pkt_stat->rx_power[RF_PATH_A] = GET_PHY_STAT_P1_PWDB_A(phy_status) - 110; pkt_stat->rx_power[RF_PATH_B] = GET_PHY_STAT_P1_PWDB_B(phy_status) - 110; diff --git a/drivers/net/xen-netback/hash.c b/drivers/net/xen-netback/hash.c index ff96f22648ef..45ddce35f6d2 100644 --- a/drivers/net/xen-netback/hash.c +++ b/drivers/net/xen-netback/hash.c @@ -95,7 +95,7 @@ static u32 xenvif_new_hash(struct xenvif *vif, const u8 *data, static void xenvif_flush_hash(struct xenvif *vif) { - struct xenvif_hash_cache_entry *entry; + struct xenvif_hash_cache_entry *entry, *n; unsigned long flags; if (xenvif_hash_cache_size == 0) @@ -103,8 +103,7 @@ static void xenvif_flush_hash(struct xenvif *vif) spin_lock_irqsave(&vif->hash.cache.lock, flags); - list_for_each_entry_rcu(entry, &vif->hash.cache.list, link, - lockdep_is_held(&vif->hash.cache.lock)) { + list_for_each_entry_safe(entry, n, &vif->hash.cache.list, link) { list_del_rcu(&entry->link); vif->hash.cache.count--; kfree_rcu(entry, rcu); diff --git a/drivers/ntb/hw/intel/ntb_hw_gen1.c b/drivers/ntb/hw/intel/ntb_hw_gen1.c index 4f1add57d81d..16e34bb8e69e 100644 --- a/drivers/ntb/hw/intel/ntb_hw_gen1.c +++ b/drivers/ntb/hw/intel/ntb_hw_gen1.c @@ -778,7 +778,7 @@ static void ndev_init_debugfs(struct intel_ntb_dev *ndev) ndev->debugfs_dir = debugfs_create_dir(pci_name(ndev->ntb.pdev), debugfs_dir); - if (!ndev->debugfs_dir) + if (IS_ERR(ndev->debugfs_dir)) ndev->debugfs_info = NULL; else ndev->debugfs_info = diff --git a/drivers/ntb/hw/mscc/ntb_hw_switchtec.c b/drivers/ntb/hw/mscc/ntb_hw_switchtec.c index 4c6eb61a6ac6..ad09946100b5 100644 --- a/drivers/ntb/hw/mscc/ntb_hw_switchtec.c +++ b/drivers/ntb/hw/mscc/ntb_hw_switchtec.c @@ -1558,6 +1558,7 @@ static void switchtec_ntb_remove(struct device *dev, switchtec_ntb_deinit_db_msg_irq(sndev); switchtec_ntb_deinit_shared_mw(sndev); switchtec_ntb_deinit_crosslink(sndev); + cancel_work_sync(&sndev->check_link_status_work); kfree(sndev); dev_info(dev, "ntb device unregistered\n"); } diff --git a/drivers/ntb/test/ntb_perf.c b/drivers/ntb/test/ntb_perf.c index 65e1e5cf1b29..5a7a02408166 100644 --- a/drivers/ntb/test/ntb_perf.c +++ b/drivers/ntb/test/ntb_perf.c @@ -1227,7 +1227,7 @@ static ssize_t perf_dbgfs_read_info(struct file *filep, char __user *ubuf, "\tOut buffer addr 0x%pK\n", peer->outbuf); pos += scnprintf(buf + pos, buf_size - pos, - "\tOut buff phys addr %pa[p]\n", &peer->out_phys_addr); + "\tOut buff phys addr %pap\n", &peer->out_phys_addr); pos += scnprintf(buf + pos, buf_size - pos, "\tOut buffer size %pa\n", &peer->outbuf_size); diff --git a/drivers/nvdimm/nd_virtio.c b/drivers/nvdimm/nd_virtio.c index 10351d5b49fa..41e97c6567cf 100644 --- a/drivers/nvdimm/nd_virtio.c +++ b/drivers/nvdimm/nd_virtio.c @@ -44,6 +44,15 @@ static int virtio_pmem_flush(struct nd_region *nd_region) unsigned long flags; int err, err1; + /* + * Don't bother to submit the request to the device if the device is + * not activated. + */ + if (vdev->config->get_status(vdev) & VIRTIO_CONFIG_S_NEEDS_RESET) { + dev_info(&vdev->dev, "virtio pmem device needs a reset\n"); + return -EIO; + } + might_sleep(); req_data = kmalloc(sizeof(*req_data), GFP_KERNEL); if (!req_data) diff --git a/drivers/of/irq.c b/drivers/of/irq.c index ad0cb49e233a..f59bbcc94430 100644 --- a/drivers/of/irq.c +++ b/drivers/of/irq.c @@ -301,8 +301,8 @@ int of_irq_parse_one(struct device_node *device, int index, struct of_phandle_ar addr = of_get_property(device, "reg", &addr_len); /* Prevent out-of-bounds read in case of longer interrupt parent address size */ - if (addr_len > (3 * sizeof(__be32))) - addr_len = 3 * sizeof(__be32); + if (addr_len > sizeof(addr_buf)) + addr_len = sizeof(addr_buf); if (addr) memcpy(addr_buf, addr, addr_len); @@ -642,8 +642,7 @@ struct irq_domain *of_msi_map_get_device_domain(struct device *dev, u32 id, * @np: device node for @dev * @token: bus type for this domain * - * Parse the msi-parent property (both the simple and the complex - * versions), and returns the corresponding MSI domain. + * Parse the msi-parent property and returns the corresponding MSI domain. * * Returns: the MSI domain for this device (or NULL on failure). */ @@ -651,33 +650,14 @@ struct irq_domain *of_msi_get_domain(struct device *dev, struct device_node *np, enum irq_domain_bus_token token) { - struct device_node *msi_np; + struct of_phandle_iterator it; struct irq_domain *d; + int err; - /* Check for a single msi-parent property */ - msi_np = of_parse_phandle(np, "msi-parent", 0); - if (msi_np && !of_property_read_bool(msi_np, "#msi-cells")) { - d = irq_find_matching_host(msi_np, token); - if (!d) - of_node_put(msi_np); - return d; - } - - if (token == DOMAIN_BUS_PLATFORM_MSI) { - /* Check for the complex msi-parent version */ - struct of_phandle_args args; - int index = 0; - - while (!of_parse_phandle_with_args(np, "msi-parent", - "#msi-cells", - index, &args)) { - d = irq_find_matching_host(args.np, token); - if (d) - return d; - - of_node_put(args.np); - index++; - } + of_for_each_phandle(&it, err, np, "msi-parent", "#msi-cells", 0) { + d = irq_find_matching_host(it.node, token); + if (d) + return d; } return NULL; diff --git a/drivers/parport/procfs.c b/drivers/parport/procfs.c index 8400a379186e..180376c09cb4 100644 --- a/drivers/parport/procfs.c +++ b/drivers/parport/procfs.c @@ -51,12 +51,12 @@ static int do_active_device(struct ctl_table *table, int write, for (dev = port->devices; dev ; dev = dev->next) { if(dev == port->cad) { - len += snprintf(buffer, sizeof(buffer), "%s\n", dev->name); + len += scnprintf(buffer, sizeof(buffer), "%s\n", dev->name); } } if(!len) { - len += snprintf(buffer, sizeof(buffer), "%s\n", "none"); + len += scnprintf(buffer, sizeof(buffer), "%s\n", "none"); } if (len > *lenp) @@ -87,19 +87,19 @@ static int do_autoprobe(struct ctl_table *table, int write, } if ((str = info->class_name) != NULL) - len += snprintf (buffer + len, sizeof(buffer) - len, "CLASS:%s;\n", str); + len += scnprintf (buffer + len, sizeof(buffer) - len, "CLASS:%s;\n", str); if ((str = info->model) != NULL) - len += snprintf (buffer + len, sizeof(buffer) - len, "MODEL:%s;\n", str); + len += scnprintf (buffer + len, sizeof(buffer) - len, "MODEL:%s;\n", str); if ((str = info->mfr) != NULL) - len += snprintf (buffer + len, sizeof(buffer) - len, "MANUFACTURER:%s;\n", str); + len += scnprintf (buffer + len, sizeof(buffer) - len, "MANUFACTURER:%s;\n", str); if ((str = info->description) != NULL) - len += snprintf (buffer + len, sizeof(buffer) - len, "DESCRIPTION:%s;\n", str); + len += scnprintf (buffer + len, sizeof(buffer) - len, "DESCRIPTION:%s;\n", str); if ((str = info->cmdset) != NULL) - len += snprintf (buffer + len, sizeof(buffer) - len, "COMMAND SET:%s;\n", str); + len += scnprintf (buffer + len, sizeof(buffer) - len, "COMMAND SET:%s;\n", str); if (len > *lenp) len = *lenp; @@ -128,7 +128,7 @@ static int do_hardware_base_addr(struct ctl_table *table, int write, if (write) /* permissions prevent this anyway */ return -EACCES; - len += snprintf (buffer, sizeof(buffer), "%lu\t%lu\n", port->base, port->base_hi); + len += scnprintf (buffer, sizeof(buffer), "%lu\t%lu\n", port->base, port->base_hi); if (len > *lenp) len = *lenp; @@ -155,7 +155,7 @@ static int do_hardware_irq(struct ctl_table *table, int write, if (write) /* permissions prevent this anyway */ return -EACCES; - len += snprintf (buffer, sizeof(buffer), "%d\n", port->irq); + len += scnprintf (buffer, sizeof(buffer), "%d\n", port->irq); if (len > *lenp) len = *lenp; @@ -182,7 +182,7 @@ static int do_hardware_dma(struct ctl_table *table, int write, if (write) /* permissions prevent this anyway */ return -EACCES; - len += snprintf (buffer, sizeof(buffer), "%d\n", port->dma); + len += scnprintf (buffer, sizeof(buffer), "%d\n", port->dma); if (len > *lenp) len = *lenp; @@ -213,7 +213,7 @@ static int do_hardware_modes(struct ctl_table *table, int write, #define printmode(x) \ do { \ if (port->modes & PARPORT_MODE_##x) \ - len += snprintf(buffer + len, sizeof(buffer) - len, "%s%s", f++ ? "," : "", #x); \ + len += scnprintf(buffer + len, sizeof(buffer) - len, "%s%s", f++ ? "," : "", #x); \ } while (0) int f = 0; printmode(PCSPP); diff --git a/drivers/pci/controller/dwc/pci-keystone.c b/drivers/pci/controller/dwc/pci-keystone.c index 0b49bdf149a6..08f37ae8a111 100644 --- a/drivers/pci/controller/dwc/pci-keystone.c +++ b/drivers/pci/controller/dwc/pci-keystone.c @@ -598,7 +598,7 @@ static void ks_pcie_quirk(struct pci_dev *dev) */ if (pci_match_id(am6_pci_devids, bridge)) { bridge_dev = pci_get_host_bridge_device(dev); - if (!bridge_dev && !bridge_dev->parent) + if (!bridge_dev || !bridge_dev->parent) return; ks_pcie = dev_get_drvdata(bridge_dev->parent); diff --git a/drivers/pci/controller/pcie-xilinx-nwl.c b/drivers/pci/controller/pcie-xilinx-nwl.c index 2a9fe7c3aef9..bf9c30776087 100644 --- a/drivers/pci/controller/pcie-xilinx-nwl.c +++ b/drivers/pci/controller/pcie-xilinx-nwl.c @@ -79,8 +79,8 @@ #define MSGF_MISC_SR_NON_FATAL_DEV BIT(22) #define MSGF_MISC_SR_FATAL_DEV BIT(23) #define MSGF_MISC_SR_LINK_DOWN BIT(24) -#define MSGF_MSIC_SR_LINK_AUTO_BWIDTH BIT(25) -#define MSGF_MSIC_SR_LINK_BWIDTH BIT(26) +#define MSGF_MISC_SR_LINK_AUTO_BWIDTH BIT(25) +#define MSGF_MISC_SR_LINK_BWIDTH BIT(26) #define MSGF_MISC_SR_MASKALL (MSGF_MISC_SR_RXMSG_AVAIL | \ MSGF_MISC_SR_RXMSG_OVER | \ @@ -95,8 +95,8 @@ MSGF_MISC_SR_NON_FATAL_DEV | \ MSGF_MISC_SR_FATAL_DEV | \ MSGF_MISC_SR_LINK_DOWN | \ - MSGF_MSIC_SR_LINK_AUTO_BWIDTH | \ - MSGF_MSIC_SR_LINK_BWIDTH) + MSGF_MISC_SR_LINK_AUTO_BWIDTH | \ + MSGF_MISC_SR_LINK_BWIDTH) /* Legacy interrupt status mask bits */ #define MSGF_LEG_SR_INTA BIT(0) @@ -305,10 +305,10 @@ static irqreturn_t nwl_pcie_misc_handler(int irq, void *data) if (misc_stat & MSGF_MISC_SR_FATAL_DEV) dev_err(dev, "Fatal Error Detected\n"); - if (misc_stat & MSGF_MSIC_SR_LINK_AUTO_BWIDTH) + if (misc_stat & MSGF_MISC_SR_LINK_AUTO_BWIDTH) dev_info(dev, "Link Autonomous Bandwidth Management Status bit set\n"); - if (misc_stat & MSGF_MSIC_SR_LINK_BWIDTH) + if (misc_stat & MSGF_MISC_SR_LINK_BWIDTH) dev_info(dev, "Link Bandwidth Management Status bit set\n"); /* Clear misc interrupt status */ @@ -381,14 +381,12 @@ static void nwl_pcie_msi_handler_low(struct irq_desc *desc) static void nwl_mask_leg_irq(struct irq_data *data) { - struct irq_desc *desc = irq_to_desc(data->irq); - struct nwl_pcie *pcie; + struct nwl_pcie *pcie = irq_data_get_irq_chip_data(data); unsigned long flags; u32 mask; u32 val; - pcie = irq_desc_get_chip_data(desc); - mask = 1 << (data->hwirq - 1); + mask = 1 << data->hwirq; raw_spin_lock_irqsave(&pcie->leg_mask_lock, flags); val = nwl_bridge_readl(pcie, MSGF_LEG_MASK); nwl_bridge_writel(pcie, (val & (~mask)), MSGF_LEG_MASK); @@ -397,14 +395,12 @@ static void nwl_mask_leg_irq(struct irq_data *data) static void nwl_unmask_leg_irq(struct irq_data *data) { - struct irq_desc *desc = irq_to_desc(data->irq); - struct nwl_pcie *pcie; + struct nwl_pcie *pcie = irq_data_get_irq_chip_data(data); unsigned long flags; u32 mask; u32 val; - pcie = irq_desc_get_chip_data(desc); - mask = 1 << (data->hwirq - 1); + mask = 1 << data->hwirq; raw_spin_lock_irqsave(&pcie->leg_mask_lock, flags); val = nwl_bridge_readl(pcie, MSGF_LEG_MASK); nwl_bridge_writel(pcie, (val | mask), MSGF_LEG_MASK); diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c index 646807a443e2..742debe347ee 100644 --- a/drivers/pci/quirks.c +++ b/drivers/pci/quirks.c @@ -3453,6 +3453,8 @@ DECLARE_PCI_FIXUP_FINAL(0x1814, 0x0601, /* Ralink RT2800 802.11n PCI */ quirk_broken_intx_masking); DECLARE_PCI_FIXUP_FINAL(0x1b7c, 0x0004, /* Ceton InfiniTV4 */ quirk_broken_intx_masking); +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_CREATIVE, PCI_DEVICE_ID_CREATIVE_20K2, + quirk_broken_intx_masking); /* * Realtek RTL8169 PCI Gigabit Ethernet Controller (rev 10) @@ -4091,6 +4093,10 @@ static void quirk_dma_func0_alias(struct pci_dev *dev) DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_RICOH, 0xe832, quirk_dma_func0_alias); DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_RICOH, 0xe476, quirk_dma_func0_alias); +/* Some Glenfly chips use function 0 as the PCIe Requester ID for DMA */ +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_GLENFLY, 0x3d40, quirk_dma_func0_alias); +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_GLENFLY, 0x3d41, quirk_dma_func0_alias); + static void quirk_dma_func1_alias(struct pci_dev *dev) { if (PCI_FUNC(dev->devfn) != 1) @@ -4915,6 +4921,8 @@ static const struct pci_dev_acs_enabled { /* QCOM QDF2xxx root ports */ { PCI_VENDOR_ID_QCOM, 0x0400, pci_quirk_qcom_rp_acs }, { PCI_VENDOR_ID_QCOM, 0x0401, pci_quirk_qcom_rp_acs }, + /* QCOM SA8775P root port */ + { PCI_VENDOR_ID_QCOM, 0x0115, pci_quirk_qcom_rp_acs }, /* HXT SD4800 root ports. The ACS design is same as QCOM QDF2xxx */ { PCI_VENDOR_ID_HXT, 0x0401, pci_quirk_qcom_rp_acs }, /* Intel PCH root ports */ diff --git a/drivers/pinctrl/mvebu/pinctrl-dove.c b/drivers/pinctrl/mvebu/pinctrl-dove.c index 545486d98532..c84326dfe371 100644 --- a/drivers/pinctrl/mvebu/pinctrl-dove.c +++ b/drivers/pinctrl/mvebu/pinctrl-dove.c @@ -769,7 +769,7 @@ static int dove_pinctrl_probe(struct platform_device *pdev) of_match_device(dove_pinctrl_of_match, &pdev->dev); struct mvebu_mpp_ctrl_data *mpp_data; void __iomem *base; - int i; + int i, ret; pdev->dev.platform_data = (void *)match->data; @@ -784,15 +784,18 @@ static int dove_pinctrl_probe(struct platform_device *pdev) } clk_prepare_enable(clk); - mpp_res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - base = devm_ioremap_resource(&pdev->dev, mpp_res); - if (IS_ERR(base)) - return PTR_ERR(base); + base = devm_platform_get_and_ioremap_resource(pdev, 0, &mpp_res); + if (IS_ERR(base)) { + ret = PTR_ERR(base); + goto err_probe; + } mpp_data = devm_kcalloc(&pdev->dev, dove_pinctrl_info.ncontrols, sizeof(*mpp_data), GFP_KERNEL); - if (!mpp_data) - return -ENOMEM; + if (!mpp_data) { + ret = -ENOMEM; + goto err_probe; + } dove_pinctrl_info.control_data = mpp_data; for (i = 0; i < ARRAY_SIZE(dove_mpp_controls); i++) @@ -811,8 +814,10 @@ static int dove_pinctrl_probe(struct platform_device *pdev) } mpp4_base = devm_ioremap_resource(&pdev->dev, res); - if (IS_ERR(mpp4_base)) - return PTR_ERR(mpp4_base); + if (IS_ERR(mpp4_base)) { + ret = PTR_ERR(mpp4_base); + goto err_probe; + } res = platform_get_resource(pdev, IORESOURCE_MEM, 2); if (!res) { @@ -823,8 +828,10 @@ static int dove_pinctrl_probe(struct platform_device *pdev) } pmu_base = devm_ioremap_resource(&pdev->dev, res); - if (IS_ERR(pmu_base)) - return PTR_ERR(pmu_base); + if (IS_ERR(pmu_base)) { + ret = PTR_ERR(pmu_base); + goto err_probe; + } gconfmap = syscon_regmap_lookup_by_compatible("marvell,dove-global-config"); if (IS_ERR(gconfmap)) { @@ -834,12 +841,17 @@ static int dove_pinctrl_probe(struct platform_device *pdev) adjust_resource(&fb_res, (mpp_res->start & INT_REGS_MASK) + GC_REGS_OFFS, 0x14); gc_base = devm_ioremap_resource(&pdev->dev, &fb_res); - if (IS_ERR(gc_base)) - return PTR_ERR(gc_base); + if (IS_ERR(gc_base)) { + ret = PTR_ERR(gc_base); + goto err_probe; + } + gconfmap = devm_regmap_init_mmio(&pdev->dev, gc_base, &gc_regmap_config); - if (IS_ERR(gconfmap)) - return PTR_ERR(gconfmap); + if (IS_ERR(gconfmap)) { + ret = PTR_ERR(gconfmap); + goto err_probe; + } } /* Warn on any missing DT resource */ @@ -847,6 +859,9 @@ static int dove_pinctrl_probe(struct platform_device *pdev) dev_warn(&pdev->dev, FW_BUG "Missing pinctrl regs in DTB. Please update your firmware.\n"); return mvebu_pinctrl_probe(pdev); +err_probe: + clk_disable_unprepare(clk); + return ret; } static struct platform_driver dove_pinctrl_driver = { diff --git a/drivers/pinctrl/pinctrl-at91.c b/drivers/pinctrl/pinctrl-at91.c index 52ecd47c18e2..bb9348f14b1b 100644 --- a/drivers/pinctrl/pinctrl-at91.c +++ b/drivers/pinctrl/pinctrl-at91.c @@ -1401,8 +1401,11 @@ static int at91_pinctrl_probe(struct platform_device *pdev) /* We will handle a range of GPIO pins */ for (i = 0; i < gpio_banks; i++) - if (gpio_chips[i]) + if (gpio_chips[i]) { pinctrl_add_gpio_range(info->pctl, &gpio_chips[i]->range); + gpiochip_add_pin_range(&gpio_chips[i]->chip, dev_name(info->pctl->dev), 0, + gpio_chips[i]->range.pin_base, gpio_chips[i]->range.npins); + } dev_info(&pdev->dev, "initialized AT91 pinctrl driver\n"); diff --git a/drivers/pinctrl/pinctrl-single.c b/drivers/pinctrl/pinctrl-single.c index 5b76594b535c..22fd7ebd5cf3 100644 --- a/drivers/pinctrl/pinctrl-single.c +++ b/drivers/pinctrl/pinctrl-single.c @@ -1923,7 +1923,8 @@ static int pcs_probe(struct platform_device *pdev) dev_info(pcs->dev, "%i pins, size %u\n", pcs->desc.npins, pcs->size); - if (pinctrl_enable(pcs->pctl)) + ret = pinctrl_enable(pcs->pctl); + if (ret) goto free; return 0; diff --git a/drivers/platform/x86/touchscreen_dmi.c b/drivers/platform/x86/touchscreen_dmi.c index dce2d26b1d0f..eff29dc7e2c6 100644 --- a/drivers/platform/x86/touchscreen_dmi.c +++ b/drivers/platform/x86/touchscreen_dmi.c @@ -840,6 +840,21 @@ static const struct ts_dmi_data rwc_nanote_p8_data = { .properties = rwc_nanote_p8_props, }; +static const struct property_entry rwc_nanote_next_props[] = { + PROPERTY_ENTRY_U32("touchscreen-min-x", 5), + PROPERTY_ENTRY_U32("touchscreen-min-y", 5), + PROPERTY_ENTRY_U32("touchscreen-size-x", 1785), + PROPERTY_ENTRY_U32("touchscreen-size-y", 1145), + PROPERTY_ENTRY_BOOL("touchscreen-inverted-y"), + PROPERTY_ENTRY_STRING("firmware-name", "gsl1680-rwc-nanote-next.fw"), + { } +}; + +static const struct ts_dmi_data rwc_nanote_next_data = { + .acpi_name = "MSSL1680:00", + .properties = rwc_nanote_next_props, +}; + static const struct property_entry schneider_sct101ctm_props[] = { PROPERTY_ENTRY_U32("touchscreen-size-x", 1715), PROPERTY_ENTRY_U32("touchscreen-size-y", 1140), @@ -1509,6 +1524,17 @@ const struct dmi_system_id touchscreen_dmi_table[] = { DMI_MATCH(DMI_PRODUCT_SKU, "0001") }, }, + { + /* RWC NANOTE NEXT */ + .driver_data = (void *)&rwc_nanote_next_data, + .matches = { + DMI_MATCH(DMI_PRODUCT_NAME, "To be filled by O.E.M."), + DMI_MATCH(DMI_BOARD_NAME, "To be filled by O.E.M."), + DMI_MATCH(DMI_BOARD_VENDOR, "To be filled by O.E.M."), + /* Above matches are too generic, add bios-version match */ + DMI_MATCH(DMI_BIOS_VERSION, "S8A70R100-V005"), + }, + }, { /* Schneider SCT101CTM */ .driver_data = (void *)&schneider_sct101ctm_data, diff --git a/drivers/power/reset/brcmstb-reboot.c b/drivers/power/reset/brcmstb-reboot.c index 884b53c483c0..9f8b9e5cad93 100644 --- a/drivers/power/reset/brcmstb-reboot.c +++ b/drivers/power/reset/brcmstb-reboot.c @@ -72,9 +72,6 @@ static int brcmstb_restart_handler(struct notifier_block *this, return NOTIFY_DONE; } - while (1) - ; - return NOTIFY_DONE; } diff --git a/drivers/power/supply/axp20x_battery.c b/drivers/power/supply/axp20x_battery.c index 9fda98b950ba..d62a249f65da 100644 --- a/drivers/power/supply/axp20x_battery.c +++ b/drivers/power/supply/axp20x_battery.c @@ -40,6 +40,7 @@ #define AXP209_FG_PERCENT GENMASK(6, 0) #define AXP22X_FG_VALID BIT(7) +#define AXP20X_CHRG_CTRL1_ENABLE BIT(7) #define AXP20X_CHRG_CTRL1_TGT_VOLT GENMASK(6, 5) #define AXP20X_CHRG_CTRL1_TGT_4_1V (0 << 5) #define AXP20X_CHRG_CTRL1_TGT_4_15V (1 << 5) @@ -303,11 +304,11 @@ static int axp20x_battery_get_prop(struct power_supply *psy, val->intval = reg & AXP209_FG_PERCENT; break; - case POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN: + case POWER_SUPPLY_PROP_VOLTAGE_MAX: return axp20x_batt->data->get_max_voltage(axp20x_batt, &val->intval); - case POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN: + case POWER_SUPPLY_PROP_VOLTAGE_MIN: ret = regmap_read(axp20x_batt->regmap, AXP20X_V_OFF, ®); if (ret) return ret; @@ -455,10 +456,10 @@ static int axp20x_battery_set_prop(struct power_supply *psy, struct axp20x_batt_ps *axp20x_batt = power_supply_get_drvdata(psy); switch (psp) { - case POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN: + case POWER_SUPPLY_PROP_VOLTAGE_MIN: return axp20x_set_voltage_min_design(axp20x_batt, val->intval); - case POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN: + case POWER_SUPPLY_PROP_VOLTAGE_MAX: return axp20x_batt->data->set_max_voltage(axp20x_batt, val->intval); case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT: @@ -467,7 +468,18 @@ static int axp20x_battery_set_prop(struct power_supply *psy, case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX: return axp20x_set_max_constant_charge_current(axp20x_batt, val->intval); + case POWER_SUPPLY_PROP_STATUS: + switch (val->intval) { + case POWER_SUPPLY_STATUS_CHARGING: + return regmap_update_bits(axp20x_batt->regmap, AXP20X_CHRG_CTRL1, + AXP20X_CHRG_CTRL1_ENABLE, AXP20X_CHRG_CTRL1_ENABLE); + case POWER_SUPPLY_STATUS_DISCHARGING: + case POWER_SUPPLY_STATUS_NOT_CHARGING: + return regmap_update_bits(axp20x_batt->regmap, AXP20X_CHRG_CTRL1, + AXP20X_CHRG_CTRL1_ENABLE, 0); + } + fallthrough; default: return -EINVAL; } @@ -482,16 +494,17 @@ static enum power_supply_property axp20x_battery_props[] = { POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT, POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX, POWER_SUPPLY_PROP_HEALTH, - POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN, - POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN, + POWER_SUPPLY_PROP_VOLTAGE_MAX, + POWER_SUPPLY_PROP_VOLTAGE_MIN, POWER_SUPPLY_PROP_CAPACITY, }; static int axp20x_battery_prop_writeable(struct power_supply *psy, enum power_supply_property psp) { - return psp == POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN || - psp == POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN || + return psp == POWER_SUPPLY_PROP_STATUS || + psp == POWER_SUPPLY_PROP_VOLTAGE_MIN || + psp == POWER_SUPPLY_PROP_VOLTAGE_MAX || psp == POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT || psp == POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX; } diff --git a/drivers/power/supply/max17042_battery.c b/drivers/power/supply/max17042_battery.c index 76b0f45a20b4..b68bf3a35465 100644 --- a/drivers/power/supply/max17042_battery.c +++ b/drivers/power/supply/max17042_battery.c @@ -851,7 +851,10 @@ static void max17042_set_soc_threshold(struct max17042_chip *chip, u16 off) /* program interrupt thesholds such that we should * get interrupt for every 'off' perc change in the soc */ - regmap_read(map, MAX17042_RepSOC, &soc); + if (chip->pdata->enable_current_sense) + regmap_read(map, MAX17042_RepSOC, &soc); + else + regmap_read(map, MAX17042_VFSOC, &soc); soc >>= 8; soc_tr = (soc + off) << 8; if (off < soc) diff --git a/drivers/powercap/intel_rapl_msr.c b/drivers/powercap/intel_rapl_msr.c index 6b68e5ed2081..17692b234f42 100644 --- a/drivers/powercap/intel_rapl_msr.c +++ b/drivers/powercap/intel_rapl_msr.c @@ -126,7 +126,7 @@ static int rapl_msr_write_raw(int cpu, struct reg_action *ra) /* List of verified CPUs. */ static const struct x86_cpu_id pl4_support_ids[] = { - { X86_VENDOR_INTEL, 6, INTEL_FAM6_TIGERLAKE_L, X86_FEATURE_ANY }, + X86_MATCH_INTEL_FAM6_MODEL(TIGERLAKE_L, NULL), {} }; diff --git a/drivers/pps/clients/pps_parport.c b/drivers/pps/clients/pps_parport.c index 7a41fb7b0dec..84e49204912f 100644 --- a/drivers/pps/clients/pps_parport.c +++ b/drivers/pps/clients/pps_parport.c @@ -144,7 +144,10 @@ static void parport_attach(struct parport *port) return; } - index = ida_simple_get(&pps_client_index, 0, 0, GFP_KERNEL); + index = ida_alloc(&pps_client_index, GFP_KERNEL); + if (index < 0) + goto err_free_device; + memset(&pps_client_cb, 0, sizeof(pps_client_cb)); pps_client_cb.private = device; pps_client_cb.irq_func = parport_irq; @@ -155,7 +158,7 @@ static void parport_attach(struct parport *port) index); if (!device->pardev) { pr_err("couldn't register with %s\n", port->name); - goto err_free; + goto err_free_ida; } if (parport_claim_or_block(device->pardev) < 0) { @@ -183,8 +186,9 @@ static void parport_attach(struct parport *port) parport_release(device->pardev); err_unregister_dev: parport_unregister_device(device->pardev); -err_free: - ida_simple_remove(&pps_client_index, index); +err_free_ida: + ida_free(&pps_client_index, index); +err_free_device: kfree(device); } @@ -204,7 +208,7 @@ static void parport_detach(struct parport *port) pps_unregister_source(device->pps); parport_release(pardev); parport_unregister_device(pardev); - ida_simple_remove(&pps_client_index, device->index); + ida_free(&pps_client_index, device->index); kfree(device); } diff --git a/drivers/reset/reset-berlin.c b/drivers/reset/reset-berlin.c index 371197bbd055..542d32719b8a 100644 --- a/drivers/reset/reset-berlin.c +++ b/drivers/reset/reset-berlin.c @@ -68,13 +68,14 @@ static int berlin_reset_xlate(struct reset_controller_dev *rcdev, static int berlin2_reset_probe(struct platform_device *pdev) { - struct device_node *parent_np = of_get_parent(pdev->dev.of_node); + struct device_node *parent_np; struct berlin_reset_priv *priv; priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); if (!priv) return -ENOMEM; + parent_np = of_get_parent(pdev->dev.of_node); priv->regmap = syscon_node_to_regmap(parent_np); of_node_put(parent_np); if (IS_ERR(priv->regmap)) diff --git a/drivers/rtc/rtc-at91sam9.c b/drivers/rtc/rtc-at91sam9.c index e39e89867d29..881d750d0900 100644 --- a/drivers/rtc/rtc-at91sam9.c +++ b/drivers/rtc/rtc-at91sam9.c @@ -368,6 +368,7 @@ static int at91_rtc_probe(struct platform_device *pdev) return ret; rtc->gpbr = syscon_node_to_regmap(args.np); + of_node_put(args.np); rtc->gpbr_offset = args.args[0]; if (IS_ERR(rtc->gpbr)) { dev_err(&pdev->dev, "failed to retrieve gpbr regmap, aborting.\n"); diff --git a/drivers/s390/char/sclp_vt220.c b/drivers/s390/char/sclp_vt220.c index 3c2ed6d01387..d574c167c9dc 100644 --- a/drivers/s390/char/sclp_vt220.c +++ b/drivers/s390/char/sclp_vt220.c @@ -325,7 +325,7 @@ sclp_vt220_add_msg(struct sclp_vt220_request *request, buffer = (void *) ((addr_t) sccb + sccb->header.length); if (convertlf) { - /* Perform Linefeed conversion (0x0a -> 0x0a 0x0d)*/ + /* Perform Linefeed conversion (0x0a -> 0x0d 0x0a)*/ for (from=0, to=0; (from < count) && (to < sclp_vt220_space_left(request)); from++) { @@ -334,8 +334,8 @@ sclp_vt220_add_msg(struct sclp_vt220_request *request, /* Perform conversion */ if (c == 0x0a) { if (to + 1 < sclp_vt220_space_left(request)) { - ((unsigned char *) buffer)[to++] = c; ((unsigned char *) buffer)[to++] = 0x0d; + ((unsigned char *) buffer)[to++] = c; } else break; diff --git a/drivers/s390/char/zcore.c b/drivers/s390/char/zcore.c index 3841c0e77df6..1aee6b2ae66f 100644 --- a/drivers/s390/char/zcore.c +++ b/drivers/s390/char/zcore.c @@ -15,6 +15,7 @@ #include #include #include +#include #include #include @@ -247,6 +248,28 @@ static int __init zcore_reipl_init(void) return 0; } +static int zcore_reboot_and_on_panic_handler(struct notifier_block *self, + unsigned long event, + void *data) +{ + if (hsa_available) + release_hsa(); + + return NOTIFY_OK; +} + +static struct notifier_block zcore_reboot_notifier = { + .notifier_call = zcore_reboot_and_on_panic_handler, + /* we need to be notified before reipl and kdump */ + .priority = INT_MAX, +}; + +static struct notifier_block zcore_on_panic_notifier = { + .notifier_call = zcore_reboot_and_on_panic_handler, + /* we need to be notified before reipl and kdump */ + .priority = INT_MAX, +}; + static int __init zcore_init(void) { unsigned char arch; @@ -302,28 +325,15 @@ static int __init zcore_init(void) goto fail; zcore_dir = debugfs_create_dir("zcore" , NULL); - if (!zcore_dir) { - rc = -ENOMEM; - goto fail; - } zcore_reipl_file = debugfs_create_file("reipl", S_IRUSR, zcore_dir, NULL, &zcore_reipl_fops); - if (!zcore_reipl_file) { - rc = -ENOMEM; - goto fail_dir; - } zcore_hsa_file = debugfs_create_file("hsa", S_IRUSR|S_IWUSR, zcore_dir, NULL, &zcore_hsa_fops); - if (!zcore_hsa_file) { - rc = -ENOMEM; - goto fail_reipl_file; - } - return 0; -fail_reipl_file: - debugfs_remove(zcore_reipl_file); -fail_dir: - debugfs_remove(zcore_dir); + register_reboot_notifier(&zcore_reboot_notifier); + atomic_notifier_chain_register(&panic_notifier_list, &zcore_on_panic_notifier); + + return 0; fail: diag308(DIAG308_REL_HSA, NULL); return rc; diff --git a/drivers/scsi/aacraid/aacraid.h b/drivers/scsi/aacraid/aacraid.h index e3e4ecbea726..76c88610c6d7 100644 --- a/drivers/scsi/aacraid/aacraid.h +++ b/drivers/scsi/aacraid/aacraid.h @@ -2028,8 +2028,8 @@ struct aac_srb_reply }; struct aac_srb_unit { - struct aac_srb srb; struct aac_srb_reply srb_reply; + struct aac_srb srb; }; /* diff --git a/drivers/soc/versatile/soc-integrator.c b/drivers/soc/versatile/soc-integrator.c index bab4ad87aa75..d5099a3386b4 100644 --- a/drivers/soc/versatile/soc-integrator.c +++ b/drivers/soc/versatile/soc-integrator.c @@ -113,6 +113,7 @@ static int __init integrator_soc_init(void) return -ENODEV; syscon_regmap = syscon_node_to_regmap(np); + of_node_put(np); if (IS_ERR(syscon_regmap)) return PTR_ERR(syscon_regmap); diff --git a/drivers/soc/versatile/soc-realview.c b/drivers/soc/versatile/soc-realview.c index c6876d232d8f..cf91abe07d38 100644 --- a/drivers/soc/versatile/soc-realview.c +++ b/drivers/soc/versatile/soc-realview.c @@ -4,6 +4,7 @@ * * Author: Linus Walleij */ +#include #include #include #include @@ -81,6 +82,13 @@ static struct attribute *realview_attrs[] = { ATTRIBUTE_GROUPS(realview); +static void realview_soc_socdev_release(void *data) +{ + struct soc_device *soc_dev = data; + + soc_device_unregister(soc_dev); +} + static int realview_soc_probe(struct platform_device *pdev) { struct regmap *syscon_regmap; @@ -93,7 +101,7 @@ static int realview_soc_probe(struct platform_device *pdev) if (IS_ERR(syscon_regmap)) return PTR_ERR(syscon_regmap); - soc_dev_attr = kzalloc(sizeof(*soc_dev_attr), GFP_KERNEL); + soc_dev_attr = devm_kzalloc(&pdev->dev, sizeof(*soc_dev_attr), GFP_KERNEL); if (!soc_dev_attr) return -ENOMEM; @@ -106,10 +114,14 @@ static int realview_soc_probe(struct platform_device *pdev) soc_dev_attr->family = "Versatile"; soc_dev_attr->custom_attr_group = realview_groups[0]; soc_dev = soc_device_register(soc_dev_attr); - if (IS_ERR(soc_dev)) { - kfree(soc_dev_attr); + if (IS_ERR(soc_dev)) return -ENODEV; - } + + ret = devm_add_action_or_reset(&pdev->dev, realview_soc_socdev_release, + soc_dev); + if (ret) + return ret; + ret = regmap_read(syscon_regmap, REALVIEW_SYS_ID_OFFSET, &realview_coreid); if (ret) diff --git a/drivers/soundwire/stream.c b/drivers/soundwire/stream.c index 29922a811d14..2741bc016738 100644 --- a/drivers/soundwire/stream.c +++ b/drivers/soundwire/stream.c @@ -1425,18 +1425,18 @@ struct sdw_dpn_prop *sdw_get_slave_dpn_prop(struct sdw_slave *slave, unsigned int port_num) { struct sdw_dpn_prop *dpn_prop; - unsigned long mask; + u8 num_ports; int i; if (direction == SDW_DATA_DIR_TX) { - mask = slave->prop.source_ports; + num_ports = hweight32(slave->prop.source_ports); dpn_prop = slave->prop.src_dpn_prop; } else { - mask = slave->prop.sink_ports; + num_ports = hweight32(slave->prop.sink_ports); dpn_prop = slave->prop.sink_dpn_prop; } - for_each_set_bit(i, &mask, 32) { + for (i = 0; i < num_ports; i++) { if (dpn_prop[i].num == port_num) return &dpn_prop[i]; } diff --git a/drivers/spi/spi-bcm63xx.c b/drivers/spi/spi-bcm63xx.c index d36384fef0d7..b31b5f4e959e 100644 --- a/drivers/spi/spi-bcm63xx.c +++ b/drivers/spi/spi-bcm63xx.c @@ -476,12 +476,14 @@ static const struct platform_device_id bcm63xx_spi_dev_match[] = { { }, }; +MODULE_DEVICE_TABLE(platform, bcm63xx_spi_dev_match); static const struct of_device_id bcm63xx_spi_of_match[] = { { .compatible = "brcm,bcm6348-spi", .data = &bcm6348_spi_reg_offsets }, { .compatible = "brcm,bcm6358-spi", .data = &bcm6358_spi_reg_offsets }, { }, }; +MODULE_DEVICE_TABLE(of, bcm63xx_spi_of_match); static int bcm63xx_spi_probe(struct platform_device *pdev) { diff --git a/drivers/spi/spi-fsl-lpspi.c b/drivers/spi/spi-fsl-lpspi.c index c21d7959dcd2..8ab3105ae8c0 100644 --- a/drivers/spi/spi-fsl-lpspi.c +++ b/drivers/spi/spi-fsl-lpspi.c @@ -919,8 +919,8 @@ static int fsl_lpspi_probe(struct platform_device *pdev) ret = devm_spi_register_controller(&pdev->dev, controller); if (ret < 0) { - dev_err(&pdev->dev, "spi_register_controller error.\n"); - goto out_pm_get; + dev_err_probe(&pdev->dev, ret, "spi_register_controller error\n"); + goto free_dma; } pm_runtime_mark_last_busy(fsl_lpspi->dev); @@ -928,6 +928,8 @@ static int fsl_lpspi_probe(struct platform_device *pdev) return 0; +free_dma: + fsl_lpspi_dma_exit(controller); out_pm_get: pm_runtime_dont_use_autosuspend(fsl_lpspi->dev); pm_runtime_put_sync(fsl_lpspi->dev); @@ -944,6 +946,9 @@ static int fsl_lpspi_remove(struct platform_device *pdev) struct fsl_lpspi_data *fsl_lpspi = spi_controller_get_devdata(controller); + fsl_lpspi_dma_exit(controller); + + pm_runtime_dont_use_autosuspend(fsl_lpspi->dev); pm_runtime_disable(fsl_lpspi->dev); return 0; } diff --git a/drivers/spi/spi-imx.c b/drivers/spi/spi-imx.c index 8566da12d15e..f1a0073a8700 100644 --- a/drivers/spi/spi-imx.c +++ b/drivers/spi/spi-imx.c @@ -1756,8 +1756,8 @@ static int spi_imx_probe(struct platform_device *pdev) spi_imx_sdma_exit(spi_imx); out_runtime_pm_put: pm_runtime_dont_use_autosuspend(spi_imx->dev); - pm_runtime_set_suspended(&pdev->dev); pm_runtime_disable(spi_imx->dev); + pm_runtime_set_suspended(&pdev->dev); clk_disable_unprepare(spi_imx->clk_ipg); out_put_per: diff --git a/drivers/spi/spi-nxp-fspi.c b/drivers/spi/spi-nxp-fspi.c index f40b93960b89..d5c62c6e03d3 100644 --- a/drivers/spi/spi-nxp-fspi.c +++ b/drivers/spi/spi-nxp-fspi.c @@ -731,14 +731,15 @@ static void nxp_fspi_fill_txfifo(struct nxp_fspi *f, if (i < op->data.nbytes) { u32 data = 0; int j; + int remaining = op->data.nbytes - i; /* Wait for TXFIFO empty */ ret = fspi_readl_poll_tout(f, f->iobase + FSPI_INTR, FSPI_INTR_IPTXWE, 0, POLL_TOUT, true); WARN_ON(ret); - for (j = 0; j < ALIGN(op->data.nbytes - i, 4); j += 4) { - memcpy(&data, buf + i + j, 4); + for (j = 0; j < ALIGN(remaining, 4); j += 4) { + memcpy(&data, buf + i + j, min_t(int, 4, remaining - j)); fspi_writel(f, data, base + FSPI_TFDR + j); } fspi_writel(f, FSPI_INTR_IPTXWE, base + FSPI_INTR); diff --git a/drivers/spi/spi-ppc4xx.c b/drivers/spi/spi-ppc4xx.c index 4200b12fc347..6413bcd28913 100644 --- a/drivers/spi/spi-ppc4xx.c +++ b/drivers/spi/spi-ppc4xx.c @@ -26,7 +26,6 @@ #include #include #include -#include #include #include #include @@ -410,7 +409,11 @@ static int spi_ppc4xx_of_probe(struct platform_device *op) } /* Request IRQ */ - hw->irqnum = irq_of_parse_and_map(np, 0); + ret = platform_get_irq(op, 0); + if (ret < 0) + goto free_host; + hw->irqnum = ret; + ret = request_irq(hw->irqnum, spi_ppc4xx_int, 0, "spi_ppc4xx_of", (void *)hw); if (ret) { diff --git a/drivers/spi/spi-s3c64xx.c b/drivers/spi/spi-s3c64xx.c index d435df1b715b..7beea6f93093 100644 --- a/drivers/spi/spi-s3c64xx.c +++ b/drivers/spi/spi-s3c64xx.c @@ -215,7 +215,7 @@ static void s3c64xx_flush_fifo(struct s3c64xx_spi_driver_data *sdd) loops = msecs_to_loops(1); do { val = readl(regs + S3C64XX_SPI_STATUS); - } while (TX_FIFO_LVL(val, sdd) && loops--); + } while (TX_FIFO_LVL(val, sdd) && --loops); if (loops == 0) dev_warn(&sdd->pdev->dev, "Timed out flushing TX FIFO\n"); @@ -228,7 +228,7 @@ static void s3c64xx_flush_fifo(struct s3c64xx_spi_driver_data *sdd) readl(regs + S3C64XX_SPI_RX_DATA); else break; - } while (loops--); + } while (--loops); if (loops == 0) dev_warn(&sdd->pdev->dev, "Timed out flushing RX FIFO\n"); diff --git a/drivers/staging/media/atomisp/pci/sh_css_frac.h b/drivers/staging/media/atomisp/pci/sh_css_frac.h index 8f08df5c88cc..569a2f59e551 100644 --- a/drivers/staging/media/atomisp/pci/sh_css_frac.h +++ b/drivers/staging/media/atomisp/pci/sh_css_frac.h @@ -30,12 +30,24 @@ #define uISP_VAL_MAX ((unsigned int)((1 << uISP_REG_BIT) - 1)) /* a:fraction bits for 16bit precision, b:fraction bits for ISP precision */ -#define sDIGIT_FITTING(v, a, b) \ - min_t(int, max_t(int, (((v) >> sSHIFT) >> max(sFRACTION_BITS_FITTING(a) - (b), 0)), \ - sISP_VAL_MIN), sISP_VAL_MAX) -#define uDIGIT_FITTING(v, a, b) \ - min((unsigned int)max((unsigned)(((v) >> uSHIFT) \ - >> max((int)(uFRACTION_BITS_FITTING(a) - (b)), 0)), \ - uISP_VAL_MIN), uISP_VAL_MAX) +static inline int sDIGIT_FITTING(int v, int a, int b) +{ + int fit_shift = sFRACTION_BITS_FITTING(a) - b; + + v >>= sSHIFT; + v >>= fit_shift > 0 ? fit_shift : 0; + + return clamp_t(int, v, sISP_VAL_MIN, sISP_VAL_MAX); +} + +static inline unsigned int uDIGIT_FITTING(unsigned int v, int a, int b) +{ + int fit_shift = uFRACTION_BITS_FITTING(a) - b; + + v >>= uSHIFT; + v >>= fit_shift > 0 ? fit_shift : 0; + + return clamp_t(unsigned int, v, uISP_VAL_MIN, uISP_VAL_MAX); +} #endif /* __SH_CSS_FRAC_H */ diff --git a/drivers/target/target_core_device.c b/drivers/target/target_core_device.c index daa4d06ce233..50135f8df1b4 100644 --- a/drivers/target/target_core_device.c +++ b/drivers/target/target_core_device.c @@ -727,7 +727,7 @@ struct se_device *target_alloc_device(struct se_hba *hba, const char *name) dev->queues = kcalloc(nr_cpu_ids, sizeof(*dev->queues), GFP_KERNEL); if (!dev->queues) { - dev->transport->free_device(dev); + hba->backend->ops->free_device(dev); return NULL; } diff --git a/drivers/tty/serial/rp2.c b/drivers/tty/serial/rp2.c index 944a4c010579..a8d3fbde5b0e 100644 --- a/drivers/tty/serial/rp2.c +++ b/drivers/tty/serial/rp2.c @@ -600,8 +600,8 @@ static void rp2_reset_asic(struct rp2_card *card, unsigned int asic_id) u32 clk_cfg; writew(1, base + RP2_GLOBAL_CMD); - readw(base + RP2_GLOBAL_CMD); msleep(100); + readw(base + RP2_GLOBAL_CMD); writel(0, base + RP2_CLK_PRESCALER); /* TDM clock configuration */ diff --git a/drivers/usb/chipidea/udc.c b/drivers/usb/chipidea/udc.c index 67d8da04848e..5cdf03534c0c 100644 --- a/drivers/usb/chipidea/udc.c +++ b/drivers/usb/chipidea/udc.c @@ -83,7 +83,7 @@ static int hw_device_state(struct ci_hdrc *ci, u32 dma) hw_write(ci, OP_ENDPTLISTADDR, ~0, dma); /* interrupt, error, port change, reset, sleep/suspend */ hw_write(ci, OP_USBINTR, ~0, - USBi_UI|USBi_UEI|USBi_PCI|USBi_URI|USBi_SLI); + USBi_UI|USBi_UEI|USBi_PCI|USBi_URI); } else { hw_write(ci, OP_USBINTR, ~0, 0); } @@ -862,6 +862,7 @@ __releases(ci->lock) __acquires(ci->lock) { int retval; + u32 intr; spin_unlock(&ci->lock); if (ci->gadget.speed != USB_SPEED_UNKNOWN) @@ -875,6 +876,11 @@ __acquires(ci->lock) if (retval) goto done; + /* clear SLI */ + hw_write(ci, OP_USBSTS, USBi_SLI, USBi_SLI); + intr = hw_read(ci, OP_USBINTR, ~0); + hw_write(ci, OP_USBINTR, ~0, intr | USBi_SLI); + ci->status = usb_ep_alloc_request(&ci->ep0in->ep, GFP_ATOMIC); if (ci->status == NULL) retval = -ENOMEM; diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c index c494b77e6749..59154e808ea5 100644 --- a/drivers/usb/class/cdc-acm.c +++ b/drivers/usb/class/cdc-acm.c @@ -942,10 +942,12 @@ static int get_serial_info(struct tty_struct *tty, struct serial_struct *ss) struct acm *acm = tty->driver_data; ss->line = acm->minor; + mutex_lock(&acm->port.mutex); ss->close_delay = jiffies_to_msecs(acm->port.close_delay) / 10; ss->closing_wait = acm->port.closing_wait == ASYNC_CLOSING_WAIT_NONE ? ASYNC_CLOSING_WAIT_NONE : jiffies_to_msecs(acm->port.closing_wait) / 10; + mutex_unlock(&acm->port.mutex); return 0; } diff --git a/drivers/usb/class/usbtmc.c b/drivers/usb/class/usbtmc.c index 76ff182427bc..78adc112a77b 100644 --- a/drivers/usb/class/usbtmc.c +++ b/drivers/usb/class/usbtmc.c @@ -724,7 +724,7 @@ static struct urb *usbtmc_create_urb(void) if (!urb) return NULL; - dmabuf = kmalloc(bufsize, GFP_KERNEL); + dmabuf = kzalloc(bufsize, GFP_KERNEL); if (!dmabuf) { usb_free_urb(urb); return NULL; diff --git a/drivers/usb/dwc2/platform.c b/drivers/usb/dwc2/platform.c index 9d0dd09a2015..f421650cfa03 100644 --- a/drivers/usb/dwc2/platform.c +++ b/drivers/usb/dwc2/platform.c @@ -441,18 +441,6 @@ static int dwc2_driver_probe(struct platform_device *dev) spin_lock_init(&hsotg->lock); - hsotg->irq = platform_get_irq(dev, 0); - if (hsotg->irq < 0) - return hsotg->irq; - - dev_dbg(hsotg->dev, "registering common handler for irq%d\n", - hsotg->irq); - retval = devm_request_irq(hsotg->dev, hsotg->irq, - dwc2_handle_common_intr, IRQF_SHARED, - dev_name(hsotg->dev), hsotg); - if (retval) - return retval; - hsotg->vbus_supply = devm_regulator_get_optional(hsotg->dev, "vbus"); if (IS_ERR(hsotg->vbus_supply)) { retval = PTR_ERR(hsotg->vbus_supply); @@ -496,6 +484,20 @@ static int dwc2_driver_probe(struct platform_device *dev) if (retval) goto error; + hsotg->irq = platform_get_irq(dev, 0); + if (hsotg->irq < 0) { + retval = hsotg->irq; + goto error; + } + + dev_dbg(hsotg->dev, "registering common handler for irq%d\n", + hsotg->irq); + retval = devm_request_irq(hsotg->dev, hsotg->irq, + dwc2_handle_common_intr, IRQF_SHARED, + dev_name(hsotg->dev), hsotg); + if (retval) + goto error; + /* * For OTG cores, set the force mode bits to reflect the value * of dr_mode. Force mode bits should not be touched at any diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c index 7cdc2bca8971..88d0ae3ccf27 100644 --- a/drivers/usb/dwc3/core.c +++ b/drivers/usb/dwc3/core.c @@ -458,6 +458,7 @@ static int dwc3_alloc_event_buffers(struct dwc3 *dwc, unsigned length) int dwc3_event_buffers_setup(struct dwc3 *dwc) { struct dwc3_event_buffer *evt; + u32 reg; if (!dwc->ev_buf) return 0; @@ -470,8 +471,10 @@ int dwc3_event_buffers_setup(struct dwc3 *dwc) upper_32_bits(evt->dma)); dwc3_writel(dwc->regs, DWC3_GEVNTSIZ(0), DWC3_GEVNTSIZ_SIZE(evt->length)); - dwc3_writel(dwc->regs, DWC3_GEVNTCOUNT(0), 0); + /* Clear any stale event */ + reg = dwc3_readl(dwc->regs, DWC3_GEVNTCOUNT(0)); + dwc3_writel(dwc->regs, DWC3_GEVNTCOUNT(0), reg); return 0; } @@ -498,7 +501,10 @@ void dwc3_event_buffers_cleanup(struct dwc3 *dwc) dwc3_writel(dwc->regs, DWC3_GEVNTADRHI(0), 0); dwc3_writel(dwc->regs, DWC3_GEVNTSIZ(0), DWC3_GEVNTSIZ_INTMASK | DWC3_GEVNTSIZ_SIZE(0)); - dwc3_writel(dwc->regs, DWC3_GEVNTCOUNT(0), 0); + + /* Clear any stale event */ + reg = dwc3_readl(dwc->regs, DWC3_GEVNTCOUNT(0)); + dwc3_writel(dwc->regs, DWC3_GEVNTCOUNT(0), reg); } static int dwc3_alloc_scratch_buffers(struct dwc3 *dwc) @@ -1936,7 +1942,11 @@ static int dwc3_runtime_resume(struct device *dev) switch (dwc->current_dr_role) { case DWC3_GCTL_PRTCAP_DEVICE: - dwc3_gadget_process_pending_events(dwc); + if (dwc->pending_events) { + pm_runtime_put(dwc->dev); + dwc->pending_events = false; + enable_irq(dwc->irq_gadget); + } break; case DWC3_GCTL_PRTCAP_HOST: default: @@ -2023,6 +2033,12 @@ static void dwc3_complete(struct device *dev) static const struct dev_pm_ops dwc3_dev_pm_ops = { SET_SYSTEM_SLEEP_PM_OPS(dwc3_suspend, dwc3_resume) .complete = dwc3_complete, + + /* + * Runtime suspend halts the controller on disconnection. It relies on + * platforms with custom connection notification to start the controller + * again. + */ SET_RUNTIME_PM_OPS(dwc3_runtime_suspend, dwc3_runtime_resume, dwc3_runtime_idle) }; diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h index 1afdf157e46e..0dc2d6474d51 100644 --- a/drivers/usb/dwc3/core.h +++ b/drivers/usb/dwc3/core.h @@ -1621,7 +1621,6 @@ static inline void dwc3_otg_host_init(struct dwc3 *dwc) #if !IS_ENABLED(CONFIG_USB_DWC3_HOST) int dwc3_gadget_suspend(struct dwc3 *dwc); int dwc3_gadget_resume(struct dwc3 *dwc); -void dwc3_gadget_process_pending_events(struct dwc3 *dwc); #else static inline int dwc3_gadget_suspend(struct dwc3 *dwc) { @@ -1633,9 +1632,6 @@ static inline int dwc3_gadget_resume(struct dwc3 *dwc) return 0; } -static inline void dwc3_gadget_process_pending_events(struct dwc3 *dwc) -{ -} #endif /* !IS_ENABLED(CONFIG_USB_DWC3_HOST) */ #if IS_ENABLED(CONFIG_USB_DWC3_ULPI) diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index b04704da3912..f8287a6a1b00 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -4641,14 +4641,3 @@ int dwc3_gadget_resume(struct dwc3 *dwc) err0: return ret; } - -void dwc3_gadget_process_pending_events(struct dwc3 *dwc) -{ - if (dwc->pending_events) { - dwc3_interrupt(dwc->irq_gadget, dwc->ev_buf); - dwc3_thread_interrupt(dwc->irq_gadget, dwc->ev_buf); - pm_runtime_put(dwc->dev); - dwc->pending_events = false; - enable_irq(dwc->irq_gadget); - } -} diff --git a/drivers/usb/host/xhci-pci-renesas.c b/drivers/usb/host/xhci-pci-renesas.c index 96692dbbd4da..01ad6fc1adca 100644 --- a/drivers/usb/host/xhci-pci-renesas.c +++ b/drivers/usb/host/xhci-pci-renesas.c @@ -631,9 +631,4 @@ int renesas_xhci_check_request_fw(struct pci_dev *pdev, } EXPORT_SYMBOL_GPL(renesas_xhci_check_request_fw); -void renesas_xhci_pci_exit(struct pci_dev *dev) -{ -} -EXPORT_SYMBOL_GPL(renesas_xhci_pci_exit); - MODULE_LICENSE("GPL v2"); diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c index cf744d7ba1c2..51879b897e2a 100644 --- a/drivers/usb/host/xhci-pci.c +++ b/drivers/usb/host/xhci-pci.c @@ -71,6 +71,7 @@ #define PCI_DEVICE_ID_ASMEDIA_1042A_XHCI 0x1142 #define PCI_DEVICE_ID_ASMEDIA_1142_XHCI 0x1242 #define PCI_DEVICE_ID_ASMEDIA_2142_XHCI 0x2142 +#define PCI_DEVICE_ID_ASMEDIA_3042_XHCI 0x3042 #define PCI_DEVICE_ID_ASMEDIA_3242_XHCI 0x3242 static const char hcd_name[] = "xhci_hcd"; @@ -321,6 +322,10 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci) pdev->device == PCI_DEVICE_ID_ASMEDIA_1042A_XHCI) xhci->quirks |= XHCI_ASMEDIA_MODIFY_FLOWCONTROL; + if (pdev->vendor == PCI_VENDOR_ID_ASMEDIA && + pdev->device == PCI_DEVICE_ID_ASMEDIA_3042_XHCI) + xhci->quirks |= XHCI_RESET_ON_RESUME; + if (pdev->vendor == PCI_VENDOR_ID_TI && pdev->device == 0x8241) xhci->quirks |= XHCI_LIMIT_ENDPOINT_INTERVAL_7; @@ -488,10 +493,10 @@ static int xhci_pci_probe(struct pci_dev *dev, const struct pci_device_id *id) static void xhci_pci_remove(struct pci_dev *dev) { struct xhci_hcd *xhci; + bool set_power_d3; xhci = hcd_to_xhci(pci_get_drvdata(dev)); - if (xhci->quirks & XHCI_RENESAS_FW_QUIRK) - renesas_xhci_pci_exit(dev); + set_power_d3 = xhci->quirks & XHCI_SPURIOUS_WAKEUP; xhci->xhc_state |= XHCI_STATE_REMOVING; @@ -504,11 +509,11 @@ static void xhci_pci_remove(struct pci_dev *dev) xhci->shared_hcd = NULL; } - /* Workaround for spurious wakeups at shutdown with HSW */ - if (xhci->quirks & XHCI_SPURIOUS_WAKEUP) - pci_set_power_state(dev, PCI_D3hot); - usb_hcd_pci_remove(dev); + + /* Workaround for spurious wakeups at shutdown with HSW */ + if (set_power_d3) + pci_set_power_state(dev, PCI_D3hot); } #ifdef CONFIG_PM diff --git a/drivers/usb/host/xhci-pci.h b/drivers/usb/host/xhci-pci.h index acd7cf0a1706..cb9a8f331a44 100644 --- a/drivers/usb/host/xhci-pci.h +++ b/drivers/usb/host/xhci-pci.h @@ -7,7 +7,6 @@ #if IS_ENABLED(CONFIG_USB_XHCI_PCI_RENESAS) int renesas_xhci_check_request_fw(struct pci_dev *dev, const struct pci_device_id *id); -void renesas_xhci_pci_exit(struct pci_dev *dev); #else static int renesas_xhci_check_request_fw(struct pci_dev *dev, @@ -16,8 +15,6 @@ static int renesas_xhci_check_request_fw(struct pci_dev *dev, return 0; } -static void renesas_xhci_pci_exit(struct pci_dev *dev) { }; - #endif struct xhci_driver_data { diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h index 7fa99116dab5..934c9b75ae30 100644 --- a/drivers/usb/host/xhci.h +++ b/drivers/usb/host/xhci.h @@ -1285,7 +1285,7 @@ enum xhci_setup_dev { /* Set TR Dequeue Pointer command TRB fields, 6.4.3.9 */ #define TRB_TO_STREAM_ID(p) ((((p) & (0xffff << 16)) >> 16)) #define STREAM_ID_FOR_TRB(p) ((((p)) & 0xffff) << 16) -#define SCT_FOR_TRB(p) (((p) << 1) & 0x7) +#define SCT_FOR_TRB(p) (((p) & 0x7) << 1) /* Link TRB specific fields */ #define TRB_TC (1<<1) diff --git a/drivers/usb/misc/appledisplay.c b/drivers/usb/misc/appledisplay.c index c8098e9b432e..62b5a30edc42 100644 --- a/drivers/usb/misc/appledisplay.c +++ b/drivers/usb/misc/appledisplay.c @@ -107,7 +107,12 @@ static void appledisplay_complete(struct urb *urb) case ACD_BTN_BRIGHT_UP: case ACD_BTN_BRIGHT_DOWN: pdata->button_pressed = 1; - schedule_delayed_work(&pdata->work, 0); + /* + * there is a window during which no device + * is registered + */ + if (pdata->bd ) + schedule_delayed_work(&pdata->work, 0); break; case ACD_BTN_NONE: default: @@ -202,6 +207,7 @@ static int appledisplay_probe(struct usb_interface *iface, const struct usb_device_id *id) { struct backlight_properties props; + struct backlight_device *backlight; struct appledisplay *pdata; struct usb_device *udev = interface_to_usbdev(iface); struct usb_endpoint_descriptor *endpoint; @@ -272,13 +278,14 @@ static int appledisplay_probe(struct usb_interface *iface, memset(&props, 0, sizeof(struct backlight_properties)); props.type = BACKLIGHT_RAW; props.max_brightness = 0xff; - pdata->bd = backlight_device_register(bl_name, NULL, pdata, + backlight = backlight_device_register(bl_name, NULL, pdata, &appledisplay_bl_data, &props); - if (IS_ERR(pdata->bd)) { + if (IS_ERR(backlight)) { dev_err(&iface->dev, "Backlight registration failed\n"); - retval = PTR_ERR(pdata->bd); + retval = PTR_ERR(backlight); goto error; } + pdata->bd = backlight; /* Try to get brightness */ brightness = appledisplay_bl_get_brightness(pdata->bd); diff --git a/drivers/usb/misc/cypress_cy7c63.c b/drivers/usb/misc/cypress_cy7c63.c index 14faec51d7a5..3be5551a9867 100644 --- a/drivers/usb/misc/cypress_cy7c63.c +++ b/drivers/usb/misc/cypress_cy7c63.c @@ -88,6 +88,9 @@ static int vendor_command(struct cypress *dev, unsigned char request, USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_OTHER, address, data, iobuf, CYPRESS_MAX_REQSIZE, USB_CTRL_GET_TIMEOUT); + /* we must not process garbage */ + if (retval < 2) + goto err_buf; /* store returned data (more READs to be added) */ switch (request) { @@ -107,6 +110,7 @@ static int vendor_command(struct cypress *dev, unsigned char request, break; } +err_buf: kfree(iobuf); error: return retval; diff --git a/drivers/usb/misc/yurex.c b/drivers/usb/misc/yurex.c index 6c3d760bd4dd..8bc7c683bf83 100644 --- a/drivers/usb/misc/yurex.c +++ b/drivers/usb/misc/yurex.c @@ -506,8 +506,11 @@ static ssize_t yurex_write(struct file *file, const char __user *user_buffer, __func__, retval); goto error; } - if (set && timeout) + if (set && timeout) { + spin_lock_irq(&dev->lock); dev->bbu = c2; + spin_unlock_irq(&dev->lock); + } return timeout ? count : -EIO; error: diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c index c9fade980f36..a71e072722da 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c @@ -279,6 +279,7 @@ static void option_instat_callback(struct urb *urb); #define QUECTEL_PRODUCT_EG912Y 0x6001 #define QUECTEL_PRODUCT_EC200S_CN 0x6002 #define QUECTEL_PRODUCT_EC200A 0x6005 +#define QUECTEL_PRODUCT_EG916Q 0x6007 #define QUECTEL_PRODUCT_EM061K_LWW 0x6008 #define QUECTEL_PRODUCT_EM061K_LCN 0x6009 #define QUECTEL_PRODUCT_EC200T 0x6026 @@ -1270,6 +1271,7 @@ static const struct usb_device_id option_ids[] = { { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EC200S_CN, 0xff, 0, 0) }, { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EC200T, 0xff, 0, 0) }, { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EG912Y, 0xff, 0, 0) }, + { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EG916Q, 0xff, 0x00, 0x00) }, { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_RM500K, 0xff, 0x00, 0x00) }, { USB_DEVICE(CMOTECH_VENDOR_ID, CMOTECH_PRODUCT_6001) }, @@ -1380,10 +1382,16 @@ static const struct usb_device_id option_ids[] = { .driver_info = NCTRL(0) | RSVD(1) }, { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x10a0, 0xff), /* Telit FN20C04 (rmnet) */ .driver_info = RSVD(0) | NCTRL(3) }, + { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x10a2, 0xff), /* Telit FN920C04 (MBIM) */ + .driver_info = NCTRL(4) }, { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x10a4, 0xff), /* Telit FN20C04 (rmnet) */ .driver_info = RSVD(0) | NCTRL(3) }, + { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x10a7, 0xff), /* Telit FN920C04 (MBIM) */ + .driver_info = NCTRL(4) }, { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x10a9, 0xff), /* Telit FN20C04 (rmnet) */ .driver_info = RSVD(0) | NCTRL(2) | RSVD(3) | RSVD(4) }, + { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x10aa, 0xff), /* Telit FN920C04 (MBIM) */ + .driver_info = NCTRL(3) | RSVD(4) | RSVD(5) }, { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_ME910), .driver_info = NCTRL(0) | RSVD(1) | RSVD(3) }, { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_ME910_DUAL_MODEM), diff --git a/drivers/usb/serial/pl2303.c b/drivers/usb/serial/pl2303.c index 16118d9f2392..e45d8f873f46 100644 --- a/drivers/usb/serial/pl2303.c +++ b/drivers/usb/serial/pl2303.c @@ -118,6 +118,7 @@ static const struct usb_device_id id_table[] = { { USB_DEVICE(SMART_VENDOR_ID, SMART_PRODUCT_ID) }, { USB_DEVICE(AT_VENDOR_ID, AT_VTKIT3_PRODUCT_ID) }, { USB_DEVICE(IBM_VENDOR_ID, IBM_PRODUCT_ID) }, + { USB_DEVICE(MACROSILICON_VENDOR_ID, MACROSILICON_MS3020_PRODUCT_ID) }, { } /* Terminating entry */ }; diff --git a/drivers/usb/serial/pl2303.h b/drivers/usb/serial/pl2303.h index 732f9b13ad5d..d60eda7f6eda 100644 --- a/drivers/usb/serial/pl2303.h +++ b/drivers/usb/serial/pl2303.h @@ -171,3 +171,7 @@ /* Allied Telesis VT-Kit3 */ #define AT_VENDOR_ID 0x0caa #define AT_VTKIT3_PRODUCT_ID 0x3001 + +/* Macrosilicon MS3020 */ +#define MACROSILICON_VENDOR_ID 0x345f +#define MACROSILICON_MS3020_PRODUCT_ID 0x3020 diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h index 20dcbccb290b..41c76566d751 100644 --- a/drivers/usb/storage/unusual_devs.h +++ b/drivers/usb/storage/unusual_devs.h @@ -2412,6 +2412,17 @@ UNUSUAL_DEV( 0xc251, 0x4003, 0x0100, 0x0100, USB_SC_DEVICE, USB_PR_DEVICE, NULL, US_FL_NOT_LOCKABLE), +/* + * Reported by Icenowy Zheng + * This is an interface for vendor-specific cryptic commands instead + * of real USB storage device. + */ +UNUSUAL_DEV( 0xe5b7, 0x0811, 0x0100, 0x0100, + "ZhuHai JieLi Technology", + "JieLi BR21", + USB_SC_DEVICE, USB_PR_DEVICE, NULL, + US_FL_IGNORE_DEVICE), + /* Reported by Andrew Simmons */ UNUSUAL_DEV( 0xed06, 0x4500, 0x0001, 0x0001, "DataStor", diff --git a/drivers/usb/typec/class.c b/drivers/usb/typec/class.c index b41b6ebaca94..b34f516d614c 100644 --- a/drivers/usb/typec/class.c +++ b/drivers/usb/typec/class.c @@ -561,6 +561,7 @@ static void typec_altmode_release(struct device *dev) typec_altmode_put_partner(alt); altmode_id_remove(alt->adev.dev.parent, alt->id); + put_device(alt->adev.dev.parent); kfree(alt); } @@ -610,6 +611,8 @@ typec_register_altmode(struct device *parent, alt->adev.dev.type = &typec_altmode_dev_type; dev_set_name(&alt->adev.dev, "%s.%u", dev_name(parent), id); + get_device(alt->adev.dev.parent); + /* Link partners and plugs with the ports */ if (!is_port) typec_altmode_set_partner(alt); diff --git a/drivers/vhost/scsi.c b/drivers/vhost/scsi.c index 4ce9f00ae10e..a23a65e7d828 100644 --- a/drivers/vhost/scsi.c +++ b/drivers/vhost/scsi.c @@ -919,20 +919,23 @@ vhost_scsi_get_req(struct vhost_virtqueue *vq, struct vhost_scsi_ctx *vc, /* virtio-scsi spec requires byte 0 of the lun to be 1 */ vq_err(vq, "Illegal virtio-scsi lun: %u\n", *vc->lunp); } else { - struct vhost_scsi_tpg **vs_tpg, *tpg; + struct vhost_scsi_tpg **vs_tpg, *tpg = NULL; - vs_tpg = vhost_vq_get_backend(vq); /* validated at handler entry */ - - tpg = READ_ONCE(vs_tpg[*vc->target]); - if (unlikely(!tpg)) { - vq_err(vq, "Target 0x%x does not exist\n", *vc->target); - } else { - if (tpgp) - *tpgp = tpg; - ret = 0; + if (vc->target) { + /* validated at handler entry */ + vs_tpg = vhost_vq_get_backend(vq); + tpg = READ_ONCE(vs_tpg[*vc->target]); + if (unlikely(!tpg)) { + vq_err(vq, "Target 0x%x does not exist\n", *vc->target); + goto out; + } } - } + if (tpgp) + *tpgp = tpg; + ret = 0; + } +out: return ret; } diff --git a/drivers/vhost/vdpa.c b/drivers/vhost/vdpa.c index c9f585db1553..61d11e7317ac 100644 --- a/drivers/vhost/vdpa.c +++ b/drivers/vhost/vdpa.c @@ -100,11 +100,9 @@ static void vhost_vdpa_setup_vq_irq(struct vhost_vdpa *v, u16 qid) if (irq < 0) return; - irq_bypass_unregister_producer(&vq->call_ctx.producer); if (!vq->call_ctx.ctx) return; - vq->call_ctx.producer.token = vq->call_ctx.ctx; vq->call_ctx.producer.irq = irq; ret = irq_bypass_register_producer(&vq->call_ctx.producer); if (unlikely(ret)) @@ -397,6 +395,14 @@ static long vhost_vdpa_vring_ioctl(struct vhost_vdpa *v, unsigned int cmd, vq->last_avail_idx = vq_state.avail_index; break; + case VHOST_SET_VRING_CALL: + if (vq->call_ctx.ctx) { + if (ops->get_status(vdpa) & + VIRTIO_CONFIG_S_DRIVER_OK) + vhost_vdpa_unsetup_vq_irq(v, idx); + vq->call_ctx.producer.token = NULL; + } + break; } r = vhost_vring_ioctl(&v->vdev, cmd, argp); @@ -422,12 +428,17 @@ static long vhost_vdpa_vring_ioctl(struct vhost_vdpa *v, unsigned int cmd, if (vq->call_ctx.ctx) { cb.callback = vhost_vdpa_virtqueue_cb; cb.private = vq; + cb.trigger = vq->call_ctx.ctx; + vq->call_ctx.producer.token = vq->call_ctx.ctx; + if (ops->get_status(vdpa) & + VIRTIO_CONFIG_S_DRIVER_OK) + vhost_vdpa_setup_vq_irq(v, idx); } else { cb.callback = NULL; cb.private = NULL; + cb.trigger = NULL; } ops->set_vq_cb(vdpa, idx, &cb); - vhost_vdpa_setup_vq_irq(v, idx); break; case VHOST_SET_VRING_NUM: @@ -888,6 +899,7 @@ static int vhost_vdpa_open(struct inode *inode, struct file *filep) for (i = 0; i < nvqs; i++) { vqs[i] = &v->vqs[i]; vqs[i]->handle_kick = handle_vq_kick; + vqs[i]->call_ctx.ctx = NULL; } vhost_dev_init(dev, vqs, nvqs, 0, 0, 0, false, vhost_vdpa_process_iotlb_msg); diff --git a/drivers/video/fbdev/hpfb.c b/drivers/video/fbdev/hpfb.c index 8d418abdd767..1e9c52e2714d 100644 --- a/drivers/video/fbdev/hpfb.c +++ b/drivers/video/fbdev/hpfb.c @@ -344,6 +344,7 @@ static int hpfb_dio_probe(struct dio_dev *d, const struct dio_device_id *ent) if (hpfb_init_one(paddr, vaddr)) { if (d->scode >= DIOII_SCBASE) iounmap((void *)vaddr); + release_mem_region(d->resource.start, resource_size(&d->resource)); return -ENOMEM; } return 0; diff --git a/drivers/video/fbdev/pxafb.c b/drivers/video/fbdev/pxafb.c index f1551e00eb12..a0db2b3d0736 100644 --- a/drivers/video/fbdev/pxafb.c +++ b/drivers/video/fbdev/pxafb.c @@ -2408,6 +2408,7 @@ static int pxafb_remove(struct platform_device *dev) info = &fbi->fb; pxafb_overlay_exit(fbi); + cancel_work_sync(&fbi->task); unregister_framebuffer(info); pxafb_disable_controller(fbi); diff --git a/drivers/video/fbdev/sis/sis_main.c b/drivers/video/fbdev/sis/sis_main.c index e540cb0c5172..7787fd21932c 100644 --- a/drivers/video/fbdev/sis/sis_main.c +++ b/drivers/video/fbdev/sis/sis_main.c @@ -183,7 +183,7 @@ static void sisfb_search_mode(char *name, bool quiet) { unsigned int j = 0, xres = 0, yres = 0, depth = 0, rate = 0; int i = 0; - char strbuf[16], strbuf1[20]; + char strbuf[24], strbuf1[20]; char *nameptr = name; /* We don't know the hardware specs yet and there is no ivideo */ diff --git a/drivers/virtio/virtio_vdpa.c b/drivers/virtio/virtio_vdpa.c index 3f95dedccceb..7b2c37a3880f 100644 --- a/drivers/virtio/virtio_vdpa.c +++ b/drivers/virtio/virtio_vdpa.c @@ -180,6 +180,7 @@ virtio_vdpa_setup_vq(struct virtio_device *vdev, unsigned int index, /* Setup virtqueue callback */ cb.callback = virtio_vdpa_virtqueue_cb; cb.private = info; + cb.trigger = NULL; ops->set_vq_cb(vdpa, index, &cb); ops->set_vq_num(vdpa, index, virtqueue_get_vring_size(vq)); diff --git a/drivers/watchdog/imx_sc_wdt.c b/drivers/watchdog/imx_sc_wdt.c index 8ac021748d16..79649b0e89e4 100644 --- a/drivers/watchdog/imx_sc_wdt.c +++ b/drivers/watchdog/imx_sc_wdt.c @@ -213,29 +213,6 @@ static int imx_sc_wdt_probe(struct platform_device *pdev) return devm_watchdog_register_device(dev, wdog); } -static int __maybe_unused imx_sc_wdt_suspend(struct device *dev) -{ - struct imx_sc_wdt_device *imx_sc_wdd = dev_get_drvdata(dev); - - if (watchdog_active(&imx_sc_wdd->wdd)) - imx_sc_wdt_stop(&imx_sc_wdd->wdd); - - return 0; -} - -static int __maybe_unused imx_sc_wdt_resume(struct device *dev) -{ - struct imx_sc_wdt_device *imx_sc_wdd = dev_get_drvdata(dev); - - if (watchdog_active(&imx_sc_wdd->wdd)) - imx_sc_wdt_start(&imx_sc_wdd->wdd); - - return 0; -} - -static SIMPLE_DEV_PM_OPS(imx_sc_wdt_pm_ops, - imx_sc_wdt_suspend, imx_sc_wdt_resume); - static const struct of_device_id imx_sc_wdt_dt_ids[] = { { .compatible = "fsl,imx-sc-wdt", }, { /* sentinel */ } @@ -247,7 +224,6 @@ static struct platform_driver imx_sc_wdt_driver = { .driver = { .name = "imx-sc-wdt", .of_match_table = imx_sc_wdt_dt_ids, - .pm = &imx_sc_wdt_pm_ops, }, }; module_platform_driver(imx_sc_wdt_driver); diff --git a/drivers/xen/swiotlb-xen.c b/drivers/xen/swiotlb-xen.c index ad3ee4857e15..000d02ea4f7d 100644 --- a/drivers/xen/swiotlb-xen.c +++ b/drivers/xen/swiotlb-xen.c @@ -91,9 +91,15 @@ static inline int range_straddles_page_boundary(phys_addr_t p, size_t size) { unsigned long next_bfn, xen_pfn = XEN_PFN_DOWN(p); unsigned int i, nr_pages = XEN_PFN_UP(xen_offset_in_page(p) + size); + phys_addr_t algn = 1ULL << (get_order(size) + PAGE_SHIFT); next_bfn = pfn_to_bfn(xen_pfn); + /* If buffer is physically aligned, ensure DMA alignment. */ + if (IS_ALIGNED(p, algn) && + !IS_ALIGNED((phys_addr_t)next_bfn << XEN_PAGE_SHIFT, algn)) + return 1; + for (i = 1; i < nr_pages; i++) if (pfn_to_bfn(++xen_pfn) != ++next_bfn) return 1; diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c index c484c145c5d0..104c86784796 100644 --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c @@ -4131,6 +4131,17 @@ void __cold close_ctree(struct btrfs_fs_info *fs_info) /* clear out the rbtree of defraggable inodes */ btrfs_cleanup_defrag_inodes(fs_info); + /* + * Wait for any fixup workers to complete. + * If we don't wait for them here and they are still running by the time + * we call kthread_stop() against the cleaner kthread further below, we + * get an use-after-free on the cleaner because the fixup worker adds an + * inode to the list of delayed iputs and then attempts to wakeup the + * cleaner kthread, which was already stopped and destroyed. We parked + * already the cleaner, but below we run all pending delayed iputs. + */ + btrfs_flush_workqueue(fs_info->fixup_workers); + /* * After we parked the cleaner kthread, ordered extents may have * completed and created new delayed iputs. If one of the async reclaim diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index cd3156a9a268..24598acb9a31 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c @@ -3704,6 +3704,7 @@ static int __btrfs_unlink_inode(struct btrfs_trans_handle *trans, btrfs_i_size_write(dir, dir->vfs_inode.i_size - name_len * 2); inode_inc_iversion(&inode->vfs_inode); + inode_set_ctime_current(&inode->vfs_inode); inode_inc_iversion(&dir->vfs_inode); inode->vfs_inode.i_ctime = dir->vfs_inode.i_mtime = dir->vfs_inode.i_ctime = current_time(&inode->vfs_inode); diff --git a/fs/btrfs/relocation.c b/fs/btrfs/relocation.c index 93db4486a943..cdd16583b2ff 100644 --- a/fs/btrfs/relocation.c +++ b/fs/btrfs/relocation.c @@ -910,7 +910,7 @@ int btrfs_update_reloc_root(struct btrfs_trans_handle *trans, btrfs_grab_root(reloc_root); /* root->reloc_root will stay until current relocation finished */ - if (fs_info->reloc_ctl->merge_reloc_tree && + if (fs_info->reloc_ctl && fs_info->reloc_ctl->merge_reloc_tree && btrfs_root_refs(root_item) == 0) { set_bit(BTRFS_ROOT_DEAD_RELOC_TREE, &root->state); /* diff --git a/fs/ceph/addr.c b/fs/ceph/addr.c index 3465ff95cb89..2362f2591f4a 100644 --- a/fs/ceph/addr.c +++ b/fs/ceph/addr.c @@ -91,7 +91,6 @@ static int ceph_set_page_dirty(struct page *page) /* dirty the head */ spin_lock(&ci->i_ceph_lock); - BUG_ON(ci->i_wr_ref == 0); // caller should hold Fw reference if (__ceph_have_pending_cap_snap(ci)) { struct ceph_cap_snap *capsnap = list_last_entry(&ci->i_cap_snaps, diff --git a/fs/cifs/smb2pdu.c b/fs/cifs/smb2pdu.c index aa3211d8cce3..03651cc6b7a5 100644 --- a/fs/cifs/smb2pdu.c +++ b/fs/cifs/smb2pdu.c @@ -2961,6 +2961,15 @@ SMB2_ioctl_init(struct cifs_tcon *tcon, struct TCP_Server_Info *server, return rc; if (indatalen) { + unsigned int len; + + if (WARN_ON_ONCE(smb3_encryption_required(tcon) && + (check_add_overflow(total_len - 1, + ALIGN(indatalen, 8), &len) || + len > MAX_CIFS_SMALL_BUFFER_SIZE))) { + cifs_small_buf_release(req); + return -EIO; + } /* * indatalen is usually small at a couple of bytes max, so * just allocate through generic pool diff --git a/fs/direct-io.c b/fs/direct-io.c index b4bf6bb10dd8..8dd15277f05d 100644 --- a/fs/direct-io.c +++ b/fs/direct-io.c @@ -39,6 +39,9 @@ #include #include #include +#ifndef __GENKSYMS__ +#include +#endif #include "internal.h" @@ -1070,6 +1073,11 @@ static int do_direct_IO(struct dio *dio, struct dio_submit *sdio, put_page(page); goto out; } + trace_android_vh_io_statistics(dio->inode->i_mapping, + sdio->block_in_file >> sdio->blkfactor, + this_chunk_blocks >> sdio->blkfactor, + iov_iter_rw(sdio->iter) == READ, true); + sdio->next_block_for_io += this_chunk_blocks; sdio->block_in_file += this_chunk_blocks; diff --git a/fs/exec.c b/fs/exec.c index dbcd3143be57..4cbc211e9049 100644 --- a/fs/exec.c +++ b/fs/exec.c @@ -146,13 +146,11 @@ SYSCALL_DEFINE1(uselib, const char __user *, library) goto out; /* - * may_open() has already checked for this, so it should be - * impossible to trip now. But we need to be extra cautious - * and check again at the very end too. + * Check do_open_execat() for an explanation. */ error = -EACCES; - if (WARN_ON_ONCE(!S_ISREG(file_inode(file)->i_mode) || - path_noexec(&file->f_path))) + if (WARN_ON_ONCE(!S_ISREG(file_inode(file)->i_mode)) || + path_noexec(&file->f_path)) goto exit; fsnotify_open(file); @@ -768,7 +766,8 @@ int setup_arg_pages(struct linux_binprm *bprm, stack_base = STACK_SIZE_MAX; /* Add space for stack randomization. */ - stack_base += (STACK_RND_MASK << PAGE_SHIFT); + if (current->flags & PF_RANDOMIZE) + stack_base += (STACK_RND_MASK << PAGE_SHIFT); /* Make sure we didn't let the argument array grow too large. */ if (vma->vm_end - vma->vm_start > stack_base) @@ -920,16 +919,16 @@ static struct file *do_open_execat(int fd, struct filename *name, int flags) file = do_filp_open(fd, name, &open_exec_flags); if (IS_ERR(file)) - goto out; + return file; /* - * may_open() has already checked for this, so it should be - * impossible to trip now. But we need to be extra cautious - * and check again at the very end too. + * In the past the regular type check was here. It moved to may_open() in + * 633fb6ac3980 ("exec: move S_ISREG() check earlier"). Since then it is + * an invariant that all non-regular files error out before we get here. */ err = -EACCES; - if (WARN_ON_ONCE(!S_ISREG(file_inode(file)->i_mode) || - path_noexec(&file->f_path))) + if (WARN_ON_ONCE(!S_ISREG(file_inode(file)->i_mode)) || + path_noexec(&file->f_path)) goto exit; err = deny_write_access(file); @@ -939,7 +938,6 @@ static struct file *do_open_execat(int fd, struct filename *name, int flags) if (name->name[0] != '\0') fsnotify_open(file); -out: return file; exit: diff --git a/fs/exfat/balloc.c b/fs/exfat/balloc.c index 132943a863a4..01afab05e4a0 100644 --- a/fs/exfat/balloc.c +++ b/fs/exfat/balloc.c @@ -110,11 +110,8 @@ int exfat_load_bitmap(struct super_block *sb) return -EIO; type = exfat_get_entry_type(ep); - if (type == TYPE_UNUSED) - break; - if (type != TYPE_BITMAP) - continue; - if (ep->dentry.bitmap.flags == 0x0) { + if (type == TYPE_BITMAP && + ep->dentry.bitmap.flags == 0x0) { int err; err = exfat_allocate_bitmap(sb, ep); @@ -122,6 +119,9 @@ int exfat_load_bitmap(struct super_block *sb) return err; } brelse(bh); + + if (type == TYPE_UNUSED) + return -EINVAL; } if (exfat_get_next_cluster(sb, &clu.dir)) diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c index f5fa9d542d64..ffdc68b11c01 100644 --- a/fs/ext4/extents.c +++ b/fs/ext4/extents.c @@ -949,6 +949,8 @@ ext4_find_extent(struct inode *inode, ext4_lblk_t block, ext4_ext_show_path(inode, path); + if (orig_path) + *orig_path = path; return path; err: @@ -1867,6 +1869,7 @@ static void ext4_ext_try_to_merge_up(handle_t *handle, path[0].p_hdr->eh_max = cpu_to_le16(max_root); brelse(path[1].p_bh); + path[1].p_bh = NULL; ext4_free_blocks(handle, inode, NULL, blk, 1, EXT4_FREE_BLOCKS_METADATA | EXT4_FREE_BLOCKS_FORGET); } @@ -2095,6 +2098,7 @@ int ext4_ext_insert_extent(handle_t *handle, struct inode *inode, ppath, newext); if (err) goto cleanup; + path = *ppath; depth = ext_depth(inode); eh = path[depth].p_hdr; @@ -3223,9 +3227,27 @@ static int ext4_split_extent_at(handle_t *handle, ext4_ext_mark_unwritten(ex2); err = ext4_ext_insert_extent(handle, inode, ppath, &newex, flags); - if (err != -ENOSPC && err != -EDQUOT) + if (err != -ENOSPC && err != -EDQUOT && err != -ENOMEM) goto out; + /* + * Update path is required because previous ext4_ext_insert_extent() + * may have freed or reallocated the path. Using EXT4_EX_NOFAIL + * guarantees that ext4_find_extent() will not return -ENOMEM, + * otherwise -ENOMEM will cause a retry in do_writepages(), and a + * WARN_ON may be triggered in ext4_da_update_reserve_space() due to + * an incorrect ee_len causing the i_reserved_data_blocks exception. + */ + path = ext4_find_extent(inode, ee_block, ppath, + flags | EXT4_EX_NOFAIL); + if (IS_ERR(path)) { + EXT4_ERROR_INODE(inode, "Failed split extent on %u, err %ld", + split, PTR_ERR(path)); + return PTR_ERR(path); + } + depth = ext_depth(inode); + ex = path[depth].p_ext; + if (EXT4_EXT_MAY_ZEROOUT & split_flag) { if (split_flag & (EXT4_EXT_DATA_VALID1|EXT4_EXT_DATA_VALID2)) { if (split_flag & EXT4_EXT_DATA_VALID1) { @@ -3278,12 +3300,12 @@ static int ext4_split_extent_at(handle_t *handle, ext4_ext_dirty(handle, inode, path + path->p_depth); return err; out: - ext4_ext_show_leaf(inode, path); + ext4_ext_show_leaf(inode, *ppath); return err; } /* - * ext4_split_extents() splits an extent and mark extent which is covered + * ext4_split_extent() splits an extent and mark extent which is covered * by @map as split_flags indicates * * It may result in splitting the extent into multiple extents (up to three) @@ -3360,7 +3382,7 @@ static int ext4_split_extent(handle_t *handle, goto out; } - ext4_ext_show_leaf(inode, path); + ext4_ext_show_leaf(inode, *ppath); out: return err ? err : allocated; } @@ -3825,14 +3847,13 @@ ext4_ext_handle_unwritten_extents(handle_t *handle, struct inode *inode, struct ext4_ext_path **ppath, int flags, unsigned int allocated, ext4_fsblk_t newblock) { - struct ext4_ext_path __maybe_unused *path = *ppath; int ret = 0; int err = 0; ext_debug(inode, "logical block %llu, max_blocks %u, flags 0x%x, allocated %u\n", (unsigned long long)map->m_lblk, map->m_len, flags, allocated); - ext4_ext_show_leaf(inode, path); + ext4_ext_show_leaf(inode, *ppath); /* * When writing into unwritten space, we should not fail to @@ -3929,7 +3950,7 @@ ext4_ext_handle_unwritten_extents(handle_t *handle, struct inode *inode, if (allocated > map->m_len) allocated = map->m_len; map->m_len = allocated; - ext4_ext_show_leaf(inode, path); + ext4_ext_show_leaf(inode, *ppath); out2: return err ? err : allocated; } @@ -5548,6 +5569,7 @@ static int ext4_insert_range(struct file *file, loff_t offset, loff_t len) path = ext4_find_extent(inode, offset_lblk, NULL, 0); if (IS_ERR(path)) { up_write(&EXT4_I(inode)->i_data_sem); + ret = PTR_ERR(path); goto out_stop; } @@ -5909,7 +5931,7 @@ int ext4_clu_mapped(struct inode *inode, ext4_lblk_t lclu) int ext4_ext_replay_update_ex(struct inode *inode, ext4_lblk_t start, int len, int unwritten, ext4_fsblk_t pblk) { - struct ext4_ext_path *path = NULL, *ppath; + struct ext4_ext_path *path; struct ext4_extent *ex; int ret; @@ -5925,30 +5947,29 @@ int ext4_ext_replay_update_ex(struct inode *inode, ext4_lblk_t start, if (le32_to_cpu(ex->ee_block) != start || ext4_ext_get_actual_len(ex) != len) { /* We need to split this extent to match our extent first */ - ppath = path; down_write(&EXT4_I(inode)->i_data_sem); - ret = ext4_force_split_extent_at(NULL, inode, &ppath, start, 1); + ret = ext4_force_split_extent_at(NULL, inode, &path, start, 1); up_write(&EXT4_I(inode)->i_data_sem); if (ret) goto out; - kfree(path); - path = ext4_find_extent(inode, start, NULL, 0); + + path = ext4_find_extent(inode, start, &path, 0); if (IS_ERR(path)) - return -1; - ppath = path; + return PTR_ERR(path); ex = path[path->p_depth].p_ext; WARN_ON(le32_to_cpu(ex->ee_block) != start); + if (ext4_ext_get_actual_len(ex) != len) { down_write(&EXT4_I(inode)->i_data_sem); - ret = ext4_force_split_extent_at(NULL, inode, &ppath, + ret = ext4_force_split_extent_at(NULL, inode, &path, start + len, 1); up_write(&EXT4_I(inode)->i_data_sem); if (ret) goto out; - kfree(path); - path = ext4_find_extent(inode, start, NULL, 0); + + path = ext4_find_extent(inode, start, &path, 0); if (IS_ERR(path)) - return -EINVAL; + return PTR_ERR(path); ex = path[path->p_depth].p_ext; } } diff --git a/fs/ext4/ialloc.c b/fs/ext4/ialloc.c index d6c4ea4a99f8..0fd7801edfd3 100644 --- a/fs/ext4/ialloc.c +++ b/fs/ext4/ialloc.c @@ -516,6 +516,8 @@ static int find_group_orlov(struct super_block *sb, struct inode *parent, if (min_inodes < 1) min_inodes = 1; min_clusters = avefreec - EXT4_CLUSTERS_PER_GROUP(sb)*flex_size / 4; + if (min_clusters < 0) + min_clusters = 0; /* * Start looking in the flex group where we last allocated an @@ -757,10 +759,10 @@ int ext4_mark_inode_used(struct super_block *sb, int ino) struct ext4_group_desc *gdp; ext4_group_t group; int bit; - int err = -EFSCORRUPTED; + int err; if (ino < EXT4_FIRST_INO(sb) || ino > max_ino) - goto out; + return -EFSCORRUPTED; group = (ino - 1) / EXT4_INODES_PER_GROUP(sb); bit = (ino - 1) % EXT4_INODES_PER_GROUP(sb); @@ -863,6 +865,7 @@ int ext4_mark_inode_used(struct super_block *sb, int ino) err = ext4_handle_dirty_metadata(NULL, NULL, group_desc_bh); sync_dirty_buffer(group_desc_bh); out: + brelse(inode_bitmap_bh); return err; } @@ -1055,12 +1058,13 @@ struct inode *__ext4_new_inode(handle_t *handle, struct inode *dir, brelse(inode_bitmap_bh); inode_bitmap_bh = ext4_read_inode_bitmap(sb, group); /* Skip groups with suspicious inode tables */ - if (((!(sbi->s_mount_state & EXT4_FC_REPLAY)) - && EXT4_MB_GRP_IBITMAP_CORRUPT(grp)) || - IS_ERR(inode_bitmap_bh)) { + if (IS_ERR(inode_bitmap_bh)) { inode_bitmap_bh = NULL; goto next_group; } + if (!(sbi->s_mount_state & EXT4_FC_REPLAY) && + EXT4_MB_GRP_IBITMAP_CORRUPT(grp)) + goto next_group; repeat_in_this_group: ret2 = find_inode_bit(sb, group, inode_bitmap_bh, &ino); diff --git a/fs/ext4/inline.c b/fs/ext4/inline.c index 58873f3329cd..4065f4a8c7ff 100644 --- a/fs/ext4/inline.c +++ b/fs/ext4/inline.c @@ -1667,24 +1667,36 @@ struct buffer_head *ext4_find_inline_entry(struct inode *dir, struct ext4_dir_entry_2 **res_dir, int *has_inline_data) { + struct ext4_xattr_ibody_find is = { + .s = { .not_found = -ENODATA, }, + }; + struct ext4_xattr_info i = { + .name_index = EXT4_XATTR_INDEX_SYSTEM, + .name = EXT4_XATTR_SYSTEM_DATA, + }; int ret; - struct ext4_iloc iloc; void *inline_start; int inline_size; - if (ext4_get_inode_loc(dir, &iloc)) - return NULL; + ret = ext4_get_inode_loc(dir, &is.iloc); + if (ret) + return ERR_PTR(ret); down_read(&EXT4_I(dir)->xattr_sem); + + ret = ext4_xattr_ibody_find(dir, &i, &is); + if (ret) + goto out; + if (!ext4_has_inline_data(dir)) { *has_inline_data = 0; goto out; } - inline_start = (void *)ext4_raw_inode(&iloc)->i_block + + inline_start = (void *)ext4_raw_inode(&is.iloc)->i_block + EXT4_INLINE_DOTDOT_SIZE; inline_size = EXT4_MIN_INLINE_DATA_SIZE - EXT4_INLINE_DOTDOT_SIZE; - ret = ext4_search_dir(iloc.bh, inline_start, inline_size, + ret = ext4_search_dir(is.iloc.bh, inline_start, inline_size, dir, fname, 0, 0, res_dir); if (ret == 1) goto out_find; @@ -1694,20 +1706,23 @@ struct buffer_head *ext4_find_inline_entry(struct inode *dir, if (ext4_get_inline_size(dir) == EXT4_MIN_INLINE_DATA_SIZE) goto out; - inline_start = ext4_get_inline_xattr_pos(dir, &iloc); + inline_start = ext4_get_inline_xattr_pos(dir, &is.iloc); inline_size = ext4_get_inline_size(dir) - EXT4_MIN_INLINE_DATA_SIZE; - ret = ext4_search_dir(iloc.bh, inline_start, inline_size, + ret = ext4_search_dir(is.iloc.bh, inline_start, inline_size, dir, fname, 0, 0, res_dir); if (ret == 1) goto out_find; out: - brelse(iloc.bh); - iloc.bh = NULL; + brelse(is.iloc.bh); + if (ret < 0) + is.iloc.bh = ERR_PTR(ret); + else + is.iloc.bh = NULL; out_find: up_read(&EXT4_I(dir)->xattr_sem); - return iloc.bh; + return is.iloc.bh; } int ext4_delete_inline_entry(handle_t *handle, diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index 667961fbde8a..77538a4a6484 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c @@ -5399,8 +5399,9 @@ static void ext4_wait_for_tail_page_commit(struct inode *inode) struct page *page; unsigned offset; journal_t *journal = EXT4_SB(inode->i_sb)->s_journal; - tid_t commit_tid = 0; + tid_t commit_tid; int ret; + bool has_transaction; offset = inode->i_size & (PAGE_SIZE - 1); /* @@ -5425,12 +5426,14 @@ static void ext4_wait_for_tail_page_commit(struct inode *inode) put_page(page); if (ret != -EBUSY) return; - commit_tid = 0; + has_transaction = false; read_lock(&journal->j_state_lock); - if (journal->j_committing_transaction) + if (journal->j_committing_transaction) { commit_tid = journal->j_committing_transaction->t_tid; + has_transaction = true; + } read_unlock(&journal->j_state_lock); - if (commit_tid) + if (has_transaction) jbd2_log_wait_commit(journal, commit_tid); } } diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c index 7cbbcee225dd..990d8031bed6 100644 --- a/fs/ext4/mballoc.c +++ b/fs/ext4/mballoc.c @@ -3176,11 +3176,8 @@ static void ext4_free_data_in_buddy(struct super_block *sb, /* * Clear the trimmed flag for the group so that the next * ext4_trim_fs can trim it. - * If the volume is mounted with -o discard, online discard - * is supported and the free blocks will be trimmed online. */ - if (!test_opt(sb, DISCARD)) - EXT4_MB_GRP_CLEAR_TRIMMED(db); + EXT4_MB_GRP_CLEAR_TRIMMED(db); if (!db->bb_free_root.rb_node) { /* No more items in the per group rb tree @@ -5589,8 +5586,9 @@ static void ext4_mb_clear_bb(handle_t *handle, struct inode *inode, " group:%u block:%d count:%lu failed" " with %d", block_group, bit, count, err); - } else - EXT4_MB_GRP_CLEAR_TRIMMED(e4b.bd_info); + } + + EXT4_MB_GRP_CLEAR_TRIMMED(e4b.bd_info); ext4_lock_group(sb, block_group); mb_clear_bits(bitmap_bh->b_data, bit, count_clusters); diff --git a/fs/ext4/migrate.c b/fs/ext4/migrate.c index b0ea646454ac..59290356aa5b 100644 --- a/fs/ext4/migrate.c +++ b/fs/ext4/migrate.c @@ -663,8 +663,8 @@ int ext4_ind_migrate(struct inode *inode) if (unlikely(ret2 && !ret)) ret = ret2; errout: - ext4_journal_stop(handle); up_write(&EXT4_I(inode)->i_data_sem); + ext4_journal_stop(handle); out_unlock: percpu_up_write(&sbi->s_writepages_rwsem); return ret; diff --git a/fs/ext4/move_extent.c b/fs/ext4/move_extent.c index f8dd5d972c33..661a8544d781 100644 --- a/fs/ext4/move_extent.c +++ b/fs/ext4/move_extent.c @@ -36,7 +36,6 @@ get_ext_path(struct inode *inode, ext4_lblk_t lblock, *ppath = NULL; return -ENODATA; } - *ppath = path; return 0; } diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c index f1f11b9dba72..f96d6effdfce 100644 --- a/fs/ext4/namei.c +++ b/fs/ext4/namei.c @@ -1490,7 +1490,7 @@ static bool ext4_match(struct inode *parent, } /* - * Returns 0 if not found, -1 on failure, and 1 on success + * Returns 0 if not found, -EFSCORRUPTED on failure, and 1 on success */ int ext4_search_dir(struct buffer_head *bh, char *search_buf, int buf_size, struct inode *dir, struct ext4_filename *fname, @@ -1512,7 +1512,7 @@ int ext4_search_dir(struct buffer_head *bh, char *search_buf, int buf_size, * a full check */ if (ext4_check_dir_entry(dir, NULL, de, bh, search_buf, buf_size, lblk, offset)) - return -1; + return -EFSCORRUPTED; *res_dir = de; return 1; } @@ -1520,7 +1520,7 @@ int ext4_search_dir(struct buffer_head *bh, char *search_buf, int buf_size, de_len = ext4_rec_len_from_disk(de->rec_len, dir->i_sb->s_blocksize); if (de_len <= 0) - return -1; + return -EFSCORRUPTED; offset += de_len; de = (struct ext4_dir_entry_2 *) ((char *) de + de_len); } @@ -1676,8 +1676,10 @@ static struct buffer_head *__ext4_find_entry(struct inode *dir, goto cleanup_and_exit; } else { brelse(bh); - if (i < 0) + if (i < 0) { + ret = ERR_PTR(i); goto cleanup_and_exit; + } } next: if (++block >= nblocks) @@ -1774,7 +1776,7 @@ static struct buffer_head * ext4_dx_find_entry(struct inode *dir, if (retval == 1) goto success; brelse(bh); - if (retval == -1) { + if (retval < 0) { bh = ERR_PTR(ERR_BAD_DX_DIR); goto errout; } @@ -2004,7 +2006,7 @@ static struct ext4_dir_entry_2 *do_split(handle_t *handle, struct inode *dir, split = count/2; hash2 = map[split].hash; - continued = hash2 == map[split - 1].hash; + continued = split > 0 ? hash2 == map[split - 1].hash : 0; dxtrace(printk(KERN_INFO "Split block %lu at %x, %i/%i\n", (unsigned long)dx_get_block(frame->at), hash2, split, count-split)); diff --git a/fs/ext4/xattr.c b/fs/ext4/xattr.c index b91a1d1099d5..d1d930d09cb8 100644 --- a/fs/ext4/xattr.c +++ b/fs/ext4/xattr.c @@ -422,7 +422,7 @@ static int ext4_xattr_inode_iget(struct inode *parent, unsigned long ea_ino, ext4_set_inode_state(inode, EXT4_STATE_LUSTRE_EA_INODE); ext4_xattr_inode_set_ref(inode, 1); } else { - inode_lock(inode); + inode_lock_nested(inode, I_MUTEX_XATTR); inode->i_flags |= S_NOQUOTA; inode_unlock(inode); } @@ -986,7 +986,7 @@ static int ext4_xattr_inode_update_ref(handle_t *handle, struct inode *ea_inode, s64 ref_count; int ret; - inode_lock(ea_inode); + inode_lock_nested(ea_inode, I_MUTEX_XATTR); ret = ext4_reserve_inode_write(handle, ea_inode, &iloc); if (ret) diff --git a/fs/f2fs/dir.c b/fs/f2fs/dir.c index db97f3d9f657..539a4ebbcc5e 100644 --- a/fs/f2fs/dir.c +++ b/fs/f2fs/dir.c @@ -190,7 +190,8 @@ static unsigned long dir_block_index(unsigned int level, unsigned long bidx = 0; for (i = 0; i < level; i++) - bidx += dir_buckets(i, dir_level) * bucket_blocks(i); + bidx += mul_u32_u32(dir_buckets(i, dir_level), + bucket_blocks(i)); bidx += idx * bucket_blocks(level); return bidx; } diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h index a98eb0089890..2ed306a49bdc 100644 --- a/fs/f2fs/f2fs.h +++ b/fs/f2fs/f2fs.h @@ -265,7 +265,8 @@ enum { ORPHAN_INO, /* for orphan ino list */ APPEND_INO, /* for append ino list */ UPDATE_INO, /* for update ino list */ - TRANS_DIR_INO, /* for trasactions dir ino list */ + TRANS_DIR_INO, /* for transactions dir ino list */ + XATTR_DIR_INO, /* for xattr updated dir ino list */ FLUSH_INO, /* for multiple device flushing */ MAX_INO_ENTRY, /* max. list */ }; @@ -1128,6 +1129,7 @@ enum cp_reason_type { CP_FASTBOOT_MODE, CP_SPEC_LOG_NUM, CP_RECOVER_DIR, + CP_XATTR_DIR, }; enum iostat_type { diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c index e26be0b92281..5dd9cd954791 100644 --- a/fs/f2fs/file.c +++ b/fs/f2fs/file.c @@ -219,6 +219,9 @@ static inline enum cp_reason_type need_do_checkpoint(struct inode *inode) f2fs_exist_written_data(sbi, F2FS_I(inode)->i_pino, TRANS_DIR_INO)) cp_reason = CP_RECOVER_DIR; + else if (f2fs_exist_written_data(sbi, F2FS_I(inode)->i_pino, + XATTR_DIR_INO)) + cp_reason = CP_XATTR_DIR; return cp_reason; } @@ -382,9 +385,20 @@ int f2fs_sync_file(struct file *file, loff_t start, loff_t end, int datasync) return f2fs_do_sync_file(file, start, end, datasync, false); } -static bool __found_offset(struct address_space *mapping, block_t blkaddr, - pgoff_t index, int whence) +static bool __found_offset(struct address_space *mapping, + struct dnode_of_data *dn, pgoff_t index, int whence) { + block_t blkaddr = f2fs_data_blkaddr(dn); + struct inode *inode = mapping->host; + bool compressed_cluster = false; + + if (f2fs_compressed_file(inode)) { + block_t first_blkaddr = data_blkaddr(dn->inode, dn->node_page, + ALIGN_DOWN(dn->ofs_in_node, F2FS_I(inode)->i_cluster_size)); + + compressed_cluster = first_blkaddr == COMPRESS_ADDR; + } + switch (whence) { case SEEK_DATA: if (__is_valid_data_blkaddr(blkaddr)) @@ -392,8 +406,12 @@ static bool __found_offset(struct address_space *mapping, block_t blkaddr, if (blkaddr == NEW_ADDR && xa_get_mark(&mapping->i_pages, index, PAGECACHE_TAG_DIRTY)) return true; + if (compressed_cluster) + return true; break; case SEEK_HOLE: + if (compressed_cluster) + return false; if (blkaddr == NULL_ADDR) return true; break; @@ -462,7 +480,7 @@ static loff_t f2fs_seek_block(struct file *file, loff_t offset, int whence) goto fail; } - if (__found_offset(file->f_mapping, blkaddr, + if (__found_offset(file->f_mapping, &dn, pgofs, whence)) { f2fs_put_dnode(&dn); goto found; @@ -2030,6 +2048,9 @@ static int f2fs_ioc_start_atomic_write(struct file *filp) struct f2fs_sb_info *sbi = F2FS_I_SB(inode); int ret; + if (!(filp->f_mode & FMODE_WRITE)) + return -EBADF; + if (!inode_owner_or_capable(inode)) return -EACCES; @@ -2100,6 +2121,9 @@ static int f2fs_ioc_commit_atomic_write(struct file *filp) struct inode *inode = file_inode(filp); int ret; + if (!(filp->f_mode & FMODE_WRITE)) + return -EBADF; + if (!inode_owner_or_capable(inode)) return -EACCES; @@ -2142,6 +2166,9 @@ static int f2fs_ioc_start_volatile_write(struct file *filp) struct inode *inode = file_inode(filp); int ret; + if (!(filp->f_mode & FMODE_WRITE)) + return -EBADF; + if (!inode_owner_or_capable(inode)) return -EACCES; @@ -2177,6 +2204,9 @@ static int f2fs_ioc_release_volatile_write(struct file *filp) struct inode *inode = file_inode(filp); int ret; + if (!(filp->f_mode & FMODE_WRITE)) + return -EBADF; + if (!inode_owner_or_capable(inode)) return -EACCES; @@ -2206,6 +2236,9 @@ static int f2fs_ioc_abort_volatile_write(struct file *filp) struct inode *inode = file_inode(filp); int ret; + if (!(filp->f_mode & FMODE_WRITE)) + return -EBADF; + if (!inode_owner_or_capable(inode)) return -EACCES; @@ -3663,7 +3696,8 @@ static int reserve_compress_blocks(struct dnode_of_data *dn, pgoff_t count) while (count) { int compr_blocks = 0; - blkcnt_t reserved; + blkcnt_t reserved = 0; + blkcnt_t to_reserved; int ret; for (i = 0; i < cluster_size; i++, dn->ofs_in_node++) { @@ -3681,8 +3715,11 @@ static int reserve_compress_blocks(struct dnode_of_data *dn, pgoff_t count) * fails in release_compress_blocks(), so NEW_ADDR * is a possible case. */ - if (blkaddr == NEW_ADDR || - __is_valid_data_blkaddr(blkaddr)) { + if (blkaddr == NEW_ADDR) { + reserved++; + continue; + } + if (__is_valid_data_blkaddr(blkaddr)) { compr_blocks++; continue; } @@ -3691,13 +3728,15 @@ static int reserve_compress_blocks(struct dnode_of_data *dn, pgoff_t count) f2fs_set_data_blkaddr(dn); } - reserved = cluster_size - compr_blocks; + to_reserved = cluster_size - compr_blocks - reserved; /* for the case all blocks in cluster were reserved */ - if (reserved == 1) + if (to_reserved == 1) { + dn->ofs_in_node += cluster_size; goto next; + } - ret = inc_valid_block_count(sbi, dn->inode, &reserved); + ret = inc_valid_block_count(sbi, dn->inode, &to_reserved); if (ret) return ret; @@ -3706,7 +3745,7 @@ static int reserve_compress_blocks(struct dnode_of_data *dn, pgoff_t count) f2fs_i_compr_blocks_update(dn->inode, compr_blocks, true); - reserved_blocks += reserved; + reserved_blocks += to_reserved; next: count -= cluster_size; } diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c index b52dbd2bd603..996845e2bb7b 100644 --- a/fs/f2fs/super.c +++ b/fs/f2fs/super.c @@ -3033,9 +3033,9 @@ static inline bool sanity_check_area_boundary(struct f2fs_sb_info *sbi, u32 segment_count = le32_to_cpu(raw_super->segment_count); u32 log_blocks_per_seg = le32_to_cpu(raw_super->log_blocks_per_seg); u64 main_end_blkaddr = main_blkaddr + - (segment_count_main << log_blocks_per_seg); + ((u64)segment_count_main << log_blocks_per_seg); u64 seg_end_blkaddr = segment0_blkaddr + - (segment_count << log_blocks_per_seg); + ((u64)segment_count << log_blocks_per_seg); if (segment0_blkaddr != cp_blkaddr) { f2fs_info(sbi, "Mismatch start address, segment0(%u) cp_blkaddr(%u)", diff --git a/fs/fat/namei_vfat.c b/fs/fat/namei_vfat.c index 01fab05dc7a1..1dc192e02576 100644 --- a/fs/fat/namei_vfat.c +++ b/fs/fat/namei_vfat.c @@ -1019,7 +1019,7 @@ static int vfat_rename(struct inode *old_dir, struct dentry *old_dentry, if (corrupt < 0) { fat_fs_error(new_dir->i_sb, "%s: Filesystem corrupted (i_pos %lld)", - __func__, sinfo.i_pos); + __func__, new_i_pos); } goto out; } diff --git a/fs/fcntl.c b/fs/fcntl.c index fcf34f83bf6a..4a65d3689620 100644 --- a/fs/fcntl.c +++ b/fs/fcntl.c @@ -84,8 +84,8 @@ static int setfl(int fd, struct file * filp, unsigned long arg) return error; } -static void f_modown(struct file *filp, struct pid *pid, enum pid_type type, - int force) +void __f_setown(struct file *filp, struct pid *pid, enum pid_type type, + int force) { write_lock_irq(&filp->f_owner.lock); if (force || !filp->f_owner.pid) { @@ -95,19 +95,13 @@ static void f_modown(struct file *filp, struct pid *pid, enum pid_type type, if (pid) { const struct cred *cred = current_cred(); + security_file_set_fowner(filp); filp->f_owner.uid = cred->uid; filp->f_owner.euid = cred->euid; } } write_unlock_irq(&filp->f_owner.lock); } - -void __f_setown(struct file *filp, struct pid *pid, enum pid_type type, - int force) -{ - security_file_set_fowner(filp); - f_modown(filp, pid, type, force); -} EXPORT_SYMBOL(__f_setown); int f_setown(struct file *filp, unsigned long arg, int force) @@ -143,7 +137,7 @@ EXPORT_SYMBOL(f_setown); void f_delown(struct file *filp) { - f_modown(filp, NULL, PIDTYPE_TGID, 1); + __f_setown(filp, NULL, PIDTYPE_TGID, 1); } pid_t f_getown(struct file *filp) diff --git a/fs/inode.c b/fs/inode.c index 85166eedc80b..5d835021fd7b 100644 --- a/fs/inode.c +++ b/fs/inode.c @@ -670,6 +670,10 @@ void evict_inodes(struct super_block *sb) continue; spin_lock(&inode->i_lock); + if (atomic_read(&inode->i_count)) { + spin_unlock(&inode->i_lock); + continue; + } if (inode->i_state & (I_NEW | I_FREEING | I_WILL_FREE)) { spin_unlock(&inode->i_lock); continue; diff --git a/fs/iomap/direct-io.c b/fs/iomap/direct-io.c index b4240cc3c9f9..ae073837ccfa 100644 --- a/fs/iomap/direct-io.c +++ b/fs/iomap/direct-io.c @@ -11,6 +11,9 @@ #include #include #include +#ifndef __GENKSYMS__ +#include +#endif #include "trace.h" #include "../internal.h" @@ -94,7 +97,6 @@ ssize_t iomap_dio_complete(struct iomap_dio *dio) if (offset + ret > dio->i_size && !(dio->flags & IOMAP_DIO_WRITE)) ret = dio->i_size - offset; - iocb->ki_pos += ret; } /* @@ -120,15 +122,18 @@ ssize_t iomap_dio_complete(struct iomap_dio *dio) } inode_dio_end(file_inode(iocb->ki_filp)); - /* - * If this is a DSYNC write, make sure we push it to stable storage now - * that we've written data. - */ - if (ret > 0 && (dio->flags & IOMAP_DIO_NEED_SYNC)) - ret = generic_write_sync(iocb, ret); + if (ret > 0) { + iocb->ki_pos += ret; + + /* + * If this is a DSYNC write, make sure we push it to stable + * storage now that we've written data. + */ + if (dio->flags & IOMAP_DIO_NEED_SYNC) + ret = generic_write_sync(iocb, ret); + } kfree(dio); - return ret; } EXPORT_SYMBOL_GPL(iomap_dio_complete); @@ -275,6 +280,8 @@ iomap_dio_bio_actor(struct inode *inode, loff_t pos, loff_t length, goto out; } + trace_android_vh_io_statistics(inode->i_mapping, pos >> inode->i_blkbits, + nr_pages, !(dio->flags & IOMAP_DIO_WRITE), true); bio = bio_alloc(GFP_KERNEL, nr_pages); fscrypt_set_bio_crypt_ctx(bio, inode, pos >> inode->i_blkbits, GFP_KERNEL); diff --git a/fs/jbd2/checkpoint.c b/fs/jbd2/checkpoint.c index 7898983c9fba..0aaff82ecd1c 100644 --- a/fs/jbd2/checkpoint.c +++ b/fs/jbd2/checkpoint.c @@ -115,17 +115,23 @@ __releases(&journal->j_state_lock) if (space_left < nblocks) { int chkpt = journal->j_checkpoint_transactions != NULL; tid_t tid = 0; + bool has_transaction = false; - if (journal->j_committing_transaction) + if (journal->j_committing_transaction) { tid = journal->j_committing_transaction->t_tid; + has_transaction = true; + } spin_unlock(&journal->j_list_lock); write_unlock(&journal->j_state_lock); if (chkpt) { jbd2_log_do_checkpoint(journal); - } else if (jbd2_cleanup_journal_tail(journal) == 0) { - /* We were able to recover space; yay! */ + } else if (jbd2_cleanup_journal_tail(journal) <= 0) { + /* + * We were able to recover space or the + * journal was aborted due to an error. + */ ; - } else if (tid) { + } else if (has_transaction) { /* * jbd2_journal_commit_transaction() may want * to take the checkpoint_mutex if JBD2_FLUSHED diff --git a/fs/jbd2/journal.c b/fs/jbd2/journal.c index ae16911a2e1b..d3ab8ccccec2 100644 --- a/fs/jbd2/journal.c +++ b/fs/jbd2/journal.c @@ -740,7 +740,7 @@ int jbd2_fc_begin_commit(journal_t *journal, tid_t tid) return -EINVAL; write_lock(&journal->j_state_lock); - if (tid <= journal->j_commit_sequence) { + if (tid_geq(journal->j_commit_sequence, tid)) { write_unlock(&journal->j_state_lock); return -EALREADY; } diff --git a/fs/jfs/jfs_discard.c b/fs/jfs/jfs_discard.c index 575cb2ba74fc..5f4b305030ad 100644 --- a/fs/jfs/jfs_discard.c +++ b/fs/jfs/jfs_discard.c @@ -65,7 +65,7 @@ void jfs_issue_discard(struct inode *ip, u64 blkno, u64 nblocks) int jfs_ioc_trim(struct inode *ip, struct fstrim_range *range) { struct inode *ipbmap = JFS_SBI(ip->i_sb)->ipbmap; - struct bmap *bmp = JFS_SBI(ip->i_sb)->bmap; + struct bmap *bmp; struct super_block *sb = ipbmap->i_sb; int agno, agno_end; u64 start, end, minlen; @@ -83,10 +83,15 @@ int jfs_ioc_trim(struct inode *ip, struct fstrim_range *range) if (minlen == 0) minlen = 1; + down_read(&sb->s_umount); + bmp = JFS_SBI(ip->i_sb)->bmap; + if (minlen > bmp->db_agsize || start >= bmp->db_mapsize || - range->len < sb->s_blocksize) + range->len < sb->s_blocksize) { + up_read(&sb->s_umount); return -EINVAL; + } if (end >= bmp->db_mapsize) end = bmp->db_mapsize - 1; @@ -100,6 +105,8 @@ int jfs_ioc_trim(struct inode *ip, struct fstrim_range *range) trimmed += dbDiscardAG(ip, agno, minlen); agno++; } + + up_read(&sb->s_umount); range->len = trimmed << sb->s_blocksize_bits; return 0; diff --git a/fs/jfs/jfs_dmap.c b/fs/jfs/jfs_dmap.c index 9b6849b9bfdb..559f6ebebfc0 100644 --- a/fs/jfs/jfs_dmap.c +++ b/fs/jfs/jfs_dmap.c @@ -187,7 +187,7 @@ int dbMount(struct inode *ipbmap) } bmp->db_numag = le32_to_cpu(dbmp_le->dn_numag); - if (!bmp->db_numag) { + if (!bmp->db_numag || bmp->db_numag > MAXAG) { err = -EINVAL; goto err_release_metapage; } @@ -652,7 +652,7 @@ int dbNextAG(struct inode *ipbmap) * average free space. */ for (i = 0 ; i < bmp->db_numag; i++, agpref++) { - if (agpref == bmp->db_numag) + if (agpref >= bmp->db_numag) agpref = 0; if (atomic_read(&bmp->db_active[agpref])) @@ -3006,9 +3006,10 @@ static void dbAdjTree(dmtree_t *tp, int leafno, int newval, bool is_ctl) static int dbFindLeaf(dmtree_t *tp, int l2nb, int *leafidx, bool is_ctl) { int ti, n = 0, k, x = 0; - int max_size; + int max_size, max_idx; max_size = is_ctl ? CTLTREESIZE : TREESIZE; + max_idx = is_ctl ? LPERCTL : LPERDMAP; /* first check the root of the tree to see if there is * sufficient free space. @@ -3040,6 +3041,8 @@ static int dbFindLeaf(dmtree_t *tp, int l2nb, int *leafidx, bool is_ctl) */ assert(n < 4); } + if (le32_to_cpu(tp->dmt_leafidx) >= max_idx) + return -ENOSPC; /* set the return to the leftmost leaf describing sufficient * free space. @@ -3084,7 +3087,7 @@ static int dbFindBits(u32 word, int l2nb) /* scan the word for nb free bits at nb alignments. */ - for (bitno = 0; mask != 0; bitno += nb, mask >>= nb) { + for (bitno = 0; mask != 0; bitno += nb, mask = (mask >> nb)) { if ((mask & word) == mask) break; } diff --git a/fs/jfs/jfs_imap.c b/fs/jfs/jfs_imap.c index 36ed75682064..da3a1c27d349 100644 --- a/fs/jfs/jfs_imap.c +++ b/fs/jfs/jfs_imap.c @@ -1362,7 +1362,7 @@ int diAlloc(struct inode *pip, bool dir, struct inode *ip) /* get the ag number of this iag */ agno = BLKTOAG(JFS_IP(pip)->agstart, JFS_SBI(pip->i_sb)); dn_numag = JFS_SBI(pip->i_sb)->bmap->db_numag; - if (agno < 0 || agno > dn_numag) + if (agno < 0 || agno > dn_numag || agno >= MAXAG) return -EIO; if (atomic_read(&JFS_SBI(pip->i_sb)->bmap->db_active[agno])) { diff --git a/fs/jfs/xattr.c b/fs/jfs/xattr.c index 64fc5263db71..7dcfaab12337 100644 --- a/fs/jfs/xattr.c +++ b/fs/jfs/xattr.c @@ -434,6 +434,8 @@ static int ea_get(struct inode *inode, struct ea_buffer *ea_buf, int min_size) int rc; int quota_allocation = 0; + memset(&ea_buf->new_ea, 0, sizeof(ea_buf->new_ea)); + /* When fsck.jfs clears a bad ea, it doesn't clear the size */ if (ji->ea.flag == 0) ea_size = 0; diff --git a/fs/namespace.c b/fs/namespace.c index 5d5a426aa495..007040b013c0 100644 --- a/fs/namespace.c +++ b/fs/namespace.c @@ -2553,20 +2553,27 @@ static void mnt_warn_timestamp_expiry(struct path *mountpoint, struct vfsmount * struct super_block *sb = mnt->mnt_sb; if (!__mnt_is_readonly(mnt) && + (!(sb->s_iflags & SB_I_TS_EXPIRY_WARNED)) && (ktime_get_real_seconds() + TIME_UPTIME_SEC_MAX > sb->s_time_max)) { - char *buf = (char *)__get_free_page(GFP_KERNEL); - char *mntpath = buf ? d_path(mountpoint, buf, PAGE_SIZE) : ERR_PTR(-ENOMEM); - struct tm tm; + char *buf, *mntpath; - time64_to_tm(sb->s_time_max, 0, &tm); + buf = (char *)__get_free_page(GFP_KERNEL); + if (buf) + mntpath = d_path(mountpoint, buf, PAGE_SIZE); + else + mntpath = ERR_PTR(-ENOMEM); + if (IS_ERR(mntpath)) + mntpath = "(unknown)"; - pr_warn("%s filesystem being %s at %s supports timestamps until %04ld (0x%llx)\n", + pr_warn("%s filesystem being %s at %s supports timestamps until %ptTd (0x%llx)\n", sb->s_type->name, is_mounted(mnt) ? "remounted" : "mounted", - mntpath, - tm.tm_year+1900, (unsigned long long)sb->s_time_max); + mntpath, &sb->s_time_max, + (unsigned long long)sb->s_time_max); - free_page((unsigned long)buf); + sb->s_iflags |= SB_I_TS_EXPIRY_WARNED; + if (buf) + free_page((unsigned long)buf); } } diff --git a/fs/nfs/callback_xdr.c b/fs/nfs/callback_xdr.c index ca8a4aa351dc..c60cc807781b 100644 --- a/fs/nfs/callback_xdr.c +++ b/fs/nfs/callback_xdr.c @@ -373,6 +373,8 @@ static __be32 decode_rc_list(struct xdr_stream *xdr, rc_list->rcl_nrefcalls = ntohl(*p++); if (rc_list->rcl_nrefcalls) { + if (unlikely(rc_list->rcl_nrefcalls > xdr->buf->len)) + goto out; p = xdr_inline_decode(xdr, rc_list->rcl_nrefcalls * 2 * sizeof(uint32_t)); if (unlikely(p == NULL)) diff --git a/fs/nfs/client.c b/fs/nfs/client.c index 1437eb31dd03..6afb66b8855e 100644 --- a/fs/nfs/client.c +++ b/fs/nfs/client.c @@ -927,6 +927,7 @@ struct nfs_server *nfs_alloc_server(void) INIT_LIST_HEAD(&server->layouts); INIT_LIST_HEAD(&server->state_owners_lru); INIT_LIST_HEAD(&server->ss_copies); + INIT_LIST_HEAD(&server->ss_src_copies); atomic_set(&server->active, 0); diff --git a/fs/nfs/delegation.c b/fs/nfs/delegation.c index 1eb6c7a142ff..c15188d0b6b3 100644 --- a/fs/nfs/delegation.c +++ b/fs/nfs/delegation.c @@ -609,6 +609,9 @@ static int nfs_server_return_marked_delegations(struct nfs_server *server, prev = delegation; continue; } + inode = nfs_delegation_grab_inode(delegation); + if (inode == NULL) + continue; if (prev) { struct inode *tmp = nfs_delegation_grab_inode(prev); @@ -619,12 +622,6 @@ static int nfs_server_return_marked_delegations(struct nfs_server *server, } } - inode = nfs_delegation_grab_inode(delegation); - if (inode == NULL) { - rcu_read_unlock(); - iput(to_put); - goto restart; - } delegation = nfs_start_delegation_return_locked(NFS_I(inode)); rcu_read_unlock(); @@ -1140,7 +1137,6 @@ static int nfs_server_reap_unclaimed_delegations(struct nfs_server *server, struct inode *inode; restart: rcu_read_lock(); -restart_locked: list_for_each_entry_rcu(delegation, &server->delegations, super_list) { if (test_bit(NFS_DELEGATION_INODE_FREEING, &delegation->flags) || @@ -1151,7 +1147,7 @@ static int nfs_server_reap_unclaimed_delegations(struct nfs_server *server, continue; inode = nfs_delegation_grab_inode(delegation); if (inode == NULL) - goto restart_locked; + continue; delegation = nfs_start_delegation_return_locked(NFS_I(inode)); rcu_read_unlock(); if (delegation != NULL) { @@ -1272,7 +1268,6 @@ static int nfs_server_reap_expired_delegations(struct nfs_server *server, nfs4_stateid stateid; restart: rcu_read_lock(); -restart_locked: list_for_each_entry_rcu(delegation, &server->delegations, super_list) { if (test_bit(NFS_DELEGATION_INODE_FREEING, &delegation->flags) || @@ -1283,7 +1278,7 @@ static int nfs_server_reap_expired_delegations(struct nfs_server *server, continue; inode = nfs_delegation_grab_inode(delegation); if (inode == NULL) - goto restart_locked; + continue; spin_lock(&delegation->lock); cred = get_cred_rcu(delegation->cred); nfs4_stateid_copy(&stateid, &delegation->stateid); diff --git a/fs/nfs/nfs42proc.c b/fs/nfs/nfs42proc.c index dfeea712014b..47aa721d0d83 100644 --- a/fs/nfs/nfs42proc.c +++ b/fs/nfs/nfs42proc.c @@ -210,7 +210,7 @@ static int handle_async_copy(struct nfs42_copy_res *res, if (dst_server != src_server) { spin_lock(&src_server->nfs_client->cl_lock); - list_add_tail(©->src_copies, &src_server->ss_copies); + list_add_tail(©->src_copies, &src_server->ss_src_copies); spin_unlock(&src_server->nfs_client->cl_lock); } diff --git a/fs/nfs/nfs4state.c b/fs/nfs/nfs4state.c index afb617a4a7e4..f03b956ef77f 100644 --- a/fs/nfs/nfs4state.c +++ b/fs/nfs/nfs4state.c @@ -1596,7 +1596,7 @@ static void nfs42_complete_copies(struct nfs4_state_owner *sp, struct nfs4_state complete(©->completion); } } - list_for_each_entry(copy, &sp->so_server->ss_copies, src_copies) { + list_for_each_entry(copy, &sp->so_server->ss_src_copies, src_copies) { if ((test_bit(NFS_CLNT_SRC_SSC_COPY_STATE, &state->flags) && !nfs4_stateid_match_other(&state->stateid, ©->parent_src_state->stateid))) @@ -1948,6 +1948,7 @@ static int nfs4_do_reclaim(struct nfs_client *clp, const struct nfs4_state_recov set_bit(ops->owner_flag_bit, &sp->so_flags); nfs4_put_state_owner(sp); status = nfs4_recovery_handle_error(clp, status); + nfs4_free_state_owners(&freeme); return (status != 0) ? status : -EAGAIN; } diff --git a/fs/nfsd/nfs4idmap.c b/fs/nfsd/nfs4idmap.c index f92161ce1f97..9062b5e14b66 100644 --- a/fs/nfsd/nfs4idmap.c +++ b/fs/nfsd/nfs4idmap.c @@ -580,6 +580,7 @@ static __be32 idmap_id_to_name(struct xdr_stream *xdr, .id = id, .type = type, }; + __be32 status = nfs_ok; __be32 *p; int ret; struct nfsd_net *nn = net_generic(SVC_NET(rqstp), nfsd_net_id); @@ -592,12 +593,16 @@ static __be32 idmap_id_to_name(struct xdr_stream *xdr, return nfserrno(ret); ret = strlen(item->name); WARN_ON_ONCE(ret > IDMAP_NAMESZ); + p = xdr_reserve_space(xdr, ret + 4); - if (!p) - return nfserr_resource; - p = xdr_encode_opaque(p, item->name, ret); + if (unlikely(!p)) { + status = nfserr_resource; + goto out_put; + } + xdr_encode_opaque(p, item->name, ret); +out_put: cache_put(&item->h, nn->idtoname_cache); - return 0; + return status; } static bool diff --git a/fs/nfsd/nfs4recover.c b/fs/nfsd/nfs4recover.c index 83c4e6883953..f2801eaea7c6 100644 --- a/fs/nfsd/nfs4recover.c +++ b/fs/nfsd/nfs4recover.c @@ -806,6 +806,10 @@ __cld_pipe_inprogress_downcall(const struct cld_msg_v2 __user *cmsg, ci = &cmsg->cm_u.cm_clntinfo; if (get_user(namelen, &ci->cc_name.cn_len)) return -EFAULT; + if (!namelen) { + dprintk("%s: namelen should not be zero", __func__); + return -EINVAL; + } name.data = memdup_user(&ci->cc_name.cn_id, namelen); if (IS_ERR_OR_NULL(name.data)) return -EFAULT; @@ -828,6 +832,10 @@ __cld_pipe_inprogress_downcall(const struct cld_msg_v2 __user *cmsg, cnm = &cmsg->cm_u.cm_name; if (get_user(namelen, &cnm->cn_len)) return -EFAULT; + if (!namelen) { + dprintk("%s: namelen should not be zero", __func__); + return -EINVAL; + } name.data = memdup_user(&cnm->cn_id, namelen); if (IS_ERR_OR_NULL(name.data)) return -EFAULT; diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c index d402ca0b535f..738aa80e1eff 100644 --- a/fs/nfsd/nfs4state.c +++ b/fs/nfsd/nfs4state.c @@ -868,7 +868,8 @@ static void nfs4_free_deleg(struct nfs4_stid *stid) * When a delegation is recalled, the filehandle is stored in the "new" * filter. * Every 30 seconds we swap the filters and clear the "new" one, - * unless both are empty of course. + * unless both are empty of course. This results in delegations for a + * given filehandle being blocked for between 30 and 60 seconds. * * Each filter is 256 bits. We hash the filehandle to 32bit and use the * low 3 bytes as hash-table indices. @@ -897,9 +898,9 @@ static int delegation_blocked(struct knfsd_fh *fh) if (ktime_get_seconds() - bd->swap_time > 30) { bd->entries -= bd->old_entries; bd->old_entries = bd->entries; + bd->new = 1-bd->new; memset(bd->set[bd->new], 0, sizeof(bd->set[0])); - bd->new = 1-bd->new; bd->swap_time = ktime_get_seconds(); } spin_unlock(&blocked_delegations_lock); diff --git a/fs/nilfs2/btree.c b/fs/nilfs2/btree.c index a426e4e2acda..7c9f4d79bdbc 100644 --- a/fs/nilfs2/btree.c +++ b/fs/nilfs2/btree.c @@ -350,7 +350,7 @@ static int nilfs_btree_node_broken(const struct nilfs_btree_node *node, if (unlikely(level < NILFS_BTREE_LEVEL_NODE_MIN || level >= NILFS_BTREE_LEVEL_MAX || (flags & NILFS_BTREE_NODE_ROOT) || - nchildren < 0 || + nchildren <= 0 || nchildren > NILFS_BTREE_NODE_NCHILDREN_MAX(size))) { nilfs_crit(inode->i_sb, "bad btree node (ino=%lu, blocknr=%llu): level = %d, flags = 0x%x, nchildren = %d", @@ -381,7 +381,8 @@ static int nilfs_btree_root_broken(const struct nilfs_btree_node *node, if (unlikely(level < NILFS_BTREE_LEVEL_NODE_MIN || level >= NILFS_BTREE_LEVEL_MAX || nchildren < 0 || - nchildren > NILFS_BTREE_ROOT_NCHILDREN_MAX)) { + nchildren > NILFS_BTREE_ROOT_NCHILDREN_MAX || + (nchildren == 0 && level > NILFS_BTREE_LEVEL_NODE_MIN))) { nilfs_crit(inode->i_sb, "bad btree root (ino=%lu): level = %d, flags = 0x%x, nchildren = %d", inode->i_ino, level, flags, nchildren); @@ -1659,13 +1660,16 @@ static int nilfs_btree_check_delete(struct nilfs_bmap *btree, __u64 key) int nchildren, ret; root = nilfs_btree_get_root(btree); + nchildren = nilfs_btree_node_get_nchildren(root); + if (unlikely(nchildren == 0)) + return 0; + switch (nilfs_btree_height(btree)) { case 2: bh = NULL; node = root; break; case 3: - nchildren = nilfs_btree_node_get_nchildren(root); if (nchildren > 1) return 0; ptr = nilfs_btree_node_get_ptr(root, nchildren - 1, @@ -1674,12 +1678,12 @@ static int nilfs_btree_check_delete(struct nilfs_bmap *btree, __u64 key) if (ret < 0) return ret; node = (struct nilfs_btree_node *)bh->b_data; + nchildren = nilfs_btree_node_get_nchildren(node); break; default: return 0; } - nchildren = nilfs_btree_node_get_nchildren(node); maxkey = nilfs_btree_node_get_key(node, nchildren - 1); nextmaxkey = (nchildren > 1) ? nilfs_btree_node_get_key(node, nchildren - 2) : 0; diff --git a/fs/nilfs2/dir.c b/fs/nilfs2/dir.c index 5c0e280c83ee..365cae5c3e35 100644 --- a/fs/nilfs2/dir.c +++ b/fs/nilfs2/dir.c @@ -331,6 +331,8 @@ static int nilfs_readdir(struct file *file, struct dir_context *ctx) * returns the page in which the entry was found, and the entry itself * (as a parameter - res_dir). Page is returned mapped and unlocked. * Entry is guaranteed to be valid. + * + * On failure, returns an error pointer and the caller should ignore res_page. */ struct nilfs_dir_entry * nilfs_find_entry(struct inode *dir, const struct qstr *qstr, @@ -358,22 +360,24 @@ nilfs_find_entry(struct inode *dir, const struct qstr *qstr, do { char *kaddr = nilfs_get_page(dir, n, &page); - if (!IS_ERR(kaddr)) { - de = (struct nilfs_dir_entry *)kaddr; - kaddr += nilfs_last_byte(dir, n) - reclen; - while ((char *) de <= kaddr) { - if (de->rec_len == 0) { - nilfs_error(dir->i_sb, - "zero-length directory entry"); - nilfs_put_page(page); - goto out; - } - if (nilfs_match(namelen, name, de)) - goto found; - de = nilfs_next_entry(de); + if (IS_ERR(kaddr)) + return ERR_CAST(kaddr); + + de = (struct nilfs_dir_entry *)kaddr; + kaddr += nilfs_last_byte(dir, n) - reclen; + while ((char *)de <= kaddr) { + if (de->rec_len == 0) { + nilfs_error(dir->i_sb, + "zero-length directory entry"); + nilfs_put_page(page); + goto out; } - nilfs_put_page(page); + if (nilfs_match(namelen, name, de)) + goto found; + de = nilfs_next_entry(de); } + nilfs_put_page(page); + if (++n >= npages) n = 0; /* next page is past the blocks we've got */ @@ -386,7 +390,7 @@ nilfs_find_entry(struct inode *dir, const struct qstr *qstr, } } while (n != start); out: - return NULL; + return ERR_PTR(-ENOENT); found: *res_page = page; @@ -431,19 +435,19 @@ struct nilfs_dir_entry *nilfs_dotdot(struct inode *dir, struct page **p) return NULL; } -ino_t nilfs_inode_by_name(struct inode *dir, const struct qstr *qstr) +int nilfs_inode_by_name(struct inode *dir, const struct qstr *qstr, ino_t *ino) { - ino_t res = 0; struct nilfs_dir_entry *de; struct page *page; de = nilfs_find_entry(dir, qstr, &page); - if (de) { - res = le64_to_cpu(de->inode); - kunmap(page); - put_page(page); - } - return res; + if (IS_ERR(de)) + return PTR_ERR(de); + + *ino = le64_to_cpu(de->inode); + kunmap(page); + put_page(page); + return 0; } /* Releases the page */ diff --git a/fs/nilfs2/namei.c b/fs/nilfs2/namei.c index a6ec7961d4f5..08c6d985edeb 100644 --- a/fs/nilfs2/namei.c +++ b/fs/nilfs2/namei.c @@ -55,12 +55,20 @@ nilfs_lookup(struct inode *dir, struct dentry *dentry, unsigned int flags) { struct inode *inode; ino_t ino; + int res; if (dentry->d_name.len > NILFS_NAME_LEN) return ERR_PTR(-ENAMETOOLONG); - ino = nilfs_inode_by_name(dir, &dentry->d_name); - inode = ino ? nilfs_iget(dir->i_sb, NILFS_I(dir)->i_root, ino) : NULL; + res = nilfs_inode_by_name(dir, &dentry->d_name, &ino); + if (res) { + if (res != -ENOENT) + return ERR_PTR(res); + inode = NULL; + } else { + inode = nilfs_iget(dir->i_sb, NILFS_I(dir)->i_root, ino); + } + return d_splice_alias(inode, dentry); } @@ -261,10 +269,11 @@ static int nilfs_do_unlink(struct inode *dir, struct dentry *dentry) struct page *page; int err; - err = -ENOENT; de = nilfs_find_entry(dir, &dentry->d_name, &page); - if (!de) + if (IS_ERR(de)) { + err = PTR_ERR(de); goto out; + } inode = d_inode(dentry); err = -EIO; @@ -358,10 +367,11 @@ static int nilfs_rename(struct inode *old_dir, struct dentry *old_dentry, if (unlikely(err)) return err; - err = -ENOENT; old_de = nilfs_find_entry(old_dir, &old_dentry->d_name, &old_page); - if (!old_de) + if (IS_ERR(old_de)) { + err = PTR_ERR(old_de); goto out; + } if (S_ISDIR(old_inode->i_mode)) { err = -EIO; @@ -378,10 +388,12 @@ static int nilfs_rename(struct inode *old_dir, struct dentry *old_dentry, if (dir_de && !nilfs_empty_dir(new_inode)) goto out_dir; - err = -ENOENT; - new_de = nilfs_find_entry(new_dir, &new_dentry->d_name, &new_page); - if (!new_de) + new_de = nilfs_find_entry(new_dir, &new_dentry->d_name, + &new_page); + if (IS_ERR(new_de)) { + err = PTR_ERR(new_de); goto out_dir; + } nilfs_set_link(new_dir, new_de, new_page, old_inode); nilfs_mark_inode_dirty(new_dir); new_inode->i_ctime = current_time(new_inode); @@ -435,14 +447,15 @@ static int nilfs_rename(struct inode *old_dir, struct dentry *old_dentry, */ static struct dentry *nilfs_get_parent(struct dentry *child) { - unsigned long ino; + ino_t ino; + int res; struct inode *inode; struct qstr dotdot = QSTR_INIT("..", 2); struct nilfs_root *root; - ino = nilfs_inode_by_name(d_inode(child), &dotdot); - if (!ino) - return ERR_PTR(-ENOENT); + res = nilfs_inode_by_name(d_inode(child), &dotdot, &ino); + if (res) + return ERR_PTR(res); root = NILFS_I(d_inode(child))->i_root; diff --git a/fs/nilfs2/nilfs.h b/fs/nilfs2/nilfs.h index 3f3971e0292d..e1b230a5011a 100644 --- a/fs/nilfs2/nilfs.h +++ b/fs/nilfs2/nilfs.h @@ -233,7 +233,7 @@ static inline __u32 nilfs_mask_flags(umode_t mode, __u32 flags) /* dir.c */ extern int nilfs_add_link(struct dentry *, struct inode *); -extern ino_t nilfs_inode_by_name(struct inode *, const struct qstr *); +int nilfs_inode_by_name(struct inode *dir, const struct qstr *qstr, ino_t *ino); extern int nilfs_make_empty(struct inode *, struct inode *); extern struct nilfs_dir_entry * nilfs_find_entry(struct inode *, const struct qstr *, struct page **); diff --git a/fs/ocfs2/aops.c b/fs/ocfs2/aops.c index 1a5f23e79f5e..667d63d23f8f 100644 --- a/fs/ocfs2/aops.c +++ b/fs/ocfs2/aops.c @@ -158,9 +158,8 @@ int ocfs2_get_block(struct inode *inode, sector_t iblock, err = ocfs2_extent_map_get_blocks(inode, iblock, &p_blkno, &count, &ext_flags); if (err) { - mlog(ML_ERROR, "Error %d from get_blocks(0x%p, %llu, 1, " - "%llu, NULL)\n", err, inode, (unsigned long long)iblock, - (unsigned long long)p_blkno); + mlog(ML_ERROR, "get_blocks() failed, inode: 0x%p, " + "block: %llu\n", inode, (unsigned long long)iblock); goto bail; } diff --git a/fs/ocfs2/buffer_head_io.c b/fs/ocfs2/buffer_head_io.c index f0b104e483d8..c8a6e3480be1 100644 --- a/fs/ocfs2/buffer_head_io.c +++ b/fs/ocfs2/buffer_head_io.c @@ -237,7 +237,6 @@ int ocfs2_read_blocks(struct ocfs2_caching_info *ci, u64 block, int nr, if (bhs[i] == NULL) { bhs[i] = sb_getblk(sb, block++); if (bhs[i] == NULL) { - ocfs2_metadata_cache_io_unlock(ci); status = -ENOMEM; mlog_errno(status); /* Don't forget to put previous bh! */ @@ -391,7 +390,8 @@ int ocfs2_read_blocks(struct ocfs2_caching_info *ci, u64 block, int nr, /* Always set the buffer in the cache, even if it was * a forced read, or read-ahead which hasn't yet * completed. */ - ocfs2_set_buffer_uptodate(ci, bh); + if (bh) + ocfs2_set_buffer_uptodate(ci, bh); } ocfs2_metadata_cache_io_unlock(ci); diff --git a/fs/ocfs2/journal.c b/fs/ocfs2/journal.c index dfa6ff2756fb..c319495988b6 100644 --- a/fs/ocfs2/journal.c +++ b/fs/ocfs2/journal.c @@ -996,7 +996,7 @@ void ocfs2_journal_shutdown(struct ocfs2_super *osb) if (!igrab(inode)) BUG(); - num_running_trans = atomic_read(&(osb->journal->j_num_trans)); + num_running_trans = atomic_read(&(journal->j_num_trans)); trace_ocfs2_journal_shutdown(num_running_trans); /* Do a commit_cache here. It will flush our journal, *and* @@ -1015,9 +1015,10 @@ void ocfs2_journal_shutdown(struct ocfs2_super *osb) osb->commit_task = NULL; } - BUG_ON(atomic_read(&(osb->journal->j_num_trans)) != 0); + BUG_ON(atomic_read(&(journal->j_num_trans)) != 0); - if (ocfs2_mount_local(osb)) { + if (ocfs2_mount_local(osb) && + (journal->j_journal->j_flags & JBD2_LOADED)) { jbd2_journal_lock_updates(journal->j_journal); status = jbd2_journal_flush(journal->j_journal); jbd2_journal_unlock_updates(journal->j_journal); diff --git a/fs/ocfs2/localalloc.c b/fs/ocfs2/localalloc.c index fc8252a28cb1..67c39fe20969 100644 --- a/fs/ocfs2/localalloc.c +++ b/fs/ocfs2/localalloc.c @@ -1010,6 +1010,25 @@ static int ocfs2_sync_local_to_main(struct ocfs2_super *osb, start = bit_off + 1; } + /* clear the contiguous bits until the end boundary */ + if (count) { + blkno = la_start_blk + + ocfs2_clusters_to_blocks(osb->sb, + start - count); + + trace_ocfs2_sync_local_to_main_free( + count, start - count, + (unsigned long long)la_start_blk, + (unsigned long long)blkno); + + status = ocfs2_release_clusters(handle, + main_bm_inode, + main_bm_bh, blkno, + count); + if (status < 0) + mlog_errno(status); + } + bail: if (status) mlog_errno(status); diff --git a/fs/ocfs2/quota_local.c b/fs/ocfs2/quota_local.c index b1a8b046f4c2..7a1c8da9e44b 100644 --- a/fs/ocfs2/quota_local.c +++ b/fs/ocfs2/quota_local.c @@ -689,7 +689,7 @@ static int ocfs2_local_read_info(struct super_block *sb, int type) int status; struct buffer_head *bh = NULL; struct ocfs2_quota_recovery *rec; - int locked = 0; + int locked = 0, global_read = 0; info->dqi_max_spc_limit = 0x7fffffffffffffffLL; info->dqi_max_ino_limit = 0x7fffffffffffffffLL; @@ -697,6 +697,7 @@ static int ocfs2_local_read_info(struct super_block *sb, int type) if (!oinfo) { mlog(ML_ERROR, "failed to allocate memory for ocfs2 quota" " info."); + status = -ENOMEM; goto out_err; } info->dqi_priv = oinfo; @@ -709,6 +710,7 @@ static int ocfs2_local_read_info(struct super_block *sb, int type) status = ocfs2_global_read_info(sb, type); if (status < 0) goto out_err; + global_read = 1; status = ocfs2_inode_lock(lqinode, &oinfo->dqi_lqi_bh, 1); if (status < 0) { @@ -779,10 +781,12 @@ static int ocfs2_local_read_info(struct super_block *sb, int type) if (locked) ocfs2_inode_unlock(lqinode, 1); ocfs2_release_local_quota_bitmaps(&oinfo->dqi_chunk); + if (global_read) + cancel_delayed_work_sync(&oinfo->dqi_sync_work); kfree(oinfo); } brelse(bh); - return -1; + return status; } /* Write local info to quota file */ diff --git a/fs/ocfs2/refcounttree.c b/fs/ocfs2/refcounttree.c index 3b397fa9c9e8..85d25c211c87 100644 --- a/fs/ocfs2/refcounttree.c +++ b/fs/ocfs2/refcounttree.c @@ -27,6 +27,7 @@ #include "namei.h" #include "ocfs2_trace.h" #include "file.h" +#include "symlink.h" #include #include @@ -4184,8 +4185,9 @@ static int __ocfs2_reflink(struct dentry *old_dentry, int ret; struct inode *inode = d_inode(old_dentry); struct buffer_head *new_bh = NULL; + struct ocfs2_inode_info *oi = OCFS2_I(inode); - if (OCFS2_I(inode)->ip_flags & OCFS2_INODE_SYSTEM_FILE) { + if (oi->ip_flags & OCFS2_INODE_SYSTEM_FILE) { ret = -EINVAL; mlog_errno(ret); goto out; @@ -4211,6 +4213,26 @@ static int __ocfs2_reflink(struct dentry *old_dentry, goto out_unlock; } + if ((oi->ip_dyn_features & OCFS2_HAS_XATTR_FL) && + (oi->ip_dyn_features & OCFS2_INLINE_XATTR_FL)) { + /* + * Adjust extent record count to reserve space for extended attribute. + * Inline data count had been adjusted in ocfs2_duplicate_inline_data(). + */ + struct ocfs2_inode_info *new_oi = OCFS2_I(new_inode); + + if (!(new_oi->ip_dyn_features & OCFS2_INLINE_DATA_FL) && + !(ocfs2_inode_is_fast_symlink(new_inode))) { + struct ocfs2_dinode *new_di = (struct ocfs2_dinode *)new_bh->b_data; + struct ocfs2_dinode *old_di = (struct ocfs2_dinode *)old_bh->b_data; + struct ocfs2_extent_list *el = &new_di->id2.i_list; + int inline_size = le16_to_cpu(old_di->i_xattr_inline_size); + + le16_add_cpu(&el->l_count, -(inline_size / + sizeof(struct ocfs2_extent_rec))); + } + } + ret = ocfs2_create_reflink_node(inode, old_bh, new_inode, new_bh, preserve); if (ret) { @@ -4218,7 +4240,7 @@ static int __ocfs2_reflink(struct dentry *old_dentry, goto inode_unlock; } - if (OCFS2_I(inode)->ip_dyn_features & OCFS2_HAS_XATTR_FL) { + if (oi->ip_dyn_features & OCFS2_HAS_XATTR_FL) { ret = ocfs2_reflink_xattrs(inode, old_bh, new_inode, new_bh, preserve); diff --git a/fs/ocfs2/xattr.c b/fs/ocfs2/xattr.c index 8b7df5e0f0c2..20bc3d9de25c 100644 --- a/fs/ocfs2/xattr.c +++ b/fs/ocfs2/xattr.c @@ -1068,13 +1068,13 @@ ssize_t ocfs2_listxattr(struct dentry *dentry, return i_ret + b_ret; } -static int ocfs2_xattr_find_entry(int name_index, +static int ocfs2_xattr_find_entry(struct inode *inode, int name_index, const char *name, struct ocfs2_xattr_search *xs) { struct ocfs2_xattr_entry *entry; size_t name_len; - int i, cmp = 1; + int i, name_offset, cmp = 1; if (name == NULL) return -EINVAL; @@ -1082,13 +1082,22 @@ static int ocfs2_xattr_find_entry(int name_index, name_len = strlen(name); entry = xs->here; for (i = 0; i < le16_to_cpu(xs->header->xh_count); i++) { + if ((void *)entry >= xs->end) { + ocfs2_error(inode->i_sb, "corrupted xattr entries"); + return -EFSCORRUPTED; + } cmp = name_index - ocfs2_xattr_get_type(entry); if (!cmp) cmp = name_len - entry->xe_name_len; - if (!cmp) - cmp = memcmp(name, (xs->base + - le16_to_cpu(entry->xe_name_offset)), - name_len); + if (!cmp) { + name_offset = le16_to_cpu(entry->xe_name_offset); + if ((xs->base + name_offset + name_len) > xs->end) { + ocfs2_error(inode->i_sb, + "corrupted xattr entries"); + return -EFSCORRUPTED; + } + cmp = memcmp(name, (xs->base + name_offset), name_len); + } if (cmp == 0) break; entry += 1; @@ -1172,7 +1181,7 @@ static int ocfs2_xattr_ibody_get(struct inode *inode, xs->base = (void *)xs->header; xs->here = xs->header->xh_entries; - ret = ocfs2_xattr_find_entry(name_index, name, xs); + ret = ocfs2_xattr_find_entry(inode, name_index, name, xs); if (ret) return ret; size = le64_to_cpu(xs->here->xe_value_size); @@ -2704,7 +2713,7 @@ static int ocfs2_xattr_ibody_find(struct inode *inode, /* Find the named attribute. */ if (oi->ip_dyn_features & OCFS2_INLINE_XATTR_FL) { - ret = ocfs2_xattr_find_entry(name_index, name, xs); + ret = ocfs2_xattr_find_entry(inode, name_index, name, xs); if (ret && ret != -ENODATA) return ret; xs->not_found = ret; @@ -2839,7 +2848,7 @@ static int ocfs2_xattr_block_find(struct inode *inode, xs->end = (void *)(blk_bh->b_data) + blk_bh->b_size; xs->here = xs->header->xh_entries; - ret = ocfs2_xattr_find_entry(name_index, name, xs); + ret = ocfs2_xattr_find_entry(inode, name_index, name, xs); } else ret = ocfs2_xattr_index_block_find(inode, blk_bh, name_index, @@ -6517,16 +6526,7 @@ static int ocfs2_reflink_xattr_inline(struct ocfs2_xattr_reflink *args) } new_oi = OCFS2_I(args->new_inode); - /* - * Adjust extent record count to reserve space for extended attribute. - * Inline data count had been adjusted in ocfs2_duplicate_inline_data(). - */ - if (!(new_oi->ip_dyn_features & OCFS2_INLINE_DATA_FL) && - !(ocfs2_inode_is_fast_symlink(args->new_inode))) { - struct ocfs2_extent_list *el = &new_di->id2.i_list; - le16_add_cpu(&el->l_count, -(inline_size / - sizeof(struct ocfs2_extent_rec))); - } + spin_lock(&new_oi->ip_lock); new_oi->ip_dyn_features |= OCFS2_HAS_XATTR_FL | OCFS2_INLINE_XATTR_FL; new_di->i_dyn_features = cpu_to_le16(new_oi->ip_dyn_features); diff --git a/fs/proc/base.c b/fs/proc/base.c index 8b1ecb57d06a..ae7970d15e8e 100644 --- a/fs/proc/base.c +++ b/fs/proc/base.c @@ -86,6 +86,7 @@ #include #include #include +#include #include #include #include @@ -116,6 +117,40 @@ static u8 nlink_tid __ro_after_init; static u8 nlink_tgid __ro_after_init; +enum proc_mem_force { + PROC_MEM_FORCE_ALWAYS, + PROC_MEM_FORCE_PTRACE, + PROC_MEM_FORCE_NEVER +}; + +static enum proc_mem_force proc_mem_force_override __ro_after_init = + IS_ENABLED(CONFIG_PROC_MEM_NO_FORCE) ? PROC_MEM_FORCE_NEVER : + IS_ENABLED(CONFIG_PROC_MEM_FORCE_PTRACE) ? PROC_MEM_FORCE_PTRACE : + PROC_MEM_FORCE_ALWAYS; + +static const struct constant_table proc_mem_force_table[] __initconst = { + { "always", PROC_MEM_FORCE_ALWAYS }, + { "ptrace", PROC_MEM_FORCE_PTRACE }, + { "never", PROC_MEM_FORCE_NEVER }, + { } +}; + +static int __init early_proc_mem_force_override(char *buf) +{ + if (!buf) + return -EINVAL; + + /* + * lookup_constant() defaults to proc_mem_force_override to preseve + * the initial Kconfig choice in case an invalid param gets passed. + */ + proc_mem_force_override = lookup_constant(proc_mem_force_table, + buf, proc_mem_force_override); + + return 0; +} +early_param("proc_mem.force_override", early_proc_mem_force_override); + struct pid_entry { const char *name; unsigned int len; @@ -833,6 +868,28 @@ static int mem_open(struct inode *inode, struct file *file) return ret; } +static bool proc_mem_foll_force(struct file *file, struct mm_struct *mm) +{ + struct task_struct *task; + bool ptrace_active = false; + + switch (proc_mem_force_override) { + case PROC_MEM_FORCE_NEVER: + return false; + case PROC_MEM_FORCE_PTRACE: + task = get_proc_task(file_inode(file)); + if (task) { + ptrace_active = READ_ONCE(task->ptrace) && + READ_ONCE(task->mm) == mm && + READ_ONCE(task->parent) == current; + put_task_struct(task); + } + return ptrace_active; + default: + return true; + } +} + static ssize_t mem_rw(struct file *file, char __user *buf, size_t count, loff_t *ppos, int write) { @@ -853,7 +910,9 @@ static ssize_t mem_rw(struct file *file, char __user *buf, if (!mmget_not_zero(mm)) goto free; - flags = FOLL_FORCE | (write ? FOLL_WRITE : 0); + flags = write ? FOLL_WRITE : 0; + if (proc_mem_foll_force(file, mm)) + flags |= FOLL_FORCE; while (count > 0) { size_t this_len = min_t(size_t, count, PAGE_SIZE); diff --git a/fs/super.c b/fs/super.c index 8fc308d26bb6..27b3da60add1 100644 --- a/fs/super.c +++ b/fs/super.c @@ -476,6 +476,8 @@ void generic_shutdown_super(struct super_block *sb) spin_unlock(&sb_lock); up_write(&sb->s_umount); if (sb->s_bdi != &noop_backing_dev_info) { + if (sb->s_iflags & SB_I_PERSB_BDI) + bdi_unregister(sb->s_bdi); bdi_put(sb->s_bdi); sb->s_bdi = &noop_backing_dev_info; } @@ -1634,6 +1636,7 @@ int super_setup_bdi_name(struct super_block *sb, char *fmt, ...) } WARN_ON(sb->s_bdi != &noop_backing_dev_info); sb->s_bdi = bdi; + sb->s_iflags |= SB_I_PERSB_BDI; return 0; } diff --git a/include/drm/drm_print.h b/include/drm/drm_print.h index f32d179e139d..037b51c166e1 100644 --- a/include/drm/drm_print.h +++ b/include/drm/drm_print.h @@ -121,7 +121,8 @@ drm_vprintf(struct drm_printer *p, const char *fmt, va_list *va) /** * struct drm_print_iterator - local struct used with drm_printer_coredump - * @data: Pointer to the devcoredump output buffer + * @data: Pointer to the devcoredump output buffer, can be NULL if using + * drm_printer_coredump to determine size of devcoredump * @start: The offset within the buffer to start writing * @remain: The number of bytes to write for this iteration */ @@ -166,6 +167,57 @@ struct drm_print_iterator { * coredump_read, ...) * } * + * The above example has a time complexity of O(N^2), where N is the size of the + * devcoredump. This is acceptable for small devcoredumps but scales poorly for + * larger ones. + * + * Another use case for drm_coredump_printer is to capture the devcoredump into + * a saved buffer before the dev_coredump() callback. This involves two passes: + * one to determine the size of the devcoredump and another to print it to a + * buffer. Then, in dev_coredump(), copy from the saved buffer into the + * devcoredump read buffer. + * + * For example:: + * + * char *devcoredump_saved_buffer; + * + * ssize_t __coredump_print(char *buffer, ssize_t count, ...) + * { + * struct drm_print_iterator iter; + * struct drm_printer p; + * + * iter.data = buffer; + * iter.start = 0; + * iter.remain = count; + * + * p = drm_coredump_printer(&iter); + * + * drm_printf(p, "foo=%d\n", foo); + * ... + * return count - iter.remain; + * } + * + * void coredump_print(...) + * { + * ssize_t count; + * + * count = __coredump_print(NULL, INT_MAX, ...); + * devcoredump_saved_buffer = kvmalloc(count, GFP_KERNEL); + * __coredump_print(devcoredump_saved_buffer, count, ...); + * } + * + * void coredump_read(char *buffer, loff_t offset, size_t count, + * void *data, size_t datalen) + * { + * ... + * memcpy(buffer, devcoredump_saved_buffer + offset, count); + * ... + * } + * + * The above example has a time complexity of O(N*2), where N is the size of the + * devcoredump. This scales better than the previous example for larger + * devcoredumps. + * * RETURNS: * The &drm_printer object */ diff --git a/include/linux/fs.h b/include/linux/fs.h index 78ff398be77b..cacd0e53228c 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -1436,6 +1436,8 @@ extern int send_sigurg(struct fown_struct *fown); #define SB_I_UNTRUSTED_MOUNTER 0x00000040 #define SB_I_SKIP_SYNC 0x00000100 /* Skip superblock at global sync */ +#define SB_I_PERSB_BDI 0x00000200 /* has a per-sb bdi */ +#define SB_I_TS_EXPIRY_WARNED 0x00000400 /* warned about timestamp range expiry */ /* Possible states of 'frozen' field */ enum { diff --git a/include/linux/fsl/enetc_mdio.h b/include/linux/fsl/enetc_mdio.h index 2d9203314865..b90c4dc50b7d 100644 --- a/include/linux/fsl/enetc_mdio.h +++ b/include/linux/fsl/enetc_mdio.h @@ -48,7 +48,8 @@ static inline int enetc_mdio_read(struct mii_bus *bus, int phy_id, int regnum) static inline int enetc_mdio_write(struct mii_bus *bus, int phy_id, int regnum, u16 value) { return -EINVAL; } -struct enetc_hw *enetc_hw_alloc(struct device *dev, void __iomem *port_regs) +static inline struct enetc_hw *enetc_hw_alloc(struct device *dev, + void __iomem *port_regs) { return ERR_PTR(-EINVAL); } #endif diff --git a/include/linux/irqchip/arm-gic-v4.h b/include/linux/irqchip/arm-gic-v4.h index 943c3411ca10..a767453a6c2a 100644 --- a/include/linux/irqchip/arm-gic-v4.h +++ b/include/linux/irqchip/arm-gic-v4.h @@ -58,10 +58,12 @@ struct its_vpe { bool enabled; bool group; } sgi_config[16]; - atomic_t vmapp_count; }; }; + /* Track the VPE being mapped */ + atomic_t vmapp_count; + /* * Ensures mutual exclusion between affinity setting of the * vPE and vLPI operations using vpe->col_idx. diff --git a/include/linux/kallsyms.h b/include/linux/kallsyms.h index 481273f0c72d..4dbf49cc8f77 100644 --- a/include/linux/kallsyms.h +++ b/include/linux/kallsyms.h @@ -164,6 +164,11 @@ static inline bool kallsyms_show_value(const struct cred *cred) return false; } +static inline int kallsyms_on_each_symbol(int (*fn)(void *, const char *, struct module *, + unsigned long), void *data) +{ + return -EOPNOTSUPP; +} #endif /*CONFIG_KALLSYMS*/ static inline void print_ip_sym(const char *loglvl, unsigned long ip) diff --git a/include/linux/nfs_fs_sb.h b/include/linux/nfs_fs_sb.h index 38e60ec742df..cb2cb4d9c013 100644 --- a/include/linux/nfs_fs_sb.h +++ b/include/linux/nfs_fs_sb.h @@ -230,6 +230,7 @@ struct nfs_server { struct list_head layouts; struct list_head delegations; struct list_head ss_copies; + struct list_head ss_src_copies; unsigned long mig_gen; unsigned long mig_status; diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h index 9394950dbbe5..fdae1e7aa4c2 100644 --- a/include/linux/pci_ids.h +++ b/include/linux/pci_ids.h @@ -2659,6 +2659,8 @@ #define PCI_DEVICE_ID_DCI_PCCOM8 0x0002 #define PCI_DEVICE_ID_DCI_PCCOM2 0x0004 +#define PCI_VENDOR_ID_GLENFLY 0x6766 + #define PCI_VENDOR_ID_INTEL 0x8086 #define PCI_DEVICE_ID_INTEL_EESSC 0x0008 #define PCI_DEVICE_ID_INTEL_PXHD_0 0x0320 diff --git a/include/linux/vdpa.h b/include/linux/vdpa.h index 30bc7a7223bb..2ee60c7c1eb0 100644 --- a/include/linux/vdpa.h +++ b/include/linux/vdpa.h @@ -11,10 +11,16 @@ * vDPA callback definition. * @callback: interrupt callback function * @private: the data passed to the callback function + * @trigger: the eventfd for the callback (Optional). + * When it is set, the vDPA driver must guarantee that + * signaling it is functional equivalent to triggering + * the callback. Then vDPA parent can signal it directly + * instead of triggering the callback. */ struct vdpa_callback { irqreturn_t (*callback)(void *data); void *private; + struct eventfd_ctx *trigger; }; /** diff --git a/include/net/ip_tunnels.h b/include/net/ip_tunnels.h index 219b407a6607..fede588f5502 100644 --- a/include/net/ip_tunnels.h +++ b/include/net/ip_tunnels.h @@ -335,9 +335,10 @@ static inline bool pskb_inet_may_pull(struct sk_buff *skb) /* Variant of pskb_inet_may_pull(). */ -static inline bool skb_vlan_inet_prepare(struct sk_buff *skb) +static inline bool skb_vlan_inet_prepare(struct sk_buff *skb, + bool inner_proto_inherit) { - int nhlen = 0, maclen = ETH_HLEN; + int nhlen = 0, maclen = inner_proto_inherit ? 0 : ETH_HLEN; __be16 type = skb->protocol; /* Essentially this is skb_protocol(skb, true) diff --git a/include/net/netfilter/nf_tables.h b/include/net/netfilter/nf_tables.h index 3cc25a5faa23..484f9cdf2dd0 100644 --- a/include/net/netfilter/nf_tables.h +++ b/include/net/netfilter/nf_tables.h @@ -262,9 +262,22 @@ struct nft_set_elem { void *priv; }; +/** + * enum nft_iter_type - nftables set iterator type + * + * @NFT_ITER_READ: read-only iteration over set elements + * @NFT_ITER_UPDATE: iteration under mutex to update set element state + */ +enum nft_iter_type { + NFT_ITER_UNSPEC, + NFT_ITER_READ, + NFT_ITER_UPDATE, +}; + struct nft_set; struct nft_set_iter { u8 genmask; + enum nft_iter_type type:8; unsigned int count; unsigned int skip; int err; diff --git a/include/net/sch_generic.h b/include/net/sch_generic.h index c9b94829a61a..31ba4b744d8b 100644 --- a/include/net/sch_generic.h +++ b/include/net/sch_generic.h @@ -833,7 +833,6 @@ static inline void qdisc_calculate_pkt_len(struct sk_buff *skb, static inline int qdisc_enqueue(struct sk_buff *skb, struct Qdisc *sch, struct sk_buff **to_free) { - qdisc_calculate_pkt_len(skb, sch); return sch->enqueue(skb, sch, to_free); } diff --git a/include/net/sock.h b/include/net/sock.h index e995fa74b813..6568f9661748 100644 --- a/include/net/sock.h +++ b/include/net/sock.h @@ -853,6 +853,8 @@ static inline void sk_add_bind_node(struct sock *sk, hlist_for_each_entry_safe(__sk, tmp, list, sk_node) #define sk_for_each_bound(__sk, list) \ hlist_for_each_entry(__sk, list, sk_bind_node) +#define sk_for_each_bound_safe(__sk, tmp, list) \ + hlist_for_each_entry_safe(__sk, tmp, list, sk_bind_node) /** * sk_for_each_entry_offset_rcu - iterate over a list at a given struct offset diff --git a/include/net/tcp.h b/include/net/tcp.h index fdb68618ce3f..202790ae7cd4 100644 --- a/include/net/tcp.h +++ b/include/net/tcp.h @@ -2117,9 +2117,26 @@ static inline s64 tcp_rto_delta_us(const struct sock *sk) { const struct sk_buff *skb = tcp_rtx_queue_head(sk); u32 rto = inet_csk(sk)->icsk_rto; - u64 rto_time_stamp_us = tcp_skb_timestamp_us(skb) + jiffies_to_usecs(rto); - return rto_time_stamp_us - tcp_sk(sk)->tcp_mstamp; + if (likely(skb)) { + u64 rto_time_stamp_us = tcp_skb_timestamp_us(skb) + jiffies_to_usecs(rto); + + return rto_time_stamp_us - tcp_sk(sk)->tcp_mstamp; + } else { + WARN_ONCE(1, + "rtx queue emtpy: " + "out:%u sacked:%u lost:%u retrans:%u " + "tlp_high_seq:%u sk_state:%u ca_state:%u " + "advmss:%u mss_cache:%u pmtu:%u\n", + tcp_sk(sk)->packets_out, tcp_sk(sk)->sacked_out, + tcp_sk(sk)->lost_out, tcp_sk(sk)->retrans_out, + tcp_sk(sk)->tlp_high_seq, sk->sk_state, + inet_csk(sk)->icsk_ca_state, + tcp_sk(sk)->advmss, tcp_sk(sk)->mss_cache, + inet_csk(sk)->icsk_pmtu_cookie); + return jiffies_to_usecs(rto); + } + } /* diff --git a/include/trace/events/f2fs.h b/include/trace/events/f2fs.h index 92bf715db0aa..a6e790c03363 100644 --- a/include/trace/events/f2fs.h +++ b/include/trace/events/f2fs.h @@ -147,7 +147,8 @@ TRACE_DEFINE_ENUM(EX_BLOCK_AGE); { CP_NODE_NEED_CP, "node needs cp" }, \ { CP_FASTBOOT_MODE, "fastboot mode" }, \ { CP_SPEC_LOG_NUM, "log type is 2" }, \ - { CP_RECOVER_DIR, "dir needs recovery" }) + { CP_RECOVER_DIR, "dir needs recovery" }, \ + { CP_XATTR_DIR, "dir's xattr updated" }) #define show_shutdown_mode(type) \ __print_symbolic(type, \ diff --git a/include/trace/events/sched.h b/include/trace/events/sched.h index bcd7f1fbb8cd..0270a2d6dec0 100644 --- a/include/trace/events/sched.h +++ b/include/trace/events/sched.h @@ -5,6 +5,7 @@ #if !defined(_TRACE_SCHED_H) || defined(TRACE_HEADER_MULTI_READ) #define _TRACE_SCHED_H +#include #include #include #include @@ -51,6 +52,89 @@ TRACE_EVENT(sched_kthread_stop_ret, TP_printk("ret=%d", __entry->ret) ); +/** + * sched_kthread_work_queue_work - called when a work gets queued + * @worker: pointer to the kthread_worker + * @work: pointer to struct kthread_work + * + * This event occurs when a work is queued immediately or once a + * delayed work is actually queued (ie: once the delay has been + * reached). + */ +TRACE_EVENT(sched_kthread_work_queue_work, + + TP_PROTO(struct kthread_worker *worker, + struct kthread_work *work), + + TP_ARGS(worker, work), + + TP_STRUCT__entry( + __field( void *, work ) + __field( void *, function) + __field( void *, worker) + ), + + TP_fast_assign( + __entry->work = work; + __entry->function = work->func; + __entry->worker = worker; + ), + + TP_printk("work struct=%p function=%ps worker=%p", + __entry->work, __entry->function, __entry->worker) +); + +/** + * sched_kthread_work_execute_start - called immediately before the work callback + * @work: pointer to struct kthread_work + * + * Allows to track kthread work execution. + */ +TRACE_EVENT(sched_kthread_work_execute_start, + + TP_PROTO(struct kthread_work *work), + + TP_ARGS(work), + + TP_STRUCT__entry( + __field( void *, work ) + __field( void *, function) + ), + + TP_fast_assign( + __entry->work = work; + __entry->function = work->func; + ), + + TP_printk("work struct %p: function %ps", __entry->work, __entry->function) +); + +/** + * sched_kthread_work_execute_end - called immediately after the work callback + * @work: pointer to struct work_struct + * @function: pointer to worker function + * + * Allows to track workqueue execution. + */ +TRACE_EVENT(sched_kthread_work_execute_end, + + TP_PROTO(struct kthread_work *work, kthread_work_func_t function), + + TP_ARGS(work, function), + + TP_STRUCT__entry( + __field( void *, work ) + __field( void *, function) + ), + + TP_fast_assign( + __entry->work = work; + __entry->function = function; + ), + + TP_printk("work struct %p: function %ps", __entry->work, __entry->function) +); + /* * Tracepoint for waking up a task: */ diff --git a/include/trace/hooks/mm.h b/include/trace/hooks/mm.h index d502c69069f1..ee3c5aaa0a58 100644 --- a/include/trace/hooks/mm.h +++ b/include/trace/hooks/mm.h @@ -370,6 +370,10 @@ DECLARE_HOOK(android_vh_do_swap_page_spf, DECLARE_HOOK(android_vh_tune_fault_around_bytes, TP_PROTO(unsigned long *fault_around_bytes), TP_ARGS(fault_around_bytes)); +DECLARE_HOOK(android_vh_io_statistics, + TP_PROTO(struct address_space *mapping, unsigned int index, + unsigned int nr_page, bool read, bool direct), + TP_ARGS(mapping, index, nr_page, read, direct)); DECLARE_HOOK(android_vh_do_anonymous_page, TP_PROTO(struct vm_area_struct *vma, struct page *page), TP_ARGS(vma, page)); diff --git a/include/uapi/linux/cec.h b/include/uapi/linux/cec.h index dc8879d179fd..570527734743 100644 --- a/include/uapi/linux/cec.h +++ b/include/uapi/linux/cec.h @@ -132,6 +132,8 @@ static inline void cec_msg_init(struct cec_msg *msg, * Set the msg destination to the orig initiator and the msg initiator to the * orig destination. Note that msg and orig may be the same pointer, in which * case the change is done in place. + * + * It also zeroes the reply, timeout and flags fields. */ static inline void cec_msg_set_reply_to(struct cec_msg *msg, struct cec_msg *orig) @@ -139,7 +141,9 @@ static inline void cec_msg_set_reply_to(struct cec_msg *msg, /* The destination becomes the initiator and vice versa */ msg->msg[0] = (cec_msg_destination(orig) << 4) | cec_msg_initiator(orig); - msg->reply = msg->timeout = 0; + msg->reply = 0; + msg->timeout = 0; + msg->flags = 0; } /* cec_msg flags field */ diff --git a/include/uapi/linux/if_link.h b/include/uapi/linux/if_link.h index c4b23f06f69e..9334f2128bb2 100644 --- a/include/uapi/linux/if_link.h +++ b/include/uapi/linux/if_link.h @@ -761,6 +761,7 @@ enum { IFLA_GENEVE_LABEL, IFLA_GENEVE_TTL_INHERIT, IFLA_GENEVE_DF, + IFLA_GENEVE_INNER_PROTO_INHERIT, __IFLA_GENEVE_MAX }; #define IFLA_GENEVE_MAX (__IFLA_GENEVE_MAX - 1) diff --git a/include/uapi/linux/netfilter/nf_tables.h b/include/uapi/linux/netfilter/nf_tables.h index 40d900537093..702bcb7c9c73 100644 --- a/include/uapi/linux/netfilter/nf_tables.h +++ b/include/uapi/linux/netfilter/nf_tables.h @@ -1602,7 +1602,7 @@ enum nft_flowtable_flags { * * @NFTA_FLOWTABLE_TABLE: name of the table containing the expression (NLA_STRING) * @NFTA_FLOWTABLE_NAME: name of this flow table (NLA_STRING) - * @NFTA_FLOWTABLE_HOOK: netfilter hook configuration(NLA_U32) + * @NFTA_FLOWTABLE_HOOK: netfilter hook configuration (NLA_NESTED) * @NFTA_FLOWTABLE_USE: number of references to this flow table (NLA_U32) * @NFTA_FLOWTABLE_HANDLE: object handle (NLA_U64) * @NFTA_FLOWTABLE_FLAGS: flags (NLA_U32) diff --git a/io_uring/io_uring.c b/io_uring/io_uring.c index 44107baa6e8d..fc4423ba5a6a 100644 --- a/io_uring/io_uring.c +++ b/io_uring/io_uring.c @@ -56,6 +56,7 @@ #include #include #include +#include #include #include #include @@ -1589,7 +1590,14 @@ static inline bool io_sqring_full(struct io_ring_ctx *ctx) { struct io_rings *r = ctx->rings; - return READ_ONCE(r->sq.tail) - ctx->cached_sq_head == ctx->sq_entries; + /* + * SQPOLL must use the actual sqring head, as using the cached_sq_head + * is race prone if the SQPOLL thread has grabbed entries but not yet + * committed them to the ring. For !SQPOLL, this doesn't matter, but + * since this helper is just used for SQPOLL sqring waits (or POLLOUT), + * just read the actual sqring head unconditionally. + */ + return READ_ONCE(r->sq.tail) - READ_ONCE(r->sq.head) == ctx->sq_entries; } static inline unsigned int __io_cqring_events(struct io_ring_ctx *ctx) @@ -8581,11 +8589,22 @@ static int io_sq_offload_create(struct io_ring_ctx *ctx, return 0; if (p->flags & IORING_SETUP_SQ_AFF) { + cpumask_var_t allowed_mask; int cpu = p->sq_thread_cpu; ret = -EINVAL; if (cpu >= nr_cpu_ids || !cpu_online(cpu)) goto err_sqpoll; + ret = -ENOMEM; + if (!alloc_cpumask_var(&allowed_mask, GFP_KERNEL)) + goto err_sqpoll; + ret = -EINVAL; + cpuset_cpus_allowed(current, allowed_mask); + if (!cpumask_test_cpu(cpu, allowed_mask)) { + free_cpumask_var(allowed_mask); + goto err_sqpoll; + } + free_cpumask_var(allowed_mask); sqd->sq_cpu = cpu; } else { sqd->sq_cpu = -1; diff --git a/kernel/bpf/arraymap.c b/kernel/bpf/arraymap.c index f241bda2679d..00546c9f4064 100644 --- a/kernel/bpf/arraymap.c +++ b/kernel/bpf/arraymap.c @@ -74,6 +74,9 @@ int array_map_alloc_check(union bpf_attr *attr) * access the elements. */ return -E2BIG; + /* percpu map value size is bound by PCPU_MIN_UNIT_SIZE */ + if (percpu && round_up(attr->value_size, 8) > PCPU_MIN_UNIT_SIZE) + return -E2BIG; return 0; } diff --git a/kernel/bpf/devmap.c b/kernel/bpf/devmap.c index 07b5edb2c70f..7eb1282edc8e 100644 --- a/kernel/bpf/devmap.c +++ b/kernel/bpf/devmap.c @@ -109,6 +109,8 @@ static inline struct hlist_head *dev_map_index_hash(struct bpf_dtab *dtab, static int dev_map_init_map(struct bpf_dtab *dtab, union bpf_attr *attr) { u32 valsize = attr->value_size; + u64 cost = 0; + int err; /* check sanity of attributes. 2 value sizes supported: * 4 bytes: ifindex @@ -136,11 +138,21 @@ static int dev_map_init_map(struct bpf_dtab *dtab, union bpf_attr *attr) return -EINVAL; dtab->n_buckets = roundup_pow_of_two(dtab->map.max_entries); + cost += (u64) sizeof(struct hlist_head) * dtab->n_buckets; + } else { + cost += (u64) dtab->map.max_entries * sizeof(struct bpf_dtab_netdev *); + } + /* if map size is larger than memlock limit, reject it */ + err = bpf_map_charge_init(&dtab->map.memory, cost); + if (err) + return -EINVAL; + + if (attr->map_type == BPF_MAP_TYPE_DEVMAP_HASH) { dtab->dev_index_head = dev_map_create_hash(dtab->n_buckets, dtab->map.numa_node); if (!dtab->dev_index_head) - return -ENOMEM; + goto free_charge; spin_lock_init(&dtab->index_lock); } else { @@ -148,10 +160,14 @@ static int dev_map_init_map(struct bpf_dtab *dtab, union bpf_attr *attr) sizeof(struct bpf_dtab_netdev *), dtab->map.numa_node); if (!dtab->netdev_map) - return -ENOMEM; + goto free_charge; } return 0; + +free_charge: + bpf_map_charge_finish(&dtab->map.memory); + return -ENOMEM; } static struct bpf_map *dev_map_alloc(union bpf_attr *attr) diff --git a/kernel/bpf/hashtab.c b/kernel/bpf/hashtab.c index d05614a2bdc7..fdcbb7f6b1d5 100644 --- a/kernel/bpf/hashtab.c +++ b/kernel/bpf/hashtab.c @@ -404,6 +404,9 @@ static int htab_map_alloc_check(union bpf_attr *attr) * kmalloc-able later in htab_map_update_elem() */ return -E2BIG; + /* percpu map value size is bound by PCPU_MIN_UNIT_SIZE */ + if (percpu && round_up(attr->value_size, 8) > PCPU_MIN_UNIT_SIZE) + return -E2BIG; return 0; } diff --git a/kernel/bpf/helpers.c b/kernel/bpf/helpers.c index 084ac7e42919..31e3a5482156 100644 --- a/kernel/bpf/helpers.c +++ b/kernel/bpf/helpers.c @@ -497,7 +497,7 @@ static int __bpf_strtoll(const char *buf, size_t buf_len, u64 flags, } BPF_CALL_4(bpf_strtol, const char *, buf, size_t, buf_len, u64, flags, - long *, res) + s64 *, res) { long long _res; int err; @@ -522,7 +522,7 @@ const struct bpf_func_proto bpf_strtol_proto = { }; BPF_CALL_4(bpf_strtoul, const char *, buf, size_t, buf_len, u64, flags, - unsigned long *, res) + u64 *, res) { unsigned long long _res; bool is_negative; diff --git a/kernel/bpf/trampoline.c b/kernel/bpf/trampoline.c index 3988776e1628..57f653a6a88c 100644 --- a/kernel/bpf/trampoline.c +++ b/kernel/bpf/trampoline.c @@ -89,18 +89,6 @@ static struct bpf_trampoline *bpf_trampoline_lookup(u64 key) return tr; } -static int is_ftrace_location(void *ip) -{ - long addr; - - addr = ftrace_location((long)ip); - if (!addr) - return 0; - if (WARN_ON_ONCE(addr != (long)ip)) - return -EFAULT; - return 1; -} - static int unregister_fentry(struct bpf_trampoline *tr, void *old_addr) { void *ip = tr->func.addr; @@ -129,12 +117,12 @@ static int modify_fentry(struct bpf_trampoline *tr, void *old_addr, void *new_ad static int register_fentry(struct bpf_trampoline *tr, void *new_addr) { void *ip = tr->func.addr; + unsigned long faddr; int ret; - ret = is_ftrace_location(ip); - if (ret < 0) - return ret; - tr->func.ftrace_managed = ret; + faddr = ftrace_location((unsigned long)ip); + if (faddr) + tr->func.ftrace_managed = true; if (tr->func.ftrace_managed) ret = register_ftrace_direct((long)ip, (long)new_addr); diff --git a/kernel/events/core.c b/kernel/events/core.c index 9fbd63813b0e..8e308ca0a389 100644 --- a/kernel/events/core.c +++ b/kernel/events/core.c @@ -4003,7 +4003,11 @@ static void perf_adjust_period(struct perf_event *event, u64 nsec, u64 count, bo period = perf_calculate_period(event, nsec, count); delta = (s64)(period - hwc->sample_period); - delta = (delta + 7) / 8; /* low pass filter */ + if (delta >= 0) + delta += 7; + else + delta -= 7; + delta /= 8; /* low pass filter */ sample_period = hwc->sample_period + delta; diff --git a/kernel/events/uprobes.c b/kernel/events/uprobes.c index 66d64b184ade..9f7386a35620 100644 --- a/kernel/events/uprobes.c +++ b/kernel/events/uprobes.c @@ -1500,7 +1500,7 @@ static struct xol_area *__create_xol_area(unsigned long vaddr) area->xol_mapping.name = "[uprobes]"; area->xol_mapping.pages = area->pages; - area->pages[0] = alloc_page(GFP_HIGHUSER); + area->pages[0] = alloc_page(GFP_HIGHUSER | __GFP_ZERO); if (!area->pages[0]) goto free_bitmap; area->pages[1] = NULL; diff --git a/kernel/kprobes.c b/kernel/kprobes.c index c8e62458d323..551ac118159f 100644 --- a/kernel/kprobes.c +++ b/kernel/kprobes.c @@ -1609,14 +1609,10 @@ static inline int check_kprobe_rereg(struct kprobe *p) int __weak arch_check_ftrace_location(struct kprobe *p) { - unsigned long ftrace_addr; + unsigned long addr = (unsigned long)p->addr; - ftrace_addr = ftrace_location((unsigned long)p->addr); - if (ftrace_addr) { + if (ftrace_location(addr) == addr) { #ifdef CONFIG_KPROBES_ON_FTRACE - /* Given address is not on the instruction boundary */ - if ((unsigned long)p->addr != ftrace_addr) - return -EILSEQ; p->flags |= KPROBE_FLAG_FTRACE; #else /* !CONFIG_KPROBES_ON_FTRACE */ return -EINVAL; diff --git a/kernel/kthread.c b/kernel/kthread.c index 9d736f57b84f..de881a05242b 100644 --- a/kernel/kthread.c +++ b/kernel/kthread.c @@ -751,10 +751,25 @@ int kthread_worker_fn(void *worker_ptr) raw_spin_unlock_irq(&worker->lock); if (work) { + kthread_work_func_t func = work->func; __set_current_state(TASK_RUNNING); + trace_sched_kthread_work_execute_start(work); work->func(work); - } else if (!freezing(current)) + /* + * Avoid dereferencing work after this point. The trace + * event only cares about the address. + */ + trace_sched_kthread_work_execute_end(work, func); + } else if (!freezing(current)) { schedule(); + } else { + /* + * Handle the case where the current remains + * TASK_INTERRUPTIBLE. try_to_freeze() expects + * the current to be TASK_RUNNING. + */ + __set_current_state(TASK_RUNNING); + } try_to_freeze(); cond_resched(); @@ -881,6 +896,8 @@ static void kthread_insert_work(struct kthread_worker *worker, { kthread_insert_work_sanity_check(worker, work); + trace_sched_kthread_work_queue_work(worker, work); + list_add_tail(&work->node, pos); work->worker = worker; if (!worker->current_work && likely(worker->task)) diff --git a/kernel/locking/lockdep.c b/kernel/locking/lockdep.c index 7471d85f54ae..b576dd00516b 100644 --- a/kernel/locking/lockdep.c +++ b/kernel/locking/lockdep.c @@ -5967,25 +5967,27 @@ static struct pending_free *get_pending_free(void) static void free_zapped_rcu(struct rcu_head *cb); /* - * Schedule an RCU callback if no RCU callback is pending. Must be called with - * the graph lock held. - */ -static void call_rcu_zapped(struct pending_free *pf) +* See if we need to queue an RCU callback, must called with +* the lockdep lock held, returns false if either we don't have +* any pending free or the callback is already scheduled. +* Otherwise, a call_rcu() must follow this function call. +*/ +static bool prepare_call_rcu_zapped(struct pending_free *pf) { WARN_ON_ONCE(inside_selftest()); if (list_empty(&pf->zapped)) - return; + return false; if (delayed_free.scheduled) - return; + return false; delayed_free.scheduled = true; WARN_ON_ONCE(delayed_free.pf + delayed_free.index != pf); delayed_free.index ^= 1; - call_rcu(&delayed_free.rcu_head, free_zapped_rcu); + return true; } /* The caller must hold the graph lock. May be called from RCU context. */ @@ -6011,6 +6013,7 @@ static void free_zapped_rcu(struct rcu_head *ch) { struct pending_free *pf; unsigned long flags; + bool need_callback; if (WARN_ON_ONCE(ch != &delayed_free.rcu_head)) return; @@ -6022,14 +6025,18 @@ static void free_zapped_rcu(struct rcu_head *ch) pf = delayed_free.pf + (delayed_free.index ^ 1); __free_zapped_classes(pf); delayed_free.scheduled = false; - - /* - * If there's anything on the open list, close and start a new callback. - */ - call_rcu_zapped(delayed_free.pf + delayed_free.index); - + need_callback = + prepare_call_rcu_zapped(delayed_free.pf + delayed_free.index); lockdep_unlock(); raw_local_irq_restore(flags); + + /* + * If there's pending free and its callback has not been scheduled, + * queue an RCU callback. + */ + if (need_callback) + call_rcu(&delayed_free.rcu_head, free_zapped_rcu); + } /* @@ -6069,6 +6076,7 @@ static void lockdep_free_key_range_reg(void *start, unsigned long size) { struct pending_free *pf; unsigned long flags; + bool need_callback; init_data_structures_once(); @@ -6076,10 +6084,11 @@ static void lockdep_free_key_range_reg(void *start, unsigned long size) lockdep_lock(); pf = get_pending_free(); __lockdep_free_key_range(pf, start, size); - call_rcu_zapped(pf); + need_callback = prepare_call_rcu_zapped(pf); lockdep_unlock(); raw_local_irq_restore(flags); - + if (need_callback) + call_rcu(&delayed_free.rcu_head, free_zapped_rcu); /* * Wait for any possible iterators from look_up_lock_class() to pass * before continuing to free the memory they refer to. @@ -6173,6 +6182,7 @@ static void lockdep_reset_lock_reg(struct lockdep_map *lock) struct pending_free *pf; unsigned long flags; int locked; + bool need_callback = false; raw_local_irq_save(flags); locked = graph_lock(); @@ -6181,11 +6191,13 @@ static void lockdep_reset_lock_reg(struct lockdep_map *lock) pf = get_pending_free(); __lockdep_reset_lock(pf, lock); - call_rcu_zapped(pf); + need_callback = prepare_call_rcu_zapped(pf); graph_unlock(); out_irq: raw_local_irq_restore(flags); + if (need_callback) + call_rcu(&delayed_free.rcu_head, free_zapped_rcu); } /* @@ -6229,6 +6241,7 @@ void lockdep_unregister_key(struct lock_class_key *key) struct pending_free *pf; unsigned long flags; bool found = false; + bool need_callback = false; might_sleep(); @@ -6249,11 +6262,14 @@ void lockdep_unregister_key(struct lock_class_key *key) if (found) { pf = get_pending_free(); __lockdep_free_key_range(pf, key, 1); - call_rcu_zapped(pf); + need_callback = prepare_call_rcu_zapped(pf); } lockdep_unlock(); raw_local_irq_restore(flags); + if (need_callback) + call_rcu(&delayed_free.rcu_head, free_zapped_rcu); + /* Wait until is_dynamic_key() has finished accessing k->hash_entry. */ synchronize_rcu(); } diff --git a/kernel/padata.c b/kernel/padata.c index 2a514cf8379b..914a88d9cee1 100644 --- a/kernel/padata.c +++ b/kernel/padata.c @@ -409,7 +409,8 @@ void padata_do_serial(struct padata_priv *padata) /* Sort in ascending order of sequence number. */ list_for_each_prev(pos, &reorder->list) { cur = list_entry(pos, struct padata_priv, list); - if (cur->seq_nr < padata->seq_nr) + /* Compare by difference to consider integer wrap around */ + if ((signed int)(cur->seq_nr - padata->seq_nr) < 0) break; } list_add(&padata->list, pos); @@ -516,9 +517,12 @@ void __init padata_do_multithreaded(struct padata_mt_job *job) * thread function. Load balance large jobs between threads by * increasing the number of chunks, guarantee at least the minimum * chunk size from the caller, and honor the caller's alignment. + * Ensure chunk_size is at least 1 to prevent divide-by-0 + * panic in padata_mt_helper(). */ ps.chunk_size = job->size / (ps.nworks * load_balance_factor); ps.chunk_size = max(ps.chunk_size, job->min_chunk); + ps.chunk_size = max(ps.chunk_size, 1ul); ps.chunk_size = roundup(ps.chunk_size, job->align); /* diff --git a/kernel/rcu/rcuscale.c b/kernel/rcu/rcuscale.c index 3b9783eda679..cfe861bac1bd 100644 --- a/kernel/rcu/rcuscale.c +++ b/kernel/rcu/rcuscale.c @@ -398,7 +398,7 @@ rcu_scale_writer(void *arg) udelay(writer_holdoff); wdp = &wdpp[i]; *wdp = ktime_get_mono_fast_ns(); - if (gp_async) { + if (gp_async && !WARN_ON_ONCE(!cur_ops->async)) { retry: if (!rhp) rhp = kmalloc(sizeof(*rhp), GFP_KERNEL); @@ -454,7 +454,7 @@ rcu_scale_writer(void *arg) i++; rcu_scale_wait_shutdown(); } while (!torture_must_stop()); - if (gp_async) { + if (gp_async && cur_ops->async) { cur_ops->gp_barrier(); } writer_n_durations[me] = i_max + 1; diff --git a/kernel/resource.c b/kernel/resource.c index 100253d4909c..1087f33d70c4 100644 --- a/kernel/resource.c +++ b/kernel/resource.c @@ -539,21 +539,63 @@ EXPORT_SYMBOL_GPL(page_is_ram); int region_intersects(resource_size_t start, size_t size, unsigned long flags, unsigned long desc) { - struct resource res; + resource_size_t ostart, oend; int type = 0; int other = 0; - struct resource *p; + struct resource *p, *dp; + bool is_type, covered; + struct resource res; res.start = start; res.end = start + size - 1; read_lock(&resource_lock); for (p = iomem_resource.child; p ; p = p->sibling) { - bool is_type = (((p->flags & flags) == flags) && - ((desc == IORES_DESC_NONE) || - (desc == p->desc))); - - if (resource_overlaps(p, &res)) - is_type ? type++ : other++; + if (!resource_overlaps(p, &res)) + continue; + is_type = (p->flags & flags) == flags && + (desc == IORES_DESC_NONE || desc == p->desc); + if (is_type) { + type++; + continue; + } + /* + * Continue to search in descendant resources as if the + * matched descendant resources cover some ranges of 'p'. + * + * |------------- "CXL Window 0" ------------| + * |-- "System RAM" --| + * + * will behave similar as the following fake resource + * tree when searching "System RAM". + * + * |-- "System RAM" --||-- "CXL Window 0a" --| + */ + covered = false; + ostart = max(res.start, p->start); + oend = min(res.end, p->end); + for (dp = p->child; dp; dp = next_resource(dp, false)) { + if (!resource_overlaps(dp, &res)) + continue; + is_type = (dp->flags & flags) == flags && + (desc == IORES_DESC_NONE || desc == dp->desc); + if (is_type) { + type++; + /* + * Range from 'ostart' to 'dp->start' + * isn't covered by matched resource. + */ + if (dp->start > ostart) + break; + if (dp->end >= oend) { + covered = true; + break; + } + /* Remove covered range */ + ostart = max(ostart, dp->end + 1); + } + } + if (!covered) + other++; } read_unlock(&resource_lock); diff --git a/kernel/signal.c b/kernel/signal.c index 1b8107e71c30..3e4144f1864b 100644 --- a/kernel/signal.c +++ b/kernel/signal.c @@ -1829,10 +1829,11 @@ struct sigqueue *sigqueue_alloc(void) void sigqueue_free(struct sigqueue *q) { - unsigned long flags; spinlock_t *lock = ¤t->sighand->siglock; + unsigned long flags; - BUG_ON(!(q->flags & SIGQUEUE_PREALLOC)); + if (WARN_ON_ONCE(!(q->flags & SIGQUEUE_PREALLOC))) + return; /* * We must hold ->siglock while testing q->list * to serialize with collect_signal() or with @@ -1860,7 +1861,10 @@ int send_sigqueue(struct sigqueue *q, struct pid *pid, enum pid_type type) unsigned long flags; int ret, result; - BUG_ON(!(q->flags & SIGQUEUE_PREALLOC)); + if (WARN_ON_ONCE(!(q->flags & SIGQUEUE_PREALLOC))) + return 0; + if (WARN_ON_ONCE(q->info.si_code != SI_TIMER)) + return 0; ret = -1; rcu_read_lock(); @@ -1879,7 +1883,6 @@ int send_sigqueue(struct sigqueue *q, struct pid *pid, enum pid_type type) * If an SI_TIMER entry is already queue just increment * the overrun count. */ - BUG_ON(q->info.si_code != SI_TIMER); q->info.si_overrun++; result = TRACE_SIGNAL_ALREADY_PENDING; goto out; @@ -4574,6 +4577,7 @@ __weak const char *arch_vma_name(struct vm_area_struct *vma) { return NULL; } +EXPORT_SYMBOL_GPL(arch_vma_name); static inline void siginfo_buildtime_checks(void) { diff --git a/kernel/time/posix-clock.c b/kernel/time/posix-clock.c index 77c0c2370b6d..8127673bfc45 100644 --- a/kernel/time/posix-clock.c +++ b/kernel/time/posix-clock.c @@ -299,6 +299,9 @@ static int pc_clock_settime(clockid_t id, const struct timespec64 *ts) goto out; } + if (!timespec64_valid_strict(ts)) + return -EINVAL; + if (cd.clk->ops.clock_settime) err = cd.clk->ops.clock_settime(cd.clk, ts); else diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c index 31fec924b7c4..36182e7e0cd7 100644 --- a/kernel/trace/ftrace.c +++ b/kernel/trace/ftrace.c @@ -1566,26 +1566,43 @@ static struct dyn_ftrace *lookup_rec(unsigned long start, unsigned long end) unsigned long ftrace_location_range(unsigned long start, unsigned long end) { struct dyn_ftrace *rec; + unsigned long ip = 0; + rcu_read_lock(); rec = lookup_rec(start, end); if (rec) - return rec->ip; + ip = rec->ip; + rcu_read_unlock(); - return 0; + return ip; } /** - * ftrace_location - return true if the ip giving is a traced location + * ftrace_location - return the ftrace location * @ip: the instruction pointer to check * - * Returns rec->ip if @ip given is a pointer to a ftrace location. - * That is, the instruction that is either a NOP or call to - * the function tracer. It checks the ftrace internal tables to - * determine if the address belongs or not. + * If @ip matches the ftrace location, return @ip. + * If @ip matches sym+0, return sym's ftrace location. + * Otherwise, return 0. */ unsigned long ftrace_location(unsigned long ip) { - return ftrace_location_range(ip, ip); + unsigned long loc; + unsigned long offset; + unsigned long size; + + loc = ftrace_location_range(ip, ip); + if (!loc) { + if (!kallsyms_lookup_size_offset(ip, &size, &offset)) + goto out; + + /* map sym+0 to __fentry__ */ + if (!offset) + loc = ftrace_location_range(ip, ip + size - 1); + } + +out: + return loc; } /** @@ -4948,7 +4965,8 @@ ftrace_match_addr(struct ftrace_hash *hash, unsigned long ip, int remove) { struct ftrace_func_entry *entry; - if (!ftrace_location(ip)) + ip = ftrace_location(ip); + if (!ip) return -EINVAL; if (remove) { @@ -5096,11 +5114,16 @@ int register_ftrace_direct(unsigned long ip, unsigned long addr) struct ftrace_func_entry *entry; struct ftrace_hash *free_hash = NULL; struct dyn_ftrace *rec; - int ret = -EBUSY; + int ret = -ENODEV; mutex_lock(&direct_mutex); + ip = ftrace_location(ip); + if (!ip) + goto out_unlock; + /* See if there's a direct function at @ip already */ + ret = -EBUSY; if (ftrace_find_rec_direct(ip)) goto out_unlock; @@ -5229,6 +5252,10 @@ int unregister_ftrace_direct(unsigned long ip, unsigned long addr) mutex_lock(&direct_mutex); + ip = ftrace_location(ip); + if (!ip) + goto out_unlock; + entry = find_direct_entry(&ip, NULL); if (!entry) goto out_unlock; @@ -5360,6 +5387,11 @@ int modify_ftrace_direct(unsigned long ip, mutex_lock(&direct_mutex); mutex_lock(&ftrace_lock); + + ip = ftrace_location(ip); + if (!ip) + goto out_unlock; + entry = find_direct_entry(&ip, &rec); if (!entry) goto out_unlock; @@ -6299,6 +6331,8 @@ static int ftrace_process_locs(struct module *mod, /* We should have used all pages unless we skipped some */ if (pg_unuse) { WARN_ON(!skipped); + /* Need to synchronize with ftrace_location_range() */ + synchronize_rcu(); ftrace_free_pages(pg_unuse); } return ret; @@ -6481,6 +6515,9 @@ void ftrace_release_mod(struct module *mod) out_unlock: mutex_unlock(&ftrace_lock); + /* Need to synchronize with ftrace_location_range() */ + if (tmp_page) + synchronize_rcu(); for (pg = tmp_page; pg; pg = tmp_page) { /* Needs to be called outside of ftrace_lock */ @@ -6803,6 +6840,7 @@ void ftrace_free_mem(struct module *mod, void *start_ptr, void *end_ptr) unsigned long start = (unsigned long)(start_ptr); unsigned long end = (unsigned long)(end_ptr); struct ftrace_page **last_pg = &ftrace_pages_start; + struct ftrace_page *tmp_page = NULL; struct ftrace_page *pg; struct dyn_ftrace *rec; struct dyn_ftrace key; @@ -6846,12 +6884,8 @@ void ftrace_free_mem(struct module *mod, void *start_ptr, void *end_ptr) ftrace_update_tot_cnt--; if (!pg->index) { *last_pg = pg->next; - if (pg->records) { - free_pages((unsigned long)pg->records, pg->order); - ftrace_number_of_pages -= 1 << pg->order; - } - ftrace_number_of_groups--; - kfree(pg); + pg->next = tmp_page; + tmp_page = pg; pg = container_of(last_pg, struct ftrace_page, next); if (!(*last_pg)) ftrace_pages = pg; @@ -6868,6 +6902,11 @@ void ftrace_free_mem(struct module *mod, void *start_ptr, void *end_ptr) clear_func_from_hashes(func); kfree(func); } + /* Need to synchronize with ftrace_location_range() */ + if (tmp_page) { + synchronize_rcu(); + ftrace_free_pages(tmp_page); + } } void __init ftrace_free_init_mem(void) diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c index 38896363adba..34515380cdcc 100644 --- a/kernel/trace/trace.c +++ b/kernel/trace/trace.c @@ -2244,6 +2244,10 @@ struct saved_cmdlines_buffer { }; static struct saved_cmdlines_buffer *savedcmd; +/* Holds the size of a cmdline and pid element */ +#define SAVED_CMDLINE_MAP_ELEMENT_SIZE(s) \ + (TASK_COMM_LEN + sizeof((s)->map_cmdline_to_pid[0])) + static inline char *get_saved_cmdlines(int idx) { return &savedcmd->saved_cmdlines[idx * TASK_COMM_LEN]; @@ -2258,7 +2262,6 @@ static void free_saved_cmdlines_buffer(struct saved_cmdlines_buffer *s) { int order = get_order(sizeof(*s) + s->cmdline_num * TASK_COMM_LEN); - kfree(s->map_cmdline_to_pid); kmemleak_free(s); free_pages((unsigned long)s, order); } @@ -2271,7 +2274,7 @@ static struct saved_cmdlines_buffer *allocate_cmdlines_buffer(unsigned int val) int order; /* Figure out how much is needed to hold the given number of cmdlines */ - orig_size = sizeof(*s) + val * TASK_COMM_LEN; + orig_size = sizeof(*s) + val * SAVED_CMDLINE_MAP_ELEMENT_SIZE(s); order = get_order(orig_size); size = 1 << (order + PAGE_SHIFT); page = alloc_pages(GFP_KERNEL, order); @@ -2283,16 +2286,11 @@ static struct saved_cmdlines_buffer *allocate_cmdlines_buffer(unsigned int val) memset(s, 0, sizeof(*s)); /* Round up to actual allocation */ - val = (size - sizeof(*s)) / TASK_COMM_LEN; + val = (size - sizeof(*s)) / SAVED_CMDLINE_MAP_ELEMENT_SIZE(s); s->cmdline_num = val; - s->map_cmdline_to_pid = kmalloc_array(val, - sizeof(*s->map_cmdline_to_pid), - GFP_KERNEL); - if (!s->map_cmdline_to_pid) { - free_saved_cmdlines_buffer(s); - return NULL; - } + /* Place map_cmdline_to_pid array right after saved_cmdlines */ + s->map_cmdline_to_pid = (unsigned *)&s->saved_cmdlines[val * TASK_COMM_LEN]; s->cmdline_idx = 0; memset(&s->map_pid_to_cmdline, NO_CMDLINE_MAP, diff --git a/kernel/trace/trace_kprobe.c b/kernel/trace/trace_kprobe.c index 718357289899..b3f9ad0dd5d1 100644 --- a/kernel/trace/trace_kprobe.c +++ b/kernel/trace/trace_kprobe.c @@ -715,6 +715,38 @@ static inline void sanitize_event_name(char *name) *name = '_'; } +struct count_symbols_struct { + const char *func_name; + unsigned int count; +}; + +static int count_symbols(void *data, const char *name, struct module *unused0, + unsigned long unused1) +{ + struct count_symbols_struct *args = data; + + if (strcmp(args->func_name, name)) + return 0; + + args->count++; + + return 0; +} + +static unsigned int number_of_same_symbols(char *func_name) +{ + struct count_symbols_struct args = { + .func_name = func_name, + .count = 0, + }; + + kallsyms_on_each_symbol(count_symbols, &args); + + module_kallsyms_on_each_symbol(count_symbols, &args); + + return args.count; +} + static int trace_kprobe_create(int argc, const char *argv[]) { /* @@ -842,6 +874,31 @@ static int trace_kprobe_create(int argc, const char *argv[]) } } + if (symbol && !strchr(symbol, ':')) { + unsigned int count; + + count = number_of_same_symbols(symbol); + if (count > 1) { + /* + * Users should use ADDR to remove the ambiguity of + * using KSYM only. + */ + trace_probe_log_err(0, NON_UNIQ_SYMBOL); + ret = -EADDRNOTAVAIL; + + goto error; + } else if (count == 0) { + /* + * We can return ENOENT earlier than when register the + * kprobe. + */ + trace_probe_log_err(0, BAD_PROBE_ADDR); + ret = -ENOENT; + + goto error; + } + } + trace_probe_log_set_index(0); if (event) { ret = traceprobe_parse_event_name(&event, &group, buf, @@ -1805,6 +1862,7 @@ static int unregister_kprobe_event(struct trace_kprobe *tk) } #ifdef CONFIG_PERF_EVENTS + /* create a trace_kprobe, but don't add it to global lists */ struct trace_event_call * create_local_trace_kprobe(char *func, void *addr, unsigned long offs, @@ -1814,6 +1872,24 @@ create_local_trace_kprobe(char *func, void *addr, unsigned long offs, int ret; char *event; + if (func) { + unsigned int count; + + count = number_of_same_symbols(func); + if (count > 1) + /* + * Users should use addr to remove the ambiguity of + * using func only. + */ + return ERR_PTR(-EADDRNOTAVAIL); + else if (count == 0) + /* + * We can return ENOENT earlier than when register the + * kprobe. + */ + return ERR_PTR(-ENOENT); + } + /* * local trace_kprobes are not added to dyn_event, so they are never * searched in find_trace_kprobe(). Therefore, there is no concern of diff --git a/kernel/trace/trace_output.c b/kernel/trace/trace_output.c index 469d7675003f..b3ee8d9b6b62 100644 --- a/kernel/trace/trace_output.c +++ b/kernel/trace/trace_output.c @@ -1303,12 +1303,11 @@ static enum print_line_t trace_print_print(struct trace_iterator *iter, { struct print_entry *field; struct trace_seq *s = &iter->seq; - int max = iter->ent_size - offsetof(struct print_entry, buf); trace_assign_type(field, iter->ent); seq_print_ip_sym(s, field->ip, flags); - trace_seq_printf(s, ": %.*s", max, field->buf); + trace_seq_printf(s, ": %s", field->buf); return trace_handle_return(s); } @@ -1317,11 +1316,10 @@ static enum print_line_t trace_print_raw(struct trace_iterator *iter, int flags, struct trace_event *event) { struct print_entry *field; - int max = iter->ent_size - offsetof(struct print_entry, buf); trace_assign_type(field, iter->ent); - trace_seq_printf(&iter->seq, "# %lx %.*s", field->ip, max, field->buf); + trace_seq_printf(&iter->seq, "# %lx %s", field->ip, field->buf); return trace_handle_return(&iter->seq); } diff --git a/kernel/trace/trace_probe.c b/kernel/trace/trace_probe.c index 073abbe3866b..1893fe5460ac 100644 --- a/kernel/trace/trace_probe.c +++ b/kernel/trace/trace_probe.c @@ -256,7 +256,7 @@ int traceprobe_parse_event_name(const char **pevent, const char **pgroup, if (len == 0) { trace_probe_log_err(offset, NO_EVENT_NAME); return -EINVAL; - } else if (len > MAX_EVENT_NAME_LEN) { + } else if (len >= MAX_EVENT_NAME_LEN) { trace_probe_log_err(offset, EVENT_TOO_LONG); return -EINVAL; } diff --git a/kernel/trace/trace_probe.h b/kernel/trace/trace_probe.h index d4a69b83902e..22c05ca97758 100644 --- a/kernel/trace/trace_probe.h +++ b/kernel/trace/trace_probe.h @@ -390,6 +390,7 @@ extern int traceprobe_define_arg_fields(struct trace_event_call *event_call, C(BAD_MAXACT, "Invalid maxactive number"), \ C(MAXACT_TOO_BIG, "Maxactive is too big"), \ C(BAD_PROBE_ADDR, "Invalid probed address or symbol"), \ + C(NON_UNIQ_SYMBOL, "The symbol is not unique"), \ C(BAD_RETPROBE, "Retprobe address must be an function entry"), \ C(BAD_ADDR_SUFFIX, "Invalid probed address suffix"), \ C(NO_GROUP_NAME, "Group name is not specified"), \ diff --git a/lib/Makefile b/lib/Makefile index 1864a5e89741..ccd4164597c6 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -350,6 +350,7 @@ obj-$(CONFIG_OBJAGG) += objagg.o obj-$(CONFIG_PLDMFW) += pldmfw/ # KUnit tests +CFLAGS_bitfield_kunit.o := $(DISABLE_STRUCTLEAK_PLUGIN) obj-$(CONFIG_BITFIELD_KUNIT) += bitfield_kunit.o obj-$(CONFIG_LIST_KUNIT_TEST) += list-test.o obj-$(CONFIG_LINEAR_RANGES_TEST) += test_linear_ranges.o diff --git a/lib/debugobjects.c b/lib/debugobjects.c index b055741a5a4d..49fc61c08ee3 100644 --- a/lib/debugobjects.c +++ b/lib/debugobjects.c @@ -144,13 +144,14 @@ static void fill_pool(void) * READ_ONCE()s pair with the WRITE_ONCE()s in pool_lock critical * sections. */ - while (READ_ONCE(obj_nr_tofree) && (READ_ONCE(obj_pool_free) < obj_pool_min_free)) { + while (READ_ONCE(obj_nr_tofree) && + READ_ONCE(obj_pool_free) < debug_objects_pool_min_level) { raw_spin_lock_irqsave(&pool_lock, flags); /* * Recheck with the lock held as the worker thread might have * won the race and freed the global free list already. */ - while (obj_nr_tofree && (obj_pool_free < obj_pool_min_free)) { + while (obj_nr_tofree && (obj_pool_free < debug_objects_pool_min_level)) { obj = hlist_entry(obj_to_free.first, typeof(*obj), node); hlist_del(&obj->node); WRITE_ONCE(obj_nr_tofree, obj_nr_tofree - 1); diff --git a/lib/xz/xz_crc32.c b/lib/xz/xz_crc32.c index 88a2c35e1b59..5627b00fca29 100644 --- a/lib/xz/xz_crc32.c +++ b/lib/xz/xz_crc32.c @@ -29,7 +29,7 @@ STATIC_RW_DATA uint32_t xz_crc32_table[256]; XZ_EXTERN void xz_crc32_init(void) { - const uint32_t poly = CRC32_POLY_LE; + const uint32_t poly = 0xEDB88320; uint32_t i; uint32_t j; diff --git a/lib/xz/xz_private.h b/lib/xz/xz_private.h index 09360ebb510e..482b90f363fe 100644 --- a/lib/xz/xz_private.h +++ b/lib/xz/xz_private.h @@ -102,10 +102,6 @@ # endif #endif -#ifndef CRC32_POLY_LE -#define CRC32_POLY_LE 0xedb88320 -#endif - /* * Allocate memory for LZMA2 decoder. xz_dec_lzma2_reset() must be used * before calling xz_dec_lzma2_run(). diff --git a/mm/filemap.c b/mm/filemap.c index 580c1b90b605..70f130898938 100644 --- a/mm/filemap.c +++ b/mm/filemap.c @@ -3525,6 +3525,7 @@ ssize_t generic_perform_write(struct file *file, break; copied = status; + trace_android_vh_io_statistics(mapping, page->index, 1, false, false); cond_resched(); iov_iter_advance(i, copied); diff --git a/mm/huge_memory.c b/mm/huge_memory.c index 14bc79900736..25bc945d2ab4 100644 --- a/mm/huge_memory.c +++ b/mm/huge_memory.c @@ -1906,6 +1906,7 @@ spinlock_t *__pmd_trans_huge_lock(pmd_t *pmd, struct vm_area_struct *vma) spin_unlock(ptl); return NULL; } +EXPORT_SYMBOL_GPL(__pmd_trans_huge_lock); /* * Returns true if a given pud maps a thp, false otherwise. diff --git a/mm/memory.c b/mm/memory.c index 2aeeef494103..82f775ec57a6 100644 --- a/mm/memory.c +++ b/mm/memory.c @@ -698,6 +698,7 @@ struct page *_vm_normal_page(struct vm_area_struct *vma, unsigned long addr, out: return pfn_to_page(pfn); } +EXPORT_SYMBOL_GPL(_vm_normal_page); #ifdef CONFIG_TRANSPARENT_HUGEPAGE struct page *vm_normal_page_pmd(struct vm_area_struct *vma, unsigned long addr, diff --git a/mm/mremap.c b/mm/mremap.c index 57b73944bfbc..e357dc0b829f 100644 --- a/mm/mremap.c +++ b/mm/mremap.c @@ -210,44 +210,11 @@ static void move_ptes(struct vm_area_struct *vma, pmd_t *old_pmd, drop_rmap_locks(vma); } -#ifdef CONFIG_SPECULATIVE_PAGE_FAULT -static inline bool trylock_vma_ref_count(struct vm_area_struct *vma) -{ - /* - * If we have the only reference, swap the refcount to -1. This - * will prevent other concurrent references by get_vma() for SPFs. - */ - return atomic_cmpxchg_acquire(&vma->vm_ref_count, 1, -1) == 1; -} - -/* - * Restore the VMA reference count to 1 after a fast mremap. - */ -static inline void unlock_vma_ref_count(struct vm_area_struct *vma) -{ - int old = atomic_xchg_release(&vma->vm_ref_count, 1); - - /* - * This should only be called after a corresponding, - * successful trylock_vma_ref_count(). - */ - VM_BUG_ON_VMA(old != -1, vma); -} -#else /* !CONFIG_SPECULATIVE_PAGE_FAULT */ -static inline bool trylock_vma_ref_count(struct vm_area_struct *vma) -{ - return true; -} -static inline void unlock_vma_ref_count(struct vm_area_struct *vma) -{ -} -#endif /* CONFIG_SPECULATIVE_PAGE_FAULT */ - #ifdef CONFIG_HAVE_MOVE_PMD static bool move_normal_pmd(struct vm_area_struct *vma, unsigned long old_addr, unsigned long new_addr, pmd_t *old_pmd, pmd_t *new_pmd) { - spinlock_t *old_ptl, *new_ptl; + spinlock_t *old_ptl, *new_ptl, *old_pte_ptl; struct mm_struct *mm = vma->vm_mm; pmd_t pmd; @@ -277,14 +244,6 @@ static bool move_normal_pmd(struct vm_area_struct *vma, unsigned long old_addr, if (WARN_ON_ONCE(!pmd_none(*new_pmd))) return false; - /* - * We hold both exclusive mmap_lock and rmap_lock at this point and - * cannot block. If we cannot immediately take exclusive ownership - * of the VMA fallback to the move_ptes(). - */ - if (!trylock_vma_ref_count(vma)) - return false; - /* * We don't have to worry about the ordering of src and dst * ptlocks because exclusive mmap_lock prevents deadlock. @@ -294,6 +253,24 @@ static bool move_normal_pmd(struct vm_area_struct *vma, unsigned long old_addr, if (new_ptl != old_ptl) spin_lock_nested(new_ptl, SINGLE_DEPTH_NESTING); + /* + * If SPF is enabled, take the ptl lock on the source page table + * page, to prevent the entire pmd from being moved under a + * concurrent SPF. + * + * There is no need to take the destination ptl lock since, mremap + * has already created a hole at the destination and freed the + * corresponding page tables in the process. + * + * NOTE: If USE_SPLIT_PTE_PTLOCKS is false, then the old_ptl, new_ptl, + * and the old_pte_ptl; are all the same lock (mm->page_table_lock). + * Check that the locks are different to avoid a deadlock. + */ + old_pte_ptl = pte_lockptr(mm, old_pmd); + if (IS_ENABLED(CONFIG_SPECULATIVE_PAGE_FAULT) && old_pte_ptl != old_ptl) + spin_lock(old_pte_ptl); + + /* Clear the pmd */ pmd = *old_pmd; pmd_clear(old_pmd); @@ -303,11 +280,13 @@ static bool move_normal_pmd(struct vm_area_struct *vma, unsigned long old_addr, /* Set the new pmd */ set_pmd_at(mm, new_addr, new_pmd, pmd); flush_tlb_range(vma, old_addr, old_addr + PMD_SIZE); + + if (IS_ENABLED(CONFIG_SPECULATIVE_PAGE_FAULT) && old_pte_ptl != old_ptl) + spin_unlock(old_pte_ptl); if (new_ptl != old_ptl) spin_unlock(new_ptl); spin_unlock(old_ptl); - unlock_vma_ref_count(vma); return true; } #else @@ -319,7 +298,8 @@ static inline bool move_normal_pmd(struct vm_area_struct *vma, } #endif -#ifdef CONFIG_HAVE_MOVE_PUD +#if CONFIG_PGTABLE_LEVELS > 2 && defined(CONFIG_HAVE_MOVE_PUD) && \ + !defined(CONFIG_SPECULATIVE_PAGE_FAULT) static bool move_normal_pud(struct vm_area_struct *vma, unsigned long old_addr, unsigned long new_addr, pud_t *old_pud, pud_t *new_pud) { @@ -334,14 +314,6 @@ static bool move_normal_pud(struct vm_area_struct *vma, unsigned long old_addr, if (WARN_ON_ONCE(!pud_none(*new_pud))) return false; - /* - * We hold both exclusive mmap_lock and rmap_lock at this point and - * cannot block. If we cannot immediately take exclusive ownership - * of the VMA fallback to the move_ptes(). - */ - if (!trylock_vma_ref_count(vma)) - return false; - /* * We don't have to worry about the ordering of src and dst * ptlocks because exclusive mmap_lock prevents deadlock. @@ -364,7 +336,6 @@ static bool move_normal_pud(struct vm_area_struct *vma, unsigned long old_addr, spin_unlock(new_ptl); spin_unlock(old_ptl); - unlock_vma_ref_count(vma); return true; } #else diff --git a/mm/pgtable-generic.c b/mm/pgtable-generic.c index 4e640baf9794..11d465c10046 100644 --- a/mm/pgtable-generic.c +++ b/mm/pgtable-generic.c @@ -50,6 +50,7 @@ void pmd_clear_bad(pmd_t *pmd) pmd_ERROR(*pmd); pmd_clear(pmd); } +EXPORT_SYMBOL_GPL(pmd_clear_bad); #ifndef __HAVE_ARCH_PTEP_SET_ACCESS_FLAGS /* diff --git a/mm/readahead.c b/mm/readahead.c index 2db21cbf7745..404fefc7d311 100644 --- a/mm/readahead.c +++ b/mm/readahead.c @@ -222,7 +222,7 @@ void page_cache_ra_unbounded(struct readahead_control *ractl, read_pages(ractl, &page_pool, true); continue; } - + trace_android_vh_io_statistics(mapping, index + i, 1, true, false); page = __page_cache_alloc(gfp_mask); if (!page) break; diff --git a/mm/slab_common.c b/mm/slab_common.c index 05135ebb6159..a84d9360cdf1 100644 --- a/mm/slab_common.c +++ b/mm/slab_common.c @@ -1101,6 +1101,13 @@ static __always_inline void *__do_krealloc(const void *p, size_t new_size, /* If the object still fits, repoison it precisely. */ if (ks >= new_size) { + /* Zero out spare memory. */ + if (want_init_on_alloc(flags)) { + kasan_disable_current(); + memset((void *)p + new_size, 0, ks - new_size); + kasan_enable_current(); + } + p = kasan_krealloc((void *)p, new_size, flags); return (void *)p; } diff --git a/mm/swapfile.c b/mm/swapfile.c index e650dd520024..842736b079bb 100644 --- a/mm/swapfile.c +++ b/mm/swapfile.c @@ -2158,7 +2158,7 @@ static int unuse_mm(struct mm_struct *mm, unsigned int type, mmap_read_lock(mm); for (vma = mm->mmap; vma; vma = vma->vm_next) { - if (vma->anon_vma) { + if (vma->anon_vma && !is_vm_hugetlb_page(vma)) { ret = unuse_vma(vma, type, frontswap, fs_pages_to_unuse); if (ret) diff --git a/mm/util.c b/mm/util.c index 70b975249bdb..45933c2f9f8d 100644 --- a/mm/util.c +++ b/mm/util.c @@ -423,7 +423,7 @@ static unsigned long mmap_base(unsigned long rnd, struct rlimit *rlim_stack) if (gap + pad > gap) gap += pad; - if (gap < MIN_GAP) + if (gap < MIN_GAP && MIN_GAP < MAX_GAP) gap = MIN_GAP; else if (gap > MAX_GAP) gap = MAX_GAP; diff --git a/net/bluetooth/af_bluetooth.c b/net/bluetooth/af_bluetooth.c index 14a917e70f3e..0b8400bda73d 100644 --- a/net/bluetooth/af_bluetooth.c +++ b/net/bluetooth/af_bluetooth.c @@ -779,6 +779,7 @@ static int __init bt_init(void) bt_sysfs_cleanup(); cleanup_led: bt_leds_cleanup(); + debugfs_remove_recursive(bt_debugfs); return err; } diff --git a/net/bluetooth/bnep/core.c b/net/bluetooth/bnep/core.c index 089160361dde..d05beafd2952 100644 --- a/net/bluetooth/bnep/core.c +++ b/net/bluetooth/bnep/core.c @@ -745,8 +745,7 @@ static int __init bnep_init(void) if (flt[0]) BT_INFO("BNEP filters: %s", flt); - bnep_sock_init(); - return 0; + return bnep_sock_init(); } static void __exit bnep_exit(void) diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c index 3a2be1b4a574..93afa52c0466 100644 --- a/net/bluetooth/l2cap_sock.c +++ b/net/bluetooth/l2cap_sock.c @@ -745,7 +745,7 @@ static int l2cap_sock_setsockopt_old(struct socket *sock, int optname, struct sock *sk = sock->sk; struct l2cap_chan *chan = l2cap_pi(sk)->chan; struct l2cap_options opts; - int len, err = 0; + int err = 0; u32 opt; BT_DBG("sk %p", sk); @@ -772,11 +772,9 @@ static int l2cap_sock_setsockopt_old(struct socket *sock, int optname, opts.max_tx = chan->max_tx; opts.txwin_size = chan->tx_win; - len = min_t(unsigned int, sizeof(opts), optlen); - if (copy_from_sockptr(&opts, optval, len)) { - err = -EFAULT; + err = bt_copy_from_sockptr(&opts, sizeof(opts), optval, optlen); + if (err) break; - } if (opts.txwin_size > L2CAP_DEFAULT_EXT_WINDOW) { err = -EINVAL; @@ -819,10 +817,9 @@ static int l2cap_sock_setsockopt_old(struct socket *sock, int optname, break; case L2CAP_LM: - if (copy_from_sockptr(&opt, optval, sizeof(u32))) { - err = -EFAULT; + err = bt_copy_from_sockptr(&opt, sizeof(opt), optval, optlen); + if (err) break; - } if (opt & L2CAP_LM_FIPS) { err = -EINVAL; @@ -903,7 +900,7 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname, struct bt_security sec; struct bt_power pwr; struct l2cap_conn *conn; - int len, err = 0; + int err = 0; u32 opt; u16 mtu; u8 mode; @@ -929,11 +926,9 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname, sec.level = BT_SECURITY_LOW; - len = min_t(unsigned int, sizeof(sec), optlen); - if (copy_from_sockptr(&sec, optval, len)) { - err = -EFAULT; + err = bt_copy_from_sockptr(&sec, sizeof(sec), optval, optlen); + if (err) break; - } if (sec.level < BT_SECURITY_LOW || sec.level > BT_SECURITY_FIPS) { @@ -978,10 +973,9 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname, break; } - if (copy_from_sockptr(&opt, optval, sizeof(u32))) { - err = -EFAULT; + err = bt_copy_from_sockptr(&opt, sizeof(opt), optval, optlen); + if (err) break; - } if (opt) { set_bit(BT_SK_DEFER_SETUP, &bt_sk(sk)->flags); @@ -993,10 +987,9 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname, break; case BT_FLUSHABLE: - if (copy_from_sockptr(&opt, optval, sizeof(u32))) { - err = -EFAULT; + err = bt_copy_from_sockptr(&opt, sizeof(opt), optval, optlen); + if (err) break; - } if (opt > BT_FLUSHABLE_ON) { err = -EINVAL; @@ -1028,11 +1021,9 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname, pwr.force_active = BT_POWER_FORCE_ACTIVE_ON; - len = min_t(unsigned int, sizeof(pwr), optlen); - if (copy_from_sockptr(&pwr, optval, len)) { - err = -EFAULT; + err = bt_copy_from_sockptr(&pwr, sizeof(pwr), optval, optlen); + if (err) break; - } if (pwr.force_active) set_bit(FLAG_FORCE_ACTIVE, &chan->flags); @@ -1041,10 +1032,9 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname, break; case BT_CHANNEL_POLICY: - if (copy_from_sockptr(&opt, optval, sizeof(u32))) { - err = -EFAULT; + err = bt_copy_from_sockptr(&opt, sizeof(opt), optval, optlen); + if (err) break; - } if (opt > BT_CHANNEL_POLICY_AMP_PREFERRED) { err = -EINVAL; @@ -1089,10 +1079,9 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname, break; } - if (copy_from_sockptr(&mtu, optval, sizeof(u16))) { - err = -EFAULT; + err = bt_copy_from_sockptr(&mtu, sizeof(mtu), optval, optlen); + if (err) break; - } if (chan->mode == L2CAP_MODE_EXT_FLOWCTL && sk->sk_state == BT_CONNECTED) @@ -1120,10 +1109,9 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname, break; } - if (copy_from_sockptr(&mode, optval, sizeof(u8))) { - err = -EFAULT; + err = bt_copy_from_sockptr(&mode, sizeof(mode), optval, optlen); + if (err) break; - } BT_DBG("mode %u", mode); diff --git a/net/bluetooth/rfcomm/sock.c b/net/bluetooth/rfcomm/sock.c index 4cf1fa9900ca..5a490f707c81 100644 --- a/net/bluetooth/rfcomm/sock.c +++ b/net/bluetooth/rfcomm/sock.c @@ -871,9 +871,7 @@ static int rfcomm_sock_ioctl(struct socket *sock, unsigned int cmd, unsigned lon if (err == -ENOIOCTLCMD) { #ifdef CONFIG_BT_RFCOMM_TTY - lock_sock(sk); err = rfcomm_dev_ioctl(sk, cmd, (void __user *) arg); - release_sock(sk); #else err = -EOPNOTSUPP; #endif diff --git a/net/bridge/br_netfilter_hooks.c b/net/bridge/br_netfilter_hooks.c index f14beb9a62ed..4f867aca6300 100644 --- a/net/bridge/br_netfilter_hooks.c +++ b/net/bridge/br_netfilter_hooks.c @@ -33,6 +33,7 @@ #include #include #include +#include #include #include #include @@ -753,6 +754,10 @@ static int br_nf_dev_queue_xmit(struct net *net, struct sock *sk, struct sk_buff return br_dev_queue_push_xmit(net, sk, skb); } + /* Fragmentation on metadata/template dst is not supported */ + if (unlikely(!skb_valid_dst(skb))) + goto drop; + /* This is wrong! We should preserve the original fragment * boundaries by preserving frag_list rather than refragmenting. */ diff --git a/net/can/bcm.c b/net/can/bcm.c index b2b1bd672787..cb849b5a8c14 100644 --- a/net/can/bcm.c +++ b/net/can/bcm.c @@ -1424,8 +1424,10 @@ static void bcm_notify(struct bcm_sock *bo, unsigned long msg, /* remove device reference, if this is our bound device */ if (bo->bound && bo->ifindex == dev->ifindex) { #if IS_ENABLED(CONFIG_PROC_FS) - if (sock_net(sk)->can.bcmproc_dir && bo->bcm_proc_read) + if (sock_net(sk)->can.bcmproc_dir && bo->bcm_proc_read) { remove_proc_entry(bo->procname, sock_net(sk)->can.bcmproc_dir); + bo->bcm_proc_read = NULL; + } #endif bo->bound = 0; bo->ifindex = 0; diff --git a/net/can/j1939/transport.c b/net/can/j1939/transport.c index 478dafc73857..a86256ab1402 100644 --- a/net/can/j1939/transport.c +++ b/net/can/j1939/transport.c @@ -1171,10 +1171,10 @@ static enum hrtimer_restart j1939_tp_txtimer(struct hrtimer *hrtimer) break; case -ENETDOWN: /* In this case we should get a netdev_event(), all active - * sessions will be cleared by - * j1939_cancel_all_active_sessions(). So handle this as an - * error, but let j1939_cancel_all_active_sessions() do the - * cleanup including propagation of the error to user space. + * sessions will be cleared by j1939_cancel_active_session(). + * So handle this as an error, but let + * j1939_cancel_active_session() do the cleanup including + * propagation of the error to user space. */ break; case -EOVERFLOW: diff --git a/net/core/dev.c b/net/core/dev.c index 1488cb5c39bb..6f9a66e57b25 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -3764,7 +3764,7 @@ static void qdisc_pkt_len_init(struct sk_buff *skb) sizeof(_tcphdr), &_tcphdr); if (likely(th)) hdr_len += __tcp_hdrlen(th); - } else { + } else if (shinfo->gso_type & SKB_GSO_UDP_L4) { struct udphdr _udphdr; if (skb_header_pointer(skb, skb_transport_offset(skb), @@ -3772,10 +3772,14 @@ static void qdisc_pkt_len_init(struct sk_buff *skb) hdr_len += sizeof(struct udphdr); } - if (shinfo->gso_type & SKB_GSO_DODGY) - gso_segs = DIV_ROUND_UP(skb->len - hdr_len, - shinfo->gso_size); + if (unlikely(shinfo->gso_type & SKB_GSO_DODGY)) { + int payload = skb->len - hdr_len; + /* Malicious packet. */ + if (payload <= 0) + return; + gso_segs = DIV_ROUND_UP(payload, shinfo->gso_size); + } qdisc_skb_cb(skb)->pkt_len += (gso_segs - 1) * hdr_len; } } diff --git a/net/core/sock_map.c b/net/core/sock_map.c index d1d0ee2dbfaa..73c081fb4220 100644 --- a/net/core/sock_map.c +++ b/net/core/sock_map.c @@ -1219,6 +1219,7 @@ static void sock_hash_free(struct bpf_map *map) sock_put(elem->sk); sock_hash_free_elem(htab, elem); } + cond_resched(); } /* wait for psock readers accessing its map link */ diff --git a/net/ipv4/devinet.c b/net/ipv4/devinet.c index 9ac7d47d27b8..6918b3ced671 100644 --- a/net/ipv4/devinet.c +++ b/net/ipv4/devinet.c @@ -273,17 +273,19 @@ static struct in_device *inetdev_init(struct net_device *dev) /* Account for reference dev->ip_ptr (below) */ refcount_set(&in_dev->refcnt, 1); - err = devinet_sysctl_register(in_dev); - if (err) { - in_dev->dead = 1; - neigh_parms_release(&arp_tbl, in_dev->arp_parms); - in_dev_put(in_dev); - in_dev = NULL; - goto out; + if (dev != blackhole_netdev) { + err = devinet_sysctl_register(in_dev); + if (err) { + in_dev->dead = 1; + neigh_parms_release(&arp_tbl, in_dev->arp_parms); + in_dev_put(in_dev); + in_dev = NULL; + goto out; + } + ip_mc_init_dev(in_dev); + if (dev->flags & IFF_UP) + ip_mc_up(in_dev); } - ip_mc_init_dev(in_dev); - if (dev->flags & IFF_UP) - ip_mc_up(in_dev); /* we can receive as soon as ip_ptr is set -- do this last */ rcu_assign_pointer(dev->ip_ptr, in_dev); @@ -328,6 +330,19 @@ static void inetdev_destroy(struct in_device *in_dev) call_rcu(&in_dev->rcu_head, in_dev_rcu_put); } +static int __init inet_blackhole_dev_init(void) +{ + int err = 0; + + rtnl_lock(); + if (!inetdev_init(blackhole_netdev)) + err = -ENOMEM; + rtnl_unlock(); + + return err; +} +late_initcall(inet_blackhole_dev_init); + int inet_addr_onlink(struct in_device *in_dev, __be32 a, __be32 b) { const struct in_ifaddr *ifa; @@ -566,10 +581,6 @@ static int inet_set_ifa(struct net_device *dev, struct in_ifaddr *ifa) ASSERT_RTNL(); - if (!in_dev) { - inet_free_ifa(ifa); - return -ENOBUFS; - } ipv4_devconf_setall(in_dev); neigh_parms_data_state_setall(in_dev->arp_parms); if (ifa->ifa_dev != in_dev) { @@ -1150,6 +1161,8 @@ int devinet_ioctl(struct net *net, unsigned int cmd, struct ifreq *ifr) if (!ifa) { ret = -ENOBUFS; + if (!in_dev) + break; ifa = inet_alloc_ifa(); if (!ifa) break; diff --git a/net/ipv4/fib_frontend.c b/net/ipv4/fib_frontend.c index 41f890bf9d4c..0394146f813c 100644 --- a/net/ipv4/fib_frontend.c +++ b/net/ipv4/fib_frontend.c @@ -1334,7 +1334,7 @@ static void nl_fib_lookup(struct net *net, struct fib_result_nl *frn) struct flowi4 fl4 = { .flowi4_mark = frn->fl_mark, .daddr = frn->fl_addr, - .flowi4_tos = frn->fl_tos, + .flowi4_tos = frn->fl_tos & IPTOS_RT_MASK, .flowi4_scope = frn->fl_scope, }; struct fib_table *tb; diff --git a/net/ipv4/fou.c b/net/ipv4/fou.c index 135da756dd5a..1d67df4d8ed6 100644 --- a/net/ipv4/fou.c +++ b/net/ipv4/fou.c @@ -334,11 +334,11 @@ static struct sk_buff *gue_gro_receive(struct sock *sk, struct gro_remcsum grc; u8 proto; + skb_gro_remcsum_init(&grc); + if (!fou) goto out; - skb_gro_remcsum_init(&grc); - off = skb_gro_offset(skb); len = off + sizeof(*guehdr); diff --git a/net/ipv4/ip_gre.c b/net/ipv4/ip_gre.c index 0ac652fef06d..9612867b70e9 100644 --- a/net/ipv4/ip_gre.c +++ b/net/ipv4/ip_gre.c @@ -639,11 +639,11 @@ static netdev_tx_t ipgre_xmit(struct sk_buff *skb, if (skb_cow_head(skb, 0)) goto free_skb; - tnl_params = (const struct iphdr *)skb->data; - - if (!pskb_network_may_pull(skb, pull_len)) + if (!pskb_may_pull(skb, pull_len)) goto free_skb; + tnl_params = (const struct iphdr *)skb->data; + /* ip_tunnel_xmit() needs skb->data pointing to gre header. */ skb_pull(skb, pull_len); skb_reset_mac_header(skb); diff --git a/net/ipv4/netfilter/nf_dup_ipv4.c b/net/ipv4/netfilter/nf_dup_ipv4.c index 6cc5743c553a..9a21175693db 100644 --- a/net/ipv4/netfilter/nf_dup_ipv4.c +++ b/net/ipv4/netfilter/nf_dup_ipv4.c @@ -52,8 +52,9 @@ void nf_dup_ipv4(struct net *net, struct sk_buff *skb, unsigned int hooknum, { struct iphdr *iph; + local_bh_disable(); if (this_cpu_read(nf_skb_duplicated)) - return; + goto out; /* * Copy the skb, and route the copy. Will later return %XT_CONTINUE for * the original skb, which should continue on its way as if nothing has @@ -61,7 +62,7 @@ void nf_dup_ipv4(struct net *net, struct sk_buff *skb, unsigned int hooknum, */ skb = pskb_copy(skb, GFP_ATOMIC); if (skb == NULL) - return; + goto out; #if IS_ENABLED(CONFIG_NF_CONNTRACK) /* Avoid counting cloned packets towards the original connection. */ @@ -90,6 +91,8 @@ void nf_dup_ipv4(struct net *net, struct sk_buff *skb, unsigned int hooknum, } else { kfree_skb(skb); } +out: + local_bh_enable(); } EXPORT_SYMBOL_GPL(nf_dup_ipv4); diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index 5003bd49fe17..be39bdef5cee 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c @@ -2424,8 +2424,22 @@ static bool tcp_skb_spurious_retrans(const struct tcp_sock *tp, */ static inline bool tcp_packet_delayed(const struct tcp_sock *tp) { - return tp->retrans_stamp && - tcp_tsopt_ecr_before(tp, tp->retrans_stamp); + const struct sock *sk = (const struct sock *)tp; + + if (tp->retrans_stamp && + tcp_tsopt_ecr_before(tp, tp->retrans_stamp)) + return true; /* got echoed TS before first retransmission */ + + /* Check if nothing was retransmitted (retrans_stamp==0), which may + * happen in fast recovery due to TSQ. But we ignore zero retrans_stamp + * in TCP_SYN_SENT, since when we set FLAG_SYN_ACKED we also clear + * retrans_stamp even if we had retransmitted the SYN. + */ + if (!tp->retrans_stamp && /* no record of a retransmit/SYN? */ + sk->sk_state != TCP_SYN_SENT) /* not the FLAG_SYN_ACKED case? */ + return true; /* nothing was retransmitted */ + + return false; } /* Undo procedures. */ @@ -2459,6 +2473,16 @@ static bool tcp_any_retrans_done(const struct sock *sk) return false; } +/* If loss recovery is finished and there are no retransmits out in the + * network, then we clear retrans_stamp so that upon the next loss recovery + * retransmits_timed_out() and timestamp-undo are using the correct value. + */ +static void tcp_retrans_stamp_cleanup(struct sock *sk) +{ + if (!tcp_any_retrans_done(sk)) + tcp_sk(sk)->retrans_stamp = 0; +} + static void DBGUNDO(struct sock *sk, const char *msg) { #if FASTRETRANS_DEBUG > 1 @@ -2795,6 +2819,9 @@ void tcp_enter_recovery(struct sock *sk, bool ece_ack) struct tcp_sock *tp = tcp_sk(sk); int mib_idx; + /* Start the clock with our fast retransmit, for undo and ETIMEDOUT. */ + tcp_retrans_stamp_cleanup(sk); + if (tcp_is_reno(tp)) mib_idx = LINUX_MIB_TCPRENORECOVERY; else diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index bb091e12709d..e02ebee07d88 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c @@ -111,6 +111,9 @@ int tcp_twsk_unique(struct sock *sk, struct sock *sktw, void *twp) const struct tcp_timewait_sock *tcptw = tcp_twsk(sktw); struct tcp_sock *tp = tcp_sk(sk); + if (tw->tw_substate == TCP_FIN_WAIT2) + reuse = 0; + if (reuse == 2) { /* Still does not detect *everything* that goes through * lo, since we require a loopback src or dst address diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c index d69ed44d9ec5..88c7b79d22ae 100644 --- a/net/ipv4/tcp_output.c +++ b/net/ipv4/tcp_output.c @@ -2305,7 +2305,7 @@ static bool tcp_can_coalesce_send_queue_head(struct sock *sk, int len) if (len <= skb->len) break; - if (unlikely(TCP_SKB_CB(skb)->eor) || tcp_has_tx_tstamp(skb)) + if (tcp_has_tx_tstamp(skb) || !tcp_skb_can_collapse(skb, next)) return false; len -= skb->len; diff --git a/net/ipv6/Kconfig b/net/ipv6/Kconfig index 747f56e0c636..db430f7c45a2 100644 --- a/net/ipv6/Kconfig +++ b/net/ipv6/Kconfig @@ -322,6 +322,7 @@ config IPV6_RPL_LWTUNNEL bool "IPv6: RPL Source Routing Header support" depends on IPV6 select LWTUNNEL + select DST_CACHE help Support for RFC6554 RPL Source Routing Header using the lightweight tunnels mechanism. diff --git a/net/ipv6/netfilter/nf_dup_ipv6.c b/net/ipv6/netfilter/nf_dup_ipv6.c index a0a2de30be3e..0c39c77fe8a8 100644 --- a/net/ipv6/netfilter/nf_dup_ipv6.c +++ b/net/ipv6/netfilter/nf_dup_ipv6.c @@ -47,11 +47,12 @@ static bool nf_dup_ipv6_route(struct net *net, struct sk_buff *skb, void nf_dup_ipv6(struct net *net, struct sk_buff *skb, unsigned int hooknum, const struct in6_addr *gw, int oif) { + local_bh_disable(); if (this_cpu_read(nf_skb_duplicated)) - return; + goto out; skb = pskb_copy(skb, GFP_ATOMIC); if (skb == NULL) - return; + goto out; #if IS_ENABLED(CONFIG_NF_CONNTRACK) nf_reset_ct(skb); @@ -69,6 +70,8 @@ void nf_dup_ipv6(struct net *net, struct sk_buff *skb, unsigned int hooknum, } else { kfree_skb(skb); } +out: + local_bh_enable(); } EXPORT_SYMBOL_GPL(nf_dup_ipv6); diff --git a/net/ipv6/netfilter/nf_reject_ipv6.c b/net/ipv6/netfilter/nf_reject_ipv6.c index 832d9f9cd10a..df572724f254 100644 --- a/net/ipv6/netfilter/nf_reject_ipv6.c +++ b/net/ipv6/netfilter/nf_reject_ipv6.c @@ -89,33 +89,23 @@ void nf_reject_ip6_tcphdr_put(struct sk_buff *nskb, const struct tcphdr *oth, unsigned int otcplen) { struct tcphdr *tcph; - int needs_ack; skb_reset_transport_header(nskb); - tcph = skb_put(nskb, sizeof(struct tcphdr)); + tcph = skb_put_zero(nskb, sizeof(struct tcphdr)); /* Truncate to length (no data) */ tcph->doff = sizeof(struct tcphdr)/4; tcph->source = oth->dest; tcph->dest = oth->source; if (oth->ack) { - needs_ack = 0; tcph->seq = oth->ack_seq; - tcph->ack_seq = 0; } else { - needs_ack = 1; tcph->ack_seq = htonl(ntohl(oth->seq) + oth->syn + oth->fin + otcplen - (oth->doff<<2)); - tcph->seq = 0; + tcph->ack = 1; } - /* Reset flags */ - ((u_int8_t *)tcph)[13] = 0; tcph->rst = 1; - tcph->ack = needs_ack; - tcph->window = 0; - tcph->urg_ptr = 0; - tcph->check = 0; /* Adjust TCP checksum */ tcph->check = csum_ipv6_magic(&ipv6_hdr(nskb)->saddr, diff --git a/net/ipv6/rpl_iptunnel.c b/net/ipv6/rpl_iptunnel.c index 2ba605db6976..274593b7c610 100644 --- a/net/ipv6/rpl_iptunnel.c +++ b/net/ipv6/rpl_iptunnel.c @@ -268,10 +268,8 @@ static int rpl_input(struct sk_buff *skb) rlwt = rpl_lwt_lwtunnel(orig_dst->lwtstate); err = rpl_do_srh(skb, rlwt); - if (unlikely(err)) { - kfree_skb(skb); - return err; - } + if (unlikely(err)) + goto drop; local_bh_disable(); dst = dst_cache_get(&rlwt->cache); @@ -292,9 +290,13 @@ static int rpl_input(struct sk_buff *skb) err = skb_cow_head(skb, LL_RESERVED_SPACE(dst->dev)); if (unlikely(err)) - return err; + goto drop; return dst_input(skb); + +drop: + kfree_skb(skb); + return err; } static int nla_put_rpl_srh(struct sk_buff *skb, int attrtype, diff --git a/net/ipv6/seg6_local.c b/net/ipv6/seg6_local.c index 11f7da4139f6..de0b20cd09f0 100644 --- a/net/ipv6/seg6_local.c +++ b/net/ipv6/seg6_local.c @@ -163,6 +163,7 @@ seg6_lookup_any_nexthop(struct sk_buff *skb, struct in6_addr *nhaddr, struct flowi6 fl6; int dev_flags = 0; + memset(&fl6, 0, sizeof(fl6)); fl6.flowi6_iif = skb->dev->ifindex; fl6.daddr = nhaddr ? *nhaddr : hdr->daddr; fl6.saddr = hdr->saddr; diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index 0c3da7771b48..c8d2fe8fbc0a 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c @@ -509,6 +509,9 @@ static int ieee80211_add_key(struct wiphy *wiphy, struct net_device *dev, sta->cipher_scheme = cs; err = ieee80211_key_link(key, sdata, sta); + /* KRACK protection, shouldn't happen but just silently accept key */ + if (err == -EALREADY) + err = 0; out_unlock: mutex_unlock(&local->sta_mtx); diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index 06ce138eedf1..55e3dfa7505d 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c @@ -370,6 +370,7 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata, { struct ieee80211_local *local = sdata->local; unsigned long flags; + struct sk_buff_head freeq; struct sk_buff *skb, *tmp; u32 hw_reconf_flags = 0; int i, flushed; @@ -565,18 +566,32 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata, skb_queue_purge(&sdata->skb_queue); } + /* + * Since ieee80211_free_txskb() may issue __dev_queue_xmit() + * which should be called with interrupts enabled, reclamation + * is done in two phases: + */ + __skb_queue_head_init(&freeq); + + /* unlink from local queues... */ spin_lock_irqsave(&local->queue_stop_reason_lock, flags); for (i = 0; i < IEEE80211_MAX_QUEUES; i++) { skb_queue_walk_safe(&local->pending[i], skb, tmp) { struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); if (info->control.vif == &sdata->vif) { __skb_unlink(skb, &local->pending[i]); - ieee80211_free_txskb(&local->hw, skb); + __skb_queue_tail(&freeq, skb); } } } spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags); + /* ... and perform actual reclamation with interrupts enabled. */ + skb_queue_walk_safe(&freeq, skb, tmp) { + __skb_unlink(skb, &freeq); + ieee80211_free_txskb(&local->hw, skb); + } + if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) ieee80211_txq_remove_vlan(local, sdata); diff --git a/net/mac80211/key.c b/net/mac80211/key.c index 6a72c33679ba..6b089594a9f3 100644 --- a/net/mac80211/key.c +++ b/net/mac80211/key.c @@ -843,7 +843,7 @@ int ieee80211_key_link(struct ieee80211_key *key, */ if (ieee80211_key_identical(sdata, old_key, key)) { ieee80211_key_free_unused(key); - ret = 0; + ret = -EALREADY; goto out; } diff --git a/net/mptcp/mib.c b/net/mptcp/mib.c index f4034e000f3e..44d083958d8e 100644 --- a/net/mptcp/mib.c +++ b/net/mptcp/mib.c @@ -23,6 +23,8 @@ static const struct snmp_mib mptcp_snmp_list[] = { SNMP_MIB_ITEM("MPJoinAckRx", MPTCP_MIB_JOINACKRX), SNMP_MIB_ITEM("MPJoinAckHMacFailure", MPTCP_MIB_JOINACKMAC), SNMP_MIB_ITEM("DSSNotMatching", MPTCP_MIB_DSSNOMATCH), + SNMP_MIB_ITEM("DSSCorruptionFallback", MPTCP_MIB_DSSCORRUPTIONFALLBACK), + SNMP_MIB_ITEM("DSSCorruptionReset", MPTCP_MIB_DSSCORRUPTIONRESET), SNMP_MIB_ITEM("InfiniteMapRx", MPTCP_MIB_INFINITEMAPRX), SNMP_MIB_ITEM("OFOQueueTail", MPTCP_MIB_OFOQUEUETAIL), SNMP_MIB_ITEM("OFOQueue", MPTCP_MIB_OFOQUEUE), diff --git a/net/mptcp/mib.h b/net/mptcp/mib.h index a9f43ff00b3c..0e17e1cebdbc 100644 --- a/net/mptcp/mib.h +++ b/net/mptcp/mib.h @@ -16,6 +16,8 @@ enum linux_mptcp_mib_field { MPTCP_MIB_JOINACKRX, /* Received an ACK + MP_JOIN */ MPTCP_MIB_JOINACKMAC, /* HMAC was wrong on ACK + MP_JOIN */ MPTCP_MIB_DSSNOMATCH, /* Received a new mapping that did not match the previous one */ + MPTCP_MIB_DSSCORRUPTIONFALLBACK,/* DSS corruption detected, fallback */ + MPTCP_MIB_DSSCORRUPTIONRESET, /* DSS corruption detected, MPJ subflow reset */ MPTCP_MIB_INFINITEMAPRX, /* Received an infinite mapping */ MPTCP_MIB_OFOQUEUETAIL, /* Segments inserted into OoO queue tail */ MPTCP_MIB_OFOQUEUE, /* Segments inserted into OoO queue */ diff --git a/net/mptcp/options.c b/net/mptcp/options.c index 9b11396552df..8bc8812f7526 100644 --- a/net/mptcp/options.c +++ b/net/mptcp/options.c @@ -915,7 +915,7 @@ void mptcp_incoming_options(struct sock *sk, struct sk_buff *skb) mptcp_pm_add_addr_received(msk, &addr); MPTCP_INC_STATS(sock_net(sk), MPTCP_MIB_ADDADDR); } else { - mptcp_pm_del_add_timer(msk, &addr); + mptcp_pm_del_add_timer(msk, &addr, true); MPTCP_INC_STATS(sock_net(sk), MPTCP_MIB_ECHOADD); } mp_opt.add_addr = 0; diff --git a/net/mptcp/pm_netlink.c b/net/mptcp/pm_netlink.c index f115c92c45d4..bd03fb6df729 100644 --- a/net/mptcp/pm_netlink.c +++ b/net/mptcp/pm_netlink.c @@ -194,9 +194,9 @@ static void check_work_pending(struct mptcp_sock *msk) WRITE_ONCE(msk->pm.work_pending, false); } -static struct mptcp_pm_add_entry * -lookup_anno_list_by_saddr(struct mptcp_sock *msk, - struct mptcp_addr_info *addr) +struct mptcp_pm_add_entry * +mptcp_lookup_anno_list_by_saddr(struct mptcp_sock *msk, + struct mptcp_addr_info *addr) { struct mptcp_pm_add_entry *entry; @@ -249,19 +249,25 @@ static void mptcp_pm_add_timer(struct timer_list *timer) struct mptcp_pm_add_entry * mptcp_pm_del_add_timer(struct mptcp_sock *msk, - struct mptcp_addr_info *addr) + struct mptcp_addr_info *addr, bool check_id) { struct mptcp_pm_add_entry *entry; struct sock *sk = (struct sock *)msk; + struct timer_list *add_timer = NULL; spin_lock_bh(&msk->pm.lock); - entry = lookup_anno_list_by_saddr(msk, addr); - if (entry) + entry = mptcp_lookup_anno_list_by_saddr(msk, addr); + if (entry && (!check_id || entry->addr.id == addr->id)) { entry->retrans_times = ADD_ADDR_RETRANS_MAX; + add_timer = &entry->add_timer; + } + if (!check_id && entry) + list_del(&entry->list); spin_unlock_bh(&msk->pm.lock); - if (entry) - sk_stop_timer_sync(sk, &entry->add_timer); + /* no lock, because sk_stop_timer_sync() is calling del_timer_sync() */ + if (add_timer) + sk_stop_timer_sync(sk, add_timer); return entry; } @@ -272,7 +278,7 @@ static bool mptcp_pm_alloc_anno_list(struct mptcp_sock *msk, struct mptcp_pm_add_entry *add_entry = NULL; struct sock *sk = (struct sock *)msk; - if (lookup_anno_list_by_saddr(msk, &entry->addr)) + if (mptcp_lookup_anno_list_by_saddr(msk, &entry->addr)) return false; add_entry = kmalloc(sizeof(*add_entry), GFP_ATOMIC); @@ -764,9 +770,8 @@ static bool remove_anno_list_by_saddr(struct mptcp_sock *msk, { struct mptcp_pm_add_entry *entry; - entry = mptcp_pm_del_add_timer(msk, addr); + entry = mptcp_pm_del_add_timer(msk, addr, false); if (entry) { - list_del(&entry->list); kfree(entry); return true; } diff --git a/net/mptcp/protocol.c b/net/mptcp/protocol.c index 590e2c9bb67e..8558309a2d3f 100644 --- a/net/mptcp/protocol.c +++ b/net/mptcp/protocol.c @@ -457,6 +457,18 @@ static void mptcp_check_data_fin(struct sock *sk) } } +static void mptcp_dss_corruption(struct mptcp_sock *msk, struct sock *ssk) +{ + if (READ_ONCE(msk->allow_infinite_fallback)) { + MPTCP_INC_STATS(sock_net(ssk), + MPTCP_MIB_DSSCORRUPTIONFALLBACK); + mptcp_do_fallback(ssk); + } else { + MPTCP_INC_STATS(sock_net(ssk), MPTCP_MIB_DSSCORRUPTIONRESET); + mptcp_subflow_reset(ssk); + } +} + static bool __mptcp_move_skbs_from_subflow(struct mptcp_sock *msk, struct sock *ssk, unsigned int *bytes) @@ -519,10 +531,12 @@ static bool __mptcp_move_skbs_from_subflow(struct mptcp_sock *msk, moved += len; seq += len; - if (WARN_ON_ONCE(map_remaining < len)) - break; + if (unlikely(map_remaining < len)) + mptcp_dss_corruption(msk, ssk); } else { - WARN_ON_ONCE(!fin); + if (unlikely(!fin)) + mptcp_dss_corruption(msk, ssk); + sk_eat_skb(ssk, skb); done = true; } @@ -1810,9 +1824,11 @@ static void mptcp_worker(struct work_struct *work) if (!mptcp_ext_cache_refill(msk)) break; } - if (copied) + if (copied) { tcp_push(ssk, msg.msg_flags, mss_now, tcp_sk(ssk)->nonagle, size_goal); + WRITE_ONCE(msk->allow_infinite_fallback, false); + } dfrag->data_seq = orig_write_seq; dfrag->offset = orig_offset; @@ -1845,6 +1861,7 @@ static int __mptcp_init_sock(struct sock *sk) msk->first = NULL; inet_csk(sk)->icsk_sync_mss = mptcp_sync_mss; + WRITE_ONCE(msk->allow_infinite_fallback, true); mptcp_pm_data_init(msk); @@ -2543,6 +2560,7 @@ bool mptcp_finish_join(struct sock *sk) if (parent_sock && !sk->sk_socket) mptcp_sock_graft(sk, parent_sock); subflow->map_seq = READ_ONCE(msk->ack_seq); + WRITE_ONCE(msk->allow_infinite_fallback, false); return true; } diff --git a/net/mptcp/protocol.h b/net/mptcp/protocol.h index b8351b671c2f..2330140d6b1c 100644 --- a/net/mptcp/protocol.h +++ b/net/mptcp/protocol.h @@ -213,6 +213,7 @@ struct mptcp_sock { bool rcv_data_fin; bool snd_data_fin_enable; bool use_64bit_ack; /* Set when we received a 64-bit DSN */ + bool allow_infinite_fallback; spinlock_t join_list_lock; struct work_struct work; struct sk_buff *ooo_last_skb; @@ -450,7 +451,10 @@ void mptcp_pm_rm_addr_received(struct mptcp_sock *msk, u8 rm_id); void mptcp_pm_free_anno_list(struct mptcp_sock *msk); struct mptcp_pm_add_entry * mptcp_pm_del_add_timer(struct mptcp_sock *msk, - struct mptcp_addr_info *addr); + struct mptcp_addr_info *addr, bool check_id); +struct mptcp_pm_add_entry * +mptcp_lookup_anno_list_by_saddr(struct mptcp_sock *msk, + struct mptcp_addr_info *addr); int mptcp_pm_announce_addr(struct mptcp_sock *msk, const struct mptcp_addr_info *addr, diff --git a/net/mptcp/subflow.c b/net/mptcp/subflow.c index 843c61ebd421..c3434069fb0a 100644 --- a/net/mptcp/subflow.c +++ b/net/mptcp/subflow.c @@ -702,7 +702,7 @@ static bool skb_is_fully_mapped(struct sock *ssk, struct sk_buff *skb) unsigned int skb_consumed; skb_consumed = tcp_sk(ssk)->copied_seq - TCP_SKB_CB(skb)->seq; - if (WARN_ON_ONCE(skb_consumed >= skb->len)) + if (unlikely(skb_consumed >= skb->len)) return true; return skb->len - skb_consumed <= subflow->map_data_len - @@ -1179,6 +1179,7 @@ int __mptcp_subflow_connect(struct sock *sk, const struct mptcp_addr_info *loc, list_add_tail(&subflow->node, &msk->join_list); spin_unlock_bh(&msk->join_list_lock); + WRITE_ONCE(msk->allow_infinite_fallback, false); return err; failed: diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c index b55e87143c2c..8c9edad0826e 100644 --- a/net/netfilter/nf_conntrack_netlink.c +++ b/net/netfilter/nf_conntrack_netlink.c @@ -365,7 +365,7 @@ static int ctnetlink_dump_secctx(struct sk_buff *skb, const struct nf_conn *ct) #define ctnetlink_dump_secctx(a, b) (0) #endif -#ifdef CONFIG_NF_CONNTRACK_LABELS +#ifdef CONFIG_NF_CONNTRACK_EVENTS static inline int ctnetlink_label_size(const struct nf_conn *ct) { struct nf_conn_labels *labels = nf_ct_labels_find(ct); @@ -374,6 +374,7 @@ static inline int ctnetlink_label_size(const struct nf_conn *ct) return 0; return nla_total_size(sizeof(labels->bits)); } +#endif static int ctnetlink_dump_labels(struct sk_buff *skb, const struct nf_conn *ct) @@ -394,10 +395,6 @@ ctnetlink_dump_labels(struct sk_buff *skb, const struct nf_conn *ct) return 0; } -#else -#define ctnetlink_dump_labels(a, b) (0) -#define ctnetlink_label_size(a) (0) -#endif #define master_tuple(ct) &(ct->master->tuplehash[IP_CT_DIR_ORIGINAL].tuple) diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c index 249c30c47cbd..2bd1c7e7edc3 100644 --- a/net/netfilter/nf_tables_api.c +++ b/net/netfilter/nf_tables_api.c @@ -594,6 +594,7 @@ static void nft_map_deactivate(const struct nft_ctx *ctx, struct nft_set *set) { struct nft_set_iter iter = { .genmask = nft_genmask_next(ctx->net), + .type = NFT_ITER_UPDATE, .fn = nft_mapelem_deactivate, }; @@ -4025,7 +4026,7 @@ int nf_msecs_to_jiffies64(const struct nlattr *nla, u64 *result) return -ERANGE; ms *= NSEC_PER_MSEC; - *result = nsecs_to_jiffies64(ms); + *result = nsecs_to_jiffies64(ms) ? : !!ms; return 0; } @@ -4777,6 +4778,7 @@ int nf_tables_bind_set(const struct nft_ctx *ctx, struct nft_set *set, } iter.genmask = nft_genmask_next(ctx->net); + iter.type = NFT_ITER_UPDATE; iter.skip = 0; iter.count = 0; iter.err = 0; @@ -4830,6 +4832,7 @@ static void nft_map_activate(const struct nft_ctx *ctx, struct nft_set *set) { struct nft_set_iter iter = { .genmask = nft_genmask_next(ctx->net), + .type = NFT_ITER_UPDATE, .fn = nft_mapelem_activate, }; @@ -5142,6 +5145,7 @@ static int nf_tables_dump_set(struct sk_buff *skb, struct netlink_callback *cb) args.cb = cb; args.skb = skb; args.iter.genmask = nft_genmask_cur(net); + args.iter.type = NFT_ITER_READ; args.iter.skip = cb->args[0]; args.iter.count = 0; args.iter.err = 0; @@ -5624,10 +5628,16 @@ static int nft_add_set_elem(struct nft_ctx *ctx, struct nft_set *set, if (nla[NFTA_SET_ELEM_EXPIRATION] != NULL) { if (!(set->flags & NFT_SET_TIMEOUT)) return -EINVAL; + if (timeout == 0) + return -EOPNOTSUPP; + err = nf_msecs_to_jiffies64(nla[NFTA_SET_ELEM_EXPIRATION], &expiration); if (err) return err; + + if (expiration > timeout) + return -ERANGE; } if (nla[NFTA_SET_ELEM_EXPR] != NULL) { @@ -6065,6 +6075,7 @@ static int nf_tables_delsetelem(struct net *net, struct sock *nlsk, if (nla[NFTA_SET_ELEM_LIST_ELEMENTS] == NULL) { struct nft_set_iter iter = { .genmask = genmask, + .type = NFT_ITER_UPDATE, .fn = nft_flush_set, }; set->ops->walk(&ctx, set, &iter); @@ -7614,7 +7625,7 @@ static void nf_tables_flowtable_destroy(struct nft_flowtable *flowtable) flowtable->data.type->setup(&flowtable->data, hook->ops.dev, FLOW_BLOCK_UNBIND); list_del_rcu(&hook->list); - kfree(hook); + kfree_rcu(hook, rcu); } kfree(flowtable->name); module_put(flowtable->data.type->owner); diff --git a/net/netfilter/nft_lookup.c b/net/netfilter/nft_lookup.c index d2f8131edaf1..f6ea1b32dae1 100644 --- a/net/netfilter/nft_lookup.c +++ b/net/netfilter/nft_lookup.c @@ -207,6 +207,7 @@ static int nft_lookup_validate(const struct nft_ctx *ctx, return 0; iter.genmask = nft_genmask_next(ctx->net); + iter.type = NFT_ITER_UPDATE; iter.skip = 0; iter.count = 0; iter.err = 0; diff --git a/net/netfilter/nft_set_pipapo.c b/net/netfilter/nft_set_pipapo.c index 9e0269e85017..ce617f6a215f 100644 --- a/net/netfilter/nft_set_pipapo.c +++ b/net/netfilter/nft_set_pipapo.c @@ -2026,13 +2026,15 @@ static void nft_pipapo_walk(const struct nft_ctx *ctx, struct nft_set *set, struct nft_set_iter *iter) { struct nft_pipapo *priv = nft_set_priv(set); - struct net *net = read_pnet(&set->net); struct nft_pipapo_match *m; struct nft_pipapo_field *f; int i, r; + WARN_ON_ONCE(iter->type != NFT_ITER_READ && + iter->type != NFT_ITER_UPDATE); + rcu_read_lock(); - if (iter->genmask == nft_genmask_cur(net)) + if (iter->type == NFT_ITER_READ) m = rcu_dereference(priv->match); else m = priv->clone; diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c index 4f2a3d46554f..bda604b37db0 100644 --- a/net/netlink/af_netlink.c +++ b/net/netlink/af_netlink.c @@ -2155,8 +2155,9 @@ void __netlink_clear_multicast_users(struct sock *ksk, unsigned int group) { struct sock *sk; struct netlink_table *tbl = &nl_table[ksk->sk_protocol]; + struct hlist_node *tmp; - sk_for_each_bound(sk, &tbl->mc_list) + sk_for_each_bound_safe(sk, tmp, &tbl->mc_list) netlink_update_socket_mc(nlk_sk(sk), group, 0); } diff --git a/net/qrtr/af_qrtr.c b/net/qrtr/af_qrtr.c index c2201f33f920..209b8934ed52 100644 --- a/net/qrtr/af_qrtr.c +++ b/net/qrtr/af_qrtr.c @@ -1669,7 +1669,7 @@ static int qrtr_bcast_enqueue(struct qrtr_node *node, struct sk_buff *skb, if (node->nid == QRTR_EP_NID_AUTO && type != QRTR_TYPE_HELLO) continue; - skbn = skb_clone(skb, GFP_KERNEL); + skbn = pskb_copy(skb, GFP_KERNEL); if (!skbn) break; skb_set_owner_w(skbn, skb->sk); diff --git a/net/sched/sch_api.c b/net/sched/sch_api.c index 5c2d230790db..b4e405676600 100644 --- a/net/sched/sch_api.c +++ b/net/sched/sch_api.c @@ -589,7 +589,6 @@ void __qdisc_calculate_pkt_len(struct sk_buff *skb, pkt_len = 1; qdisc_skb_cb(skb)->pkt_len = pkt_len; } -EXPORT_SYMBOL(__qdisc_calculate_pkt_len); void qdisc_warn_nonwc(const char *txt, struct Qdisc *qdisc) { @@ -781,7 +780,7 @@ void qdisc_tree_reduce_backlog(struct Qdisc *sch, int n, int len) drops = max_t(int, n, 0); rcu_read_lock(); while ((parentid = sch->parent)) { - if (TC_H_MAJ(parentid) == TC_H_MAJ(TC_H_INGRESS)) + if (parentid == TC_H_ROOT) break; if (sch->flags & TCQ_F_NOPARENT) @@ -1119,6 +1118,12 @@ static int qdisc_graft(struct net_device *dev, struct Qdisc *parent, return -EINVAL; } + if (new && + !(parent->flags & TCQ_F_MQROOT) && + rcu_access_pointer(new->stab)) { + NL_SET_ERR_MSG(extack, "STAB not supported on a non root"); + return -EINVAL; + } err = cops->graft(parent, cl, new, &old, extack); if (err) return err; diff --git a/net/sched/sch_taprio.c b/net/sched/sch_taprio.c index ec6b24edf5f9..04ed23b5f21b 100644 --- a/net/sched/sch_taprio.c +++ b/net/sched/sch_taprio.c @@ -1577,7 +1577,9 @@ static int taprio_change(struct Qdisc *sch, struct nlattr *opt, goto unlock; } - rcu_assign_pointer(q->admin_sched, new_admin); + /* Not going to race against advance_sched(), but still */ + admin = rcu_replace_pointer(q->admin_sched, new_admin, + lockdep_rtnl_is_held()); if (admin) call_rcu(&admin->rcu, taprio_free_sched_cb); } else { diff --git a/net/sctp/socket.c b/net/sctp/socket.c index 1b6a30e4b151..b58ff321b3e2 100644 --- a/net/sctp/socket.c +++ b/net/sctp/socket.c @@ -8262,6 +8262,7 @@ static int sctp_listen_start(struct sock *sk, int backlog) struct sctp_endpoint *ep = sp->ep; struct crypto_shash *tfm = NULL; char alg[32]; + int err; /* Allocate HMAC for generating cookie. */ if (!sp->hmac && sp->sctp_hmac_alg) { @@ -8288,17 +8289,26 @@ static int sctp_listen_start(struct sock *sk, int backlog) */ inet_sk_set_state(sk, SCTP_SS_LISTENING); if (!ep->base.bind_addr.port) { - if (sctp_autobind(sk)) - return -EAGAIN; + if (sctp_autobind(sk)) { + err = -EAGAIN; + goto err; + } } else { if (sctp_get_port(sk, inet_sk(sk)->inet_num)) { - inet_sk_set_state(sk, SCTP_SS_CLOSED); - return -EADDRINUSE; + err = -EADDRINUSE; + goto err; } } WRITE_ONCE(sk->sk_max_ack_backlog, backlog); - return sctp_hash_endpoint(ep); + err = sctp_hash_endpoint(ep); + if (err) + goto err; + + return 0; +err: + inet_sk_set_state(sk, SCTP_SS_CLOSED); + return err; } /* diff --git a/net/smc/smc_pnet.c b/net/smc/smc_pnet.c index ed9cfa11b589..7824b32cdb66 100644 --- a/net/smc/smc_pnet.c +++ b/net/smc/smc_pnet.c @@ -744,7 +744,7 @@ static int smc_pnet_add_pnetid(struct net *net, u8 *pnetid) write_lock(&sn->pnetids_ndev.lock); list_for_each_entry(pi, &sn->pnetids_ndev.list, list) { - if (smc_pnet_match(pnetid, pe->pnetid)) { + if (smc_pnet_match(pnetid, pi->pnetid)) { refcount_inc(&pi->refcnt); kfree(pe); goto unlock; diff --git a/net/tipc/bcast.c b/net/tipc/bcast.c index 593846d25214..114fef65f92e 100644 --- a/net/tipc/bcast.c +++ b/net/tipc/bcast.c @@ -320,8 +320,8 @@ static int tipc_mcast_send_sync(struct net *net, struct sk_buff *skb, { struct tipc_msg *hdr, *_hdr; struct sk_buff_head tmpq; + u16 cong_link_cnt = 0; struct sk_buff *_skb; - u16 cong_link_cnt; int rc = 0; /* Is a cluster supporting with new capabilities ? */ diff --git a/net/tipc/bearer.c b/net/tipc/bearer.c index 9928b3bd32c4..80ddfdbb93e3 100644 --- a/net/tipc/bearer.c +++ b/net/tipc/bearer.c @@ -161,8 +161,12 @@ static int bearer_name_validate(const char *name, /* return bearer name components, if necessary */ if (name_parts) { - strcpy(name_parts->media_name, media_name); - strcpy(name_parts->if_name, if_name); + if (strscpy(name_parts->media_name, media_name, + TIPC_MAX_MEDIA_NAME) < 0) + return 0; + if (strscpy(name_parts->if_name, if_name, + TIPC_MAX_IF_NAME) < 0) + return 0; } return 1; } diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index 943c2857da01..979b1f690bdb 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -8583,7 +8583,8 @@ nl80211_parse_sched_scan(struct wiphy *wiphy, struct wireless_dev *wdev, return ERR_PTR(-ENOMEM); if (n_ssids) - request->ssids = (void *)&request->channels[n_channels]; + request->ssids = (void *)request + + struct_size(request, channels, n_channels); request->n_ssids = n_ssids; if (ie_len) { if (n_ssids) diff --git a/net/wireless/scan.c b/net/wireless/scan.c index e8a9ce039295..f6307061aac4 100644 --- a/net/wireless/scan.c +++ b/net/wireless/scan.c @@ -2803,8 +2803,8 @@ int cfg80211_wext_siwscan(struct net_device *dev, n_channels = ieee80211_get_num_supported_channels(wiphy); } - creq = kzalloc(sizeof(*creq) + sizeof(struct cfg80211_ssid) + - n_channels * sizeof(void *), + creq = kzalloc(struct_size(creq, channels, n_channels) + + sizeof(struct cfg80211_ssid), GFP_ATOMIC); if (!creq) { err = -ENOMEM; @@ -2814,7 +2814,7 @@ int cfg80211_wext_siwscan(struct net_device *dev, creq->wiphy = wiphy; creq->wdev = dev->ieee80211_ptr; /* SSIDs come after channels */ - creq->ssids = (void *)&creq->channels[n_channels]; + creq->ssids = (void *)creq + struct_size(creq, channels, n_channels); creq->n_channels = n_channels; creq->n_ssids = 1; creq->scan_start = jiffies; diff --git a/net/wireless/sme.c b/net/wireless/sme.c index f7e2e172a68d..ae8ff2cdf1ff 100644 --- a/net/wireless/sme.c +++ b/net/wireless/sme.c @@ -116,7 +116,8 @@ static int cfg80211_conn_scan(struct wireless_dev *wdev) n_channels = i; } request->n_channels = n_channels; - request->ssids = (void *)&request->channels[n_channels]; + request->ssids = (void *)request + + struct_size(request, channels, n_channels); request->n_ssids = 1; memcpy(request->ssids[0].ssid, wdev->conn->params.ssid, diff --git a/net/wireless/util.c b/net/wireless/util.c index 4eabbd8ecf6a..7447fe3c331c 100644 --- a/net/wireless/util.c +++ b/net/wireless/util.c @@ -1231,7 +1231,7 @@ static u32 cfg80211_calculate_bitrate_edmg(struct rate_info *rate) static u32 cfg80211_calculate_bitrate_vht(struct rate_info *rate) { - static const u32 base[4][10] = { + static const u32 base[4][12] = { { 6500000, 13000000, 19500000, @@ -1242,7 +1242,9 @@ static u32 cfg80211_calculate_bitrate_vht(struct rate_info *rate) 65000000, 78000000, /* not in the spec, but some devices use this: */ - 86500000, + 86700000, + 97500000, + 108300000, }, { 13500000, 27000000, @@ -1254,6 +1256,8 @@ static u32 cfg80211_calculate_bitrate_vht(struct rate_info *rate) 135000000, 162000000, 180000000, + 202500000, + 225000000, }, { 29300000, 58500000, @@ -1265,6 +1269,8 @@ static u32 cfg80211_calculate_bitrate_vht(struct rate_info *rate) 292500000, 351000000, 390000000, + 438800000, + 487500000, }, { 58500000, 117000000, @@ -1276,12 +1282,14 @@ static u32 cfg80211_calculate_bitrate_vht(struct rate_info *rate) 585000000, 702000000, 780000000, + 877500000, + 975000000, }, }; u32 bitrate; int idx; - if (rate->mcs > 9) + if (rate->mcs > 11) goto warn; switch (rate->bw) { diff --git a/scripts/kconfig/merge_config.sh b/scripts/kconfig/merge_config.sh index 7201bdfaad1e..ac40f2f6a439 100755 --- a/scripts/kconfig/merge_config.sh +++ b/scripts/kconfig/merge_config.sh @@ -160,6 +160,8 @@ for ORIG_MERGE_FILE in $MERGE_LIST ; do sed -i "/$CFG[ =]/d" $MERGE_FILE fi done + # In case the previous file lacks a new line at the end + echo >> $TMP_FILE cat $MERGE_FILE >> $TMP_FILE done diff --git a/scripts/kconfig/qconf.cc b/scripts/kconfig/qconf.cc index f7eb093614f2..b889fe604e42 100644 --- a/scripts/kconfig/qconf.cc +++ b/scripts/kconfig/qconf.cc @@ -1167,7 +1167,7 @@ void ConfigInfoView::clicked(const QUrl &url) { QByteArray str = url.toEncoded(); const std::size_t count = str.size(); - char *data = new char[count + 1]; + char *data = new char[count + 2]; // '$' + '\0' struct symbol **result; struct menu *m = NULL; diff --git a/security/Kconfig b/security/Kconfig index 9893c316da89..b49370d4f466 100644 --- a/security/Kconfig +++ b/security/Kconfig @@ -19,6 +19,38 @@ config SECURITY_DMESG_RESTRICT If you are unsure how to answer this question, answer N. +choice + prompt "Allow /proc/pid/mem access override" + default PROC_MEM_ALWAYS_FORCE + help + Traditionally /proc/pid/mem allows users to override memory + permissions for users like ptrace, assuming they have ptrace + capability. + + This allows people to limit that - either never override, or + require actual active ptrace attachment. + + Defaults to the traditional behavior (for now) + +config PROC_MEM_ALWAYS_FORCE + bool "Traditional /proc/pid/mem behavior" + help + This allows /proc/pid/mem accesses to override memory mapping + permissions if you have ptrace access rights. + +config PROC_MEM_FORCE_PTRACE + bool "Require active ptrace() use for access override" + help + This allows /proc/pid/mem accesses to override memory mapping + permissions for active ptracers like gdb. + +config PROC_MEM_NO_FORCE + bool "Never" + help + Never override memory mapping permissions + +endchoice + config SECURITY bool "Enable different security models" depends on SYSFS diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 055e8cca428b..65d2f3209b17 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -6629,7 +6629,8 @@ static int selinux_inode_notifysecctx(struct inode *inode, void *ctx, u32 ctxlen */ static int selinux_inode_setsecctx(struct dentry *dentry, void *ctx, u32 ctxlen) { - return __vfs_setxattr_noperm(dentry, XATTR_NAME_SELINUX, ctx, ctxlen, 0); + return __vfs_setxattr_locked(dentry, XATTR_NAME_SELINUX, ctx, ctxlen, 0, + NULL); } static int selinux_inode_getsecctx(struct inode *inode, void **ctx, u32 *ctxlen) diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c index 199020a09f2c..4bf9217fe0d4 100644 --- a/security/smack/smack_lsm.c +++ b/security/smack/smack_lsm.c @@ -4652,7 +4652,8 @@ static int smack_inode_notifysecctx(struct inode *inode, void *ctx, u32 ctxlen) static int smack_inode_setsecctx(struct dentry *dentry, void *ctx, u32 ctxlen) { - return __vfs_setxattr_noperm(dentry, XATTR_NAME_SMACK, ctx, ctxlen, 0); + return __vfs_setxattr_locked(dentry, XATTR_NAME_SMACK, ctx, ctxlen, 0, + NULL); } static int smack_inode_getsecctx(struct inode *inode, void **ctx, u32 *ctxlen) diff --git a/security/smack/smackfs.c b/security/smack/smackfs.c index 8403c91a6b29..44f0b5148a5b 100644 --- a/security/smack/smackfs.c +++ b/security/smack/smackfs.c @@ -920,7 +920,7 @@ static ssize_t smk_set_cipso(struct file *file, const char __user *buf, rc = smk_netlbl_mls(maplevel, mapcatset, &ncats, SMK_CIPSOLEN); if (rc >= 0) { old_cat = skp->smk_netlabel.attr.mls.cat; - skp->smk_netlabel.attr.mls.cat = ncats.attr.mls.cat; + rcu_assign_pointer(skp->smk_netlabel.attr.mls.cat, ncats.attr.mls.cat); skp->smk_netlabel.attr.mls.lvl = ncats.attr.mls.lvl; synchronize_rcu(); netlbl_catmap_free(old_cat); diff --git a/security/tomoyo/domain.c b/security/tomoyo/domain.c index dc4ecc0b2038..2e00a2d6f343 100644 --- a/security/tomoyo/domain.c +++ b/security/tomoyo/domain.c @@ -725,10 +725,13 @@ int tomoyo_find_next_domain(struct linux_binprm *bprm) ee->r.obj = &ee->obj; ee->obj.path1 = bprm->file->f_path; /* Get symlink's pathname of program. */ - retval = -ENOENT; exename.name = tomoyo_realpath_nofollow(original_name); - if (!exename.name) - goto out; + if (!exename.name) { + /* Fallback to realpath if symlink's pathname does not exist. */ + exename.name = tomoyo_realpath_from_path(&bprm->file->f_path); + if (!exename.name) + goto out; + } tomoyo_fill_path_info(&exename); retry: /* Check 'aggregator' directive. */ diff --git a/sound/core/init.c b/sound/core/init.c index b6dd43005c27..476ab6df3aeb 100644 --- a/sound/core/init.c +++ b/sound/core/init.c @@ -534,13 +534,19 @@ int snd_card_free(struct snd_card *card) } EXPORT_SYMBOL(snd_card_free); +/* check, if the character is in the valid ASCII range */ +static inline bool safe_ascii_char(char c) +{ + return isascii(c) && isalnum(c); +} + /* retrieve the last word of shortname or longname */ static const char *retrieve_id_from_card_name(const char *name) { const char *spos = name; while (*name) { - if (isspace(*name) && isalnum(name[1])) + if (isspace(*name) && safe_ascii_char(name[1])) spos = name + 1; name++; } @@ -567,12 +573,12 @@ static void copy_valid_id_string(struct snd_card *card, const char *src, { char *id = card->id; - while (*nid && !isalnum(*nid)) + while (*nid && !safe_ascii_char(*nid)) nid++; if (isdigit(*nid)) *id++ = isalpha(*src) ? *src : 'D'; while (*nid && (size_t)(id - card->id) < sizeof(card->id) - 1) { - if (isalnum(*nid)) + if (safe_ascii_char(*nid)) *id++ = *nid; nid++; } @@ -670,7 +676,7 @@ card_id_store_attr(struct device *dev, struct device_attribute *attr, for (idx = 0; idx < copy; idx++) { c = buf[idx]; - if (!isalnum(c) && c != '_' && c != '-') + if (!safe_ascii_char(c) && c != '_' && c != '-') return -EINVAL; } memcpy(buf1, buf, copy); diff --git a/sound/core/oss/mixer_oss.c b/sound/core/oss/mixer_oss.c index bfed82a3a188..eb1a6229a31c 100644 --- a/sound/core/oss/mixer_oss.c +++ b/sound/core/oss/mixer_oss.c @@ -957,8 +957,8 @@ static void snd_mixer_oss_slot_free(struct snd_mixer_oss_slot *chn) struct slot *p = chn->private_data; if (p) { if (p->allocated && p->assigned) { - kfree_const(p->assigned->name); - kfree_const(p->assigned); + kfree(p->assigned->name); + kfree(p->assigned); } kfree(p); } diff --git a/sound/pci/asihpi/hpimsgx.c b/sound/pci/asihpi/hpimsgx.c index f7427f8eb630..761fc62f68f1 100644 --- a/sound/pci/asihpi/hpimsgx.c +++ b/sound/pci/asihpi/hpimsgx.c @@ -713,7 +713,7 @@ static u16 HPIMSGX__init(struct hpi_message *phm, phr->error = HPI_ERROR_PROCESSING_MESSAGE; return phr->error; } - if (hr.error == 0) { + if (hr.error == 0 && hr.u.s.adapter_index < HPI_MAX_ADAPTERS) { /* the adapter was created successfully save the mapping for future use */ hpi_entry_points[hr.u.s.adapter_index] = entry_point_func; diff --git a/sound/pci/hda/hda_generic.c b/sound/pci/hda/hda_generic.c index 733dc9953a38..d697041a8529 100644 --- a/sound/pci/hda/hda_generic.c +++ b/sound/pci/hda/hda_generic.c @@ -1377,7 +1377,7 @@ static int try_assign_dacs(struct hda_codec *codec, int num_outs, struct nid_path *path; hda_nid_t pin = pins[i]; - if (!spec->obey_preferred_dacs) { + if (!spec->preferred_dacs) { path = snd_hda_get_path_from_idx(codec, path_idx[i]); if (path) { badness += assign_out_path_ctls(codec, path); @@ -1389,7 +1389,7 @@ static int try_assign_dacs(struct hda_codec *codec, int num_outs, if (dacs[i]) { if (is_dac_already_used(codec, dacs[i])) badness += bad->shared_primary; - } else if (spec->obey_preferred_dacs) { + } else if (spec->preferred_dacs) { badness += BAD_NO_PRIMARY_DAC; } diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c index a3c6a5eeba3a..b92095bb28c3 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c @@ -2777,7 +2777,7 @@ static const struct pci_device_id azx_ids[] = { .driver_data = AZX_DRIVER_ATIHDMI_NS | AZX_DCAPS_PRESET_ATI_HDMI_NS | AZX_DCAPS_PM_RUNTIME }, /* GLENFLY */ - { PCI_DEVICE(0x6766, PCI_ANY_ID), + { PCI_DEVICE(PCI_VENDOR_ID_GLENFLY, PCI_ANY_ID), .class = PCI_CLASS_MULTIMEDIA_HD_AUDIO << 8, .class_mask = 0xffffff, .driver_data = AZX_DRIVER_GFHDMI | AZX_DCAPS_POSFIX_LPIB | diff --git a/sound/pci/hda/patch_conexant.c b/sound/pci/hda/patch_conexant.c index d908a39af9f5..51d97de74cad 100644 --- a/sound/pci/hda/patch_conexant.c +++ b/sound/pci/hda/patch_conexant.c @@ -234,6 +234,7 @@ enum { CXT_FIXUP_HP_SPECTRE, CXT_FIXUP_HP_GATE_MIC, CXT_FIXUP_MUTE_LED_GPIO, + CXT_FIXUP_HP_ELITEONE_OUT_DIS, CXT_FIXUP_HP_ZBOOK_MUTE_LED, CXT_FIXUP_HEADSET_MIC, CXT_FIXUP_HP_MIC_NO_PRESENCE, @@ -251,6 +252,19 @@ static void cxt_fixup_stereo_dmic(struct hda_codec *codec, spec->gen.inv_dmic_split = 1; } +/* fix widget control pin settings */ +static void cxt_fixup_update_pinctl(struct hda_codec *codec, + const struct hda_fixup *fix, int action) +{ + if (action == HDA_FIXUP_ACT_PROBE) { + /* Unset OUT_EN for this Node pin, leaving only HP_EN. + * This is the value stored in the codec register after + * the correct initialization of the previous windows boot. + */ + snd_hda_set_pin_ctl_cache(codec, 0x1d, AC_PINCTL_HP_EN); + } +} + static void cxt5066_increase_mic_boost(struct hda_codec *codec, const struct hda_fixup *fix, int action) { @@ -747,6 +761,23 @@ static const struct hda_pintbl cxt_pincfg_sws_js201d[] = { {} }; +/* pincfg quirk for Tuxedo Sirius; + * unfortunately the (PCI) SSID conflicts with System76 Pangolin pang14, + * which has incompatible pin setup, so we check the codec SSID (luckily + * different one!) and conditionally apply the quirk here + */ +static void cxt_fixup_sirius_top_speaker(struct hda_codec *codec, + const struct hda_fixup *fix, + int action) +{ + /* ignore for incorrectly picked-up pang14 */ + if (codec->core.subsystem_id == 0x278212b3) + return; + /* set up the top speaker pin */ + if (action == HDA_FIXUP_ACT_PRE_PROBE) + snd_hda_codec_set_pincfg(codec, 0x1d, 0x82170111); +} + static const struct hda_fixup cxt_fixups[] = { [CXT_PINCFG_LENOVO_X200] = { .type = HDA_FIXUP_PINS, @@ -885,6 +916,10 @@ static const struct hda_fixup cxt_fixups[] = { .type = HDA_FIXUP_FUNC, .v.func = cxt_fixup_mute_led_gpio, }, + [CXT_FIXUP_HP_ELITEONE_OUT_DIS] = { + .type = HDA_FIXUP_FUNC, + .v.func = cxt_fixup_update_pinctl, + }, [CXT_FIXUP_HP_ZBOOK_MUTE_LED] = { .type = HDA_FIXUP_FUNC, .v.func = cxt_fixup_hp_zbook_mute_led, @@ -907,11 +942,8 @@ static const struct hda_fixup cxt_fixups[] = { .v.pins = cxt_pincfg_sws_js201d, }, [CXT_PINCFG_TOP_SPEAKER] = { - .type = HDA_FIXUP_PINS, - .v.pins = (const struct hda_pintbl[]) { - { 0x1d, 0x82170111 }, - { } - }, + .type = HDA_FIXUP_FUNC, + .v.func = cxt_fixup_sirius_top_speaker, }, }; @@ -978,6 +1010,7 @@ static const struct snd_pci_quirk cxt5066_fixups[] = { SND_PCI_QUIRK(0x103c, 0x83b2, "HP EliteBook 840 G5", CXT_FIXUP_HP_DOCK), SND_PCI_QUIRK(0x103c, 0x83b3, "HP EliteBook 830 G5", CXT_FIXUP_HP_DOCK), SND_PCI_QUIRK(0x103c, 0x83d3, "HP ProBook 640 G4", CXT_FIXUP_HP_DOCK), + SND_PCI_QUIRK(0x103c, 0x83e5, "HP EliteOne 1000 G2", CXT_FIXUP_HP_ELITEONE_OUT_DIS), SND_PCI_QUIRK(0x103c, 0x8402, "HP ProBook 645 G4", CXT_FIXUP_MUTE_LED_GPIO), SND_PCI_QUIRK(0x103c, 0x8427, "HP ZBook Studio G5", CXT_FIXUP_HP_ZBOOK_MUTE_LED), SND_PCI_QUIRK(0x103c, 0x844f, "HP ZBook Studio G5", CXT_FIXUP_HP_ZBOOK_MUTE_LED), diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index c104a33b3e8f..05a2442cfc65 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -578,6 +578,7 @@ static void alc_shutup_pins(struct hda_codec *codec) switch (codec->core.vendor_id) { case 0x10ec0236: case 0x10ec0256: + case 0x10ec0257: case 0x19e58326: case 0x10ec0283: case 0x10ec0285: @@ -4846,6 +4847,30 @@ static void alc269_fixup_hp_line1_mic1_led(struct hda_codec *codec, } } +static void alc_hp_mute_disable(struct hda_codec *codec, unsigned int delay) +{ + if (delay <= 0) + delay = 75; + snd_hda_codec_write(codec, 0x21, 0, + AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE); + msleep(delay); + snd_hda_codec_write(codec, 0x21, 0, + AC_VERB_SET_PIN_WIDGET_CONTROL, 0x0); + msleep(delay); +} + +static void alc_hp_enable_unmute(struct hda_codec *codec, unsigned int delay) +{ + if (delay <= 0) + delay = 75; + snd_hda_codec_write(codec, 0x21, 0, + AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT); + msleep(delay); + snd_hda_codec_write(codec, 0x21, 0, + AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE); + msleep(delay); +} + static const struct coef_fw alc225_pre_hsmode[] = { UPDATE_COEF(0x4a, 1<<8, 0), UPDATE_COEFEX(0x57, 0x05, 1<<14, 0), @@ -4947,6 +4972,7 @@ static void alc_headset_mode_unplugged(struct hda_codec *codec) case 0x10ec0236: case 0x10ec0256: case 0x19e58326: + alc_hp_mute_disable(codec, 75); alc_process_coef_fw(codec, coef0256); break; case 0x10ec0234: @@ -4981,6 +5007,7 @@ static void alc_headset_mode_unplugged(struct hda_codec *codec) case 0x10ec0295: case 0x10ec0289: case 0x10ec0299: + alc_hp_mute_disable(codec, 75); alc_process_coef_fw(codec, alc225_pre_hsmode); alc_process_coef_fw(codec, coef0225); break; @@ -5206,6 +5233,7 @@ static void alc_headset_mode_default(struct hda_codec *codec) case 0x10ec0299: alc_process_coef_fw(codec, alc225_pre_hsmode); alc_process_coef_fw(codec, coef0225); + alc_hp_enable_unmute(codec, 75); break; case 0x10ec0255: alc_process_coef_fw(codec, coef0255); @@ -5218,6 +5246,7 @@ static void alc_headset_mode_default(struct hda_codec *codec) alc_write_coef_idx(codec, 0x45, 0xc089); msleep(50); alc_process_coef_fw(codec, coef0256); + alc_hp_enable_unmute(codec, 75); break; case 0x10ec0234: case 0x10ec0274: @@ -5315,6 +5344,7 @@ static void alc_headset_mode_ctia(struct hda_codec *codec) case 0x10ec0256: case 0x19e58326: alc_process_coef_fw(codec, coef0256); + alc_hp_enable_unmute(codec, 75); break; case 0x10ec0234: case 0x10ec0274: @@ -5363,6 +5393,7 @@ static void alc_headset_mode_ctia(struct hda_codec *codec) alc_process_coef_fw(codec, coef0225_2); else alc_process_coef_fw(codec, coef0225_1); + alc_hp_enable_unmute(codec, 75); break; case 0x10ec0867: alc_update_coefex_idx(codec, 0x57, 0x5, 1<<14, 0); @@ -5430,6 +5461,7 @@ static void alc_headset_mode_omtp(struct hda_codec *codec) case 0x10ec0256: case 0x19e58326: alc_process_coef_fw(codec, coef0256); + alc_hp_enable_unmute(codec, 75); break; case 0x10ec0234: case 0x10ec0274: @@ -5467,6 +5499,7 @@ static void alc_headset_mode_omtp(struct hda_codec *codec) case 0x10ec0289: case 0x10ec0299: alc_process_coef_fw(codec, coef0225); + alc_hp_enable_unmute(codec, 75); break; } codec_dbg(codec, "Headset jack set to Nokia-style headset mode.\n"); @@ -5535,25 +5568,21 @@ static void alc_determine_headset_type(struct hda_codec *codec) alc_write_coef_idx(codec, 0x06, 0x6104); alc_write_coefex_idx(codec, 0x57, 0x3, 0x09a3); - snd_hda_codec_write(codec, 0x21, 0, - AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE); - msleep(80); - snd_hda_codec_write(codec, 0x21, 0, - AC_VERB_SET_PIN_WIDGET_CONTROL, 0x0); - alc_process_coef_fw(codec, coef0255); msleep(300); val = alc_read_coef_idx(codec, 0x46); is_ctia = (val & 0x0070) == 0x0070; - + if (!is_ctia) { + alc_write_coef_idx(codec, 0x45, 0xe089); + msleep(100); + val = alc_read_coef_idx(codec, 0x46); + if ((val & 0x0070) == 0x0070) + is_ctia = false; + else + is_ctia = true; + } alc_write_coefex_idx(codec, 0x57, 0x3, 0x0da3); alc_update_coefex_idx(codec, 0x57, 0x5, 1<<14, 0); - - snd_hda_codec_write(codec, 0x21, 0, - AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT); - msleep(80); - snd_hda_codec_write(codec, 0x21, 0, - AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE); break; case 0x10ec0234: case 0x10ec0274: @@ -5630,12 +5659,6 @@ static void alc_determine_headset_type(struct hda_codec *codec) case 0x10ec0295: case 0x10ec0289: case 0x10ec0299: - snd_hda_codec_write(codec, 0x21, 0, - AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE); - msleep(80); - snd_hda_codec_write(codec, 0x21, 0, - AC_VERB_SET_PIN_WIDGET_CONTROL, 0x0); - alc_process_coef_fw(codec, alc225_pre_hsmode); alc_update_coef_idx(codec, 0x67, 0xf000, 0x1000); val = alc_read_coef_idx(codec, 0x45); @@ -5652,15 +5675,19 @@ static void alc_determine_headset_type(struct hda_codec *codec) val = alc_read_coef_idx(codec, 0x46); is_ctia = (val & 0x00f0) == 0x00f0; } + if (!is_ctia) { + alc_update_coef_idx(codec, 0x45, 0x3f<<10, 0x38<<10); + alc_update_coef_idx(codec, 0x49, 3<<8, 1<<8); + msleep(100); + val = alc_read_coef_idx(codec, 0x46); + if ((val & 0x00f0) == 0x00f0) + is_ctia = false; + else + is_ctia = true; + } alc_update_coef_idx(codec, 0x4a, 7<<6, 7<<6); alc_update_coef_idx(codec, 0x4a, 3<<4, 3<<4); alc_update_coef_idx(codec, 0x67, 0xf000, 0x3000); - - snd_hda_codec_write(codec, 0x21, 0, - AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT); - msleep(80); - snd_hda_codec_write(codec, 0x21, 0, - AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE); break; case 0x10ec0867: is_ctia = true; @@ -9392,6 +9419,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { SND_PCI_QUIRK(0x1849, 0xa233, "Positivo Master C6300", ALC269_FIXUP_HEADSET_MIC), SND_PCI_QUIRK(0x19e5, 0x3204, "Huawei MACH-WX9", ALC256_FIXUP_HUAWEI_MACH_WX9_PINS), SND_PCI_QUIRK(0x19e5, 0x320f, "Huawei WRT-WX9 ", ALC256_FIXUP_ASUS_MIC_NO_PRESENCE), + SND_PCI_QUIRK(0x19e5, 0x3212, "Huawei KLV-WX9 ", ALC256_FIXUP_ACER_HEADSET_MIC), SND_PCI_QUIRK(0x1b35, 0x1235, "CZC B20", ALC269_FIXUP_CZC_B20), SND_PCI_QUIRK(0x1b35, 0x1236, "CZC TMI", ALC269_FIXUP_CZC_TMI), SND_PCI_QUIRK(0x1b35, 0x1237, "CZC L101", ALC269_FIXUP_CZC_L101), diff --git a/sound/pci/rme9652/hdsp.c b/sound/pci/rme9652/hdsp.c index 954347424500..f592eb7a5d1b 100644 --- a/sound/pci/rme9652/hdsp.c +++ b/sound/pci/rme9652/hdsp.c @@ -1303,8 +1303,10 @@ static int snd_hdsp_midi_output_possible (struct hdsp *hdsp, int id) static void snd_hdsp_flush_midi_input (struct hdsp *hdsp, int id) { - while (snd_hdsp_midi_input_available (hdsp, id)) - snd_hdsp_midi_read_byte (hdsp, id); + int count = 256; + + while (snd_hdsp_midi_input_available(hdsp, id) && --count) + snd_hdsp_midi_read_byte(hdsp, id); } static int snd_hdsp_midi_output_write (struct hdsp_midi *hmidi) diff --git a/sound/pci/rme9652/hdspm.c b/sound/pci/rme9652/hdspm.c index 51c3c6a08a1c..04f9d92af46c 100644 --- a/sound/pci/rme9652/hdspm.c +++ b/sound/pci/rme9652/hdspm.c @@ -1839,8 +1839,10 @@ static inline int snd_hdspm_midi_output_possible (struct hdspm *hdspm, int id) static void snd_hdspm_flush_midi_input(struct hdspm *hdspm, int id) { - while (snd_hdspm_midi_input_available (hdspm, id)) - snd_hdspm_midi_read_byte (hdspm, id); + int count = 256; + + while (snd_hdspm_midi_input_available(hdspm, id) && --count) + snd_hdspm_midi_read_byte(hdspm, id); } static int snd_hdspm_midi_output_write (struct hdspm_midi *hmidi) diff --git a/sound/soc/au1x/db1200.c b/sound/soc/au1x/db1200.c index 5f8baad37a40..48243164b7ac 100644 --- a/sound/soc/au1x/db1200.c +++ b/sound/soc/au1x/db1200.c @@ -44,6 +44,7 @@ static const struct platform_device_id db1200_pids[] = { }, {}, }; +MODULE_DEVICE_TABLE(platform, db1200_pids); /*------------------------- AC97 PART ---------------------------*/ diff --git a/sound/soc/codecs/rt5682.c b/sound/soc/codecs/rt5682.c index 113ed00ddf1e..d62212791dff 100644 --- a/sound/soc/codecs/rt5682.c +++ b/sound/soc/codecs/rt5682.c @@ -2843,8 +2843,10 @@ static int rt5682_register_dai_clks(struct snd_soc_component *component) } if (dev->of_node) { - devm_of_clk_add_hw_provider(dev, of_clk_hw_simple_get, + ret = devm_of_clk_add_hw_provider(dev, of_clk_hw_simple_get, dai_clk_hw); + if (ret) + return ret; } else { ret = devm_clk_hw_register_clkdev(dev, dai_clk_hw, init.name, diff --git a/sound/soc/codecs/tda7419.c b/sound/soc/codecs/tda7419.c index 83d220054c96..9183db51547d 100644 --- a/sound/soc/codecs/tda7419.c +++ b/sound/soc/codecs/tda7419.c @@ -624,6 +624,7 @@ static const struct of_device_id tda7419_of_match[] = { { .compatible = "st,tda7419" }, { }, }; +MODULE_DEVICE_TABLE(of, tda7419_of_match); static struct i2c_driver tda7419_driver = { .driver = { diff --git a/sound/soc/fsl/fsl_sai.c b/sound/soc/fsl/fsl_sai.c index 03731d14d475..998102711da0 100644 --- a/sound/soc/fsl/fsl_sai.c +++ b/sound/soc/fsl/fsl_sai.c @@ -490,6 +490,9 @@ static int fsl_sai_hw_params(struct snd_pcm_substream *substream, val_cr4 |= FSL_SAI_CR4_FRSZ(slots); + /* Set to avoid channel swap */ + val_cr4 |= FSL_SAI_CR4_FCONT; + /* Set to output mode to avoid tri-stated data pins */ if (tx) val_cr4 |= FSL_SAI_CR4_CHMOD; @@ -515,7 +518,7 @@ static int fsl_sai_hw_params(struct snd_pcm_substream *substream, FSL_SAI_CR3_TRCE((1 << pins) - 1)); regmap_update_bits(sai->regmap, FSL_SAI_xCR4(tx, ofs), FSL_SAI_CR4_SYWD_MASK | FSL_SAI_CR4_FRSZ_MASK | - FSL_SAI_CR4_CHMOD_MASK, + FSL_SAI_CR4_CHMOD_MASK | FSL_SAI_CR4_FCONT_MASK, val_cr4); regmap_update_bits(sai->regmap, FSL_SAI_xCR5(tx, ofs), FSL_SAI_CR5_WNW_MASK | FSL_SAI_CR5_W0W_MASK | diff --git a/sound/soc/fsl/fsl_sai.h b/sound/soc/fsl/fsl_sai.h index 691847d54b17..eff3b7b2dd3e 100644 --- a/sound/soc/fsl/fsl_sai.h +++ b/sound/soc/fsl/fsl_sai.h @@ -132,6 +132,7 @@ /* SAI Transmit and Receive Configuration 4 Register */ +#define FSL_SAI_CR4_FCONT_MASK BIT(28) #define FSL_SAI_CR4_FCONT BIT(28) #define FSL_SAI_CR4_FCOMB_SHIFT BIT(26) #define FSL_SAI_CR4_FCOMB_SOFT BIT(27) diff --git a/sound/soc/intel/keembay/kmb_platform.c b/sound/soc/intel/keembay/kmb_platform.c index 291a686568c2..c7b754034d24 100644 --- a/sound/soc/intel/keembay/kmb_platform.c +++ b/sound/soc/intel/keembay/kmb_platform.c @@ -634,6 +634,7 @@ static const struct of_device_id kmb_plat_of_match[] = { { .compatible = "intel,keembay-tdm", .data = &intel_kmb_tdm_dai}, {} }; +MODULE_DEVICE_TABLE(of, kmb_plat_of_match); static int kmb_plat_dai_probe(struct platform_device *pdev) { diff --git a/sound/soc/meson/axg-card.c b/sound/soc/meson/axg-card.c index 2b77010c2c5c..985dbe1805e3 100644 --- a/sound/soc/meson/axg-card.c +++ b/sound/soc/meson/axg-card.c @@ -104,7 +104,7 @@ static int axg_card_add_tdm_loopback(struct snd_soc_card *card, int *index) { struct meson_card *priv = snd_soc_card_get_drvdata(card); - struct snd_soc_dai_link *pad = &card->dai_link[*index]; + struct snd_soc_dai_link *pad; struct snd_soc_dai_link *lb; struct snd_soc_dai_link_component *dlc; int ret; @@ -114,6 +114,7 @@ static int axg_card_add_tdm_loopback(struct snd_soc_card *card, if (ret) return ret; + pad = &card->dai_link[*index]; lb = &card->dai_link[*index + 1]; lb->name = devm_kasprintf(card->dev, GFP_KERNEL, "%s-lb", pad->name); diff --git a/sound/usb/card.c b/sound/usb/card.c index ee5d28ad8968..c53864905b71 100644 --- a/sound/usb/card.c +++ b/sound/usb/card.c @@ -556,6 +556,12 @@ static const struct usb_audio_device_name usb_audio_names[] = { /* Creative/Toshiba Multimedia Center SB-0500 */ DEVICE_NAME(0x041e, 0x3048, "Toshiba", "SB-0500"), + /* Logitech Audio Devices */ + DEVICE_NAME(0x046d, 0x0867, "Logitech, Inc.", "Logi-MeetUp"), + DEVICE_NAME(0x046d, 0x0874, "Logitech, Inc.", "Logi-Tap-Audio"), + DEVICE_NAME(0x046d, 0x087c, "Logitech, Inc.", "Logi-Huddle"), + DEVICE_NAME(0x046d, 0x0898, "Logitech, Inc.", "Logi-RB-Audio"), + DEVICE_NAME(0x046d, 0x08d2, "Logitech, Inc.", "Logi-RBM-Audio"), DEVICE_NAME(0x046d, 0x0990, "Logitech, Inc.", "QuickCam Pro 9000"), /* ASUS ROG Zenith II: this machine has also two devices, one for diff --git a/sound/usb/line6/podhd.c b/sound/usb/line6/podhd.c index b24bc82f89e3..a933a0241524 100644 --- a/sound/usb/line6/podhd.c +++ b/sound/usb/line6/podhd.c @@ -507,7 +507,7 @@ static const struct line6_properties podhd_properties_table[] = { [LINE6_PODHD500X] = { .id = "PODHD500X", .name = "POD HD500X", - .capabilities = LINE6_CAP_CONTROL + .capabilities = LINE6_CAP_CONTROL | LINE6_CAP_HWMON_CTL | LINE6_CAP_PCM | LINE6_CAP_HWMON, .altsetting = 1, .ep_ctrl_r = 0x81, diff --git a/sound/usb/quirks-table.h b/sound/usb/quirks-table.h index 008229ae7ff4..c6104523dd79 100644 --- a/sound/usb/quirks-table.h +++ b/sound/usb/quirks-table.h @@ -35,6 +35,83 @@ .bInterfaceClass = USB_CLASS_AUDIO, \ .bInterfaceSubClass = USB_SUBCLASS_AUDIOCONTROL +/* Quirk .driver_info, followed by the definition of the quirk entry; + * put like QUIRK_DRIVER_INFO { ... } in each entry of the quirk table + */ +#define QUIRK_DRIVER_INFO \ + .driver_info = (unsigned long)&(const struct snd_usb_audio_quirk) + +/* + * Macros for quirk data entries + */ + +/* Quirk data entry for ignoring the interface */ +#define QUIRK_DATA_IGNORE(_ifno) \ + .ifnum = (_ifno), .type = QUIRK_IGNORE_INTERFACE +/* Quirk data entry for a standard audio interface */ +#define QUIRK_DATA_STANDARD_AUDIO(_ifno) \ + .ifnum = (_ifno), .type = QUIRK_AUDIO_STANDARD_INTERFACE +/* Quirk data entry for a standard MIDI interface */ +#define QUIRK_DATA_STANDARD_MIDI(_ifno) \ + .ifnum = (_ifno), .type = QUIRK_MIDI_STANDARD_INTERFACE +/* Quirk data entry for a standard mixer interface */ +#define QUIRK_DATA_STANDARD_MIXER(_ifno) \ + .ifnum = (_ifno), .type = QUIRK_AUDIO_STANDARD_MIXER + +/* Quirk data entry for Yamaha MIDI */ +#define QUIRK_DATA_MIDI_YAMAHA(_ifno) \ + .ifnum = (_ifno), .type = QUIRK_MIDI_YAMAHA +/* Quirk data entry for Edirol UAxx */ +#define QUIRK_DATA_EDIROL_UAXX(_ifno) \ + .ifnum = (_ifno), .type = QUIRK_AUDIO_EDIROL_UAXX +/* Quirk data entry for raw bytes interface */ +#define QUIRK_DATA_RAW_BYTES(_ifno) \ + .ifnum = (_ifno), .type = QUIRK_MIDI_RAW_BYTES + +/* Quirk composite array terminator */ +#define QUIRK_COMPOSITE_END { .ifnum = -1 } + +/* Quirk data entry for composite quirks; + * followed by the quirk array that is terminated with QUIRK_COMPOSITE_END + * e.g. QUIRK_DATA_COMPOSITE { { quirk1 }, { quirk2 },..., QUIRK_COMPOSITE_END } + */ +#define QUIRK_DATA_COMPOSITE \ + .ifnum = QUIRK_ANY_INTERFACE, \ + .type = QUIRK_COMPOSITE, \ + .data = &(const struct snd_usb_audio_quirk[]) + +/* Quirk data entry for a fixed audio endpoint; + * followed by audioformat definition + * e.g. QUIRK_DATA_AUDIOFORMAT(n) { .formats = xxx, ... } + */ +#define QUIRK_DATA_AUDIOFORMAT(_ifno) \ + .ifnum = (_ifno), \ + .type = QUIRK_AUDIO_FIXED_ENDPOINT, \ + .data = &(const struct audioformat) + +/* Quirk data entry for a fixed MIDI endpoint; + * followed by snd_usb_midi_endpoint_info definition + * e.g. QUIRK_DATA_MIDI_FIXED_ENDPOINT(n) { .out_cables = x, .in_cables = y } + */ +#define QUIRK_DATA_MIDI_FIXED_ENDPOINT(_ifno) \ + .ifnum = (_ifno), \ + .type = QUIRK_MIDI_FIXED_ENDPOINT, \ + .data = &(const struct snd_usb_midi_endpoint_info) +/* Quirk data entry for a MIDIMAN MIDI endpoint */ +#define QUIRK_DATA_MIDI_MIDIMAN(_ifno) \ + .ifnum = (_ifno), \ + .type = QUIRK_MIDI_MIDIMAN, \ + .data = &(const struct snd_usb_midi_endpoint_info) +/* Quirk data entry for a EMAGIC MIDI endpoint */ +#define QUIRK_DATA_MIDI_EMAGIC(_ifno) \ + .ifnum = (_ifno), \ + .type = QUIRK_MIDI_EMAGIC, \ + .data = &(const struct snd_usb_midi_endpoint_info) + +/* + * Here we go... the quirk table definition begins: + */ + /* FTDI devices */ { USB_DEVICE(0x0403, 0xb8d8), diff --git a/tools/iio/iio_generic_buffer.c b/tools/iio/iio_generic_buffer.c index 2fd10eab75b5..5ef09ac6e7cf 100644 --- a/tools/iio/iio_generic_buffer.c +++ b/tools/iio/iio_generic_buffer.c @@ -479,6 +479,10 @@ int main(int argc, char **argv) return -ENOMEM; } trigger_name = malloc(IIO_MAX_NAME_LENGTH); + if (!trigger_name) { + ret = -ENOMEM; + goto error; + } ret = read_sysfs_string("name", trig_dev_name, trigger_name); free(trig_dev_name); if (ret < 0) { diff --git a/tools/lib/subcmd/parse-options.c b/tools/lib/subcmd/parse-options.c index e799d35cba43..3624bcd5195d 100644 --- a/tools/lib/subcmd/parse-options.c +++ b/tools/lib/subcmd/parse-options.c @@ -637,9 +637,11 @@ int parse_options_subcommand(int argc, const char **argv, const struct option *o /* build usage string if it's not provided */ if (subcommands && !usagestr[0]) { + int i; + astrcatf(&buf, "%s %s [] {", subcmd_config.exec_name, argv[0]); - for (int i = 0; subcommands[i]; i++) { + for (i = 0; subcommands[i]; i++) { if (i) astrcat(&buf, "|"); astrcat(&buf, subcommands[i]); @@ -665,7 +667,9 @@ int parse_options_subcommand(int argc, const char **argv, const struct option *o exit(130); case PARSE_OPT_LIST_SUBCMDS: if (subcommands) { - for (int i = 0; subcommands[i]; i++) + int i; + + for (i = 0; subcommands[i]; i++) printf("%s ", subcommands[i]); } putchar('\n'); diff --git a/tools/objtool/Makefile b/tools/objtool/Makefile index a43096f713c7..0a1f1559a621 100644 --- a/tools/objtool/Makefile +++ b/tools/objtool/Makefile @@ -59,7 +59,7 @@ $(OBJTOOL): $(LIBSUBCMD) $(OBJTOOL_IN) $(LIBSUBCMD): fixdep FORCE - $(Q)$(MAKE) -C $(SUBCMD_SRCDIR) OUTPUT=$(LIBSUBCMD_OUTPUT) + $(Q)$(MAKE) -C $(SUBCMD_SRCDIR) EXTRA_CFLAGS="${CFLAGS}" OUTPUT=$(LIBSUBCMD_OUTPUT) clean: $(call QUIET_CLEAN, objtool) $(RM) $(OBJTOOL) diff --git a/tools/perf/builtin-sched.c b/tools/perf/builtin-sched.c index 02e5774cabb6..4f8658f5f9de 100644 --- a/tools/perf/builtin-sched.c +++ b/tools/perf/builtin-sched.c @@ -2577,9 +2577,12 @@ static int timehist_sched_change_event(struct perf_tool *tool, * - previous sched event is out of window - we are done * - sample time is beyond window user cares about - reset it * to close out stats for time window interest + * - If tprev is 0, that is, sched_in event for current task is + * not recorded, cannot determine whether sched_in event is + * within time window interest - ignore it */ if (ptime->end) { - if (tprev > ptime->end) + if (!tprev || tprev > ptime->end) goto out; if (t > ptime->end) @@ -3027,7 +3030,8 @@ static int perf_sched__timehist(struct perf_sched *sched) if (perf_time__parse_str(&sched->ptime, sched->time_str) != 0) { pr_err("Invalid time string\n"); - return -EINVAL; + err = -EINVAL; + goto out; } if (timehist_check_attr(sched, evlist) != 0) diff --git a/tools/perf/util/time-utils.c b/tools/perf/util/time-utils.c index 302443921681..1b91ccd4d523 100644 --- a/tools/perf/util/time-utils.c +++ b/tools/perf/util/time-utils.c @@ -20,7 +20,7 @@ int parse_nsec_time(const char *str, u64 *ptime) u64 time_sec, time_nsec; char *end; - time_sec = strtoul(str, &end, 10); + time_sec = strtoull(str, &end, 10); if (*end != '.' && *end != '\0') return -1; @@ -38,7 +38,7 @@ int parse_nsec_time(const char *str, u64 *ptime) for (i = strlen(nsec_buf); i < 9; i++) nsec_buf[i] = '0'; - time_nsec = strtoul(nsec_buf, &end, 10); + time_nsec = strtoull(nsec_buf, &end, 10); if (*end != '\0') return -1; } else diff --git a/tools/testing/ktest/ktest.pl b/tools/testing/ktest/ktest.pl index f72da30795dd..f260b455b74d 100755 --- a/tools/testing/ktest/ktest.pl +++ b/tools/testing/ktest/ktest.pl @@ -1985,7 +1985,7 @@ sub get_grub_index { } elsif ($reboot_type eq "grub2") { $command = "cat $grub_file"; $target = '^\s*menuentry.*' . $grub_menu_qt; - $skip = '^\s*menuentry'; + $skip = '^\s*menuentry\s'; $submenu = '^\s*submenu\s'; } elsif ($reboot_type eq "grub2bls") { $command = $grub_bls_get; diff --git a/tools/testing/selftests/bpf/bench.c b/tools/testing/selftests/bpf/bench.c index 332ed2f7b402..0a257dd3e027 100644 --- a/tools/testing/selftests/bpf/bench.c +++ b/tools/testing/selftests/bpf/bench.c @@ -11,6 +11,7 @@ #include #include #include "bench.h" +#include "bpf_util.h" #include "testing_helpers.h" struct env env = { diff --git a/tools/testing/selftests/bpf/map_tests/sk_storage_map.c b/tools/testing/selftests/bpf/map_tests/sk_storage_map.c index e569edc679d8..9228e33cc0db 100644 --- a/tools/testing/selftests/bpf/map_tests/sk_storage_map.c +++ b/tools/testing/selftests/bpf/map_tests/sk_storage_map.c @@ -416,7 +416,7 @@ static void test_sk_storage_map_stress_free(void) rlim_new.rlim_max = rlim_new.rlim_cur + 128; err = setrlimit(RLIMIT_NOFILE, &rlim_new); CHECK(err, "setrlimit(RLIMIT_NOFILE)", "rlim_new:%lu errno:%d", - rlim_new.rlim_cur, errno); + (unsigned long) rlim_new.rlim_cur, errno); } err = do_sk_storage_map_stress_free(); diff --git a/tools/testing/selftests/bpf/prog_tests/flow_dissector.c b/tools/testing/selftests/bpf/prog_tests/flow_dissector.c index cd6dc80edf18..5518bbf370bf 100644 --- a/tools/testing/selftests/bpf/prog_tests/flow_dissector.c +++ b/tools/testing/selftests/bpf/prog_tests/flow_dissector.c @@ -1,4 +1,5 @@ // SPDX-License-Identifier: GPL-2.0 +#define _GNU_SOURCE #include #include #include diff --git a/tools/testing/selftests/bpf/prog_tests/kfree_skb.c b/tools/testing/selftests/bpf/prog_tests/kfree_skb.c index 42c3a3103c26..a37b1d663f96 100644 --- a/tools/testing/selftests/bpf/prog_tests/kfree_skb.c +++ b/tools/testing/selftests/bpf/prog_tests/kfree_skb.c @@ -1,4 +1,5 @@ // SPDX-License-Identifier: GPL-2.0 +#define _GNU_SOURCE #include #include diff --git a/tools/testing/selftests/bpf/prog_tests/tcp_rtt.c b/tools/testing/selftests/bpf/prog_tests/tcp_rtt.c index d207e968e6b1..dee68ef976ae 100644 --- a/tools/testing/selftests/bpf/prog_tests/tcp_rtt.c +++ b/tools/testing/selftests/bpf/prog_tests/tcp_rtt.c @@ -1,4 +1,5 @@ // SPDX-License-Identifier: GPL-2.0 +#define _GNU_SOURCE #include #include "cgroup_helpers.h" #include "network_helpers.h" diff --git a/tools/testing/selftests/bpf/progs/cg_storage_multi.h b/tools/testing/selftests/bpf/progs/cg_storage_multi.h index a0778fe7857a..41d59f0ee606 100644 --- a/tools/testing/selftests/bpf/progs/cg_storage_multi.h +++ b/tools/testing/selftests/bpf/progs/cg_storage_multi.h @@ -3,8 +3,6 @@ #ifndef __PROGS_CG_STORAGE_MULTI_H #define __PROGS_CG_STORAGE_MULTI_H -#include - struct cgroup_value { __u32 egress_pkts; __u32 ingress_pkts; diff --git a/tools/testing/selftests/bpf/test_cpp.cpp b/tools/testing/selftests/bpf/test_cpp.cpp index a8d2e9a87fbf..6edcb541cc90 100644 --- a/tools/testing/selftests/bpf/test_cpp.cpp +++ b/tools/testing/selftests/bpf/test_cpp.cpp @@ -3,6 +3,10 @@ #include #include #include + +#ifndef _Bool +#define _Bool bool +#endif #include "test_core_extern.skel.h" /* do nothing, just make sure we can link successfully */ diff --git a/tools/testing/selftests/bpf/test_lru_map.c b/tools/testing/selftests/bpf/test_lru_map.c index 6a5349f9eb14..7748d28e8b97 100644 --- a/tools/testing/selftests/bpf/test_lru_map.c +++ b/tools/testing/selftests/bpf/test_lru_map.c @@ -137,7 +137,8 @@ static int sched_next_online(int pid, int *next_to_try) while (next < nr_cpus) { CPU_ZERO(&cpuset); - CPU_SET(next++, &cpuset); + CPU_SET(next, &cpuset); + next++; if (!sched_setaffinity(pid, sizeof(cpuset), &cpuset)) { ret = 0; break; diff --git a/tools/testing/selftests/breakpoints/step_after_suspend_test.c b/tools/testing/selftests/breakpoints/step_after_suspend_test.c index 2cf6f10ab7c4..fc02918962c7 100644 --- a/tools/testing/selftests/breakpoints/step_after_suspend_test.c +++ b/tools/testing/selftests/breakpoints/step_after_suspend_test.c @@ -153,7 +153,10 @@ void suspend(void) if (err < 0) ksft_exit_fail_msg("timerfd_settime() failed\n"); - if (write(power_state_fd, "mem", strlen("mem")) != strlen("mem")) + system("(echo mem > /sys/power/state) 2> /dev/null"); + + timerfd_gettime(timerfd, &spec); + if (spec.it_value.tv_sec != 0 || spec.it_value.tv_nsec != 0) ksft_exit_fail_msg("Failed to enter Suspend state\n"); close(timerfd); diff --git a/tools/testing/selftests/vDSO/parse_vdso.c b/tools/testing/selftests/vDSO/parse_vdso.c index 4ae417372e9e..d9ccc5acac18 100644 --- a/tools/testing/selftests/vDSO/parse_vdso.c +++ b/tools/testing/selftests/vDSO/parse_vdso.c @@ -216,7 +216,8 @@ void *vdso_sym(const char *version, const char *name) ELF(Sym) *sym = &vdso_info.symtab[chain]; /* Check for a defined global or weak function w/ right name. */ - if (ELF64_ST_TYPE(sym->st_info) != STT_FUNC) + if (ELF64_ST_TYPE(sym->st_info) != STT_FUNC && + ELF64_ST_TYPE(sym->st_info) != STT_NOTYPE) continue; if (ELF64_ST_BIND(sym->st_info) != STB_GLOBAL && ELF64_ST_BIND(sym->st_info) != STB_WEAK) diff --git a/tools/testing/selftests/vm/charge_reserved_hugetlb.sh b/tools/testing/selftests/vm/charge_reserved_hugetlb.sh index d0107f8ae621..28192ec98498 100644 --- a/tools/testing/selftests/vm/charge_reserved_hugetlb.sh +++ b/tools/testing/selftests/vm/charge_reserved_hugetlb.sh @@ -249,7 +249,7 @@ function cleanup_hugetlb_memory() { local cgroup="$1" if [[ "$(pgrep -f write_to_hugetlbfs)" != "" ]]; then echo killing write_to_hugetlbfs - killall -2 write_to_hugetlbfs + killall -2 --wait write_to_hugetlbfs wait_for_hugetlb_memory_to_get_depleted $cgroup fi set -e diff --git a/tools/testing/selftests/vm/write_to_hugetlbfs.c b/tools/testing/selftests/vm/write_to_hugetlbfs.c index 6a2caba19ee1..1289d311efd7 100644 --- a/tools/testing/selftests/vm/write_to_hugetlbfs.c +++ b/tools/testing/selftests/vm/write_to_hugetlbfs.c @@ -28,7 +28,7 @@ enum method { /* Global variables. */ static const char *self; -static char *shmaddr; +static int *shmaddr; static int shmid; /* @@ -47,15 +47,17 @@ void sig_handler(int signo) { printf("Received %d.\n", signo); if (signo == SIGINT) { - printf("Deleting the memory\n"); - if (shmdt((const void *)shmaddr) != 0) { - perror("Detach failure"); - shmctl(shmid, IPC_RMID, NULL); - exit(4); - } + if (shmaddr) { + printf("Deleting the memory\n"); + if (shmdt((const void *)shmaddr) != 0) { + perror("Detach failure"); + shmctl(shmid, IPC_RMID, NULL); + exit(4); + } - shmctl(shmid, IPC_RMID, NULL); - printf("Done deleting the memory\n"); + shmctl(shmid, IPC_RMID, NULL); + printf("Done deleting the memory\n"); + } } exit(2); } @@ -211,7 +213,8 @@ int main(int argc, char **argv) shmctl(shmid, IPC_RMID, NULL); exit(2); } - printf("shmaddr: %p\n", ptr); + shmaddr = ptr; + printf("shmaddr: %p\n", shmaddr); break; default: diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c index b7638c3c9eb7..ef66abe687d7 100644 --- a/virt/kvm/kvm_main.c +++ b/virt/kvm/kvm_main.c @@ -3090,12 +3090,13 @@ void kvm_vcpu_on_spin(struct kvm_vcpu *me, bool yield_to_kernel_mode) { struct kvm *kvm = me->kvm; struct kvm_vcpu *vcpu; - int last_boosted_vcpu = me->kvm->last_boosted_vcpu; + int last_boosted_vcpu; int yielded = 0; int try = 3; int pass; int i; + last_boosted_vcpu = READ_ONCE(kvm->last_boosted_vcpu); kvm_vcpu_set_in_spin_loop(me, true); /* * We boost the priority of a VCPU that is runnable but not @@ -3126,7 +3127,7 @@ void kvm_vcpu_on_spin(struct kvm_vcpu *me, bool yield_to_kernel_mode) yielded = kvm_vcpu_yield_to(vcpu); if (yielded > 0) { - kvm->last_boosted_vcpu = i; + WRITE_ONCE(kvm->last_boosted_vcpu, i); break; } else if (yielded < 0) { try--;