diff --git a/BUILD.bazel b/BUILD.bazel index 078c5c7588af..3a63587af890 100644 --- a/BUILD.bazel +++ b/BUILD.bazel @@ -24,6 +24,7 @@ _aarch64_additional_kmi_symbol_lists = [ "android/abi_gki_aarch64_honor", "android/abi_gki_aarch64_imx", "android/abi_gki_aarch64_lenovo", + "android/abi_gki_aarch64_microsoft", "android/abi_gki_aarch64_moto", "android/abi_gki_aarch64_mtk", "android/abi_gki_aarch64_mtktv", @@ -34,6 +35,7 @@ _aarch64_additional_kmi_symbol_lists = [ "android/abi_gki_aarch64_rtktv", "android/abi_gki_aarch64_sony", "android/abi_gki_aarch64_sunxi", + "android/abi_gki_aarch64_transsion", "android/abi_gki_aarch64_tuxera", "android/abi_gki_aarch64_type_visibility", "android/abi_gki_aarch64_unisoc", diff --git a/Documentation/ABI/testing/sysfs-fs-f2fs b/Documentation/ABI/testing/sysfs-fs-f2fs index 9b583dd0298b..083ac2d63eef 100644 --- a/Documentation/ABI/testing/sysfs-fs-f2fs +++ b/Documentation/ABI/testing/sysfs-fs-f2fs @@ -580,3 +580,33 @@ Date: January 2022 Contact: "Jaegeuk Kim" Description: Controls max # of node block writes to be used for roll forward recovery. This can limit the roll forward recovery time. + +What: /sys/fs/f2fs//unusable_blocks_per_sec +Date: June 2022 +Contact: "Jaegeuk Kim" +Description: Shows the number of unusable blocks in a section which was defined by + the zone capacity reported by underlying zoned device. + +What: /sys/fs/f2fs//current_atomic_write +Date: July 2022 +Contact: "Daeho Jeong" +Description: Show the total current atomic write block count, which is not committed yet. + This is a read-only entry. + +What: /sys/fs/f2fs//peak_atomic_write +Date: July 2022 +Contact: "Daeho Jeong" +Description: Show the peak value of total current atomic write block count after boot. + If you write "0" here, you can initialize to "0". + +What: /sys/fs/f2fs//committed_atomic_block +Date: July 2022 +Contact: "Daeho Jeong" +Description: Show the accumulated total committed atomic write block count after boot. + If you write "0" here, you can initialize to "0". + +What: /sys/fs/f2fs//revoked_atomic_block +Date: July 2022 +Contact: "Daeho Jeong" +Description: Show the accumulated total revoked atomic write block count after boot. + If you write "0" here, you can initialize to "0". diff --git a/Documentation/admin-guide/device-mapper/dm-init.rst b/Documentation/admin-guide/device-mapper/dm-init.rst index e5242ff17e9b..981d6a907699 100644 --- a/Documentation/admin-guide/device-mapper/dm-init.rst +++ b/Documentation/admin-guide/device-mapper/dm-init.rst @@ -123,3 +123,11 @@ Other examples (per target): 0 1638400 verity 1 8:1 8:2 4096 4096 204800 1 sha256 fb1a5a0f00deb908d8b53cb270858975e76cf64105d412ce764225d53b8f3cfd 51934789604d1b92399c52e7cb149d1b3a1b74bbbcb103b2a0aaacbed5c08584 + +For setups using device-mapper on top of asynchronously probed block +devices (MMC, USB, ..), it may be necessary to tell dm-init to +explicitly wait for them to become available before setting up the +device-mapper tables. This can be done with the "dm-mod.waitfor=" +module parameter, which takes a list of devices to wait for:: + + dm-mod.waitfor=[,..,] diff --git a/Documentation/filesystems/autofs-mount-control.rst b/Documentation/filesystems/autofs-mount-control.rst index bf4b511cdbe8..b5a379d25c40 100644 --- a/Documentation/filesystems/autofs-mount-control.rst +++ b/Documentation/filesystems/autofs-mount-control.rst @@ -196,7 +196,7 @@ information and return operation results:: struct args_ismountpoint ismountpoint; }; - char path[0]; + char path[]; }; The ioctlfd field is a mount point file descriptor of an autofs mount diff --git a/Documentation/filesystems/autofs.rst b/Documentation/filesystems/autofs.rst index 681c6a492bc0..1b495768e7aa 100644 --- a/Documentation/filesystems/autofs.rst +++ b/Documentation/filesystems/autofs.rst @@ -467,7 +467,7 @@ Each ioctl is passed a pointer to an `autofs_dev_ioctl` structure:: struct args_ismountpoint ismountpoint; }; - char path[0]; + char path[]; }; For the **OPEN_MOUNT** and **IS_MOUNTPOINT** commands, the target diff --git a/Documentation/filesystems/directory-locking.rst b/Documentation/filesystems/directory-locking.rst index 504ba940c36c..dccd61c7c5c3 100644 --- a/Documentation/filesystems/directory-locking.rst +++ b/Documentation/filesystems/directory-locking.rst @@ -22,12 +22,11 @@ exclusive. 3) object removal. Locking rules: caller locks parent, finds victim, locks victim and calls the method. Locks are exclusive. -4) rename() that is _not_ cross-directory. Locking rules: caller locks -the parent and finds source and target. In case of exchange (with -RENAME_EXCHANGE in flags argument) lock both. In any case, -if the target already exists, lock it. If the source is a non-directory, -lock it. If we need to lock both, lock them in inode pointer order. -Then call the method. All locks are exclusive. +4) rename() that is _not_ cross-directory. Locking rules: caller locks the +parent and finds source and target. We lock both (provided they exist). If we +need to lock two inodes of different type (dir vs non-dir), we lock directory +first. If we need to lock two inodes of the same type, lock them in inode +pointer order. Then call the method. All locks are exclusive. NB: we might get away with locking the source (and target in exchange case) shared. @@ -44,15 +43,17 @@ All locks are exclusive. rules: * lock the filesystem - * lock parents in "ancestors first" order. + * lock parents in "ancestors first" order. If one is not ancestor of + the other, lock them in inode pointer order. * find source and target. * if old parent is equal to or is a descendent of target fail with -ENOTEMPTY * if new parent is equal to or is a descendent of source fail with -ELOOP - * If it's an exchange, lock both the source and the target. - * If the target exists, lock it. If the source is a non-directory, - lock it. If we need to lock both, do so in inode pointer order. + * Lock both the source and the target provided they exist. If we + need to lock two inodes of different type (dir vs non-dir), we lock + the directory first. If we need to lock two inodes of the same type, + lock them in inode pointer order. * call the method. All ->i_rwsem are taken exclusive. Again, we might get away with locking @@ -66,8 +67,9 @@ If no directory is its own ancestor, the scheme above is deadlock-free. Proof: - First of all, at any moment we have a partial ordering of the - objects - A < B iff A is an ancestor of B. + First of all, at any moment we have a linear ordering of the + objects - A < B iff (A is an ancestor of B) or (B is not an ancestor + of A and ptr(A) < ptr(B)). That ordering can change. However, the following is true: diff --git a/Documentation/networking/af_xdp.rst b/Documentation/networking/af_xdp.rst index 60b217b436be..5b77b9e5ac7e 100644 --- a/Documentation/networking/af_xdp.rst +++ b/Documentation/networking/af_xdp.rst @@ -433,6 +433,15 @@ start N bytes into the buffer leaving the first N bytes for the application to use. The final option is the flags field, but it will be dealt with in separate sections for each UMEM flag. +SO_BINDTODEVICE setsockopt +-------------------------- + +This is a generic SOL_SOCKET option that can be used to tie AF_XDP +socket to a particular network interface. It is useful when a socket +is created by a privileged process and passed to a non-privileged one. +Once the option is set, kernel will refuse attempts to bind that socket +to a different interface. Updating the value requires CAP_NET_RAW. + XDP_STATISTICS getsockopt ------------------------- diff --git a/Documentation/networking/ip-sysctl.rst b/Documentation/networking/ip-sysctl.rst index d06b40b4ebef..13effeb095a1 100644 --- a/Documentation/networking/ip-sysctl.rst +++ b/Documentation/networking/ip-sysctl.rst @@ -2083,6 +2083,17 @@ accept_ra_min_hop_limit - INTEGER Default: 1 +accept_ra_min_lft - INTEGER + Minimum acceptable lifetime value in Router Advertisement. + + RA sections with a lifetime less than this value shall be + ignored. Zero lifetimes stay unaffected. + + Possible values: 0-65535 + + Default: 0 + + accept_ra_pinfo - BOOLEAN Learn Prefix Information in Router Advertisement. diff --git a/Makefile b/Makefile index 46696f82fa55..bca6f57f1f2f 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ # SPDX-License-Identifier: GPL-2.0 VERSION = 5 PATCHLEVEL = 15 -SUBLEVEL = 119 +SUBLEVEL = 123 EXTRAVERSION = NAME = Trick or Treat diff --git a/android/ACK_SHA b/android/ACK_SHA index 7f742e6d2e2a..0cb5713a7393 100644 --- a/android/ACK_SHA +++ b/android/ACK_SHA @@ -1,2 +1,2 @@ -8a670a1c6394cd9153cb465966e86c2b57b78e1a -android13-5.15-2023-08_r2 +3ca6a2912c7e6f416930ce3dbb26381cb04ec8d5 +android13-5.15-2023-11_r1 diff --git a/android/abi_gki_aarch64 b/android/abi_gki_aarch64 index 28bcc4ea887a..fc7c5bbb2329 100644 --- a/android/abi_gki_aarch64 +++ b/android/abi_gki_aarch64 @@ -141,3 +141,6 @@ unregister_shrinker wait_on_page_bit __wake_up + +# preserved by --additions-only + android_kmalloc_64_create diff --git a/android/abi_gki_aarch64.xml b/android/abi_gki_aarch64.xml index c228d1dd504d..6eb27bda5f67 100644 --- a/android/abi_gki_aarch64.xml +++ b/android/abi_gki_aarch64.xml @@ -174,7 +174,9 @@ + + @@ -321,6 +323,7 @@ + @@ -488,11 +491,13 @@ + + @@ -544,6 +549,8 @@ + + @@ -572,13 +579,17 @@ + + + + @@ -606,6 +617,7 @@ + @@ -660,6 +672,7 @@ + @@ -708,6 +721,7 @@ + @@ -770,6 +784,7 @@ + @@ -805,6 +820,7 @@ + @@ -819,6 +835,7 @@ + @@ -1176,6 +1193,7 @@ + @@ -1359,6 +1377,8 @@ + + @@ -1745,6 +1765,7 @@ + @@ -2718,6 +2739,7 @@ + @@ -2802,6 +2824,7 @@ + @@ -2911,6 +2934,7 @@ + @@ -3379,6 +3403,7 @@ + @@ -3654,6 +3679,7 @@ + @@ -4067,6 +4093,7 @@ + @@ -4152,6 +4179,7 @@ + @@ -4326,6 +4354,7 @@ + @@ -4357,6 +4386,7 @@ + @@ -4494,6 +4524,7 @@ + @@ -4861,6 +4892,7 @@ + @@ -4872,6 +4904,7 @@ + @@ -6073,6 +6106,7 @@ + @@ -6182,13 +6216,17 @@ + + + + @@ -6553,6 +6591,7 @@ + @@ -6589,6 +6628,7 @@ + @@ -6650,10 +6690,13 @@ + + + @@ -6796,6 +6839,8 @@ + + @@ -6855,6 +6900,7 @@ + @@ -7129,11 +7175,13 @@ + + @@ -7185,6 +7233,8 @@ + + @@ -7213,13 +7263,17 @@ + + + + @@ -7247,6 +7301,7 @@ + @@ -7301,6 +7356,7 @@ + @@ -7349,6 +7405,7 @@ + @@ -7411,6 +7468,7 @@ + @@ -7446,6 +7504,7 @@ + @@ -7460,6 +7519,7 @@ + @@ -7494,6 +7554,7 @@ + @@ -7534,6 +7595,7 @@ + @@ -7606,6 +7668,7 @@ + @@ -7647,6 +7710,7 @@ + @@ -13545,48 +13609,48 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -27289,15 +27353,15 @@ - + - + - + - + @@ -31007,6 +31071,7 @@ + @@ -33600,6 +33665,11 @@ + + + + + @@ -41553,9 +41623,9 @@ - + - + @@ -42345,186 +42415,186 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -44894,24 +44964,24 @@ - + - + - + - + - + - + - + @@ -44987,6 +45057,7 @@ + @@ -48284,24 +48355,24 @@ - + - + - + - + - + - + - + @@ -50815,7 +50886,7 @@ - + @@ -52321,10 +52392,10 @@ - + - + @@ -56403,6 +56474,7 @@ + @@ -57134,6 +57206,7 @@ + @@ -58173,15 +58246,15 @@ - + - + - + - + @@ -59220,15 +59293,15 @@ - + - + - + - + @@ -60656,6 +60729,14 @@ + + + + + + + + @@ -62342,27 +62423,27 @@ - + - + - + - + - + - + - + - + @@ -66180,21 +66261,21 @@ - + - + - + - + - + - + @@ -68362,12 +68443,12 @@ - + - + - + @@ -79077,7 +79158,7 @@ - + @@ -79795,12 +79876,12 @@ - + - + - + @@ -81210,18 +81291,18 @@ - + - + - + - + - + @@ -84104,12 +84185,12 @@ - + - + - + @@ -84250,9 +84331,9 @@ - + - + @@ -86582,6 +86663,14 @@ + + + + + + + + @@ -87232,12 +87321,12 @@ - + - + - + @@ -90106,73 +90195,73 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -92791,114 +92880,114 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -94201,6 +94290,7 @@ + @@ -96513,39 +96603,39 @@ - + - + - + - + - + - + - + - + - + - + - + - + @@ -99161,6 +99251,11 @@ + + + + + @@ -103443,6 +103538,7 @@ + @@ -116555,51 +116651,51 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -118648,6 +118744,7 @@ + @@ -120391,21 +120488,21 @@ - + - + - + - + - + - + @@ -123397,15 +123494,15 @@ - + - + - + - + @@ -125793,33 +125890,33 @@ - + - + - + - + - + - + - + - + - + - + @@ -127446,7 +127543,7 @@ - + @@ -127573,11 +127670,11 @@ - - - - - + + + + + @@ -127598,8 +127695,8 @@ - - + + @@ -128229,8 +128326,8 @@ - - + + @@ -128364,9 +128461,9 @@ - - - + + + @@ -128416,9 +128513,9 @@ - - - + + + @@ -128426,15 +128523,15 @@ - - - + + + - - - - + + + + @@ -128493,12 +128590,25 @@ + + + + + + + + + + + + + @@ -128757,10 +128867,10 @@ - - - - + + + + @@ -128882,10 +128992,10 @@ - - - - + + + + @@ -128953,11 +129063,11 @@ - - - - - + + + + + @@ -128979,13 +129089,13 @@ - - - - - - - + + + + + + + @@ -129014,9 +129124,9 @@ - - - + + + @@ -129053,9 +129163,9 @@ - - - + + + @@ -129373,6 +129483,12 @@ + + + + + + @@ -129400,8 +129516,8 @@ - - + + @@ -129712,9 +129828,9 @@ - - - + + + @@ -130070,9 +130186,9 @@ - - - + + + @@ -130250,9 +130366,9 @@ - - - + + + @@ -130262,14 +130378,14 @@ - - - + + + - - - + + + @@ -130363,10 +130479,10 @@ - - - - + + + + @@ -130408,11 +130524,17 @@ - - - - - + + + + + + + + + + + @@ -130439,40 +130561,48 @@ - - - - + + + + - - - + + + - - - - - - - + + + + + + - - - - - - - + + + + + + + - - - - - + + + + + + + + + + + + + + @@ -130497,9 +130627,9 @@ - - - + + + @@ -130730,11 +130860,11 @@ - - - - - + + + + + @@ -130793,28 +130923,43 @@ - - - - - + + + + + - - - - + + + - - - - + + + + + + + + - - - + + + + + + + + + + + + + + + @@ -130875,11 +131020,11 @@ - - - - - + + + + + @@ -130894,10 +131039,10 @@ - - - - + + + + @@ -130927,12 +131072,12 @@ - - - - - - + + + + + + @@ -130942,9 +131087,9 @@ - - - + + + @@ -130953,14 +131098,14 @@ - - - - - - - - + + + + + + + + @@ -130985,6 +131130,13 @@ + + + + + + + @@ -130996,9 +131148,14 @@ - - - + + + + + + + + @@ -131006,14 +131163,20 @@ - - - - - - - - + + + + + + + + + + + + + + @@ -131021,12 +131184,18 @@ - - - - - - + + + + + + + + + + + + @@ -131196,6 +131365,13 @@ + + + + + + + @@ -131208,18 +131384,18 @@ - - - - - + + + + + - - - - - + + + + + @@ -131229,11 +131405,11 @@ - - - - - + + + + + @@ -131248,18 +131424,18 @@ - - - - - - + + + + + + - - - - + + + + @@ -131268,16 +131444,16 @@ - - - - + + + + - - - - + + + + @@ -131298,47 +131474,47 @@ - - - + + + - - - + + + - - - - + + + + - - - - + + + + - - - + + + - - - + + + - - - + + + - - - - + + + + @@ -131474,17 +131650,17 @@ - - - - + + + + - - - - - + + + + + @@ -131495,10 +131671,10 @@ - - - - + + + + @@ -131517,10 +131693,16 @@ - - - - + + + + + + + + + + @@ -131528,9 +131710,9 @@ - - - + + + @@ -131570,10 +131752,10 @@ - - - - + + + + @@ -131606,37 +131788,37 @@ - - - - - - - - + + + + + + + + - - - - - - + + + + + + - - - - - + + + + + - - - - - - + + + + + + @@ -131659,10 +131841,10 @@ - - - - + + + + @@ -131736,10 +131918,10 @@ - - - - + + + + @@ -131805,6 +131987,11 @@ + + + + + @@ -131826,26 +132013,26 @@ - - - - - - - - - + + + + + + + + + - - - + + + - - - - + + + + @@ -131873,11 +132060,11 @@ - - - - - + + + + + @@ -131897,18 +132084,18 @@ - - - - - - - + + + + + + + - - - + + + @@ -131932,11 +132119,11 @@ - - - - - + + + + + @@ -131956,12 +132143,12 @@ - - - - - - + + + + + + @@ -131970,13 +132157,13 @@ - - - - - - - + + + + + + + @@ -132150,20 +132337,20 @@ - - - - - + + + + + - - - - - - - + + + + + + + @@ -132171,21 +132358,21 @@ - - - - + + + + - - - + + + - - - - + + + + @@ -132201,6 +132388,12 @@ + + + + + + @@ -132356,15 +132549,15 @@ - - - - + + + + - - - + + + @@ -132410,6 +132603,14 @@ + + + + + + + + @@ -132494,6 +132695,14 @@ + + + + + + + + @@ -132669,7 +132878,7 @@ - + @@ -132724,7 +132933,7 @@ - + @@ -132752,10 +132961,10 @@ - + - - + + @@ -132771,26 +132980,28 @@ - + - + + - - - - - + + + + + + - + @@ -132824,7 +133035,7 @@ - + @@ -132834,10 +133045,12 @@ - - - - + + + + + + @@ -132847,29 +133060,33 @@ - + - + - + - + - + + - + + - + + - + + @@ -132897,29 +133114,30 @@ + - - + + - + - - + + - - + + - - - - - - - - + + + + + + + + @@ -132943,37 +133161,38 @@ - - + + - + - + + - + - + - - - - + + + + - + @@ -132987,7 +133206,7 @@ - + @@ -132999,33 +133218,34 @@ + - - - + + + - + - - + + - + - + - + @@ -133053,14 +133273,15 @@ - - + + - - - + + + + @@ -133087,8 +133308,8 @@ - - + + @@ -133096,6 +133317,7 @@ + @@ -133110,6 +133332,7 @@ + @@ -133612,7 +133835,7 @@ - + @@ -133623,12 +133846,12 @@ - - - - - - + + + + + + @@ -133708,27 +133931,27 @@ - - - - - - - - - - - - + + + + + + + + + + + + - - - + + + @@ -133834,11 +134057,11 @@ - - - - - + + + + + @@ -133875,27 +134098,27 @@ - - - + + + - - - - - - + + + + + + - - - - + + + + @@ -134040,10 +134263,11 @@ - - + + + @@ -134104,7 +134328,7 @@ - + @@ -134919,6 +135143,11 @@ + + + + + @@ -134967,15 +135196,15 @@ - - - + + + - - - - + + + + @@ -135129,8 +135358,8 @@ - - + + @@ -135228,11 +135457,11 @@ - - - - - + + + + + @@ -135391,16 +135620,16 @@ - - + + - - + + - - + + @@ -135968,6 +136197,16 @@ + + + + + + + + + + @@ -136062,19 +136301,19 @@ - - - + + + - - - - + + + + @@ -136091,9 +136330,9 @@ - - - + + + @@ -137101,14 +137340,14 @@ - - + + - + @@ -137420,11 +137659,11 @@ - - - - - + + + + + @@ -137449,8 +137688,8 @@ - - + + @@ -137473,8 +137712,8 @@ - - + + @@ -137627,28 +137866,28 @@ - - - - + + + + - - - - - - + + + + + + - - - + + + - - - + + + @@ -137693,8 +137932,8 @@ - - + + @@ -137755,42 +137994,42 @@ - - + + - - + + - - + + - - + + - - + + - - + + - - - + + + - - + + - - - + + + @@ -137798,9 +138037,9 @@ - - - + + + @@ -137808,10 +138047,10 @@ - - - - + + + + @@ -137819,10 +138058,10 @@ - - - - + + + + @@ -137922,6 +138161,10 @@ + + + + @@ -138960,14 +139203,14 @@ - - - - + + + + - - + + @@ -139092,21 +139335,21 @@ - - - + + + - - - - + + + + - - - - + + + + @@ -139388,6 +139631,7 @@ + @@ -140075,8 +140319,8 @@ - - + + @@ -140091,7 +140335,7 @@ - + @@ -140231,16 +140475,16 @@ - - - - + + + + - - - - + + + + @@ -140248,9 +140492,9 @@ - - - + + + @@ -140261,11 +140505,11 @@ - - - - - + + + + + @@ -140277,39 +140521,39 @@ - - - - - + + + + + - - - - - + + + + + - - - + + + - - - - + + + + - - - - + + + + @@ -140322,8 +140566,8 @@ - - + + @@ -140382,14 +140626,14 @@ - - - + + + - - - + + + @@ -140407,48 +140651,48 @@ - - + + - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + @@ -140460,13 +140704,13 @@ - - - - - - - + + + + + + + @@ -140497,52 +140741,52 @@ - - - + + + - - - - + + + + - - + + - - - + + + - - + + - - - + + + - - - + + + - - - - + + + + - - + + - - + + @@ -140586,31 +140830,31 @@ - - - + + + - - - + + + - - - + + + - - + + - - - - - - + + + + + + @@ -140626,81 +140870,81 @@ - - - + + + - - - + + + - - - + + + - - - + + + - - + + - - + + - - - + + + - - - + + + - - - - - - - - - - - - - + + + + + + + + + + + + + - - + + - - - - + + + + - - - + + + - - - + + + - - + + @@ -140708,20 +140952,20 @@ - - - + + + - - + + - - - - - + + + + + @@ -140754,16 +140998,16 @@ - - + + - - + + - - + + @@ -140867,18 +141111,18 @@ - - + + - - + + - - - - + + + + @@ -142724,9 +142968,9 @@ - - - + + + @@ -143102,6 +143346,12 @@ + + + + + + @@ -143252,85 +143502,85 @@ - - + + - - + + - - - + + + - - + + - - + + - - - - - + + + + + - - - - + + + + - - - + + + - - - - + + + + - - - - - + + + + + - - - - + + + + - - - - + + + + - - - - + + + + - - - + + + - - - - + + + + @@ -143384,8 +143634,8 @@ - - + + @@ -143399,12 +143649,12 @@ - - + + - - + + @@ -143422,8 +143672,8 @@ - - + + @@ -143446,10 +143696,10 @@ - - - - + + + + @@ -143484,11 +143734,11 @@ - - - - - + + + + + @@ -143522,10 +143772,10 @@ - - - - + + + + @@ -143550,6 +143800,11 @@ + + + + + @@ -143572,26 +143827,26 @@ - - + + - - + + - - + + - - + + - - - - + + + + @@ -143629,9 +143884,9 @@ - - - + + + @@ -143647,14 +143902,14 @@ - - - + + + - - - + + + @@ -143990,8 +144245,8 @@ - - + + @@ -144109,6 +144364,11 @@ + + + + + @@ -144310,9 +144570,9 @@ - - - + + + @@ -144336,9 +144596,9 @@ - - - + + + @@ -144346,9 +144606,9 @@ - - - + + + @@ -144359,9 +144619,9 @@ - - - + + + @@ -144396,10 +144656,10 @@ - - - - + + + + @@ -144740,15 +145000,15 @@ - - - + + + - - - - + + + + @@ -144874,8 +145134,8 @@ - - + + @@ -145209,10 +145469,10 @@ - - - - + + + + @@ -146016,13 +146276,13 @@ - - - - - - - + + + + + + + @@ -146133,26 +146393,26 @@ - - - - - - + + + + + + - - - + + + - - + + @@ -146362,16 +146622,16 @@ - - - + + + - - - - - + + + + + @@ -146500,17 +146760,17 @@ - + - - - - + + + + @@ -146533,8 +146793,13 @@ - - + + + + + + + @@ -146545,15 +146810,15 @@ - - - - - + + + + + - - + + @@ -146561,13 +146826,13 @@ - - + + - - - + + + @@ -146575,10 +146840,10 @@ - - - - + + + + @@ -146732,8 +146997,8 @@ - - + + @@ -146785,11 +147050,11 @@ - + - - + + @@ -147186,10 +147451,10 @@ - - - - + + + + @@ -147217,8 +147482,8 @@ - - + + @@ -147236,19 +147501,19 @@ - - - - - + + + + + - - - - - - + + + + + + @@ -147691,8 +147956,8 @@ - - + + @@ -147721,9 +147986,9 @@ - - - + + + @@ -147834,7 +148099,7 @@ - + @@ -147879,9 +148144,9 @@ - - - + + + @@ -147889,10 +148154,10 @@ - - - - + + + + @@ -147983,6 +148248,10 @@ + + + + @@ -148001,10 +148270,10 @@ - - - - + + + + @@ -148206,7 +148475,7 @@ - + @@ -148359,101 +148628,101 @@ - - - + + + - - - + + + - + - - + + - - + + - - - - - + + + + + - - - + + + - - + + - - + + - - + + - - + + - - + + - - - - + + + + - - + + - + - - - - + + + + - - - + + + - + - + - - + + - - + + - - + + @@ -148532,8 +148801,8 @@ - - + + @@ -148766,9 +149035,9 @@ - - - + + + @@ -149172,15 +149441,15 @@ - - + + - - - - - + + + + + @@ -149226,7 +149495,7 @@ - + @@ -149343,31 +149612,31 @@ - - - + + + - - - - - + + + + + - - - + + + - - - - - - - - + + + + + + + + @@ -149850,11 +150119,11 @@ - - - - - + + + + + @@ -150049,6 +150318,15 @@ + + + + + + + + + @@ -150285,11 +150563,11 @@ - - - - - + + + + + @@ -150300,8 +150578,8 @@ - - + + @@ -150309,8 +150587,8 @@ - - + + @@ -150320,8 +150598,8 @@ - - + + @@ -150467,7 +150745,7 @@ - + @@ -150493,13 +150771,16 @@ - + + + + @@ -150619,48 +150900,48 @@ - - - - + + + + - - - - + + + + - - + + - - - + + + - - - + + + - - + + - - + + - - - + + + - - - + + + @@ -150668,9 +150949,9 @@ - - - + + + @@ -150678,14 +150959,14 @@ - - - + + + - - - + + + @@ -151398,6 +151679,12 @@ + + + + + + @@ -151508,21 +151795,21 @@ - - - - - + + + + + - - + + - - - - + + + + @@ -151537,6 +151824,7 @@ + @@ -151562,6 +151850,13 @@ + + + + + + + @@ -151570,15 +151865,15 @@ - - - - + + + + - - - + + + @@ -151594,24 +151889,24 @@ - - - - - - - - + + + + + + + + - - - - - - - - + + + + + + + + @@ -151855,9 +152150,9 @@ - - - + + + @@ -152282,6 +152577,11 @@ + + + + + @@ -152357,8 +152657,8 @@ - - + + @@ -152451,8 +152751,8 @@ - - + + @@ -152482,8 +152782,8 @@ - - + + @@ -152501,70 +152801,70 @@ - - + + - - - - - - + + + + + + - - + + - - + + - - - + + + - - - - - + + + + + - - - - + + + + - - + + - - + + - - - - + + + + - - - - + + + + - - + + @@ -152573,15 +152873,15 @@ - - - - - - - - - + + + + + + + + + @@ -153076,8 +153376,8 @@ - - + + @@ -153901,10 +154201,10 @@ - + - + @@ -154055,13 +154355,13 @@ - - - + + + - - + + @@ -154153,6 +154453,12 @@ + + + + + + @@ -154200,6 +154506,10 @@ + + + + @@ -154265,17 +154575,17 @@ - - - - - + + + + + - - - - + + + + @@ -154562,37 +154872,37 @@ - - + + - - + + - - + + - - + + - - + + - - - - - + + + + + - - - - + + + + @@ -154842,8 +155152,8 @@ - - + + @@ -154852,18 +155162,18 @@ - - - - - + + + + + - - - - - + + + + + @@ -154881,30 +155191,30 @@ - - - + + + - - - - - - - + + + + + + + - - + + - - + + @@ -154924,63 +155234,63 @@ - - - - + + + + - - - - + + + + - - - - - + + + + + - - - - - + + + + + - - - - - + + + + + - - - - - + + + + + - - - - - + + + + + - - - - + + + + - - - - + + + + @@ -154988,14 +155298,14 @@ - - - - - - - - + + + + + + + + @@ -155004,34 +155314,34 @@ - - - + + + - - - + + + - - - + + + - - - + + + - - - - + + + + - - + + @@ -155039,85 +155349,85 @@ - - + + - - + + - - + + - - - + + + - - + + - - + + - - + + - - + + - - - + + + - - + + - - + + - - + + - - - - + + + + - - - + + + @@ -155159,24 +155469,24 @@ - - - - + + + + - - + + - - - + + + - - - + + + @@ -155184,10 +155494,10 @@ - - - - + + + + @@ -155196,14 +155506,14 @@ - - - + + + - - - + + + @@ -155211,10 +155521,10 @@ - - - - + + + + @@ -155222,29 +155532,29 @@ - - - - + + + + - - - - + + + + - - + + - - + + - - - + + + @@ -155280,8 +155590,8 @@ - - + + @@ -155293,8 +155603,8 @@ - - + + @@ -155350,41 +155660,41 @@ - - - - + + + + - - - - + + + + - - - - - - + + + + + + - - - - - - - - + + + + + + + + - - - - - + + + + + @@ -155524,7 +155834,8 @@ - + + @@ -156003,43 +156314,43 @@ - - + + - - + + - - - + + + - - - + + + - - - + + + - - - - + + + + - - - - + + + + - - + + @@ -156077,7 +156388,7 @@ - + @@ -156620,23 +156931,23 @@ - - - - + + + + - - - - + + + + - - - - - + + + + + @@ -156915,9 +157226,9 @@ - - - + + + @@ -157122,21 +157433,21 @@ - + - - + + - - - - + + + + @@ -157295,8 +157606,8 @@ - - + + @@ -157306,9 +157617,9 @@ - - - + + + @@ -157349,10 +157660,10 @@ - - - - + + + + @@ -157369,9 +157680,9 @@ - - - + + + @@ -157379,16 +157690,16 @@ - - - - + + + + - - - - + + + + @@ -157437,9 +157748,9 @@ - - - + + + @@ -157460,18 +157771,18 @@ - - - - - + + + + + - - - - - + + + + + @@ -157479,9 +157790,9 @@ - - - + + + @@ -157489,8 +157800,8 @@ - - + + @@ -158865,20 +159176,20 @@ - - - - - - - + + + + + + + - - - - - + + + + + @@ -158902,88 +159213,88 @@ - - - - - + + + + + - - - + + + - - - - - + + + + + - - - - + + + + - - - - - + + + + + - - - - + + + + - - - + + + - - - - + + + + - - - - - + + + + + - - - - + + + + - - - - - - + + + + + + - - - + + + - - - + + + @@ -159021,11 +159332,11 @@ - - - - - + + + + + @@ -159189,9 +159500,9 @@ - - - + + + @@ -159870,8 +160181,8 @@ - - + + @@ -160173,9 +160484,9 @@ - - - + + + @@ -160189,8 +160500,8 @@ - - + + @@ -160214,12 +160525,12 @@ - - + + - - + + @@ -160425,6 +160736,10 @@ + + + + @@ -160432,9 +160747,9 @@ - - - + + + @@ -160981,6 +161296,10 @@ + + + + @@ -160992,6 +161311,10 @@ + + + + @@ -161015,6 +161338,16 @@ + + + + + + + + + + @@ -161237,26 +161570,26 @@ - - - + + + - - - + + + - - + + - - + + - - + + @@ -161266,13 +161599,13 @@ - - - + + + - - + + @@ -161288,9 +161621,9 @@ - - - + + + @@ -161316,8 +161649,8 @@ - - + + @@ -161353,9 +161686,9 @@ - - - + + + @@ -161368,9 +161701,9 @@ - - - + + + @@ -161476,48 +161809,48 @@ - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + @@ -161564,11 +161897,11 @@ - - - - - + + + + + @@ -162817,6 +163150,12 @@ + + + + + + @@ -163022,6 +163361,13 @@ + + + + + + + @@ -163344,6 +163690,12 @@ + + + + + + @@ -163366,6 +163718,18 @@ + + + + + + + + + + + + @@ -164121,6 +164485,14 @@ + + + + + + + + @@ -164435,6 +164807,11 @@ + + + + + @@ -164516,20 +164893,20 @@ - - + + - - - - + + + + - - - - + + + + @@ -164792,10 +165169,10 @@ - - - - + + + + @@ -164811,15 +165188,15 @@ - - - + + + - - - - + + + + @@ -164832,13 +165209,13 @@ - - - + + + - - + + @@ -164847,9 +165224,9 @@ - - - + + + @@ -164860,14 +165237,14 @@ - - - + + + - - - + + + @@ -164888,13 +165265,13 @@ - - + + - - - + + + @@ -165020,7 +165397,7 @@ - + diff --git a/android/abi_gki_aarch64_amlogic b/android/abi_gki_aarch64_amlogic index a11cb15ecd1d..e7e892e84c71 100644 --- a/android/abi_gki_aarch64_amlogic +++ b/android/abi_gki_aarch64_amlogic @@ -162,6 +162,8 @@ clk_register clk_register_composite clk_round_rate + clk_set_max_rate + clk_set_min_rate clk_set_parent clk_set_rate clk_unprepare @@ -469,6 +471,7 @@ dma_heap_get_dev dma_heap_get_drvdata dma_heap_get_name + dma_heap_put d_make_root dmam_alloc_attrs dma_map_page_attrs @@ -533,6 +536,7 @@ drm_atomic_helper_resume drm_atomic_helper_set_config drm_atomic_helper_setup_commit + drm_atomic_helper_shutdown drm_atomic_helper_suspend drm_atomic_helper_swap_state drm_atomic_helper_update_plane @@ -644,6 +648,8 @@ drm_poll drm_prime_gem_destroy drm_printf + __drm_printfn_coredump + __drm_printfn_seq_file drm_property_add_enum drm_property_blob_get drm_property_blob_put @@ -654,9 +660,12 @@ drm_property_destroy drm_property_lookup_blob drm_property_replace_blob + __drm_puts_coredump + __drm_puts_seq_file drm_read drm_release drm_self_refresh_helper_update_avg_times + drm_state_dump drm_universal_plane_init drm_vblank_init drm_writeback_connector_init @@ -797,6 +806,7 @@ get_cpu_iowait_time_us get_device get_device_system_crosststamp + get_each_dmabuf __get_free_pages get_kernel_pages get_net_ns_by_fd @@ -1020,6 +1030,7 @@ kill_block_super kill_fasync kill_pid + kimage_vaddr kimage_voffset __kmalloc kmalloc_caches @@ -1079,6 +1090,7 @@ led_trigger_unregister_simple __list_add_valid __list_del_entry_valid + list_sort ll_rw_block load_nls load_nls_default @@ -1302,6 +1314,7 @@ of_prop_next_u32 of_pwm_xlate_with_flags of_reserved_mem_device_init_by_idx + of_reserved_mem_device_init_by_name of_reserved_mem_device_release of_reserved_mem_lookup of_reset_control_array_get @@ -1327,6 +1340,7 @@ panic panic_notifier_list param_array_ops + param_get_bool param_get_charp param_get_hexint param_get_int @@ -1897,6 +1911,7 @@ syscon_node_to_regmap syscon_regmap_lookup_by_phandle sysctl_sched_latency + sysfs_create_bin_file sysfs_create_file_ns sysfs_create_group sysfs_create_link @@ -1921,6 +1936,7 @@ __tasklet_schedule tasklet_setup tasklet_unlock_wait + tasklist_lock task_may_not_preempt thermal_cooling_device_unregister thermal_of_cooling_device_register @@ -1943,6 +1959,7 @@ __traceiter_android_rvh_check_preempt_tick __traceiter_android_rvh_check_preempt_wakeup __traceiter_android_rvh_do_sea + __traceiter_android_rvh_do_undefinstr __traceiter_android_rvh_enqueue_task __traceiter_android_rvh_gic_v3_set_affinity __traceiter_android_rvh_iommu_setup_dma_ops @@ -1952,6 +1969,8 @@ __traceiter_android_rvh_schedule __traceiter_android_rvh_select_task_rq_rt __traceiter_android_rvh_tick_entry + __traceiter_android_vh_alloc_pages_entry + __traceiter_android_vh_cma_alloc_bypass __traceiter_android_vh_cma_drain_all_pages_bypass __traceiter_android_vh_cpu_idle_enter __traceiter_android_vh_cpu_idle_exit @@ -1959,17 +1978,26 @@ __traceiter_android_vh_dump_throttled_rt_tasks __traceiter_android_vh_ftrace_format_check __traceiter_android_vh_iommu_iovad_free_iova + __traceiter_android_vh_ipi_stop + __traceiter_android_vh_isolate_freepages __traceiter_android_vh_mem_cgroup_alloc __traceiter_android_vh_mmc_sd_update_cmdline_timing __traceiter_android_vh_mmc_sd_update_dataline_timing __traceiter_android_vh_rmqueue __traceiter_android_vh_sched_show_task + __traceiter_android_vh_set_module_permit_after_init + __traceiter_android_vh_xhci_urb_suitable_bypass __traceiter_gpu_mem_total __traceiter_irq_handler_entry __traceiter_irq_handler_exit __traceiter_mmap_lock_acquire_returned __traceiter_mmap_lock_released __traceiter_mmap_lock_start_locking + __traceiter_mm_page_alloc + __traceiter_rwmmio_post_read + __traceiter_rwmmio_post_write + __traceiter_rwmmio_read + __traceiter_rwmmio_write __traceiter_sched_switch __traceiter_xdp_exception trace_output_call @@ -1977,6 +2005,7 @@ __tracepoint_android_rvh_check_preempt_tick __tracepoint_android_rvh_check_preempt_wakeup __tracepoint_android_rvh_do_sea + __tracepoint_android_rvh_do_undefinstr __tracepoint_android_rvh_enqueue_task __tracepoint_android_rvh_gic_v3_set_affinity __tracepoint_android_rvh_iommu_setup_dma_ops @@ -1986,6 +2015,8 @@ __tracepoint_android_rvh_schedule __tracepoint_android_rvh_select_task_rq_rt __tracepoint_android_rvh_tick_entry + __tracepoint_android_vh_alloc_pages_entry + __tracepoint_android_vh_cma_alloc_bypass __tracepoint_android_vh_cma_drain_all_pages_bypass __tracepoint_android_vh_cpu_idle_enter __tracepoint_android_vh_cpu_idle_exit @@ -1993,19 +2024,28 @@ __tracepoint_android_vh_dump_throttled_rt_tasks __tracepoint_android_vh_ftrace_format_check __tracepoint_android_vh_iommu_iovad_free_iova + __tracepoint_android_vh_ipi_stop + __tracepoint_android_vh_isolate_freepages __tracepoint_android_vh_mem_cgroup_alloc __tracepoint_android_vh_mmc_sd_update_cmdline_timing __tracepoint_android_vh_mmc_sd_update_dataline_timing __tracepoint_android_vh_rmqueue __tracepoint_android_vh_sched_show_task + __tracepoint_android_vh_set_module_permit_after_init + __tracepoint_android_vh_xhci_urb_suitable_bypass __tracepoint_gpu_mem_total __tracepoint_irq_handler_entry __tracepoint_irq_handler_exit __tracepoint_mmap_lock_acquire_returned __tracepoint_mmap_lock_released __tracepoint_mmap_lock_start_locking + __tracepoint_mm_page_alloc tracepoint_probe_register tracepoint_probe_unregister + __tracepoint_rwmmio_post_read + __tracepoint_rwmmio_post_write + __tracepoint_rwmmio_read + __tracepoint_rwmmio_write __tracepoint_sched_switch __tracepoint_xdp_exception trace_print_array_seq diff --git a/android/abi_gki_aarch64_microsoft b/android/abi_gki_aarch64_microsoft new file mode 100644 index 000000000000..2caeb242ca97 --- /dev/null +++ b/android/abi_gki_aarch64_microsoft @@ -0,0 +1,10 @@ +[abi_symbol_list] +# required by igb.ko + dev_trans_start + eth_get_headlen + flow_rule_match_eth_addrs + __hw_addr_sync_dev + __hw_addr_unsync_dev + ndo_dflt_fdb_add + pci_sriov_set_totalvfs + ptp_find_pin diff --git a/android/abi_gki_aarch64_mtk b/android/abi_gki_aarch64_mtk index 7f5a50646d02..e9c9d9d69661 100644 --- a/android/abi_gki_aarch64_mtk +++ b/android/abi_gki_aarch64_mtk @@ -794,6 +794,7 @@ fwnode_property_read_string fwnode_property_read_u32_array fwnode_property_read_u64_array + fwnode_typec_mux_get g_audio_cleanup g_audio_setup gcd @@ -2191,10 +2192,13 @@ tty_unregister_ldisc tty_write_room typec_mux_get_drvdata + typec_mux_put typec_mux_register typec_mux_set typec_mux_unregister typec_partner_set_identity + typec_partner_set_pd_revision + typec_partner_set_svdm_version typec_register_partner typec_register_port typec_set_data_role diff --git a/android/abi_gki_aarch64_oplus b/android/abi_gki_aarch64_oplus index a24c4a3bfeb0..45fc3bd5c283 100644 --- a/android/abi_gki_aarch64_oplus +++ b/android/abi_gki_aarch64_oplus @@ -156,6 +156,7 @@ kern_unmount kfree kfree_skb + kick_process kill_anon_super kmalloc_caches kmem_cache_alloc @@ -230,12 +231,14 @@ nla_reserve nonseekable_open nr_cpu_ids + nr_running __num_online_cpus of_css page_endio __page_file_index __page_mapcount page_mapping + page_referenced page_to_lruvec param_ops_uint __per_cpu_offset @@ -286,6 +289,7 @@ register_sysctl_table register_tcf_proto_ops remove_proc_subtree + root_mem_cgroup rtc_read_alarm __rtnl_link_unregister sched_clock @@ -409,9 +413,12 @@ __traceiter_android_vh_dm_bufio_shrink_scan_bypass __traceiter_android_vh_drain_all_pages_bypass __traceiter_android_vh_dup_task_struct + __traceiter_android_vh_exit_check __traceiter_android_vh_exit_mm __traceiter_android_vh_exit_signal + __traceiter_android_vh_exit_signal_whether_wake __traceiter_android_vh_free_task + __traceiter_android_vh_freeze_whether_wake __traceiter_android_vh_futex_sleep_start __traceiter_android_vh_futex_wait_end __traceiter_android_vh_futex_wait_start @@ -427,6 +434,7 @@ __traceiter_android_vh_madvise_cold_or_pageout_abort __traceiter_android_vh_mark_page_accessed __traceiter_android_vh_mem_cgroup_alloc + __traceiter_android_vh_adjust_alloc_flags __traceiter_android_vh_mem_cgroup_css_offline __traceiter_android_vh_mem_cgroup_css_online __traceiter_android_vh_mem_cgroup_free @@ -446,6 +454,7 @@ __traceiter_android_vh_print_slabinfo_header __traceiter_android_vh_record_mutex_lock_starttime __traceiter_android_vh_record_pcpu_rwsem_starttime + __traceiter_android_vh_percpu_rwsem_wq_add __traceiter_android_vh_record_rtmutex_lock_starttime __traceiter_android_vh_record_rwsem_lock_starttime __traceiter_android_vh_rmqueue @@ -533,9 +542,12 @@ __tracepoint_android_vh_do_traversal_lruvec __tracepoint_android_vh_drain_all_pages_bypass __tracepoint_android_vh_dup_task_struct + __tracepoint_android_vh_exit_check __tracepoint_android_vh_exit_mm __tracepoint_android_vh_exit_signal + __tracepoint_android_vh_exit_signal_whether_wake __tracepoint_android_vh_free_task + __tracepoint_android_vh_freeze_whether_wake __tracepoint_android_vh_futex_sleep_start __tracepoint_android_vh_futex_wait_end __tracepoint_android_vh_futex_wait_start @@ -551,6 +563,7 @@ __tracepoint_android_vh_madvise_cold_or_pageout_abort __tracepoint_android_vh_mark_page_accessed __tracepoint_android_vh_mem_cgroup_alloc + __tracepoint_android_vh_adjust_alloc_flags __tracepoint_android_vh_mem_cgroup_css_offline __tracepoint_android_vh_mem_cgroup_css_online __tracepoint_android_vh_mem_cgroup_free @@ -570,6 +583,7 @@ __tracepoint_android_vh_print_slabinfo_header __tracepoint_android_vh_record_mutex_lock_starttime __tracepoint_android_vh_record_pcpu_rwsem_starttime + __tracepoint_android_vh_percpu_rwsem_wq_add __tracepoint_android_vh_record_rtmutex_lock_starttime __tracepoint_android_vh_record_rwsem_lock_starttime __tracepoint_android_vh_rmqueue @@ -629,6 +643,7 @@ wait_for_completion_io_timeout __wake_up wake_up_process + wake_up_state wq_worker_comm is_ashmem_file zero_pfn diff --git a/android/abi_gki_aarch64_pixel b/android/abi_gki_aarch64_pixel index 06b013e7e350..c201ea67a65a 100644 --- a/android/abi_gki_aarch64_pixel +++ b/android/abi_gki_aarch64_pixel @@ -1919,6 +1919,7 @@ __traceiter_android_vh_cpu_idle_enter __traceiter_android_vh_cpu_idle_exit __traceiter_android_vh_dup_task_struct + __traceiter_android_vh_enable_thermal_genl_check __traceiter_android_vh_ipi_stop __traceiter_android_vh_scheduler_tick __traceiter_android_vh_setscheduler_uclamp @@ -1975,6 +1976,7 @@ __tracepoint_android_vh_cpu_idle_enter __tracepoint_android_vh_cpu_idle_exit __tracepoint_android_vh_dup_task_struct + __tracepoint_android_vh_enable_thermal_genl_check __tracepoint_android_vh_ipi_stop __tracepoint_android_vh_scheduler_tick __tracepoint_android_vh_setscheduler_uclamp diff --git a/android/abi_gki_aarch64_qcom b/android/abi_gki_aarch64_qcom index b97eb4ffa7cc..80c9e4ec27e9 100644 --- a/android/abi_gki_aarch64_qcom +++ b/android/abi_gki_aarch64_qcom @@ -103,6 +103,7 @@ blk_get_request blk_ksm_get_slot_idx blk_ksm_register + blk_ksm_reprogram_all_keys blk_mark_disk_dead blk_mq_alloc_request blk_mq_alloc_request_hctx @@ -374,6 +375,7 @@ dev_get_by_name dev_get_by_name_rcu dev_get_regmap + dev_get_tstats64 device_add device_add_disk device_add_groups @@ -697,6 +699,7 @@ ethnl_cable_test_pulse ethnl_cable_test_result ethnl_cable_test_step + eth_platform_get_mac_address ethtool_convert_legacy_u32_to_link_mode ethtool_convert_link_mode_to_legacy_u32 eventfd_ctx_fdget @@ -764,6 +767,7 @@ generic_handle_domain_irq generic_handle_irq generic_iommu_put_resv_regions + generic_mii_ioctl geni_icc_disable geni_icc_enable geni_icc_get @@ -1295,6 +1299,8 @@ migrate_pages migrate_swap __migrate_task + mii_check_media + mii_ethtool_gset mipi_dsi_dcs_set_tear_off misc_deregister misc_register @@ -1461,6 +1467,7 @@ page_endio page_is_ram page_mapping + page_owner_inited page_pool_alloc_pages page_pool_create page_pool_destroy @@ -1991,6 +1998,7 @@ set_next_entity set_normalized_timespec64 __SetPageMovable + __set_page_owner set_task_cpu set_user_nice sg_alloc_table @@ -2495,6 +2503,7 @@ typec_set_pwr_opmode typec_set_pwr_role typec_unregister_partner + typec_get_orientation uart_add_one_port uart_get_baud_rate uart_insert_char @@ -2569,6 +2578,8 @@ usb_alloc_coherent usb_alloc_dev usb_assign_descriptors + usb_autopm_get_interface_async + usb_autopm_put_interface_async usb_bus_idr usb_bus_idr_lock usb_composite_setup_continue @@ -2597,6 +2608,26 @@ usb_interface_id usb_mon_deregister usb_mon_register + usbnet_disconnect + usbnet_get_endpoints + usbnet_get_msglevel + usbnet_link_change + usbnet_nway_reset + usbnet_open + usbnet_probe + usbnet_read_cmd + usbnet_read_cmd_nopm + usbnet_resume + usbnet_set_msglevel + usbnet_skb_return + usbnet_start_xmit + usbnet_stop + usbnet_suspend + usbnet_tx_timeout + usbnet_update_max_qlen + usbnet_write_cmd + usbnet_write_cmd_async + usbnet_write_cmd_nopm usb_phy_set_charger_current usb_pipe_type_check usb_put_function_instance @@ -2672,6 +2703,7 @@ wait_for_completion_interruptible_timeout wait_for_completion_io_timeout wait_for_completion_timeout + wait_for_device_probe __wait_rcu_gp __wake_up wake_up_if_idle diff --git a/android/abi_gki_aarch64_sunxi b/android/abi_gki_aarch64_sunxi index 2444a6c846a3..8872bdb075ae 100644 --- a/android/abi_gki_aarch64_sunxi +++ b/android/abi_gki_aarch64_sunxi @@ -1603,6 +1603,7 @@ __v4l2_device_register_subdev_nodes v4l2_device_unregister v4l2_device_unregister_subdev + v4l2_enum_dv_timings_cap v4l2_event_queue v4l2_event_subdev_unsubscribe v4l2_event_subscribe @@ -1614,8 +1615,11 @@ v4l2_s_ctrl v4l2_spi_new_subdev v4l2_spi_subdev_init + v4l2_src_change_event_subdev_subscribe v4l2_subdev_call_wrappers v4l2_subdev_init + v4l2_subdev_notify_event + v4l2_valid_dv_timings v4l_bound_align_image vabits_actual vb2_buffer_done diff --git a/android/abi_gki_aarch64_transsion b/android/abi_gki_aarch64_transsion new file mode 100644 index 000000000000..4f0126a8151c --- /dev/null +++ b/android/abi_gki_aarch64_transsion @@ -0,0 +1,2 @@ +[abi_symbol_list] + avenrun diff --git a/android/abi_gki_aarch64_tuxera b/android/abi_gki_aarch64_tuxera index 5b5f71f66653..80093f21a417 100644 --- a/android/abi_gki_aarch64_tuxera +++ b/android/abi_gki_aarch64_tuxera @@ -23,6 +23,7 @@ blk_start_plug __blockdev_direct_IO block_invalidatepage block_is_partially_uptodate +block_read_full_page __breadahead __bread_gfp __brelse @@ -49,6 +50,7 @@ delete_from_page_cache d_instantiate d_make_root d_obtain_alias +dirty_writeback_interval down_read down_write down_write_trylock @@ -104,6 +106,7 @@ __init_rwsem init_special_inode init_wait_entry __init_waitqueue_head +inode_add_bytes inode_dio_wait inode_init_once inode_init_owner @@ -255,6 +258,7 @@ truncate_inode_pages truncate_inode_pages_final truncate_pagecache truncate_setsize +try_to_free_buffers try_to_release_page try_to_writeback_inodes_sb __ubsan_handle_cfi_check_fail_abort @@ -266,6 +270,7 @@ unmap_mapping_range unregister_filesystem up_read up_write +utf32_to_utf8 vfree vfs_fsync_range __vmalloc diff --git a/android/abi_gki_aarch64_unisoc b/android/abi_gki_aarch64_unisoc index b60456fe4be5..01d9e74bd802 100644 --- a/android/abi_gki_aarch64_unisoc +++ b/android/abi_gki_aarch64_unisoc @@ -2354,6 +2354,8 @@ skb_copy_bits skb_vlan_untag unregister_netdevice_notifier + vlan_dev_real_dev + vlan_dev_vlan_id # required by sha1-ce.ko crypto_sha1_finup @@ -3164,17 +3166,21 @@ __tracepoint_android_vh_show_mem # required by unisoc_mm_reclaim.ko + __traceiter_android_vh_clear_page_migrating __traceiter_android_vh_do_page_trylock __traceiter_android_vh_handle_failed_page_trylock __traceiter_android_vh_page_trylock_clear __traceiter_android_vh_page_trylock_get_result __traceiter_android_vh_page_trylock_set + __traceiter_android_vh_set_page_migrating __traceiter_android_vh_shrink_slab_bypass + __tracepoint_android_vh_clear_page_migrating __tracepoint_android_vh_do_page_trylock __tracepoint_android_vh_handle_failed_page_trylock __tracepoint_android_vh_page_trylock_clear __tracepoint_android_vh_page_trylock_get_result __tracepoint_android_vh_page_trylock_set + __tracepoint_android_vh_set_page_migrating __tracepoint_android_vh_shrink_slab_bypass # required by unisoc_mm_slab.ko @@ -3254,6 +3260,9 @@ usb_store_new_id usb_unpoison_urb +# required by sprd_time_sync_cp.ko + pvclock_gtod_register_notifier + # required by vha.ko clk_bulk_get device_wakeup_disable diff --git a/arch/arc/include/asm/linkage.h b/arch/arc/include/asm/linkage.h index c9434ff3aa4c..8a3fb71e9cfa 100644 --- a/arch/arc/include/asm/linkage.h +++ b/arch/arc/include/asm/linkage.h @@ -8,6 +8,10 @@ #include +#define ASM_NL ` /* use '`' to mark new line in macro */ +#define __ALIGN .align 4 +#define __ALIGN_STR __stringify(__ALIGN) + #ifdef __ASSEMBLY__ .macro ST2 e, o, off @@ -28,10 +32,6 @@ #endif .endm -#define ASM_NL ` /* use '`' to mark new line in macro */ -#define __ALIGN .align 4 -#define __ALIGN_STR __stringify(__ALIGN) - /* annotation for data we want in DCCM - if enabled in .config */ .macro ARCFP_DATA nm #ifdef CONFIG_ARC_HAS_DCCM diff --git a/arch/arm/boot/dts/bcm53015-meraki-mr26.dts b/arch/arm/boot/dts/bcm53015-meraki-mr26.dts index 14f58033efeb..ca2266b936ee 100644 --- a/arch/arm/boot/dts/bcm53015-meraki-mr26.dts +++ b/arch/arm/boot/dts/bcm53015-meraki-mr26.dts @@ -128,7 +128,7 @@ fixed-link { speed = <1000>; - duplex-full; + full-duplex; }; }; }; diff --git a/arch/arm/boot/dts/bcm53016-meraki-mr32.dts b/arch/arm/boot/dts/bcm53016-meraki-mr32.dts index 577a4dc604d9..edf9910100b0 100644 --- a/arch/arm/boot/dts/bcm53016-meraki-mr32.dts +++ b/arch/arm/boot/dts/bcm53016-meraki-mr32.dts @@ -212,7 +212,7 @@ fixed-link { speed = <1000>; - duplex-full; + full-duplex; }; }; }; diff --git a/arch/arm/boot/dts/bcm5301x.dtsi b/arch/arm/boot/dts/bcm5301x.dtsi index 30217948ef82..b4b73ab99626 100644 --- a/arch/arm/boot/dts/bcm5301x.dtsi +++ b/arch/arm/boot/dts/bcm5301x.dtsi @@ -542,7 +542,6 @@ "spi_lr_session_done", "spi_lr_overread"; clocks = <&iprocmed>; - clock-names = "iprocmed"; num-cs = <2>; #address-cells = <1>; #size-cells = <0>; diff --git a/arch/arm/boot/dts/iwg20d-q7-common.dtsi b/arch/arm/boot/dts/iwg20d-q7-common.dtsi index bc857676d191..c13d2f6e1a38 100644 --- a/arch/arm/boot/dts/iwg20d-q7-common.dtsi +++ b/arch/arm/boot/dts/iwg20d-q7-common.dtsi @@ -49,7 +49,7 @@ lcd_backlight: backlight { compatible = "pwm-backlight"; - pwms = <&pwm3 0 5000000 0>; + pwms = <&pwm3 0 5000000>; brightness-levels = <0 4 8 16 32 64 128 255>; default-brightness-level = <7>; enable-gpios = <&gpio5 14 GPIO_ACTIVE_HIGH>; diff --git a/arch/arm/boot/dts/meson8.dtsi b/arch/arm/boot/dts/meson8.dtsi index 9997a5d0333a..72828b9d4281 100644 --- a/arch/arm/boot/dts/meson8.dtsi +++ b/arch/arm/boot/dts/meson8.dtsi @@ -749,13 +749,13 @@ &uart_B { compatible = "amlogic,meson8-uart"; - clocks = <&xtal>, <&clkc CLKID_UART0>, <&clkc CLKID_CLK81>; + clocks = <&xtal>, <&clkc CLKID_UART1>, <&clkc CLKID_CLK81>; clock-names = "xtal", "pclk", "baud"; }; &uart_C { compatible = "amlogic,meson8-uart"; - clocks = <&xtal>, <&clkc CLKID_UART0>, <&clkc CLKID_CLK81>; + clocks = <&xtal>, <&clkc CLKID_UART2>, <&clkc CLKID_CLK81>; clock-names = "xtal", "pclk", "baud"; }; diff --git a/arch/arm/boot/dts/meson8b.dtsi b/arch/arm/boot/dts/meson8b.dtsi index 94f1c03decce..cfd4a909a7a7 100644 --- a/arch/arm/boot/dts/meson8b.dtsi +++ b/arch/arm/boot/dts/meson8b.dtsi @@ -737,13 +737,13 @@ &uart_B { compatible = "amlogic,meson8b-uart"; - clocks = <&xtal>, <&clkc CLKID_UART0>, <&clkc CLKID_CLK81>; + clocks = <&xtal>, <&clkc CLKID_UART1>, <&clkc CLKID_CLK81>; clock-names = "xtal", "pclk", "baud"; }; &uart_C { compatible = "amlogic,meson8b-uart"; - clocks = <&xtal>, <&clkc CLKID_UART0>, <&clkc CLKID_CLK81>; + clocks = <&xtal>, <&clkc CLKID_UART2>, <&clkc CLKID_CLK81>; clock-names = "xtal", "pclk", "baud"; }; diff --git a/arch/arm/boot/dts/omap3-gta04a5one.dts b/arch/arm/boot/dts/omap3-gta04a5one.dts index 9db9fe67cd63..95df45cc70c0 100644 --- a/arch/arm/boot/dts/omap3-gta04a5one.dts +++ b/arch/arm/boot/dts/omap3-gta04a5one.dts @@ -5,9 +5,11 @@ #include "omap3-gta04a5.dts" -&omap3_pmx_core { +/ { model = "Goldelico GTA04A5/Letux 2804 with OneNAND"; +}; +&omap3_pmx_core { gpmc_pins: pinmux_gpmc_pins { pinctrl-single,pins = < diff --git a/arch/arm/boot/dts/qcom-ipq4019-ap.dk04.1-c1.dts b/arch/arm/boot/dts/qcom-ipq4019-ap.dk04.1-c1.dts index b0f476ff017f..aadca9bf416c 100644 --- a/arch/arm/boot/dts/qcom-ipq4019-ap.dk04.1-c1.dts +++ b/arch/arm/boot/dts/qcom-ipq4019-ap.dk04.1-c1.dts @@ -11,9 +11,9 @@ dma@7984000 { status = "okay"; }; - - qpic-nand@79b0000 { - status = "okay"; - }; }; }; + +&nand { + status = "okay"; +}; diff --git a/arch/arm/boot/dts/qcom-ipq4019-ap.dk04.1.dtsi b/arch/arm/boot/dts/qcom-ipq4019-ap.dk04.1.dtsi index 7a337dc08741..726aa30eeef5 100644 --- a/arch/arm/boot/dts/qcom-ipq4019-ap.dk04.1.dtsi +++ b/arch/arm/boot/dts/qcom-ipq4019-ap.dk04.1.dtsi @@ -102,10 +102,10 @@ status = "okay"; perst-gpio = <&tlmm 38 0x1>; }; - - qpic-nand@79b0000 { - pinctrl-0 = <&nand_pins>; - pinctrl-names = "default"; - }; }; }; + +&nand { + pinctrl-0 = <&nand_pins>; + pinctrl-names = "default"; +}; diff --git a/arch/arm/boot/dts/qcom-ipq4019-ap.dk07.1.dtsi b/arch/arm/boot/dts/qcom-ipq4019-ap.dk07.1.dtsi index 94872518b5a2..9988b9eab803 100644 --- a/arch/arm/boot/dts/qcom-ipq4019-ap.dk07.1.dtsi +++ b/arch/arm/boot/dts/qcom-ipq4019-ap.dk07.1.dtsi @@ -65,11 +65,11 @@ dma@7984000 { status = "okay"; }; - - qpic-nand@79b0000 { - pinctrl-0 = <&nand_pins>; - pinctrl-names = "default"; - status = "okay"; - }; }; }; + +&nand { + pinctrl-0 = <&nand_pins>; + pinctrl-names = "default"; + status = "okay"; +}; diff --git a/arch/arm/boot/dts/stm32mp15xx-dhcom-pdk2.dtsi b/arch/arm/boot/dts/stm32mp15xx-dhcom-pdk2.dtsi index fbf3826933e4..7c0aa59accc5 100644 --- a/arch/arm/boot/dts/stm32mp15xx-dhcom-pdk2.dtsi +++ b/arch/arm/boot/dts/stm32mp15xx-dhcom-pdk2.dtsi @@ -137,10 +137,13 @@ sound { compatible = "audio-graph-card"; - routing = - "MIC_IN", "Capture", - "Capture", "Mic Bias", - "Playback", "HP_OUT"; + widgets = "Headphone", "Headphone Jack", + "Line", "Line In Jack", + "Microphone", "Microphone Jack"; + routing = "Headphone Jack", "HP_OUT", + "LINE_IN", "Line In Jack", + "MIC_IN", "Microphone Jack", + "Microphone Jack", "Mic Bias"; dais = <&sai2a_port &sai2b_port>; status = "okay"; }; diff --git a/arch/arm/boot/dts/stm32mp15xx-dhcor-avenger96.dtsi b/arch/arm/boot/dts/stm32mp15xx-dhcor-avenger96.dtsi index d3375ad8c91f..5f65d96435f6 100644 --- a/arch/arm/boot/dts/stm32mp15xx-dhcor-avenger96.dtsi +++ b/arch/arm/boot/dts/stm32mp15xx-dhcor-avenger96.dtsi @@ -88,7 +88,7 @@ sound { compatible = "audio-graph-card"; - label = "STM32MP1-AV96-HDMI"; + label = "STM32-AV96-HDMI"; dais = <&sai2a_port>; status = "okay"; }; @@ -267,6 +267,12 @@ }; }; }; + + dh_mac_eeprom: eeprom@53 { + compatible = "atmel,24c02"; + reg = <0x53>; + pagesize = <16>; + }; }; <dc { diff --git a/arch/arm/boot/dts/stm32mp15xx-dhcor-som.dtsi b/arch/arm/boot/dts/stm32mp15xx-dhcor-som.dtsi index 44ecc4708587..108d934a186b 100644 --- a/arch/arm/boot/dts/stm32mp15xx-dhcor-som.dtsi +++ b/arch/arm/boot/dts/stm32mp15xx-dhcor-som.dtsi @@ -171,12 +171,6 @@ status = "disabled"; }; }; - - eeprom@53 { - compatible = "atmel,24c02"; - reg = <0x53>; - pagesize = <16>; - }; }; &iwdg2 { diff --git a/arch/arm/boot/dts/stm32mp15xx-dkx.dtsi b/arch/arm/boot/dts/stm32mp15xx-dkx.dtsi index 48beed0f1f30..a76173e8a2a1 100644 --- a/arch/arm/boot/dts/stm32mp15xx-dkx.dtsi +++ b/arch/arm/boot/dts/stm32mp15xx-dkx.dtsi @@ -438,7 +438,7 @@ i2s2_port: port { i2s2_endpoint: endpoint { remote-endpoint = <&sii9022_tx_endpoint>; - format = "i2s"; + dai-format = "i2s"; mclk-fs = <256>; }; }; diff --git a/arch/arm/include/asm/assembler.h b/arch/arm/include/asm/assembler.h index 09c241280ed9..5d52da168ab3 100644 --- a/arch/arm/include/asm/assembler.h +++ b/arch/arm/include/asm/assembler.h @@ -326,6 +326,23 @@ #endif .endm +/* + * Raw SMP data memory barrier + */ + .macro __smp_dmb mode +#if __LINUX_ARM_ARCH__ >= 7 + .ifeqs "\mode","arm" + dmb ish + .else + W(dmb) ish + .endif +#elif __LINUX_ARM_ARCH__ == 6 + mcr p15, 0, r0, c7, c10, 5 @ dmb +#else + .error "Incompatible SMP platform" +#endif + .endm + #if defined(CONFIG_CPU_V7M) /* * setmode is used to assert to be in svc mode during boot. For v7-M diff --git a/arch/arm/include/asm/sync_bitops.h b/arch/arm/include/asm/sync_bitops.h index 6f5d627c44a3..f46b3c570f92 100644 --- a/arch/arm/include/asm/sync_bitops.h +++ b/arch/arm/include/asm/sync_bitops.h @@ -14,14 +14,35 @@ * ops which are SMP safe even on a UP kernel. */ +/* + * Unordered + */ + #define sync_set_bit(nr, p) _set_bit(nr, p) #define sync_clear_bit(nr, p) _clear_bit(nr, p) #define sync_change_bit(nr, p) _change_bit(nr, p) -#define sync_test_and_set_bit(nr, p) _test_and_set_bit(nr, p) -#define sync_test_and_clear_bit(nr, p) _test_and_clear_bit(nr, p) -#define sync_test_and_change_bit(nr, p) _test_and_change_bit(nr, p) #define sync_test_bit(nr, addr) test_bit(nr, addr) -#define arch_sync_cmpxchg arch_cmpxchg +/* + * Fully ordered + */ + +int _sync_test_and_set_bit(int nr, volatile unsigned long * p); +#define sync_test_and_set_bit(nr, p) _sync_test_and_set_bit(nr, p) + +int _sync_test_and_clear_bit(int nr, volatile unsigned long * p); +#define sync_test_and_clear_bit(nr, p) _sync_test_and_clear_bit(nr, p) + +int _sync_test_and_change_bit(int nr, volatile unsigned long * p); +#define sync_test_and_change_bit(nr, p) _sync_test_and_change_bit(nr, p) + +#define arch_sync_cmpxchg(ptr, old, new) \ +({ \ + __typeof__(*(ptr)) __ret; \ + __smp_mb__before_atomic(); \ + __ret = arch_cmpxchg_relaxed((ptr), (old), (new)); \ + __smp_mb__after_atomic(); \ + __ret; \ +}) #endif diff --git a/arch/arm/include/asm/syscall.h b/arch/arm/include/asm/syscall.h index 24c19d63ff0a..95bf70ebd878 100644 --- a/arch/arm/include/asm/syscall.h +++ b/arch/arm/include/asm/syscall.h @@ -25,6 +25,9 @@ static inline int syscall_get_nr(struct task_struct *task, if (IS_ENABLED(CONFIG_AEABI) && !IS_ENABLED(CONFIG_OABI_COMPAT)) return task_thread_info(task)->abi_syscall; + if (task_thread_info(task)->abi_syscall == -1) + return -1; + return task_thread_info(task)->abi_syscall & __NR_SYSCALL_MASK; } diff --git a/arch/arm/kernel/entry-common.S b/arch/arm/kernel/entry-common.S index fde7ac271b14..e7bfdd10bbcd 100644 --- a/arch/arm/kernel/entry-common.S +++ b/arch/arm/kernel/entry-common.S @@ -101,6 +101,7 @@ slow_work_pending: cmp r0, #0 beq no_work_pending movlt scno, #(__NR_restart_syscall - __NR_SYSCALL_BASE) + str scno, [tsk, #TI_ABI_SYSCALL] @ make sure tracers see update ldmia sp, {r0 - r6} @ have to reload r0 - r6 b local_restart @ ... and off we go ENDPROC(ret_fast_syscall) diff --git a/arch/arm/kernel/ptrace.c b/arch/arm/kernel/ptrace.c index 43b963ea4a0e..71c98ca3a455 100644 --- a/arch/arm/kernel/ptrace.c +++ b/arch/arm/kernel/ptrace.c @@ -786,8 +786,9 @@ long arch_ptrace(struct task_struct *child, long request, break; case PTRACE_SET_SYSCALL: - task_thread_info(child)->abi_syscall = data & - __NR_SYSCALL_MASK; + if (data != -1) + data &= __NR_SYSCALL_MASK; + task_thread_info(child)->abi_syscall = data; ret = 0; break; diff --git a/arch/arm/lib/bitops.h b/arch/arm/lib/bitops.h index 95bd35991288..f069d1b2318e 100644 --- a/arch/arm/lib/bitops.h +++ b/arch/arm/lib/bitops.h @@ -28,7 +28,7 @@ UNWIND( .fnend ) ENDPROC(\name ) .endm - .macro testop, name, instr, store + .macro __testop, name, instr, store, barrier ENTRY( \name ) UNWIND( .fnstart ) ands ip, r1, #3 @@ -38,7 +38,7 @@ UNWIND( .fnstart ) mov r0, r0, lsr #5 add r1, r1, r0, lsl #2 @ Get word offset mov r3, r2, lsl r3 @ create mask - smp_dmb + \barrier #if __LINUX_ARM_ARCH__ >= 7 && defined(CONFIG_SMP) .arch_extension mp ALT_SMP(W(pldw) [r1]) @@ -50,13 +50,21 @@ UNWIND( .fnstart ) strex ip, r2, [r1] cmp ip, #0 bne 1b - smp_dmb + \barrier cmp r0, #0 movne r0, #1 2: bx lr UNWIND( .fnend ) ENDPROC(\name ) .endm + + .macro testop, name, instr, store + __testop \name, \instr, \store, smp_dmb + .endm + + .macro sync_testop, name, instr, store + __testop \name, \instr, \store, __smp_dmb + .endm #else .macro bitop, name, instr ENTRY( \name ) diff --git a/arch/arm/lib/testchangebit.S b/arch/arm/lib/testchangebit.S index 4ebecc67e6e0..f13fe9bc2399 100644 --- a/arch/arm/lib/testchangebit.S +++ b/arch/arm/lib/testchangebit.S @@ -10,3 +10,7 @@ .text testop _test_and_change_bit, eor, str + +#if __LINUX_ARM_ARCH__ >= 6 +sync_testop _sync_test_and_change_bit, eor, str +#endif diff --git a/arch/arm/lib/testclearbit.S b/arch/arm/lib/testclearbit.S index 009afa0f5b4a..4d2c5ca620eb 100644 --- a/arch/arm/lib/testclearbit.S +++ b/arch/arm/lib/testclearbit.S @@ -10,3 +10,7 @@ .text testop _test_and_clear_bit, bicne, strne + +#if __LINUX_ARM_ARCH__ >= 6 +sync_testop _sync_test_and_clear_bit, bicne, strne +#endif diff --git a/arch/arm/lib/testsetbit.S b/arch/arm/lib/testsetbit.S index f3192e55acc8..649dbab65d8d 100644 --- a/arch/arm/lib/testsetbit.S +++ b/arch/arm/lib/testsetbit.S @@ -10,3 +10,7 @@ .text testop _test_and_set_bit, orreq, streq + +#if __LINUX_ARM_ARCH__ >= 6 +sync_testop _sync_test_and_set_bit, orreq, streq +#endif diff --git a/arch/arm/mach-ep93xx/timer-ep93xx.c b/arch/arm/mach-ep93xx/timer-ep93xx.c index dd4b164d1831..a9efa7bc2fa1 100644 --- a/arch/arm/mach-ep93xx/timer-ep93xx.c +++ b/arch/arm/mach-ep93xx/timer-ep93xx.c @@ -9,6 +9,7 @@ #include #include #include "soc.h" +#include "platform.h" /************************************************************************* * Timer handling for EP93xx @@ -60,7 +61,7 @@ static u64 notrace ep93xx_read_sched_clock(void) return ret; } -u64 ep93xx_clocksource_read(struct clocksource *c) +static u64 ep93xx_clocksource_read(struct clocksource *c) { u64 ret; diff --git a/arch/arm/mach-omap2/board-generic.c b/arch/arm/mach-omap2/board-generic.c index 1610c567a6a3..10d2f078e4a8 100644 --- a/arch/arm/mach-omap2/board-generic.c +++ b/arch/arm/mach-omap2/board-generic.c @@ -13,6 +13,7 @@ #include #include #include +#include #include #include diff --git a/arch/arm/mach-orion5x/board-dt.c b/arch/arm/mach-orion5x/board-dt.c index 3d36f1d95196..3f651df3a71c 100644 --- a/arch/arm/mach-orion5x/board-dt.c +++ b/arch/arm/mach-orion5x/board-dt.c @@ -63,6 +63,9 @@ static void __init orion5x_dt_init(void) if (of_machine_is_compatible("maxtor,shared-storage-2")) mss2_init(); + if (of_machine_is_compatible("lacie,d2-network")) + d2net_init(); + of_platform_default_populate(NULL, orion5x_auxdata_lookup, NULL); } diff --git a/arch/arm/mach-orion5x/common.h b/arch/arm/mach-orion5x/common.h index eb96009e21c4..b9cfdb456456 100644 --- a/arch/arm/mach-orion5x/common.h +++ b/arch/arm/mach-orion5x/common.h @@ -75,6 +75,12 @@ extern void mss2_init(void); static inline void mss2_init(void) {} #endif +#ifdef CONFIG_MACH_D2NET_DT +void d2net_init(void); +#else +static inline void d2net_init(void) {} +#endif + /***************************************************************************** * Helpers to access Orion registers ****************************************************************************/ diff --git a/arch/arm/probes/kprobes/checkers-common.c b/arch/arm/probes/kprobes/checkers-common.c index 4d720990cf2a..eba7ac4725c0 100644 --- a/arch/arm/probes/kprobes/checkers-common.c +++ b/arch/arm/probes/kprobes/checkers-common.c @@ -40,7 +40,7 @@ enum probes_insn checker_stack_use_imm_0xx(probes_opcode_t insn, * Different from other insn uses imm8, the real addressing offset of * STRD in T32 encoding should be imm8 * 4. See ARMARM description. */ -enum probes_insn checker_stack_use_t32strd(probes_opcode_t insn, +static enum probes_insn checker_stack_use_t32strd(probes_opcode_t insn, struct arch_probes_insn *asi, const struct decode_header *h) { diff --git a/arch/arm/probes/kprobes/core.c b/arch/arm/probes/kprobes/core.c index 9bcae72dda44..3bd017f6e256 100644 --- a/arch/arm/probes/kprobes/core.c +++ b/arch/arm/probes/kprobes/core.c @@ -233,7 +233,7 @@ singlestep(struct kprobe *p, struct pt_regs *regs, struct kprobe_ctlblk *kcb) * kprobe, and that level is reserved for user kprobe handlers, so we can't * risk encountering a new kprobe in an interrupt handler. */ -void __kprobes kprobe_handler(struct pt_regs *regs) +static void __kprobes kprobe_handler(struct pt_regs *regs) { struct kprobe *p, *cur; struct kprobe_ctlblk *kcb; diff --git a/arch/arm/probes/kprobes/opt-arm.c b/arch/arm/probes/kprobes/opt-arm.c index c78180172120..e20304f1d8bc 100644 --- a/arch/arm/probes/kprobes/opt-arm.c +++ b/arch/arm/probes/kprobes/opt-arm.c @@ -145,8 +145,6 @@ __arch_remove_optimized_kprobe(struct optimized_kprobe *op, int dirty) } } -extern void kprobe_handler(struct pt_regs *regs); - static void optimized_callback(struct optimized_kprobe *op, struct pt_regs *regs) { diff --git a/arch/arm/probes/kprobes/test-core.c b/arch/arm/probes/kprobes/test-core.c index c562832b8627..171c7076b89f 100644 --- a/arch/arm/probes/kprobes/test-core.c +++ b/arch/arm/probes/kprobes/test-core.c @@ -720,7 +720,7 @@ static const char coverage_register_lookup[16] = { [REG_TYPE_NOSPPCX] = COVERAGE_ANY_REG | COVERAGE_SP, }; -unsigned coverage_start_registers(const struct decode_header *h) +static unsigned coverage_start_registers(const struct decode_header *h) { unsigned regs = 0; int i; diff --git a/arch/arm/probes/kprobes/test-core.h b/arch/arm/probes/kprobes/test-core.h index f1d5583e7bbb..7054d9fae2ea 100644 --- a/arch/arm/probes/kprobes/test-core.h +++ b/arch/arm/probes/kprobes/test-core.h @@ -454,3 +454,7 @@ void kprobe_thumb32_test_cases(void); #else void kprobe_arm_test_cases(void); #endif + +void __kprobes_test_case_start(void); +void __kprobes_test_case_end_16(void); +void __kprobes_test_case_end_32(void); diff --git a/arch/arm64/boot/dts/mediatek/mt8183-kukui.dtsi b/arch/arm64/boot/dts/mediatek/mt8183-kukui.dtsi index 8e9cf36a9a41..6529962edd4e 100644 --- a/arch/arm64/boot/dts/mediatek/mt8183-kukui.dtsi +++ b/arch/arm64/boot/dts/mediatek/mt8183-kukui.dtsi @@ -281,6 +281,10 @@ }; }; +&gic { + mediatek,broken-save-restore-fw; +}; + &gpu { mali-supply = <&mt6358_vgpu_reg>; sram-supply = <&mt6358_vsram_gpu_reg>; diff --git a/arch/arm64/boot/dts/mediatek/mt8192.dtsi b/arch/arm64/boot/dts/mediatek/mt8192.dtsi index 9ed1a7229574..72f444405ebf 100644 --- a/arch/arm64/boot/dts/mediatek/mt8192.dtsi +++ b/arch/arm64/boot/dts/mediatek/mt8192.dtsi @@ -41,7 +41,8 @@ clock-frequency = <1701000000>; cpu-idle-states = <&cpu_sleep_l &cluster_sleep_l>; next-level-cache = <&l2_0>; - capacity-dmips-mhz = <530>; + performance-domains = <&performance 0>; + capacity-dmips-mhz = <427>; }; cpu1: cpu@100 { @@ -52,7 +53,8 @@ clock-frequency = <1701000000>; cpu-idle-states = <&cpu_sleep_l &cluster_sleep_l>; next-level-cache = <&l2_0>; - capacity-dmips-mhz = <530>; + performance-domains = <&performance 0>; + capacity-dmips-mhz = <427>; }; cpu2: cpu@200 { @@ -63,7 +65,8 @@ clock-frequency = <1701000000>; cpu-idle-states = <&cpu_sleep_l &cluster_sleep_l>; next-level-cache = <&l2_0>; - capacity-dmips-mhz = <530>; + performance-domains = <&performance 0>; + capacity-dmips-mhz = <427>; }; cpu3: cpu@300 { @@ -74,7 +77,8 @@ clock-frequency = <1701000000>; cpu-idle-states = <&cpu_sleep_l &cluster_sleep_l>; next-level-cache = <&l2_0>; - capacity-dmips-mhz = <530>; + performance-domains = <&performance 0>; + capacity-dmips-mhz = <427>; }; cpu4: cpu@400 { @@ -85,6 +89,7 @@ clock-frequency = <2171000000>; cpu-idle-states = <&cpu_sleep_b &cluster_sleep_b>; next-level-cache = <&l2_1>; + performance-domains = <&performance 1>; capacity-dmips-mhz = <1024>; }; @@ -96,6 +101,7 @@ clock-frequency = <2171000000>; cpu-idle-states = <&cpu_sleep_b &cluster_sleep_b>; next-level-cache = <&l2_1>; + performance-domains = <&performance 1>; capacity-dmips-mhz = <1024>; }; @@ -107,6 +113,7 @@ clock-frequency = <2171000000>; cpu-idle-states = <&cpu_sleep_b &cluster_sleep_b>; next-level-cache = <&l2_1>; + performance-domains = <&performance 1>; capacity-dmips-mhz = <1024>; }; @@ -118,6 +125,7 @@ clock-frequency = <2171000000>; cpu-idle-states = <&cpu_sleep_b &cluster_sleep_b>; next-level-cache = <&l2_1>; + performance-domains = <&performance 1>; capacity-dmips-mhz = <1024>; }; @@ -234,6 +242,12 @@ compatible = "simple-bus"; ranges; + performance: performance-controller@11bc10 { + compatible = "mediatek,cpufreq-hw"; + reg = <0 0x0011bc10 0 0x120>, <0 0x0011bd30 0 0x120>; + #performance-domain-cells = <1>; + }; + gic: interrupt-controller@c000000 { compatible = "arm,gic-v3"; #interrupt-cells = <4>; diff --git a/arch/arm64/boot/dts/microchip/sparx5.dtsi b/arch/arm64/boot/dts/microchip/sparx5.dtsi index 787ebcec121d..a6405059636c 100644 --- a/arch/arm64/boot/dts/microchip/sparx5.dtsi +++ b/arch/arm64/boot/dts/microchip/sparx5.dtsi @@ -61,7 +61,7 @@ interrupt-affinity = <&cpu0>, <&cpu1>; }; - psci { + psci: psci { compatible = "arm,psci-0.2"; method = "smc"; }; diff --git a/arch/arm64/boot/dts/microchip/sparx5_pcb_common.dtsi b/arch/arm64/boot/dts/microchip/sparx5_pcb_common.dtsi index 9d1a082de3e2..32bb76b3202a 100644 --- a/arch/arm64/boot/dts/microchip/sparx5_pcb_common.dtsi +++ b/arch/arm64/boot/dts/microchip/sparx5_pcb_common.dtsi @@ -6,6 +6,18 @@ /dts-v1/; #include "sparx5.dtsi" +&psci { + status = "disabled"; +}; + +&cpu0 { + enable-method = "spin-table"; +}; + +&cpu1 { + enable-method = "spin-table"; +}; + &uart0 { status = "okay"; }; diff --git a/arch/arm64/boot/dts/qcom/apq8016-sbc.dts b/arch/arm64/boot/dts/qcom/apq8016-sbc.dts index f3c0dbfd0a23..c6e8bf18defc 100644 --- a/arch/arm64/boot/dts/qcom/apq8016-sbc.dts +++ b/arch/arm64/boot/dts/qcom/apq8016-sbc.dts @@ -5,9 +5,847 @@ /dts-v1/; -#include "apq8016-sbc.dtsi" +#include "msm8916-pm8916.dtsi" +#include +#include +#include +#include +#include / { model = "Qualcomm Technologies, Inc. APQ 8016 SBC"; compatible = "qcom,apq8016-sbc", "qcom,apq8016"; + + aliases { + serial0 = &blsp1_uart2; + serial1 = &blsp1_uart1; + usid0 = &pm8916_0; + i2c0 = &blsp_i2c2; + i2c1 = &blsp_i2c6; + i2c3 = &blsp_i2c4; + spi0 = &blsp_spi5; + spi1 = &blsp_spi3; + }; + + chosen { + stdout-path = "serial0"; + }; + + camera_vdddo_1v8: camera-vdddo-1v8 { + compatible = "regulator-fixed"; + regulator-name = "camera_vdddo"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-always-on; + }; + + camera_vdda_2v8: camera-vdda-2v8 { + compatible = "regulator-fixed"; + regulator-name = "camera_vdda"; + regulator-min-microvolt = <2800000>; + regulator-max-microvolt = <2800000>; + regulator-always-on; + }; + + camera_vddd_1v5: camera-vddd-1v5 { + compatible = "regulator-fixed"; + regulator-name = "camera_vddd"; + regulator-min-microvolt = <1500000>; + regulator-max-microvolt = <1500000>; + regulator-always-on; + }; + + reserved-memory { + ramoops@bff00000 { + compatible = "ramoops"; + reg = <0x0 0xbff00000 0x0 0x100000>; + + record-size = <0x20000>; + console-size = <0x20000>; + ftrace-size = <0x20000>; + }; + }; + + usb2513 { + compatible = "smsc,usb3503"; + reset-gpios = <&pm8916_gpios 3 GPIO_ACTIVE_LOW>; + initial-mode = <1>; + }; + + usb_id: usb-id { + compatible = "linux,extcon-usb-gpio"; + id-gpio = <&msmgpio 121 GPIO_ACTIVE_HIGH>; + pinctrl-names = "default"; + pinctrl-0 = <&usb_id_default>; + }; + + hdmi-out { + compatible = "hdmi-connector"; + type = "a"; + + port { + hdmi_con: endpoint { + remote-endpoint = <&adv7533_out>; + }; + }; + }; + + gpio-keys { + compatible = "gpio-keys"; + #address-cells = <1>; + #size-cells = <0>; + autorepeat; + + pinctrl-names = "default"; + pinctrl-0 = <&msm_key_volp_n_default>; + + button@0 { + label = "Volume Up"; + linux,code = ; + gpios = <&msmgpio 107 GPIO_ACTIVE_LOW>; + }; + }; + + leds { + pinctrl-names = "default"; + pinctrl-0 = <&msmgpio_leds>, + <&pm8916_gpios_leds>, + <&pm8916_mpps_leds>; + + compatible = "gpio-leds"; + + led@1 { + label = "apq8016-sbc:green:user1"; + gpios = <&msmgpio 21 GPIO_ACTIVE_HIGH>; + linux,default-trigger = "heartbeat"; + default-state = "off"; + }; + + led@2 { + label = "apq8016-sbc:green:user2"; + gpios = <&msmgpio 120 GPIO_ACTIVE_HIGH>; + linux,default-trigger = "mmc0"; + default-state = "off"; + }; + + led@3 { + label = "apq8016-sbc:green:user3"; + gpios = <&pm8916_gpios 1 GPIO_ACTIVE_HIGH>; + linux,default-trigger = "mmc1"; + default-state = "off"; + }; + + led@4 { + label = "apq8016-sbc:green:user4"; + gpios = <&pm8916_gpios 2 GPIO_ACTIVE_HIGH>; + linux,default-trigger = "none"; + panic-indicator; + default-state = "off"; + }; + + led@5 { + label = "apq8016-sbc:yellow:wlan"; + gpios = <&pm8916_mpps 2 GPIO_ACTIVE_HIGH>; + linux,default-trigger = "phy0tx"; + default-state = "off"; + }; + + led@6 { + label = "apq8016-sbc:blue:bt"; + gpios = <&pm8916_mpps 3 GPIO_ACTIVE_HIGH>; + linux,default-trigger = "bluetooth-power"; + default-state = "off"; + }; + }; +}; + +&blsp_dma { + status = "okay"; +}; + +&blsp_i2c2 { + /* On Low speed expansion */ + status = "okay"; + label = "LS-I2C0"; +}; + +&blsp_i2c4 { + /* On High speed expansion */ + status = "okay"; + label = "HS-I2C2"; + + adv_bridge: bridge@39 { + status = "okay"; + + compatible = "adi,adv7533"; + reg = <0x39>; + + interrupt-parent = <&msmgpio>; + interrupts = <31 IRQ_TYPE_EDGE_FALLING>; + + adi,dsi-lanes = <4>; + clocks = <&rpmcc RPM_SMD_BB_CLK2>; + clock-names = "cec"; + + pd-gpios = <&msmgpio 32 GPIO_ACTIVE_HIGH>; + + avdd-supply = <&pm8916_l6>; + v1p2-supply = <&pm8916_l6>; + v3p3-supply = <&pm8916_l17>; + + pinctrl-names = "default","sleep"; + pinctrl-0 = <&adv7533_int_active &adv7533_switch_active>; + pinctrl-1 = <&adv7533_int_suspend &adv7533_switch_suspend>; + #sound-dai-cells = <1>; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + adv7533_in: endpoint { + remote-endpoint = <&dsi0_out>; + }; + }; + + port@1 { + reg = <1>; + adv7533_out: endpoint { + remote-endpoint = <&hdmi_con>; + }; + }; + }; + }; +}; + +&blsp_i2c6 { + /* On Low speed expansion */ + status = "okay"; + label = "LS-I2C1"; +}; + +&blsp_spi3 { + /* On High speed expansion */ + status = "okay"; + label = "HS-SPI1"; +}; + +&blsp_spi5 { + /* On Low speed expansion */ + status = "okay"; + label = "LS-SPI0"; +}; + +&blsp1_uart1 { + status = "okay"; + label = "LS-UART0"; +}; + +&blsp1_uart2 { + status = "okay"; + label = "LS-UART1"; +}; + +&camss { + status = "okay"; + ports { + port@0 { + reg = <0>; + csiphy0_ep: endpoint { + clock-lanes = <1>; + data-lanes = <0 2>; + remote-endpoint = <&ov5640_ep>; + status = "okay"; + }; + }; + }; +}; + +&cci { + status = "okay"; +}; + +&cci_i2c0 { + camera_rear@3b { + compatible = "ovti,ov5640"; + reg = <0x3b>; + + enable-gpios = <&msmgpio 34 GPIO_ACTIVE_HIGH>; + reset-gpios = <&msmgpio 35 GPIO_ACTIVE_LOW>; + pinctrl-names = "default"; + pinctrl-0 = <&camera_rear_default>; + + clocks = <&gcc GCC_CAMSS_MCLK0_CLK>; + clock-names = "xclk"; + clock-frequency = <23880000>; + + vdddo-supply = <&camera_vdddo_1v8>; + vdda-supply = <&camera_vdda_2v8>; + vddd-supply = <&camera_vddd_1v5>; + + /* No camera mezzanine by default */ + status = "disabled"; + + port { + ov5640_ep: endpoint { + clock-lanes = <1>; + data-lanes = <0 2>; + remote-endpoint = <&csiphy0_ep>; + }; + }; + }; +}; + +&dsi0_out { + data-lanes = <0 1 2 3>; + remote-endpoint = <&adv7533_in>; +}; + +&lpass { + status = "okay"; +}; + +&mdss { + status = "okay"; +}; + +&mpss { + status = "okay"; + + firmware-name = "qcom/apq8016/mba.mbn", "qcom/apq8016/modem.mbn"; +}; + +&pm8916_resin { + status = "okay"; + linux,code = ; +}; + +&pronto { + status = "okay"; + + firmware-name = "qcom/apq8016/wcnss.mbn"; +}; + +&sdhc_1 { + status = "okay"; + + pinctrl-names = "default", "sleep"; + pinctrl-0 = <&sdc1_clk_on &sdc1_cmd_on &sdc1_data_on>; + pinctrl-1 = <&sdc1_clk_off &sdc1_cmd_off &sdc1_data_off>; +}; + +&sdhc_2 { + status = "okay"; + + pinctrl-names = "default", "sleep"; + pinctrl-0 = <&sdc2_clk_on &sdc2_cmd_on &sdc2_data_on &sdc2_cd_on>; + pinctrl-1 = <&sdc2_clk_off &sdc2_cmd_off &sdc2_data_off &sdc2_cd_off>; + + cd-gpios = <&msmgpio 38 GPIO_ACTIVE_LOW>; +}; + +&sound { + status = "okay"; + + pinctrl-0 = <&cdc_pdm_lines_act &ext_sec_tlmm_lines_act &ext_mclk_tlmm_lines_act>; + pinctrl-1 = <&cdc_pdm_lines_sus &ext_sec_tlmm_lines_sus &ext_mclk_tlmm_lines_sus>; + pinctrl-names = "default", "sleep"; + qcom,model = "DB410c"; + qcom,audio-routing = + "AMIC2", "MIC BIAS Internal2", + "AMIC3", "MIC BIAS External1"; + + external-dai-link@0 { + link-name = "ADV7533"; + cpu { + sound-dai = <&lpass MI2S_QUATERNARY>; + }; + codec { + sound-dai = <&adv_bridge 0>; + }; + }; + + internal-codec-playback-dai-link@0 { + link-name = "WCD"; + cpu { + sound-dai = <&lpass MI2S_PRIMARY>; + }; + codec { + sound-dai = <&lpass_codec 0>, <&wcd_codec 0>; + }; + }; + + internal-codec-capture-dai-link@0 { + link-name = "WCD-Capture"; + cpu { + sound-dai = <&lpass MI2S_TERTIARY>; + }; + codec { + sound-dai = <&lpass_codec 1>, <&wcd_codec 1>; + }; + }; +}; + +&usb { + status = "okay"; + extcon = <&usb_id>, <&usb_id>; + + pinctrl-names = "default", "device"; + pinctrl-0 = <&usb_sw_sel_pm &usb_hub_reset_pm>; + pinctrl-1 = <&usb_sw_sel_pm_device &usb_hub_reset_pm_device>; +}; + +&usb_hs_phy { + extcon = <&usb_id>; +}; + +&wcd_codec { + clocks = <&gcc GCC_CODEC_DIGCODEC_CLK>; + clock-names = "mclk"; + qcom,mbhc-vthreshold-low = <75 150 237 450 500>; + qcom,mbhc-vthreshold-high = <75 150 237 450 500>; +}; + +&wcnss_ctrl { + firmware-name = "qcom/apq8016/WCNSS_qcom_wlan_nv_sbc.bin"; +}; + +/* Enable CoreSight */ +&cti0 { status = "okay"; }; +&cti1 { status = "okay"; }; +&cti12 { status = "okay"; }; +&cti13 { status = "okay"; }; +&cti14 { status = "okay"; }; +&cti15 { status = "okay"; }; +&debug0 { status = "okay"; }; +&debug1 { status = "okay"; }; +&debug2 { status = "okay"; }; +&debug3 { status = "okay"; }; +&etf { status = "okay"; }; +&etm0 { status = "okay"; }; +&etm1 { status = "okay"; }; +&etm2 { status = "okay"; }; +&etm3 { status = "okay"; }; +&etr { status = "okay"; }; +&funnel0 { status = "okay"; }; +&funnel1 { status = "okay"; }; +&replicator { status = "okay"; }; +&stm { status = "okay"; }; +&tpiu { status = "okay"; }; + +&smd_rpm_regulators { + vdd_l1_l2_l3-supply = <&pm8916_s3>; + vdd_l4_l5_l6-supply = <&pm8916_s4>; + vdd_l7-supply = <&pm8916_s4>; + + s3 { + regulator-min-microvolt = <1250000>; + regulator-max-microvolt = <1350000>; + }; + + s4 { + regulator-min-microvolt = <1850000>; + regulator-max-microvolt = <2150000>; + + regulator-always-on; + regulator-boot-on; + }; + + l1 { + regulator-min-microvolt = <1225000>; + regulator-max-microvolt = <1225000>; + }; + + l2 { + regulator-min-microvolt = <1200000>; + regulator-max-microvolt = <1200000>; + }; + + l4 { + regulator-min-microvolt = <2050000>; + regulator-max-microvolt = <2050000>; + }; + + l5 { + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + }; + + l6 { + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + }; + + l7 { + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + }; + + l8 { + regulator-min-microvolt = <2900000>; + regulator-max-microvolt = <2900000>; + }; + + l9 { + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + }; + + l10 { + regulator-min-microvolt = <2800000>; + regulator-max-microvolt = <2800000>; + }; + + l11 { + regulator-min-microvolt = <2950000>; + regulator-max-microvolt = <2950000>; + regulator-allow-set-load; + regulator-system-load = <200000>; + }; + + l12 { + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <2950000>; + }; + + l13 { + regulator-min-microvolt = <3075000>; + regulator-max-microvolt = <3075000>; + }; + + l14 { + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <3300000>; + }; + + /* + * The 96Boards specification expects a 1.8V power rail on the low-speed + * expansion connector that is able to provide at least 0.18W / 100 mA. + * L15/L16 are connected in parallel to provide 55 mA each. A minimum load + * must be specified to ensure the regulators are not put in LPM where they + * would only provide 5 mA. + */ + l15 { + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-system-load = <50000>; + regulator-allow-set-load; + regulator-always-on; + }; + + l16 { + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-system-load = <50000>; + regulator-allow-set-load; + regulator-always-on; + }; + + l17 { + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + }; + + l18 { + regulator-min-microvolt = <2700000>; + regulator-max-microvolt = <2700000>; + }; +}; + +/* + * 2mA drive strength is not enough when connecting multiple + * I2C devices with different pull up resistors. + */ +&i2c2_default { + drive-strength = <16>; +}; + +&i2c4_default { + drive-strength = <16>; +}; + +&i2c6_default { + drive-strength = <16>; +}; + +/* + * GPIO name legend: proper name = the GPIO line is used as GPIO + * NC = not connected (pin out but not routed from the chip to + * anything the board) + * "[PER]" = pin is muxed for [peripheral] (not GPIO) + * LSEC = Low Speed External Connector + * HSEC = High Speed External Connector + * + * Line names are taken from the schematic "DragonBoard410c" + * dated monday, august 31, 2015. Page 5 in particular. + * + * For the lines routed to the external connectors the + * lines are named after the 96Boards CE Specification 1.0, + * Appendix "Expansion Connector Signal Description". + * + * When the 96Board naming of a line and the schematic name of + * the same line are in conflict, the 96Board specification + * takes precedence, which means that the external UART on the + * LSEC is named UART0 while the schematic and SoC names this + * UART3. This is only for the informational lines i.e. "[FOO]", + * the GPIO named lines "GPIO-A" thru "GPIO-L" are the only + * ones actually used for GPIO. + */ + +&msmgpio { + gpio-line-names = + "[UART0_TX]", /* GPIO_0, LSEC pin 5 */ + "[UART0_RX]", /* GPIO_1, LSEC pin 7 */ + "[UART0_CTS_N]", /* GPIO_2, LSEC pin 3 */ + "[UART0_RTS_N]", /* GPIO_3, LSEC pin 9 */ + "[UART1_TX]", /* GPIO_4, LSEC pin 11 */ + "[UART1_RX]", /* GPIO_5, LSEC pin 13 */ + "[I2C0_SDA]", /* GPIO_8, LSEC pin 17 */ + "[I2C0_SCL]", /* GPIO_7, LSEC pin 15 */ + "[SPI1_DOUT]", /* SPI1_MOSI, HSEC pin 1 */ + "[SPI1_DIN]", /* SPI1_MISO, HSEC pin 11 */ + "[SPI1_CS]", /* SPI1_CS_N, HSEC pin 7 */ + "[SPI1_SCLK]", /* SPI1_CLK, HSEC pin 9 */ + "GPIO-B", /* LS_EXP_GPIO_B, LSEC pin 24 */ + "GPIO-C", /* LS_EXP_GPIO_C, LSEC pin 25 */ + "[I2C3_SDA]", /* HSEC pin 38 */ + "[I2C3_SCL]", /* HSEC pin 36 */ + "[SPI0_MOSI]", /* LSEC pin 14 */ + "[SPI0_MISO]", /* LSEC pin 10 */ + "[SPI0_CS_N]", /* LSEC pin 12 */ + "[SPI0_CLK]", /* LSEC pin 8 */ + "HDMI_HPD_N", /* GPIO 20 */ + "USR_LED_1_CTRL", + "[I2C1_SDA]", /* GPIO_22, LSEC pin 21 */ + "[I2C1_SCL]", /* GPIO_23, LSEC pin 19 */ + "GPIO-G", /* LS_EXP_GPIO_G, LSEC pin 29 */ + "GPIO-H", /* LS_EXP_GPIO_H, LSEC pin 30 */ + "[CSI0_MCLK]", /* HSEC pin 15 */ + "[CSI1_MCLK]", /* HSEC pin 17 */ + "GPIO-K", /* LS_EXP_GPIO_K, LSEC pin 33 */ + "[I2C2_SDA]", /* HSEC pin 34 */ + "[I2C2_SCL]", /* HSEC pin 32 */ + "DSI2HDMI_INT_N", + "DSI_SW_SEL_APQ", + "GPIO-L", /* LS_EXP_GPIO_L, LSEC pin 34 */ + "GPIO-J", /* LS_EXP_GPIO_J, LSEC pin 32 */ + "GPIO-I", /* LS_EXP_GPIO_I, LSEC pin 31 */ + "GPIO-A", /* LS_EXP_GPIO_A, LSEC pin 23 */ + "FORCED_USB_BOOT", + "SD_CARD_DET_N", + "[WCSS_BT_SSBI]", + "[WCSS_WLAN_DATA_2]", /* GPIO 40 */ + "[WCSS_WLAN_DATA_1]", + "[WCSS_WLAN_DATA_0]", + "[WCSS_WLAN_SET]", + "[WCSS_WLAN_CLK]", + "[WCSS_FM_SSBI]", + "[WCSS_FM_SDI]", + "[WCSS_BT_DAT_CTL]", + "[WCSS_BT_DAT_STB]", + "NC", + "NC", /* GPIO 50 */ + "NC", + "NC", + "NC", + "NC", + "NC", + "NC", + "NC", + "NC", + "NC", + "NC", /* GPIO 60 */ + "NC", + "NC", + "[CDC_PDM0_CLK]", + "[CDC_PDM0_SYNC]", + "[CDC_PDM0_TX0]", + "[CDC_PDM0_RX0]", + "[CDC_PDM0_RX1]", + "[CDC_PDM0_RX2]", + "GPIO-D", /* LS_EXP_GPIO_D, LSEC pin 26 */ + "NC", /* GPIO 70 */ + "NC", + "NC", + "NC", + "NC", /* GPIO 74 */ + "NC", + "NC", + "NC", + "NC", + "NC", + "BOOT_CONFIG_0", /* GPIO 80 */ + "BOOT_CONFIG_1", + "BOOT_CONFIG_2", + "BOOT_CONFIG_3", + "NC", + "NC", + "BOOT_CONFIG_5", + "NC", + "NC", + "NC", + "NC", /* GPIO 90 */ + "NC", + "NC", + "NC", + "NC", + "NC", + "NC", + "NC", + "NC", + "NC", + "NC", /* GPIO 100 */ + "NC", + "NC", + "NC", + "SSBI_GPS", + "NC", + "NC", + "KEY_VOLP_N", + "NC", + "NC", + "[LS_EXP_MI2S_WS]", /* GPIO 110 */ + "NC", + "NC", + "[LS_EXP_MI2S_SCK]", + "[LS_EXP_MI2S_DATA0]", + "GPIO-E", /* LS_EXP_GPIO_E, LSEC pin 27 */ + "NC", + "[DSI2HDMI_MI2S_WS]", + "[DSI2HDMI_MI2S_SCK]", + "[DSI2HDMI_MI2S_DATA0]", + "USR_LED_2_CTRL", /* GPIO 120 */ + "SB_HS_ID"; + + msmgpio_leds: msmgpio-leds { + pins = "gpio21", "gpio120"; + function = "gpio"; + + output-low; + }; + + usb_id_default: usb-id-default { + pins = "gpio121"; + function = "gpio"; + + drive-strength = <8>; + input-enable; + bias-pull-up; + }; + + adv7533_int_active: adv533-int-active { + pins = "gpio31"; + function = "gpio"; + + drive-strength = <16>; + bias-disable; + }; + + adv7533_int_suspend: adv7533-int-suspend { + pins = "gpio31"; + function = "gpio"; + + drive-strength = <2>; + bias-disable; + }; + + adv7533_switch_active: adv7533-switch-active { + pins = "gpio32"; + function = "gpio"; + + drive-strength = <16>; + bias-disable; + }; + + adv7533_switch_suspend: adv7533-switch-suspend { + pins = "gpio32"; + function = "gpio"; + + drive-strength = <2>; + bias-disable; + }; + + msm_key_volp_n_default: msm-key-volp-n-default { + pins = "gpio107"; + function = "gpio"; + + drive-strength = <8>; + input-enable; + bias-pull-up; + }; +}; + +&pm8916_gpios { + gpio-line-names = + "USR_LED_3_CTRL", + "USR_LED_4_CTRL", + "USB_HUB_RESET_N_PM", + "USB_SW_SEL_PM"; + + usb_hub_reset_pm: usb-hub-reset-pm { + pins = "gpio3"; + function = PMIC_GPIO_FUNC_NORMAL; + + input-disable; + output-high; + }; + + usb_hub_reset_pm_device: usb-hub-reset-pm-device { + pins = "gpio3"; + function = PMIC_GPIO_FUNC_NORMAL; + + output-low; + }; + + usb_sw_sel_pm: usb-sw-sel-pm { + pins = "gpio4"; + function = PMIC_GPIO_FUNC_NORMAL; + + power-source = ; + input-disable; + output-high; + }; + + usb_sw_sel_pm_device: usb-sw-sel-pm-device { + pins = "gpio4"; + function = PMIC_GPIO_FUNC_NORMAL; + + power-source = ; + input-disable; + output-low; + }; + + pm8916_gpios_leds: pm8916-gpios-leds { + pins = "gpio1", "gpio2"; + function = PMIC_GPIO_FUNC_NORMAL; + + output-low; + }; +}; + +&pm8916_mpps { + gpio-line-names = + "VDD_PX_BIAS", + "WLAN_LED_CTRL", + "BT_LED_CTRL", + "GPIO-F"; /* LS_EXP_GPIO_F, LSEC pin 28 */ + + pinctrl-names = "default"; + pinctrl-0 = <&ls_exp_gpio_f>; + + ls_exp_gpio_f: pm8916-mpp4-state { + pins = "mpp4"; + function = "digital"; + + output-low; + power-source = ; // 1.8V + }; + + pm8916_mpps_leds: pm8916-mpps-state { + pins = "mpp2", "mpp3"; + function = "digital"; + + output-low; + }; }; diff --git a/arch/arm64/boot/dts/qcom/apq8016-sbc.dtsi b/arch/arm64/boot/dts/qcom/apq8016-sbc.dtsi deleted file mode 100644 index f8d8f3e3664e..000000000000 --- a/arch/arm64/boot/dts/qcom/apq8016-sbc.dtsi +++ /dev/null @@ -1,826 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * Copyright (c) 2015, The Linux Foundation. All rights reserved. - */ - -#include "msm8916-pm8916.dtsi" -#include -#include -#include -#include -#include - -/ { - aliases { - serial0 = &blsp1_uart2; - serial1 = &blsp1_uart1; - usid0 = &pm8916_0; - i2c0 = &blsp_i2c2; - i2c1 = &blsp_i2c6; - i2c3 = &blsp_i2c4; - spi0 = &blsp_spi5; - spi1 = &blsp_spi3; - }; - - chosen { - stdout-path = "serial0"; - }; - - camera_vdddo_1v8: camera-vdddo-1v8 { - compatible = "regulator-fixed"; - regulator-name = "camera_vdddo"; - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <1800000>; - regulator-always-on; - }; - - camera_vdda_2v8: camera-vdda-2v8 { - compatible = "regulator-fixed"; - regulator-name = "camera_vdda"; - regulator-min-microvolt = <2800000>; - regulator-max-microvolt = <2800000>; - regulator-always-on; - }; - - camera_vddd_1v5: camera-vddd-1v5 { - compatible = "regulator-fixed"; - regulator-name = "camera_vddd"; - regulator-min-microvolt = <1500000>; - regulator-max-microvolt = <1500000>; - regulator-always-on; - }; - - reserved-memory { - ramoops@bff00000 { - compatible = "ramoops"; - reg = <0x0 0xbff00000 0x0 0x100000>; - - record-size = <0x20000>; - console-size = <0x20000>; - ftrace-size = <0x20000>; - }; - }; - - usb2513 { - compatible = "smsc,usb3503"; - reset-gpios = <&pm8916_gpios 3 GPIO_ACTIVE_LOW>; - initial-mode = <1>; - }; - - usb_id: usb-id { - compatible = "linux,extcon-usb-gpio"; - id-gpio = <&msmgpio 121 GPIO_ACTIVE_HIGH>; - pinctrl-names = "default"; - pinctrl-0 = <&usb_id_default>; - }; - - hdmi-out { - compatible = "hdmi-connector"; - type = "a"; - - port { - hdmi_con: endpoint { - remote-endpoint = <&adv7533_out>; - }; - }; - }; - - gpio-keys { - compatible = "gpio-keys"; - #address-cells = <1>; - #size-cells = <0>; - autorepeat; - - pinctrl-names = "default"; - pinctrl-0 = <&msm_key_volp_n_default>; - - button@0 { - label = "Volume Up"; - linux,code = ; - gpios = <&msmgpio 107 GPIO_ACTIVE_LOW>; - }; - }; - - leds { - pinctrl-names = "default"; - pinctrl-0 = <&msmgpio_leds>, - <&pm8916_gpios_leds>, - <&pm8916_mpps_leds>; - - compatible = "gpio-leds"; - - led@1 { - label = "apq8016-sbc:green:user1"; - gpios = <&msmgpio 21 GPIO_ACTIVE_HIGH>; - linux,default-trigger = "heartbeat"; - default-state = "off"; - }; - - led@2 { - label = "apq8016-sbc:green:user2"; - gpios = <&msmgpio 120 GPIO_ACTIVE_HIGH>; - linux,default-trigger = "mmc0"; - default-state = "off"; - }; - - led@3 { - label = "apq8016-sbc:green:user3"; - gpios = <&pm8916_gpios 1 GPIO_ACTIVE_HIGH>; - linux,default-trigger = "mmc1"; - default-state = "off"; - }; - - led@4 { - label = "apq8016-sbc:green:user4"; - gpios = <&pm8916_gpios 2 GPIO_ACTIVE_HIGH>; - linux,default-trigger = "none"; - panic-indicator; - default-state = "off"; - }; - - led@5 { - label = "apq8016-sbc:yellow:wlan"; - gpios = <&pm8916_mpps 2 GPIO_ACTIVE_HIGH>; - linux,default-trigger = "phy0tx"; - default-state = "off"; - }; - - led@6 { - label = "apq8016-sbc:blue:bt"; - gpios = <&pm8916_mpps 3 GPIO_ACTIVE_HIGH>; - linux,default-trigger = "bluetooth-power"; - default-state = "off"; - }; - }; -}; - -&blsp_dma { - status = "okay"; -}; - -&blsp_i2c2 { - /* On Low speed expansion */ - status = "okay"; - label = "LS-I2C0"; -}; - -&blsp_i2c4 { - /* On High speed expansion */ - status = "okay"; - label = "HS-I2C2"; - - adv_bridge: bridge@39 { - status = "okay"; - - compatible = "adi,adv7533"; - reg = <0x39>; - - interrupt-parent = <&msmgpio>; - interrupts = <31 IRQ_TYPE_EDGE_FALLING>; - - adi,dsi-lanes = <4>; - clocks = <&rpmcc RPM_SMD_BB_CLK2>; - clock-names = "cec"; - - pd-gpios = <&msmgpio 32 GPIO_ACTIVE_HIGH>; - - avdd-supply = <&pm8916_l6>; - v1p2-supply = <&pm8916_l6>; - v3p3-supply = <&pm8916_l17>; - - pinctrl-names = "default","sleep"; - pinctrl-0 = <&adv7533_int_active &adv7533_switch_active>; - pinctrl-1 = <&adv7533_int_suspend &adv7533_switch_suspend>; - #sound-dai-cells = <1>; - - ports { - #address-cells = <1>; - #size-cells = <0>; - - port@0 { - reg = <0>; - adv7533_in: endpoint { - remote-endpoint = <&dsi0_out>; - }; - }; - - port@1 { - reg = <1>; - adv7533_out: endpoint { - remote-endpoint = <&hdmi_con>; - }; - }; - }; - }; -}; - -&blsp_i2c6 { - /* On Low speed expansion */ - status = "okay"; - label = "LS-I2C1"; -}; - -&blsp_spi3 { - /* On High speed expansion */ - status = "okay"; - label = "HS-SPI1"; -}; - -&blsp_spi5 { - /* On Low speed expansion */ - status = "okay"; - label = "LS-SPI0"; -}; - -&blsp1_uart1 { - status = "okay"; - label = "LS-UART0"; -}; - -&blsp1_uart2 { - status = "okay"; - label = "LS-UART1"; -}; - -&camss { - status = "okay"; - ports { - port@0 { - reg = <0>; - csiphy0_ep: endpoint { - clock-lanes = <1>; - data-lanes = <0 2>; - remote-endpoint = <&ov5640_ep>; - status = "okay"; - }; - }; - }; -}; - -&cci { - status = "okay"; -}; - -&cci_i2c0 { - camera_rear@3b { - compatible = "ovti,ov5640"; - reg = <0x3b>; - - enable-gpios = <&msmgpio 34 GPIO_ACTIVE_HIGH>; - reset-gpios = <&msmgpio 35 GPIO_ACTIVE_LOW>; - pinctrl-names = "default"; - pinctrl-0 = <&camera_rear_default>; - - clocks = <&gcc GCC_CAMSS_MCLK0_CLK>; - clock-names = "xclk"; - clock-frequency = <23880000>; - - vdddo-supply = <&camera_vdddo_1v8>; - vdda-supply = <&camera_vdda_2v8>; - vddd-supply = <&camera_vddd_1v5>; - - /* No camera mezzanine by default */ - status = "disabled"; - - port { - ov5640_ep: endpoint { - clock-lanes = <1>; - data-lanes = <0 2>; - remote-endpoint = <&csiphy0_ep>; - }; - }; - }; -}; - -&dsi0_out { - data-lanes = <0 1 2 3>; - remote-endpoint = <&adv7533_in>; -}; - -&lpass { - status = "okay"; -}; - -&mdss { - status = "okay"; -}; - -&pm8916_resin { - status = "okay"; - linux,code = ; -}; - -&pronto { - status = "okay"; -}; - -&sdhc_1 { - status = "okay"; - - pinctrl-names = "default", "sleep"; - pinctrl-0 = <&sdc1_clk_on &sdc1_cmd_on &sdc1_data_on>; - pinctrl-1 = <&sdc1_clk_off &sdc1_cmd_off &sdc1_data_off>; -}; - -&sdhc_2 { - status = "okay"; - - pinctrl-names = "default", "sleep"; - pinctrl-0 = <&sdc2_clk_on &sdc2_cmd_on &sdc2_data_on &sdc2_cd_on>; - pinctrl-1 = <&sdc2_clk_off &sdc2_cmd_off &sdc2_data_off &sdc2_cd_off>; - - cd-gpios = <&msmgpio 38 GPIO_ACTIVE_LOW>; -}; - -&sound { - status = "okay"; - - pinctrl-0 = <&cdc_pdm_lines_act &ext_sec_tlmm_lines_act &ext_mclk_tlmm_lines_act>; - pinctrl-1 = <&cdc_pdm_lines_sus &ext_sec_tlmm_lines_sus &ext_mclk_tlmm_lines_sus>; - pinctrl-names = "default", "sleep"; - qcom,model = "DB410c"; - qcom,audio-routing = - "AMIC2", "MIC BIAS Internal2", - "AMIC3", "MIC BIAS External1"; - - external-dai-link@0 { - link-name = "ADV7533"; - cpu { - sound-dai = <&lpass MI2S_QUATERNARY>; - }; - codec { - sound-dai = <&adv_bridge 0>; - }; - }; - - internal-codec-playback-dai-link@0 { - link-name = "WCD"; - cpu { - sound-dai = <&lpass MI2S_PRIMARY>; - }; - codec { - sound-dai = <&lpass_codec 0>, <&wcd_codec 0>; - }; - }; - - internal-codec-capture-dai-link@0 { - link-name = "WCD-Capture"; - cpu { - sound-dai = <&lpass MI2S_TERTIARY>; - }; - codec { - sound-dai = <&lpass_codec 1>, <&wcd_codec 1>; - }; - }; -}; - -&usb { - status = "okay"; - extcon = <&usb_id>, <&usb_id>; - - pinctrl-names = "default", "device"; - pinctrl-0 = <&usb_sw_sel_pm &usb_hub_reset_pm>; - pinctrl-1 = <&usb_sw_sel_pm_device &usb_hub_reset_pm_device>; -}; - -&usb_hs_phy { - extcon = <&usb_id>; -}; - -&wcd_codec { - clocks = <&gcc GCC_CODEC_DIGCODEC_CLK>; - clock-names = "mclk"; - qcom,mbhc-vthreshold-low = <75 150 237 450 500>; - qcom,mbhc-vthreshold-high = <75 150 237 450 500>; -}; - -/* Enable CoreSight */ -&cti0 { status = "okay"; }; -&cti1 { status = "okay"; }; -&cti12 { status = "okay"; }; -&cti13 { status = "okay"; }; -&cti14 { status = "okay"; }; -&cti15 { status = "okay"; }; -&debug0 { status = "okay"; }; -&debug1 { status = "okay"; }; -&debug2 { status = "okay"; }; -&debug3 { status = "okay"; }; -&etf { status = "okay"; }; -&etm0 { status = "okay"; }; -&etm1 { status = "okay"; }; -&etm2 { status = "okay"; }; -&etm3 { status = "okay"; }; -&etr { status = "okay"; }; -&funnel0 { status = "okay"; }; -&funnel1 { status = "okay"; }; -&replicator { status = "okay"; }; -&stm { status = "okay"; }; -&tpiu { status = "okay"; }; - -&smd_rpm_regulators { - vdd_l1_l2_l3-supply = <&pm8916_s3>; - vdd_l4_l5_l6-supply = <&pm8916_s4>; - vdd_l7-supply = <&pm8916_s4>; - - s3 { - regulator-min-microvolt = <375000>; - regulator-max-microvolt = <1562000>; - }; - - s4 { - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <1800000>; - - regulator-always-on; - regulator-boot-on; - }; - - l1 { - regulator-min-microvolt = <375000>; - regulator-max-microvolt = <1525000>; - }; - - l2 { - regulator-min-microvolt = <1200000>; - regulator-max-microvolt = <1200000>; - }; - - l4 { - regulator-min-microvolt = <1750000>; - regulator-max-microvolt = <3337000>; - }; - - l5 { - regulator-min-microvolt = <1750000>; - regulator-max-microvolt = <3337000>; - }; - - l6 { - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <1800000>; - }; - - l7 { - regulator-min-microvolt = <1750000>; - regulator-max-microvolt = <3337000>; - }; - - l8 { - regulator-min-microvolt = <1750000>; - regulator-max-microvolt = <3337000>; - }; - - l9 { - regulator-min-microvolt = <1750000>; - regulator-max-microvolt = <3337000>; - }; - - l10 { - regulator-min-microvolt = <1750000>; - regulator-max-microvolt = <3337000>; - }; - - l11 { - regulator-min-microvolt = <1750000>; - regulator-max-microvolt = <3337000>; - regulator-allow-set-load; - regulator-system-load = <200000>; - }; - - l12 { - regulator-min-microvolt = <1750000>; - regulator-max-microvolt = <3337000>; - }; - - l13 { - regulator-min-microvolt = <1750000>; - regulator-max-microvolt = <3337000>; - }; - - l14 { - regulator-min-microvolt = <1750000>; - regulator-max-microvolt = <3337000>; - }; - - /** - * 1.8v required on LS expansion - * for mezzanine boards - */ - l15 { - regulator-min-microvolt = <1750000>; - regulator-max-microvolt = <3337000>; - regulator-always-on; - }; - - l16 { - regulator-min-microvolt = <1750000>; - regulator-max-microvolt = <3337000>; - }; - - l17 { - regulator-min-microvolt = <3300000>; - regulator-max-microvolt = <3300000>; - }; - - l18 { - regulator-min-microvolt = <1750000>; - regulator-max-microvolt = <3337000>; - }; -}; - -/* - * 2mA drive strength is not enough when connecting multiple - * I2C devices with different pull up resistors. - */ -&i2c2_default { - drive-strength = <16>; -}; - -&i2c4_default { - drive-strength = <16>; -}; - -&i2c6_default { - drive-strength = <16>; -}; - -/* - * GPIO name legend: proper name = the GPIO line is used as GPIO - * NC = not connected (pin out but not routed from the chip to - * anything the board) - * "[PER]" = pin is muxed for [peripheral] (not GPIO) - * LSEC = Low Speed External Connector - * HSEC = High Speed External Connector - * - * Line names are taken from the schematic "DragonBoard410c" - * dated monday, august 31, 2015. Page 5 in particular. - * - * For the lines routed to the external connectors the - * lines are named after the 96Boards CE Specification 1.0, - * Appendix "Expansion Connector Signal Description". - * - * When the 96Board naming of a line and the schematic name of - * the same line are in conflict, the 96Board specification - * takes precedence, which means that the external UART on the - * LSEC is named UART0 while the schematic and SoC names this - * UART3. This is only for the informational lines i.e. "[FOO]", - * the GPIO named lines "GPIO-A" thru "GPIO-L" are the only - * ones actually used for GPIO. - */ - -&msmgpio { - gpio-line-names = - "[UART0_TX]", /* GPIO_0, LSEC pin 5 */ - "[UART0_RX]", /* GPIO_1, LSEC pin 7 */ - "[UART0_CTS_N]", /* GPIO_2, LSEC pin 3 */ - "[UART0_RTS_N]", /* GPIO_3, LSEC pin 9 */ - "[UART1_TX]", /* GPIO_4, LSEC pin 11 */ - "[UART1_RX]", /* GPIO_5, LSEC pin 13 */ - "[I2C0_SDA]", /* GPIO_8, LSEC pin 17 */ - "[I2C0_SCL]", /* GPIO_7, LSEC pin 15 */ - "[SPI1_DOUT]", /* SPI1_MOSI, HSEC pin 1 */ - "[SPI1_DIN]", /* SPI1_MISO, HSEC pin 11 */ - "[SPI1_CS]", /* SPI1_CS_N, HSEC pin 7 */ - "[SPI1_SCLK]", /* SPI1_CLK, HSEC pin 9 */ - "GPIO-B", /* LS_EXP_GPIO_B, LSEC pin 24 */ - "GPIO-C", /* LS_EXP_GPIO_C, LSEC pin 25 */ - "[I2C3_SDA]", /* HSEC pin 38 */ - "[I2C3_SCL]", /* HSEC pin 36 */ - "[SPI0_MOSI]", /* LSEC pin 14 */ - "[SPI0_MISO]", /* LSEC pin 10 */ - "[SPI0_CS_N]", /* LSEC pin 12 */ - "[SPI0_CLK]", /* LSEC pin 8 */ - "HDMI_HPD_N", /* GPIO 20 */ - "USR_LED_1_CTRL", - "[I2C1_SDA]", /* GPIO_22, LSEC pin 21 */ - "[I2C1_SCL]", /* GPIO_23, LSEC pin 19 */ - "GPIO-G", /* LS_EXP_GPIO_G, LSEC pin 29 */ - "GPIO-H", /* LS_EXP_GPIO_H, LSEC pin 30 */ - "[CSI0_MCLK]", /* HSEC pin 15 */ - "[CSI1_MCLK]", /* HSEC pin 17 */ - "GPIO-K", /* LS_EXP_GPIO_K, LSEC pin 33 */ - "[I2C2_SDA]", /* HSEC pin 34 */ - "[I2C2_SCL]", /* HSEC pin 32 */ - "DSI2HDMI_INT_N", - "DSI_SW_SEL_APQ", - "GPIO-L", /* LS_EXP_GPIO_L, LSEC pin 34 */ - "GPIO-J", /* LS_EXP_GPIO_J, LSEC pin 32 */ - "GPIO-I", /* LS_EXP_GPIO_I, LSEC pin 31 */ - "GPIO-A", /* LS_EXP_GPIO_A, LSEC pin 23 */ - "FORCED_USB_BOOT", - "SD_CARD_DET_N", - "[WCSS_BT_SSBI]", - "[WCSS_WLAN_DATA_2]", /* GPIO 40 */ - "[WCSS_WLAN_DATA_1]", - "[WCSS_WLAN_DATA_0]", - "[WCSS_WLAN_SET]", - "[WCSS_WLAN_CLK]", - "[WCSS_FM_SSBI]", - "[WCSS_FM_SDI]", - "[WCSS_BT_DAT_CTL]", - "[WCSS_BT_DAT_STB]", - "NC", - "NC", /* GPIO 50 */ - "NC", - "NC", - "NC", - "NC", - "NC", - "NC", - "NC", - "NC", - "NC", - "NC", /* GPIO 60 */ - "NC", - "NC", - "[CDC_PDM0_CLK]", - "[CDC_PDM0_SYNC]", - "[CDC_PDM0_TX0]", - "[CDC_PDM0_RX0]", - "[CDC_PDM0_RX1]", - "[CDC_PDM0_RX2]", - "GPIO-D", /* LS_EXP_GPIO_D, LSEC pin 26 */ - "NC", /* GPIO 70 */ - "NC", - "NC", - "NC", - "NC", /* GPIO 74 */ - "NC", - "NC", - "NC", - "NC", - "NC", - "BOOT_CONFIG_0", /* GPIO 80 */ - "BOOT_CONFIG_1", - "BOOT_CONFIG_2", - "BOOT_CONFIG_3", - "NC", - "NC", - "BOOT_CONFIG_5", - "NC", - "NC", - "NC", - "NC", /* GPIO 90 */ - "NC", - "NC", - "NC", - "NC", - "NC", - "NC", - "NC", - "NC", - "NC", - "NC", /* GPIO 100 */ - "NC", - "NC", - "NC", - "SSBI_GPS", - "NC", - "NC", - "KEY_VOLP_N", - "NC", - "NC", - "[LS_EXP_MI2S_WS]", /* GPIO 110 */ - "NC", - "NC", - "[LS_EXP_MI2S_SCK]", - "[LS_EXP_MI2S_DATA0]", - "GPIO-E", /* LS_EXP_GPIO_E, LSEC pin 27 */ - "NC", - "[DSI2HDMI_MI2S_WS]", - "[DSI2HDMI_MI2S_SCK]", - "[DSI2HDMI_MI2S_DATA0]", - "USR_LED_2_CTRL", /* GPIO 120 */ - "SB_HS_ID"; - - msmgpio_leds: msmgpio-leds { - pins = "gpio21", "gpio120"; - function = "gpio"; - - output-low; - }; - - usb_id_default: usb-id-default { - pins = "gpio121"; - function = "gpio"; - - drive-strength = <8>; - input-enable; - bias-pull-up; - }; - - adv7533_int_active: adv533-int-active { - pins = "gpio31"; - function = "gpio"; - - drive-strength = <16>; - bias-disable; - }; - - adv7533_int_suspend: adv7533-int-suspend { - pins = "gpio31"; - function = "gpio"; - - drive-strength = <2>; - bias-disable; - }; - - adv7533_switch_active: adv7533-switch-active { - pins = "gpio32"; - function = "gpio"; - - drive-strength = <16>; - bias-disable; - }; - - adv7533_switch_suspend: adv7533-switch-suspend { - pins = "gpio32"; - function = "gpio"; - - drive-strength = <2>; - bias-disable; - }; - - msm_key_volp_n_default: msm-key-volp-n-default { - pins = "gpio107"; - function = "gpio"; - - drive-strength = <8>; - input-enable; - bias-pull-up; - }; -}; - -&pm8916_gpios { - gpio-line-names = - "USR_LED_3_CTRL", - "USR_LED_4_CTRL", - "USB_HUB_RESET_N_PM", - "USB_SW_SEL_PM"; - - usb_hub_reset_pm: usb-hub-reset-pm { - pins = "gpio3"; - function = PMIC_GPIO_FUNC_NORMAL; - - input-disable; - output-high; - }; - - usb_hub_reset_pm_device: usb-hub-reset-pm-device { - pins = "gpio3"; - function = PMIC_GPIO_FUNC_NORMAL; - - output-low; - }; - - usb_sw_sel_pm: usb-sw-sel-pm { - pins = "gpio4"; - function = PMIC_GPIO_FUNC_NORMAL; - - power-source = ; - input-disable; - output-high; - }; - - usb_sw_sel_pm_device: usb-sw-sel-pm-device { - pins = "gpio4"; - function = PMIC_GPIO_FUNC_NORMAL; - - power-source = ; - input-disable; - output-low; - }; - - pm8916_gpios_leds: pm8916-gpios-leds { - pins = "gpio1", "gpio2"; - function = PMIC_GPIO_FUNC_NORMAL; - - output-low; - }; -}; - -&pm8916_mpps { - gpio-line-names = - "VDD_PX_BIAS", - "WLAN_LED_CTRL", - "BT_LED_CTRL", - "GPIO-F"; /* LS_EXP_GPIO_F, LSEC pin 28 */ - - pinctrl-names = "default"; - pinctrl-0 = <&ls_exp_gpio_f>; - - ls_exp_gpio_f: pm8916-mpp4 { - pins = "mpp4"; - function = "digital"; - - output-low; - power-source = ; // 1.8V - }; - - pm8916_mpps_leds: pm8916-mpps-leds { - pins = "mpp2", "mpp3"; - function = "digital"; - - output-low; - }; -}; diff --git a/arch/arm64/boot/dts/qcom/apq8096-db820c.dts b/arch/arm64/boot/dts/qcom/apq8096-db820c.dts index 757afa27424d..d01a512634cf 100644 --- a/arch/arm64/boot/dts/qcom/apq8096-db820c.dts +++ b/arch/arm64/boot/dts/qcom/apq8096-db820c.dts @@ -5,9 +5,1077 @@ /dts-v1/; -#include "apq8096-db820c.dtsi" +#include "msm8996.dtsi" +#include "pm8994.dtsi" +#include "pmi8994.dtsi" +#include +#include +#include +#include +#include + +/* + * GPIO name legend: proper name = the GPIO line is used as GPIO + * NC = not connected (pin out but not routed from the chip to + * anything the board) + * "[PER]" = pin is muxed for [peripheral] (not GPIO) + * LSEC = Low Speed External Connector + * P HSEC = Primary High Speed External Connector + * S HSEC = Secondary High Speed External Connector + * J14 = Camera Connector + * TP = Test Points + * + * Line names are taken from the schematic "DragonBoard 820c", + * drawing no: LM25-P2751-1 + * + * For the lines routed to the external connectors the + * lines are named after the 96Boards CE Specification 1.0, + * Appendix "Expansion Connector Signal Description". + * + * When the 96Board naming of a line and the schematic name of + * the same line are in conflict, the 96Board specification + * takes precedence, which means that the external UART on the + * LSEC is named UART0 while the schematic and SoC names this + * UART3. This is only for the informational lines i.e. "[FOO]", + * the GPIO named lines "GPIO-A" thru "GPIO-L" are the only + * ones actually used for GPIO. + */ / { model = "Qualcomm Technologies, Inc. DB820c"; compatible = "arrow,apq8096-db820c", "qcom,apq8096-sbc", "qcom,apq8096"; + + aliases { + serial0 = &blsp2_uart2; + serial1 = &blsp2_uart3; + serial2 = &blsp1_uart2; + i2c0 = &blsp1_i2c3; + i2c1 = &blsp2_i2c1; + i2c2 = &blsp2_i2c1; + spi0 = &blsp1_spi1; + spi1 = &blsp2_spi6; + }; + + chosen { + stdout-path = "serial0:115200n8"; + }; + + clocks { + compatible = "simple-bus"; + divclk4: divclk4 { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <32768>; + clock-output-names = "divclk4"; + + pinctrl-names = "default"; + pinctrl-0 = <&divclk4_pin_a>; + }; + + div1_mclk: divclk1 { + compatible = "gpio-gate-clock"; + pinctrl-0 = <&audio_mclk>; + pinctrl-names = "default"; + clocks = <&rpmcc RPM_SMD_DIV_CLK1>; + #clock-cells = <0>; + enable-gpios = <&pm8994_gpios 15 0>; + }; + }; + + gpio_keys { + compatible = "gpio-keys"; + #address-cells = <1>; + #size-cells = <0>; + autorepeat; + + pinctrl-names = "default"; + pinctrl-0 = <&volume_up_gpio>; + + button@0 { + label = "Volume Up"; + linux,code = ; + gpios = <&pm8994_gpios 2 GPIO_ACTIVE_LOW>; + }; + }; + + usb2_id: usb2-id { + compatible = "linux,extcon-usb-gpio"; + id-gpio = <&pmi8994_gpios 6 GPIO_ACTIVE_HIGH>; + pinctrl-names = "default"; + pinctrl-0 = <&usb2_vbus_det_gpio>; + }; + + usb3_id: usb3-id { + compatible = "linux,extcon-usb-gpio"; + id-gpio = <&pm8994_gpios 22 GPIO_ACTIVE_HIGH>; + pinctrl-names = "default"; + pinctrl-0 = <&usb3_vbus_det_gpio>; + }; + + vph_pwr: vph-pwr-regulator { + compatible = "regulator-fixed"; + regulator-name = "vph_pwr"; + regulator-always-on; + regulator-boot-on; + + regulator-min-microvolt = <3700000>; + regulator-max-microvolt = <3700000>; + }; + + wlan_en: wlan-en-1-8v { + pinctrl-names = "default"; + pinctrl-0 = <&wlan_en_gpios>; + compatible = "regulator-fixed"; + regulator-name = "wlan-en-regulator"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + + gpio = <&pm8994_gpios 8 0>; + + /* WLAN card specific delay */ + startup-delay-us = <70000>; + enable-active-high; + }; +}; + +&blsp1_i2c3 { + /* On Low speed expansion */ + label = "LS-I2C0"; + status = "okay"; +}; + +&blsp1_spi1 { + /* On Low speed expansion */ + label = "LS-SPI0"; + status = "okay"; +}; + +&blsp1_uart2 { + label = "BT-UART"; + status = "okay"; + + bluetooth { + compatible = "qcom,qca6174-bt"; + + /* bt_disable_n gpio */ + enable-gpios = <&pm8994_gpios 19 GPIO_ACTIVE_HIGH>; + + clocks = <&divclk4>; + }; +}; + +&adsp_pil { + status = "okay"; +}; + +&blsp2_i2c1 { + /* On High speed expansion */ + label = "HS-I2C2"; + status = "okay"; +}; + +&blsp2_i2c1 { + /* On Low speed expansion */ + label = "LS-I2C1"; + status = "okay"; +}; + +&blsp2_spi6 { + /* On High speed expansion */ + label = "HS-SPI1"; + status = "okay"; +}; + +&blsp2_uart2 { + label = "LS-UART1"; + status = "okay"; + pinctrl-names = "default", "sleep"; + pinctrl-0 = <&blsp2_uart2_2pins_default>; + pinctrl-1 = <&blsp2_uart2_2pins_sleep>; +}; + +&blsp2_uart3 { + label = "LS-UART0"; + status = "disabled"; + pinctrl-names = "default", "sleep"; + pinctrl-0 = <&blsp2_uart3_4pins_default>; + pinctrl-1 = <&blsp2_uart3_4pins_sleep>; +}; + +&camss { + vdda-supply = <&vreg_l2a_1p25>; +}; + +&gpu { + status = "okay"; +}; + +&hdmi { + status = "okay"; + + pinctrl-names = "default", "sleep"; + pinctrl-0 = <&hdmi_hpd_active &hdmi_ddc_active>; + pinctrl-1 = <&hdmi_hpd_suspend &hdmi_ddc_suspend>; + + core-vdda-supply = <&vreg_l12a_1p8>; + core-vcc-supply = <&vreg_s4a_1p8>; +}; + +&hdmi_phy { + status = "okay"; + + vddio-supply = <&vreg_l12a_1p8>; + vcca-supply = <&vreg_l28a_0p925>; + #phy-cells = <0>; +}; + +&hsusb_phy1 { + status = "okay"; + + vdda-pll-supply = <&vreg_l12a_1p8>; + vdda-phy-dpdm-supply = <&vreg_l24a_3p075>; +}; + +&hsusb_phy2 { + status = "okay"; + + vdda-pll-supply = <&vreg_l12a_1p8>; + vdda-phy-dpdm-supply = <&vreg_l24a_3p075>; +}; + +&mdp { + status = "okay"; +}; + +&mdss { + status = "okay"; +}; + +&mmcc { + vdd-gfx-supply = <&vdd_gfx>; +}; + +&pm8994_resin { + status = "okay"; + linux,code = ; +}; + +&tlmm { + gpio-line-names = + "[SPI0_DOUT]", /* GPIO_0, BLSP1_SPI_MOSI, LSEC pin 14 */ + "[SPI0_DIN]", /* GPIO_1, BLSP1_SPI_MISO, LSEC pin 10 */ + "[SPI0_CS]", /* GPIO_2, BLSP1_SPI_CS_N, LSEC pin 12 */ + "[SPI0_SCLK]", /* GPIO_3, BLSP1_SPI_CLK, LSEC pin 8 */ + "[UART1_TxD]", /* GPIO_4, BLSP8_UART_TX, LSEC pin 11 */ + "[UART1_RxD]", /* GPIO_5, BLSP8_UART_RX, LSEC pin 13 */ + "[I2C1_SDA]", /* GPIO_6, BLSP8_I2C_SDA, LSEC pin 21 */ + "[I2C1_SCL]", /* GPIO_7, BLSP8_I2C_SCL, LSEC pin 19 */ + "GPIO-H", /* GPIO_8, LCD0_RESET_N, LSEC pin 30 */ + "TP93", /* GPIO_9 */ + "GPIO-G", /* GPIO_10, MDP_VSYNC_P, LSEC pin 29 */ + "[MDP_VSYNC_S]", /* GPIO_11, S HSEC pin 55 */ + "NC", /* GPIO_12 */ + "[CSI0_MCLK]", /* GPIO_13, CAM_MCLK0, P HSEC pin 15 */ + "[CAM_MCLK1]", /* GPIO_14, J14 pin 11 */ + "[CSI1_MCLK]", /* GPIO_15, CAM_MCLK2, P HSEC pin 17 */ + "TP99", /* GPIO_16 */ + "[I2C2_SDA]", /* GPIO_17, CCI_I2C_SDA0, P HSEC pin 34 */ + "[I2C2_SCL]", /* GPIO_18, CCI_I2C_SCL0, P HSEC pin 32 */ + "[CCI_I2C_SDA1]", /* GPIO_19, S HSEC pin 38 */ + "[CCI_I2C_SCL1]", /* GPIO_20, S HSEC pin 36 */ + "FLASH_STROBE_EN", /* GPIO_21, S HSEC pin 5 */ + "FLASH_STROBE_TRIG", /* GPIO_22, S HSEC pin 1 */ + "GPIO-K", /* GPIO_23, CAM2_RST_N, LSEC pin 33 */ + "GPIO-D", /* GPIO_24, LSEC pin 26 */ + "GPIO-I", /* GPIO_25, CAM0_RST_N, LSEC pin 31 */ + "GPIO-J", /* GPIO_26, CAM0_STANDBY_N, LSEC pin 32 */ + "BLSP6_I2C_SDA", /* GPIO_27 */ + "BLSP6_I2C_SCL", /* GPIO_28 */ + "GPIO-B", /* GPIO_29, TS0_RESET_N, LSEC pin 24 */ + "GPIO30", /* GPIO_30, S HSEC pin 4 */ + "HDMI_CEC", /* GPIO_31 */ + "HDMI_DDC_CLOCK", /* GPIO_32 */ + "HDMI_DDC_DATA", /* GPIO_33 */ + "HDMI_HOT_PLUG_DETECT", /* GPIO_34 */ + "PCIE0_RST_N", /* GPIO_35 */ + "PCIE0_CLKREQ_N", /* GPIO_36 */ + "PCIE0_WAKE", /* GPIO_37 */ + "SD_CARD_DET_N", /* GPIO_38 */ + "TSIF1_SYNC", /* GPIO_39, S HSEC pin 48 */ + "W_DISABLE_N", /* GPIO_40 */ + "[BLSP9_UART_TX]", /* GPIO_41 */ + "[BLSP9_UART_RX]", /* GPIO_42 */ + "[BLSP2_UART_CTS_N]", /* GPIO_43 */ + "[BLSP2_UART_RFR_N]", /* GPIO_44 */ + "[BLSP3_UART_TX]", /* GPIO_45 */ + "[BLSP3_UART_RX]", /* GPIO_46 */ + "[I2C0_SDA]", /* GPIO_47, LS_I2C0_SDA, LSEC pin 17 */ + "[I2C0_SCL]", /* GPIO_48, LS_I2C0_SCL, LSEC pin 15 */ + "[UART0_TxD]", /* GPIO_49, BLSP9_UART_TX, LSEC pin 5 */ + "[UART0_RxD]", /* GPIO_50, BLSP9_UART_RX, LSEC pin 7 */ + "[UART0_CTS]", /* GPIO_51, BLSP9_UART_CTS_N, LSEC pin 3 */ + "[UART0_RTS]", /* GPIO_52, BLSP9_UART_RFR_N, LSEC pin 9 */ + "[CODEC_INT1_N]", /* GPIO_53 */ + "[CODEC_INT2_N]", /* GPIO_54 */ + "[BLSP7_I2C_SDA]", /* GPIO_55 */ + "[BLSP7_I2C_SCL]", /* GPIO_56 */ + "MI2S_MCLK", /* GPIO_57, S HSEC pin 3 */ + "[PCM_CLK]", /* GPIO_58, QUA_MI2S_SCK, LSEC pin 18 */ + "[PCM_FS]", /* GPIO_59, QUA_MI2S_WS, LSEC pin 16 */ + "[PCM_DO]", /* GPIO_60, QUA_MI2S_DATA0, LSEC pin 20 */ + "[PCM_DI]", /* GPIO_61, QUA_MI2S_DATA1, LSEC pin 22 */ + "GPIO-E", /* GPIO_62, LSEC pin 27 */ + "TP87", /* GPIO_63 */ + "[CODEC_RST_N]", /* GPIO_64 */ + "[PCM1_CLK]", /* GPIO_65 */ + "[PCM1_SYNC]", /* GPIO_66 */ + "[PCM1_DIN]", /* GPIO_67 */ + "[PCM1_DOUT]", /* GPIO_68 */ + "AUDIO_REF_CLK", /* GPIO_69 */ + "SLIMBUS_CLK", /* GPIO_70 */ + "SLIMBUS_DATA0", /* GPIO_71 */ + "SLIMBUS_DATA1", /* GPIO_72 */ + "NC", /* GPIO_73 */ + "NC", /* GPIO_74 */ + "NC", /* GPIO_75 */ + "NC", /* GPIO_76 */ + "TP94", /* GPIO_77 */ + "NC", /* GPIO_78 */ + "TP95", /* GPIO_79 */ + "GPIO-A", /* GPIO_80, MEMS_RESET_N, LSEC pin 23 */ + "TP88", /* GPIO_81 */ + "TP89", /* GPIO_82 */ + "TP90", /* GPIO_83 */ + "TP91", /* GPIO_84 */ + "[SD_DAT0]", /* GPIO_85, BLSP12_SPI_MOSI, P HSEC pin 1 */ + "[SD_CMD]", /* GPIO_86, BLSP12_SPI_MISO, P HSEC pin 11 */ + "[SD_DAT3]", /* GPIO_87, BLSP12_SPI_CS_N, P HSEC pin 7 */ + "[SD_SCLK]", /* GPIO_88, BLSP12_SPI_CLK, P HSEC pin 9 */ + "TSIF1_CLK", /* GPIO_89, S HSEC pin 42 */ + "TSIF1_EN", /* GPIO_90, S HSEC pin 46 */ + "TSIF1_DATA", /* GPIO_91, S HSEC pin 44 */ + "NC", /* GPIO_92 */ + "TSIF2_CLK", /* GPIO_93, S HSEC pin 52 */ + "TSIF2_EN", /* GPIO_94, S HSEC pin 56 */ + "TSIF2_DATA", /* GPIO_95, S HSEC pin 54 */ + "TSIF2_SYNC", /* GPIO_96, S HSEC pin 58 */ + "NC", /* GPIO_97 */ + "CAM1_STANDBY_N", /* GPIO_98 */ + "NC", /* GPIO_99 */ + "NC", /* GPIO_100 */ + "[LCD1_RESET_N]", /* GPIO_101, S HSEC pin 51 */ + "BOOT_CONFIG1", /* GPIO_102 */ + "USB_HUB_RESET", /* GPIO_103 */ + "CAM1_RST_N", /* GPIO_104 */ + "NC", /* GPIO_105 */ + "NC", /* GPIO_106 */ + "NC", /* GPIO_107 */ + "NC", /* GPIO_108 */ + "NC", /* GPIO_109 */ + "NC", /* GPIO_110 */ + "NC", /* GPIO_111 */ + "NC", /* GPIO_112 */ + "PMI8994_BUA", /* GPIO_113 */ + "PCIE2_RST_N", /* GPIO_114 */ + "PCIE2_CLKREQ_N", /* GPIO_115 */ + "PCIE2_WAKE", /* GPIO_116 */ + "SSC_IRQ_0", /* GPIO_117 */ + "SSC_IRQ_1", /* GPIO_118 */ + "SSC_IRQ_2", /* GPIO_119 */ + "NC", /* GPIO_120 */ + "GPIO121", /* GPIO_121, S HSEC pin 2 */ + "NC", /* GPIO_122 */ + "SSC_IRQ_6", /* GPIO_123 */ + "SSC_IRQ_7", /* GPIO_124 */ + "GPIO-C", /* GPIO_125, TS_INT0, LSEC pin 25 */ + "BOOT_CONFIG5", /* GPIO_126 */ + "NC", /* GPIO_127 */ + "NC", /* GPIO_128 */ + "BOOT_CONFIG7", /* GPIO_129 */ + "PCIE1_RST_N", /* GPIO_130 */ + "PCIE1_CLKREQ_N", /* GPIO_131 */ + "PCIE1_WAKE", /* GPIO_132 */ + "GPIO-L", /* GPIO_133, CAM2_STANDBY_N, LSEC pin 34 */ + "NC", /* GPIO_134 */ + "NC", /* GPIO_135 */ + "BOOT_CONFIG8", /* GPIO_136 */ + "NC", /* GPIO_137 */ + "NC", /* GPIO_138 */ + "GPS_SSBI2", /* GPIO_139 */ + "GPS_SSBI1", /* GPIO_140 */ + "NC", /* GPIO_141 */ + "NC", /* GPIO_142 */ + "NC", /* GPIO_143 */ + "BOOT_CONFIG6", /* GPIO_144 */ + "NC", /* GPIO_145 */ + "NC", /* GPIO_146 */ + "NC", /* GPIO_147 */ + "NC", /* GPIO_148 */ + "NC"; /* GPIO_149 */ + + sdc2_cd_on: sdc2_cd_on { + mux { + pins = "gpio38"; + function = "gpio"; + }; + + config { + pins = "gpio38"; + bias-pull-up; /* pull up */ + drive-strength = <16>; /* 16 MA */ + }; + }; + + sdc2_cd_off: sdc2_cd_off { + mux { + pins = "gpio38"; + function = "gpio"; + }; + + config { + pins = "gpio38"; + bias-pull-up; /* pull up */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + hdmi_hpd_active: hdmi_hpd_active { + mux { + pins = "gpio34"; + function = "hdmi_hot"; + }; + + config { + pins = "gpio34"; + bias-pull-down; + drive-strength = <16>; + }; + }; + + hdmi_hpd_suspend: hdmi_hpd_suspend { + mux { + pins = "gpio34"; + function = "hdmi_hot"; + }; + + config { + pins = "gpio34"; + bias-pull-down; + drive-strength = <2>; + }; + }; + + hdmi_ddc_active: hdmi_ddc_active { + mux { + pins = "gpio32", "gpio33"; + function = "hdmi_ddc"; + }; + + config { + pins = "gpio32", "gpio33"; + drive-strength = <2>; + bias-pull-up; + }; + }; + + hdmi_ddc_suspend: hdmi_ddc_suspend { + mux { + pins = "gpio32", "gpio33"; + function = "hdmi_ddc"; + }; + + config { + pins = "gpio32", "gpio33"; + drive-strength = <2>; + bias-pull-down; + }; + }; +}; + +&pcie0 { + status = "okay"; + perst-gpio = <&tlmm 35 GPIO_ACTIVE_LOW>; + vddpe-3v3-supply = <&wlan_en>; + vdda-supply = <&vreg_l28a_0p925>; +}; + +&pcie1 { + status = "okay"; + perst-gpio = <&tlmm 130 GPIO_ACTIVE_LOW>; + vdda-supply = <&vreg_l28a_0p925>; +}; + +&pcie2 { + status = "okay"; + perst-gpio = <&tlmm 114 GPIO_ACTIVE_LOW>; + vdda-supply = <&vreg_l28a_0p925>; +}; + +&pcie_phy { + status = "okay"; + + vdda-phy-supply = <&vreg_l28a_0p925>; + vdda-pll-supply = <&vreg_l12a_1p8>; +}; + +&pm8994_gpios { + gpio-line-names = + "NC", + "KEY_VOLP_N", + "NC", + "BL1_PWM", + "GPIO-F", /* BL0_PWM, LSEC pin 28 */ + "BL1_EN", + "NC", + "WLAN_EN", + "NC", + "NC", + "NC", + "NC", + "NC", + "NC", + "DIVCLK1", + "DIVCLK2", + "DIVCLK3", + "DIVCLK4", + "BT_EN", + "PMIC_SLB", + "PMIC_BUA", + "USB_VBUS_DET"; + + pinctrl-names = "default"; + pinctrl-0 = <&ls_exp_gpio_f &bt_en_gpios>; + + ls_exp_gpio_f: pm8994_gpio5 { + pinconf { + pins = "gpio5"; + output-low; + power-source = <2>; // PM8994_GPIO_S4, 1.8V + }; + }; + + bt_en_gpios: bt_en_gpios { + pinconf { + pins = "gpio19"; + function = PMIC_GPIO_FUNC_NORMAL; + output-low; + power-source = ; // 1.8V + qcom,drive-strength = ; + bias-pull-down; + }; + }; + + wlan_en_gpios: wlan_en_gpios { + pinconf { + pins = "gpio8"; + function = PMIC_GPIO_FUNC_NORMAL; + output-low; + power-source = ; // 1.8V + qcom,drive-strength = ; + bias-pull-down; + }; + }; + + audio_mclk: clk_div1 { + pinconf { + pins = "gpio15"; + function = "func1"; + power-source = ; // 1.8V + }; + }; + + volume_up_gpio: pm8996_gpio2 { + pinconf { + pins = "gpio2"; + function = "normal"; + input-enable; + drive-push-pull; + bias-pull-up; + qcom,drive-strength = ; + power-source = ; // 1.8V + }; + }; + + divclk4_pin_a: divclk4 { + pinconf { + pins = "gpio18"; + function = PMIC_GPIO_FUNC_FUNC2; + + bias-disable; + power-source = ; + }; + }; + + usb3_vbus_det_gpio: pm8996_gpio22 { + pinconf { + pins = "gpio22"; + function = PMIC_GPIO_FUNC_NORMAL; + input-enable; + bias-pull-down; + qcom,drive-strength = ; + power-source = ; // 1.8V + }; + }; +}; + +&pm8994_mpps { + gpio-line-names = + "VDDPX_BIAS", + "WIFI_LED", + "NC", + "BT_LED", + "PM_MPP05", + "PM_MPP06", + "PM_MPP07", + "NC"; +}; + +&pm8994_spmi_regulators { + qcom,saw-reg = <&saw3>; + s9 { + qcom,saw-slave; + }; + s10 { + qcom,saw-slave; + }; + s11 { + qcom,saw-leader; + regulator-always-on; + regulator-min-microvolt = <980000>; + regulator-max-microvolt = <980000>; + }; +}; + +&pmi8994_gpios { + gpio-line-names = + "NC", + "SPKR_AMP_EN1", + "SPKR_AMP_EN2", + "TP61", + "NC", + "USB2_VBUS_DET", + "NC", + "NC", + "NC", + "NC"; + + usb2_vbus_det_gpio: pmi8996_gpio6 { + pinconf { + pins = "gpio6"; + function = PMIC_GPIO_FUNC_NORMAL; + input-enable; + bias-pull-down; + qcom,drive-strength = ; + power-source = ; // 1.8V + }; + }; +}; + +&pmi8994_spmi_regulators { + vdd_gfx: s2@1700 { + reg = <0x1700 0x100>; + regulator-name = "VDD_GFX"; + regulator-min-microvolt = <980000>; + regulator-max-microvolt = <980000>; + }; +}; + +&rpm_requests { + pm8994-regulators { + compatible = "qcom,rpm-pm8994-regulators"; + + vdd_s1-supply = <&vph_pwr>; + vdd_s2-supply = <&vph_pwr>; + vdd_s3-supply = <&vph_pwr>; + vdd_s4-supply = <&vph_pwr>; + vdd_s5-supply = <&vph_pwr>; + vdd_s6-supply = <&vph_pwr>; + vdd_s7-supply = <&vph_pwr>; + vdd_s8-supply = <&vph_pwr>; + vdd_s9-supply = <&vph_pwr>; + vdd_s10-supply = <&vph_pwr>; + vdd_s11-supply = <&vph_pwr>; + vdd_s12-supply = <&vph_pwr>; + vdd_l1-supply = <&vreg_s1b_1p025>; + vdd_l2_l26_l28-supply = <&vreg_s3a_1p3>; + vdd_l3_l11-supply = <&vreg_s3a_1p3>; + vdd_l4_l27_l31-supply = <&vreg_s3a_1p3>; + vdd_l5_l7-supply = <&vreg_s5a_2p15>; + vdd_l6_l12_l32-supply = <&vreg_s5a_2p15>; + vdd_l8_l16_l30-supply = <&vph_pwr>; + vdd_l9_l10_l18_l22-supply = <&vph_pwr_bbyp>; + vdd_l13_l19_l23_l24-supply = <&vph_pwr_bbyp>; + vdd_l14_l15-supply = <&vreg_s5a_2p15>; + vdd_l17_l29-supply = <&vph_pwr_bbyp>; + vdd_l20_l21-supply = <&vph_pwr_bbyp>; + vdd_l25-supply = <&vreg_s3a_1p3>; + vdd_lvs1_lvs2-supply = <&vreg_s4a_1p8>; + + vreg_s3a_1p3: s3 { + regulator-name = "vreg_s3a_1p3"; + regulator-min-microvolt = <1300000>; + regulator-max-microvolt = <1300000>; + }; + + /** + * 1.8v required on LS expansion + * for mezzanine boards + */ + vreg_s4a_1p8: s4 { + regulator-name = "vreg_s4a_1p8"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-always-on; + }; + vreg_s5a_2p15: s5 { + regulator-name = "vreg_s5a_2p15"; + regulator-min-microvolt = <2150000>; + regulator-max-microvolt = <2150000>; + }; + vreg_s7a_1p0: s7 { + regulator-name = "vreg_s7a_1p0"; + regulator-min-microvolt = <800000>; + regulator-max-microvolt = <800000>; + }; + + vreg_l1a_1p0: l1 { + regulator-name = "vreg_l1a_1p0"; + regulator-min-microvolt = <1000000>; + regulator-max-microvolt = <1000000>; + }; + vreg_l2a_1p25: l2 { + regulator-name = "vreg_l2a_1p25"; + regulator-min-microvolt = <1250000>; + regulator-max-microvolt = <1250000>; + }; + vreg_l3a_0p875: l3 { + regulator-name = "vreg_l3a_0p875"; + regulator-min-microvolt = <850000>; + regulator-max-microvolt = <850000>; + }; + vreg_l4a_1p225: l4 { + regulator-name = "vreg_l4a_1p225"; + regulator-min-microvolt = <1225000>; + regulator-max-microvolt = <1225000>; + }; + vreg_l6a_1p2: l6 { + regulator-name = "vreg_l6a_1p2"; + regulator-min-microvolt = <1200000>; + regulator-max-microvolt = <1200000>; + }; + vreg_l8a_1p8: l8 { + regulator-name = "vreg_l8a_1p8"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + }; + vreg_l9a_1p8: l9 { + regulator-name = "vreg_l9a_1p8"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + }; + vreg_l10a_1p8: l10 { + regulator-name = "vreg_l10a_1p8"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + }; + vreg_l11a_1p15: l11 { + regulator-name = "vreg_l11a_1p15"; + regulator-min-microvolt = <1150000>; + regulator-max-microvolt = <1150000>; + }; + vreg_l12a_1p8: l12 { + regulator-name = "vreg_l12a_1p8"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + }; + vreg_l13a_2p95: l13 { + regulator-name = "vreg_l13a_2p95"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <2950000>; + }; + vreg_l14a_1p8: l14 { + regulator-name = "vreg_l14a_1p8"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + }; + vreg_l15a_1p8: l15 { + regulator-name = "vreg_l15a_1p8"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + }; + vreg_l16a_2p7: l16 { + regulator-name = "vreg_l16a_2p7"; + regulator-min-microvolt = <2700000>; + regulator-max-microvolt = <2700000>; + }; + vreg_l17a_2p8: l17 { + regulator-name = "vreg_l17a_2p8"; + regulator-min-microvolt = <2500000>; + regulator-max-microvolt = <2500000>; + }; + vreg_l18a_2p85: l18 { + regulator-name = "vreg_l18a_2p85"; + regulator-min-microvolt = <2700000>; + regulator-max-microvolt = <2900000>; + }; + vreg_l19a_2p8: l19 { + regulator-name = "vreg_l19a_2p8"; + regulator-min-microvolt = <3000000>; + regulator-max-microvolt = <3000000>; + }; + vreg_l20a_2p95: l20 { + regulator-name = "vreg_l20a_2p95"; + regulator-min-microvolt = <2950000>; + regulator-max-microvolt = <2950000>; + regulator-allow-set-load; + }; + vreg_l21a_2p95: l21 { + regulator-name = "vreg_l21a_2p95"; + regulator-min-microvolt = <2950000>; + regulator-max-microvolt = <2950000>; + regulator-allow-set-load; + regulator-system-load = <200000>; + }; + vreg_l22a_3p0: l22 { + regulator-name = "vreg_l22a_3p0"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + }; + vreg_l23a_2p8: l23 { + regulator-name = "vreg_l23a_2p8"; + regulator-min-microvolt = <2800000>; + regulator-max-microvolt = <2800000>; + }; + vreg_l24a_3p075: l24 { + regulator-name = "vreg_l24a_3p075"; + regulator-min-microvolt = <3075000>; + regulator-max-microvolt = <3075000>; + }; + vreg_l25a_1p2: l25 { + regulator-name = "vreg_l25a_1p2"; + regulator-min-microvolt = <1200000>; + regulator-max-microvolt = <1200000>; + regulator-allow-set-load; + }; + vreg_l26a_0p8: l27 { + regulator-name = "vreg_l26a_0p8"; + regulator-min-microvolt = <1000000>; + regulator-max-microvolt = <1000000>; + }; + vreg_l28a_0p925: l28 { + regulator-name = "vreg_l28a_0p925"; + regulator-min-microvolt = <925000>; + regulator-max-microvolt = <925000>; + regulator-allow-set-load; + }; + vreg_l29a_2p8: l29 { + regulator-name = "vreg_l29a_2p8"; + regulator-min-microvolt = <2800000>; + regulator-max-microvolt = <2800000>; + }; + vreg_l30a_1p8: l30 { + regulator-name = "vreg_l30a_1p8"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + }; + vreg_l32a_1p8: l32 { + regulator-name = "vreg_l32a_1p8"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + }; + + vreg_lvs1a_1p8: lvs1 { + regulator-name = "vreg_lvs1a_1p8"; + }; + + vreg_lvs2a_1p8: lvs2 { + regulator-name = "vreg_lvs2a_1p8"; + }; + }; + + pmi8994-regulators { + compatible = "qcom,rpm-pmi8994-regulators"; + + vdd_s1-supply = <&vph_pwr>; + vdd_s2-supply = <&vph_pwr>; + vdd_s3-supply = <&vph_pwr>; + vdd_bst_byp-supply = <&vph_pwr>; + + vph_pwr_bbyp: boost-bypass { + regulator-name = "vph_pwr_bbyp"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + }; + + vreg_s1b_1p025: s1 { + regulator-name = "vreg_s1b_1p025"; + regulator-min-microvolt = <1025000>; + regulator-max-microvolt = <1025000>; + }; + }; +}; + +&sdhc2 { + /* External SD card */ + pinctrl-names = "default", "sleep"; + pinctrl-0 = <&sdc2_state_on &sdc2_cd_on>; + pinctrl-1 = <&sdc2_state_off &sdc2_cd_off>; + cd-gpios = <&tlmm 38 GPIO_ACTIVE_LOW>; + vmmc-supply = <&vreg_l21a_2p95>; + vqmmc-supply = <&vreg_l13a_2p95>; + status = "okay"; +}; + +&q6asmdai { + dai@0 { + reg = <0>; + }; + + dai@1 { + reg = <1>; + }; + + dai@2 { + reg = <2>; + }; +}; + +&sound { + compatible = "qcom,apq8096-sndcard"; + model = "DB820c"; + audio-routing = "RX_BIAS", "MCLK", + "MM_DL1", "MultiMedia1 Playback", + "MM_DL2", "MultiMedia2 Playback", + "MultiMedia3 Capture", "MM_UL3"; + + mm1-dai-link { + link-name = "MultiMedia1"; + cpu { + sound-dai = <&q6asmdai MSM_FRONTEND_DAI_MULTIMEDIA1>; + }; + }; + + mm2-dai-link { + link-name = "MultiMedia2"; + cpu { + sound-dai = <&q6asmdai MSM_FRONTEND_DAI_MULTIMEDIA2>; + }; + }; + + mm3-dai-link { + link-name = "MultiMedia3"; + cpu { + sound-dai = <&q6asmdai MSM_FRONTEND_DAI_MULTIMEDIA3>; + }; + }; + + hdmi-dai-link { + link-name = "HDMI"; + cpu { + sound-dai = <&q6afedai HDMI_RX>; + }; + + platform { + sound-dai = <&q6routing>; + }; + + codec { + sound-dai = <&hdmi 0>; + }; + }; + + slim-dai-link { + link-name = "SLIM Playback"; + cpu { + sound-dai = <&q6afedai SLIMBUS_6_RX>; + }; + + platform { + sound-dai = <&q6routing>; + }; + + codec { + sound-dai = <&wcd9335 6>; + }; + }; + + slimcap-dai-link { + link-name = "SLIM Capture"; + cpu { + sound-dai = <&q6afedai SLIMBUS_0_TX>; + }; + + platform { + sound-dai = <&q6routing>; + }; + + codec { + sound-dai = <&wcd9335 1>; + }; + }; +}; + +&ufsphy { + status = "okay"; + + vdda-phy-supply = <&vreg_l28a_0p925>; + vdda-pll-supply = <&vreg_l12a_1p8>; + vddp-ref-clk-supply = <&vreg_l25a_1p2>; +}; + +&ufshc { + status = "okay"; + + vcc-supply = <&vreg_l20a_2p95>; + vccq-supply = <&vreg_l25a_1p2>; + vccq2-supply = <&vreg_s4a_1p8>; + + vcc-max-microamp = <600000>; + vccq-max-microamp = <450000>; + vccq2-max-microamp = <450000>; +}; + +&usb2 { + status = "okay"; + extcon = <&usb2_id>; + + dwc3@7600000 { + extcon = <&usb2_id>; + dr_mode = "otg"; + maximum-speed = "high-speed"; + }; +}; + +&usb3 { + status = "okay"; + extcon = <&usb3_id>; + + dwc3@6a00000 { + extcon = <&usb3_id>; + dr_mode = "otg"; + }; +}; + +&usb3phy { + status = "okay"; + + vdda-phy-supply = <&vreg_l28a_0p925>; + vdda-pll-supply = <&vreg_l12a_1p8>; + +}; + +&venus { + status = "okay"; +}; + +&wcd9335 { + clock-names = "mclk", "slimbus"; + clocks = <&div1_mclk>, + <&rpmcc RPM_SMD_BB_CLK1>; + + vdd-buck-supply = <&vreg_s4a_1p8>; + vdd-buck-sido-supply = <&vreg_s4a_1p8>; + vdd-tx-supply = <&vreg_s4a_1p8>; + vdd-rx-supply = <&vreg_s4a_1p8>; + vdd-io-supply = <&vreg_s4a_1p8>; }; diff --git a/arch/arm64/boot/dts/qcom/apq8096-db820c.dtsi b/arch/arm64/boot/dts/qcom/apq8096-db820c.dtsi deleted file mode 100644 index 51e17094d7b1..000000000000 --- a/arch/arm64/boot/dts/qcom/apq8096-db820c.dtsi +++ /dev/null @@ -1,1105 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * Copyright (c) 2014-2016, The Linux Foundation. All rights reserved. - */ - -#include "msm8996.dtsi" -#include "pm8994.dtsi" -#include "pmi8994.dtsi" -#include -#include -#include -#include -#include - -/* - * GPIO name legend: proper name = the GPIO line is used as GPIO - * NC = not connected (pin out but not routed from the chip to - * anything the board) - * "[PER]" = pin is muxed for [peripheral] (not GPIO) - * LSEC = Low Speed External Connector - * P HSEC = Primary High Speed External Connector - * S HSEC = Secondary High Speed External Connector - * J14 = Camera Connector - * TP = Test Points - * - * Line names are taken from the schematic "DragonBoard 820c", - * drawing no: LM25-P2751-1 - * - * For the lines routed to the external connectors the - * lines are named after the 96Boards CE Specification 1.0, - * Appendix "Expansion Connector Signal Description". - * - * When the 96Board naming of a line and the schematic name of - * the same line are in conflict, the 96Board specification - * takes precedence, which means that the external UART on the - * LSEC is named UART0 while the schematic and SoC names this - * UART3. This is only for the informational lines i.e. "[FOO]", - * the GPIO named lines "GPIO-A" thru "GPIO-L" are the only - * ones actually used for GPIO. - */ - -/ { - aliases { - serial0 = &blsp2_uart2; - serial1 = &blsp2_uart3; - serial2 = &blsp1_uart2; - i2c0 = &blsp1_i2c3; - i2c1 = &blsp2_i2c1; - i2c2 = &blsp2_i2c1; - spi0 = &blsp1_spi1; - spi1 = &blsp2_spi6; - }; - - chosen { - stdout-path = "serial0:115200n8"; - }; - - clocks { - compatible = "simple-bus"; - divclk4: divclk4 { - compatible = "fixed-clock"; - #clock-cells = <0>; - clock-frequency = <32768>; - clock-output-names = "divclk4"; - - pinctrl-names = "default"; - pinctrl-0 = <&divclk4_pin_a>; - }; - - div1_mclk: divclk1 { - compatible = "gpio-gate-clock"; - pinctrl-0 = <&audio_mclk>; - pinctrl-names = "default"; - clocks = <&rpmcc RPM_SMD_DIV_CLK1>; - #clock-cells = <0>; - enable-gpios = <&pm8994_gpios 15 0>; - }; - }; - - gpio_keys { - compatible = "gpio-keys"; - #address-cells = <1>; - #size-cells = <0>; - autorepeat; - - pinctrl-names = "default"; - pinctrl-0 = <&volume_up_gpio>; - - button@0 { - label = "Volume Up"; - linux,code = ; - gpios = <&pm8994_gpios 2 GPIO_ACTIVE_LOW>; - }; - }; - - usb2_id: usb2-id { - compatible = "linux,extcon-usb-gpio"; - id-gpio = <&pmi8994_gpios 6 GPIO_ACTIVE_HIGH>; - pinctrl-names = "default"; - pinctrl-0 = <&usb2_vbus_det_gpio>; - }; - - usb3_id: usb3-id { - compatible = "linux,extcon-usb-gpio"; - id-gpio = <&pm8994_gpios 22 GPIO_ACTIVE_HIGH>; - pinctrl-names = "default"; - pinctrl-0 = <&usb3_vbus_det_gpio>; - }; - - vph_pwr: vph-pwr-regulator { - compatible = "regulator-fixed"; - regulator-name = "vph_pwr"; - regulator-always-on; - regulator-boot-on; - - regulator-min-microvolt = <3700000>; - regulator-max-microvolt = <3700000>; - }; - - wlan_en: wlan-en-1-8v { - pinctrl-names = "default"; - pinctrl-0 = <&wlan_en_gpios>; - compatible = "regulator-fixed"; - regulator-name = "wlan-en-regulator"; - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <1800000>; - - gpio = <&pm8994_gpios 8 0>; - - /* WLAN card specific delay */ - startup-delay-us = <70000>; - enable-active-high; - }; -}; - -&blsp1_i2c3 { - /* On Low speed expansion */ - label = "LS-I2C0"; - status = "okay"; -}; - -&blsp1_spi1 { - /* On Low speed expansion */ - label = "LS-SPI0"; - status = "okay"; -}; - -&blsp1_uart2 { - label = "BT-UART"; - status = "okay"; - pinctrl-names = "default", "sleep"; - pinctrl-0 = <&blsp1_uart2_default>; - pinctrl-1 = <&blsp1_uart2_sleep>; - - bluetooth { - compatible = "qcom,qca6174-bt"; - - /* bt_disable_n gpio */ - enable-gpios = <&pm8994_gpios 19 GPIO_ACTIVE_HIGH>; - - clocks = <&divclk4>; - }; -}; - -&adsp_pil { - status = "okay"; -}; - -&blsp2_i2c1 { - /* On High speed expansion */ - label = "HS-I2C2"; - status = "okay"; -}; - -&blsp2_i2c1 { - /* On Low speed expansion */ - label = "LS-I2C1"; - status = "okay"; -}; - -&blsp2_spi6 { - /* On High speed expansion */ - label = "HS-SPI1"; - status = "okay"; -}; - -&blsp2_uart2 { - label = "LS-UART1"; - status = "okay"; - pinctrl-names = "default", "sleep"; - pinctrl-0 = <&blsp2_uart2_2pins_default>; - pinctrl-1 = <&blsp2_uart2_2pins_sleep>; -}; - -&blsp2_uart3 { - label = "LS-UART0"; - status = "disabled"; - pinctrl-names = "default", "sleep"; - pinctrl-0 = <&blsp2_uart3_4pins_default>; - pinctrl-1 = <&blsp2_uart3_4pins_sleep>; -}; - -&camss { - vdda-supply = <&vreg_l2a_1p25>; -}; - -&gpu { - status = "okay"; -}; - -&hdmi { - status = "okay"; - - pinctrl-names = "default", "sleep"; - pinctrl-0 = <&hdmi_hpd_active &hdmi_ddc_active>; - pinctrl-1 = <&hdmi_hpd_suspend &hdmi_ddc_suspend>; - - core-vdda-supply = <&vreg_l12a_1p8>; - core-vcc-supply = <&vreg_s4a_1p8>; -}; - -&hdmi_phy { - status = "okay"; - - vddio-supply = <&vreg_l12a_1p8>; - vcca-supply = <&vreg_l28a_0p925>; - #phy-cells = <0>; -}; - -&hsusb_phy1 { - status = "okay"; - - vdda-pll-supply = <&vreg_l12a_1p8>; - vdda-phy-dpdm-supply = <&vreg_l24a_3p075>; -}; - -&hsusb_phy2 { - status = "okay"; - - vdda-pll-supply = <&vreg_l12a_1p8>; - vdda-phy-dpdm-supply = <&vreg_l24a_3p075>; -}; - -&mdp { - status = "okay"; -}; - -&mdss { - status = "okay"; -}; - -&mmcc { - vdd-gfx-supply = <&vdd_gfx>; -}; - -&pm8994_resin { - status = "okay"; - linux,code = ; -}; - -&tlmm { - gpio-line-names = - "[SPI0_DOUT]", /* GPIO_0, BLSP1_SPI_MOSI, LSEC pin 14 */ - "[SPI0_DIN]", /* GPIO_1, BLSP1_SPI_MISO, LSEC pin 10 */ - "[SPI0_CS]", /* GPIO_2, BLSP1_SPI_CS_N, LSEC pin 12 */ - "[SPI0_SCLK]", /* GPIO_3, BLSP1_SPI_CLK, LSEC pin 8 */ - "[UART1_TxD]", /* GPIO_4, BLSP8_UART_TX, LSEC pin 11 */ - "[UART1_RxD]", /* GPIO_5, BLSP8_UART_RX, LSEC pin 13 */ - "[I2C1_SDA]", /* GPIO_6, BLSP8_I2C_SDA, LSEC pin 21 */ - "[I2C1_SCL]", /* GPIO_7, BLSP8_I2C_SCL, LSEC pin 19 */ - "GPIO-H", /* GPIO_8, LCD0_RESET_N, LSEC pin 30 */ - "TP93", /* GPIO_9 */ - "GPIO-G", /* GPIO_10, MDP_VSYNC_P, LSEC pin 29 */ - "[MDP_VSYNC_S]", /* GPIO_11, S HSEC pin 55 */ - "NC", /* GPIO_12 */ - "[CSI0_MCLK]", /* GPIO_13, CAM_MCLK0, P HSEC pin 15 */ - "[CAM_MCLK1]", /* GPIO_14, J14 pin 11 */ - "[CSI1_MCLK]", /* GPIO_15, CAM_MCLK2, P HSEC pin 17 */ - "TP99", /* GPIO_16 */ - "[I2C2_SDA]", /* GPIO_17, CCI_I2C_SDA0, P HSEC pin 34 */ - "[I2C2_SCL]", /* GPIO_18, CCI_I2C_SCL0, P HSEC pin 32 */ - "[CCI_I2C_SDA1]", /* GPIO_19, S HSEC pin 38 */ - "[CCI_I2C_SCL1]", /* GPIO_20, S HSEC pin 36 */ - "FLASH_STROBE_EN", /* GPIO_21, S HSEC pin 5 */ - "FLASH_STROBE_TRIG", /* GPIO_22, S HSEC pin 1 */ - "GPIO-K", /* GPIO_23, CAM2_RST_N, LSEC pin 33 */ - "GPIO-D", /* GPIO_24, LSEC pin 26 */ - "GPIO-I", /* GPIO_25, CAM0_RST_N, LSEC pin 31 */ - "GPIO-J", /* GPIO_26, CAM0_STANDBY_N, LSEC pin 32 */ - "BLSP6_I2C_SDA", /* GPIO_27 */ - "BLSP6_I2C_SCL", /* GPIO_28 */ - "GPIO-B", /* GPIO_29, TS0_RESET_N, LSEC pin 24 */ - "GPIO30", /* GPIO_30, S HSEC pin 4 */ - "HDMI_CEC", /* GPIO_31 */ - "HDMI_DDC_CLOCK", /* GPIO_32 */ - "HDMI_DDC_DATA", /* GPIO_33 */ - "HDMI_HOT_PLUG_DETECT", /* GPIO_34 */ - "PCIE0_RST_N", /* GPIO_35 */ - "PCIE0_CLKREQ_N", /* GPIO_36 */ - "PCIE0_WAKE", /* GPIO_37 */ - "SD_CARD_DET_N", /* GPIO_38 */ - "TSIF1_SYNC", /* GPIO_39, S HSEC pin 48 */ - "W_DISABLE_N", /* GPIO_40 */ - "[BLSP9_UART_TX]", /* GPIO_41 */ - "[BLSP9_UART_RX]", /* GPIO_42 */ - "[BLSP2_UART_CTS_N]", /* GPIO_43 */ - "[BLSP2_UART_RFR_N]", /* GPIO_44 */ - "[BLSP3_UART_TX]", /* GPIO_45 */ - "[BLSP3_UART_RX]", /* GPIO_46 */ - "[I2C0_SDA]", /* GPIO_47, LS_I2C0_SDA, LSEC pin 17 */ - "[I2C0_SCL]", /* GPIO_48, LS_I2C0_SCL, LSEC pin 15 */ - "[UART0_TxD]", /* GPIO_49, BLSP9_UART_TX, LSEC pin 5 */ - "[UART0_RxD]", /* GPIO_50, BLSP9_UART_RX, LSEC pin 7 */ - "[UART0_CTS]", /* GPIO_51, BLSP9_UART_CTS_N, LSEC pin 3 */ - "[UART0_RTS]", /* GPIO_52, BLSP9_UART_RFR_N, LSEC pin 9 */ - "[CODEC_INT1_N]", /* GPIO_53 */ - "[CODEC_INT2_N]", /* GPIO_54 */ - "[BLSP7_I2C_SDA]", /* GPIO_55 */ - "[BLSP7_I2C_SCL]", /* GPIO_56 */ - "MI2S_MCLK", /* GPIO_57, S HSEC pin 3 */ - "[PCM_CLK]", /* GPIO_58, QUA_MI2S_SCK, LSEC pin 18 */ - "[PCM_FS]", /* GPIO_59, QUA_MI2S_WS, LSEC pin 16 */ - "[PCM_DO]", /* GPIO_60, QUA_MI2S_DATA0, LSEC pin 20 */ - "[PCM_DI]", /* GPIO_61, QUA_MI2S_DATA1, LSEC pin 22 */ - "GPIO-E", /* GPIO_62, LSEC pin 27 */ - "TP87", /* GPIO_63 */ - "[CODEC_RST_N]", /* GPIO_64 */ - "[PCM1_CLK]", /* GPIO_65 */ - "[PCM1_SYNC]", /* GPIO_66 */ - "[PCM1_DIN]", /* GPIO_67 */ - "[PCM1_DOUT]", /* GPIO_68 */ - "AUDIO_REF_CLK", /* GPIO_69 */ - "SLIMBUS_CLK", /* GPIO_70 */ - "SLIMBUS_DATA0", /* GPIO_71 */ - "SLIMBUS_DATA1", /* GPIO_72 */ - "NC", /* GPIO_73 */ - "NC", /* GPIO_74 */ - "NC", /* GPIO_75 */ - "NC", /* GPIO_76 */ - "TP94", /* GPIO_77 */ - "NC", /* GPIO_78 */ - "TP95", /* GPIO_79 */ - "GPIO-A", /* GPIO_80, MEMS_RESET_N, LSEC pin 23 */ - "TP88", /* GPIO_81 */ - "TP89", /* GPIO_82 */ - "TP90", /* GPIO_83 */ - "TP91", /* GPIO_84 */ - "[SD_DAT0]", /* GPIO_85, BLSP12_SPI_MOSI, P HSEC pin 1 */ - "[SD_CMD]", /* GPIO_86, BLSP12_SPI_MISO, P HSEC pin 11 */ - "[SD_DAT3]", /* GPIO_87, BLSP12_SPI_CS_N, P HSEC pin 7 */ - "[SD_SCLK]", /* GPIO_88, BLSP12_SPI_CLK, P HSEC pin 9 */ - "TSIF1_CLK", /* GPIO_89, S HSEC pin 42 */ - "TSIF1_EN", /* GPIO_90, S HSEC pin 46 */ - "TSIF1_DATA", /* GPIO_91, S HSEC pin 44 */ - "NC", /* GPIO_92 */ - "TSIF2_CLK", /* GPIO_93, S HSEC pin 52 */ - "TSIF2_EN", /* GPIO_94, S HSEC pin 56 */ - "TSIF2_DATA", /* GPIO_95, S HSEC pin 54 */ - "TSIF2_SYNC", /* GPIO_96, S HSEC pin 58 */ - "NC", /* GPIO_97 */ - "CAM1_STANDBY_N", /* GPIO_98 */ - "NC", /* GPIO_99 */ - "NC", /* GPIO_100 */ - "[LCD1_RESET_N]", /* GPIO_101, S HSEC pin 51 */ - "BOOT_CONFIG1", /* GPIO_102 */ - "USB_HUB_RESET", /* GPIO_103 */ - "CAM1_RST_N", /* GPIO_104 */ - "NC", /* GPIO_105 */ - "NC", /* GPIO_106 */ - "NC", /* GPIO_107 */ - "NC", /* GPIO_108 */ - "NC", /* GPIO_109 */ - "NC", /* GPIO_110 */ - "NC", /* GPIO_111 */ - "NC", /* GPIO_112 */ - "PMI8994_BUA", /* GPIO_113 */ - "PCIE2_RST_N", /* GPIO_114 */ - "PCIE2_CLKREQ_N", /* GPIO_115 */ - "PCIE2_WAKE", /* GPIO_116 */ - "SSC_IRQ_0", /* GPIO_117 */ - "SSC_IRQ_1", /* GPIO_118 */ - "SSC_IRQ_2", /* GPIO_119 */ - "NC", /* GPIO_120 */ - "GPIO121", /* GPIO_121, S HSEC pin 2 */ - "NC", /* GPIO_122 */ - "SSC_IRQ_6", /* GPIO_123 */ - "SSC_IRQ_7", /* GPIO_124 */ - "GPIO-C", /* GPIO_125, TS_INT0, LSEC pin 25 */ - "BOOT_CONFIG5", /* GPIO_126 */ - "NC", /* GPIO_127 */ - "NC", /* GPIO_128 */ - "BOOT_CONFIG7", /* GPIO_129 */ - "PCIE1_RST_N", /* GPIO_130 */ - "PCIE1_CLKREQ_N", /* GPIO_131 */ - "PCIE1_WAKE", /* GPIO_132 */ - "GPIO-L", /* GPIO_133, CAM2_STANDBY_N, LSEC pin 34 */ - "NC", /* GPIO_134 */ - "NC", /* GPIO_135 */ - "BOOT_CONFIG8", /* GPIO_136 */ - "NC", /* GPIO_137 */ - "NC", /* GPIO_138 */ - "GPS_SSBI2", /* GPIO_139 */ - "GPS_SSBI1", /* GPIO_140 */ - "NC", /* GPIO_141 */ - "NC", /* GPIO_142 */ - "NC", /* GPIO_143 */ - "BOOT_CONFIG6", /* GPIO_144 */ - "NC", /* GPIO_145 */ - "NC", /* GPIO_146 */ - "NC", /* GPIO_147 */ - "NC", /* GPIO_148 */ - "NC"; /* GPIO_149 */ - - sdc2_cd_on: sdc2_cd_on { - mux { - pins = "gpio38"; - function = "gpio"; - }; - - config { - pins = "gpio38"; - bias-pull-up; /* pull up */ - drive-strength = <16>; /* 16 MA */ - }; - }; - - sdc2_cd_off: sdc2_cd_off { - mux { - pins = "gpio38"; - function = "gpio"; - }; - - config { - pins = "gpio38"; - bias-pull-up; /* pull up */ - drive-strength = <2>; /* 2 MA */ - }; - }; - - blsp1_uart2_default: blsp1_uart2_default { - mux { - pins = "gpio41", "gpio42", "gpio43", "gpio44"; - function = "blsp_uart2"; - }; - - config { - pins = "gpio41", "gpio42", "gpio43", "gpio44"; - drive-strength = <16>; - bias-disable; - }; - }; - - blsp1_uart2_sleep: blsp1_uart2_sleep { - mux { - pins = "gpio41", "gpio42", "gpio43", "gpio44"; - function = "gpio"; - }; - - config { - pins = "gpio41", "gpio42", "gpio43", "gpio44"; - drive-strength = <2>; - bias-disable; - }; - }; - - hdmi_hpd_active: hdmi_hpd_active { - mux { - pins = "gpio34"; - function = "hdmi_hot"; - }; - - config { - pins = "gpio34"; - bias-pull-down; - drive-strength = <16>; - }; - }; - - hdmi_hpd_suspend: hdmi_hpd_suspend { - mux { - pins = "gpio34"; - function = "hdmi_hot"; - }; - - config { - pins = "gpio34"; - bias-pull-down; - drive-strength = <2>; - }; - }; - - hdmi_ddc_active: hdmi_ddc_active { - mux { - pins = "gpio32", "gpio33"; - function = "hdmi_ddc"; - }; - - config { - pins = "gpio32", "gpio33"; - drive-strength = <2>; - bias-pull-up; - }; - }; - - hdmi_ddc_suspend: hdmi_ddc_suspend { - mux { - pins = "gpio32", "gpio33"; - function = "hdmi_ddc"; - }; - - config { - pins = "gpio32", "gpio33"; - drive-strength = <2>; - bias-pull-down; - }; - }; -}; - -&pcie0 { - status = "okay"; - perst-gpio = <&tlmm 35 GPIO_ACTIVE_LOW>; - vddpe-3v3-supply = <&wlan_en>; - vdda-supply = <&vreg_l28a_0p925>; -}; - -&pcie1 { - status = "okay"; - perst-gpio = <&tlmm 130 GPIO_ACTIVE_LOW>; - vdda-supply = <&vreg_l28a_0p925>; -}; - -&pcie2 { - status = "okay"; - perst-gpio = <&tlmm 114 GPIO_ACTIVE_LOW>; - vdda-supply = <&vreg_l28a_0p925>; -}; - -&pcie_phy { - status = "okay"; - - vdda-phy-supply = <&vreg_l28a_0p925>; - vdda-pll-supply = <&vreg_l12a_1p8>; -}; - -&pm8994_gpios { - gpio-line-names = - "NC", - "KEY_VOLP_N", - "NC", - "BL1_PWM", - "GPIO-F", /* BL0_PWM, LSEC pin 28 */ - "BL1_EN", - "NC", - "WLAN_EN", - "NC", - "NC", - "NC", - "NC", - "NC", - "NC", - "DIVCLK1", - "DIVCLK2", - "DIVCLK3", - "DIVCLK4", - "BT_EN", - "PMIC_SLB", - "PMIC_BUA", - "USB_VBUS_DET"; - - pinctrl-names = "default"; - pinctrl-0 = <&ls_exp_gpio_f &bt_en_gpios>; - - ls_exp_gpio_f: pm8994_gpio5 { - pinconf { - pins = "gpio5"; - output-low; - power-source = <2>; // PM8994_GPIO_S4, 1.8V - }; - }; - - bt_en_gpios: bt_en_gpios { - pinconf { - pins = "gpio19"; - function = PMIC_GPIO_FUNC_NORMAL; - output-low; - power-source = ; // 1.8V - qcom,drive-strength = ; - bias-pull-down; - }; - }; - - wlan_en_gpios: wlan_en_gpios { - pinconf { - pins = "gpio8"; - function = PMIC_GPIO_FUNC_NORMAL; - output-low; - power-source = ; // 1.8V - qcom,drive-strength = ; - bias-pull-down; - }; - }; - - audio_mclk: clk_div1 { - pinconf { - pins = "gpio15"; - function = "func1"; - power-source = ; // 1.8V - }; - }; - - volume_up_gpio: pm8996_gpio2 { - pinconf { - pins = "gpio2"; - function = "normal"; - input-enable; - drive-push-pull; - bias-pull-up; - qcom,drive-strength = ; - power-source = ; // 1.8V - }; - }; - - divclk4_pin_a: divclk4 { - pinconf { - pins = "gpio18"; - function = PMIC_GPIO_FUNC_FUNC2; - - bias-disable; - power-source = ; - }; - }; - - usb3_vbus_det_gpio: pm8996_gpio22 { - pinconf { - pins = "gpio22"; - function = PMIC_GPIO_FUNC_NORMAL; - input-enable; - bias-pull-down; - qcom,drive-strength = ; - power-source = ; // 1.8V - }; - }; -}; - -&pm8994_mpps { - gpio-line-names = - "VDDPX_BIAS", - "WIFI_LED", - "NC", - "BT_LED", - "PM_MPP05", - "PM_MPP06", - "PM_MPP07", - "NC"; -}; - -&pm8994_spmi_regulators { - qcom,saw-reg = <&saw3>; - s9 { - qcom,saw-slave; - }; - s10 { - qcom,saw-slave; - }; - s11 { - qcom,saw-leader; - regulator-always-on; - regulator-min-microvolt = <980000>; - regulator-max-microvolt = <980000>; - }; -}; - -&pmi8994_gpios { - gpio-line-names = - "NC", - "SPKR_AMP_EN1", - "SPKR_AMP_EN2", - "TP61", - "NC", - "USB2_VBUS_DET", - "NC", - "NC", - "NC", - "NC"; - - usb2_vbus_det_gpio: pmi8996_gpio6 { - pinconf { - pins = "gpio6"; - function = PMIC_GPIO_FUNC_NORMAL; - input-enable; - bias-pull-down; - qcom,drive-strength = ; - power-source = ; // 1.8V - }; - }; -}; - -&pmi8994_spmi_regulators { - vdd_gfx: s2@1700 { - reg = <0x1700 0x100>; - regulator-name = "VDD_GFX"; - regulator-min-microvolt = <980000>; - regulator-max-microvolt = <980000>; - }; -}; - -&rpm_requests { - pm8994-regulators { - compatible = "qcom,rpm-pm8994-regulators"; - - vdd_s1-supply = <&vph_pwr>; - vdd_s2-supply = <&vph_pwr>; - vdd_s3-supply = <&vph_pwr>; - vdd_s4-supply = <&vph_pwr>; - vdd_s5-supply = <&vph_pwr>; - vdd_s6-supply = <&vph_pwr>; - vdd_s7-supply = <&vph_pwr>; - vdd_s8-supply = <&vph_pwr>; - vdd_s9-supply = <&vph_pwr>; - vdd_s10-supply = <&vph_pwr>; - vdd_s11-supply = <&vph_pwr>; - vdd_s12-supply = <&vph_pwr>; - vdd_l1-supply = <&vreg_s1b_1p025>; - vdd_l2_l26_l28-supply = <&vreg_s3a_1p3>; - vdd_l3_l11-supply = <&vreg_s3a_1p3>; - vdd_l4_l27_l31-supply = <&vreg_s3a_1p3>; - vdd_l5_l7-supply = <&vreg_s5a_2p15>; - vdd_l6_l12_l32-supply = <&vreg_s5a_2p15>; - vdd_l8_l16_l30-supply = <&vph_pwr>; - vdd_l9_l10_l18_l22-supply = <&vph_pwr_bbyp>; - vdd_l13_l19_l23_l24-supply = <&vph_pwr_bbyp>; - vdd_l14_l15-supply = <&vreg_s5a_2p15>; - vdd_l17_l29-supply = <&vph_pwr_bbyp>; - vdd_l20_l21-supply = <&vph_pwr_bbyp>; - vdd_l25-supply = <&vreg_s3a_1p3>; - vdd_lvs1_lvs2-supply = <&vreg_s4a_1p8>; - - vreg_s3a_1p3: s3 { - regulator-name = "vreg_s3a_1p3"; - regulator-min-microvolt = <1300000>; - regulator-max-microvolt = <1300000>; - }; - - /** - * 1.8v required on LS expansion - * for mezzanine boards - */ - vreg_s4a_1p8: s4 { - regulator-name = "vreg_s4a_1p8"; - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <1800000>; - regulator-always-on; - }; - vreg_s5a_2p15: s5 { - regulator-name = "vreg_s5a_2p15"; - regulator-min-microvolt = <2150000>; - regulator-max-microvolt = <2150000>; - }; - vreg_s7a_1p0: s7 { - regulator-name = "vreg_s7a_1p0"; - regulator-min-microvolt = <800000>; - regulator-max-microvolt = <800000>; - }; - - vreg_l1a_1p0: l1 { - regulator-name = "vreg_l1a_1p0"; - regulator-min-microvolt = <1000000>; - regulator-max-microvolt = <1000000>; - }; - vreg_l2a_1p25: l2 { - regulator-name = "vreg_l2a_1p25"; - regulator-min-microvolt = <1250000>; - regulator-max-microvolt = <1250000>; - }; - vreg_l3a_0p875: l3 { - regulator-name = "vreg_l3a_0p875"; - regulator-min-microvolt = <850000>; - regulator-max-microvolt = <850000>; - }; - vreg_l4a_1p225: l4 { - regulator-name = "vreg_l4a_1p225"; - regulator-min-microvolt = <1225000>; - regulator-max-microvolt = <1225000>; - }; - vreg_l6a_1p2: l6 { - regulator-name = "vreg_l6a_1p2"; - regulator-min-microvolt = <1200000>; - regulator-max-microvolt = <1200000>; - }; - vreg_l8a_1p8: l8 { - regulator-name = "vreg_l8a_1p8"; - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <1800000>; - }; - vreg_l9a_1p8: l9 { - regulator-name = "vreg_l9a_1p8"; - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <1800000>; - }; - vreg_l10a_1p8: l10 { - regulator-name = "vreg_l10a_1p8"; - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <1800000>; - }; - vreg_l11a_1p15: l11 { - regulator-name = "vreg_l11a_1p15"; - regulator-min-microvolt = <1150000>; - regulator-max-microvolt = <1150000>; - }; - vreg_l12a_1p8: l12 { - regulator-name = "vreg_l12a_1p8"; - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <1800000>; - }; - vreg_l13a_2p95: l13 { - regulator-name = "vreg_l13a_2p95"; - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <2950000>; - }; - vreg_l14a_1p8: l14 { - regulator-name = "vreg_l14a_1p8"; - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <1800000>; - }; - vreg_l15a_1p8: l15 { - regulator-name = "vreg_l15a_1p8"; - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <1800000>; - }; - vreg_l16a_2p7: l16 { - regulator-name = "vreg_l16a_2p7"; - regulator-min-microvolt = <2700000>; - regulator-max-microvolt = <2700000>; - }; - vreg_l17a_2p8: l17 { - regulator-name = "vreg_l17a_2p8"; - regulator-min-microvolt = <2500000>; - regulator-max-microvolt = <2500000>; - }; - vreg_l18a_2p85: l18 { - regulator-name = "vreg_l18a_2p85"; - regulator-min-microvolt = <2700000>; - regulator-max-microvolt = <2900000>; - }; - vreg_l19a_2p8: l19 { - regulator-name = "vreg_l19a_2p8"; - regulator-min-microvolt = <3000000>; - regulator-max-microvolt = <3000000>; - }; - vreg_l20a_2p95: l20 { - regulator-name = "vreg_l20a_2p95"; - regulator-min-microvolt = <2950000>; - regulator-max-microvolt = <2950000>; - regulator-allow-set-load; - }; - vreg_l21a_2p95: l21 { - regulator-name = "vreg_l21a_2p95"; - regulator-min-microvolt = <2950000>; - regulator-max-microvolt = <2950000>; - regulator-allow-set-load; - regulator-system-load = <200000>; - }; - vreg_l22a_3p0: l22 { - regulator-name = "vreg_l22a_3p0"; - regulator-min-microvolt = <3300000>; - regulator-max-microvolt = <3300000>; - }; - vreg_l23a_2p8: l23 { - regulator-name = "vreg_l23a_2p8"; - regulator-min-microvolt = <2800000>; - regulator-max-microvolt = <2800000>; - }; - vreg_l24a_3p075: l24 { - regulator-name = "vreg_l24a_3p075"; - regulator-min-microvolt = <3075000>; - regulator-max-microvolt = <3075000>; - }; - vreg_l25a_1p2: l25 { - regulator-name = "vreg_l25a_1p2"; - regulator-min-microvolt = <1200000>; - regulator-max-microvolt = <1200000>; - regulator-allow-set-load; - }; - vreg_l26a_0p8: l27 { - regulator-name = "vreg_l26a_0p8"; - regulator-min-microvolt = <1000000>; - regulator-max-microvolt = <1000000>; - }; - vreg_l28a_0p925: l28 { - regulator-name = "vreg_l28a_0p925"; - regulator-min-microvolt = <925000>; - regulator-max-microvolt = <925000>; - regulator-allow-set-load; - }; - vreg_l29a_2p8: l29 { - regulator-name = "vreg_l29a_2p8"; - regulator-min-microvolt = <2800000>; - regulator-max-microvolt = <2800000>; - }; - vreg_l30a_1p8: l30 { - regulator-name = "vreg_l30a_1p8"; - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <1800000>; - }; - vreg_l32a_1p8: l32 { - regulator-name = "vreg_l32a_1p8"; - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <1800000>; - }; - - vreg_lvs1a_1p8: lvs1 { - regulator-name = "vreg_lvs1a_1p8"; - }; - - vreg_lvs2a_1p8: lvs2 { - regulator-name = "vreg_lvs2a_1p8"; - }; - }; - - pmi8994-regulators { - compatible = "qcom,rpm-pmi8994-regulators"; - - vdd_s1-supply = <&vph_pwr>; - vdd_s2-supply = <&vph_pwr>; - vdd_s3-supply = <&vph_pwr>; - vdd_bst_byp-supply = <&vph_pwr>; - - vph_pwr_bbyp: boost-bypass { - regulator-name = "vph_pwr_bbyp"; - regulator-min-microvolt = <3300000>; - regulator-max-microvolt = <3300000>; - }; - - vreg_s1b_1p025: s1 { - regulator-name = "vreg_s1b_1p025"; - regulator-min-microvolt = <1025000>; - regulator-max-microvolt = <1025000>; - }; - }; -}; - -&sdhc2 { - /* External SD card */ - pinctrl-names = "default", "sleep"; - pinctrl-0 = <&sdc2_state_on &sdc2_cd_on>; - pinctrl-1 = <&sdc2_state_off &sdc2_cd_off>; - cd-gpios = <&tlmm 38 GPIO_ACTIVE_LOW>; - vmmc-supply = <&vreg_l21a_2p95>; - vqmmc-supply = <&vreg_l13a_2p95>; - status = "okay"; -}; - -&q6asmdai { - dai@0 { - reg = <0>; - }; - - dai@1 { - reg = <1>; - }; - - dai@2 { - reg = <2>; - }; -}; - -&sound { - compatible = "qcom,apq8096-sndcard"; - model = "DB820c"; - audio-routing = "RX_BIAS", "MCLK", - "MM_DL1", "MultiMedia1 Playback", - "MM_DL2", "MultiMedia2 Playback", - "MultiMedia3 Capture", "MM_UL3"; - - mm1-dai-link { - link-name = "MultiMedia1"; - cpu { - sound-dai = <&q6asmdai MSM_FRONTEND_DAI_MULTIMEDIA1>; - }; - }; - - mm2-dai-link { - link-name = "MultiMedia2"; - cpu { - sound-dai = <&q6asmdai MSM_FRONTEND_DAI_MULTIMEDIA2>; - }; - }; - - mm3-dai-link { - link-name = "MultiMedia3"; - cpu { - sound-dai = <&q6asmdai MSM_FRONTEND_DAI_MULTIMEDIA3>; - }; - }; - - hdmi-dai-link { - link-name = "HDMI"; - cpu { - sound-dai = <&q6afedai HDMI_RX>; - }; - - platform { - sound-dai = <&q6routing>; - }; - - codec { - sound-dai = <&hdmi 0>; - }; - }; - - slim-dai-link { - link-name = "SLIM Playback"; - cpu { - sound-dai = <&q6afedai SLIMBUS_6_RX>; - }; - - platform { - sound-dai = <&q6routing>; - }; - - codec { - sound-dai = <&wcd9335 6>; - }; - }; - - slimcap-dai-link { - link-name = "SLIM Capture"; - cpu { - sound-dai = <&q6afedai SLIMBUS_0_TX>; - }; - - platform { - sound-dai = <&q6routing>; - }; - - codec { - sound-dai = <&wcd9335 1>; - }; - }; -}; - -&ufsphy { - status = "okay"; - - vdda-phy-supply = <&vreg_l28a_0p925>; - vdda-pll-supply = <&vreg_l12a_1p8>; - vddp-ref-clk-supply = <&vreg_l25a_1p2>; -}; - -&ufshc { - status = "okay"; - - vcc-supply = <&vreg_l20a_2p95>; - vccq-supply = <&vreg_l25a_1p2>; - vccq2-supply = <&vreg_s4a_1p8>; - - vcc-max-microamp = <600000>; - vccq-max-microamp = <450000>; - vccq2-max-microamp = <450000>; -}; - -&usb2 { - status = "okay"; - extcon = <&usb2_id>; - - dwc3@7600000 { - extcon = <&usb2_id>; - dr_mode = "otg"; - maximum-speed = "high-speed"; - }; -}; - -&usb3 { - status = "okay"; - extcon = <&usb3_id>; - - dwc3@6a00000 { - extcon = <&usb3_id>; - dr_mode = "otg"; - }; -}; - -&usb3phy { - status = "okay"; - - vdda-phy-supply = <&vreg_l28a_0p925>; - vdda-pll-supply = <&vreg_l12a_1p8>; - -}; - -&venus { - status = "okay"; -}; - -&wcd9335 { - clock-names = "mclk", "slimbus"; - clocks = <&div1_mclk>, - <&rpmcc RPM_SMD_BB_CLK1>; - - vdd-buck-supply = <&vreg_s4a_1p8>; - vdd-buck-sido-supply = <&vreg_s4a_1p8>; - vdd-tx-supply = <&vreg_s4a_1p8>; - vdd-rx-supply = <&vreg_s4a_1p8>; - vdd-io-supply = <&vreg_s4a_1p8>; -}; diff --git a/arch/arm64/boot/dts/qcom/apq8096-ifc6640.dts b/arch/arm64/boot/dts/qcom/apq8096-ifc6640.dts index a57c60070cdc..f0a98ab1616a 100644 --- a/arch/arm64/boot/dts/qcom/apq8096-ifc6640.dts +++ b/arch/arm64/boot/dts/qcom/apq8096-ifc6640.dts @@ -26,7 +26,7 @@ v1p05: v1p05-regulator { compatible = "regulator-fixed"; - reglator-name = "v1p05"; + regulator-name = "v1p05"; regulator-always-on; regulator-boot-on; @@ -38,7 +38,7 @@ v12_poe: v12-poe-regulator { compatible = "regulator-fixed"; - reglator-name = "v12_poe"; + regulator-name = "v12_poe"; regulator-always-on; regulator-boot-on; diff --git a/arch/arm64/boot/dts/qcom/msm8916-mtp.dts b/arch/arm64/boot/dts/qcom/msm8916-mtp.dts index d66c15538785..7c0ceb3cff45 100644 --- a/arch/arm64/boot/dts/qcom/msm8916-mtp.dts +++ b/arch/arm64/boot/dts/qcom/msm8916-mtp.dts @@ -5,9 +5,22 @@ /dts-v1/; -#include "msm8916-mtp.dtsi" +#include "msm8916-pm8916.dtsi" / { model = "Qualcomm Technologies, Inc. MSM 8916 MTP"; compatible = "qcom,msm8916-mtp", "qcom,msm8916-mtp/1", "qcom,msm8916"; + + aliases { + serial0 = &blsp1_uart2; + usid0 = &pm8916_0; + }; + + chosen { + stdout-path = "serial0"; + }; +}; + +&blsp1_uart2 { + status = "okay"; }; diff --git a/arch/arm64/boot/dts/qcom/msm8916-mtp.dtsi b/arch/arm64/boot/dts/qcom/msm8916-mtp.dtsi deleted file mode 100644 index 1bd05046cdeb..000000000000 --- a/arch/arm64/boot/dts/qcom/msm8916-mtp.dtsi +++ /dev/null @@ -1,21 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * Copyright (c) 2014-2015, The Linux Foundation. All rights reserved. - */ - -#include "msm8916-pm8916.dtsi" - -/ { - aliases { - serial0 = &blsp1_uart2; - usid0 = &pm8916_0; - }; - - chosen { - stdout-path = "serial0"; - }; -}; - -&blsp1_uart2 { - status = "okay"; -}; diff --git a/arch/arm64/boot/dts/qcom/msm8916.dtsi b/arch/arm64/boot/dts/qcom/msm8916.dtsi index b967dbfba3b8..fcc9f757c9e1 100644 --- a/arch/arm64/boot/dts/qcom/msm8916.dtsi +++ b/arch/arm64/boot/dts/qcom/msm8916.dtsi @@ -1064,7 +1064,7 @@ }; }; - camss: camss@1b00000 { + camss: camss@1b0ac00 { compatible = "qcom,msm8916-camss"; reg = <0x01b0ac00 0x200>, <0x01b00030 0x4>, @@ -1771,7 +1771,7 @@ label = "pronto"; - wcnss { + wcnss_ctrl: wcnss { compatible = "qcom,wcnss"; qcom,smd-channels = "WCNSS_CTRL"; diff --git a/arch/arm64/boot/dts/qcom/msm8994.dtsi b/arch/arm64/boot/dts/qcom/msm8994.dtsi index a8dc8163ee82..4447ed146b3a 100644 --- a/arch/arm64/boot/dts/qcom/msm8994.dtsi +++ b/arch/arm64/boot/dts/qcom/msm8994.dtsi @@ -725,7 +725,7 @@ reg = <0xfc4ab000 0x4>; }; - spmi_bus: spmi@fc4c0000 { + spmi_bus: spmi@fc4cf000 { compatible = "qcom,spmi-pmic-arb"; reg = <0xfc4cf000 0x1000>, <0xfc4cb000 0x1000>, diff --git a/arch/arm64/boot/dts/qcom/msm8996-mtp.dts b/arch/arm64/boot/dts/qcom/msm8996-mtp.dts index 45ed594c1b9c..7d9fc35bc7a0 100644 --- a/arch/arm64/boot/dts/qcom/msm8996-mtp.dts +++ b/arch/arm64/boot/dts/qcom/msm8996-mtp.dts @@ -5,9 +5,31 @@ /dts-v1/; -#include "msm8996-mtp.dtsi" +#include "msm8996.dtsi" / { model = "Qualcomm Technologies, Inc. MSM 8996 MTP"; compatible = "qcom,msm8996-mtp"; + + aliases { + serial0 = &blsp2_uart2; + }; + + chosen { + stdout-path = "serial0"; + }; + + soc { + serial@75b0000 { + status = "okay"; + }; + }; +}; + +&hdmi { + status = "okay"; +}; + +&hdmi_phy { + status = "okay"; }; diff --git a/arch/arm64/boot/dts/qcom/msm8996-mtp.dtsi b/arch/arm64/boot/dts/qcom/msm8996-mtp.dtsi deleted file mode 100644 index ac43a91f1104..000000000000 --- a/arch/arm64/boot/dts/qcom/msm8996-mtp.dtsi +++ /dev/null @@ -1,30 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * Copyright (c) 2014-2015, The Linux Foundation. All rights reserved. - */ - -#include "msm8996.dtsi" - -/ { - aliases { - serial0 = &blsp2_uart2; - }; - - chosen { - stdout-path = "serial0"; - }; - - soc { - serial@75b0000 { - status = "okay"; - }; - }; -}; - -&hdmi { - status = "okay"; -}; - -&hdmi_phy { - status = "okay"; -}; diff --git a/arch/arm64/boot/dts/qcom/msm8996.dtsi b/arch/arm64/boot/dts/qcom/msm8996.dtsi index cd66bb16c739..ec3ef14048cc 100644 --- a/arch/arm64/boot/dts/qcom/msm8996.dtsi +++ b/arch/arm64/boot/dts/qcom/msm8996.dtsi @@ -1228,6 +1228,20 @@ }; }; + blsp1_uart2_default: blsp1-uart2-default { + pins = "gpio41", "gpio42", "gpio43", "gpio44"; + function = "blsp_uart2"; + drive-strength = <16>; + bias-disable; + }; + + blsp1_uart2_sleep: blsp1-uart2-sleep { + pins = "gpio41", "gpio42", "gpio43", "gpio44"; + function = "gpio"; + drive-strength = <2>; + bias-disable; + }; + blsp1_i2c3_default: blsp1-i2c2-default { pins = "gpio47", "gpio48"; function = "blsp_i2c3"; @@ -1771,7 +1785,7 @@ }; }; - camss: camss@a00000 { + camss: camss@a34000 { compatible = "qcom,msm8996-camss"; reg = <0x00a34000 0x1000>, <0x00a00030 0x4>, @@ -2724,6 +2738,9 @@ clocks = <&gcc GCC_BLSP1_UART2_APPS_CLK>, <&gcc GCC_BLSP1_AHB_CLK>; clock-names = "core", "iface"; + pinctrl-names = "default", "sleep"; + pinctrl-0 = <&blsp1_uart2_default>; + pinctrl-1 = <&blsp1_uart2_sleep>; dmas = <&blsp1_dma 2>, <&blsp1_dma 3>; dma-names = "tx", "rx"; status = "disabled"; diff --git a/arch/arm64/boot/dts/qcom/sdm630.dtsi b/arch/arm64/boot/dts/qcom/sdm630.dtsi index c2e1a0d9a272..e00c0577cef7 100644 --- a/arch/arm64/boot/dts/qcom/sdm630.dtsi +++ b/arch/arm64/boot/dts/qcom/sdm630.dtsi @@ -1834,7 +1834,7 @@ }; }; - camss: camss@ca00000 { + camss: camss@ca00020 { compatible = "qcom,sdm660-camss"; reg = <0x0c824000 0x1000>, <0x0ca00120 0x4>, diff --git a/arch/arm64/boot/dts/qcom/sdm845.dtsi b/arch/arm64/boot/dts/qcom/sdm845.dtsi index d973aa39e410..a0489a45aafb 100644 --- a/arch/arm64/boot/dts/qcom/sdm845.dtsi +++ b/arch/arm64/boot/dts/qcom/sdm845.dtsi @@ -3921,7 +3921,7 @@ #reset-cells = <1>; }; - camss: camss@a00000 { + camss: camss@acb3000 { compatible = "qcom,sdm845-camss"; reg = <0 0xacb3000 0 0x1000>, diff --git a/arch/arm64/boot/dts/qcom/sm8250-sony-xperia-edo.dtsi b/arch/arm64/boot/dts/qcom/sm8250-sony-xperia-edo.dtsi index effbd6a9c989..b093f2a02a9c 100644 --- a/arch/arm64/boot/dts/qcom/sm8250-sony-xperia-edo.dtsi +++ b/arch/arm64/boot/dts/qcom/sm8250-sony-xperia-edo.dtsi @@ -26,9 +26,10 @@ framebuffer: framebuffer@9c000000 { compatible = "simple-framebuffer"; reg = <0 0x9c000000 0 0x2300000>; - width = <1644>; - height = <3840>; - stride = <(1644 * 4)>; + /* pdx203 BL initializes in 2.5k mode, not 4k */ + width = <1096>; + height = <2560>; + stride = <(1096 * 4)>; format = "a8r8g8b8"; /* * That's a lot of clocks, but it's necessary due diff --git a/arch/arm64/boot/dts/renesas/ulcb-kf.dtsi b/arch/arm64/boot/dts/renesas/ulcb-kf.dtsi index 61bd4df09df0..26cb5f14f9c7 100644 --- a/arch/arm64/boot/dts/renesas/ulcb-kf.dtsi +++ b/arch/arm64/boot/dts/renesas/ulcb-kf.dtsi @@ -270,7 +270,7 @@ }; scif1_pins: scif1 { - groups = "scif1_data_b", "scif1_ctrl"; + groups = "scif1_data_b"; function = "scif1"; }; @@ -330,7 +330,6 @@ &scif1 { pinctrl-0 = <&scif1_pins>; pinctrl-names = "default"; - uart-has-rtscts; status = "okay"; }; diff --git a/arch/arm64/boot/dts/ti/k3-j7200-common-proc-board.dts b/arch/arm64/boot/dts/ti/k3-j7200-common-proc-board.dts index 4417fe81afd7..ee244df75eae 100644 --- a/arch/arm64/boot/dts/ti/k3-j7200-common-proc-board.dts +++ b/arch/arm64/boot/dts/ti/k3-j7200-common-proc-board.dts @@ -80,25 +80,25 @@ &wkup_pmx2 { mcu_cpsw_pins_default: mcu-cpsw-pins-default { pinctrl-single,pins = < - J721E_WKUP_IOPAD(0x0068, PIN_OUTPUT, 0) /* MCU_RGMII1_TX_CTL */ - J721E_WKUP_IOPAD(0x006c, PIN_INPUT, 0) /* MCU_RGMII1_RX_CTL */ - J721E_WKUP_IOPAD(0x0070, PIN_OUTPUT, 0) /* MCU_RGMII1_TD3 */ - J721E_WKUP_IOPAD(0x0074, PIN_OUTPUT, 0) /* MCU_RGMII1_TD2 */ - J721E_WKUP_IOPAD(0x0078, PIN_OUTPUT, 0) /* MCU_RGMII1_TD1 */ - J721E_WKUP_IOPAD(0x007c, PIN_OUTPUT, 0) /* MCU_RGMII1_TD0 */ - J721E_WKUP_IOPAD(0x0088, PIN_INPUT, 0) /* MCU_RGMII1_RD3 */ - J721E_WKUP_IOPAD(0x008c, PIN_INPUT, 0) /* MCU_RGMII1_RD2 */ - J721E_WKUP_IOPAD(0x0090, PIN_INPUT, 0) /* MCU_RGMII1_RD1 */ - J721E_WKUP_IOPAD(0x0094, PIN_INPUT, 0) /* MCU_RGMII1_RD0 */ - J721E_WKUP_IOPAD(0x0080, PIN_OUTPUT, 0) /* MCU_RGMII1_TXC */ - J721E_WKUP_IOPAD(0x0084, PIN_INPUT, 0) /* MCU_RGMII1_RXC */ + J721E_WKUP_IOPAD(0x0000, PIN_OUTPUT, 0) /* MCU_RGMII1_TX_CTL */ + J721E_WKUP_IOPAD(0x0004, PIN_INPUT, 0) /* MCU_RGMII1_RX_CTL */ + J721E_WKUP_IOPAD(0x0008, PIN_OUTPUT, 0) /* MCU_RGMII1_TD3 */ + J721E_WKUP_IOPAD(0x000c, PIN_OUTPUT, 0) /* MCU_RGMII1_TD2 */ + J721E_WKUP_IOPAD(0x0010, PIN_OUTPUT, 0) /* MCU_RGMII1_TD1 */ + J721E_WKUP_IOPAD(0x0014, PIN_OUTPUT, 0) /* MCU_RGMII1_TD0 */ + J721E_WKUP_IOPAD(0x0020, PIN_INPUT, 0) /* MCU_RGMII1_RD3 */ + J721E_WKUP_IOPAD(0x0024, PIN_INPUT, 0) /* MCU_RGMII1_RD2 */ + J721E_WKUP_IOPAD(0x0028, PIN_INPUT, 0) /* MCU_RGMII1_RD1 */ + J721E_WKUP_IOPAD(0x002c, PIN_INPUT, 0) /* MCU_RGMII1_RD0 */ + J721E_WKUP_IOPAD(0x0018, PIN_OUTPUT, 0) /* MCU_RGMII1_TXC */ + J721E_WKUP_IOPAD(0x001c, PIN_INPUT, 0) /* MCU_RGMII1_RXC */ >; }; mcu_mdio_pins_default: mcu-mdio1-pins-default { pinctrl-single,pins = < - J721E_WKUP_IOPAD(0x009c, PIN_OUTPUT, 0) /* (L1) MCU_MDIO0_MDC */ - J721E_WKUP_IOPAD(0x0098, PIN_INPUT, 0) /* (L4) MCU_MDIO0_MDIO */ + J721E_WKUP_IOPAD(0x0034, PIN_OUTPUT, 0) /* (L1) MCU_MDIO0_MDC */ + J721E_WKUP_IOPAD(0x0030, PIN_INPUT, 0) /* (L4) MCU_MDIO0_MDIO */ >; }; }; diff --git a/arch/arm64/configs/generic_iot_defconfig b/arch/arm64/configs/generic_iot_defconfig index 8f1a2644e11d..7738f6077aa8 100644 --- a/arch/arm64/configs/generic_iot_defconfig +++ b/arch/arm64/configs/generic_iot_defconfig @@ -96,7 +96,6 @@ CONFIG_BLK_INLINE_ENCRYPTION=y CONFIG_BLK_INLINE_ENCRYPTION_FALLBACK=y CONFIG_IOSCHED_BFQ=y CONFIG_BFQ_GROUP_IOSCHED=y -CONFIG_GKI_HACKS_TO_FIX=y # CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set CONFIG_BINFMT_MISC=y CONFIG_MEMORY_HOTPLUG=y @@ -104,7 +103,6 @@ CONFIG_MEMORY_HOTREMOVE=y CONFIG_DEFAULT_MMAP_MIN_ADDR=32768 CONFIG_CLEANCACHE=y CONFIG_CMA=y -CONFIG_CMA_DEBUGFS=y CONFIG_CMA_AREAS=16 CONFIG_NET=y CONFIG_PACKET=y @@ -119,10 +117,6 @@ CONFIG_INET=y CONFIG_IP_MULTICAST=y CONFIG_IP_ADVANCED_ROUTER=y CONFIG_IP_MULTIPLE_TABLES=y -CONFIG_NET_IPIP=y -CONFIG_NET_IPGRE_DEMUX=y -CONFIG_NET_IPGRE=y -CONFIG_NET_IPVTI=y CONFIG_INET_ESP=y CONFIG_INET_UDP_DIAG=y CONFIG_INET_DIAG_DESTROY=y @@ -132,8 +126,6 @@ CONFIG_IPV6_OPTIMISTIC_DAD=y CONFIG_INET6_ESP=y CONFIG_INET6_IPCOMP=y CONFIG_IPV6_MIP6=y -CONFIG_IPV6_VTI=y -CONFIG_IPV6_GRE=y CONFIG_IPV6_MULTIPLE_TABLES=y CONFIG_NETFILTER=y CONFIG_NF_CONNTRACK=y @@ -144,14 +136,12 @@ CONFIG_NF_CONNTRACK_FTP=y CONFIG_NF_CONNTRACK_H323=y CONFIG_NF_CONNTRACK_IRC=y CONFIG_NF_CONNTRACK_NETBIOS_NS=y -CONFIG_NF_CONNTRACK_PPTP=y CONFIG_NF_CONNTRACK_SANE=y CONFIG_NF_CONNTRACK_TFTP=y CONFIG_NF_CT_NETLINK=y CONFIG_NETFILTER_XT_TARGET_CLASSIFY=y CONFIG_NETFILTER_XT_TARGET_CONNMARK=y CONFIG_NETFILTER_XT_TARGET_CONNSECMARK=y -CONFIG_NETFILTER_XT_TARGET_DSCP=y CONFIG_NETFILTER_XT_TARGET_IDLETIMER=y CONFIG_NETFILTER_XT_TARGET_MARK=y CONFIG_NETFILTER_XT_TARGET_NFLOG=y @@ -162,7 +152,6 @@ CONFIG_NETFILTER_XT_TARGET_TPROXY=y CONFIG_NETFILTER_XT_TARGET_TRACE=y CONFIG_NETFILTER_XT_TARGET_SECMARK=y CONFIG_NETFILTER_XT_TARGET_TCPMSS=y -CONFIG_NETFILTER_XT_MATCH_BPF=y CONFIG_NETFILTER_XT_MATCH_COMMENT=y CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=y CONFIG_NETFILTER_XT_MATCH_CONNMARK=y @@ -177,7 +166,6 @@ CONFIG_NETFILTER_XT_MATCH_LIMIT=y CONFIG_NETFILTER_XT_MATCH_MAC=y CONFIG_NETFILTER_XT_MATCH_MARK=y CONFIG_NETFILTER_XT_MATCH_MULTIPORT=y -CONFIG_NETFILTER_XT_MATCH_OWNER=y CONFIG_NETFILTER_XT_MATCH_POLICY=y CONFIG_NETFILTER_XT_MATCH_PKTTYPE=y CONFIG_NETFILTER_XT_MATCH_QUOTA=y @@ -211,7 +199,6 @@ CONFIG_IP6_NF_TARGET_REJECT=y CONFIG_IP6_NF_MANGLE=y CONFIG_IP6_NF_RAW=y CONFIG_TIPC=y -CONFIG_L2TP=y CONFIG_BRIDGE=y CONFIG_6LOWPAN=y CONFIG_IEEE802154=y @@ -220,21 +207,10 @@ CONFIG_MAC802154=y CONFIG_NET_SCHED=y CONFIG_NET_SCH_HTB=y CONFIG_NET_SCH_PRIO=y -CONFIG_NET_SCH_MULTIQ=y -CONFIG_NET_SCH_SFQ=y -CONFIG_NET_SCH_TBF=y -CONFIG_NET_SCH_NETEM=y -CONFIG_NET_SCH_CODEL=y -CONFIG_NET_SCH_FQ_CODEL=y -CONFIG_NET_SCH_FQ=y -CONFIG_NET_SCH_INGRESS=y -CONFIG_NET_CLS_BASIC=y CONFIG_NET_CLS_FW=y CONFIG_NET_CLS_U32=y CONFIG_CLS_U32_MARK=y CONFIG_NET_CLS_FLOW=y -CONFIG_NET_CLS_BPF=y -CONFIG_NET_CLS_MATCHALL=y CONFIG_NET_EMATCH=y CONFIG_NET_EMATCH_CMP=y CONFIG_NET_EMATCH_NBYTE=y @@ -242,12 +218,9 @@ CONFIG_NET_EMATCH_U32=y CONFIG_NET_EMATCH_META=y CONFIG_NET_EMATCH_TEXT=y CONFIG_NET_CLS_ACT=y -CONFIG_NET_ACT_POLICE=y CONFIG_NET_ACT_GACT=y CONFIG_NET_ACT_MIRRED=y -CONFIG_NET_ACT_SKBEDIT=y CONFIG_VSOCKETS=y -CONFIG_CGROUP_NET_PRIO=y CONFIG_CAN=y CONFIG_CFG80211=y CONFIG_NL80211_TESTMODE=y @@ -303,8 +276,6 @@ CONFIG_PPP=y CONFIG_PPP_BSDCOMP=y CONFIG_PPP_DEFLATE=y CONFIG_PPP_MPPE=y -CONFIG_PPTP=y -CONFIG_PPPOL2TP=y CONFIG_USB_RTL8150=y CONFIG_USB_RTL8152=y CONFIG_USB_USBNET=y @@ -336,7 +307,6 @@ CONFIG_KEYBOARD_GPIO=y # CONFIG_MOUSE_PS2 is not set CONFIG_INPUT_JOYSTICK=y CONFIG_JOYSTICK_XPAD=y -CONFIG_INPUT_TOUCHSCREEN=y CONFIG_INPUT_MISC=y CONFIG_INPUT_UINPUT=y # CONFIG_VT is not set @@ -393,18 +363,6 @@ CONFIG_LIRC=y CONFIG_BPF_LIRC_MODE2=y CONFIG_RC_DECODERS=y CONFIG_RC_DEVICES=y -CONFIG_MEDIA_CEC_RC=y -# CONFIG_MEDIA_ANALOG_TV_SUPPORT is not set -# CONFIG_MEDIA_DIGITAL_TV_SUPPORT is not set -# CONFIG_MEDIA_RADIO_SUPPORT is not set -# CONFIG_MEDIA_SDR_SUPPORT is not set -# CONFIG_MEDIA_TEST_SUPPORT is not set -CONFIG_VIDEO_V4L2_SUBDEV_API=y -CONFIG_MEDIA_USB_SUPPORT=y -CONFIG_USB_VIDEO_CLASS=y -CONFIG_USB_GSPCA=y -CONFIG_V4L_PLATFORM_DRIVERS=y -CONFIG_V4L_MEM2MEM_DRIVERS=y # CONFIG_VGA_ARB is not set CONFIG_DRM=y CONFIG_BACKLIGHT_CLASS_DEVICE=y @@ -418,7 +376,6 @@ CONFIG_HID_LOGITECH=y CONFIG_HID_LOGITECH_DJ=y CONFIG_HID_MAGICMOUSE=y CONFIG_HID_MICROSOFT=y -CONFIG_HID_MULTITOUCH=y CONFIG_HID_NINTENDO=y CONFIG_HID_PICOLCD=y CONFIG_HID_PLANTRONICS=y @@ -603,15 +560,12 @@ CONFIG_XZ_DEC=y CONFIG_DMA_CMA=y CONFIG_PRINTK_TIME=y CONFIG_PRINTK_CALLER=y -CONFIG_DYNAMIC_DEBUG_CORE=y CONFIG_DEBUG_INFO=y CONFIG_DEBUG_INFO_DWARF4=y CONFIG_HEADERS_INSTALL=y # CONFIG_SECTION_MISMATCH_WARN_ONLY is not set CONFIG_MAGIC_SYSRQ=y CONFIG_PAGE_OWNER=y -CONFIG_DEBUG_STACK_USAGE=y -CONFIG_DEBUG_MEMORY_INIT=y CONFIG_PANIC_ON_OOPS=y CONFIG_PANIC_TIMEOUT=-1 CONFIG_SOFTLOCKUP_DETECTOR=y @@ -622,5 +576,3 @@ CONFIG_SCHEDSTATS=y CONFIG_BUG_ON_DATA_CORRUPTION=y CONFIG_TRACE_MMIO_ACCESS=y CONFIG_KUNIT=y -CONFIG_KUNIT_DEBUGFS=y -# CONFIG_RUNTIME_TESTING_MENU is not set diff --git a/arch/arm64/configs/generic_robotics_defconfig b/arch/arm64/configs/generic_robotics_defconfig index 31c72d82cf79..384e2d0308a0 100644 --- a/arch/arm64/configs/generic_robotics_defconfig +++ b/arch/arm64/configs/generic_robotics_defconfig @@ -30,7 +30,6 @@ CONFIG_CPUSETS=y CONFIG_CGROUP_CPUACCT=y CONFIG_CGROUP_BPF=y CONFIG_NAMESPACES=y -# CONFIG_PID_NS is not set CONFIG_RT_SOFTINT_OPTIMIZATION=y # CONFIG_RD_BZIP2 is not set # CONFIG_RD_LZMA is not set @@ -697,3 +696,16 @@ CONFIG_PINCTRL_SX150X=y CONFIG_USB_SERIAL=y CONFIG_USB_SERIAL_CH341=y CONFIG_USB_SERIAL_CP210X=y +CONFIG_SYSVIPC=y +CONFIG_SYSVIPC_COMPAT=y +CONFIG_SYSVIPC_SYSCTL=y +CONFIG_POSIX_MQUEUE=y +CONFIG_POSIX_MQUEUE_SYSCTL=y +CONFIG_PID_NS=y +CONFIG_USER_NS=y +CONFIG_IPC_NS=y +CONFIG_BRIDGE_NETFILTER=y +CONFIG_NETFILTER_FAMILY_BRIDGE=y +CONFIG_NETFILTER_XT_MATCH_ADDRTYPE=y +CONFIG_CGROUP_DEVICE=y +CONFIG_CGROUP_PIDS=y diff --git a/arch/arm64/configs/gki_defconfig b/arch/arm64/configs/gki_defconfig index 21c805648f41..29e7bba5a7f2 100644 --- a/arch/arm64/configs/gki_defconfig +++ b/arch/arm64/configs/gki_defconfig @@ -489,6 +489,7 @@ CONFIG_USB_HIDDEV=y CONFIG_USB_ANNOUNCE_NEW_DEVICES=y CONFIG_USB_OTG=y CONFIG_USB_XHCI_HCD=y +CONFIG_USB_XHCI_PCI_RENESAS=y CONFIG_USB_EHCI_HCD=y CONFIG_USB_EHCI_ROOT_HUB_TT=y CONFIG_USB_EHCI_HCD_PLATFORM=y diff --git a/arch/arm64/configs/kalama_le_gki.fragment b/arch/arm64/configs/kalama_le_gki.fragment index d1c8f9066e4c..771c1d29366b 100644 --- a/arch/arm64/configs/kalama_le_gki.fragment +++ b/arch/arm64/configs/kalama_le_gki.fragment @@ -3,6 +3,13 @@ CONFIG_TMPFS_POSIX_ACL=y CONFIG_USB_SERIAL=y CONFIG_USB_SERIAL_CH341=y CONFIG_USB_SERIAL_CP210X=y +CONFIG_I2C_MUX=y +CONFIG_PINCTRL_SX150X=y CONFIG_GPIO_SYSFS=y CONFIG_PM_AUTOSLEEP=y CONFIG_CAN=y +CONFIG_USB_XHCI_PCI_RENESAS=y +CONFIG_HWMON=y +CONFIG_POWER_SUPPLY_HWMON=y +CONFIG_THERMAL_HWMON=y + diff --git a/arch/arm64/configs/kalama_lu_gki.fragment b/arch/arm64/configs/kalama_lu_gki.fragment new file mode 100644 index 000000000000..ca040383c0bb --- /dev/null +++ b/arch/arm64/configs/kalama_lu_gki.fragment @@ -0,0 +1,7 @@ +CONFIG_DEVTMPFS=y +CONFIG_TMPFS_POSIX_ACL=y +CONFIG_USB_SERIAL=y +CONFIG_USB_SERIAL_CH341=y +CONFIG_USB_SERIAL_CP210X=y +CONFIG_GPIO_SYSFS=y +CONFIG_PM_AUTOSLEEP=y diff --git a/arch/arm64/configs/vendor/autogvm.config b/arch/arm64/configs/vendor/autogvm.config index 2fb0daaabb3f..e0862964dc04 100644 --- a/arch/arm64/configs/vendor/autogvm.config +++ b/arch/arm64/configs/vendor/autogvm.config @@ -6,6 +6,7 @@ CONFIG_ARM_SMMU_DISABLE_BYPASS_BY_DEFAULT=y CONFIG_ARM_SMMU_QCOM=y # CONFIG_ARM_SMMU_SELFTEST is not set # CONFIG_BPF_KPROBE_OVERRIDE is not set +CONFIG_BRIDGE_NETFILTER=y CONFIG_CFG80211=y # CONFIG_CFG80211_CERTIFICATION_ONUS is not set # CONFIG_CFG80211_CRDA_SUPPORT is not set @@ -35,6 +36,32 @@ CONFIG_IP6_NF_TARGET_MASQUERADE=y # CONFIG_IP6_NF_TARGET_NPT is not set CONFIG_IPC_LOGGING=y CONFIG_IPC_LOG_MINIDUMP_BUFFERS=0 +CONFIG_IP_VS=y +# CONFIG_IP_VS_DEBUG is not set +# CONFIG_IP_VS_DH is not set +# CONFIG_IP_VS_FO is not set +# CONFIG_IP_VS_IPV6 is not set +# CONFIG_IP_VS_LBLC is not set +# CONFIG_IP_VS_LBLCR is not set +# CONFIG_IP_VS_LC is not set +# CONFIG_IP_VS_MH is not set +CONFIG_IP_VS_MH_TAB_INDEX=12 +# CONFIG_IP_VS_NFCT is not set +# CONFIG_IP_VS_NQ is not set +# CONFIG_IP_VS_OVF is not set +# CONFIG_IP_VS_PROTO_AH is not set +# CONFIG_IP_VS_PROTO_ESP is not set +# CONFIG_IP_VS_PROTO_SCTP is not set +# CONFIG_IP_VS_PROTO_TCP is not set +# CONFIG_IP_VS_PROTO_UDP is not set +# CONFIG_IP_VS_RR is not set +# CONFIG_IP_VS_SED is not set +# CONFIG_IP_VS_SH is not set +CONFIG_IP_VS_SH_TAB_BITS=8 +CONFIG_IP_VS_TAB_BITS=12 +# CONFIG_IP_VS_TWOS is not set +# CONFIG_IP_VS_WLC is not set +# CONFIG_IP_VS_WRR is not set CONFIG_KPROBES=y CONFIG_KPROBE_EVENTS=y # CONFIG_KPROBE_EVENT_GEN_TEST is not set @@ -52,9 +79,13 @@ CONFIG_MSM_BOOT_TIME_MARKER=y CONFIG_MSM_HAB=y CONFIG_MSM_HSUSB_PHY=y CONFIG_MSM_QUIN_SUBSYSTEM_NOTIF_VIRT=y +CONFIG_NETFILTER_FAMILY_BRIDGE=y CONFIG_NETFILTER_NETLINK_ACCT=y CONFIG_NETFILTER_XT_MATCH_CGROUP=y +CONFIG_NETFILTER_XT_MATCH_IPVS=y +# CONFIG_NETFILTER_XT_MATCH_PHYSDEV is not set CONFIG_NET_CLS_CGROUP=y +CONFIG_NET_DROP_MONITOR=y CONFIG_NET_FAILOVER=y CONFIG_NF_CONNTRACK_TIMESTAMP=y CONFIG_NF_LOG_IPV6=y @@ -87,6 +118,7 @@ CONFIG_QCOM_MEM_BUF_GH=y CONFIG_QCOM_MEM_BUF_MSGQ=y CONFIG_QCOM_MINIDUMP=y CONFIG_QCOM_MINIDUMP_MMIO=y +# CONFIG_QCOM_MINIDUMP_SMEM is not set CONFIG_QCOM_PDC=y CONFIG_QCOM_QMI_HELPERS=y CONFIG_QCOM_RAMDUMP=y diff --git a/arch/arm64/configs/vendor/autogvm_GKI.config b/arch/arm64/configs/vendor/autogvm_GKI.config index 618207c4559a..e22f6315bd54 100644 --- a/arch/arm64/configs/vendor/autogvm_GKI.config +++ b/arch/arm64/configs/vendor/autogvm_GKI.config @@ -1,4 +1,5 @@ CONFIG_ARCH_QCOM=y +CONFIG_ARM_PARAVIRT_SMMU_V3=m CONFIG_ARM_SMMU=m CONFIG_ARM_SMMU_DISABLE_BYPASS_BY_DEFAULT=y CONFIG_ARM_SMMU_QCOM=m @@ -146,6 +147,7 @@ CONFIG_USB_F_CDEV=m CONFIG_USB_F_DIAG=m # CONFIG_USB_F_FS_IPC_LOGGING is not set CONFIG_USB_F_QDSS=m +CONFIG_USB_LINK_LAYER_TEST=m CONFIG_USB_MON=m CONFIG_USB_MSM_SSPHY_QMP=m # CONFIG_USB_NET_RNDIS_WLAN is not set diff --git a/arch/arm64/configs/vendor/gen3auto.config b/arch/arm64/configs/vendor/gen3auto.config index 52a625ce7396..af4042b1cb59 100644 --- a/arch/arm64/configs/vendor/gen3auto.config +++ b/arch/arm64/configs/vendor/gen3auto.config @@ -236,6 +236,7 @@ CONFIG_QTI_CPU_HOTPLUG_COOLING_DEVICE=m CONFIG_QTI_CPU_PAUSE_COOLING_DEVICE=m CONFIG_QTI_CRYPTO_COMMON=y CONFIG_QTI_CRYPTO_FDE=y +CONFIG_QTI_CRYPTO_LEGACY_KEY_FDE=y CONFIG_QTI_CRYPTO_TZ=y CONFIG_QTI_DEVFREQ_CDEV=m CONFIG_QTI_IOMMU_SUPPORT=y diff --git a/arch/arm64/configs/vendor/gen3auto_GKI.config b/arch/arm64/configs/vendor/gen3auto_GKI.config index 4e20803340a9..87572c3c3b3a 100644 --- a/arch/arm64/configs/vendor/gen3auto_GKI.config +++ b/arch/arm64/configs/vendor/gen3auto_GKI.config @@ -296,6 +296,10 @@ CONFIG_STMMAC_ETH=m # CONFIG_STMMAC_PCI is not set CONFIG_STMMAC_PLATFORM=m # CONFIG_STMMAC_SELFTESTS is not set +CONFIG_STM_PROTO_BASIC=m +CONFIG_STM_PROTO_OST=m +CONFIG_STM_SOURCE_CONSOLE=m +CONFIG_STM_SOURCE_FTRACE=m CONFIG_THERMAL_TSENS_LEGACY=m CONFIG_UIO_MSM_SHAREDMEM=m CONFIG_USB_BAM=m diff --git a/arch/arm64/configs/vendor/gen3auto_consolidate.config b/arch/arm64/configs/vendor/gen3auto_consolidate.config index 7c9cdb137b0e..0316e7165ae4 100644 --- a/arch/arm64/configs/vendor/gen3auto_consolidate.config +++ b/arch/arm64/configs/vendor/gen3auto_consolidate.config @@ -7,4 +7,8 @@ CONFIG_LKDTM=m CONFIG_LOCALVERSION="-gki-consolidate" CONFIG_MHI_BUS_DEBUG=y CONFIG_MSM_GPI_DMA_DEBUG=y +CONFIG_STM_PROTO_BASIC=m +CONFIG_STM_PROTO_OST=m +CONFIG_STM_SOURCE_CONSOLE=m +CONFIG_STM_SOURCE_FTRACE=m CONFIG_TEST_USER_COPY=m diff --git a/arch/arm64/configs/vendor/gen4auto_GKI.config b/arch/arm64/configs/vendor/gen4auto_GKI.config index c620eee8fb34..d256593fb4e2 100644 --- a/arch/arm64/configs/vendor/gen4auto_GKI.config +++ b/arch/arm64/configs/vendor/gen4auto_GKI.config @@ -43,6 +43,7 @@ CONFIG_CPU_FREQ_GOV_ONDEMAND=m CONFIG_CPU_IDLE_GOV_QCOM_LPM=m CONFIG_DEEPSLEEP=y CONFIG_DRM_ANALOGIX_ANX7625=m +CONFIG_DUMP_XBL_LOG=m # CONFIG_DWMAC_DWC_QOS_ETH is not set # CONFIG_DWMAC_GENERIC is not set # CONFIG_DWMAC_INTEL_PLAT is not set @@ -51,6 +52,9 @@ CONFIG_DRM_ANALOGIX_ANX7625=m CONFIG_DWMAC_QCOM_VER3=y # CONFIG_DWMAC_SUN8I is not set # CONFIG_DWMAC_SUNXI is not set +CONFIG_EDAC_QCOM=m +# CONFIG_EDAC_QCOM_LLCC_PANIC_ON_CE is not set +# CONFIG_EDAC_QCOM_LLCC_PANIC_ON_UE is not set CONFIG_ETHQOS_QCOM_SERDES=y # CONFIG_ETM4X_IMPDEF_FEATURE is not set CONFIG_GPIO_PCA953X=m @@ -108,12 +112,15 @@ CONFIG_POWER_RESET_QCOM_DOWNLOAD_MODE=m CONFIG_POWER_RESET_QCOM_DOWNLOAD_MODE_DEFAULT=y CONFIG_POWER_RESET_QCOM_PON=m CONFIG_POWER_RESET_QCOM_REBOOT_REASON=m +CONFIG_PROFILER=m +CONFIG_QCOM_AOP_SET_DDR=m CONFIG_QCOM_AOSS_QMP=m CONFIG_QCOM_BWMON=m CONFIG_QCOM_CLK_RPMH=m CONFIG_QCOM_COMMAND_DB=m CONFIG_QCOM_CPUSS_SLEEP_STATS=m CONFIG_QCOM_CPU_VENDOR_HOOKS=m +CONFIG_QCOM_DCC_V2=m CONFIG_QCOM_DCVS=m CONFIG_QCOM_DCVS_FP=m CONFIG_QCOM_DMABUF_HEAPS=m diff --git a/arch/arm64/configs/vendor/kalama_GKI.config b/arch/arm64/configs/vendor/kalama_GKI.config index 74f49ae0d550..7936539036b0 100644 --- a/arch/arm64/configs/vendor/kalama_GKI.config +++ b/arch/arm64/configs/vendor/kalama_GKI.config @@ -7,6 +7,7 @@ CONFIG_ARM_SMMU=m CONFIG_ARM_SMMU_DISABLE_BYPASS_BY_DEFAULT=y # CONFIG_ARM_SMMU_SELFTEST is not set CONFIG_BLK_DEV_NVME=m +CONFIG_CAN_MCP25XXFD=m CONFIG_CFG80211=m # CONFIG_CFG80211_CERTIFICATION_ONUS is not set # CONFIG_CFG80211_CRDA_SUPPORT is not set diff --git a/arch/arm64/configs/vendor/kalama_le_GKI.config b/arch/arm64/configs/vendor/kalama_le_GKI.config index 84dc0a619589..42ce44525fbe 100644 --- a/arch/arm64/configs/vendor/kalama_le_GKI.config +++ b/arch/arm64/configs/vendor/kalama_le_GKI.config @@ -1,3 +1,4 @@ +CONFIG_ADS7052_TDK_THERMISTOR=m CONFIG_ARCH_KAKA=y CONFIG_ARCH_KALAMA=y CONFIG_ARCH_QCOM=y @@ -17,6 +18,8 @@ CONFIG_CFG80211=m CONFIG_CFG80211_REQUIRE_SIGNED_REGDB=y CONFIG_CFG80211_USE_KERNEL_REGDB_KEYS=y # CONFIG_CFG80211_WEXT is not set +CONFIG_CH101=m +CONFIG_CH101_I2C=m # CONFIG_CHARGER_QCOM_SMBB is not set CONFIG_CHR_DEV_SG=m CONFIG_COMMON_CLK_QCOM=m @@ -32,7 +35,7 @@ CONFIG_CORESIGHT_TGU=m CONFIG_CORESIGHT_TPDA=m CONFIG_CORESIGHT_TPDM=m CONFIG_CPU_IDLE_GOV_QCOM_LPM=m -CONFIG_DRM_LT9611UXC=m +# CONFIG_DRM_LT9611UXC is not set CONFIG_EDAC_QCOM=m # CONFIG_EDAC_QCOM_LLCC_PANIC_ON_CE is not set CONFIG_EDAC_QCOM_LLCC_PANIC_ON_UE=y diff --git a/arch/arm64/configs/vendor/kalama_le_consolidate.config b/arch/arm64/configs/vendor/kalama_le_consolidate.config index b298fbb0b001..9391554813dd 100644 --- a/arch/arm64/configs/vendor/kalama_le_consolidate.config +++ b/arch/arm64/configs/vendor/kalama_le_consolidate.config @@ -4,6 +4,7 @@ CONFIG_CMA_DEBUGFS=y CONFIG_CNSS2_DEBUG=y CONFIG_CORESIGHT_SOURCE_ETM4X=m CONFIG_QTI_THERMALZONE_CONFIG_DEBUG=m +CONFIG_HWMON=y # CONFIG_HYP_ASSIGN_DEBUG is not set CONFIG_I2C_CHARDEV=m CONFIG_IOMMU_TLBSYNC_DEBUG=y @@ -12,15 +13,20 @@ CONFIG_LOCALVERSION="-gki-consolidate" CONFIG_LOCK_TORTURE_TEST=m CONFIG_MHI_BUS_DEBUG=y CONFIG_MSM_GPI_DMA_DEBUG=y +CONFIG_POWER_SUPPLY_HWMON=y # CONFIG_QCOM_DYN_MINIDUMP_STACK is not set CONFIG_QCOM_RTB=m CONFIG_QCOM_RTB_SEPARATE_CPUS=y +CONFIG_QRC=m +CONFIG_QRC_DEBUG=m CONFIG_QTI_PMIC_GLINK_CLIENT_DEBUG=y CONFIG_RCU_TORTURE_TEST=m CONFIG_REGMAP_QTI_DEBUGFS_ALLOW_WRITE=y CONFIG_RPMSG_QCOM_GLINK_DEBUG=y CONFIG_RUNTIME_TESTING_MENU=y CONFIG_SCHED_WALT_DEBUG=m +CONFIG_SENSORS_PWM_FAN=m CONFIG_SPI_SPIDEV=m CONFIG_TEST_USER_COPY=m +CONFIG_THERMAL_HWMON=y CONFIG_UFS_DBG=y diff --git a/arch/arm64/configs/vendor/kalama_lu_GKI.config b/arch/arm64/configs/vendor/kalama_lu_GKI.config new file mode 100644 index 000000000000..68d12e751f57 --- /dev/null +++ b/arch/arm64/configs/vendor/kalama_lu_GKI.config @@ -0,0 +1,379 @@ +CONFIG_ARCH_KAKA=y +CONFIG_ARCH_KALAMA=y +CONFIG_ARCH_QCOM=y +CONFIG_ARM_QCOM_CPUFREQ_HW=m +CONFIG_ARM_QCOM_CPUFREQ_HW_DEBUG=m +CONFIG_ARM_SMMU=m +CONFIG_ARM_SMMU_DISABLE_BYPASS_BY_DEFAULT=y +# CONFIG_ARM_SMMU_SELFTEST is not set +CONFIG_BLK_DEV_NVME=m +CONFIG_CFG80211=m +# CONFIG_CFG80211_CERTIFICATION_ONUS is not set +# CONFIG_CFG80211_CRDA_SUPPORT is not set +# CONFIG_CFG80211_DEBUGFS is not set +# CONFIG_CFG80211_DEFAULT_PS is not set +# CONFIG_CFG80211_DEVELOPER_WARNINGS is not set +CONFIG_CFG80211_REQUIRE_SIGNED_REGDB=y +CONFIG_CFG80211_USE_KERNEL_REGDB_KEYS=y +# CONFIG_CFG80211_WEXT is not set +# CONFIG_CHARGER_QCOM_SMBB is not set +CONFIG_CHR_DEV_SG=m +CONFIG_COMMON_CLK_QCOM=m +CONFIG_CORESIGHT=m +CONFIG_CORESIGHT_CTI=m +CONFIG_CORESIGHT_DUMMY=m +CONFIG_CORESIGHT_HWEVENT=m +CONFIG_CORESIGHT_LINKS_AND_SINKS=m +CONFIG_CORESIGHT_LINK_AND_SINK_TMC=m +CONFIG_CORESIGHT_REMOTE_ETM=m +CONFIG_CORESIGHT_STM=m +CONFIG_CORESIGHT_TGU=m +CONFIG_CORESIGHT_TPDA=m +CONFIG_CORESIGHT_TPDM=m +CONFIG_CPU_IDLE_GOV_QCOM_LPM=m +CONFIG_DRM_LT9611UXC=m +CONFIG_EDAC_QCOM=m +# CONFIG_EDAC_QCOM_LLCC_PANIC_ON_CE is not set +CONFIG_EDAC_QCOM_LLCC_PANIC_ON_UE=y +# CONFIG_EXT4_KUNIT_TESTS is not set +# CONFIG_FAT_KUNIT_TEST is not set +CONFIG_GH_ARM64_DRV=m +CONFIG_GH_CTRL=m +CONFIG_GH_DBL=m +# CONFIG_GH_GUEST_POPS is not set +CONFIG_GH_IRQ_LEND=m +CONFIG_GH_MEM_NOTIFIER=m +CONFIG_GH_MSGQ=m +CONFIG_GH_PROXY_SCHED=m +CONFIG_GH_RM_DRV=m +CONFIG_GH_SECURE_VM_LOADER=m +CONFIG_GH_TLMM_VM_MEM_ACCESS=m +CONFIG_GH_VIRT_WATCHDOG=m +CONFIG_GUNYAH=m +CONFIG_GUNYAH_DRIVERS=y +CONFIG_HVC_GUNYAH=m +# CONFIG_HVC_GUNYAH_CONSOLE is not set +CONFIG_HWSPINLOCK_QCOM=m +CONFIG_I2C_EUSB2_REPEATER=m +CONFIG_I2C_MSM_GENI=m +CONFIG_I3C_MASTER_MSM_GENI=m +CONFIG_INPUT_PM8941_PWRKEY=m +# CONFIG_INPUT_PM8XXX_VIBRATOR is not set +CONFIG_INPUT_QCOM_HV_HAPTICS=m +CONFIG_INTERCONNECT_QCOM=m +CONFIG_INTERCONNECT_QCOM_DEBUG=m +CONFIG_INTERCONNECT_QCOM_KALAMA=m +CONFIG_INTERCONNECT_TEST=m +CONFIG_IOMMU_IO_PGTABLE_FAST=y +# CONFIG_IOMMU_IO_PGTABLE_FAST_PROVE_TLB is not set +# CONFIG_IOMMU_IO_PGTABLE_FAST_SELFTEST is not set +CONFIG_IPA3=m +CONFIG_IPC_LOGGING=m +CONFIG_IPC_LOG_MINIDUMP_BUFFERS=16 +# CONFIG_KASAN_KUNIT_TEST is not set +# CONFIG_KFENCE_KUNIT_TEST is not set +CONFIG_KUNIT=m +# CONFIG_KUNIT_ALL_TESTS is not set +CONFIG_KUNIT_DEBUGFS=y +# CONFIG_KUNIT_EXAMPLE_TEST is not set +# CONFIG_KUNIT_TEST is not set +CONFIG_LEDS_QTI_FLASH=m +CONFIG_LEDS_QTI_TRI_LED=m +CONFIG_MAC80211=m +# CONFIG_MAC80211_DEBUGFS is not set +# CONFIG_MAC80211_DEBUG_MENU is not set +# CONFIG_MAC80211_HWSIM is not set +# CONFIG_MAC80211_LEDS is not set +# CONFIG_MAC80211_MESH is not set +# CONFIG_MAC80211_MESSAGE_TRACING is not set +CONFIG_MAC80211_RC_DEFAULT="" +# CONFIG_MAC80211_RC_MINSTREL is not set +CONFIG_MAX31760_FAN_CONTROLLER=m +CONFIG_MEM_SHARE_QMI_SERVICE=m +CONFIG_MFD_SPMI_PMIC=m +# CONFIG_MFD_WCD934X is not set +CONFIG_MHI_BUS=m +CONFIG_MHI_BUS_MISC=y +CONFIG_MHI_DTR=m +CONFIG_MHI_NETDEV=m +CONFIG_MHI_QCOM=m +CONFIG_MHI_SATELLITE=m +CONFIG_MHI_UCI=m +CONFIG_MINIDUMP_MAX_ENTRIES=200 +CONFIG_MMC_SDHCI_MSM=m +# CONFIG_MODULE_SIG_ALL is not set +CONFIG_MSM_ADSPRPC=m +CONFIG_MSM_BOOT_STATS=m +CONFIG_MSM_BOOT_TIME_MARKER=y +CONFIG_MSM_CDSP_LOADER=m +CONFIG_MSM_CORE_HANG_DETECT=m +CONFIG_MSM_GLOBAL_SYNX=m +CONFIG_MSM_GPI_DMA=m +# CONFIG_MSM_GPI_DMA_DEBUG is not set +CONFIG_MSM_PERFORMANCE=m +CONFIG_MSM_POWER_STATE=m +CONFIG_MSM_QBT_HANDLER=m +CONFIG_MSM_QMP=m +CONFIG_MSM_RDBG=m +CONFIG_MSM_SPCOM=m +CONFIG_MSM_SPSS_UTILS=m +CONFIG_MSM_SYSSTATS=m +CONFIG_MSM_TMECOM_QMP=m +CONFIG_NL80211_TESTMODE=y +CONFIG_NOP_USB_XCEIV=m +CONFIG_NVMEM_SPMI_SDAM=m +CONFIG_NVME_CORE=m +# CONFIG_NVME_MULTIPATH is not set +CONFIG_PCI_MSM=m +CONFIG_PDR_INDICATION_NOTIF_TIMEOUT=9000 +CONFIG_PHY_QCOM_UFS=m +CONFIG_PHY_QCOM_UFS_QRBTC_SDM845=m +CONFIG_PHY_QCOM_UFS_V4=m +CONFIG_PINCTRL_KALAMA=m +CONFIG_PINCTRL_QCOM_SPMI_PMIC=m +# CONFIG_PM8916_WATCHDOG is not set +CONFIG_POWER_RESET_QCOM_DOWNLOAD_MODE=m +CONFIG_POWER_RESET_QCOM_DOWNLOAD_MODE_DEFAULT=y +CONFIG_POWER_RESET_QCOM_PON=m +CONFIG_POWER_RESET_QCOM_REBOOT_REASON=m +# CONFIG_PRISM2_USB is not set +CONFIG_PWM_QTI_LPG=m +CONFIG_QCOM_ADSP_SLEEPMON=m +CONFIG_QCOM_AOSS_QMP=m +CONFIG_QCOM_BALANCE_ANON_FILE_RECLAIM=y +CONFIG_QCOM_BAM_DMA=m +CONFIG_QCOM_BWMON=m +CONFIG_QCOM_CDSP_RM=m +CONFIG_QCOM_CLK_RPMH=m +# CONFIG_QCOM_COINCELL is not set +CONFIG_QCOM_COMMAND_DB=m +CONFIG_QCOM_CPUSS_SLEEP_STATS=m +CONFIG_QCOM_CPU_VENDOR_HOOKS=m +CONFIG_QCOM_DCC_V2=m +CONFIG_QCOM_DCVS=m +CONFIG_QCOM_DCVS_FP=m +CONFIG_QCOM_DMABUF_HEAPS=m +CONFIG_QCOM_DMABUF_HEAPS_BITSTREAM_CONTIG=y +CONFIG_QCOM_DMABUF_HEAPS_CARVEOUT=y +CONFIG_QCOM_DMABUF_HEAPS_CMA=y +CONFIG_QCOM_DMABUF_HEAPS_PAGE_POOL_REFILL=y +CONFIG_QCOM_DMABUF_HEAPS_SYSTEM=y +CONFIG_QCOM_DMABUF_HEAPS_SYSTEM_SECURE=y +# CONFIG_QCOM_DMABUF_HEAPS_SYSTEM_UNCACHED is not set +# CONFIG_QCOM_DYN_MINIDUMP_STACK is not set +CONFIG_QCOM_ESOC=m +CONFIG_QCOM_ESOC_CLIENT=m +# CONFIG_QCOM_ESOC_DBG_ENG is not set +CONFIG_QCOM_ESOC_DEBUG=m +CONFIG_QCOM_ESOC_DEV=m +CONFIG_QCOM_ESOC_MDM_4X=m +CONFIG_QCOM_ESOC_MDM_DRV=m +CONFIG_QCOM_EUD=m +CONFIG_QCOM_FORCE_WDOG_BITE_ON_PANIC=y +CONFIG_QCOM_FSA4480_I2C=m +CONFIG_QCOM_GDSC_REGULATOR=m +CONFIG_QCOM_GLINK=m +CONFIG_QCOM_GLINK_PKT=m +# CONFIG_QCOM_GUESTVM is not set +CONFIG_QCOM_HUNG_TASK_ENH=m +CONFIG_QCOM_IOMMU_DEBUG=m +CONFIG_QCOM_IOMMU_UTIL=m +# CONFIG_QCOM_IPA is not set +CONFIG_QCOM_IRQ_STAT=y +CONFIG_QCOM_LAZY_MAPPING=m +CONFIG_QCOM_LLCC=m +CONFIG_QCOM_LLCC_PERFMON=m +CONFIG_QCOM_LLCC_PMU=m +CONFIG_QCOM_LOGBUF_VENDOR_HOOKS=m +CONFIG_QCOM_MDT_LOADER=m +CONFIG_QCOM_MEMLAT=m +CONFIG_QCOM_MEMORY_DUMP_V2=m +CONFIG_QCOM_MEM_BUF=m +CONFIG_QCOM_MEM_BUF_DEV=m +CONFIG_QCOM_MEM_BUF_GH=y +CONFIG_QCOM_MEM_BUF_MSGQ=m +CONFIG_QCOM_MEM_HOOKS=m +CONFIG_QCOM_MEM_OFFLINE=m +CONFIG_QCOM_MICRODUMP=m +CONFIG_QCOM_MINIDUMP=m +CONFIG_QCOM_MINIDUMP_FTRACE=y +CONFIG_QCOM_MINIDUMP_PANIC_CPU_CONTEXT=y +CONFIG_QCOM_MINIDUMP_PANIC_DUMP=y +CONFIG_QCOM_MINIDUMP_PSTORE=y +CONFIG_QCOM_MSM_IPCC=m +CONFIG_QCOM_PANEL_EVENT_NOTIFIER=m +CONFIG_QCOM_PANIC_ON_NOTIF_TIMEOUT=y +CONFIG_QCOM_PANIC_ON_PDR_NOTIF_TIMEOUT=y +CONFIG_QCOM_PDC=m +CONFIG_QCOM_PDR_HELPERS=m +CONFIG_QCOM_PIL_INFO=m +CONFIG_QCOM_PMU_LIB=m +# CONFIG_QCOM_Q6V5_ADSP is not set +CONFIG_QCOM_Q6V5_COMMON=m +# CONFIG_QCOM_Q6V5_MSS is not set +CONFIG_QCOM_Q6V5_PAS=m +# CONFIG_QCOM_Q6V5_WCSS is not set +CONFIG_QCOM_QDSS_BRIDGE=m +CONFIG_QCOM_QFPROM=m +CONFIG_QCOM_QMI_HELPERS=m +CONFIG_QCOM_RAMDUMP=m +CONFIG_QCOM_RIMPS=m +CONFIG_QCOM_RPMH=m +CONFIG_QCOM_RPROC_COMMON=m +CONFIG_QCOM_RUN_QUEUE_STATS=m +CONFIG_QCOM_S2D_VENDOR_HOOK=m +CONFIG_QCOM_SCM=m +CONFIG_QCOM_SECURE_BUFFER=m +CONFIG_QCOM_SHOW_RESUME_IRQ=m +CONFIG_QCOM_SMEM=m +CONFIG_QCOM_SMP2P=m +CONFIG_QCOM_SMP2P_SLEEPSTATE=m +# CONFIG_QCOM_SMSM is not set +CONFIG_QCOM_SOCINFO=m +CONFIG_QCOM_SOC_SLEEP_STATS=m +# CONFIG_QCOM_SOC_WATCHDOG is not set +CONFIG_QCOM_SPMI_ADC5_GEN3=m +CONFIG_QCOM_SPMI_TEMP_ALARM=m +CONFIG_QCOM_SPSS=m +CONFIG_QCOM_SUBSYSTEM_SLEEP_STATS=m +CONFIG_QCOM_SYSMON=m +CONFIG_QCOM_SYSMON_SUBSYSTEM_STATS=m +CONFIG_QCOM_TSENS=m +CONFIG_QCOM_VADC_COMMON=m +CONFIG_QCOM_VA_MINIDUMP=m +CONFIG_QCOM_VM_DMESG_DUMPER=m +CONFIG_QCOM_WATCHDOG_BARK_TIME=11000 +CONFIG_QCOM_WATCHDOG_IPI_PING=y +CONFIG_QCOM_WATCHDOG_PET_TIME=9360 +# CONFIG_QCOM_WATCHDOG_USERSPACE_PET is not set +CONFIG_QCOM_WATCHDOG_WAKEUP_ENABLE=y +# CONFIG_QCOM_WCNSS_PIL is not set +# CONFIG_QCOM_WDOG_BITE_EARLY_PANIC is not set +CONFIG_QCOM_WDT_CORE=m +CONFIG_QRTR=m +CONFIG_QRTR_GUNYAH=m +CONFIG_QRTR_MHI=m +CONFIG_QRTR_SMD=m +# CONFIG_QRTR_TUN is not set +CONFIG_QSEECOM_PROXY=m +CONFIG_QSEE_IPC_IRQ_BRIDGE=m +CONFIG_QTI_ALTMODE_GLINK=m +CONFIG_QTI_BATTERY_CHARGER=m +CONFIG_QTI_BATTERY_GLINK_DEBUG=m +CONFIG_QTI_BCL_PMIC5=m +CONFIG_QTI_BCL_SOC_DRIVER=m +CONFIG_QTI_C1DCVS_SCMI_CLIENT=m +CONFIG_QTI_CHARGER_ULOG_GLINK=m +CONFIG_QTI_CPUFREQ_CDEV=m +CONFIG_QTI_CPU_HOTPLUG_COOLING_DEVICE=m +CONFIG_QTI_CPU_PAUSE_COOLING_DEVICE=m +CONFIG_QTI_CPU_VOLTAGE_COOLING_DEVICE=m +CONFIG_QTI_CRYPTO_COMMON=m +CONFIG_QTI_DDR_COOLING_DEVICE=m +CONFIG_QTI_DEVFREQ_CDEV=m +CONFIG_QTI_HW_KEY_MANAGER=m +CONFIG_QTI_HW_MEMLAT_SCMI_CLIENT=m +CONFIG_QTI_IOMMU_SUPPORT=m +CONFIG_QTI_PMIC_EUSB2_REPEATER=m +CONFIG_QTI_PMIC_GLINK=m +# CONFIG_QTI_PMIC_GLINK_CLIENT_DEBUG is not set +CONFIG_QTI_PMIC_GLINK_DEBUG=m +CONFIG_QTI_PMIC_PON_LOG=m +CONFIG_QTI_PMU_SCMI_CLIENT=m +CONFIG_QTI_POLICY_ENGINE_SENSOR=m +CONFIG_QTI_QMI_COOLING_DEVICE=m +CONFIG_QTI_QMI_SENSOR_V2=m +CONFIG_QTI_RIMPS_LOG=m +CONFIG_QTI_SCMI_C1DCVS_PROTOCOL=m +CONFIG_QTI_SCMI_MEMLAT_PROTOCOL=m +CONFIG_QTI_SCMI_PMU_PROTOCOL=m +CONFIG_QTI_SDPM_CLOCK_MONITOR=m +CONFIG_QTI_SYS_PM_VX=m +CONFIG_QTI_THERMAL_LIMITS_DCVS=m +CONFIG_QTI_THERMAL_MINIDUMP=m +CONFIG_QTI_USERSPACE_CDEV=m +# CONFIG_R8188EU is not set +# CONFIG_R8712U is not set +CONFIG_REBOOT_MODE=m +CONFIG_REGMAP_QTI_DEBUGFS=m +# CONFIG_REGMAP_QTI_DEBUGFS_ALLOW_WRITE is not set +CONFIG_REGMAP_SPMI=m +CONFIG_REGULATOR_DEBUG_CONTROL=m +CONFIG_REGULATOR_PROXY_CONSUMER=m +# CONFIG_REGULATOR_PROXY_CONSUMER_LEGACY is not set +CONFIG_REGULATOR_QTI_FIXED_VOLTAGE=m +CONFIG_REGULATOR_QTI_OCP_NOTIFIER=m +CONFIG_REGULATOR_RPMH=m +CONFIG_REGULATOR_STUB=m +CONFIG_RPMSG_QCOM_GLINK=m +CONFIG_RPMSG_QCOM_GLINK_SMEM=m +CONFIG_RPMSG_QCOM_GLINK_SPSS=m +CONFIG_RPMSG_QCOM_SMD=m +CONFIG_RPROC_SSR_NOTIF_TIMEOUT=20000 +CONFIG_RPROC_SYSMON_NOTIF_TIMEOUT=20000 +CONFIG_RTC_DRV_PM8XXX=m +# CONFIG_RTC_LIB_KUNIT_TEST is not set +# CONFIG_RTL8723BS is not set +CONFIG_SCHED_WALT=m +CONFIG_SCSI_UFS_CRYPTO_QTI=m +CONFIG_SCSI_UFS_QCOM=m +CONFIG_SERIAL_MSM_GENI=m +CONFIG_SHOW_SUSPEND_EPOCH=m +CONFIG_SLIMBUS=m +# CONFIG_SLIM_QCOM_CTRL is not set +CONFIG_SLIM_QCOM_NGD_CTRL=m +CONFIG_SM_CAMCC_KALAMA=m +CONFIG_SM_DEBUGCC_KALAMA=m +CONFIG_SM_DISPCC_KALAMA=m +CONFIG_SM_GCC_KALAMA=m +CONFIG_SM_GPUCC_KALAMA=m +CONFIG_SM_TCSRCC_KALAMA=m +CONFIG_SM_VIDEOCC_KALAMA=m +# CONFIG_SND_SOC_TOPOLOGY_KUNIT_TEST is not set +# CONFIG_SND_SOC_WCD9335 is not set +CONFIG_SND_USB_AUDIO_QMI=m +CONFIG_SPI_MSM_GENI=m +CONFIG_SPMI_MSM_PMIC_ARB=m +CONFIG_SPMI_MSM_PMIC_ARB_DEBUG=m +CONFIG_SPS=m +# CONFIG_SPS_SUPPORT_BAMDMA is not set +CONFIG_SPS_SUPPORT_NDP_BAM=y +CONFIG_STM_PROTO_BASIC=m +CONFIG_STM_PROTO_OST=m +CONFIG_STM_SOURCE_CONSOLE=m +CONFIG_STM_SOURCE_FTRACE=m +# CONFIG_SWIOTLB_NONLINEAR is not set +# CONFIG_TIME_KUNIT_TEST is not set +CONFIG_UCSI_QTI_GLINK=m +CONFIG_UIO_MSM_SHAREDMEM=m +CONFIG_USB_BAM=m +CONFIG_USB_CONFIGFS_F_CCID=m +CONFIG_USB_CONFIGFS_F_CDEV=m +CONFIG_USB_CONFIGFS_F_DIAG=m +CONFIG_USB_CONFIGFS_F_GSI=m +CONFIG_USB_CONFIGFS_F_QDSS=m +CONFIG_USB_DWC3_MSM=m +CONFIG_USB_EHSET_TEST_FIXTURE=m +CONFIG_USB_F_CCID=m +CONFIG_USB_F_CDEV=m +CONFIG_USB_F_DIAG=m +CONFIG_USB_F_FS_IPC_LOGGING=m +CONFIG_USB_F_GSI=m +CONFIG_USB_F_QDSS=m +CONFIG_USB_M31_MSM_EUSB2_PHY=m +CONFIG_USB_MON=m +CONFIG_USB_MSM_EUSB2_PHY=m +CONFIG_USB_MSM_SSPHY_QMP=m +# CONFIG_USB_NET_RNDIS_WLAN is not set +CONFIG_USB_QCOM_EMU_PHY=m +CONFIG_USB_REDRIVER=m +CONFIG_USB_REDRIVER_NB7VPQ904M=m +CONFIG_USB_REPEATER=m +# CONFIG_VIDEO_QCOM_VENUS is not set +CONFIG_VIRT_DRIVERS=y +# CONFIG_VIRT_WIFI is not set +# CONFIG_VT6655 is not set +# CONFIG_VT6656 is not set +# CONFIG_WFX is not set +# CONFIG_WILC1000_SDIO is not set +# CONFIG_WILC1000_SPI is not set diff --git a/arch/arm64/configs/vendor/kalama_lu_consolidate.config b/arch/arm64/configs/vendor/kalama_lu_consolidate.config new file mode 100644 index 000000000000..b298fbb0b001 --- /dev/null +++ b/arch/arm64/configs/vendor/kalama_lu_consolidate.config @@ -0,0 +1,26 @@ +CONFIG_ATOMIC64_SELFTEST=m +CONFIG_BUG_ON_HW_MEM_ONLINE_FAIL=y +CONFIG_CMA_DEBUGFS=y +CONFIG_CNSS2_DEBUG=y +CONFIG_CORESIGHT_SOURCE_ETM4X=m +CONFIG_QTI_THERMALZONE_CONFIG_DEBUG=m +# CONFIG_HYP_ASSIGN_DEBUG is not set +CONFIG_I2C_CHARDEV=m +CONFIG_IOMMU_TLBSYNC_DEBUG=y +CONFIG_LKDTM=m +CONFIG_LOCALVERSION="-gki-consolidate" +CONFIG_LOCK_TORTURE_TEST=m +CONFIG_MHI_BUS_DEBUG=y +CONFIG_MSM_GPI_DMA_DEBUG=y +# CONFIG_QCOM_DYN_MINIDUMP_STACK is not set +CONFIG_QCOM_RTB=m +CONFIG_QCOM_RTB_SEPARATE_CPUS=y +CONFIG_QTI_PMIC_GLINK_CLIENT_DEBUG=y +CONFIG_RCU_TORTURE_TEST=m +CONFIG_REGMAP_QTI_DEBUGFS_ALLOW_WRITE=y +CONFIG_RPMSG_QCOM_GLINK_DEBUG=y +CONFIG_RUNTIME_TESTING_MENU=y +CONFIG_SCHED_WALT_DEBUG=m +CONFIG_SPI_SPIDEV=m +CONFIG_TEST_USER_COPY=m +CONFIG_UFS_DBG=y diff --git a/arch/arm64/configs/vendor/kona_le_GKI.config b/arch/arm64/configs/vendor/kona_le_GKI.config index 4d49b3bbb26c..ae3acd93d687 100644 --- a/arch/arm64/configs/vendor/kona_le_GKI.config +++ b/arch/arm64/configs/vendor/kona_le_GKI.config @@ -257,6 +257,8 @@ CONFIG_QPNP_REVID=m CONFIG_QPNP_SMB5=m # CONFIG_QPNP_SMBLITE is not set CONFIG_QPNP_USB_PDPHY=m +CONFIG_QRC=m +CONFIG_QRC_DEBUG=m CONFIG_QRTR=m # CONFIG_QRTR_GENPOOL is not set # CONFIG_QRTR_GUNYAH is not set diff --git a/arch/arm64/configs/vendor/kona_le_consolidate.config b/arch/arm64/configs/vendor/kona_le_consolidate.config index 22d6275fcac9..06934b4d9adf 100644 --- a/arch/arm64/configs/vendor/kona_le_consolidate.config +++ b/arch/arm64/configs/vendor/kona_le_consolidate.config @@ -50,8 +50,6 @@ CONFIG_PM_DEBUG=y CONFIG_PM_SLEEP_DEBUG=y # CONFIG_PM_TEST_SUSPEND is not set CONFIG_PREEMPTIRQ_TRACEPOINTS=y -CONFIG_QRC=m -CONFIG_QRC_DEBUG=m # CONFIG_RBTREE_TEST is not set CONFIG_RCU_TORTURE_TEST=m # CONFIG_REED_SOLOMON_TEST is not set diff --git a/arch/arm64/configs/vendor/qcs405.config b/arch/arm64/configs/vendor/qcs405.config index b87ae669178f..3fe3e52e2715 100644 --- a/arch/arm64/configs/vendor/qcs405.config +++ b/arch/arm64/configs/vendor/qcs405.config @@ -1,7 +1,5 @@ CONFIG_ANON_VMA_NAME=y CONFIG_ARCH_QCS405=y -CONFIG_ARM_QCOM_CPUFREQ_HW=y -CONFIG_ARM_QCOM_CPUFREQ_HW_DEBUG=y CONFIG_ARM_SMMU=y CONFIG_ARM_SMMU_DISABLE_BYPASS_BY_DEFAULT=y CONFIG_ARM_SMMU_QCOM=y @@ -36,6 +34,7 @@ CONFIG_DWMAC_QCOM_ETHQOS=y # CONFIG_EP_PCIE is not set # CONFIG_ETHQOS_QCOM_SERDES is not set # CONFIG_GPIO_SYSFS is not set +# CONFIG_HID_MULTITOUCH is not set CONFIG_HWMON=y CONFIG_HWSPINLOCK_QCOM=y CONFIG_I2C_CHARDEV=y @@ -43,12 +42,15 @@ CONFIG_I2C_MSM_V2=y CONFIG_I2C_SLAVE_QCOM=y CONFIG_I2C_SLAVE_TEST=y CONFIG_INPUT_QPNP_POWER_ON=y +# CONFIG_INPUT_TOUCHSCREEN is not set CONFIG_INTERCONNECT_QCOM=y CONFIG_INTERCONNECT_QCOM_DEBUG=y CONFIG_INTERCONNECT_QCOM_QCS405=y CONFIG_INTERCONNECT_QCOM_QOS_RPM=y CONFIG_INTERCONNECT_QCOM_RPM=y CONFIG_INTERCONNECT_TEST=y +CONFIG_INTERVAL_TREE=y +CONFIG_INTERVAL_TREE_TEST=y # CONFIG_IOMMU_IO_PGTABLE_FAST is not set CONFIG_IPC_LOGGING=y CONFIG_IPC_LOG_MINIDUMP_BUFFERS=16 @@ -78,7 +80,6 @@ CONFIG_MSM_BOOT_STATS=y # CONFIG_MSM_BOOT_TIME_MARKER is not set CONFIG_MSM_CDSP_LOADER=y CONFIG_MSM_CORE_HANG_DETECT=y -CONFIG_MSM_GPI_DMA=y CONFIG_MSM_HSUSB_PHY=y CONFIG_MSM_L2_SPM=y CONFIG_MSM_QMP=y @@ -108,7 +109,6 @@ CONFIG_POWER_SUPPLY_HWMON=y CONFIG_PWM_QTI_LPG=y CONFIG_QCOM_APCS_IPC=y CONFIG_QCOM_BALANCE_ANON_FILE_RECLAIM=y -CONFIG_QCOM_BAM_DMA=y CONFIG_QCOM_BWMON=y # CONFIG_QCOM_CLK_APCC_MSM8996 is not set # CONFIG_QCOM_CLK_APCS_MSM8916 is not set @@ -180,7 +180,6 @@ CONFIG_QCOM_SPMI_ADC5=y CONFIG_QCOM_SPMI_ADC_TM5=y CONFIG_QCOM_SPMI_TEMP_ALARM=y # CONFIG_QCOM_SPSS is not set -CONFIG_QCOM_SPS_DMA=y CONFIG_QCOM_SUBSYSTEM_SLEEP_STATS=y CONFIG_QCOM_SYSMON=y # CONFIG_QCOM_SYSMON_SUBSYSTEM_STATS is not set @@ -233,6 +232,7 @@ CONFIG_QTI_RPM_STATS_LOG=y # CONFIG_QTI_THERMAL_MINIDUMP is not set CONFIG_REBOOT_MODE=y CONFIG_REGMAP_SPMI=y +CONFIG_REGULATOR_COOLING_DEVICE=y CONFIG_REGULATOR_CPR=y CONFIG_REGULATOR_MEM_ACC=y CONFIG_REGULATOR_PROXY_CONSUMER=y @@ -252,7 +252,6 @@ CONFIG_SERIAL_MSM=y # CONFIG_SERIAL_MSM_CONSOLE is not set CONFIG_SERIAL_MSM_HS=y CONFIG_SLIMBUS=y -CONFIG_SLIM_QCOM_NGD_CTRL=y CONFIG_SND=y CONFIG_SND_HRTIMER=y CONFIG_SND_SOC=y @@ -261,7 +260,6 @@ CONFIG_SOUND=y CONFIG_SPI_QUP=y CONFIG_SPI_SPIDEV=y CONFIG_SPMI_MSM_PMIC_ARB=y -CONFIG_SPMI_MSM_PMIC_ARB_DEBUG=y CONFIG_SPMI_PMIC_CLKDIV=y CONFIG_SPS=y # CONFIG_SPS_SUPPORT_BAMDMA is not set @@ -281,14 +279,12 @@ CONFIG_STM_SOURCE_FTRACE=y # CONFIG_STM_SOURCE_HEARTBEAT is not set CONFIG_THERMAL_HWMON=y CONFIG_THERMAL_TSENS_LEGACY=y -# CONFIG_TOUCHSCREEN_SUN4I is not set CONFIG_UIO_MSM_SHAREDMEM=y CONFIG_USB_DWC3_MSM=y CONFIG_USB_EHSET_TEST_FIXTURE=y # CONFIG_USB_F_FS_IPC_LOGGING is not set CONFIG_USB_MSM_SSPHY=y CONFIG_USER_NS=y -# CONFIG_VIDEO_QCOM_VENUS is not set CONFIG_XDP_SOCKETS=y CONFIG_ZRAM=y CONFIG_ZRAM_DEF_COMP="zstd" diff --git a/arch/arm64/configs/vendor/qcs405_debug.config b/arch/arm64/configs/vendor/qcs405_debug.config index d1442a7afa2f..2ef32abc8669 100644 --- a/arch/arm64/configs/vendor/qcs405_debug.config +++ b/arch/arm64/configs/vendor/qcs405_debug.config @@ -1,5 +1,6 @@ # CONFIG_ARM_SMMU_CAPTUREBUS_DEBUGFS is not set CONFIG_CMA_DEBUG=y +CONFIG_CMA_DEBUGFS=y CONFIG_CMDLINE="stack_depot_disable=off kasan.stacktrace=off cgroup_disable=pressure page_owner=on" CONFIG_CORESIGHT=y # CONFIG_CORESIGHT_CATU is not set @@ -30,6 +31,7 @@ CONFIG_DEBUG_KMEMLEAK_AUTO_SCAN=y CONFIG_DEBUG_KMEMLEAK_DEFAULT_OFF=y CONFIG_DEBUG_KMEMLEAK_MEM_POOL_SIZE=16000 # CONFIG_DEBUG_KOBJECT_RELEASE is not set +CONFIG_DEBUG_MEMORY_INIT=y CONFIG_DEBUG_MUTEXES=y CONFIG_DEBUG_OBJECTS=y CONFIG_DEBUG_OBJECTS_ENABLE_DEFAULT=1 @@ -42,6 +44,7 @@ CONFIG_DEBUG_OBJECTS_WORK=y CONFIG_DEBUG_PAGEALLOC=y # CONFIG_DEBUG_PAGEALLOC_ENABLE_DEFAULT is not set CONFIG_DEBUG_SPINLOCK=y +CONFIG_DEBUG_STACK_USAGE=y CONFIG_DYNAMIC_DEBUG=y CONFIG_ECPRI_DMA=y # CONFIG_ETM4X_IMPDEF_FEATURE is not set @@ -52,11 +55,11 @@ CONFIG_INPUT_GPIO_BEEPER=y CONFIG_INPUT_QPNP_POWER_ON=y CONFIG_INPUT_TABLET=y CONFIG_IOMMU_TLBSYNC_DEBUG=y +CONFIG_KUNIT_DEBUGFS=y CONFIG_LKDTM=y CONFIG_LOCK_TORTURE_TEST=y CONFIG_MODULE_SIG_HASH="sha512" CONFIG_MODULE_SIG_SHA512=y -CONFIG_MSM_GPI_DMA_DEBUG=y CONFIG_MSM_SNPS_FEMTO_PHY=y CONFIG_MSM_TZ_SMMU=y CONFIG_PARTITION_ADVANCED=y @@ -67,7 +70,6 @@ CONFIG_QCOM_GLINK=y CONFIG_QCOM_GLINK_PKT=y CONFIG_QCOM_IOMMU_DEBUG=y CONFIG_QCOM_SMP2P_SLEEPSTATE=y -CONFIG_QCOM_SPS_DMA=y CONFIG_QCOM_SYSMON_SUBSYSTEM_STATS=y CONFIG_QRTR=y # CONFIG_QRTR_BPF_FILTER is not set @@ -104,8 +106,6 @@ CONFIG_SPMI_PMIC_CLKDIV=y CONFIG_STM_PROTO_OST=y CONFIG_THERMAL_TSENS_LEGACY=y CONFIG_TORTURE_TEST=y -CONFIG_TOUCHSCREEN_ATMEL_MXT=y -CONFIG_TOUCHSCREEN_BU21029=y CONFIG_USB_DWC3_MSM=y CONFIG_USB_EHSET_TEST_FIXTURE=y # CONFIG_USB_F_FS_IPC_LOGGING is not set diff --git a/arch/arm64/configs/vendor/qcs605_GKI.config b/arch/arm64/configs/vendor/qcs605_GKI.config new file mode 100644 index 000000000000..3ec76a43e557 --- /dev/null +++ b/arch/arm64/configs/vendor/qcs605_GKI.config @@ -0,0 +1,279 @@ +CONFIG_ARCH_QCOM=y +CONFIG_ARCH_SDM670=y +CONFIG_ARM_QCOM_CPUFREQ_HW=m +CONFIG_ARM_QCOM_CPUFREQ_HW_DEBUG=m +CONFIG_ARM_SMMU=m +CONFIG_ARM_SMMU_DISABLE_BYPASS_BY_DEFAULT=y +# CONFIG_ARM_SMMU_SELFTEST is not set +CONFIG_CFG80211=m +# CONFIG_CFG80211_CRDA_SUPPORT is not set +# CONFIG_CFG80211_DEBUGFS is not set +# CONFIG_CFG80211_DEFAULT_PS is not set +# CONFIG_CFG80211_DEVELOPER_WARNINGS is not set +CONFIG_CFG80211_REQUIRE_SIGNED_REGDB=y +CONFIG_CFG80211_USE_KERNEL_REGDB_KEYS=y +# CONFIG_CFG80211_WEXT is not set +# CONFIG_CHARGER_QCOM_SMBB is not set +CONFIG_CHR_DEV_SG=m +CONFIG_COMMON_CLK_QCOM=m +# CONFIG_COMPAT_BRK is not set +CONFIG_CORESIGHT=m +CONFIG_CORESIGHT_CTI=m +CONFIG_CORESIGHT_DUMMY=m +CONFIG_CORESIGHT_HWEVENT=m +CONFIG_CORESIGHT_LINKS_AND_SINKS=m +CONFIG_CORESIGHT_LINK_AND_SINK_TMC=m +CONFIG_CORESIGHT_REMOTE_ETM=m +CONFIG_CORESIGHT_STM=m +CONFIG_CORESIGHT_TGU=m +CONFIG_CORESIGHT_TPDA=m +CONFIG_CORESIGHT_TPDM=m +CONFIG_CPU_FREQ_GOV_ONDEMAND=m +CONFIG_CPU_FREQ_GOV_USERSPACE=m +CONFIG_CPU_IDLE_GOV_QCOM_LPM=m +# CONFIG_DEBUG_PREEMPT is not set +CONFIG_EXTCON_USB_GPIO=m +CONFIG_HWSPINLOCK_QCOM=m +CONFIG_HW_RANDOM_MSM_LEGACY=m +CONFIG_I2C_MSM_GENI=m +# CONFIG_INPUT_PM8XXX_VIBRATOR is not set +CONFIG_INPUT_QPNP_POWER_ON=m +CONFIG_INPUT_QTI_HAPTICS=m +CONFIG_INTERCONNECT_QCOM=m +CONFIG_INTERCONNECT_QCOM_BCM_VOTER=m +CONFIG_INTERCONNECT_QCOM_DEBUG=m +CONFIG_INTERCONNECT_QCOM_QOS=m +CONFIG_INTERCONNECT_QCOM_RPMH=m +CONFIG_INTERCONNECT_QCOM_RPMH_POSSIBLE=m +CONFIG_INTERCONNECT_QCOM_SDM670=m +CONFIG_IOMMU_IO_PGTABLE_FAST=y +# CONFIG_IOMMU_IO_PGTABLE_FAST_PROVE_TLB is not set +# CONFIG_IOMMU_IO_PGTABLE_FAST_SELFTEST is not set +CONFIG_IPA3=m +CONFIG_IPC_LOGGING=m +CONFIG_IPC_LOG_MINIDUMP_BUFFERS=16 +CONFIG_LEDS_QPNP_FLASH_V2=m +CONFIG_LEDS_QTI_TRI_LED=m +CONFIG_LOG_CPU_MAX_BUF_SHIFT=17 +CONFIG_MEM_SHARE_QMI_SERVICE=m +CONFIG_MFD_I2C_PMIC=m +CONFIG_MFD_SPMI_PMIC=m +# CONFIG_MFD_WCD934X is not set +CONFIG_MINIDUMP_MAX_ENTRIES=200 +CONFIG_MMC_BLOCK_MINORS=32 +CONFIG_MMC_SDHCI_MSM=m +# CONFIG_MODULE_SIG_ALL is not set +CONFIG_MSM_ADSPRPC=m +CONFIG_MSM_BOOT_STATS=m +CONFIG_MSM_CDSP_LOADER=m +CONFIG_MSM_CORE_HANG_DETECT=m +CONFIG_MSM_GPI_DMA=m +# CONFIG_MSM_GPI_DMA_DEBUG is not set +CONFIG_MSM_PERFORMANCE=m +CONFIG_MSM_QMP=m +CONFIG_MSM_QUSB_PHY=m +CONFIG_MSM_RDBG=m +CONFIG_MSM_SYSSTATS=m +CONFIG_MSM_TMECOM_QMP=m +# CONFIG_NETFILTER_XT_MATCH_L2TP is not set +# CONFIG_NETFILTER_XT_MATCH_SCTP is not set +CONFIG_NL80211_TESTMODE=y +CONFIG_NOP_USB_XCEIV=m +# CONFIG_NVMEM_SYSFS is not set +CONFIG_PCI_MSM=m +CONFIG_PDR_INDICATION_NOTIF_TIMEOUT=9000 +CONFIG_PHY_QCOM_UFS=m +CONFIG_PHY_QCOM_UFS_QRBTC_SDM845=m +CONFIG_PHY_QCOM_UFS_V4=m +CONFIG_PINCTRL_QCOM_SPMI_PMIC=m +CONFIG_PINCTRL_SDM670=m +# CONFIG_PM8916_WATCHDOG is not set +CONFIG_POWER_RESET_MSM=m +# CONFIG_PRISM2_USB is not set +CONFIG_PWM_QTI_LPG=m +CONFIG_QCOM_AOSS_QMP=m +CONFIG_QCOM_APCS_IPC=m +CONFIG_QCOM_BALANCE_ANON_FILE_RECLAIM=y +CONFIG_QCOM_BWMON=m +CONFIG_QCOM_CDSP_RM=m +CONFIG_QCOM_CLK_RPMH=m +# CONFIG_QCOM_COINCELL is not set +CONFIG_QCOM_COMMAND_DB=m +CONFIG_QCOM_CPUSS_SLEEP_STATS=m +CONFIG_QCOM_CPU_VENDOR_HOOKS=m +CONFIG_QCOM_DCC_V2=m +CONFIG_QCOM_DCVS=m +CONFIG_QCOM_DCVS_FP=m +CONFIG_QCOM_DMABUF_HEAPS=m +CONFIG_QCOM_DMABUF_HEAPS_BITSTREAM_CONTIG=y +CONFIG_QCOM_DMABUF_HEAPS_CARVEOUT=y +CONFIG_QCOM_DMABUF_HEAPS_CMA=y +CONFIG_QCOM_DMABUF_HEAPS_PAGE_POOL_REFILL=y +CONFIG_QCOM_DMABUF_HEAPS_SYSTEM=y +CONFIG_QCOM_DMABUF_HEAPS_SYSTEM_SECURE=y +# CONFIG_QCOM_DMABUF_HEAPS_SYSTEM_UNCACHED is not set +# CONFIG_QCOM_DYN_MINIDUMP_STACK is not set +CONFIG_QCOM_EUD=m +CONFIG_QCOM_FORCE_WDOG_BITE_ON_PANIC=y +CONFIG_QCOM_GDSC_REGULATOR=m +CONFIG_QCOM_GLINK=m +CONFIG_QCOM_GLINK_PKT=m +# CONFIG_QCOM_GUESTVM is not set +CONFIG_QCOM_HUNG_TASK_ENH=m +CONFIG_QCOM_IOMMU_DEBUG=m +CONFIG_QCOM_IOMMU_UTIL=m +# CONFIG_QCOM_IPA is not set +CONFIG_QCOM_IRQ_STAT=y +CONFIG_QCOM_LAZY_MAPPING=m +CONFIG_QCOM_LLCC=m +CONFIG_QCOM_LLCC_PERFMON=m +CONFIG_QCOM_LLCC_PMU=m +CONFIG_QCOM_LOGBUF_VENDOR_HOOKS=m +CONFIG_QCOM_MDT_LOADER=m +CONFIG_QCOM_MEMLAT=m +CONFIG_QCOM_MEMORY_DUMP_V2=m +CONFIG_QCOM_MEM_BUF=m +CONFIG_QCOM_MEM_BUF_DEV=m +CONFIG_QCOM_MEM_HOOKS=m +CONFIG_QCOM_MEM_OFFLINE=m +# CONFIG_QCOM_MICRODUMP is not set +CONFIG_QCOM_MINIDUMP=m +CONFIG_QCOM_MINIDUMP_FTRACE=y +CONFIG_QCOM_MINIDUMP_PANIC_CPU_CONTEXT=y +CONFIG_QCOM_MINIDUMP_PANIC_DUMP=y +CONFIG_QCOM_MINIDUMP_PSTORE=y +CONFIG_QCOM_PANEL_EVENT_NOTIFIER=m +CONFIG_QCOM_PANIC_ON_NOTIF_TIMEOUT=y +CONFIG_QCOM_PDC=m +CONFIG_QCOM_PDR_HELPERS=m +CONFIG_QCOM_PIL_INFO=m +CONFIG_QCOM_PMU_LIB=m +CONFIG_QCOM_POWER_SUPPLY=y +# CONFIG_QCOM_Q6V5_ADSP is not set +CONFIG_QCOM_Q6V5_COMMON=m +# CONFIG_QCOM_Q6V5_MSS is not set +CONFIG_QCOM_Q6V5_PAS=m +# CONFIG_QCOM_Q6V5_WCSS is not set +CONFIG_QCOM_QFPROM=m +CONFIG_QCOM_QFPROM_SYS=m +CONFIG_QCOM_QMI_HELPERS=m +CONFIG_QCOM_RAMDUMP=m +CONFIG_QCOM_RPMH=m +CONFIG_QCOM_RPROC_COMMON=m +CONFIG_QCOM_RUN_QUEUE_STATS=m +CONFIG_QCOM_SCM=m +CONFIG_QCOM_SECURE_BUFFER=m +CONFIG_QCOM_SHOW_RESUME_IRQ=m +CONFIG_QCOM_SMEM=m +CONFIG_QCOM_SMP2P=m +CONFIG_QCOM_SMP2P_SLEEPSTATE=m +# CONFIG_QCOM_SMSM is not set +CONFIG_QCOM_SOCINFO=m +CONFIG_QCOM_SOC_SLEEP_STATS=m +# CONFIG_QCOM_SOC_WATCHDOG is not set +CONFIG_QCOM_SPMI_ADC5_GEN3=m +CONFIG_QCOM_SPMI_TEMP_ALARM=m +CONFIG_QCOM_SYSMON=m +CONFIG_QCOM_SYSMON_SUBSYSTEM_STATS=m +CONFIG_QCOM_TSENS=m +CONFIG_QCOM_VADC_COMMON=m +CONFIG_QCOM_VA_MINIDUMP=m +CONFIG_QCOM_WATCHDOG_BARK_TIME=11000 +CONFIG_QCOM_WATCHDOG_IPI_PING=y +CONFIG_QCOM_WATCHDOG_PET_TIME=9360 +# CONFIG_QCOM_WATCHDOG_USERSPACE_PET is not set +CONFIG_QCOM_WATCHDOG_WAKEUP_ENABLE=y +# CONFIG_QCOM_WCNSS_PIL is not set +# CONFIG_QCOM_WDOG_BITE_EARLY_PANIC is not set +CONFIG_QCOM_WDT_CORE=m +# CONFIG_QPNP_QG is not set +# CONFIG_QPNP_QNOVO5 is not set +# CONFIG_QPNP_SMB5 is not set +# CONFIG_QPNP_SMBLITE is not set +CONFIG_QPNP_USB_PDPHY=m +CONFIG_QRTR=m +CONFIG_QSEECOM_PROXY=m +CONFIG_QTI_CRYPTO_COMMON=m +CONFIG_QTI_HW_KEY_MANAGER=m +CONFIG_QTI_IOMMU_SUPPORT=m +CONFIG_QTI_PMIC_GLINK=m +# CONFIG_QTI_PMIC_GLINK_CLIENT_DEBUG is not set +CONFIG_QTI_QMI_COOLING_DEVICE=m +CONFIG_QTI_THERMAL_LIMITS_DCVS=m +# CONFIG_R8188EU is not set +# CONFIG_R8712U is not set +# CONFIG_RD_LZ4 is not set +CONFIG_REGMAP_QTI_DEBUGFS=m +# CONFIG_REGMAP_QTI_DEBUGFS_ALLOW_WRITE is not set +CONFIG_REGMAP_SPMI=m +CONFIG_REGULATOR_DEBUG_CONTROL=m +CONFIG_REGULATOR_PROXY_CONSUMER=m +# CONFIG_REGULATOR_PROXY_CONSUMER_LEGACY is not set +CONFIG_REGULATOR_QTI_FIXED_VOLTAGE=m +CONFIG_REGULATOR_QTI_OCP_NOTIFIER=m +CONFIG_REGULATOR_REFGEN=m +CONFIG_REGULATOR_RPMH=m +CONFIG_REGULATOR_STUB=m +CONFIG_RPMSG_QCOM_GLINK=m +CONFIG_RPMSG_QCOM_GLINK_SMEM=m +CONFIG_RPMSG_QCOM_GLINK_SPSS=m +CONFIG_RPMSG_QCOM_SMD=m +CONFIG_RPROC_SSR_NOTIF_TIMEOUT=20000 +CONFIG_RPROC_SYSMON_NOTIF_TIMEOUT=20000 +# CONFIG_RTL8723BS is not set +CONFIG_SCHED_WALT=m +CONFIG_SCSI_UFS_CRYPTO_QTI=m +CONFIG_SCSI_UFS_QCOM=m +CONFIG_SDM_CAMCC_845=m +CONFIG_SDM_DISPCC_845=m +CONFIG_SDM_GCC_845=m +CONFIG_SDM_GPUCC_845=m +CONFIG_SDM_VIDEOCC_845=m +CONFIG_SERIAL_MSM_GENI=m +# CONFIG_SERIO_SERPORT is not set +CONFIG_SLIMBUS=m +# CONFIG_SLIM_QCOM_CTRL is not set +CONFIG_SLIM_QCOM_NGD_CTRL=m +CONFIG_SMB1355_SLAVE_CHARGER=m +# CONFIG_SMB1390_CHARGE_PUMP_PSY is not set +# CONFIG_SMB1398_CHARGER is not set +# CONFIG_SMB23X_CHARGER is not set +# CONFIG_SMB358_CHARGER is not set +# CONFIG_SND_SOC_WCD9335 is not set +CONFIG_SND_USB_AUDIO_QMI=m +CONFIG_SPI_MSM_GENI=m +CONFIG_SPI_QUP=m +CONFIG_SPMI_MSM_PMIC_ARB=m +CONFIG_SPMI_MSM_PMIC_ARB_DEBUG=m +CONFIG_SPS=m +# CONFIG_SPS_SUPPORT_BAMDMA is not set +CONFIG_SPS_SUPPORT_NDP_BAM=y +CONFIG_STM_PROTO_BASIC=m +CONFIG_STM_PROTO_OST=m +CONFIG_STM_SOURCE_CONSOLE=m +CONFIG_STM_SOURCE_FTRACE=m +# CONFIG_SWIOTLB_NONLINEAR is not set +CONFIG_UIO_MSM_SHAREDMEM=m +CONFIG_USB_BAM=m +CONFIG_USB_CONFIGFS_F_CCID=m +CONFIG_USB_CONFIGFS_F_CDEV=m +CONFIG_USB_CONFIGFS_F_DIAG=m +CONFIG_USB_CONFIGFS_F_GSI=m +CONFIG_USB_CONFIGFS_F_QDSS=m +CONFIG_USB_DWC3_MSM=m +CONFIG_USB_EHSET_TEST_FIXTURE=m +CONFIG_USB_F_CCID=m +CONFIG_USB_F_CDEV=m +CONFIG_USB_F_DIAG=m +CONFIG_USB_F_FS_IPC_LOGGING=m +CONFIG_USB_F_GSI=m +CONFIG_USB_F_QDSS=m +CONFIG_USB_MSM_SSPHY_QMP=m +# CONFIG_USB_NET_RNDIS_WLAN is not set +CONFIG_USB_PD_POLICY=m +CONFIG_USB_QCOM_EMU_PHY=m +# CONFIG_UTS_NS is not set +# CONFIG_VIDEO_QCOM_VENUS is not set +# CONFIG_VIRT_WIFI is not set +# CONFIG_WILC1000_SDIO is not set +# CONFIG_WILC1000_SPI is not set diff --git a/arch/arm64/configs/vendor/qcs605_consolidate.config b/arch/arm64/configs/vendor/qcs605_consolidate.config new file mode 100644 index 000000000000..f3fc605d166d --- /dev/null +++ b/arch/arm64/configs/vendor/qcs605_consolidate.config @@ -0,0 +1,25 @@ +CONFIG_ATOMIC64_SELFTEST=m +CONFIG_BUG_ON_HW_MEM_ONLINE_FAIL=y +CONFIG_CMA_DEBUGFS=y +CONFIG_CNSS2_DEBUG=y +CONFIG_CORESIGHT_SOURCE_ETM4X=m +CONFIG_QTI_THERMALZONE_CONFIG_DEBUG=m +CONFIG_HYP_ASSIGN_DEBUG=y +CONFIG_I2C_CHARDEV=m +CONFIG_ICNSS2_DEBUG=y +CONFIG_IOMMU_TLBSYNC_DEBUG=y +CONFIG_LKDTM=m +CONFIG_LOCALVERSION="-gki-consolidate" +CONFIG_LOCK_TORTURE_TEST=m +CONFIG_MSM_GPI_DMA_DEBUG=y +CONFIG_PARTITION_ADVANCED=y +# CONFIG_QCOM_DYN_MINIDUMP_STACK is not set +CONFIG_QTI_PMIC_GLINK_CLIENT_DEBUG=y +CONFIG_RCU_TORTURE_TEST=m +CONFIG_REGMAP_QTI_DEBUGFS_ALLOW_WRITE=y +CONFIG_RPMSG_QCOM_GLINK_DEBUG=y +CONFIG_RUNTIME_TESTING_MENU=y +CONFIG_SCHED_WALT_DEBUG=m +CONFIG_SPI_SPIDEV=m +CONFIG_TEST_USER_COPY=m +CONFIG_UFS_DBG=y diff --git a/arch/arm64/configs/vendor/trinket_GKI.config b/arch/arm64/configs/vendor/trinket_GKI.config index 35aa73cf3e34..238e55870aba 100644 --- a/arch/arm64/configs/vendor/trinket_GKI.config +++ b/arch/arm64/configs/vendor/trinket_GKI.config @@ -60,6 +60,7 @@ CONFIG_MFD_SPMI_PMIC=m CONFIG_MINIDUMP_MAX_ENTRIES=200 CONFIG_MMC_BLOCK_MINORS=32 CONFIG_MMC_CQHCI=m +CONFIG_MMC_CRYPTO_QTI=m CONFIG_MMC_SDHCI_MSM=m # CONFIG_MODULE_SIG_ALL is not set CONFIG_MSM_ADSPRPC=m @@ -88,6 +89,7 @@ CONFIG_NOP_USB_XCEIV=m CONFIG_NVMEM_SPMI_SDAM=m # CONFIG_NVMEM_SYSFS is not set CONFIG_PHY_QCOM_UFS=m +CONFIG_PHY_QCOM_UFS_V3=m CONFIG_PHY_QCOM_UFS_V4=m CONFIG_PHY_XGENE=m CONFIG_PINCTRL_MSM=m @@ -200,6 +202,9 @@ CONFIG_QTI_CHARGER_ULOG_GLINK=m CONFIG_QTI_CPUFREQ_CDEV=m CONFIG_QTI_CPU_HOTPLUG_COOLING_DEVICE=m CONFIG_QTI_CPU_PAUSE_COOLING_DEVICE=m +CONFIG_QTI_CRYPTO_COMMON=m +# CONFIG_QTI_CRYPTO_FDE is not set +CONFIG_QTI_CRYPTO_TZ=m CONFIG_QTI_DEVFREQ_CDEV=m CONFIG_QTI_IOMMU_SUPPORT=m CONFIG_QTI_LMH_CPU_VDD_COOLING_DEVICE=m @@ -208,7 +213,7 @@ CONFIG_QTI_PMIC_GLINK=m # CONFIG_QTI_QBG is not set CONFIG_QTI_QMI_COOLING_DEVICE=m CONFIG_QTI_QMI_SENSOR=m -# CONFIG_QTI_RPM_SMD_COOLING_DEVICE is not set +CONFIG_QTI_RPM_SMD_COOLING_DEVICE=m CONFIG_QTI_RPM_STATS_LOG=m CONFIG_QTI_THERMAL_LIMITS_DCVS=m # CONFIG_R8188EU is not set @@ -217,6 +222,7 @@ CONFIG_QTI_THERMAL_LIMITS_DCVS=m CONFIG_REGMAP_QTI_DEBUGFS=m # CONFIG_REGMAP_QTI_DEBUGFS_ALLOW_WRITE is not set CONFIG_REGMAP_SPMI=m +CONFIG_REGULATOR_COOLING_DEVICE=m CONFIG_REGULATOR_DEBUG_CONTROL=m CONFIG_REGULATOR_PROXY_CONSUMER=m # CONFIG_REGULATOR_PROXY_CONSUMER_LEGACY is not set @@ -249,6 +255,7 @@ CONFIG_SM_GCC_TRINKET=m CONFIG_SM_GPUCC_TRINKET=m CONFIG_SM_VIDEOCC_TRINKET=m # CONFIG_SND_SOC_WCD9335 is not set +CONFIG_SND_USB_AUDIO_QMI=m CONFIG_SPI_MSM_GENI=m CONFIG_SPI_QCOM_GENI=m CONFIG_SPMI_MSM_PMIC_ARB=m diff --git a/arch/mips/include/asm/dec/prom.h b/arch/mips/include/asm/dec/prom.h index 1e1247add1cf..908e96e3a311 100644 --- a/arch/mips/include/asm/dec/prom.h +++ b/arch/mips/include/asm/dec/prom.h @@ -70,7 +70,7 @@ static inline bool prom_is_rex(u32 magic) */ typedef struct { int pagesize; - unsigned char bitmap[0]; + unsigned char bitmap[]; } memmap; diff --git a/arch/mips/include/asm/kvm_host.h b/arch/mips/include/asm/kvm_host.h index 696f6b009377..cfd9e1581777 100644 --- a/arch/mips/include/asm/kvm_host.h +++ b/arch/mips/include/asm/kvm_host.h @@ -318,7 +318,7 @@ struct kvm_vcpu_arch { unsigned int aux_inuse; /* COP0 State */ - struct mips_coproc *cop0; + struct mips_coproc cop0; /* Resume PC after MMIO completion */ unsigned long io_pc; @@ -699,7 +699,7 @@ static inline bool kvm_mips_guest_can_have_fpu(struct kvm_vcpu_arch *vcpu) static inline bool kvm_mips_guest_has_fpu(struct kvm_vcpu_arch *vcpu) { return kvm_mips_guest_can_have_fpu(vcpu) && - kvm_read_c0_guest_config1(vcpu->cop0) & MIPS_CONF1_FP; + kvm_read_c0_guest_config1(&vcpu->cop0) & MIPS_CONF1_FP; } static inline bool kvm_mips_guest_can_have_msa(struct kvm_vcpu_arch *vcpu) @@ -711,7 +711,7 @@ static inline bool kvm_mips_guest_can_have_msa(struct kvm_vcpu_arch *vcpu) static inline bool kvm_mips_guest_has_msa(struct kvm_vcpu_arch *vcpu) { return kvm_mips_guest_can_have_msa(vcpu) && - kvm_read_c0_guest_config3(vcpu->cop0) & MIPS_CONF3_MSA; + kvm_read_c0_guest_config3(&vcpu->cop0) & MIPS_CONF3_MSA; } struct kvm_mips_callbacks { diff --git a/arch/mips/kernel/cpu-probe.c b/arch/mips/kernel/cpu-probe.c index 7c861e6a8952..8ebcc298bf75 100644 --- a/arch/mips/kernel/cpu-probe.c +++ b/arch/mips/kernel/cpu-probe.c @@ -1734,7 +1734,10 @@ static inline void decode_cpucfg(struct cpuinfo_mips *c) static inline void cpu_probe_loongson(struct cpuinfo_mips *c, unsigned int cpu) { + c->cputype = CPU_LOONGSON64; + /* All Loongson processors covered here define ExcCode 16 as GSExc. */ + decode_configs(c); c->options |= MIPS_CPU_GSEXCEX; switch (c->processor_id & PRID_IMP_MASK) { @@ -1744,7 +1747,6 @@ static inline void cpu_probe_loongson(struct cpuinfo_mips *c, unsigned int cpu) case PRID_REV_LOONGSON2K_R1_1: case PRID_REV_LOONGSON2K_R1_2: case PRID_REV_LOONGSON2K_R1_3: - c->cputype = CPU_LOONGSON64; __cpu_name[cpu] = "Loongson-2K"; set_elf_platform(cpu, "gs264e"); set_isa(c, MIPS_CPU_ISA_M64R2); @@ -1757,14 +1759,12 @@ static inline void cpu_probe_loongson(struct cpuinfo_mips *c, unsigned int cpu) switch (c->processor_id & PRID_REV_MASK) { case PRID_REV_LOONGSON3A_R2_0: case PRID_REV_LOONGSON3A_R2_1: - c->cputype = CPU_LOONGSON64; __cpu_name[cpu] = "ICT Loongson-3"; set_elf_platform(cpu, "loongson3a"); set_isa(c, MIPS_CPU_ISA_M64R2); break; case PRID_REV_LOONGSON3A_R3_0: case PRID_REV_LOONGSON3A_R3_1: - c->cputype = CPU_LOONGSON64; __cpu_name[cpu] = "ICT Loongson-3"; set_elf_platform(cpu, "loongson3a"); set_isa(c, MIPS_CPU_ISA_M64R2); @@ -1784,7 +1784,6 @@ static inline void cpu_probe_loongson(struct cpuinfo_mips *c, unsigned int cpu) c->ases &= ~MIPS_ASE_VZ; /* VZ of Loongson-3A2000/3000 is incomplete */ break; case PRID_IMP_LOONGSON_64G: - c->cputype = CPU_LOONGSON64; __cpu_name[cpu] = "ICT Loongson-3"; set_elf_platform(cpu, "loongson3a"); set_isa(c, MIPS_CPU_ISA_M64R2); @@ -1794,8 +1793,6 @@ static inline void cpu_probe_loongson(struct cpuinfo_mips *c, unsigned int cpu) panic("Unknown Loongson Processor ID!"); break; } - - decode_configs(c); } #else static inline void cpu_probe_loongson(struct cpuinfo_mips *c, unsigned int cpu) { } diff --git a/arch/mips/kvm/emulate.c b/arch/mips/kvm/emulate.c index 22e745e49b0a..3e80b0b2deaa 100644 --- a/arch/mips/kvm/emulate.c +++ b/arch/mips/kvm/emulate.c @@ -312,7 +312,7 @@ int kvm_get_badinstrp(u32 *opc, struct kvm_vcpu *vcpu, u32 *out) */ int kvm_mips_count_disabled(struct kvm_vcpu *vcpu) { - struct mips_coproc *cop0 = vcpu->arch.cop0; + struct mips_coproc *cop0 = &vcpu->arch.cop0; return (vcpu->arch.count_ctl & KVM_REG_MIPS_COUNT_CTL_DC) || (kvm_read_c0_guest_cause(cop0) & CAUSEF_DC); @@ -384,7 +384,7 @@ static inline ktime_t kvm_mips_count_time(struct kvm_vcpu *vcpu) */ static u32 kvm_mips_read_count_running(struct kvm_vcpu *vcpu, ktime_t now) { - struct mips_coproc *cop0 = vcpu->arch.cop0; + struct mips_coproc *cop0 = &vcpu->arch.cop0; ktime_t expires, threshold; u32 count, compare; int running; @@ -444,7 +444,7 @@ static u32 kvm_mips_read_count_running(struct kvm_vcpu *vcpu, ktime_t now) */ u32 kvm_mips_read_count(struct kvm_vcpu *vcpu) { - struct mips_coproc *cop0 = vcpu->arch.cop0; + struct mips_coproc *cop0 = &vcpu->arch.cop0; /* If count disabled just read static copy of count */ if (kvm_mips_count_disabled(vcpu)) @@ -502,7 +502,7 @@ ktime_t kvm_mips_freeze_hrtimer(struct kvm_vcpu *vcpu, u32 *count) static void kvm_mips_resume_hrtimer(struct kvm_vcpu *vcpu, ktime_t now, u32 count) { - struct mips_coproc *cop0 = vcpu->arch.cop0; + struct mips_coproc *cop0 = &vcpu->arch.cop0; u32 compare; u64 delta; ktime_t expire; @@ -603,7 +603,7 @@ resume: */ void kvm_mips_write_count(struct kvm_vcpu *vcpu, u32 count) { - struct mips_coproc *cop0 = vcpu->arch.cop0; + struct mips_coproc *cop0 = &vcpu->arch.cop0; ktime_t now; /* Calculate bias */ @@ -649,7 +649,7 @@ void kvm_mips_init_count(struct kvm_vcpu *vcpu, unsigned long count_hz) */ int kvm_mips_set_count_hz(struct kvm_vcpu *vcpu, s64 count_hz) { - struct mips_coproc *cop0 = vcpu->arch.cop0; + struct mips_coproc *cop0 = &vcpu->arch.cop0; int dc; ktime_t now; u32 count; @@ -696,7 +696,7 @@ int kvm_mips_set_count_hz(struct kvm_vcpu *vcpu, s64 count_hz) */ void kvm_mips_write_compare(struct kvm_vcpu *vcpu, u32 compare, bool ack) { - struct mips_coproc *cop0 = vcpu->arch.cop0; + struct mips_coproc *cop0 = &vcpu->arch.cop0; int dc; u32 old_compare = kvm_read_c0_guest_compare(cop0); s32 delta = compare - old_compare; @@ -779,7 +779,7 @@ void kvm_mips_write_compare(struct kvm_vcpu *vcpu, u32 compare, bool ack) */ static ktime_t kvm_mips_count_disable(struct kvm_vcpu *vcpu) { - struct mips_coproc *cop0 = vcpu->arch.cop0; + struct mips_coproc *cop0 = &vcpu->arch.cop0; u32 count; ktime_t now; @@ -806,7 +806,7 @@ static ktime_t kvm_mips_count_disable(struct kvm_vcpu *vcpu) */ void kvm_mips_count_disable_cause(struct kvm_vcpu *vcpu) { - struct mips_coproc *cop0 = vcpu->arch.cop0; + struct mips_coproc *cop0 = &vcpu->arch.cop0; kvm_set_c0_guest_cause(cop0, CAUSEF_DC); if (!(vcpu->arch.count_ctl & KVM_REG_MIPS_COUNT_CTL_DC)) @@ -826,7 +826,7 @@ void kvm_mips_count_disable_cause(struct kvm_vcpu *vcpu) */ void kvm_mips_count_enable_cause(struct kvm_vcpu *vcpu) { - struct mips_coproc *cop0 = vcpu->arch.cop0; + struct mips_coproc *cop0 = &vcpu->arch.cop0; u32 count; kvm_clear_c0_guest_cause(cop0, CAUSEF_DC); @@ -852,7 +852,7 @@ void kvm_mips_count_enable_cause(struct kvm_vcpu *vcpu) */ int kvm_mips_set_count_ctl(struct kvm_vcpu *vcpu, s64 count_ctl) { - struct mips_coproc *cop0 = vcpu->arch.cop0; + struct mips_coproc *cop0 = &vcpu->arch.cop0; s64 changed = count_ctl ^ vcpu->arch.count_ctl; s64 delta; ktime_t expire, now; diff --git a/arch/mips/kvm/mips.c b/arch/mips/kvm/mips.c index 75c6f264c626..6b15ac978658 100644 --- a/arch/mips/kvm/mips.c +++ b/arch/mips/kvm/mips.c @@ -652,7 +652,7 @@ static int kvm_mips_copy_reg_indices(struct kvm_vcpu *vcpu, u64 __user *indices) static int kvm_mips_get_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg) { - struct mips_coproc *cop0 = vcpu->arch.cop0; + struct mips_coproc *cop0 = &vcpu->arch.cop0; struct mips_fpu_struct *fpu = &vcpu->arch.fpu; int ret; s64 v; @@ -764,7 +764,7 @@ static int kvm_mips_get_reg(struct kvm_vcpu *vcpu, static int kvm_mips_set_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg) { - struct mips_coproc *cop0 = vcpu->arch.cop0; + struct mips_coproc *cop0 = &vcpu->arch.cop0; struct mips_fpu_struct *fpu = &vcpu->arch.fpu; s64 v; s64 vs[2]; @@ -1104,7 +1104,7 @@ int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext) int kvm_cpu_has_pending_timer(struct kvm_vcpu *vcpu) { return kvm_mips_pending_timer(vcpu) || - kvm_read_c0_guest_cause(vcpu->arch.cop0) & C_TI; + kvm_read_c0_guest_cause(&vcpu->arch.cop0) & C_TI; } int kvm_arch_vcpu_dump_regs(struct kvm_vcpu *vcpu) @@ -1128,7 +1128,7 @@ int kvm_arch_vcpu_dump_regs(struct kvm_vcpu *vcpu) kvm_debug("\thi: 0x%08lx\n", vcpu->arch.hi); kvm_debug("\tlo: 0x%08lx\n", vcpu->arch.lo); - cop0 = vcpu->arch.cop0; + cop0 = &vcpu->arch.cop0; kvm_debug("\tStatus: 0x%08x, Cause: 0x%08x\n", kvm_read_c0_guest_status(cop0), kvm_read_c0_guest_cause(cop0)); @@ -1250,7 +1250,7 @@ int kvm_mips_handle_exit(struct kvm_vcpu *vcpu) case EXCCODE_TLBS: kvm_debug("TLB ST fault: cause %#x, status %#x, PC: %p, BadVaddr: %#lx\n", - cause, kvm_read_c0_guest_status(vcpu->arch.cop0), opc, + cause, kvm_read_c0_guest_status(&vcpu->arch.cop0), opc, badvaddr); ++vcpu->stat.tlbmiss_st_exits; @@ -1322,7 +1322,7 @@ int kvm_mips_handle_exit(struct kvm_vcpu *vcpu) kvm_get_badinstr(opc, vcpu, &inst); kvm_err("Exception Code: %d, not yet handled, @ PC: %p, inst: 0x%08x BadVaddr: %#lx Status: %#x\n", exccode, opc, inst, badvaddr, - kvm_read_c0_guest_status(vcpu->arch.cop0)); + kvm_read_c0_guest_status(&vcpu->arch.cop0)); kvm_arch_vcpu_dump_regs(vcpu); run->exit_reason = KVM_EXIT_INTERNAL_ERROR; ret = RESUME_HOST; @@ -1384,7 +1384,7 @@ int kvm_mips_handle_exit(struct kvm_vcpu *vcpu) /* Enable FPU for guest and restore context */ void kvm_own_fpu(struct kvm_vcpu *vcpu) { - struct mips_coproc *cop0 = vcpu->arch.cop0; + struct mips_coproc *cop0 = &vcpu->arch.cop0; unsigned int sr, cfg5; preempt_disable(); @@ -1428,7 +1428,7 @@ void kvm_own_fpu(struct kvm_vcpu *vcpu) /* Enable MSA for guest and restore context */ void kvm_own_msa(struct kvm_vcpu *vcpu) { - struct mips_coproc *cop0 = vcpu->arch.cop0; + struct mips_coproc *cop0 = &vcpu->arch.cop0; unsigned int sr, cfg5; preempt_disable(); diff --git a/arch/mips/kvm/stats.c b/arch/mips/kvm/stats.c index 53f851a61554..3e6682018fbe 100644 --- a/arch/mips/kvm/stats.c +++ b/arch/mips/kvm/stats.c @@ -54,9 +54,9 @@ void kvm_mips_dump_stats(struct kvm_vcpu *vcpu) kvm_info("\nKVM VCPU[%d] COP0 Access Profile:\n", vcpu->vcpu_id); for (i = 0; i < N_MIPS_COPROC_REGS; i++) { for (j = 0; j < N_MIPS_COPROC_SEL; j++) { - if (vcpu->arch.cop0->stat[i][j]) + if (vcpu->arch.cop0.stat[i][j]) kvm_info("%s[%d]: %lu\n", kvm_cop0_str[i], j, - vcpu->arch.cop0->stat[i][j]); + vcpu->arch.cop0.stat[i][j]); } } #endif diff --git a/arch/mips/kvm/trace.h b/arch/mips/kvm/trace.h index a8c7fd7bf6d2..136c3535a1cb 100644 --- a/arch/mips/kvm/trace.h +++ b/arch/mips/kvm/trace.h @@ -322,11 +322,11 @@ TRACE_EVENT_FN(kvm_guest_mode_change, ), TP_fast_assign( - __entry->epc = kvm_read_c0_guest_epc(vcpu->arch.cop0); + __entry->epc = kvm_read_c0_guest_epc(&vcpu->arch.cop0); __entry->pc = vcpu->arch.pc; - __entry->badvaddr = kvm_read_c0_guest_badvaddr(vcpu->arch.cop0); - __entry->status = kvm_read_c0_guest_status(vcpu->arch.cop0); - __entry->cause = kvm_read_c0_guest_cause(vcpu->arch.cop0); + __entry->badvaddr = kvm_read_c0_guest_badvaddr(&vcpu->arch.cop0); + __entry->status = kvm_read_c0_guest_status(&vcpu->arch.cop0); + __entry->cause = kvm_read_c0_guest_cause(&vcpu->arch.cop0); ), TP_printk("EPC: 0x%08lx PC: 0x%08lx Status: 0x%08x Cause: 0x%08x BadVAddr: 0x%08lx", diff --git a/arch/mips/kvm/vz.c b/arch/mips/kvm/vz.c index 4adca5abbc72..717f88333316 100644 --- a/arch/mips/kvm/vz.c +++ b/arch/mips/kvm/vz.c @@ -422,7 +422,7 @@ static void _kvm_vz_restore_htimer(struct kvm_vcpu *vcpu, */ static void kvm_vz_restore_timer(struct kvm_vcpu *vcpu) { - struct mips_coproc *cop0 = vcpu->arch.cop0; + struct mips_coproc *cop0 = &vcpu->arch.cop0; u32 cause, compare; compare = kvm_read_sw_gc0_compare(cop0); @@ -517,7 +517,7 @@ static void _kvm_vz_save_htimer(struct kvm_vcpu *vcpu, */ static void kvm_vz_save_timer(struct kvm_vcpu *vcpu) { - struct mips_coproc *cop0 = vcpu->arch.cop0; + struct mips_coproc *cop0 = &vcpu->arch.cop0; u32 gctl0, compare, cause; gctl0 = read_c0_guestctl0(); @@ -863,7 +863,7 @@ static unsigned long mips_process_maar(unsigned int op, unsigned long val) static void kvm_write_maari(struct kvm_vcpu *vcpu, unsigned long val) { - struct mips_coproc *cop0 = vcpu->arch.cop0; + struct mips_coproc *cop0 = &vcpu->arch.cop0; val &= MIPS_MAARI_INDEX; if (val == MIPS_MAARI_INDEX) @@ -876,7 +876,7 @@ static enum emulation_result kvm_vz_gpsi_cop0(union mips_instruction inst, u32 *opc, u32 cause, struct kvm_vcpu *vcpu) { - struct mips_coproc *cop0 = vcpu->arch.cop0; + struct mips_coproc *cop0 = &vcpu->arch.cop0; enum emulation_result er = EMULATE_DONE; u32 rt, rd, sel; unsigned long curr_pc; @@ -1905,7 +1905,7 @@ static int kvm_vz_get_one_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg, s64 *v) { - struct mips_coproc *cop0 = vcpu->arch.cop0; + struct mips_coproc *cop0 = &vcpu->arch.cop0; unsigned int idx; switch (reg->id) { @@ -2075,7 +2075,7 @@ static int kvm_vz_get_one_reg(struct kvm_vcpu *vcpu, case KVM_REG_MIPS_CP0_MAARI: if (!cpu_guest_has_maar || cpu_guest_has_dyn_maar) return -EINVAL; - *v = kvm_read_sw_gc0_maari(vcpu->arch.cop0); + *v = kvm_read_sw_gc0_maari(&vcpu->arch.cop0); break; #ifdef CONFIG_64BIT case KVM_REG_MIPS_CP0_XCONTEXT: @@ -2129,7 +2129,7 @@ static int kvm_vz_set_one_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg, s64 v) { - struct mips_coproc *cop0 = vcpu->arch.cop0; + struct mips_coproc *cop0 = &vcpu->arch.cop0; unsigned int idx; int ret = 0; unsigned int cur, change; @@ -2556,7 +2556,7 @@ static void kvm_vz_vcpu_load_tlb(struct kvm_vcpu *vcpu, int cpu) static int kvm_vz_vcpu_load(struct kvm_vcpu *vcpu, int cpu) { - struct mips_coproc *cop0 = vcpu->arch.cop0; + struct mips_coproc *cop0 = &vcpu->arch.cop0; bool migrated, all; /* @@ -2698,7 +2698,7 @@ static int kvm_vz_vcpu_load(struct kvm_vcpu *vcpu, int cpu) static int kvm_vz_vcpu_put(struct kvm_vcpu *vcpu, int cpu) { - struct mips_coproc *cop0 = vcpu->arch.cop0; + struct mips_coproc *cop0 = &vcpu->arch.cop0; if (current->flags & PF_VCPU) kvm_vz_vcpu_save_wired(vcpu); @@ -3070,7 +3070,7 @@ static void kvm_vz_vcpu_uninit(struct kvm_vcpu *vcpu) static int kvm_vz_vcpu_setup(struct kvm_vcpu *vcpu) { - struct mips_coproc *cop0 = vcpu->arch.cop0; + struct mips_coproc *cop0 = &vcpu->arch.cop0; unsigned long count_hz = 100*1000*1000; /* default to 100 MHz */ /* diff --git a/arch/parisc/include/asm/assembly.h b/arch/parisc/include/asm/assembly.h index a39250cb7dfc..fd8c1ebd2747 100644 --- a/arch/parisc/include/asm/assembly.h +++ b/arch/parisc/include/asm/assembly.h @@ -72,10 +72,6 @@ #include - sp = 30 - gp = 27 - ipsw = 22 - /* * We provide two versions of each macro to convert from physical * to virtual and vice versa. The "_r1" versions take one argument diff --git a/arch/powerpc/Kconfig.debug b/arch/powerpc/Kconfig.debug index 192f0ed0097f..80ce54f59fae 100644 --- a/arch/powerpc/Kconfig.debug +++ b/arch/powerpc/Kconfig.debug @@ -240,7 +240,7 @@ config PPC_EARLY_DEBUG_40x config PPC_EARLY_DEBUG_CPM bool "Early serial debugging for Freescale CPM-based serial ports" - depends on SERIAL_CPM + depends on SERIAL_CPM=y help Select this to enable early debugging for Freescale chips using a CPM-based serial port. This assumes that the bootwrapper diff --git a/arch/powerpc/Makefile b/arch/powerpc/Makefile index a8e52e64c1a5..3dc75040a756 100644 --- a/arch/powerpc/Makefile +++ b/arch/powerpc/Makefile @@ -444,3 +444,11 @@ checkbin: echo -n '*** Please use a different binutils version.' ; \ false ; \ fi + @if test "x${CONFIG_FTRACE_MCOUNT_USE_RECORDMCOUNT}" = "xy" -a \ + "x${CONFIG_LD_IS_BFD}" = "xy" -a \ + "${CONFIG_LD_VERSION}" = "23700" ; then \ + echo -n '*** binutils 2.37 drops unused section symbols, which recordmcount ' ; \ + echo 'is unable to handle.' ; \ + echo '*** Please use a different binutils version.' ; \ + false ; \ + fi diff --git a/arch/powerpc/kernel/interrupt.c b/arch/powerpc/kernel/interrupt.c index 8703df709cce..e93f67c3af76 100644 --- a/arch/powerpc/kernel/interrupt.c +++ b/arch/powerpc/kernel/interrupt.c @@ -531,7 +531,6 @@ void preempt_schedule_irq(void); notrace unsigned long interrupt_exit_kernel_prepare(struct pt_regs *regs) { - unsigned long flags; unsigned long ret = 0; unsigned long kuap; bool stack_store = current_thread_info()->flags & @@ -548,7 +547,7 @@ notrace unsigned long interrupt_exit_kernel_prepare(struct pt_regs *regs) kuap = kuap_get_and_assert_locked(); - local_irq_save(flags); + local_irq_disable(); if (!arch_irq_disabled_regs(regs)) { /* Returning to a kernel context with local irqs enabled. */ diff --git a/arch/powerpc/kernel/ppc_save_regs.S b/arch/powerpc/kernel/ppc_save_regs.S index 2d4d21bb46a9..235ae2428451 100644 --- a/arch/powerpc/kernel/ppc_save_regs.S +++ b/arch/powerpc/kernel/ppc_save_regs.S @@ -21,60 +21,33 @@ * different ABIs, though). */ _GLOBAL(ppc_save_regs) - PPC_STL r0,0*SZL(r3) + /* This allows stack frame accessor macros and offsets to be used */ + subi r3,r3,STACK_FRAME_OVERHEAD + PPC_STL r0,GPR0(r3) #ifdef CONFIG_PPC32 - stmw r2, 2*SZL(r3) + stmw r2,GPR2(r3) #else - PPC_STL r2,2*SZL(r3) - PPC_STL r3,3*SZL(r3) - PPC_STL r4,4*SZL(r3) - PPC_STL r5,5*SZL(r3) - PPC_STL r6,6*SZL(r3) - PPC_STL r7,7*SZL(r3) - PPC_STL r8,8*SZL(r3) - PPC_STL r9,9*SZL(r3) - PPC_STL r10,10*SZL(r3) - PPC_STL r11,11*SZL(r3) - PPC_STL r12,12*SZL(r3) - PPC_STL r13,13*SZL(r3) - PPC_STL r14,14*SZL(r3) - PPC_STL r15,15*SZL(r3) - PPC_STL r16,16*SZL(r3) - PPC_STL r17,17*SZL(r3) - PPC_STL r18,18*SZL(r3) - PPC_STL r19,19*SZL(r3) - PPC_STL r20,20*SZL(r3) - PPC_STL r21,21*SZL(r3) - PPC_STL r22,22*SZL(r3) - PPC_STL r23,23*SZL(r3) - PPC_STL r24,24*SZL(r3) - PPC_STL r25,25*SZL(r3) - PPC_STL r26,26*SZL(r3) - PPC_STL r27,27*SZL(r3) - PPC_STL r28,28*SZL(r3) - PPC_STL r29,29*SZL(r3) - PPC_STL r30,30*SZL(r3) - PPC_STL r31,31*SZL(r3) + SAVE_GPRS(2, 31, r3) lbz r0,PACAIRQSOFTMASK(r13) - PPC_STL r0,SOFTE-STACK_FRAME_OVERHEAD(r3) + PPC_STL r0,SOFTE(r3) #endif - /* go up one stack frame for SP */ - PPC_LL r4,0(r1) - PPC_STL r4,1*SZL(r3) + /* store current SP */ + PPC_STL r1,GPR1(r3) /* get caller's LR */ + PPC_LL r4,0(r1) PPC_LL r0,LRSAVE(r4) - PPC_STL r0,_LINK-STACK_FRAME_OVERHEAD(r3) + PPC_STL r0,_LINK(r3) mflr r0 - PPC_STL r0,_NIP-STACK_FRAME_OVERHEAD(r3) + PPC_STL r0,_NIP(r3) mfmsr r0 - PPC_STL r0,_MSR-STACK_FRAME_OVERHEAD(r3) + PPC_STL r0,_MSR(r3) mfctr r0 - PPC_STL r0,_CTR-STACK_FRAME_OVERHEAD(r3) + PPC_STL r0,_CTR(r3) mfxer r0 - PPC_STL r0,_XER-STACK_FRAME_OVERHEAD(r3) + PPC_STL r0,_XER(r3) mfcr r0 - PPC_STL r0,_CCR-STACK_FRAME_OVERHEAD(r3) + PPC_STL r0,_CCR(r3) li r0,0 - PPC_STL r0,_TRAP-STACK_FRAME_OVERHEAD(r3) - PPC_STL r0,ORIG_GPR3-STACK_FRAME_OVERHEAD(r3) + PPC_STL r0,_TRAP(r3) + PPC_STL r0,ORIG_GPR3(r3) blr diff --git a/arch/powerpc/kernel/security.c b/arch/powerpc/kernel/security.c index 15fb5ea1b9ea..cd6fc64ad9ca 100644 --- a/arch/powerpc/kernel/security.c +++ b/arch/powerpc/kernel/security.c @@ -363,26 +363,27 @@ ssize_t cpu_show_spec_store_bypass(struct device *dev, struct device_attribute * static int ssb_prctl_get(struct task_struct *task) { - if (stf_enabled_flush_types == STF_BARRIER_NONE) - /* - * We don't have an explicit signal from firmware that we're - * vulnerable or not, we only have certain CPU revisions that - * are known to be vulnerable. - * - * We assume that if we're on another CPU, where the barrier is - * NONE, then we are not vulnerable. - */ + /* + * The STF_BARRIER feature is on by default, so if it's off that means + * firmware has explicitly said the CPU is not vulnerable via either + * the hypercall or device tree. + */ + if (!security_ftr_enabled(SEC_FTR_STF_BARRIER)) return PR_SPEC_NOT_AFFECTED; - else - /* - * If we do have a barrier type then we are vulnerable. The - * barrier is not a global or per-process mitigation, so the - * only value we can report here is PR_SPEC_ENABLE, which - * appears as "vulnerable" in /proc. - */ - return PR_SPEC_ENABLE; - return -EINVAL; + /* + * If the system's CPU has no known barrier (see setup_stf_barrier()) + * then assume that the CPU is not vulnerable. + */ + if (stf_enabled_flush_types == STF_BARRIER_NONE) + return PR_SPEC_NOT_AFFECTED; + + /* + * Otherwise the CPU is vulnerable. The barrier is not a global or + * per-process mitigation, so the only value that can be reported here + * is PR_SPEC_ENABLE, which appears as "vulnerable" in /proc. + */ + return PR_SPEC_ENABLE; } int arch_prctl_spec_ctrl_get(struct task_struct *task, unsigned long which) diff --git a/arch/powerpc/kernel/signal_32.c b/arch/powerpc/kernel/signal_32.c index 3e053e2fd6b6..68ed8ecf64fc 100644 --- a/arch/powerpc/kernel/signal_32.c +++ b/arch/powerpc/kernel/signal_32.c @@ -258,8 +258,9 @@ static void prepare_save_user_regs(int ctx_has_vsx_region) #endif } -static int __unsafe_save_user_regs(struct pt_regs *regs, struct mcontext __user *frame, - struct mcontext __user *tm_frame, int ctx_has_vsx_region) +static __always_inline int +__unsafe_save_user_regs(struct pt_regs *regs, struct mcontext __user *frame, + struct mcontext __user *tm_frame, int ctx_has_vsx_region) { unsigned long msr = regs->msr; @@ -358,8 +359,9 @@ static void prepare_save_tm_user_regs(void) current->thread.ckvrsave = mfspr(SPRN_VRSAVE); } -static int save_tm_user_regs_unsafe(struct pt_regs *regs, struct mcontext __user *frame, - struct mcontext __user *tm_frame, unsigned long msr) +static __always_inline int +save_tm_user_regs_unsafe(struct pt_regs *regs, struct mcontext __user *frame, + struct mcontext __user *tm_frame, unsigned long msr) { /* Save both sets of general registers */ unsafe_save_general_regs(¤t->thread.ckpt_regs, frame, failed); @@ -438,8 +440,9 @@ failed: #else static void prepare_save_tm_user_regs(void) { } -static int save_tm_user_regs_unsafe(struct pt_regs *regs, struct mcontext __user *frame, - struct mcontext __user *tm_frame, unsigned long msr) +static __always_inline int +save_tm_user_regs_unsafe(struct pt_regs *regs, struct mcontext __user *frame, + struct mcontext __user *tm_frame, unsigned long msr) { return 0; } diff --git a/arch/powerpc/mm/book3s64/radix_pgtable.c b/arch/powerpc/mm/book3s64/radix_pgtable.c index 1d9d7efacbc7..832dfc59fc6c 100644 --- a/arch/powerpc/mm/book3s64/radix_pgtable.c +++ b/arch/powerpc/mm/book3s64/radix_pgtable.c @@ -764,9 +764,9 @@ static void free_pud_table(pud_t *pud_start, p4d_t *p4d) } static void remove_pte_table(pte_t *pte_start, unsigned long addr, - unsigned long end) + unsigned long end, bool direct) { - unsigned long next; + unsigned long next, pages = 0; pte_t *pte; pte = pte_start + pte_index(addr); @@ -788,13 +788,16 @@ static void remove_pte_table(pte_t *pte_start, unsigned long addr, } pte_clear(&init_mm, addr, pte); + pages++; } + if (direct) + update_page_count(mmu_virtual_psize, -pages); } static void __meminit remove_pmd_table(pmd_t *pmd_start, unsigned long addr, - unsigned long end) + unsigned long end, bool direct) { - unsigned long next; + unsigned long next, pages = 0; pte_t *pte_base; pmd_t *pmd; @@ -812,19 +815,22 @@ static void __meminit remove_pmd_table(pmd_t *pmd_start, unsigned long addr, continue; } pte_clear(&init_mm, addr, (pte_t *)pmd); + pages++; continue; } pte_base = (pte_t *)pmd_page_vaddr(*pmd); - remove_pte_table(pte_base, addr, next); + remove_pte_table(pte_base, addr, next, direct); free_pte_table(pte_base, pmd); } + if (direct) + update_page_count(MMU_PAGE_2M, -pages); } static void __meminit remove_pud_table(pud_t *pud_start, unsigned long addr, - unsigned long end) + unsigned long end, bool direct) { - unsigned long next; + unsigned long next, pages = 0; pmd_t *pmd_base; pud_t *pud; @@ -842,16 +848,20 @@ static void __meminit remove_pud_table(pud_t *pud_start, unsigned long addr, continue; } pte_clear(&init_mm, addr, (pte_t *)pud); + pages++; continue; } pmd_base = pud_pgtable(*pud); - remove_pmd_table(pmd_base, addr, next); + remove_pmd_table(pmd_base, addr, next, direct); free_pmd_table(pmd_base, pud); } + if (direct) + update_page_count(MMU_PAGE_1G, -pages); } -static void __meminit remove_pagetable(unsigned long start, unsigned long end) +static void __meminit remove_pagetable(unsigned long start, unsigned long end, + bool direct) { unsigned long addr, next; pud_t *pud_base; @@ -880,7 +890,7 @@ static void __meminit remove_pagetable(unsigned long start, unsigned long end) } pud_base = p4d_pgtable(*p4d); - remove_pud_table(pud_base, addr, next); + remove_pud_table(pud_base, addr, next, direct); free_pud_table(pud_base, p4d); } @@ -903,7 +913,7 @@ int __meminit radix__create_section_mapping(unsigned long start, int __meminit radix__remove_section_mapping(unsigned long start, unsigned long end) { - remove_pagetable(start, end); + remove_pagetable(start, end, true); return 0; } #endif /* CONFIG_MEMORY_HOTPLUG */ @@ -939,7 +949,7 @@ int __meminit radix__vmemmap_create_mapping(unsigned long start, #ifdef CONFIG_MEMORY_HOTPLUG void __meminit radix__vmemmap_remove_mapping(unsigned long start, unsigned long page_size) { - remove_pagetable(start, start + page_size); + remove_pagetable(start, start + page_size, false); } #endif #endif diff --git a/arch/powerpc/mm/init_64.c b/arch/powerpc/mm/init_64.c index 386be136026e..b76cd49d521b 100644 --- a/arch/powerpc/mm/init_64.c +++ b/arch/powerpc/mm/init_64.c @@ -188,7 +188,7 @@ static bool altmap_cross_boundary(struct vmem_altmap *altmap, unsigned long star unsigned long nr_pfn = page_size / sizeof(struct page); unsigned long start_pfn = page_to_pfn((struct page *)start); - if ((start_pfn + nr_pfn) > altmap->end_pfn) + if ((start_pfn + nr_pfn - 1) > altmap->end_pfn) return true; if (start_pfn < altmap->base_pfn) diff --git a/arch/powerpc/platforms/powernv/pci-sriov.c b/arch/powerpc/platforms/powernv/pci-sriov.c index 28aac933a439..e3e52ff2cbf5 100644 --- a/arch/powerpc/platforms/powernv/pci-sriov.c +++ b/arch/powerpc/platforms/powernv/pci-sriov.c @@ -600,12 +600,12 @@ static void pnv_pci_sriov_disable(struct pci_dev *pdev) struct pnv_iov_data *iov; iov = pnv_iov_get(pdev); - num_vfs = iov->num_vfs; - base_pe = iov->vf_pe_arr[0].pe_number; - if (WARN_ON(!iov)) return; + num_vfs = iov->num_vfs; + base_pe = iov->vf_pe_arr[0].pe_number; + /* Release VF PEs */ pnv_ioda_release_vf_PE(pdev); diff --git a/arch/powerpc/platforms/powernv/vas-window.c b/arch/powerpc/platforms/powernv/vas-window.c index 0072682531d8..b664838008c1 100644 --- a/arch/powerpc/platforms/powernv/vas-window.c +++ b/arch/powerpc/platforms/powernv/vas-window.c @@ -1310,8 +1310,8 @@ int vas_win_close(struct vas_window *vwin) /* if send window, drop reference to matching receive window */ if (window->tx_win) { if (window->user_win) { - put_vas_user_win_ref(&vwin->task_ref); mm_context_remove_vas_window(vwin->task_ref.mm); + put_vas_user_win_ref(&vwin->task_ref); } put_rx_win(window->rxwin); } diff --git a/arch/powerpc/platforms/pseries/vas.c b/arch/powerpc/platforms/pseries/vas.c index 15046d80f042..b54f6fc27896 100644 --- a/arch/powerpc/platforms/pseries/vas.c +++ b/arch/powerpc/platforms/pseries/vas.c @@ -441,8 +441,8 @@ static int vas_deallocate_window(struct vas_window *vwin) atomic_dec(&caps->used_lpar_creds); mutex_unlock(&vas_pseries_mutex); - put_vas_user_win_ref(&vwin->task_ref); mm_context_remove_vas_window(vwin->task_ref.mm); + put_vas_user_win_ref(&vwin->task_ref); kfree(win); return 0; diff --git a/arch/riscv/kernel/probes/uprobes.c b/arch/riscv/kernel/probes/uprobes.c index c976a21cd4bd..194f166b2cc4 100644 --- a/arch/riscv/kernel/probes/uprobes.c +++ b/arch/riscv/kernel/probes/uprobes.c @@ -67,6 +67,7 @@ int arch_uprobe_post_xol(struct arch_uprobe *auprobe, struct pt_regs *regs) struct uprobe_task *utask = current->utask; WARN_ON_ONCE(current->thread.bad_cause != UPROBE_TRAP_NR); + current->thread.bad_cause = utask->autask.saved_cause; instruction_pointer_set(regs, utask->vaddr + auprobe->insn_size); @@ -102,6 +103,7 @@ void arch_uprobe_abort_xol(struct arch_uprobe *auprobe, struct pt_regs *regs) { struct uprobe_task *utask = current->utask; + current->thread.bad_cause = utask->autask.saved_cause; /* * Task has received a fatal signal, so reset back to probbed * address. diff --git a/arch/riscv/mm/init.c b/arch/riscv/mm/init.c index 0afcd4ae7eed..d7115acab350 100644 --- a/arch/riscv/mm/init.c +++ b/arch/riscv/mm/init.c @@ -235,7 +235,6 @@ static void __init setup_bootmem(void) dma_contiguous_reserve(dma32_phys_limit); if (IS_ENABLED(CONFIG_64BIT)) hugetlb_cma_reserve(PUD_SHIFT - PAGE_SHIFT); - memblock_allow_resize(); } #ifdef CONFIG_MMU @@ -844,7 +843,7 @@ static void __init reserve_crashkernel(void) */ crash_base = memblock_phys_alloc_range(crash_size, PMD_SIZE, search_start, - min(search_end, (unsigned long) SZ_4G)); + min(search_end, (unsigned long)(SZ_4G - 1))); if (crash_base == 0) { /* Try again without restricting region to 32bit addressible memory */ crash_base = memblock_phys_alloc_range(crash_size, PMD_SIZE, @@ -868,6 +867,9 @@ void __init paging_init(void) { setup_bootmem(); setup_vm_final(); + + /* Depend on that Linear Mapping is ready */ + memblock_allow_resize(); } void __init misc_mem_init(void) diff --git a/arch/riscv/net/bpf_jit.h b/arch/riscv/net/bpf_jit.h index 75c1e9996867..ef336fe16004 100644 --- a/arch/riscv/net/bpf_jit.h +++ b/arch/riscv/net/bpf_jit.h @@ -69,6 +69,7 @@ struct rv_jit_context { struct bpf_prog *prog; u16 *insns; /* RV insns */ int ninsns; + int prologue_len; int epilogue_offset; int *offset; /* BPF to RV */ unsigned long flags; @@ -214,8 +215,8 @@ static inline int rv_offset(int insn, int off, struct rv_jit_context *ctx) int from, to; off++; /* BPF branch is from PC+1, RV is from PC */ - from = (insn > 0) ? ctx->offset[insn - 1] : 0; - to = (insn + off > 0) ? ctx->offset[insn + off - 1] : 0; + from = (insn > 0) ? ctx->offset[insn - 1] : ctx->prologue_len; + to = (insn + off > 0) ? ctx->offset[insn + off - 1] : ctx->prologue_len; return ninsns_rvoff(to - from); } diff --git a/arch/riscv/net/bpf_jit_core.c b/arch/riscv/net/bpf_jit_core.c index 753d85bdfad0..b95c60f663d4 100644 --- a/arch/riscv/net/bpf_jit_core.c +++ b/arch/riscv/net/bpf_jit_core.c @@ -83,6 +83,12 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog) prog = orig_prog; goto out_offset; } + + if (build_body(ctx, extra_pass, NULL)) { + prog = orig_prog; + goto out_offset; + } + for (i = 0; i < prog->len; i++) { prev_ninsns += 32; ctx->offset[i] = prev_ninsns; @@ -91,11 +97,15 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog) for (i = 0; i < NR_JIT_ITERATIONS; i++) { pass++; ctx->ninsns = 0; + + bpf_jit_build_prologue(ctx); + ctx->prologue_len = ctx->ninsns; + if (build_body(ctx, extra_pass, ctx->offset)) { prog = orig_prog; goto out_offset; } - bpf_jit_build_prologue(ctx); + ctx->epilogue_offset = ctx->ninsns; bpf_jit_build_epilogue(ctx); @@ -154,6 +164,9 @@ skip_init_ctx: if (!prog->is_func || extra_pass) { bpf_jit_binary_lock_ro(jit_data->header); + for (i = 0; i < prog->len; i++) + ctx->offset[i] = ninsns_rvoff(ctx->offset[i]); + bpf_prog_fill_jited_linfo(prog, ctx->offset); out_offset: kfree(ctx->offset); kfree(jit_data); diff --git a/arch/s390/Makefile b/arch/s390/Makefile index c7b7a60f6405..dc840ba0b016 100644 --- a/arch/s390/Makefile +++ b/arch/s390/Makefile @@ -29,6 +29,7 @@ KBUILD_CFLAGS_DECOMPRESSOR += -fno-delete-null-pointer-checks -msoft-float -mbac KBUILD_CFLAGS_DECOMPRESSOR += -fno-asynchronous-unwind-tables KBUILD_CFLAGS_DECOMPRESSOR += -ffreestanding KBUILD_CFLAGS_DECOMPRESSOR += -fno-stack-protector +KBUILD_CFLAGS_DECOMPRESSOR += -fPIE KBUILD_CFLAGS_DECOMPRESSOR += $(call cc-disable-warning, address-of-packed-member) KBUILD_CFLAGS_DECOMPRESSOR += $(if $(CONFIG_DEBUG_INFO),-g) KBUILD_CFLAGS_DECOMPRESSOR += $(if $(CONFIG_DEBUG_INFO_DWARF4), $(call cc-option, -gdwarf-4,)) diff --git a/arch/s390/kvm/diag.c b/arch/s390/kvm/diag.c index 807fa9da1e72..3c65b8258ae6 100644 --- a/arch/s390/kvm/diag.c +++ b/arch/s390/kvm/diag.c @@ -166,6 +166,7 @@ static int diag9c_forwarding_overrun(void) static int __diag_time_slice_end_directed(struct kvm_vcpu *vcpu) { struct kvm_vcpu *tcpu; + int tcpu_cpu; int tid; tid = vcpu->run->s.regs.gprs[(vcpu->arch.sie_block->ipa & 0xf0) >> 4]; @@ -181,14 +182,15 @@ static int __diag_time_slice_end_directed(struct kvm_vcpu *vcpu) goto no_yield; /* target guest VCPU already running */ - if (READ_ONCE(tcpu->cpu) >= 0) { + tcpu_cpu = READ_ONCE(tcpu->cpu); + if (tcpu_cpu >= 0) { if (!diag9c_forwarding_hz || diag9c_forwarding_overrun()) goto no_yield; /* target host CPU already running */ - if (!vcpu_is_preempted(tcpu->cpu)) + if (!vcpu_is_preempted(tcpu_cpu)) goto no_yield; - smp_yield_cpu(tcpu->cpu); + smp_yield_cpu(tcpu_cpu); VCPU_EVENT(vcpu, 5, "diag time slice end directed to %d: yield forwarded", tid); diff --git a/arch/s390/kvm/kvm-s390.c b/arch/s390/kvm/kvm-s390.c index d7aa442ceaf1..eb97db59b236 100644 --- a/arch/s390/kvm/kvm-s390.c +++ b/arch/s390/kvm/kvm-s390.c @@ -2030,6 +2030,10 @@ static unsigned long kvm_s390_next_dirty_cmma(struct kvm_memslots *slots, ms = slots->memslots + slotidx; ofs = 0; } + + if (cur_gfn < ms->base_gfn) + ofs = 0; + ofs = find_next_bit(kvm_second_dirty_bitmap(ms), ms->npages, ofs); while ((slotidx > 0) && (ofs >= ms->npages)) { slotidx--; diff --git a/arch/s390/kvm/vsie.c b/arch/s390/kvm/vsie.c index 2c0704f5eb3c..e07bc0d3df6f 100644 --- a/arch/s390/kvm/vsie.c +++ b/arch/s390/kvm/vsie.c @@ -169,7 +169,8 @@ static int setup_apcb00(struct kvm_vcpu *vcpu, unsigned long *apcb_s, sizeof(struct kvm_s390_apcb0))) return -EFAULT; - bitmap_and(apcb_s, apcb_s, apcb_h, sizeof(struct kvm_s390_apcb0)); + bitmap_and(apcb_s, apcb_s, apcb_h, + BITS_PER_BYTE * sizeof(struct kvm_s390_apcb0)); return 0; } @@ -191,7 +192,8 @@ static int setup_apcb11(struct kvm_vcpu *vcpu, unsigned long *apcb_s, sizeof(struct kvm_s390_apcb1))) return -EFAULT; - bitmap_and(apcb_s, apcb_s, apcb_h, sizeof(struct kvm_s390_apcb1)); + bitmap_and(apcb_s, apcb_s, apcb_h, + BITS_PER_BYTE * sizeof(struct kvm_s390_apcb1)); return 0; } diff --git a/arch/sh/drivers/dma/dma-sh.c b/arch/sh/drivers/dma/dma-sh.c index 96c626c2cd0a..306fba1564e5 100644 --- a/arch/sh/drivers/dma/dma-sh.c +++ b/arch/sh/drivers/dma/dma-sh.c @@ -18,6 +18,18 @@ #include #include +/* + * Some of the SoCs feature two DMAC modules. In such a case, the channels are + * distributed equally among them. + */ +#ifdef SH_DMAC_BASE1 +#define SH_DMAC_NR_MD_CH (CONFIG_NR_ONCHIP_DMA_CHANNELS / 2) +#else +#define SH_DMAC_NR_MD_CH CONFIG_NR_ONCHIP_DMA_CHANNELS +#endif + +#define SH_DMAC_CH_SZ 0x10 + /* * Define the default configuration for dual address memory-memory transfer. * The 0x400 value represents auto-request, external->external. @@ -29,7 +41,7 @@ static unsigned long dma_find_base(unsigned int chan) unsigned long base = SH_DMAC_BASE0; #ifdef SH_DMAC_BASE1 - if (chan >= 6) + if (chan >= SH_DMAC_NR_MD_CH) base = SH_DMAC_BASE1; #endif @@ -40,13 +52,13 @@ static unsigned long dma_base_addr(unsigned int chan) { unsigned long base = dma_find_base(chan); - /* Normalize offset calculation */ - if (chan >= 9) - chan -= 6; - if (chan >= 4) - base += 0x10; + chan = (chan % SH_DMAC_NR_MD_CH) * SH_DMAC_CH_SZ; - return base + (chan * 0x10); + /* DMAOR is placed inside the channel register space. Step over it. */ + if (chan >= DMAOR) + base += SH_DMAC_CH_SZ; + + return base + chan; } #ifdef CONFIG_SH_DMA_IRQ_MULTI @@ -250,12 +262,11 @@ static int sh_dmac_get_dma_residue(struct dma_channel *chan) #define NR_DMAOR 1 #endif -/* - * DMAOR bases are broken out amongst channel groups. DMAOR0 manages - * channels 0 - 5, DMAOR1 6 - 11 (optional). - */ -#define dmaor_read_reg(n) __raw_readw(dma_find_base((n)*6)) -#define dmaor_write_reg(n, data) __raw_writew(data, dma_find_base(n)*6) +#define dmaor_read_reg(n) __raw_readw(dma_find_base((n) * \ + SH_DMAC_NR_MD_CH) + DMAOR) +#define dmaor_write_reg(n, data) __raw_writew(data, \ + dma_find_base((n) * \ + SH_DMAC_NR_MD_CH) + DMAOR) static inline int dmaor_reset(int no) { diff --git a/arch/sh/kernel/cpu/sh2/probe.c b/arch/sh/kernel/cpu/sh2/probe.c index d342ea08843f..70a07f4f2142 100644 --- a/arch/sh/kernel/cpu/sh2/probe.c +++ b/arch/sh/kernel/cpu/sh2/probe.c @@ -21,7 +21,7 @@ static int __init scan_cache(unsigned long node, const char *uname, if (!of_flat_dt_is_compatible(node, "jcore,cache")) return 0; - j2_ccr_base = (u32 __iomem *)of_flat_dt_translate_address(node); + j2_ccr_base = ioremap(of_flat_dt_translate_address(node), 4); return 1; } diff --git a/arch/um/Makefile b/arch/um/Makefile index f1d4d67157be..3dbd0e3b660e 100644 --- a/arch/um/Makefile +++ b/arch/um/Makefile @@ -148,7 +148,7 @@ export LDFLAGS_vmlinux := $(LDFLAGS_EXECSTACK) # When cleaning we don't include .config, so we don't include # TT or skas makefiles and don't clean skas_ptregs.h. CLEAN_FILES += linux x.i gmon.out -MRPROPER_FILES += arch/$(SUBARCH)/include/generated +MRPROPER_FILES += $(HOST_DIR)/include/generated archclean: @find . \( -name '*.bb' -o -name '*.bbg' -o -name '*.da' \ diff --git a/arch/x86/configs/gki_defconfig b/arch/x86/configs/gki_defconfig index 7508b1948078..ce988f371cf4 100644 --- a/arch/x86/configs/gki_defconfig +++ b/arch/x86/configs/gki_defconfig @@ -448,6 +448,7 @@ CONFIG_HID_WIIMOTE=y CONFIG_USB_HIDDEV=y CONFIG_USB_ANNOUNCE_NEW_DEVICES=y CONFIG_USB_XHCI_HCD=y +CONFIG_USB_XHCI_PCI_RENESAS=y CONFIG_USB_EHCI_HCD=y CONFIG_USB_EHCI_ROOT_HUB_TT=y CONFIG_USB_EHCI_HCD_PLATFORM=y diff --git a/arch/x86/events/amd/core.c b/arch/x86/events/amd/core.c index d93d098dea99..4ebedc7e1188 100644 --- a/arch/x86/events/amd/core.c +++ b/arch/x86/events/amd/core.c @@ -364,7 +364,7 @@ static int amd_pmu_hw_config(struct perf_event *event) /* pass precise event sampling to ibs: */ if (event->attr.precise_ip && get_ibs_caps()) - return -ENOENT; + return forward_event_to_ibs(event); if (has_branch_stack(event)) return -EOPNOTSUPP; diff --git a/arch/x86/events/amd/ibs.c b/arch/x86/events/amd/ibs.c index 2704ec1e42a3..b605e08f9a8e 100644 --- a/arch/x86/events/amd/ibs.c +++ b/arch/x86/events/amd/ibs.c @@ -194,7 +194,7 @@ static struct perf_ibs *get_ibs_pmu(int type) } /* - * Use IBS for precise event sampling: + * core pmu config -> IBS config * * perf record -a -e cpu-cycles:p ... # use ibs op counting cycle count * perf record -a -e r076:p ... # same as -e cpu-cycles:p @@ -203,25 +203,9 @@ static struct perf_ibs *get_ibs_pmu(int type) * IbsOpCntCtl (bit 19) of IBS Execution Control Register (IbsOpCtl, * MSRC001_1033) is used to select either cycle or micro-ops counting * mode. - * - * The rip of IBS samples has skid 0. Thus, IBS supports precise - * levels 1 and 2 and the PERF_EFLAGS_EXACT is set. In rare cases the - * rip is invalid when IBS was not able to record the rip correctly. - * We clear PERF_EFLAGS_EXACT and take the rip from pt_regs then. - * */ -static int perf_ibs_precise_event(struct perf_event *event, u64 *config) +static int core_pmu_ibs_config(struct perf_event *event, u64 *config) { - switch (event->attr.precise_ip) { - case 0: - return -ENOENT; - case 1: - case 2: - break; - default: - return -EOPNOTSUPP; - } - switch (event->attr.type) { case PERF_TYPE_HARDWARE: switch (event->attr.config) { @@ -247,22 +231,37 @@ static int perf_ibs_precise_event(struct perf_event *event, u64 *config) return -EOPNOTSUPP; } +/* + * The rip of IBS samples has skid 0. Thus, IBS supports precise + * levels 1 and 2 and the PERF_EFLAGS_EXACT is set. In rare cases the + * rip is invalid when IBS was not able to record the rip correctly. + * We clear PERF_EFLAGS_EXACT and take the rip from pt_regs then. + */ +int forward_event_to_ibs(struct perf_event *event) +{ + u64 config = 0; + + if (!event->attr.precise_ip || event->attr.precise_ip > 2) + return -EOPNOTSUPP; + + if (!core_pmu_ibs_config(event, &config)) { + event->attr.type = perf_ibs_op.pmu.type; + event->attr.config = config; + } + return -ENOENT; +} + static int perf_ibs_init(struct perf_event *event) { struct hw_perf_event *hwc = &event->hw; struct perf_ibs *perf_ibs; u64 max_cnt, config; - int ret; perf_ibs = get_ibs_pmu(event->attr.type); - if (perf_ibs) { - config = event->attr.config; - } else { - perf_ibs = &perf_ibs_op; - ret = perf_ibs_precise_event(event, &config); - if (ret) - return ret; - } + if (!perf_ibs) + return -ENOENT; + + config = event->attr.config; if (event->pmu != &perf_ibs->pmu) return -ENOENT; diff --git a/arch/x86/include/asm/microcode.h b/arch/x86/include/asm/microcode.h index 1bf064a14b95..4ca377efc986 100644 --- a/arch/x86/include/asm/microcode.h +++ b/arch/x86/include/asm/microcode.h @@ -5,6 +5,7 @@ #include #include #include +#include struct ucode_patch { struct list_head plist; diff --git a/arch/x86/include/asm/microcode_amd.h b/arch/x86/include/asm/microcode_amd.h index a645b25ee442..403a8e76b310 100644 --- a/arch/x86/include/asm/microcode_amd.h +++ b/arch/x86/include/asm/microcode_amd.h @@ -48,11 +48,13 @@ extern void __init load_ucode_amd_bsp(unsigned int family); extern void load_ucode_amd_ap(unsigned int family); extern int __init save_microcode_in_initrd_amd(unsigned int family); void reload_ucode_amd(unsigned int cpu); +extern void amd_check_microcode(void); #else static inline void __init load_ucode_amd_bsp(unsigned int family) {} static inline void load_ucode_amd_ap(unsigned int family) {} static inline int __init save_microcode_in_initrd_amd(unsigned int family) { return -EINVAL; } static inline void reload_ucode_amd(unsigned int cpu) {} +static inline void amd_check_microcode(void) {} #endif #endif /* _ASM_X86_MICROCODE_AMD_H */ diff --git a/arch/x86/include/asm/msr-index.h b/arch/x86/include/asm/msr-index.h index 3588b799c63f..e78755ed82cf 100644 --- a/arch/x86/include/asm/msr-index.h +++ b/arch/x86/include/asm/msr-index.h @@ -503,6 +503,7 @@ #define MSR_AMD64_DE_CFG 0xc0011029 #define MSR_AMD64_DE_CFG_LFENCE_SERIALIZE_BIT 1 #define MSR_AMD64_DE_CFG_LFENCE_SERIALIZE BIT_ULL(MSR_AMD64_DE_CFG_LFENCE_SERIALIZE_BIT) +#define MSR_AMD64_DE_CFG_ZEN2_FP_BACKUP_FIX_BIT 9 #define MSR_AMD64_BU_CFG2 0xc001102a #define MSR_AMD64_IBSFETCHCTL 0xc0011030 diff --git a/arch/x86/include/asm/perf_event.h b/arch/x86/include/asm/perf_event.h index a2b6626c681f..0e4efcde0783 100644 --- a/arch/x86/include/asm/perf_event.h +++ b/arch/x86/include/asm/perf_event.h @@ -427,8 +427,10 @@ struct pebs_xmm { #ifdef CONFIG_X86_LOCAL_APIC extern u32 get_ibs_caps(void); +extern int forward_event_to_ibs(struct perf_event *event); #else static inline u32 get_ibs_caps(void) { return 0; } +static inline int forward_event_to_ibs(struct perf_event *event) { return -ENOENT; } #endif #ifdef CONFIG_PERF_EVENTS diff --git a/arch/x86/include/asm/pgtable.h b/arch/x86/include/asm/pgtable.h index 01a1763123ff..4e95b11c4239 100644 --- a/arch/x86/include/asm/pgtable.h +++ b/arch/x86/include/asm/pgtable.h @@ -1147,6 +1147,11 @@ static inline pmd_t pmdp_establish(struct vm_area_struct *vma, } } #endif + +#define __HAVE_ARCH_PMDP_INVALIDATE_AD +extern pmd_t pmdp_invalidate_ad(struct vm_area_struct *vma, + unsigned long address, pmd_t *pmdp); + /* * Page table pages are page-aligned. The lower half of the top * level is used for userspace and the top half for the kernel. diff --git a/arch/x86/include/asm/pgtable_64.h b/arch/x86/include/asm/pgtable_64.h index 56d0399a0cd1..dd520b44e89c 100644 --- a/arch/x86/include/asm/pgtable_64.h +++ b/arch/x86/include/asm/pgtable_64.h @@ -235,8 +235,8 @@ static inline void native_pgd_clear(pgd_t *pgd) #define __pte_to_swp_entry(pte) ((swp_entry_t) { pte_val((pte)) }) #define __pmd_to_swp_entry(pmd) ((swp_entry_t) { pmd_val((pmd)) }) -#define __swp_entry_to_pte(x) ((pte_t) { .pte = (x).val }) -#define __swp_entry_to_pmd(x) ((pmd_t) { .pmd = (x).val }) +#define __swp_entry_to_pte(x) (__pte((x).val)) +#define __swp_entry_to_pmd(x) (__pmd((x).val)) extern int kern_addr_valid(unsigned long addr); extern void cleanup_highmap(void); diff --git a/arch/x86/include/asm/pgtable_types.h b/arch/x86/include/asm/pgtable_types.h index 40497a9020c6..8668bc661026 100644 --- a/arch/x86/include/asm/pgtable_types.h +++ b/arch/x86/include/asm/pgtable_types.h @@ -110,9 +110,11 @@ #if defined(CONFIG_X86_64) || defined(CONFIG_X86_PAE) #define _PAGE_NX (_AT(pteval_t, 1) << _PAGE_BIT_NX) #define _PAGE_DEVMAP (_AT(u64, 1) << _PAGE_BIT_DEVMAP) +#define _PAGE_SOFTW4 (_AT(pteval_t, 1) << _PAGE_BIT_SOFTW4) #else #define _PAGE_NX (_AT(pteval_t, 0)) #define _PAGE_DEVMAP (_AT(pteval_t, 0)) +#define _PAGE_SOFTW4 (_AT(pteval_t, 0)) #endif #define _PAGE_PROTNONE (_AT(pteval_t, 1) << _PAGE_BIT_PROTNONE) diff --git a/arch/x86/include/asm/tlbflush.h b/arch/x86/include/asm/tlbflush.h index b587a9ee9cb2..8be1ff908172 100644 --- a/arch/x86/include/asm/tlbflush.h +++ b/arch/x86/include/asm/tlbflush.h @@ -259,6 +259,103 @@ static inline void arch_tlbbatch_add_mm(struct arch_tlbflush_unmap_batch *batch, extern void arch_tlbbatch_flush(struct arch_tlbflush_unmap_batch *batch); +static inline bool pte_flags_need_flush(unsigned long oldflags, + unsigned long newflags, + bool ignore_access) +{ + /* + * Flags that require a flush when cleared but not when they are set. + * Only include flags that would not trigger spurious page-faults. + * Non-present entries are not cached. Hardware would set the + * dirty/access bit if needed without a fault. + */ + const pteval_t flush_on_clear = _PAGE_DIRTY | _PAGE_PRESENT | + _PAGE_ACCESSED; + const pteval_t software_flags = _PAGE_SOFTW1 | _PAGE_SOFTW2 | + _PAGE_SOFTW3 | _PAGE_SOFTW4; + const pteval_t flush_on_change = _PAGE_RW | _PAGE_USER | _PAGE_PWT | + _PAGE_PCD | _PAGE_PSE | _PAGE_GLOBAL | _PAGE_PAT | + _PAGE_PAT_LARGE | _PAGE_PKEY_BIT0 | _PAGE_PKEY_BIT1 | + _PAGE_PKEY_BIT2 | _PAGE_PKEY_BIT3 | _PAGE_NX; + unsigned long diff = oldflags ^ newflags; + + BUILD_BUG_ON(flush_on_clear & software_flags); + BUILD_BUG_ON(flush_on_clear & flush_on_change); + BUILD_BUG_ON(flush_on_change & software_flags); + + /* Ignore software flags */ + diff &= ~software_flags; + + if (ignore_access) + diff &= ~_PAGE_ACCESSED; + + /* + * Did any of the 'flush_on_clear' flags was clleared set from between + * 'oldflags' and 'newflags'? + */ + if (diff & oldflags & flush_on_clear) + return true; + + /* Flush on modified flags. */ + if (diff & flush_on_change) + return true; + + /* Ensure there are no flags that were left behind */ + if (IS_ENABLED(CONFIG_DEBUG_VM) && + (diff & ~(flush_on_clear | software_flags | flush_on_change))) { + VM_WARN_ON_ONCE(1); + return true; + } + + return false; +} + +/* + * pte_needs_flush() checks whether permissions were demoted and require a + * flush. It should only be used for userspace PTEs. + */ +static inline bool pte_needs_flush(pte_t oldpte, pte_t newpte) +{ + /* !PRESENT -> * ; no need for flush */ + if (!(pte_flags(oldpte) & _PAGE_PRESENT)) + return false; + + /* PFN changed ; needs flush */ + if (pte_pfn(oldpte) != pte_pfn(newpte)) + return true; + + /* + * check PTE flags; ignore access-bit; see comment in + * ptep_clear_flush_young(). + */ + return pte_flags_need_flush(pte_flags(oldpte), pte_flags(newpte), + true); +} +#define pte_needs_flush pte_needs_flush + +/* + * huge_pmd_needs_flush() checks whether permissions were demoted and require a + * flush. It should only be used for userspace huge PMDs. + */ +static inline bool huge_pmd_needs_flush(pmd_t oldpmd, pmd_t newpmd) +{ + /* !PRESENT -> * ; no need for flush */ + if (!(pmd_flags(oldpmd) & _PAGE_PRESENT)) + return false; + + /* PFN changed ; needs flush */ + if (pmd_pfn(oldpmd) != pmd_pfn(newpmd)) + return true; + + /* + * check PMD flags; do not ignore access-bit; see + * pmdp_clear_flush_young(). + */ + return pte_flags_need_flush(pmd_flags(oldpmd), pmd_flags(newpmd), + false); +} +#define huge_pmd_needs_flush huge_pmd_needs_flush + #endif /* !MODULE */ #endif /* _ASM_X86_TLBFLUSH_H */ diff --git a/arch/x86/kernel/cpu/amd.c b/arch/x86/kernel/cpu/amd.c index 83bf26eaff2e..3daceadf5d1f 100644 --- a/arch/x86/kernel/cpu/amd.c +++ b/arch/x86/kernel/cpu/amd.c @@ -27,11 +27,6 @@ #include "cpu.h" -static const int amd_erratum_383[]; -static const int amd_erratum_400[]; -static const int amd_erratum_1054[]; -static bool cpu_has_amd_erratum(struct cpuinfo_x86 *cpu, const int *erratum); - /* * nodes_per_socket: Stores the number of nodes per socket. * Refer to Fam15h Models 00-0fh BKDG - CPUID Fn8000_001E_ECX @@ -39,6 +34,78 @@ static bool cpu_has_amd_erratum(struct cpuinfo_x86 *cpu, const int *erratum); */ static u32 nodes_per_socket = 1; +/* + * AMD errata checking + * + * Errata are defined as arrays of ints using the AMD_LEGACY_ERRATUM() or + * AMD_OSVW_ERRATUM() macros. The latter is intended for newer errata that + * have an OSVW id assigned, which it takes as first argument. Both take a + * variable number of family-specific model-stepping ranges created by + * AMD_MODEL_RANGE(). + * + * Example: + * + * const int amd_erratum_319[] = + * AMD_LEGACY_ERRATUM(AMD_MODEL_RANGE(0x10, 0x2, 0x1, 0x4, 0x2), + * AMD_MODEL_RANGE(0x10, 0x8, 0x0, 0x8, 0x0), + * AMD_MODEL_RANGE(0x10, 0x9, 0x0, 0x9, 0x0)); + */ + +#define AMD_LEGACY_ERRATUM(...) { -1, __VA_ARGS__, 0 } +#define AMD_OSVW_ERRATUM(osvw_id, ...) { osvw_id, __VA_ARGS__, 0 } +#define AMD_MODEL_RANGE(f, m_start, s_start, m_end, s_end) \ + ((f << 24) | (m_start << 16) | (s_start << 12) | (m_end << 4) | (s_end)) +#define AMD_MODEL_RANGE_FAMILY(range) (((range) >> 24) & 0xff) +#define AMD_MODEL_RANGE_START(range) (((range) >> 12) & 0xfff) +#define AMD_MODEL_RANGE_END(range) ((range) & 0xfff) + +static const int amd_erratum_400[] = + AMD_OSVW_ERRATUM(1, AMD_MODEL_RANGE(0xf, 0x41, 0x2, 0xff, 0xf), + AMD_MODEL_RANGE(0x10, 0x2, 0x1, 0xff, 0xf)); + +static const int amd_erratum_383[] = + AMD_OSVW_ERRATUM(3, AMD_MODEL_RANGE(0x10, 0, 0, 0xff, 0xf)); + +/* #1054: Instructions Retired Performance Counter May Be Inaccurate */ +static const int amd_erratum_1054[] = + AMD_LEGACY_ERRATUM(AMD_MODEL_RANGE(0x17, 0, 0, 0x2f, 0xf)); + +static const int amd_zenbleed[] = + AMD_LEGACY_ERRATUM(AMD_MODEL_RANGE(0x17, 0x30, 0x0, 0x4f, 0xf), + AMD_MODEL_RANGE(0x17, 0x60, 0x0, 0x7f, 0xf), + AMD_MODEL_RANGE(0x17, 0xa0, 0x0, 0xaf, 0xf)); + +static bool cpu_has_amd_erratum(struct cpuinfo_x86 *cpu, const int *erratum) +{ + int osvw_id = *erratum++; + u32 range; + u32 ms; + + if (osvw_id >= 0 && osvw_id < 65536 && + cpu_has(cpu, X86_FEATURE_OSVW)) { + u64 osvw_len; + + rdmsrl(MSR_AMD64_OSVW_ID_LENGTH, osvw_len); + if (osvw_id < osvw_len) { + u64 osvw_bits; + + rdmsrl(MSR_AMD64_OSVW_STATUS + (osvw_id >> 6), + osvw_bits); + return osvw_bits & (1ULL << (osvw_id & 0x3f)); + } + } + + /* OSVW unavailable or ID unknown, match family-model-stepping range */ + ms = (cpu->x86_model << 4) | cpu->x86_stepping; + while ((range = *erratum++)) + if ((cpu->x86 == AMD_MODEL_RANGE_FAMILY(range)) && + (ms >= AMD_MODEL_RANGE_START(range)) && + (ms <= AMD_MODEL_RANGE_END(range))) + return true; + + return false; +} + static inline int rdmsrl_amd_safe(unsigned msr, unsigned long long *p) { u32 gprs[8] = { 0 }; @@ -940,6 +1007,47 @@ static void init_amd_zn(struct cpuinfo_x86 *c) } } +static bool cpu_has_zenbleed_microcode(void) +{ + u32 good_rev = 0; + + switch (boot_cpu_data.x86_model) { + case 0x30 ... 0x3f: good_rev = 0x0830107a; break; + case 0x60 ... 0x67: good_rev = 0x0860010b; break; + case 0x68 ... 0x6f: good_rev = 0x08608105; break; + case 0x70 ... 0x7f: good_rev = 0x08701032; break; + case 0xa0 ... 0xaf: good_rev = 0x08a00008; break; + + default: + return false; + break; + } + + if (boot_cpu_data.microcode < good_rev) + return false; + + return true; +} + +static void zenbleed_check(struct cpuinfo_x86 *c) +{ + if (!cpu_has_amd_erratum(c, amd_zenbleed)) + return; + + if (cpu_has(c, X86_FEATURE_HYPERVISOR)) + return; + + if (!cpu_has(c, X86_FEATURE_AVX)) + return; + + if (!cpu_has_zenbleed_microcode()) { + pr_notice_once("Zenbleed: please update your microcode for the most optimal fix\n"); + msr_set_bit(MSR_AMD64_DE_CFG, MSR_AMD64_DE_CFG_ZEN2_FP_BACKUP_FIX_BIT); + } else { + msr_clear_bit(MSR_AMD64_DE_CFG, MSR_AMD64_DE_CFG_ZEN2_FP_BACKUP_FIX_BIT); + } +} + static void init_amd(struct cpuinfo_x86 *c) { early_init_amd(c); @@ -1030,6 +1138,8 @@ static void init_amd(struct cpuinfo_x86 *c) msr_set_bit(MSR_K7_HWCR, MSR_K7_HWCR_IRPERF_EN_BIT); check_null_seg_clears_base(c); + + zenbleed_check(c); } #ifdef CONFIG_X86_32 @@ -1125,73 +1235,6 @@ static const struct cpu_dev amd_cpu_dev = { cpu_dev_register(amd_cpu_dev); -/* - * AMD errata checking - * - * Errata are defined as arrays of ints using the AMD_LEGACY_ERRATUM() or - * AMD_OSVW_ERRATUM() macros. The latter is intended for newer errata that - * have an OSVW id assigned, which it takes as first argument. Both take a - * variable number of family-specific model-stepping ranges created by - * AMD_MODEL_RANGE(). - * - * Example: - * - * const int amd_erratum_319[] = - * AMD_LEGACY_ERRATUM(AMD_MODEL_RANGE(0x10, 0x2, 0x1, 0x4, 0x2), - * AMD_MODEL_RANGE(0x10, 0x8, 0x0, 0x8, 0x0), - * AMD_MODEL_RANGE(0x10, 0x9, 0x0, 0x9, 0x0)); - */ - -#define AMD_LEGACY_ERRATUM(...) { -1, __VA_ARGS__, 0 } -#define AMD_OSVW_ERRATUM(osvw_id, ...) { osvw_id, __VA_ARGS__, 0 } -#define AMD_MODEL_RANGE(f, m_start, s_start, m_end, s_end) \ - ((f << 24) | (m_start << 16) | (s_start << 12) | (m_end << 4) | (s_end)) -#define AMD_MODEL_RANGE_FAMILY(range) (((range) >> 24) & 0xff) -#define AMD_MODEL_RANGE_START(range) (((range) >> 12) & 0xfff) -#define AMD_MODEL_RANGE_END(range) ((range) & 0xfff) - -static const int amd_erratum_400[] = - AMD_OSVW_ERRATUM(1, AMD_MODEL_RANGE(0xf, 0x41, 0x2, 0xff, 0xf), - AMD_MODEL_RANGE(0x10, 0x2, 0x1, 0xff, 0xf)); - -static const int amd_erratum_383[] = - AMD_OSVW_ERRATUM(3, AMD_MODEL_RANGE(0x10, 0, 0, 0xff, 0xf)); - -/* #1054: Instructions Retired Performance Counter May Be Inaccurate */ -static const int amd_erratum_1054[] = - AMD_LEGACY_ERRATUM(AMD_MODEL_RANGE(0x17, 0, 0, 0x2f, 0xf)); - -static bool cpu_has_amd_erratum(struct cpuinfo_x86 *cpu, const int *erratum) -{ - int osvw_id = *erratum++; - u32 range; - u32 ms; - - if (osvw_id >= 0 && osvw_id < 65536 && - cpu_has(cpu, X86_FEATURE_OSVW)) { - u64 osvw_len; - - rdmsrl(MSR_AMD64_OSVW_ID_LENGTH, osvw_len); - if (osvw_id < osvw_len) { - u64 osvw_bits; - - rdmsrl(MSR_AMD64_OSVW_STATUS + (osvw_id >> 6), - osvw_bits); - return osvw_bits & (1ULL << (osvw_id & 0x3f)); - } - } - - /* OSVW unavailable or ID unknown, match family-model-stepping range */ - ms = (cpu->x86_model << 4) | cpu->x86_stepping; - while ((range = *erratum++)) - if ((cpu->x86 == AMD_MODEL_RANGE_FAMILY(range)) && - (ms >= AMD_MODEL_RANGE_START(range)) && - (ms <= AMD_MODEL_RANGE_END(range))) - return true; - - return false; -} - void set_dr_addr_mask(unsigned long mask, int dr) { if (!boot_cpu_has(X86_FEATURE_BPEXT)) @@ -1226,3 +1269,15 @@ u32 amd_get_highest_perf(void) return 255; } EXPORT_SYMBOL_GPL(amd_get_highest_perf); + +static void zenbleed_check_cpu(void *unused) +{ + struct cpuinfo_x86 *c = &cpu_data(smp_processor_id()); + + zenbleed_check(c); +} + +void amd_check_microcode(void) +{ + on_each_cpu(zenbleed_check_cpu, NULL, 1); +} diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c index f7b4bbe71cdf..69752745a5b1 100644 --- a/arch/x86/kernel/cpu/common.c +++ b/arch/x86/kernel/cpu/common.c @@ -2185,6 +2185,8 @@ void microcode_check(struct cpuinfo_x86 *prev_info) perf_check_microcode(); + amd_check_microcode(); + store_cpu_caps(&curr_info); if (!memcmp(&prev_info->x86_capability, &curr_info.x86_capability, diff --git a/arch/x86/kernel/cpu/microcode/amd.c b/arch/x86/kernel/cpu/microcode/amd.c index 9bffe40e97d3..6a95a52d08da 100644 --- a/arch/x86/kernel/cpu/microcode/amd.c +++ b/arch/x86/kernel/cpu/microcode/amd.c @@ -699,7 +699,7 @@ static enum ucode_state apply_microcode_amd(int cpu) rdmsr(MSR_AMD64_PATCH_LEVEL, rev, dummy); /* need to apply patch? */ - if (rev >= mc_amd->hdr.patch_id) { + if (rev > mc_amd->hdr.patch_id) { ret = UCODE_OK; goto out; } diff --git a/arch/x86/kernel/cpu/resctrl/rdtgroup.c b/arch/x86/kernel/cpu/resctrl/rdtgroup.c index 421d31718fbd..2ec16477eb3e 100644 --- a/arch/x86/kernel/cpu/resctrl/rdtgroup.c +++ b/arch/x86/kernel/cpu/resctrl/rdtgroup.c @@ -731,11 +731,15 @@ unlock: static void show_rdt_tasks(struct rdtgroup *r, struct seq_file *s) { struct task_struct *p, *t; + pid_t pid; rcu_read_lock(); for_each_process_thread(p, t) { - if (is_closid_match(t, r) || is_rmid_match(t, r)) - seq_printf(s, "%d\n", t->pid); + if (is_closid_match(t, r) || is_rmid_match(t, r)) { + pid = task_pid_vnr(t); + if (pid) + seq_printf(s, "%d\n", pid); + } } rcu_read_unlock(); } diff --git a/arch/x86/kernel/smpboot.c b/arch/x86/kernel/smpboot.c index 85f6e242b6b4..714f66aa0338 100644 --- a/arch/x86/kernel/smpboot.c +++ b/arch/x86/kernel/smpboot.c @@ -105,6 +105,17 @@ DEFINE_PER_CPU_READ_MOSTLY(cpumask_var_t, cpu_llc_shared_map); DEFINE_PER_CPU_READ_MOSTLY(struct cpuinfo_x86, cpu_info); EXPORT_PER_CPU_SYMBOL(cpu_info); +struct mwait_cpu_dead { + unsigned int control; + unsigned int status; +}; + +/* + * Cache line aligned data for mwait_play_dead(). Separate on purpose so + * that it's unlikely to be touched by other CPUs. + */ +static DEFINE_PER_CPU_ALIGNED(struct mwait_cpu_dead, mwait_cpu_dead); + /* Logical package management. We might want to allocate that dynamically */ unsigned int __max_logical_packages __read_mostly; EXPORT_SYMBOL(__max_logical_packages); @@ -1685,10 +1696,10 @@ EXPORT_SYMBOL_GPL(cond_wakeup_cpu0); */ static inline void mwait_play_dead(void) { + struct mwait_cpu_dead *md = this_cpu_ptr(&mwait_cpu_dead); unsigned int eax, ebx, ecx, edx; unsigned int highest_cstate = 0; unsigned int highest_subcstate = 0; - void *mwait_ptr; int i; if (boot_cpu_data.x86_vendor == X86_VENDOR_AMD || @@ -1723,13 +1734,6 @@ static inline void mwait_play_dead(void) (highest_subcstate - 1); } - /* - * This should be a memory location in a cache line which is - * unlikely to be touched by other processors. The actual - * content is immaterial as it is not actually modified in any way. - */ - mwait_ptr = ¤t_thread_info()->flags; - wbinvd(); while (1) { @@ -1741,9 +1745,9 @@ static inline void mwait_play_dead(void) * case where we return around the loop. */ mb(); - clflush(mwait_ptr); + clflush(md); mb(); - __monitor(mwait_ptr, 0, 0); + __monitor(md, 0, 0); mb(); __mwait(eax, 0); diff --git a/arch/x86/mm/pgtable.c b/arch/x86/mm/pgtable.c index a224193d84bf..6bfb01b36b89 100644 --- a/arch/x86/mm/pgtable.c +++ b/arch/x86/mm/pgtable.c @@ -611,6 +611,16 @@ int pmdp_clear_flush_young(struct vm_area_struct *vma, return young; } + +pmd_t pmdp_invalidate_ad(struct vm_area_struct *vma, unsigned long address, + pmd_t *pmdp) +{ + /* + * No flush is necessary. Once an invalid PTE is established, the PTE's + * access and dirty bits cannot be updated. + */ + return pmdp_establish(vma, address, pmdp, pmd_mkinvalid(*pmdp)); +} #endif /** diff --git a/arch/xtensa/platforms/iss/network.c b/arch/xtensa/platforms/iss/network.c index 08d70c868c13..1270de83435e 100644 --- a/arch/xtensa/platforms/iss/network.c +++ b/arch/xtensa/platforms/iss/network.c @@ -231,7 +231,7 @@ static int tuntap_probe(struct iss_net_private *lp, int index, char *init) init += sizeof(TRANSPORT_TUNTAP_NAME) - 1; if (*init == ',') { - rem = split_if_spec(init + 1, &mac_str, &dev_name); + rem = split_if_spec(init + 1, &mac_str, &dev_name, NULL); if (rem != NULL) { pr_err("%s: extra garbage on specification : '%s'\n", dev->name, rem); diff --git a/block/blk-iocost.c b/block/blk-iocost.c index 43cf04966c74..f95feabb3ca8 100644 --- a/block/blk-iocost.c +++ b/block/blk-iocost.c @@ -2448,6 +2448,7 @@ static u64 adjust_inuse_and_calc_cost(struct ioc_gq *iocg, u64 vtime, u32 hwi, adj_step; s64 margin; u64 cost, new_inuse; + unsigned long flags; current_hweight(iocg, NULL, &hwi); old_hwi = hwi; @@ -2466,11 +2467,11 @@ static u64 adjust_inuse_and_calc_cost(struct ioc_gq *iocg, u64 vtime, iocg->inuse == iocg->active) return cost; - spin_lock_irq(&ioc->lock); + spin_lock_irqsave(&ioc->lock, flags); /* we own inuse only when @iocg is in the normal active state */ if (iocg->abs_vdebt || list_empty(&iocg->active_list)) { - spin_unlock_irq(&ioc->lock); + spin_unlock_irqrestore(&ioc->lock, flags); return cost; } @@ -2491,7 +2492,7 @@ static u64 adjust_inuse_and_calc_cost(struct ioc_gq *iocg, u64 vtime, } while (time_after64(vtime + cost, now->vnow) && iocg->inuse != iocg->active); - spin_unlock_irq(&ioc->lock); + spin_unlock_irqrestore(&ioc->lock, flags); TRACE_IOCG_PATH(inuse_adjust, iocg, now, old_inuse, iocg->inuse, old_hwi, hwi); diff --git a/block/disk-events.c b/block/disk-events.c index 8d5496e7592a..c3488409dd32 100644 --- a/block/disk-events.c +++ b/block/disk-events.c @@ -307,6 +307,7 @@ bool disk_force_media_change(struct gendisk *disk, unsigned int events) if (!(events & DISK_EVENT_MEDIA_CHANGE)) return false; + inc_diskseq(disk); if (__invalidate_device(disk->part0, true)) pr_warn("VFS: busy inodes on changed media %s\n", disk->disk_name); diff --git a/block/mq-deadline.c b/block/mq-deadline.c index aaef5088a3ba..c87309d0ff3b 100644 --- a/block/mq-deadline.c +++ b/block/mq-deadline.c @@ -31,6 +31,11 @@ */ static const int read_expire = HZ / 2; /* max time before a read is submitted. */ static const int write_expire = 5 * HZ; /* ditto for writes, these limits are SOFT! */ +/* + * Time after which to dispatch lower priority requests even if higher + * priority requests are pending. + */ +static const int prio_aging_expire = 10 * HZ; static const int writes_starved = 2; /* max times reads can starve a write */ static const int fifo_batch = 16; /* # of sequential requests treated as one by the above parameters. For throughput. */ @@ -51,17 +56,16 @@ enum dd_prio { enum { DD_PRIO_COUNT = 3 }; -/* I/O statistics per I/O priority. */ +/* + * I/O statistics per I/O priority. It is fine if these counters overflow. + * What matters is that these counters are at least as wide as + * log2(max_outstanding_requests). + */ struct io_stats_per_prio { - local_t inserted; - local_t merged; - local_t dispatched; - local_t completed; -}; - -/* I/O statistics for all I/O priorities (enum dd_prio). */ -struct io_stats { - struct io_stats_per_prio stats[DD_PRIO_COUNT]; + uint32_t inserted; + uint32_t merged; + uint32_t dispatched; + atomic_t completed; }; /* @@ -74,6 +78,7 @@ struct dd_per_prio { struct list_head fifo_list[DD_DIR_COUNT]; /* Next request in FIFO order. Read, write or both are NULL. */ struct request *next_rq[DD_DIR_COUNT]; + struct io_stats_per_prio stats; }; struct deadline_data { @@ -88,8 +93,6 @@ struct deadline_data { unsigned int batching; /* number of sequential requests made */ unsigned int starved; /* times reads have starved writes */ - struct io_stats __percpu *stats; - /* * settings that change how the i/o scheduler behaves */ @@ -98,38 +101,12 @@ struct deadline_data { int writes_starved; int front_merges; u32 async_depth; + int prio_aging_expire; spinlock_t lock; spinlock_t zone_lock; }; -/* Count one event of type 'event_type' and with I/O priority 'prio' */ -#define dd_count(dd, event_type, prio) do { \ - struct io_stats *io_stats = get_cpu_ptr((dd)->stats); \ - \ - BUILD_BUG_ON(!__same_type((dd), struct deadline_data *)); \ - BUILD_BUG_ON(!__same_type((prio), enum dd_prio)); \ - local_inc(&io_stats->stats[(prio)].event_type); \ - put_cpu_ptr(io_stats); \ -} while (0) - -/* - * Returns the total number of dd_count(dd, event_type, prio) calls across all - * CPUs. No locking or barriers since it is fine if the returned sum is slightly - * outdated. - */ -#define dd_sum(dd, event_type, prio) ({ \ - unsigned int cpu; \ - u32 sum = 0; \ - \ - BUILD_BUG_ON(!__same_type((dd), struct deadline_data *)); \ - BUILD_BUG_ON(!__same_type((prio), enum dd_prio)); \ - for_each_present_cpu(cpu) \ - sum += local_read(&per_cpu_ptr((dd)->stats, cpu)-> \ - stats[(prio)].event_type); \ - sum; \ -}) - /* Maps an I/O priority class to a deadline scheduler priority. */ static const enum dd_prio ioprio_class_to_prio[] = { [IOPRIO_CLASS_NONE] = DD_BE_PRIO, @@ -247,7 +224,9 @@ static void dd_merged_requests(struct request_queue *q, struct request *req, const u8 ioprio_class = dd_rq_ioclass(next); const enum dd_prio prio = ioprio_class_to_prio[ioprio_class]; - dd_count(dd, merged, prio); + lockdep_assert_held(&dd->lock); + + dd->per_prio[prio].stats.merged++; /* * if next expires before rq, assign its expire time to rq @@ -284,6 +263,16 @@ deadline_move_request(struct deadline_data *dd, struct dd_per_prio *per_prio, deadline_remove_request(rq->q, per_prio, rq); } +/* Number of requests queued for a given priority level. */ +static u32 dd_queued(struct deadline_data *dd, enum dd_prio prio) +{ + const struct io_stats_per_prio *stats = &dd->per_prio[prio].stats; + + lockdep_assert_held(&dd->lock); + + return stats->inserted - atomic_read(&stats->completed); +} + /* * deadline_check_fifo returns 0 if there are no expired requests on the fifo, * 1 otherwise. Requires !list_empty(&dd->fifo_list[data_dir]) @@ -413,12 +402,27 @@ deadline_next_request(struct deadline_data *dd, struct dd_per_prio *per_prio, return rq; } +/* + * Returns true if and only if @rq started after @latest_start where + * @latest_start is in jiffies. + */ +static bool started_after(struct deadline_data *dd, struct request *rq, + unsigned long latest_start) +{ + unsigned long start_time = (unsigned long)rq->fifo_time; + + start_time -= dd->fifo_expire[rq_data_dir(rq)]; + + return time_after(start_time, latest_start); +} + /* * deadline_dispatch_requests selects the best request according to - * read/write expire, fifo_batch, etc + * read/write expire, fifo_batch, etc and with a start time <= @latest_start. */ static struct request *__dd_dispatch_request(struct deadline_data *dd, - struct dd_per_prio *per_prio) + struct dd_per_prio *per_prio, + unsigned long latest_start) { struct request *rq, *next_rq; enum dd_data_dir data_dir; @@ -430,6 +434,8 @@ static struct request *__dd_dispatch_request(struct deadline_data *dd, if (!list_empty(&per_prio->dispatch)) { rq = list_first_entry(&per_prio->dispatch, struct request, queuelist); + if (started_after(dd, rq, latest_start)) + return NULL; list_del_init(&rq->queuelist); goto done; } @@ -507,6 +513,9 @@ dispatch_find_request: dd->batching = 0; dispatch_request: + if (started_after(dd, rq, latest_start)) + return NULL; + /* * rq is the selected appropriate request. */ @@ -515,7 +524,7 @@ dispatch_request: done: ioprio_class = dd_rq_ioclass(rq); prio = ioprio_class_to_prio[ioprio_class]; - dd_count(dd, dispatched, prio); + dd->per_prio[prio].stats.dispatched++; /* * If the request needs its target zone locked, do it. */ @@ -524,6 +533,34 @@ done: return rq; } +/* + * Check whether there are any requests with priority other than DD_RT_PRIO + * that were inserted more than prio_aging_expire jiffies ago. + */ +static struct request *dd_dispatch_prio_aged_requests(struct deadline_data *dd, + unsigned long now) +{ + struct request *rq; + enum dd_prio prio; + int prio_cnt; + + lockdep_assert_held(&dd->lock); + + prio_cnt = !!dd_queued(dd, DD_RT_PRIO) + !!dd_queued(dd, DD_BE_PRIO) + + !!dd_queued(dd, DD_IDLE_PRIO); + if (prio_cnt < 2) + return NULL; + + for (prio = DD_BE_PRIO; prio <= DD_PRIO_MAX; prio++) { + rq = __dd_dispatch_request(dd, &dd->per_prio[prio], + now - dd->prio_aging_expire); + if (rq) + return rq; + } + + return NULL; +} + /* * Called from blk_mq_run_hw_queue() -> __blk_mq_sched_dispatch_requests(). * @@ -535,15 +572,26 @@ done: static struct request *dd_dispatch_request(struct blk_mq_hw_ctx *hctx) { struct deadline_data *dd = hctx->queue->elevator->elevator_data; + const unsigned long now = jiffies; struct request *rq; enum dd_prio prio; spin_lock(&dd->lock); + rq = dd_dispatch_prio_aged_requests(dd, now); + if (rq) + goto unlock; + + /* + * Next, dispatch requests in priority order. Ignore lower priority + * requests if any higher priority requests are pending. + */ for (prio = 0; prio <= DD_PRIO_MAX; prio++) { - rq = __dd_dispatch_request(dd, &dd->per_prio[prio]); - if (rq) + rq = __dd_dispatch_request(dd, &dd->per_prio[prio], now); + if (rq || dd_queued(dd, prio)) break; } + +unlock: spin_unlock(&dd->lock); return rq; @@ -574,8 +622,9 @@ static void dd_depth_updated(struct blk_mq_hw_ctx *hctx) struct request_queue *q = hctx->queue; struct deadline_data *dd = q->elevator->elevator_data; struct blk_mq_tags *tags = hctx->sched_tags; + unsigned int shift = tags->bitmap_tags->sb.shift; - dd->async_depth = max(1UL, 3 * q->nr_requests / 4); + dd->async_depth = max(1U, 3 * (1U << shift) / 4); sbitmap_queue_min_shallow_depth(tags->bitmap_tags, dd->async_depth); } @@ -594,12 +643,21 @@ static void dd_exit_sched(struct elevator_queue *e) for (prio = 0; prio <= DD_PRIO_MAX; prio++) { struct dd_per_prio *per_prio = &dd->per_prio[prio]; + const struct io_stats_per_prio *stats = &per_prio->stats; + uint32_t queued; WARN_ON_ONCE(!list_empty(&per_prio->fifo_list[DD_READ])); WARN_ON_ONCE(!list_empty(&per_prio->fifo_list[DD_WRITE])); - } - free_percpu(dd->stats); + spin_lock(&dd->lock); + queued = dd_queued(dd, prio); + spin_unlock(&dd->lock); + + WARN_ONCE(queued != 0, + "statistics for priority %d: i %u m %u d %u c %u\n", + prio, stats->inserted, stats->merged, + stats->dispatched, atomic_read(&stats->completed)); + } kfree(dd); } @@ -624,11 +682,6 @@ static int dd_init_sched(struct request_queue *q, struct elevator_type *e) eq->elevator_data = dd; - dd->stats = alloc_percpu_gfp(typeof(*dd->stats), - GFP_KERNEL | __GFP_ZERO); - if (!dd->stats) - goto free_dd; - for (prio = 0; prio <= DD_PRIO_MAX; prio++) { struct dd_per_prio *per_prio = &dd->per_prio[prio]; @@ -644,15 +697,13 @@ static int dd_init_sched(struct request_queue *q, struct elevator_type *e) dd->front_merges = 1; dd->last_dir = DD_WRITE; dd->fifo_batch = fifo_batch; + dd->prio_aging_expire = prio_aging_expire; spin_lock_init(&dd->lock); spin_lock_init(&dd->zone_lock); q->elevator = eq; return 0; -free_dd: - kfree(dd); - put_eq: kobject_put(&eq->kobj); return ret; @@ -735,8 +786,11 @@ static void dd_insert_request(struct blk_mq_hw_ctx *hctx, struct request *rq, blk_req_zone_write_unlock(rq); prio = ioprio_class_to_prio[ioprio_class]; - dd_count(dd, inserted, prio); - rq->elv.priv[0] = (void *)(uintptr_t)1; + per_prio = &dd->per_prio[prio]; + if (!rq->elv.priv[0]) { + per_prio->stats.inserted++; + rq->elv.priv[0] = (void *)(uintptr_t)1; + } if (blk_mq_sched_try_insert_merge(q, rq, &free)) { blk_mq_free_requests(&free); @@ -745,9 +799,9 @@ static void dd_insert_request(struct blk_mq_hw_ctx *hctx, struct request *rq, trace_block_rq_insert(rq); - per_prio = &dd->per_prio[prio]; if (at_head) { list_add(&rq->queuelist, &per_prio->dispatch); + rq->fifo_time = jiffies; } else { deadline_add_rq_rb(per_prio, rq); @@ -825,15 +879,17 @@ static void dd_finish_request(struct request *rq) struct deadline_data *dd = q->elevator->elevator_data; const u8 ioprio_class = dd_rq_ioclass(rq); const enum dd_prio prio = ioprio_class_to_prio[ioprio_class]; + struct dd_per_prio *per_prio = &dd->per_prio[prio]; /* * The block layer core may call dd_finish_request() without having - * called dd_insert_requests(). Hence only update statistics for - * requests for which dd_insert_requests() has been called. See also - * blk_mq_request_bypass_insert(). + * called dd_insert_requests(). Skip requests that bypassed I/O + * scheduling. See also blk_mq_request_bypass_insert(). */ - if (rq->elv.priv[0]) - dd_count(dd, completed, prio); + if (!rq->elv.priv[0]) + return; + + atomic_inc(&per_prio->stats.completed); if (blk_queue_is_zoned(q)) { unsigned long flags; @@ -879,6 +935,7 @@ static ssize_t __FUNC(struct elevator_queue *e, char *page) \ #define SHOW_JIFFIES(__FUNC, __VAR) SHOW_INT(__FUNC, jiffies_to_msecs(__VAR)) SHOW_JIFFIES(deadline_read_expire_show, dd->fifo_expire[DD_READ]); SHOW_JIFFIES(deadline_write_expire_show, dd->fifo_expire[DD_WRITE]); +SHOW_JIFFIES(deadline_prio_aging_expire_show, dd->prio_aging_expire); SHOW_INT(deadline_writes_starved_show, dd->writes_starved); SHOW_INT(deadline_front_merges_show, dd->front_merges); SHOW_INT(deadline_async_depth_show, dd->async_depth); @@ -908,6 +965,7 @@ static ssize_t __FUNC(struct elevator_queue *e, const char *page, size_t count) STORE_FUNCTION(__FUNC, __PTR, MIN, MAX, msecs_to_jiffies) STORE_JIFFIES(deadline_read_expire_store, &dd->fifo_expire[DD_READ], 0, INT_MAX); STORE_JIFFIES(deadline_write_expire_store, &dd->fifo_expire[DD_WRITE], 0, INT_MAX); +STORE_JIFFIES(deadline_prio_aging_expire_store, &dd->prio_aging_expire, 0, INT_MAX); STORE_INT(deadline_writes_starved_store, &dd->writes_starved, INT_MIN, INT_MAX); STORE_INT(deadline_front_merges_store, &dd->front_merges, 0, 1); STORE_INT(deadline_async_depth_store, &dd->async_depth, 1, INT_MAX); @@ -926,6 +984,7 @@ static struct elv_fs_entry deadline_attrs[] = { DD_ATTR(front_merges), DD_ATTR(async_depth), DD_ATTR(fifo_batch), + DD_ATTR(prio_aging_expire), __ATTR_NULL }; @@ -1017,38 +1076,48 @@ static int dd_async_depth_show(void *data, struct seq_file *m) return 0; } -/* Number of requests queued for a given priority level. */ -static u32 dd_queued(struct deadline_data *dd, enum dd_prio prio) -{ - return dd_sum(dd, inserted, prio) - dd_sum(dd, completed, prio); -} - static int dd_queued_show(void *data, struct seq_file *m) { struct request_queue *q = data; struct deadline_data *dd = q->elevator->elevator_data; + u32 rt, be, idle; + + spin_lock(&dd->lock); + rt = dd_queued(dd, DD_RT_PRIO); + be = dd_queued(dd, DD_BE_PRIO); + idle = dd_queued(dd, DD_IDLE_PRIO); + spin_unlock(&dd->lock); + + seq_printf(m, "%u %u %u\n", rt, be, idle); - seq_printf(m, "%u %u %u\n", dd_queued(dd, DD_RT_PRIO), - dd_queued(dd, DD_BE_PRIO), - dd_queued(dd, DD_IDLE_PRIO)); return 0; } /* Number of requests owned by the block driver for a given priority. */ static u32 dd_owned_by_driver(struct deadline_data *dd, enum dd_prio prio) { - return dd_sum(dd, dispatched, prio) + dd_sum(dd, merged, prio) - - dd_sum(dd, completed, prio); + const struct io_stats_per_prio *stats = &dd->per_prio[prio].stats; + + lockdep_assert_held(&dd->lock); + + return stats->dispatched + stats->merged - + atomic_read(&stats->completed); } static int dd_owned_by_driver_show(void *data, struct seq_file *m) { struct request_queue *q = data; struct deadline_data *dd = q->elevator->elevator_data; + u32 rt, be, idle; + + spin_lock(&dd->lock); + rt = dd_owned_by_driver(dd, DD_RT_PRIO); + be = dd_owned_by_driver(dd, DD_BE_PRIO); + idle = dd_owned_by_driver(dd, DD_IDLE_PRIO); + spin_unlock(&dd->lock); + + seq_printf(m, "%u %u %u\n", rt, be, idle); - seq_printf(m, "%u %u %u\n", dd_owned_by_driver(dd, DD_RT_PRIO), - dd_owned_by_driver(dd, DD_BE_PRIO), - dd_owned_by_driver(dd, DD_IDLE_PRIO)); return 0; } diff --git a/block/partitions/amiga.c b/block/partitions/amiga.c index 5c8624e26a54..506921095412 100644 --- a/block/partitions/amiga.c +++ b/block/partitions/amiga.c @@ -11,10 +11,18 @@ #define pr_fmt(fmt) fmt #include +#include +#include #include #include "check.h" +/* magic offsets in partition DosEnvVec */ +#define NR_HD 3 +#define NR_SECT 5 +#define LO_CYL 9 +#define HI_CYL 10 + static __inline__ u32 checksum_block(__be32 *m, int size) { @@ -31,8 +39,12 @@ int amiga_partition(struct parsed_partitions *state) unsigned char *data; struct RigidDiskBlock *rdb; struct PartitionBlock *pb; - int start_sect, nr_sects, blk, part, res = 0; - int blksize = 1; /* Multiplier for disk block size */ + u64 start_sect, nr_sects; + sector_t blk, end_sect; + u32 cylblk; /* rdb_CylBlocks = nr_heads*sect_per_track */ + u32 nr_hd, nr_sect, lo_cyl, hi_cyl; + int part, res = 0; + unsigned int blksize = 1; /* Multiplier for disk block size */ int slot = 1; for (blk = 0; ; blk++, put_dev_sector(sect)) { @@ -40,7 +52,7 @@ int amiga_partition(struct parsed_partitions *state) goto rdb_done; data = read_part_sector(state, blk, §); if (!data) { - pr_err("Dev %s: unable to read RDB block %d\n", + pr_err("Dev %s: unable to read RDB block %llu\n", state->disk->disk_name, blk); res = -1; goto rdb_done; @@ -57,12 +69,12 @@ int amiga_partition(struct parsed_partitions *state) *(__be32 *)(data+0xdc) = 0; if (checksum_block((__be32 *)data, be32_to_cpu(rdb->rdb_SummedLongs) & 0x7F)==0) { - pr_err("Trashed word at 0xd0 in block %d ignored in checksum calculation\n", + pr_err("Trashed word at 0xd0 in block %llu ignored in checksum calculation\n", blk); break; } - pr_err("Dev %s: RDB in block %d has bad checksum\n", + pr_err("Dev %s: RDB in block %llu has bad checksum\n", state->disk->disk_name, blk); } @@ -78,11 +90,16 @@ int amiga_partition(struct parsed_partitions *state) } blk = be32_to_cpu(rdb->rdb_PartitionList); put_dev_sector(sect); - for (part = 1; blk>0 && part<=16; part++, put_dev_sector(sect)) { - blk *= blksize; /* Read in terms partition table understands */ + for (part = 1; (s32) blk>0 && part<=16; part++, put_dev_sector(sect)) { + /* Read in terms partition table understands */ + if (check_mul_overflow(blk, (sector_t) blksize, &blk)) { + pr_err("Dev %s: overflow calculating partition block %llu! Skipping partitions %u and beyond\n", + state->disk->disk_name, blk, part); + break; + } data = read_part_sector(state, blk, §); if (!data) { - pr_err("Dev %s: unable to read partition block %d\n", + pr_err("Dev %s: unable to read partition block %llu\n", state->disk->disk_name, blk); res = -1; goto rdb_done; @@ -94,19 +111,70 @@ int amiga_partition(struct parsed_partitions *state) if (checksum_block((__be32 *)pb, be32_to_cpu(pb->pb_SummedLongs) & 0x7F) != 0 ) continue; - /* Tell Kernel about it */ + /* RDB gives us more than enough rope to hang ourselves with, + * many times over (2^128 bytes if all fields max out). + * Some careful checks are in order, so check for potential + * overflows. + * We are multiplying four 32 bit numbers to one sector_t! + */ + + nr_hd = be32_to_cpu(pb->pb_Environment[NR_HD]); + nr_sect = be32_to_cpu(pb->pb_Environment[NR_SECT]); + + /* CylBlocks is total number of blocks per cylinder */ + if (check_mul_overflow(nr_hd, nr_sect, &cylblk)) { + pr_err("Dev %s: heads*sects %u overflows u32, skipping partition!\n", + state->disk->disk_name, cylblk); + continue; + } + + /* check for consistency with RDB defined CylBlocks */ + if (cylblk > be32_to_cpu(rdb->rdb_CylBlocks)) { + pr_warn("Dev %s: cylblk %u > rdb_CylBlocks %u!\n", + state->disk->disk_name, cylblk, + be32_to_cpu(rdb->rdb_CylBlocks)); + } + + /* RDB allows for variable logical block size - + * normalize to 512 byte blocks and check result. + */ + + if (check_mul_overflow(cylblk, blksize, &cylblk)) { + pr_err("Dev %s: partition %u bytes per cyl. overflows u32, skipping partition!\n", + state->disk->disk_name, part); + continue; + } + + /* Calculate partition start and end. Limit of 32 bit on cylblk + * guarantees no overflow occurs if LBD support is enabled. + */ + + lo_cyl = be32_to_cpu(pb->pb_Environment[LO_CYL]); + start_sect = ((u64) lo_cyl * cylblk); + + hi_cyl = be32_to_cpu(pb->pb_Environment[HI_CYL]); + nr_sects = (((u64) hi_cyl - lo_cyl + 1) * cylblk); - nr_sects = (be32_to_cpu(pb->pb_Environment[10]) + 1 - - be32_to_cpu(pb->pb_Environment[9])) * - be32_to_cpu(pb->pb_Environment[3]) * - be32_to_cpu(pb->pb_Environment[5]) * - blksize; if (!nr_sects) continue; - start_sect = be32_to_cpu(pb->pb_Environment[9]) * - be32_to_cpu(pb->pb_Environment[3]) * - be32_to_cpu(pb->pb_Environment[5]) * - blksize; + + /* Warn user if partition end overflows u32 (AmigaDOS limit) */ + + if ((start_sect + nr_sects) > UINT_MAX) { + pr_warn("Dev %s: partition %u (%llu-%llu) needs 64 bit device support!\n", + state->disk->disk_name, part, + start_sect, start_sect + nr_sects); + } + + if (check_add_overflow(start_sect, nr_sects, &end_sect)) { + pr_err("Dev %s: partition %u (%llu-%llu) needs LBD device support, skipping partition!\n", + state->disk->disk_name, part, + start_sect, end_sect); + continue; + } + + /* Tell Kernel about it */ + put_partition(state,slot++,start_sect,nr_sects); { /* Be even more informative to aid mounting */ diff --git a/build.config.gki.aarch64 b/build.config.gki.aarch64 index e0567a300c38..0a04fe765c97 100644 --- a/build.config.gki.aarch64 +++ b/build.config.gki.aarch64 @@ -25,6 +25,7 @@ android/abi_gki_aarch64_general android/abi_gki_aarch64_honor android/abi_gki_aarch64_imx android/abi_gki_aarch64_pixel +android/abi_gki_aarch64_microsoft android/abi_gki_aarch64_moto android/abi_gki_aarch64_mtktv android/abi_gki_aarch64_mtk @@ -41,6 +42,7 @@ android/abi_gki_aarch64_sunxi android/abi_gki_aarch64_pasa android/abi_gki_aarch64_zeku android/abi_gki_aarch64_lenovo +android/abi_gki_aarch64_transsion " FILES="${FILES} @@ -50,6 +52,7 @@ arch/arm64/boot/Image.gz # Update BUILD.bazel, define_common_kernels() if the value is not 1. TRIM_NONLISTED_KMI=${TRIM_NONLISTED_KMI:-1} +KMI_SYMBOL_LIST_ADD_ONLY=1 KMI_SYMBOL_LIST_STRICT_MODE=${KMI_SYMBOL_LIST_STRICT_MODE:-1} KMI_ENFORCED=1 diff --git a/build.config.msm.gki_fragement.kalama_lu b/build.config.msm.gki_fragement.kalama_lu new file mode 100644 index 000000000000..a404fce2264a --- /dev/null +++ b/build.config.msm.gki_fragement.kalama_lu @@ -0,0 +1,18 @@ +MSM_ARCH_FRAGMENT_CONFIG=kalama_lu_gki.fragment +export SOURCE_DATE_EPOCH=$(date '+%s') + +if [ "${VARIANT}" = gki ]; then + DEFCONFIG=lu_gki_defconfig + + PRE_DEFCONFIG_CMDS="KCONFIG_CONFIG=${ROOT_DIR}/${KERNEL_DIR}/arch/arm64/configs/${DEFCONFIG} ${ROOT_DIR}/${KERNEL_DIR}/scripts/kconfig/merge_config.sh -m -r ${ROOT_DIR}/${KERNEL_DIR}/arch/arm64/configs/gki_defconfig ${ROOT_DIR}/msm-kernel/arch/arm64/configs/${MSM_ARCH_FRAGMENT_CONFIG}" + POST_DEFCONFIG_CMDS="rm ${ROOT_DIR}/${KERNEL_DIR}/arch/arm64/configs/${DEFCONFIG}" + +elif [ "${VARIANT}" = consolidate ]; then + DEFCONFIG=lu_consolidate_defconfig + FRAGMENT_CONFIG=msm-kernel/arch/arm64/configs/consolidate.fragment + + PRE_DEFCONFIG_CMDS="KCONFIG_CONFIG=${ROOT_DIR}/${KERNEL_DIR}/arch/arm64/configs/lu_gki_defconfig ${ROOT_DIR}/${KERNEL_DIR}/scripts/kconfig/merge_config.sh -m -r ${ROOT_DIR}/${KERNEL_DIR}/arch/arm64/configs/gki_defconfig ${ROOT_DIR}/msm-kernel/arch/arm64/configs/${MSM_ARCH_FRAGMENT_CONFIG} && KCONFIG_CONFIG=${ROOT_DIR}/${KERNEL_DIR}/arch/arm64/configs/${DEFCONFIG} ${ROOT_DIR}/${KERNEL_DIR}/scripts/kconfig/merge_config.sh -m -r ${ROOT_DIR}/${KERNEL_DIR}/arch/arm64/configs/lu_gki_defconfig ${ROOT_DIR}/${FRAGMENT_CONFIG}" + POST_DEFCONFIG_CMDS="rm ${ROOT_DIR}/${KERNEL_DIR}/arch/arm64/configs/${DEFCONFIG} && rm ${ROOT_DIR}/${KERNEL_DIR}/arch/arm64/configs/lu_gki_defconfig" + +fi + diff --git a/build.config.msm.kalama.lu b/build.config.msm.kalama.lu new file mode 100644 index 000000000000..3f45430a6155 --- /dev/null +++ b/build.config.msm.kalama.lu @@ -0,0 +1,38 @@ +################################################################################ +## Inheriting configs from ACK +. ${ROOT_DIR}/msm-kernel/build.config.common +. ${ROOT_DIR}/msm-kernel/build.config.aarch64 + +################################################################################ +## Variant setup +MSM_ARCH=kalama_lu +VARIANTS=(consolidate gki) +[ -z "${VARIANT}" ] && VARIANT=consolidate + +ABL_SRC=bootable/bootloader/edk2 +BOOT_IMAGE_HEADER_VERSION=2 +BASE_ADDRESS=0x80000000 +PAGE_SIZE=4096 + +BUILD_CONFIG_ABL=${ABL_SRC}/QcomModulePkg/build.config.msm.kalama.lu + +[ -z "${DT_OVERLAY_SUPPORT}" ] && DT_OVERLAY_SUPPORT=1 + +if [ "${KERNEL_CMDLINE_CONSOLE_AUTO}" != "0" ]; then + KERNEL_VENDOR_CMDLINE+=' console=ttyMSM0,115200n8 earlycon=qcom_geni,0x00a9C000 qcom_geni_serial.con_enabled=1 ' +fi + +if [ "${VARIANT}" == "gki" ]; then + KERNEL_VENDOR_CMDLINE+=' nosoftlockup ' + VENDOR_EXTRA_CMDLINE=' nosoftlockup ' +fi + +KERNEL_VENDOR_CMDLINE+=' bootconfig ' + +################################################################################ +## Inheriting MSM configs +. ${KERNEL_DIR}/build.config.msm.common +DEFCONFIG="gki_defconfig" +apply_defconfig_fragment ${KERNEL_DIR}/arch/${ARCH}/configs/kalama_lu_gki.fragment +. ${KERNEL_DIR}/build.config.msm.gki +GKI_GKI_BUILD_CONFIG_FRAGMENT=${KERNEL_DIR}/build.config.msm.gki_fragement.${MSM_ARCH} diff --git a/build.config.msm.qcs605 b/build.config.msm.qcs605 new file mode 100644 index 000000000000..51dc56354a0e --- /dev/null +++ b/build.config.msm.qcs605 @@ -0,0 +1,35 @@ +################################################################################ +## Inheriting configs from ACK +. "${ROOT_DIR}"/msm-kernel/build.config.common +. "${ROOT_DIR}"/msm-kernel/build.config.aarch64 + +################################################################################ +## Variant setup +MSM_ARCH=qcs605 +VARIANTS=(consolidate gki) +[ -z "${VARIANT}" ] && VARIANT=consolidate + +ABL_SRC=bootable/bootloader/edk2 +BOOT_IMAGE_HEADER_VERSION=4 +BASE_ADDRESS=0x80000000 +PAGE_SIZE=4096 +BUILD_VENDOR_DLKM=1 +PREPARE_SYSTEM_DLKM=1 +SYSTEM_DLKM_MODULES_LIST=${ROOT_DIR}/${KERNEL_DIR}/android/gki_system_dlkm_modules +SUPER_IMAGE_SIZE=0x10000000 +TRIM_UNUSED_MODULES=1 +BUILD_INIT_BOOT_IMG=1 + +MODULES_LIST_ORDER="1" +[ -z "${DT_OVERLAY_SUPPORT}" ] && DT_OVERLAY_SUPPORT=1 + +if [ "${KERNEL_CMDLINE_CONSOLE_AUTO}" != "0" ]; then + KERNEL_VENDOR_CMDLINE+=' console=ttyMSM0,115200n8 earlycon=qcom_geni,0x00a90000 qcom_geni_serial.con_enabled=1 ' +fi + +KERNEL_VENDOR_CMDLINE+=' bootconfig ' + +################################################################################ +## Inheriting MSM configs +. "${KERNEL_DIR}"/build.config.msm.common +. "${KERNEL_DIR}"/build.config.msm.gki diff --git a/build.targets b/build.targets index 92705cc541be..cefe7b224a0d 100644 --- a/build.targets +++ b/build.targets @@ -1,5 +1,6 @@ build.config.msm.kalama build.config.msm.kalama.le +build.config.msm.kalama.lu build.config.msm.kalama.vm build.config.msm.gen3auto build.config.msm.gen4auto @@ -14,3 +15,4 @@ build.config.msm.kona build.config.msm.kona.le build.config.msm.qcs405 build.config.msm.trinket +build.config.msm.qcs605 diff --git a/drivers/android/vendor_hooks.c b/drivers/android/vendor_hooks.c index ff6b45d7cbe3..5d67ca6962d6 100644 --- a/drivers/android/vendor_hooks.c +++ b/drivers/android/vendor_hooks.c @@ -278,6 +278,7 @@ EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_record_mutex_lock_starttime); EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_record_rtmutex_lock_starttime); EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_record_rwsem_lock_starttime); EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_record_pcpu_rwsem_starttime); +EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_percpu_rwsem_wq_add); EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_set_memory_nx); EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_set_memory_rw); EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_set_module_permit_before_init); @@ -385,6 +386,7 @@ EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_mem_cgroup_css_offline); EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_mem_cgroup_css_online); EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_mem_cgroup_free); EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_mem_cgroup_alloc); +EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_adjust_alloc_flags); EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_kmalloc_slab); EXPORT_TRACEPOINT_SYMBOL_GPL(android_rvh_cpuset_fork); EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_binder_looper_state_registered); @@ -453,8 +455,18 @@ EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_check_page_look_around_ref); EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_look_around); EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_look_around_migrate_page); EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_test_clear_look_around_ref); +EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_set_page_migrating); +EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_clear_page_migrating); +EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_cma_alloc_bypass); +EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_enable_thermal_genl_check); +EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_xhci_urb_suitable_bypass); +EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_alloc_pages_entry); +EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_isolate_freepages); /* * For type visibility */ const struct readahead_control *GKI_struct_readahead_control; EXPORT_SYMBOL_GPL(GKI_struct_readahead_control); +EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_exit_signal_whether_wake); +EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_exit_check); +EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_freeze_whether_wake); diff --git a/drivers/base/firmware_loader/fallback.c b/drivers/base/firmware_loader/fallback.c index d7d63c1aa993..00f0c234e5c5 100644 --- a/drivers/base/firmware_loader/fallback.c +++ b/drivers/base/firmware_loader/fallback.c @@ -106,7 +106,7 @@ static void fw_load_abort(struct fw_sysfs *fw_sysfs) static LIST_HEAD(pending_fw_head); -void kill_pending_fw_fallback_reqs(bool only_kill_custom) +void kill_pending_fw_fallback_reqs(bool kill_all) { struct fw_priv *fw_priv; struct fw_priv *next; @@ -114,9 +114,13 @@ void kill_pending_fw_fallback_reqs(bool only_kill_custom) mutex_lock(&fw_lock); list_for_each_entry_safe(fw_priv, next, &pending_fw_head, pending_list) { - if (!fw_priv->need_uevent || !only_kill_custom) + if (kill_all || !fw_priv->need_uevent) __fw_load_abort(fw_priv); } + + if (kill_all) + fw_load_abort_all = true; + mutex_unlock(&fw_lock); } @@ -511,7 +515,7 @@ static int fw_load_sysfs_fallback(struct fw_sysfs *fw_sysfs, long timeout) } mutex_lock(&fw_lock); - if (fw_state_is_aborted(fw_priv)) { + if (fw_load_abort_all || fw_state_is_aborted(fw_priv)) { mutex_unlock(&fw_lock); retval = -EINTR; goto out; diff --git a/drivers/base/firmware_loader/fallback.h b/drivers/base/firmware_loader/fallback.h index 3af7205b302f..1d9476d16a01 100644 --- a/drivers/base/firmware_loader/fallback.h +++ b/drivers/base/firmware_loader/fallback.h @@ -35,7 +35,7 @@ int firmware_fallback_sysfs(struct firmware *fw, const char *name, struct device *device, u32 opt_flags, int ret); -void kill_pending_fw_fallback_reqs(bool only_kill_custom); +void kill_pending_fw_fallback_reqs(bool kill_all); void fw_fallback_set_cache_timeout(void); void fw_fallback_set_default_timeout(void); @@ -52,7 +52,7 @@ static inline int firmware_fallback_sysfs(struct firmware *fw, const char *name, return ret; } -static inline void kill_pending_fw_fallback_reqs(bool only_kill_custom) { } +static inline void kill_pending_fw_fallback_reqs(bool kill_all) { } static inline void fw_fallback_set_cache_timeout(void) { } static inline void fw_fallback_set_default_timeout(void) { } diff --git a/drivers/base/firmware_loader/firmware.h b/drivers/base/firmware_loader/firmware.h index a3014e9e2c85..53e08de04b86 100644 --- a/drivers/base/firmware_loader/firmware.h +++ b/drivers/base/firmware_loader/firmware.h @@ -87,6 +87,7 @@ struct fw_priv { }; extern struct mutex fw_lock; +extern bool fw_load_abort_all; static inline bool __fw_state_check(struct fw_priv *fw_priv, enum fw_status status) diff --git a/drivers/base/firmware_loader/main.c b/drivers/base/firmware_loader/main.c index e74e5d0644b5..cada3c3018e0 100644 --- a/drivers/base/firmware_loader/main.c +++ b/drivers/base/firmware_loader/main.c @@ -92,6 +92,7 @@ static inline struct fw_priv *to_fw_priv(struct kref *ref) DEFINE_MUTEX(fw_lock); static struct firmware_cache fw_cache; +bool fw_load_abort_all; /* Builtin firmware support */ @@ -1525,10 +1526,10 @@ static int fw_pm_notify(struct notifier_block *notify_block, case PM_SUSPEND_PREPARE: case PM_RESTORE_PREPARE: /* - * kill pending fallback requests with a custom fallback - * to avoid stalling suspend. + * Here, kill pending fallback requests will only kill + * non-uevent firmware request to avoid stalling suspend. */ - kill_pending_fw_fallback_reqs(true); + kill_pending_fw_fallback_reqs(false); device_cache_fw_images(); break; @@ -1613,7 +1614,7 @@ static int fw_shutdown_notify(struct notifier_block *unused1, * Kill all pending fallback requests to avoid both stalling shutdown, * and avoid a deadlock with the usermode_lock. */ - kill_pending_fw_fallback_reqs(false); + kill_pending_fw_fallback_reqs(true); return NOTIFY_DONE; } diff --git a/drivers/base/power/domain.c b/drivers/base/power/domain.c index 24a82e252b7e..6ffee01e174d 100644 --- a/drivers/base/power/domain.c +++ b/drivers/base/power/domain.c @@ -2860,10 +2860,10 @@ static int genpd_parse_state(struct genpd_power_state *genpd_state, err = of_property_read_u32(state_node, "min-residency-us", &residency); if (!err) - genpd_state->residency_ns = 1000 * residency; + genpd_state->residency_ns = 1000LL * residency; - genpd_state->power_on_latency_ns = 1000 * exit_latency; - genpd_state->power_off_latency_ns = 1000 * entry_latency; + genpd_state->power_on_latency_ns = 1000LL * exit_latency; + genpd_state->power_off_latency_ns = 1000LL * entry_latency; genpd_state->fwnode = &state_node->fwnode; return 0; diff --git a/drivers/base/regmap/regmap-i2c.c b/drivers/base/regmap/regmap-i2c.c index 980e5ce6a3a3..3ec611dc0c09 100644 --- a/drivers/base/regmap/regmap-i2c.c +++ b/drivers/base/regmap/regmap-i2c.c @@ -242,8 +242,8 @@ static int regmap_i2c_smbus_i2c_read(void *context, const void *reg, static const struct regmap_bus regmap_i2c_smbus_i2c_block = { .write = regmap_i2c_smbus_i2c_write, .read = regmap_i2c_smbus_i2c_read, - .max_raw_read = I2C_SMBUS_BLOCK_MAX, - .max_raw_write = I2C_SMBUS_BLOCK_MAX, + .max_raw_read = I2C_SMBUS_BLOCK_MAX - 1, + .max_raw_write = I2C_SMBUS_BLOCK_MAX - 1, }; static int regmap_i2c_smbus_i2c_write_reg16(void *context, const void *data, @@ -299,8 +299,8 @@ static int regmap_i2c_smbus_i2c_read_reg16(void *context, const void *reg, static const struct regmap_bus regmap_i2c_smbus_i2c_block_reg16 = { .write = regmap_i2c_smbus_i2c_write_reg16, .read = regmap_i2c_smbus_i2c_read_reg16, - .max_raw_read = I2C_SMBUS_BLOCK_MAX, - .max_raw_write = I2C_SMBUS_BLOCK_MAX, + .max_raw_read = I2C_SMBUS_BLOCK_MAX - 2, + .max_raw_write = I2C_SMBUS_BLOCK_MAX - 2, }; static const struct regmap_bus *regmap_get_i2c_bus(struct i2c_client *i2c, diff --git a/drivers/base/regmap/regmap-spi-avmm.c b/drivers/base/regmap/regmap-spi-avmm.c index 67f89937219c..ad1da83e849f 100644 --- a/drivers/base/regmap/regmap-spi-avmm.c +++ b/drivers/base/regmap/regmap-spi-avmm.c @@ -666,7 +666,7 @@ static const struct regmap_bus regmap_spi_avmm_bus = { .reg_format_endian_default = REGMAP_ENDIAN_NATIVE, .val_format_endian_default = REGMAP_ENDIAN_NATIVE, .max_raw_read = SPI_AVMM_VAL_SIZE * MAX_READ_CNT, - .max_raw_write = SPI_AVMM_REG_SIZE + SPI_AVMM_VAL_SIZE * MAX_WRITE_CNT, + .max_raw_write = SPI_AVMM_VAL_SIZE * MAX_WRITE_CNT, .free_context = spi_avmm_bridge_ctx_free, }; diff --git a/drivers/base/regmap/regmap.c b/drivers/base/regmap/regmap.c index e65888d84222..8f9fe5fd4707 100644 --- a/drivers/base/regmap/regmap.c +++ b/drivers/base/regmap/regmap.c @@ -2042,8 +2042,6 @@ int _regmap_raw_write(struct regmap *map, unsigned int reg, size_t val_count = val_len / val_bytes; size_t chunk_count, chunk_bytes; size_t chunk_regs = val_count; - size_t max_data = map->max_raw_write - map->format.reg_bytes - - map->format.pad_bytes; int ret, i; if (!val_count) @@ -2051,8 +2049,8 @@ int _regmap_raw_write(struct regmap *map, unsigned int reg, if (map->use_single_write) chunk_regs = 1; - else if (map->max_raw_write && val_len > max_data) - chunk_regs = max_data / val_bytes; + else if (map->max_raw_write && val_len > map->max_raw_write) + chunk_regs = map->max_raw_write / val_bytes; chunk_count = val_count / chunk_regs; chunk_bytes = chunk_regs * val_bytes; diff --git a/drivers/bus/intel-ixp4xx-eb.c b/drivers/bus/intel-ixp4xx-eb.c index 91db001eb69a..972603ed06a6 100644 --- a/drivers/bus/intel-ixp4xx-eb.c +++ b/drivers/bus/intel-ixp4xx-eb.c @@ -33,7 +33,7 @@ #define IXP4XX_EXP_TIMING_STRIDE 0x04 #define IXP4XX_EXP_CS_EN BIT(31) #define IXP456_EXP_PAR_EN BIT(30) /* Only on IXP45x and IXP46x */ -#define IXP4XX_EXP_T1_MASK GENMASK(28, 27) +#define IXP4XX_EXP_T1_MASK GENMASK(29, 28) #define IXP4XX_EXP_T1_SHIFT 28 #define IXP4XX_EXP_T2_MASK GENMASK(27, 26) #define IXP4XX_EXP_T2_SHIFT 26 diff --git a/drivers/bus/mhi/controllers/mhi_qcom.c b/drivers/bus/mhi/controllers/mhi_qcom.c index 7938b7c0c4cb..22de0bfd5b9f 100644 --- a/drivers/bus/mhi/controllers/mhi_qcom.c +++ b/drivers/bus/mhi/controllers/mhi_qcom.c @@ -292,7 +292,7 @@ static struct mhi_event_config qcom_sxr_mhi_events[] = { static const struct mhi_controller_config qcom_sxr_mhi_config = { .max_channels = 128, - .timeout_ms = 2000, + .timeout_ms = 10000, .buf_len = 0x8000, .num_channels = ARRAY_SIZE(qcom_sxr_mhi_channels), .ch_cfg = qcom_sxr_mhi_channels, diff --git a/drivers/bus/ti-sysc.c b/drivers/bus/ti-sysc.c index e93912e56f28..7d508f905003 100644 --- a/drivers/bus/ti-sysc.c +++ b/drivers/bus/ti-sysc.c @@ -1759,7 +1759,7 @@ static u32 sysc_quirk_dispc(struct sysc *ddata, int dispc_offset, if (!ddata->module_va) return -EIO; - /* DISP_CONTROL */ + /* DISP_CONTROL, shut down lcd and digit on disable if enabled */ val = sysc_read(ddata, dispc_offset + 0x40); lcd_en = val & lcd_en_mask; digit_en = val & digit_en_mask; @@ -1771,7 +1771,7 @@ static u32 sysc_quirk_dispc(struct sysc *ddata, int dispc_offset, else irq_mask |= BIT(2) | BIT(3); /* EVSYNC bits */ } - if (disable & (lcd_en | digit_en)) + if (disable && (lcd_en || digit_en)) sysc_write(ddata, dispc_offset + 0x40, val & ~(lcd_en_mask | digit_en_mask)); diff --git a/drivers/char/adsprpc.c b/drivers/char/adsprpc.c index acbb0fd5a6ec..671a53a7eccd 100644 --- a/drivers/char/adsprpc.c +++ b/drivers/char/adsprpc.c @@ -57,6 +57,7 @@ #include #include #include +#include #ifdef CONFIG_HIBERNATION #include @@ -1002,14 +1003,13 @@ static void fastrpc_mmap_free(struct fastrpc_mmap *map, uint32_t flags) map->refs--; if (!map->refs && !map->is_persistent && !map->ctx_refs) hlist_del_init(&map->hn); - spin_unlock_irqrestore(&me->hlock, irq_flags); if (map->refs > 0) { ADSPRPC_WARN( "multiple references for remote heap size %zu va 0x%lx ref count is %d\n", map->size, map->va, map->refs); + spin_unlock_irqrestore(&me->hlock, irq_flags); return; } - spin_lock_irqsave(&me->hlock, irq_flags); if (map->is_persistent && map->in_use) map->in_use = false; spin_unlock_irqrestore(&me->hlock, irq_flags); @@ -4704,7 +4704,7 @@ static int fastrpc_mmap_on_dsp(struct fastrpc_file *fl, uint32_t flags, struct smq_phy_page page; int num = 1; remote_arg_t ra[3]; - int err = 0; + int err = 0, scm_ret = 0; struct { int pid; uint32_t flags; @@ -4752,7 +4752,8 @@ static int fastrpc_mmap_on_dsp(struct fastrpc_file *fl, uint32_t flags, *raddr = (uintptr_t)routargs.vaddrout; if (err) goto bail; - if (flags == ADSP_MMAP_REMOTE_HEAP_ADDR) { + if (flags == ADSP_MMAP_REMOTE_HEAP_ADDR || + flags == ADSP_MMAP_HEAP_ADDR) { VERIFY(err, VALID_FASTRPC_CID(cid)); if (err) { err = -ECHRNG; @@ -4762,7 +4763,30 @@ static int fastrpc_mmap_on_dsp(struct fastrpc_file *fl, uint32_t flags, goto bail; } } - if (flags == ADSP_MMAP_REMOTE_HEAP_ADDR + if (flags == ADSP_MMAP_HEAP_ADDR) { + struct qseecom_scm_desc desc = {0}; + + desc.args[0] = TZ_PIL_AUTH_QDSP6_PROC; + desc.args[1] = phys; + desc.args[2] = size; + desc.arginfo = SCM_ARGS(3); + scm_ret = qcom_scm_qseecom_call(SCM_SIP_FNID(SCM_SVC_PIL, + TZ_PIL_PROTECT_MEM_SUBSYS_ID), &desc, true); + if (scm_ret) { + ADSPRPC_ERR( + "qcom_scm_qseecom_call failed with %d for phys 0x%llx, size %zu\n", + scm_ret, phys, size); + scm_ret = -EADDRNOTAVAIL; + err = fastrpc_unmap_on_dsp(fl, + *raddr, phys, size, flags); + if (err) { + ADSPRPC_ERR( + "failed to unmap %d for phys 0x%llx, size %zd\n", + err, phys, size); + } + goto bail; + } + } else if (flags == ADSP_MMAP_REMOTE_HEAP_ADDR && me->channel[cid].rhvm.vmid && refs == 1) { err = hyp_assign_phys(phys, (uint64_t)size, hlosvm, 1, me->channel[cid].rhvm.vmid, @@ -4795,6 +4819,7 @@ static int fastrpc_munmap_on_dsp_rh(struct fastrpc_file *fl, uint64_t phys, struct fastrpc_apps *me = &gfa; int cid = -1; struct fastrpc_ioctl_invoke_async ioctl; + struct qseecom_scm_desc desc = {0}; remote_arg_t ra[2]; struct { uint8_t skey; @@ -4840,6 +4865,20 @@ static int fastrpc_munmap_on_dsp_rh(struct fastrpc_file *fl, uint64_t phys, } if (err) goto bail; + desc.args[0] = TZ_PIL_AUTH_QDSP6_PROC; + desc.args[1] = phys; + desc.args[2] = size; + desc.args[3] = routargs.skey; + desc.arginfo = SCM_ARGS(4); + err = qcom_scm_qseecom_call(SCM_SIP_FNID(SCM_SVC_PIL, + TZ_PIL_CLEAR_PROTECT_MEM_SUBSYS_ID), &desc, true); + if (err) { + ADSPRPC_ERR( + "qcom_scm_qseecom_call failed with %d for phys 0x%llx, size %zu\n", + err, phys, size); + err = -EADDRNOTAVAIL; + return err; + } bail: return err; @@ -4984,6 +5023,8 @@ static int fastrpc_mmap_remove_ssr(struct fastrpc_file *fl, int locked) fastrpc_mmap_add(match); } } + if (err) + goto bail; } memset(&ramdump_segments_rh, 0, sizeof(ramdump_segments_rh)); ramdump_segments_rh.da = match->phys; diff --git a/drivers/char/hw_random/imx-rngc.c b/drivers/char/hw_random/imx-rngc.c index 2964efeb71c3..c4ae72b6743e 100644 --- a/drivers/char/hw_random/imx-rngc.c +++ b/drivers/char/hw_random/imx-rngc.c @@ -110,7 +110,7 @@ static int imx_rngc_self_test(struct imx_rngc *rngc) cmd = readl(rngc->base + RNGC_COMMAND); writel(cmd | RNGC_CMD_SELF_TEST, rngc->base + RNGC_COMMAND); - ret = wait_for_completion_timeout(&rngc->rng_op_done, RNGC_TIMEOUT); + ret = wait_for_completion_timeout(&rngc->rng_op_done, msecs_to_jiffies(RNGC_TIMEOUT)); imx_rngc_irq_mask_clear(rngc); if (!ret) return -ETIMEDOUT; @@ -187,9 +187,7 @@ static int imx_rngc_init(struct hwrng *rng) cmd = readl(rngc->base + RNGC_COMMAND); writel(cmd | RNGC_CMD_SEED, rngc->base + RNGC_COMMAND); - ret = wait_for_completion_timeout(&rngc->rng_op_done, - RNGC_TIMEOUT); - + ret = wait_for_completion_timeout(&rngc->rng_op_done, msecs_to_jiffies(RNGC_TIMEOUT)); if (!ret) { ret = -ETIMEDOUT; goto err; diff --git a/drivers/char/hw_random/st-rng.c b/drivers/char/hw_random/st-rng.c index 15ba1e6fae4d..6e9dfac9fc9f 100644 --- a/drivers/char/hw_random/st-rng.c +++ b/drivers/char/hw_random/st-rng.c @@ -42,7 +42,6 @@ struct st_rng_data { void __iomem *base; - struct clk *clk; struct hwrng ops; }; @@ -85,26 +84,18 @@ static int st_rng_probe(struct platform_device *pdev) if (IS_ERR(base)) return PTR_ERR(base); - clk = devm_clk_get(&pdev->dev, NULL); + clk = devm_clk_get_enabled(&pdev->dev, NULL); if (IS_ERR(clk)) return PTR_ERR(clk); - ret = clk_prepare_enable(clk); - if (ret) - return ret; - ddata->ops.priv = (unsigned long)ddata; ddata->ops.read = st_rng_read; ddata->ops.name = pdev->name; ddata->base = base; - ddata->clk = clk; - - dev_set_drvdata(&pdev->dev, ddata); ret = devm_hwrng_register(&pdev->dev, &ddata->ops); if (ret) { dev_err(&pdev->dev, "Failed to register HW RNG\n"); - clk_disable_unprepare(clk); return ret; } @@ -113,15 +104,6 @@ static int st_rng_probe(struct platform_device *pdev) return 0; } -static int st_rng_remove(struct platform_device *pdev) -{ - struct st_rng_data *ddata = dev_get_drvdata(&pdev->dev); - - clk_disable_unprepare(ddata->clk); - - return 0; -} - static const struct of_device_id st_rng_match[] __maybe_unused = { { .compatible = "st,rng" }, {}, @@ -134,7 +116,6 @@ static struct platform_driver st_rng_driver = { .of_match_table = of_match_ptr(st_rng_match), }, .probe = st_rng_probe, - .remove = st_rng_remove }; module_platform_driver(st_rng_driver); diff --git a/drivers/char/hw_random/virtio-rng.c b/drivers/char/hw_random/virtio-rng.c index 208c547dcac1..3a194eb3ce8a 100644 --- a/drivers/char/hw_random/virtio-rng.c +++ b/drivers/char/hw_random/virtio-rng.c @@ -4,6 +4,7 @@ * Copyright (C) 2007, 2008 Rusty Russell IBM Corporation */ +#include #include #include #include @@ -20,12 +21,12 @@ struct virtrng_info { struct virtqueue *vq; char name[25]; int index; - bool busy; bool hwrng_register_done; bool hwrng_removed; /* data transfer */ struct completion have_data; unsigned int data_avail; + unsigned int data_idx; /* minimal size returned by rng_buffer_size() */ #if SMP_CACHE_BYTES < 32 u8 data[32]; @@ -37,19 +38,23 @@ struct virtrng_info { static void random_recv_done(struct virtqueue *vq) { struct virtrng_info *vi = vq->vdev->priv; + unsigned int len; /* We can get spurious callbacks, e.g. shared IRQs + virtio_pci. */ - if (!virtqueue_get_buf(vi->vq, &vi->data_avail)) + if (!virtqueue_get_buf(vi->vq, &len)) return; + smp_store_release(&vi->data_avail, len); complete(&vi->have_data); } -/* The host will fill any buffer we give it with sweet, sweet randomness. */ -static void register_buffer(struct virtrng_info *vi) +static void request_entropy(struct virtrng_info *vi) { struct scatterlist sg; + reinit_completion(&vi->have_data); + vi->data_idx = 0; + sg_init_one(&sg, vi->data, sizeof(vi->data)); /* There should always be room for one buffer. */ @@ -58,6 +63,18 @@ static void register_buffer(struct virtrng_info *vi) virtqueue_kick(vi->vq); } +static unsigned int copy_data(struct virtrng_info *vi, void *buf, + unsigned int size) +{ + size = min_t(unsigned int, size, vi->data_avail); + memcpy(buf, vi->data + vi->data_idx, size); + vi->data_idx += size; + vi->data_avail -= size; + if (vi->data_avail == 0) + request_entropy(vi); + return size; +} + static int virtio_read(struct hwrng *rng, void *buf, size_t size, bool wait) { int ret; @@ -68,35 +85,37 @@ static int virtio_read(struct hwrng *rng, void *buf, size_t size, bool wait) if (vi->hwrng_removed) return -ENODEV; - if (!vi->busy) { - vi->busy = true; - reinit_completion(&vi->have_data); - register_buffer(vi); + read = 0; + + /* copy available data */ + if (smp_load_acquire(&vi->data_avail)) { + chunk = copy_data(vi, buf, size); + size -= chunk; + read += chunk; } if (!wait) - return 0; + return read; - read = 0; + /* We have already copied available entropy, + * so either size is 0 or data_avail is 0 + */ while (size != 0) { + /* data_avail is 0 but a request is pending */ ret = wait_for_completion_killable(&vi->have_data); if (ret < 0) return ret; + /* if vi->data_avail is 0, we have been interrupted + * by a cleanup, but buffer stays in the queue + */ + if (vi->data_avail == 0) + return read; - chunk = min_t(unsigned int, size, vi->data_avail); - memcpy(buf + read, vi->data, chunk); - read += chunk; + chunk = copy_data(vi, buf + read, size); size -= chunk; - vi->data_avail = 0; - - if (size != 0) { - reinit_completion(&vi->have_data); - register_buffer(vi); - } + read += chunk; } - vi->busy = false; - return read; } @@ -104,8 +123,7 @@ static void virtio_cleanup(struct hwrng *rng) { struct virtrng_info *vi = (struct virtrng_info *)rng->priv; - if (vi->busy) - wait_for_completion(&vi->have_data); + complete(&vi->have_data); } static int probe_common(struct virtio_device *vdev) @@ -141,6 +159,9 @@ static int probe_common(struct virtio_device *vdev) goto err_find; } + /* we always have a pending entropy request */ + request_entropy(vi); + return 0; err_find: @@ -156,9 +177,9 @@ static void remove_common(struct virtio_device *vdev) vi->hwrng_removed = true; vi->data_avail = 0; + vi->data_idx = 0; complete(&vi->have_data); vdev->config->reset(vdev); - vi->busy = false; if (vi->hwrng_register_done) hwrng_unregister(&vi->hwrng); vdev->config->del_vqs(vdev); diff --git a/drivers/char/tpm/tpm_vtpm_proxy.c b/drivers/char/tpm/tpm_vtpm_proxy.c index 91c772e38bb5..ff2ec71d592e 100644 --- a/drivers/char/tpm/tpm_vtpm_proxy.c +++ b/drivers/char/tpm/tpm_vtpm_proxy.c @@ -683,37 +683,21 @@ static struct miscdevice vtpmx_miscdev = { .fops = &vtpmx_fops, }; -static int vtpmx_init(void) -{ - return misc_register(&vtpmx_miscdev); -} - -static void vtpmx_cleanup(void) -{ - misc_deregister(&vtpmx_miscdev); -} - static int __init vtpm_module_init(void) { int rc; - rc = vtpmx_init(); - if (rc) { - pr_err("couldn't create vtpmx device\n"); - return rc; - } - workqueue = create_workqueue("tpm-vtpm"); if (!workqueue) { pr_err("couldn't create workqueue\n"); - rc = -ENOMEM; - goto err_vtpmx_cleanup; + return -ENOMEM; } - return 0; - -err_vtpmx_cleanup: - vtpmx_cleanup(); + rc = misc_register(&vtpmx_miscdev); + if (rc) { + pr_err("couldn't create vtpmx device\n"); + destroy_workqueue(workqueue); + } return rc; } @@ -721,7 +705,7 @@ err_vtpmx_cleanup: static void __exit vtpm_module_exit(void) { destroy_workqueue(workqueue); - vtpmx_cleanup(); + misc_deregister(&vtpmx_miscdev); } module_init(vtpm_module_init); diff --git a/drivers/clk/clk-cdce925.c b/drivers/clk/clk-cdce925.c index 308b353815e1..470d91d7314d 100644 --- a/drivers/clk/clk-cdce925.c +++ b/drivers/clk/clk-cdce925.c @@ -705,6 +705,10 @@ static int cdce925_probe(struct i2c_client *client, for (i = 0; i < data->chip_info->num_plls; ++i) { pll_clk_name[i] = kasprintf(GFP_KERNEL, "%pOFn.pll%d", client->dev.of_node, i); + if (!pll_clk_name[i]) { + err = -ENOMEM; + goto error; + } init.name = pll_clk_name[i]; data->pll[i].chip = data; data->pll[i].hw.init = &init; @@ -746,6 +750,10 @@ static int cdce925_probe(struct i2c_client *client, init.num_parents = 1; init.parent_names = &parent_name; /* Mux Y1 to input */ init.name = kasprintf(GFP_KERNEL, "%pOFn.Y1", client->dev.of_node); + if (!init.name) { + err = -ENOMEM; + goto error; + } data->clk[0].chip = data; data->clk[0].hw.init = &init; data->clk[0].index = 0; @@ -764,6 +772,10 @@ static int cdce925_probe(struct i2c_client *client, for (i = 1; i < data->chip_info->num_outputs; ++i) { init.name = kasprintf(GFP_KERNEL, "%pOFn.Y%d", client->dev.of_node, i+1); + if (!init.name) { + err = -ENOMEM; + goto error; + } data->clk[i].chip = data; data->clk[i].hw.init = &init; data->clk[i].index = i; diff --git a/drivers/clk/clk-si5341.c b/drivers/clk/clk-si5341.c index 4de098b6b0d4..91a6bc74ebd5 100644 --- a/drivers/clk/clk-si5341.c +++ b/drivers/clk/clk-si5341.c @@ -1554,7 +1554,7 @@ static int si5341_probe(struct i2c_client *client, struct clk_init_data init; struct clk *input; const char *root_clock_name; - const char *synth_clock_names[SI5341_NUM_SYNTH]; + const char *synth_clock_names[SI5341_NUM_SYNTH] = { NULL }; int err; unsigned int i; struct clk_si5341_output_config config[SI5341_MAX_NUM_OUTPUTS]; @@ -1698,6 +1698,10 @@ static int si5341_probe(struct i2c_client *client, for (i = 0; i < data->num_synth; ++i) { synth_clock_names[i] = devm_kasprintf(&client->dev, GFP_KERNEL, "%s.N%u", client->dev.of_node->name, i); + if (!synth_clock_names[i]) { + err = -ENOMEM; + goto free_clk_names; + } init.name = synth_clock_names[i]; data->synth[i].index = i; data->synth[i].data = data; @@ -1706,6 +1710,7 @@ static int si5341_probe(struct i2c_client *client, if (err) { dev_err(&client->dev, "synth N%u registration failed\n", i); + goto free_clk_names; } } @@ -1715,6 +1720,10 @@ static int si5341_probe(struct i2c_client *client, for (i = 0; i < data->num_outputs; ++i) { init.name = kasprintf(GFP_KERNEL, "%s.%d", client->dev.of_node->name, i); + if (!init.name) { + err = -ENOMEM; + goto free_clk_names; + } init.flags = config[i].synth_master ? CLK_SET_RATE_PARENT : 0; data->clk[i].index = i; data->clk[i].data = data; @@ -1736,7 +1745,7 @@ static int si5341_probe(struct i2c_client *client, if (err) { dev_err(&client->dev, "output %u registration failed\n", i); - goto cleanup; + goto free_clk_names; } if (config[i].always_on) clk_prepare(data->clk[i].hw.clk); @@ -1746,7 +1755,7 @@ static int si5341_probe(struct i2c_client *client, data); if (err) { dev_err(&client->dev, "unable to add clk provider\n"); - goto cleanup; + goto free_clk_names; } if (initialization_required) { @@ -1754,11 +1763,11 @@ static int si5341_probe(struct i2c_client *client, regcache_cache_only(data->regmap, false); err = regcache_sync(data->regmap); if (err < 0) - goto cleanup; + goto free_clk_names; err = si5341_finalize_defaults(data); if (err < 0) - goto cleanup; + goto free_clk_names; } /* wait for device to report input clock present and PLL lock */ @@ -1767,32 +1776,31 @@ static int si5341_probe(struct i2c_client *client, 10000, 250000); if (err) { dev_err(&client->dev, "Error waiting for input clock or PLL lock\n"); - goto cleanup; + goto free_clk_names; } /* clear sticky alarm bits from initialization */ err = regmap_write(data->regmap, SI5341_STATUS_STICKY, 0); if (err) { dev_err(&client->dev, "unable to clear sticky status\n"); - goto cleanup; + goto free_clk_names; } err = sysfs_create_files(&client->dev.kobj, si5341_attributes); - if (err) { + if (err) dev_err(&client->dev, "unable to create sysfs files\n"); - goto cleanup; - } +free_clk_names: /* Free the names, clk framework makes copies */ for (i = 0; i < data->num_synth; ++i) devm_kfree(&client->dev, (void *)synth_clock_names[i]); - return 0; - cleanup: - for (i = 0; i < SI5341_MAX_NUM_OUTPUTS; ++i) { - if (data->clk[i].vddo_reg) - regulator_disable(data->clk[i].vddo_reg); + if (err) { + for (i = 0; i < SI5341_MAX_NUM_OUTPUTS; ++i) { + if (data->clk[i].vddo_reg) + regulator_disable(data->clk[i].vddo_reg); + } } return err; } diff --git a/drivers/clk/clk-versaclock5.c b/drivers/clk/clk-versaclock5.c index 5f8bd49b0810..c52f02471bb4 100644 --- a/drivers/clk/clk-versaclock5.c +++ b/drivers/clk/clk-versaclock5.c @@ -992,6 +992,11 @@ static int vc5_probe(struct i2c_client *client, const struct i2c_device_id *id) } init.name = kasprintf(GFP_KERNEL, "%pOFn.mux", client->dev.of_node); + if (!init.name) { + ret = -ENOMEM; + goto err_clk; + } + init.ops = &vc5_mux_ops; init.flags = 0; init.parent_names = parent_names; @@ -1006,6 +1011,10 @@ static int vc5_probe(struct i2c_client *client, const struct i2c_device_id *id) memset(&init, 0, sizeof(init)); init.name = kasprintf(GFP_KERNEL, "%pOFn.dbl", client->dev.of_node); + if (!init.name) { + ret = -ENOMEM; + goto err_clk; + } init.ops = &vc5_dbl_ops; init.flags = CLK_SET_RATE_PARENT; init.parent_names = parent_names; @@ -1021,6 +1030,10 @@ static int vc5_probe(struct i2c_client *client, const struct i2c_device_id *id) /* Register PFD */ memset(&init, 0, sizeof(init)); init.name = kasprintf(GFP_KERNEL, "%pOFn.pfd", client->dev.of_node); + if (!init.name) { + ret = -ENOMEM; + goto err_clk; + } init.ops = &vc5_pfd_ops; init.flags = CLK_SET_RATE_PARENT; init.parent_names = parent_names; @@ -1038,6 +1051,10 @@ static int vc5_probe(struct i2c_client *client, const struct i2c_device_id *id) /* Register PLL */ memset(&init, 0, sizeof(init)); init.name = kasprintf(GFP_KERNEL, "%pOFn.pll", client->dev.of_node); + if (!init.name) { + ret = -ENOMEM; + goto err_clk; + } init.ops = &vc5_pll_ops; init.flags = CLK_SET_RATE_PARENT; init.parent_names = parent_names; @@ -1057,6 +1074,10 @@ static int vc5_probe(struct i2c_client *client, const struct i2c_device_id *id) memset(&init, 0, sizeof(init)); init.name = kasprintf(GFP_KERNEL, "%pOFn.fod%d", client->dev.of_node, idx); + if (!init.name) { + ret = -ENOMEM; + goto err_clk; + } init.ops = &vc5_fod_ops; init.flags = CLK_SET_RATE_PARENT; init.parent_names = parent_names; @@ -1075,6 +1096,10 @@ static int vc5_probe(struct i2c_client *client, const struct i2c_device_id *id) memset(&init, 0, sizeof(init)); init.name = kasprintf(GFP_KERNEL, "%pOFn.out0_sel_i2cb", client->dev.of_node); + if (!init.name) { + ret = -ENOMEM; + goto err_clk; + } init.ops = &vc5_clk_out_ops; init.flags = CLK_SET_RATE_PARENT; init.parent_names = parent_names; @@ -1101,6 +1126,10 @@ static int vc5_probe(struct i2c_client *client, const struct i2c_device_id *id) memset(&init, 0, sizeof(init)); init.name = kasprintf(GFP_KERNEL, "%pOFn.out%d", client->dev.of_node, idx + 1); + if (!init.name) { + ret = -ENOMEM; + goto err_clk; + } init.ops = &vc5_clk_out_ops; init.flags = CLK_SET_RATE_PARENT; init.parent_names = parent_names; diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c index d7315a317cb7..6e6273334188 100644 --- a/drivers/clk/clk.c +++ b/drivers/clk/clk.c @@ -4569,6 +4569,7 @@ int devm_clk_notifier_register(struct device *dev, struct clk *clk, if (!ret) { devres->clk = clk; devres->nb = nb; + devres_add(dev, devres); } else { devres_free(devres); } diff --git a/drivers/clk/imx/clk-imx8mn.c b/drivers/clk/imx/clk-imx8mn.c index 52903146fdba..4499da4154f0 100644 --- a/drivers/clk/imx/clk-imx8mn.c +++ b/drivers/clk/imx/clk-imx8mn.c @@ -299,7 +299,7 @@ static int imx8mn_clocks_probe(struct platform_device *pdev) void __iomem *base; int ret; - clk_hw_data = kzalloc(struct_size(clk_hw_data, hws, + clk_hw_data = devm_kzalloc(dev, struct_size(clk_hw_data, hws, IMX8MN_CLK_END), GFP_KERNEL); if (WARN_ON(!clk_hw_data)) return -ENOMEM; @@ -316,10 +316,10 @@ static int imx8mn_clocks_probe(struct platform_device *pdev) hws[IMX8MN_CLK_EXT4] = imx_obtain_fixed_clk_hw(np, "clk_ext4"); np = of_find_compatible_node(NULL, NULL, "fsl,imx8mn-anatop"); - base = of_iomap(np, 0); + base = devm_of_iomap(dev, np, 0, NULL); of_node_put(np); - if (WARN_ON(!base)) { - ret = -ENOMEM; + if (WARN_ON(IS_ERR(base))) { + ret = PTR_ERR(base); goto unregister_hws; } diff --git a/drivers/clk/imx/clk-imx8mp.c b/drivers/clk/imx/clk-imx8mp.c index b173c3009394..0191457fb3cf 100644 --- a/drivers/clk/imx/clk-imx8mp.c +++ b/drivers/clk/imx/clk-imx8mp.c @@ -407,25 +407,22 @@ static int imx8mp_clocks_probe(struct platform_device *pdev) struct device *dev = &pdev->dev; struct device_node *np; void __iomem *anatop_base, *ccm_base; + int err; np = of_find_compatible_node(NULL, NULL, "fsl,imx8mp-anatop"); - anatop_base = of_iomap(np, 0); + anatop_base = devm_of_iomap(dev, np, 0, NULL); of_node_put(np); - if (WARN_ON(!anatop_base)) - return -ENOMEM; + if (WARN_ON(IS_ERR(anatop_base))) + return PTR_ERR(anatop_base); np = dev->of_node; ccm_base = devm_platform_ioremap_resource(pdev, 0); - if (WARN_ON(IS_ERR(ccm_base))) { - iounmap(anatop_base); + if (WARN_ON(IS_ERR(ccm_base))) return PTR_ERR(ccm_base); - } - clk_hw_data = kzalloc(struct_size(clk_hw_data, hws, IMX8MP_CLK_END), GFP_KERNEL); - if (WARN_ON(!clk_hw_data)) { - iounmap(anatop_base); + clk_hw_data = devm_kzalloc(dev, struct_size(clk_hw_data, hws, IMX8MP_CLK_END), GFP_KERNEL); + if (WARN_ON(!clk_hw_data)) return -ENOMEM; - } clk_hw_data->num = IMX8MP_CLK_END; hws = clk_hw_data->hws; @@ -710,7 +707,12 @@ static int imx8mp_clocks_probe(struct platform_device *pdev) imx_check_clk_hws(hws, IMX8MP_CLK_END); - of_clk_add_hw_provider(np, of_clk_hw_onecell_get, clk_hw_data); + err = of_clk_add_hw_provider(np, of_clk_hw_onecell_get, clk_hw_data); + if (err < 0) { + dev_err(dev, "failed to register hws for i.MX8MP\n"); + imx_unregister_hw_clocks(hws, IMX8MP_CLK_END); + return err; + } imx_register_uart_clocks(4); diff --git a/drivers/clk/imx/clk-scu.c b/drivers/clk/imx/clk-scu.c index dc933fd5d5a0..1cee88b073fa 100644 --- a/drivers/clk/imx/clk-scu.c +++ b/drivers/clk/imx/clk-scu.c @@ -702,11 +702,11 @@ struct clk_hw *imx_clk_scu_alloc_dev(const char *name, void imx_clk_scu_unregister(void) { - struct imx_scu_clk_node *clk; + struct imx_scu_clk_node *clk, *n; int i; for (i = 0; i < IMX_SC_R_LAST; i++) { - list_for_each_entry(clk, &imx_scu_clks[i], node) { + list_for_each_entry_safe(clk, n, &imx_scu_clks[i], node) { clk_hw_unregister(clk->hw); kfree(clk); } diff --git a/drivers/clk/keystone/sci-clk.c b/drivers/clk/keystone/sci-clk.c index 7e1b136e71ae..8af2a9faa805 100644 --- a/drivers/clk/keystone/sci-clk.c +++ b/drivers/clk/keystone/sci-clk.c @@ -302,6 +302,8 @@ static int _sci_clk_build(struct sci_clk_provider *provider, name = kasprintf(GFP_KERNEL, "clk:%d:%d", sci_clk->dev_id, sci_clk->clk_id); + if (!name) + return -ENOMEM; init.name = name; diff --git a/drivers/clk/qcom/Kconfig b/drivers/clk/qcom/Kconfig index 0f1cd4a3f09b..b00f44bf83ba 100644 --- a/drivers/clk/qcom/Kconfig +++ b/drivers/clk/qcom/Kconfig @@ -549,6 +549,15 @@ config SDM_LPASSCC_845 Say Y if you want to use the LPASS branch clocks of the LPASS clock controller to reset the LPASS subsystem. +config SDM_DEBUGCC_845 + tristate "SDM845 Debug Clock Controller" + depends on COMMON_CLK_QCOM + help + Support for the debug clock controller on Qualcomm Technologies, Inc + SDM845 devices. + Say Y if you want to support the debug clocks such as + clock measurement functionality. + config SDX_GCC_55 tristate "SDX55 Global Clock Controller" select QCOM_GDSC diff --git a/drivers/clk/qcom/Makefile b/drivers/clk/qcom/Makefile index 7f9cf2285c14..8ff7555b5946 100644 --- a/drivers/clk/qcom/Makefile +++ b/drivers/clk/qcom/Makefile @@ -96,6 +96,7 @@ obj-$(CONFIG_SC_MSS_7180) += mss-sc7180.o obj-$(CONFIG_SC_VIDEOCC_7180) += videocc-sc7180.o obj-$(CONFIG_SC_VIDEOCC_7280) += videocc-sc7280.o obj-$(CONFIG_SDM_CAMCC_845) += camcc-sdm845.o +obj-$(CONFIG_SDM_DEBUGCC_845) += debugcc-sdm845.o obj-$(CONFIG_SDM_DISPCC_845) += dispcc-sdm845.o obj-$(CONFIG_SDM_GCC_660) += gcc-sdm660.o obj-$(CONFIG_SDM_MMCC_660) += mmcc-sdm660.o diff --git a/drivers/clk/qcom/camcc-lemans.c b/drivers/clk/qcom/camcc-lemans.c index 2b09278a5384..e776e9fafdf2 100644 --- a/drivers/clk/qcom/camcc-lemans.c +++ b/drivers/clk/qcom/camcc-lemans.c @@ -18,6 +18,7 @@ #include "clk-alpha-pll.h" #include "clk-branch.h" #include "clk-pll.h" +#include "clk-pm.h" #include "clk-rcg.h" #include "clk-regmap.h" #include "common.h" @@ -1950,6 +1951,14 @@ static struct clk_branch cam_cc_titan_top_accu_shift_clk = { }, }; +/* + * Keep clocks always enabled: + * cam_cc_gdsc_clk + */ +static struct critical_clk_offset lemans_critical_clk_list[] = { + { .offset = 0x131ec, .mask = BIT(0) }, +}; + static struct clk_regmap *cam_cc_lemans_clocks[] = { [CAM_CC_CAMNOC_AXI_CLK] = &cam_cc_camnoc_axi_clk.clkr, [CAM_CC_CAMNOC_AXI_CLK_SRC] = &cam_cc_camnoc_axi_clk_src.clkr, @@ -2063,6 +2072,8 @@ static struct qcom_cc_desc cam_cc_lemans_desc = { .num_resets = ARRAY_SIZE(cam_cc_lemans_resets), .clk_regulators = cam_cc_lemans_regulators, .num_clk_regulators = ARRAY_SIZE(cam_cc_lemans_regulators), + .critical_clk_en = lemans_critical_clk_list, + .num_critical_clk = ARRAY_SIZE(lemans_critical_clk_list), }; static const struct of_device_id cam_cc_lemans_match_table[] = { @@ -2074,8 +2085,6 @@ MODULE_DEVICE_TABLE(of, cam_cc_lemans_match_table); static int cam_cc_lemans_fixup(struct platform_device *pdev, struct regmap *regmap) { - u32 offset = 0x131ec; - if (of_device_is_compatible(pdev->dev.of_node, "qcom,monaco_auto-camcc")) { cam_cc_camnoc_axi_clk_src.cmd_rcgr = 0x13154; cam_cc_camnoc_axi_clk.halt_reg = 0x1316c; @@ -2143,14 +2152,11 @@ static int cam_cc_lemans_fixup(struct platform_device *pdev, struct regmap *regm cam_cc_lemans_clocks[CAM_CC_TITAN_TOP_ACCU_SHIFT_CLK] = &cam_cc_titan_top_accu_shift_clk.clkr; - offset = 0x131d0; + lemans_critical_clk_list[0].offset = 0x131d0; } - /* - * Keep clocks always enabled: - * cam_cc_gdsc_clk - */ - regmap_update_bits(regmap, offset, BIT(0), BIT(0)); + /* Enabling always ON clocks */ + clk_restore_critical_clocks(&pdev->dev); return 0; } @@ -2164,13 +2170,9 @@ static int cam_cc_lemans_probe(struct platform_device *pdev) if (IS_ERR(regmap)) return PTR_ERR(regmap); - ret = qcom_cc_runtime_init(pdev, &cam_cc_lemans_desc); + ret = register_qcom_clks_pm(pdev, true, &cam_cc_lemans_desc); if (ret) - return ret; - - ret = pm_runtime_get_sync(&pdev->dev); - if (ret) - return ret; + dev_err(&pdev->dev, "Failed register cam_cc_pm_rt_ops clocks\n"); clk_lucid_evo_pll_configure(&cam_cc_pll0, regmap, cam_cc_pll0.config); clk_rivian_evo_pll_configure(&cam_cc_pll2, regmap, cam_cc_pll2.config); @@ -2199,19 +2201,12 @@ static void cam_cc_lemans_sync_state(struct device *dev) qcom_cc_sync_state(dev, &cam_cc_lemans_desc); } -static const struct dev_pm_ops cam_cc_lemans_pm_ops = { - SET_RUNTIME_PM_OPS(qcom_cc_runtime_suspend, qcom_cc_runtime_resume, NULL) - SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, - pm_runtime_force_resume) -}; - static struct platform_driver cam_cc_lemans_driver = { .probe = cam_cc_lemans_probe, .driver = { .name = "cam_cc-lemans", .of_match_table = cam_cc_lemans_match_table, .sync_state = cam_cc_lemans_sync_state, - .pm = &cam_cc_lemans_pm_ops, }, }; diff --git a/drivers/clk/qcom/camcc-sc7180.c b/drivers/clk/qcom/camcc-sc7180.c index ce73ee9037cb..4b3e3902b7ee 100644 --- a/drivers/clk/qcom/camcc-sc7180.c +++ b/drivers/clk/qcom/camcc-sc7180.c @@ -1493,12 +1493,21 @@ static struct clk_branch cam_cc_sys_tmr_clk = { }, }; +static struct gdsc titan_top_gdsc = { + .gdscr = 0xb134, + .pd = { + .name = "titan_top_gdsc", + }, + .pwrsts = PWRSTS_OFF_ON, +}; + static struct gdsc bps_gdsc = { .gdscr = 0x6004, .pd = { .name = "bps_gdsc", }, .pwrsts = PWRSTS_OFF_ON, + .parent = &titan_top_gdsc.pd, .flags = HW_CTRL, }; @@ -1508,6 +1517,7 @@ static struct gdsc ife_0_gdsc = { .name = "ife_0_gdsc", }, .pwrsts = PWRSTS_OFF_ON, + .parent = &titan_top_gdsc.pd, }; static struct gdsc ife_1_gdsc = { @@ -1516,6 +1526,7 @@ static struct gdsc ife_1_gdsc = { .name = "ife_1_gdsc", }, .pwrsts = PWRSTS_OFF_ON, + .parent = &titan_top_gdsc.pd, }; static struct gdsc ipe_0_gdsc = { @@ -1525,15 +1536,9 @@ static struct gdsc ipe_0_gdsc = { }, .pwrsts = PWRSTS_OFF_ON, .flags = HW_CTRL, + .parent = &titan_top_gdsc.pd, }; -static struct gdsc titan_top_gdsc = { - .gdscr = 0xb134, - .pd = { - .name = "titan_top_gdsc", - }, - .pwrsts = PWRSTS_OFF_ON, -}; static struct clk_hw *cam_cc_sc7180_hws[] = { [CAM_CC_PLL2_OUT_EARLY] = &cam_cc_pll2_out_early.hw, diff --git a/drivers/clk/qcom/clk-pm.c b/drivers/clk/qcom/clk-pm.c index 5b56bfc162c9..009799549a26 100644 --- a/drivers/clk/qcom/clk-pm.c +++ b/drivers/clk/qcom/clk-pm.c @@ -27,8 +27,20 @@ static int clock_pm_resume_early(struct device *dev) { #ifdef CONFIG_DEEPSLEEP if (pm_suspend_via_firmware()) { - clk_restore_context(); + if (pm_runtime_enabled(dev)) { + int ret; + + ret = pm_runtime_get_sync(dev); + if (ret < 0) + return ret; + + clk_restore_context(); + } + clk_restore_critical_clocks(dev); + + if (pm_runtime_enabled(dev)) + pm_runtime_put_sync(dev); } #endif return 0; diff --git a/drivers/clk/qcom/clk-rpmh.c b/drivers/clk/qcom/clk-rpmh.c index 0bfbf2f5f167..4a16d66efe33 100644 --- a/drivers/clk/qcom/clk-rpmh.c +++ b/drivers/clk/qcom/clk-rpmh.c @@ -462,6 +462,25 @@ static const struct clk_rpmh_desc clk_rpmh_sm8150 = { .num_clks = ARRAY_SIZE(sm8150_rpmh_clocks), }; +static struct clk_hw *sdm670_rpmh_clocks[] = { + [RPMH_CXO_CLK] = &sdm845_bi_tcxo.hw, + [RPMH_CXO_CLK_A] = &sdm845_bi_tcxo_ao.hw, + [RPMH_LN_BB_CLK2] = &sdm845_ln_bb_clk2.hw, + [RPMH_LN_BB_CLK2_A] = &sdm845_ln_bb_clk2_ao.hw, + [RPMH_LN_BB_CLK3] = &sdm845_ln_bb_clk3.hw, + [RPMH_LN_BB_CLK3_A] = &sdm845_ln_bb_clk3_ao.hw, + [RPMH_RF_CLK1] = &sdm845_rf_clk1.hw, + [RPMH_RF_CLK1_A] = &sdm845_rf_clk1_ao.hw, + [RPMH_RF_CLK2] = &sdm845_rf_clk2.hw, + [RPMH_RF_CLK2_A] = &sdm845_rf_clk2_ao.hw, + [RPMH_IPA_CLK] = &sdm845_ipa.hw, +}; + +static const struct clk_rpmh_desc clk_rpmh_sdm670 = { + .clks = sdm670_rpmh_clocks, + .num_clks = ARRAY_SIZE(sdm670_rpmh_clocks), +}; + static struct clk_hw *sc7180_rpmh_clocks[] = { [RPMH_CXO_CLK] = &sdm845_bi_tcxo.hw, [RPMH_CXO_CLK_A] = &sdm845_bi_tcxo_ao.hw, @@ -870,6 +889,7 @@ static const struct of_device_id clk_rpmh_match_table[] = { { .compatible = "qcom,sdxbaagha-rpmh-clk", .data = &clk_rpmh_sdxbaagha}, { .compatible = "qcom,lemans-rpmh-clk", .data = &clk_rpmh_lemans}, { .compatible = "qcom,crow-rpmh-clk", .data = &clk_rpmh_crow}, + { .compatible = "qcom,sdm670-rpmh-clk", .data = &clk_rpmh_sdm670}, { } }; MODULE_DEVICE_TABLE(of, clk_rpmh_match_table); diff --git a/drivers/clk/qcom/clk-smd-rpm.c b/drivers/clk/qcom/clk-smd-rpm.c index 1ac2358ea31e..8e367184eab1 100644 --- a/drivers/clk/qcom/clk-smd-rpm.c +++ b/drivers/clk/qcom/clk-smd-rpm.c @@ -1241,6 +1241,7 @@ DEFINE_CLK_SMD_RPM(monaco, bimc_gpu_clk, bimc_gpu_a_clk, QCOM_SMD_RPM_MEM_CLK, 2); DEFINE_CLK_SMD_RPM_XO_BUFFER(monaco, ln_bb_clk2, ln_bb_clk2_a, 0x2); +DEFINE_CLK_SMD_RPM_XO_BUFFER(monaco, rf_clk2, rf_clk2_a, 5); DEFINE_CLK_SMD_RPM_XO_BUFFER(monaco, rf_clk3, rf_clk3_a, 6); DEFINE_CLK_SMD_RPM_XO_BUFFER(monaco, cxo_d0, cxo_d0_a, 0); @@ -1255,6 +1256,8 @@ static struct clk_hw *monaco_clks[] = { [RPM_SMD_QDSS_A_CLK] = &holi_qdss_a_clk.hw, [RPM_SMD_LN_BB_CLK2] = &monaco_ln_bb_clk2.hw, [RPM_SMD_LN_BB_CLK2_A] = &monaco_ln_bb_clk2_a.hw, + [RPM_SMD_RF_CLK2] = &monaco_rf_clk2.hw, + [RPM_SMD_RF_CLK2_A] = &monaco_rf_clk2_a.hw, [RPM_SMD_RF_CLK3] = &monaco_rf_clk3.hw, [RPM_SMD_RF_CLK3_A] = &monaco_rf_clk3_a.hw, [RPM_SMD_CNOC_CLK] = &holi_cnoc_clk.hw, diff --git a/drivers/clk/qcom/debugcc-sdm845.c b/drivers/clk/qcom/debugcc-sdm845.c new file mode 100644 index 000000000000..303b5575fd40 --- /dev/null +++ b/drivers/clk/qcom/debugcc-sdm845.c @@ -0,0 +1,862 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2023, Qualcomm Innovation Center, Inc. All rights reserved. + */ + +#define pr_fmt(fmt) "clk: %s: " fmt, __func__ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "clk-debug.h" +#include "common.h" + +static struct measure_clk_data debug_mux_priv = { + .ctl_reg = 0x62024, + .status_reg = 0x62028, + .xo_div4_cbcr = 0x43008, +}; + +static const char *const apss_cc_debug_mux_parent_names[] = { + "measure_only_pwrcl_clk", + "measure_only_perfcl_clk", + "measure_only_l3_clk", +}; + +static int apss_cc_debug_mux_sels[] = { + 0x44, /* measure_only_pwrcl_clk */ + 0x45, /* measure_only_perfcl_clk */ + 0x46, /* measure_only_l3_clk */ +}; + +static int apss_cc_debug_mux_pre_divs[] = { + 0x10, /* measure_only_pwrcl_clk */ + 0x10, /* measure_only_perfcl_clk */ + 0x10, /* measure_only_l3_clk */ +}; + +static struct clk_debug_mux apss_cc_debug_mux = { + .priv = &debug_mux_priv, + .debug_offset = 0, + .post_div_offset = 0, + .cbcr_offset = U32_MAX, + .src_sel_mask = 0x7F0, + .src_sel_shift = 4, + .post_div_mask = 0x7800, + .post_div_shift = 11, + .post_div_val = 1, + .mux_sels = apss_cc_debug_mux_sels, + .num_mux_sels = ARRAY_SIZE(apss_cc_debug_mux_sels), + .pre_div_vals = apss_cc_debug_mux_pre_divs, + .hw.init = &(const struct clk_init_data){ + .name = "apss_cc_debug_mux", + .ops = &clk_debug_mux_ops, + .parent_names = apss_cc_debug_mux_parent_names, + .num_parents = ARRAY_SIZE(apss_cc_debug_mux_parent_names), + }, +}; + +static const char *const cam_cc_debug_mux_parent_names[] = { + "cam_cc_bps_ahb_clk", + "cam_cc_bps_areg_clk", + "cam_cc_bps_axi_clk", + "cam_cc_bps_clk", + "cam_cc_camnoc_atb_clk", + "cam_cc_camnoc_axi_clk", + "cam_cc_cci_clk", + "cam_cc_cpas_ahb_clk", + "cam_cc_csi0phytimer_clk", + "cam_cc_csi1phytimer_clk", + "cam_cc_csi2phytimer_clk", + "cam_cc_csi3phytimer_clk", + "cam_cc_csiphy0_clk", + "cam_cc_csiphy1_clk", + "cam_cc_csiphy2_clk", + "cam_cc_csiphy3_clk", + "cam_cc_fd_core_clk", + "cam_cc_fd_core_uar_clk", + "cam_cc_icp_apb_clk", + "cam_cc_icp_atb_clk", + "cam_cc_icp_clk", + "cam_cc_icp_cti_clk", + "cam_cc_icp_ts_clk", + "cam_cc_ife_0_axi_clk", + "cam_cc_ife_0_clk", + "cam_cc_ife_0_cphy_rx_clk", + "cam_cc_ife_0_csid_clk", + "cam_cc_ife_0_dsp_clk", + "cam_cc_ife_1_axi_clk", + "cam_cc_ife_1_clk", + "cam_cc_ife_1_cphy_rx_clk", + "cam_cc_ife_1_csid_clk", + "cam_cc_ife_1_dsp_clk", + "cam_cc_ife_lite_clk", + "cam_cc_ife_lite_cphy_rx_clk", + "cam_cc_ife_lite_csid_clk", + "cam_cc_ipe_0_ahb_clk", + "cam_cc_ipe_0_areg_clk", + "cam_cc_ipe_0_axi_clk", + "cam_cc_ipe_0_clk", + "cam_cc_ipe_1_ahb_clk", + "cam_cc_ipe_1_areg_clk", + "cam_cc_ipe_1_axi_clk", + "cam_cc_ipe_1_clk", + "cam_cc_jpeg_clk", + "cam_cc_lrme_clk", + "cam_cc_mclk0_clk", + "cam_cc_mclk1_clk", + "cam_cc_mclk2_clk", + "cam_cc_mclk3_clk", + "cam_cc_soc_ahb_clk", + "cam_cc_sys_tmr_clk", +}; + +static int cam_cc_debug_mux_sels[] = { + 0xE, /* cam_cc_bps_ahb_clk */ + 0xD, /* cam_cc_bps_areg_clk */ + 0xC, /* cam_cc_bps_axi_clk */ + 0xB, /* cam_cc_bps_clk */ + 0x34, /* cam_cc_camnoc_atb_clk */ + 0x2D, /* cam_cc_camnoc_axi_clk */ + 0x2A, /* cam_cc_cci_clk */ + 0x2C, /* cam_cc_cpas_ahb_clk */ + 0x5, /* cam_cc_csi0phytimer_clk */ + 0x7, /* cam_cc_csi1phytimer_clk */ + 0x9, /* cam_cc_csi2phytimer_clk */ + 0x35, /* cam_cc_csi3phytimer_clk */ + 0x6, /* cam_cc_csiphy0_clk */ + 0x8, /* cam_cc_csiphy1_clk */ + 0xA, /* cam_cc_csiphy2_clk */ + 0x36, /* cam_cc_csiphy3_clk */ + 0x28, /* cam_cc_fd_core_clk */ + 0x29, /* cam_cc_fd_core_uar_clk */ + 0x32, /* cam_cc_icp_apb_clk */ + 0x2F, /* cam_cc_icp_atb_clk */ + 0x26, /* cam_cc_icp_clk */ + 0x30, /* cam_cc_icp_cti_clk */ + 0x31, /* cam_cc_icp_ts_clk */ + 0x1B, /* cam_cc_ife_0_axi_clk */ + 0x17, /* cam_cc_ife_0_clk */ + 0x1A, /* cam_cc_ife_0_cphy_rx_clk */ + 0x19, /* cam_cc_ife_0_csid_clk */ + 0x18, /* cam_cc_ife_0_dsp_clk */ + 0x21, /* cam_cc_ife_1_axi_clk */ + 0x1D, /* cam_cc_ife_1_clk */ + 0x20, /* cam_cc_ife_1_cphy_rx_clk */ + 0x1F, /* cam_cc_ife_1_csid_clk */ + 0x1E, /* cam_cc_ife_1_dsp_clk */ + 0x22, /* cam_cc_ife_lite_clk */ + 0x24, /* cam_cc_ife_lite_cphy_rx_clk */ + 0x23, /* cam_cc_ife_lite_csid_clk */ + 0x12, /* cam_cc_ipe_0_ahb_clk */ + 0x11, /* cam_cc_ipe_0_areg_clk */ + 0x10, /* cam_cc_ipe_0_axi_clk */ + 0xF, /* cam_cc_ipe_0_clk */ + 0x16, /* cam_cc_ipe_1_ahb_clk */ + 0x15, /* cam_cc_ipe_1_areg_clk */ + 0x14, /* cam_cc_ipe_1_axi_clk */ + 0x13, /* cam_cc_ipe_1_clk */ + 0x25, /* cam_cc_jpeg_clk */ + 0x2B, /* cam_cc_lrme_clk */ + 0x1, /* cam_cc_mclk0_clk */ + 0x2, /* cam_cc_mclk1_clk */ + 0x3, /* cam_cc_mclk2_clk */ + 0x4, /* cam_cc_mclk3_clk */ + 0x2E, /* cam_cc_soc_ahb_clk */ + 0x33, /* cam_cc_sys_tmr_clk */ +}; + +static struct clk_debug_mux cam_cc_debug_mux = { + .priv = &debug_mux_priv, + .debug_offset = 0xc000, + .post_div_offset = 0xc004, + .cbcr_offset = 0xc008, + .src_sel_mask = 0xFF, + .src_sel_shift = 0, + .post_div_mask = 0x3, + .post_div_shift = 0, + .post_div_val = 1, + .mux_sels = cam_cc_debug_mux_sels, + .num_mux_sels = ARRAY_SIZE(cam_cc_debug_mux_sels), + .hw.init = &(const struct clk_init_data){ + .name = "cam_cc_debug_mux", + .ops = &clk_debug_mux_ops, + .parent_names = cam_cc_debug_mux_parent_names, + .num_parents = ARRAY_SIZE(cam_cc_debug_mux_parent_names), + }, +}; + +static const char *const disp_cc_debug_mux_parent_names[] = { + "disp_cc_mdss_ahb_clk", + "disp_cc_mdss_axi_clk", + "disp_cc_mdss_byte0_clk", + "disp_cc_mdss_byte0_intf_clk", + "disp_cc_mdss_byte1_clk", + "disp_cc_mdss_byte1_intf_clk", + "disp_cc_mdss_dp_aux_clk", + "disp_cc_mdss_dp_crypto_clk", + "disp_cc_mdss_dp_link_clk", + "disp_cc_mdss_dp_link_intf_clk", + "disp_cc_mdss_dp_pixel1_clk", + "disp_cc_mdss_dp_pixel_clk", + "disp_cc_mdss_esc0_clk", + "disp_cc_mdss_esc1_clk", + "disp_cc_mdss_mdp_clk", + "disp_cc_mdss_mdp_lut_clk", + "disp_cc_mdss_pclk0_clk", + "disp_cc_mdss_pclk1_clk", + "disp_cc_mdss_qdss_at_clk", + "disp_cc_mdss_qdss_tsctr_div8_clk", + "disp_cc_mdss_rot_clk", + "disp_cc_mdss_rscc_ahb_clk", + "disp_cc_mdss_rscc_vsync_clk", + "disp_cc_mdss_vsync_clk", +}; + +static int disp_cc_debug_mux_sels[] = { + 0x13, /* disp_cc_mdss_ahb_clk */ + 0x14, /* disp_cc_mdss_axi_clk */ + 0x7, /* disp_cc_mdss_byte0_clk */ + 0x8, /* disp_cc_mdss_byte0_intf_clk */ + 0x9, /* disp_cc_mdss_byte1_clk */ + 0xA, /* disp_cc_mdss_byte1_intf_clk */ + 0x12, /* disp_cc_mdss_dp_aux_clk */ + 0xF, /* disp_cc_mdss_dp_crypto_clk */ + 0xD, /* disp_cc_mdss_dp_link_clk */ + 0xE, /* disp_cc_mdss_dp_link_intf_clk */ + 0x11, /* disp_cc_mdss_dp_pixel1_clk */ + 0x10, /* disp_cc_mdss_dp_pixel_clk */ + 0xB, /* disp_cc_mdss_esc0_clk */ + 0xC, /* disp_cc_mdss_esc1_clk */ + 0x3, /* disp_cc_mdss_mdp_clk */ + 0x5, /* disp_cc_mdss_mdp_lut_clk */ + 0x1, /* disp_cc_mdss_pclk0_clk */ + 0x2, /* disp_cc_mdss_pclk1_clk */ + 0x15, /* disp_cc_mdss_qdss_at_clk */ + 0x16, /* disp_cc_mdss_qdss_tsctr_div8_clk */ + 0x4, /* disp_cc_mdss_rot_clk */ + 0x17, /* disp_cc_mdss_rscc_ahb_clk */ + 0x18, /* disp_cc_mdss_rscc_vsync_clk */ + 0x6, /* disp_cc_mdss_vsync_clk */ +}; + +static struct clk_debug_mux disp_cc_debug_mux = { + .priv = &debug_mux_priv, + .debug_offset = 0x6000, + .post_div_offset = 0x6008, + .cbcr_offset = 0x600C, + .src_sel_mask = 0xFF, + .src_sel_shift = 0, + .post_div_mask = 0x3, + .post_div_shift = 0, + .post_div_val = 1, + .mux_sels = disp_cc_debug_mux_sels, + .num_mux_sels = ARRAY_SIZE(disp_cc_debug_mux_sels), + .hw.init = &(const struct clk_init_data){ + .name = "disp_cc_debug_mux", + .ops = &clk_debug_mux_ops, + .parent_names = disp_cc_debug_mux_parent_names, + .num_parents = ARRAY_SIZE(disp_cc_debug_mux_parent_names), + }, +}; + +static const char *const gcc_debug_mux_parent_names[] = { + "cam_cc_debug_mux", + "disp_cc_debug_mux", + "video_cc_debug_mux", + "apss_cc_debug_mux", + "mss_gcc_debug_clk", + "gpu_cc_debug_mux", + "measure_only_snoc_clk", + "measure_only_cnoc_clk", + "measure_only_bimc_clk", + "measure_only_ipa_2x_clk", + "gcc_aggre_noc_pcie_tbu_clk", + "gcc_aggre_ufs_card_axi_clk", + "gcc_aggre_ufs_phy_axi_clk", + "gcc_aggre_usb3_prim_axi_clk", + "gcc_aggre_usb3_sec_axi_clk", + "gcc_apc_vs_clk", + "gcc_boot_rom_ahb_clk", + "gcc_camera_ahb_clk", + "gcc_camera_axi_clk", + "gcc_camera_xo_clk", + "gcc_ce1_ahb_clk", + "gcc_ce1_axi_clk", + "gcc_ce1_clk", + "gcc_cfg_noc_usb3_prim_axi_clk", + "gcc_cfg_noc_usb3_sec_axi_clk", + "gcc_cpuss_ahb_clk", + "gcc_cpuss_dvm_bus_clk", + "gcc_cpuss_gnoc_clk", + "gcc_cpuss_rbcpr_clk", + "gcc_ddrss_gpu_axi_clk", + "gcc_disp_ahb_clk", + "gcc_disp_axi_clk", + "gcc_disp_gpll0_clk_src", + "gcc_disp_gpll0_div_clk_src", + "gcc_disp_xo_clk", + "gcc_gp1_clk", + "gcc_gp2_clk", + "gcc_gp3_clk", + "gcc_gpu_cfg_ahb_clk", + "gcc_gpu_gpll0_clk_src", + "gcc_gpu_gpll0_div_clk_src", + "gcc_gpu_memnoc_gfx_clk", + "gcc_gpu_snoc_dvm_gfx_clk", + "gcc_gpu_vs_clk", + "gcc_mss_axis2_clk", + "gcc_mss_cfg_ahb_clk", + "gcc_mss_gpll0_div_clk_src", + "gcc_mss_mfab_axis_clk", + "gcc_mss_q6_memnoc_axi_clk", + "gcc_mss_snoc_axi_clk", + "gcc_mss_vs_clk", + "gcc_pcie_0_aux_clk", + "gcc_pcie_0_cfg_ahb_clk", + "gcc_pcie_0_mstr_axi_clk", + "gcc_pcie_0_pipe_clk", + "gcc_pcie_0_slv_axi_clk", + "gcc_pcie_0_slv_q2a_axi_clk", + "gcc_pcie_1_aux_clk", + "gcc_pcie_1_cfg_ahb_clk", + "gcc_pcie_1_mstr_axi_clk", + "gcc_pcie_1_pipe_clk", + "gcc_pcie_1_slv_axi_clk", + "gcc_pcie_1_slv_q2a_axi_clk", + "gcc_pcie_phy_aux_clk", + "gcc_pcie_phy_refgen_clk", + "gcc_pdm2_clk", + "gcc_pdm_ahb_clk", + "gcc_pdm_xo4_clk", + "gcc_prng_ahb_clk", + "gcc_qmip_camera_ahb_clk", + "gcc_qmip_disp_ahb_clk", + "gcc_qmip_video_ahb_clk", + "gcc_qupv3_wrap0_core_2x_clk", + "gcc_qupv3_wrap0_core_clk", + "gcc_qupv3_wrap0_s0_clk", + "gcc_qupv3_wrap0_s1_clk", + "gcc_qupv3_wrap0_s2_clk", + "gcc_qupv3_wrap0_s3_clk", + "gcc_qupv3_wrap0_s4_clk", + "gcc_qupv3_wrap0_s5_clk", + "gcc_qupv3_wrap0_s6_clk", + "gcc_qupv3_wrap0_s7_clk", + "gcc_qupv3_wrap1_core_2x_clk", + "gcc_qupv3_wrap1_core_clk", + "gcc_qupv3_wrap1_s0_clk", + "gcc_qupv3_wrap1_s1_clk", + "gcc_qupv3_wrap1_s2_clk", + "gcc_qupv3_wrap1_s3_clk", + "gcc_qupv3_wrap1_s4_clk", + "gcc_qupv3_wrap1_s5_clk", + "gcc_qupv3_wrap1_s6_clk", + "gcc_qupv3_wrap1_s7_clk", + "gcc_qupv3_wrap_0_m_ahb_clk", + "gcc_qupv3_wrap_0_s_ahb_clk", + "gcc_qupv3_wrap_1_m_ahb_clk", + "gcc_qupv3_wrap_1_s_ahb_clk", + "gcc_sdcc2_ahb_clk", + "gcc_sdcc2_apps_clk", + "gcc_sdcc4_ahb_clk", + "gcc_sdcc4_apps_clk", + "gcc_sys_noc_cpuss_ahb_clk", + "gcc_tsif_ahb_clk", + "gcc_tsif_inactivity_timers_clk", + "gcc_tsif_ref_clk", + "gcc_ufs_card_ahb_clk", + "gcc_ufs_card_axi_clk", + "gcc_ufs_card_ice_core_clk", + "gcc_ufs_card_phy_aux_clk", + "gcc_ufs_card_rx_symbol_0_clk", + "gcc_ufs_card_rx_symbol_1_clk", + "gcc_ufs_card_tx_symbol_0_clk", + "gcc_ufs_card_unipro_core_clk", + "gcc_ufs_phy_ahb_clk", + "gcc_ufs_phy_axi_clk", + "gcc_ufs_phy_ice_core_clk", + "gcc_ufs_phy_phy_aux_clk", + "gcc_ufs_phy_rx_symbol_0_clk", + "gcc_ufs_phy_rx_symbol_1_clk", + "gcc_ufs_phy_tx_symbol_0_clk", + "gcc_ufs_phy_unipro_core_clk", + "gcc_usb30_prim_master_clk", + "gcc_usb30_prim_mock_utmi_clk", + "gcc_usb30_prim_sleep_clk", + "gcc_usb30_sec_master_clk", + "gcc_usb30_sec_mock_utmi_clk", + "gcc_usb30_sec_sleep_clk", + "gcc_usb3_prim_phy_aux_clk", + "gcc_usb3_prim_phy_com_aux_clk", + "gcc_usb3_prim_phy_pipe_clk", + "gcc_usb3_sec_phy_aux_clk", + "gcc_usb3_sec_phy_com_aux_clk", + "gcc_usb3_sec_phy_pipe_clk", + "gcc_usb_phy_cfg_ahb2phy_clk", + "gcc_vdda_vs_clk", + "gcc_vddcx_vs_clk", + "gcc_vddmx_vs_clk", + "gcc_video_ahb_clk", + "gcc_video_axi_clk", + "gcc_video_xo_clk", + "gcc_vs_ctrl_ahb_clk", + "gcc_vs_ctrl_clk", + "gcc_sdcc1_ahb_clk", + "gcc_sdcc1_apps_clk", + "gcc_sdcc1_ice_core_clk", +}; + +static int gcc_debug_mux_sels[] = { + 0x46, /* cam_cc_debug_mux */ + 0x47, /* disp_cc_debug_mux */ + 0x48, /* video_cc_debug_mux */ + 0xD6, /* apss_cc_debug_mux */ + 0x136, /* mss_gcc_debug_clk */ + 0x144, /* gpu_cc_debug_mux */ + 0x7, /* measure_only_snoc_clk */ + 0x7, /* measure_only_cnoc_clk */ + 0x7, /* measure_only_bimc_clk */ + 0x7, /* measure_only_ipa_2x_clk */ + 0x2D, /* gcc_aggre_noc_pcie_tbu_clk */ + 0x11E, /* gcc_aggre_ufs_card_axi_clk */ + 0x11D, /* gcc_aggre_ufs_phy_axi_clk */ + 0x11B, /* gcc_aggre_usb3_prim_axi_clk */ + 0x11C, /* gcc_aggre_usb3_sec_axi_clk */ + 0x113, /* gcc_apc_vs_clk */ + 0x94, /* gcc_boot_rom_ahb_clk */ + 0x3A, /* gcc_camera_ahb_clk */ + 0x40, /* gcc_camera_axi_clk */ + 0x43, /* gcc_camera_xo_clk */ + 0xA9, /* gcc_ce1_ahb_clk */ + 0xA8, /* gcc_ce1_axi_clk */ + 0xA7, /* gcc_ce1_clk */ + 0x1D, /* gcc_cfg_noc_usb3_prim_axi_clk */ + 0x1E, /* gcc_cfg_noc_usb3_sec_axi_clk */ + 0xCE, /* gcc_cpuss_ahb_clk */ + 0xD3, /* gcc_cpuss_dvm_bus_clk */ + 0xCF, /* gcc_cpuss_gnoc_clk */ + 0xD0, /* gcc_cpuss_rbcpr_clk */ + 0xBB, /* gcc_ddrss_gpu_axi_clk */ + 0x3B, /* gcc_disp_ahb_clk */ + 0x41, /* gcc_disp_axi_clk */ + 0x4C, /* gcc_disp_gpll0_clk_src */ + 0x4D, /* gcc_disp_gpll0_div_clk_src */ + 0x44, /* gcc_disp_xo_clk */ + 0xDE, /* gcc_gp1_clk */ + 0xDF, /* gcc_gp2_clk */ + 0xE0, /* gcc_gp3_clk */ + 0x142, /* gcc_gpu_cfg_ahb_clk */ + 0x148, /* gcc_gpu_gpll0_clk_src */ + 0x149, /* gcc_gpu_gpll0_div_clk_src */ + 0x145, /* gcc_gpu_memnoc_gfx_clk */ + 0x147, /* gcc_gpu_snoc_dvm_gfx_clk */ + 0x112, /* gcc_gpu_vs_clk */ + 0x12F, /* gcc_mss_axis2_clk */ + 0x12D, /* gcc_mss_cfg_ahb_clk */ + 0x133, /* gcc_mss_gpll0_div_clk_src */ + 0x12E, /* gcc_mss_mfab_axis_clk */ + 0x135, /* gcc_mss_q6_memnoc_axi_clk */ + 0x134, /* gcc_mss_snoc_axi_clk */ + 0x111, /* gcc_mss_vs_clk */ + 0xE5, /* gcc_pcie_0_aux_clk */ + 0xE4, /* gcc_pcie_0_cfg_ahb_clk */ + 0xE3, /* gcc_pcie_0_mstr_axi_clk */ + 0xE6, /* gcc_pcie_0_pipe_clk */ + 0xE2, /* gcc_pcie_0_slv_axi_clk */ + 0xE1, /* gcc_pcie_0_slv_q2a_axi_clk */ + 0xEC, /* gcc_pcie_1_aux_clk */ + 0xEB, /* gcc_pcie_1_cfg_ahb_clk */ + 0xEA, /* gcc_pcie_1_mstr_axi_clk */ + 0xED, /* gcc_pcie_1_pipe_clk */ + 0xE9, /* gcc_pcie_1_slv_axi_clk */ + 0xE8, /* gcc_pcie_1_slv_q2a_axi_clk */ + 0xEF, /* gcc_pcie_phy_aux_clk */ + 0x160, /* gcc_pcie_phy_refgen_clk */ + 0x8E, /* gcc_pdm2_clk */ + 0x8C, /* gcc_pdm_ahb_clk */ + 0x8D, /* gcc_pdm_xo4_clk */ + 0x8F, /* gcc_prng_ahb_clk */ + 0x3D, /* gcc_qmip_camera_ahb_clk */ + 0x3E, /* gcc_qmip_disp_ahb_clk */ + 0x3C, /* gcc_qmip_video_ahb_clk */ + 0x77, /* gcc_qupv3_wrap0_core_2x_clk */ + 0x76, /* gcc_qupv3_wrap0_core_clk */ + 0x78, /* gcc_qupv3_wrap0_s0_clk */ + 0x79, /* gcc_qupv3_wrap0_s1_clk */ + 0x7A, /* gcc_qupv3_wrap0_s2_clk */ + 0x7B, /* gcc_qupv3_wrap0_s3_clk */ + 0x7C, /* gcc_qupv3_wrap0_s4_clk */ + 0x7D, /* gcc_qupv3_wrap0_s5_clk */ + 0x7E, /* gcc_qupv3_wrap0_s6_clk */ + 0x7F, /* gcc_qupv3_wrap0_s7_clk */ + 0x80, /* gcc_qupv3_wrap1_core_2x_clk */ + 0x81, /* gcc_qupv3_wrap1_core_clk */ + 0x84, /* gcc_qupv3_wrap1_s0_clk */ + 0x85, /* gcc_qupv3_wrap1_s1_clk */ + 0x86, /* gcc_qupv3_wrap1_s2_clk */ + 0x87, /* gcc_qupv3_wrap1_s3_clk */ + 0x88, /* gcc_qupv3_wrap1_s4_clk */ + 0x89, /* gcc_qupv3_wrap1_s5_clk */ + 0x8A, /* gcc_qupv3_wrap1_s6_clk */ + 0x8B, /* gcc_qupv3_wrap1_s7_clk */ + 0x74, /* gcc_qupv3_wrap_0_m_ahb_clk */ + 0x75, /* gcc_qupv3_wrap_0_s_ahb_clk */ + 0x82, /* gcc_qupv3_wrap_1_m_ahb_clk */ + 0x83, /* gcc_qupv3_wrap_1_s_ahb_clk */ + 0x71, /* gcc_sdcc2_ahb_clk */ + 0x70, /* gcc_sdcc2_apps_clk */ + 0x73, /* gcc_sdcc4_ahb_clk */ + 0x72, /* gcc_sdcc4_apps_clk */ + 0xC, /* gcc_sys_noc_cpuss_ahb_clk */ + 0x90, /* gcc_tsif_ahb_clk */ + 0x92, /* gcc_tsif_inactivity_timers_clk */ + 0x91, /* gcc_tsif_ref_clk */ + 0xF1, /* gcc_ufs_card_ahb_clk */ + 0xF0, /* gcc_ufs_card_axi_clk */ + 0xF7, /* gcc_ufs_card_ice_core_clk */ + 0xF8, /* gcc_ufs_card_phy_aux_clk */ + 0xF3, /* gcc_ufs_card_rx_symbol_0_clk */ + 0xF9, /* gcc_ufs_card_rx_symbol_1_clk */ + 0xF2, /* gcc_ufs_card_tx_symbol_0_clk */ + 0xF6, /* gcc_ufs_card_unipro_core_clk */ + 0xFC, /* gcc_ufs_phy_ahb_clk */ + 0xFB, /* gcc_ufs_phy_axi_clk */ + 0x102, /* gcc_ufs_phy_ice_core_clk */ + 0x103, /* gcc_ufs_phy_phy_aux_clk */ + 0xFE, /* gcc_ufs_phy_rx_symbol_0_clk */ + 0x104, /* gcc_ufs_phy_rx_symbol_1_clk */ + 0xFD, /* gcc_ufs_phy_tx_symbol_0_clk */ + 0x101, /* gcc_ufs_phy_unipro_core_clk */ + 0x5F, /* gcc_usb30_prim_master_clk */ + 0x61, /* gcc_usb30_prim_mock_utmi_clk */ + 0x60, /* gcc_usb30_prim_sleep_clk */ + 0x65, /* gcc_usb30_sec_master_clk */ + 0x67, /* gcc_usb30_sec_mock_utmi_clk */ + 0x66, /* gcc_usb30_sec_sleep_clk */ + 0x62, /* gcc_usb3_prim_phy_aux_clk */ + 0x63, /* gcc_usb3_prim_phy_com_aux_clk */ + 0x64, /* gcc_usb3_prim_phy_pipe_clk */ + 0x68, /* gcc_usb3_sec_phy_aux_clk */ + 0x69, /* gcc_usb3_sec_phy_com_aux_clk */ + 0x6A, /* gcc_usb3_sec_phy_pipe_clk */ + 0x6F, /* gcc_usb_phy_cfg_ahb2phy_clk */ + 0x10E, /* gcc_vdda_vs_clk */ + 0x10C, /* gcc_vddcx_vs_clk */ + 0x10D, /* gcc_vddmx_vs_clk */ + 0x39, /* gcc_video_ahb_clk */ + 0x3F, /* gcc_video_axi_clk */ + 0x42, /* gcc_video_xo_clk */ + 0x110, /* gcc_vs_ctrl_ahb_clk */ + 0x10F, /* gcc_vs_ctrl_clk */ + 0x15c, /* gcc_sdcc1_ahb_clk */ + 0x15b, /* gcc_sdcc1_apps_clk */ + 0x15d, /* gcc_sdcc1_ice_core_clk */ +}; + +static struct clk_debug_mux gcc_debug_mux = { + .priv = &debug_mux_priv, + .debug_offset = 0x62008, + .post_div_offset = 0x62000, + .cbcr_offset = 0x62004, + .src_sel_mask = 0x3FF, + .src_sel_shift = 0, + .post_div_mask = 0xF, + .post_div_shift = 0, + .post_div_val = 2, + .mux_sels = gcc_debug_mux_sels, + .num_mux_sels = ARRAY_SIZE(gcc_debug_mux_sels), + .hw.init = &(const struct clk_init_data){ + .name = "gcc_debug_mux", + .ops = &clk_debug_mux_ops, + .parent_names = gcc_debug_mux_parent_names, + .num_parents = ARRAY_SIZE(gcc_debug_mux_parent_names), + }, +}; + +static const char *const gpu_cc_debug_mux_parent_names[] = { + "gpu_cc_acd_cxo_clk", + "gpu_cc_crc_ahb_clk", + "gpu_cc_cx_apb_clk", + "gpu_cc_cx_gfx3d_clk", + "gpu_cc_cx_gfx3d_slv_clk", + "gpu_cc_cx_gmu_clk", + "gpu_cc_cx_qdss_at_clk", + "gpu_cc_cx_qdss_trig_clk", + "gpu_cc_cx_qdss_tsctr_clk", + "gpu_cc_cx_snoc_dvm_clk", + "gpu_cc_cxo_aon_clk", + "gpu_cc_cxo_clk", + "gpu_cc_gx_gfx3d_clk", + "gpu_cc_gx_gmu_clk", + "gpu_cc_gx_qdss_tsctr_clk", + "gpu_cc_gx_vsense_clk", + "gpu_cc_rbcpr_ahb_clk", + "gpu_cc_rbcpr_clk", + "gpu_cc_sleep_clk", +}; + +static int gpu_cc_debug_mux_sels[] = { + 0x1F, /* gpu_cc_acd_cxo_clk */ + 0x12, /* gpu_cc_crc_ahb_clk */ + 0x15, /* gpu_cc_cx_apb_clk */ + 0x1A, /* gpu_cc_cx_gfx3d_clk */ + 0x1B, /* gpu_cc_cx_gfx3d_slv_clk */ + 0x19, /* gpu_cc_cx_gmu_clk */ + 0x13, /* gpu_cc_cx_qdss_at_clk */ + 0x18, /* gpu_cc_cx_qdss_trig_clk */ + 0x14, /* gpu_cc_cx_qdss_tsctr_clk */ + 0x16, /* gpu_cc_cx_snoc_dvm_clk */ + 0xB, /* gpu_cc_cxo_aon_clk */ + 0xA, /* gpu_cc_cxo_clk */ + 0xC, /* gpu_cc_gx_gfx3d_clk */ + 0x10, /* gpu_cc_gx_gmu_clk */ + 0xE, /* gpu_cc_gx_qdss_tsctr_clk */ + 0xD, /* gpu_cc_gx_vsense_clk */ + 0x1D, /* gpu_cc_rbcpr_ahb_clk */ + 0x1C, /* gpu_cc_rbcpr_clk */ + 0x17, /* gpu_cc_sleep_clk */ +}; + +static struct clk_debug_mux gpu_cc_debug_mux = { + .priv = &debug_mux_priv, + .debug_offset = 0x1568, + .post_div_offset = 0x10FC, + .cbcr_offset = 0x1100, + .src_sel_mask = 0xFF, + .src_sel_shift = 0, + .post_div_mask = 0x3, + .post_div_shift = 0, + .post_div_val = 1, + .mux_sels = gpu_cc_debug_mux_sels, + .num_mux_sels = ARRAY_SIZE(gpu_cc_debug_mux_sels), + .hw.init = &(const struct clk_init_data){ + .name = "gpu_cc_debug_mux", + .ops = &clk_debug_mux_ops, + .parent_names = gpu_cc_debug_mux_parent_names, + .num_parents = ARRAY_SIZE(gpu_cc_debug_mux_parent_names), + }, +}; + +static const char *const video_cc_debug_mux_parent_names[] = { + "video_cc_apb_clk", + "video_cc_at_clk", + "video_cc_qdss_trig_clk", + "video_cc_qdss_tsctr_div8_clk", + "video_cc_vcodec0_axi_clk", + "video_cc_vcodec0_core_clk", + "video_cc_vcodec1_axi_clk", + "video_cc_vcodec1_core_clk", + "video_cc_venus_ahb_clk", + "video_cc_venus_ctl_axi_clk", + "video_cc_venus_ctl_core_clk", +}; + +static int video_cc_debug_mux_sels[] = { + 0x8, /* video_cc_apb_clk */ + 0xB, /* video_cc_at_clk */ + 0x7, /* video_cc_qdss_trig_clk */ + 0xA, /* video_cc_qdss_tsctr_div8_clk */ + 0x5, /* video_cc_vcodec0_axi_clk */ + 0x2, /* video_cc_vcodec0_core_clk */ + 0x6, /* video_cc_vcodec1_axi_clk */ + 0x3, /* video_cc_vcodec1_core_clk */ + 0x9, /* video_cc_venus_ahb_clk */ + 0x4, /* video_cc_venus_ctl_axi_clk */ + 0x1, /* video_cc_venus_ctl_core_clk */ +}; + +static struct clk_debug_mux video_cc_debug_mux = { + .priv = &debug_mux_priv, + .debug_offset = 0xA4C, + .post_div_offset = 0xA50, + .cbcr_offset = 0xA58, + .src_sel_mask = 0x3F, + .src_sel_shift = 0, + .post_div_mask = 0x7, + .post_div_shift = 0, + .post_div_val = 1, + .mux_sels = video_cc_debug_mux_sels, + .num_mux_sels = ARRAY_SIZE(video_cc_debug_mux_sels), + .hw.init = &(const struct clk_init_data){ + .name = "video_cc_debug_mux", + .ops = &clk_debug_mux_ops, + .parent_names = video_cc_debug_mux_parent_names, + .num_parents = ARRAY_SIZE(video_cc_debug_mux_parent_names), + }, +}; + +static struct mux_regmap_names mux_list[] = { + { .mux = &video_cc_debug_mux, .regmap_name = "qcom,videocc" }, + { .mux = &gpu_cc_debug_mux, .regmap_name = "qcom,gpucc" }, + { .mux = &disp_cc_debug_mux, .regmap_name = "qcom,dispcc" }, + { .mux = &cam_cc_debug_mux, .regmap_name = "qcom,camcc" }, + { .mux = &apss_cc_debug_mux, .regmap_name = "qcom,cpucc" }, + { .mux = &gcc_debug_mux, .regmap_name = "qcom,gcc" }, +}; + +static struct clk_dummy measure_only_perfcl_clk = { + .rrate = 1000, + .hw.init = &(const struct clk_init_data){ + .name = "measure_only_perfcl_clk", + .ops = &clk_dummy_ops, + }, +}; + +static struct clk_dummy measure_only_l3_clk = { + .rrate = 1000, + .hw.init = &(const struct clk_init_data){ + .name = "measure_only_l3_clk", + .ops = &clk_dummy_ops, + }, +}; + +static struct clk_dummy measure_only_pwrcl_clk = { + .rrate = 1000, + .hw.init = &(const struct clk_init_data){ + .name = "measure_only_pwrcl_clk", + .ops = &clk_dummy_ops, + }, +}; + +static struct clk_dummy measure_only_snoc_clk = { + .rrate = 1000, + .hw.init = &(struct clk_init_data){ + .name = "measure_only_snoc_clk", + .ops = &clk_dummy_ops, + }, +}; + +static struct clk_dummy measure_only_cnoc_clk = { + .rrate = 1000, + .hw.init = &(struct clk_init_data){ + .name = "measure_only_cnoc_clk", + .ops = &clk_dummy_ops, + }, +}; + +static struct clk_dummy measure_only_bimc_clk = { + .rrate = 1000, + .hw.init = &(struct clk_init_data){ + .name = "measure_only_bimc_clk", + .ops = &clk_dummy_ops, + }, +}; + +static struct clk_dummy measure_only_ipa_2x_clk = { + .rrate = 1000, + .hw.init = &(struct clk_init_data){ + .name = "measure_only_ipa_2x_clk", + .ops = &clk_dummy_ops, + }, +}; + +static struct clk_hw *debugcc_sdm845_hws[] = { + &measure_only_perfcl_clk.hw, + &measure_only_l3_clk.hw, + &measure_only_pwrcl_clk.hw, + &measure_only_snoc_clk.hw, + &measure_only_cnoc_clk.hw, + &measure_only_bimc_clk.hw, + &measure_only_ipa_2x_clk.hw, + + +}; + +static const struct of_device_id clk_debug_match_table[] = { + { .compatible = "qcom,sdm845-debugcc" }, + { } +}; + +static int clk_debug_sdm845_probe(struct platform_device *pdev) +{ + struct clk *clk; + int ret = 0, i; + + BUILD_BUG_ON(ARRAY_SIZE(apss_cc_debug_mux_parent_names) != + ARRAY_SIZE(apss_cc_debug_mux_sels)); + BUILD_BUG_ON(ARRAY_SIZE(cam_cc_debug_mux_parent_names) != + ARRAY_SIZE(cam_cc_debug_mux_sels)); + BUILD_BUG_ON(ARRAY_SIZE(disp_cc_debug_mux_parent_names) != + ARRAY_SIZE(disp_cc_debug_mux_sels)); + BUILD_BUG_ON(ARRAY_SIZE(gcc_debug_mux_parent_names) != ARRAY_SIZE(gcc_debug_mux_sels)); + BUILD_BUG_ON(ARRAY_SIZE(gpu_cc_debug_mux_parent_names) != + ARRAY_SIZE(gpu_cc_debug_mux_sels)); + BUILD_BUG_ON(ARRAY_SIZE(video_cc_debug_mux_parent_names) != + ARRAY_SIZE(video_cc_debug_mux_sels)); + + clk = devm_clk_get(&pdev->dev, "xo_clk_src"); + if (IS_ERR(clk)) { + if (PTR_ERR(clk) != -EPROBE_DEFER) + dev_err(&pdev->dev, "Unable to get xo clock\n"); + return PTR_ERR(clk); + } + + debug_mux_priv.cxo = clk; + + for (i = 0; i < ARRAY_SIZE(mux_list); i++) { + if (IS_ERR_OR_NULL(mux_list[i].mux->regmap)) { + ret = map_debug_bases(pdev, mux_list[i].regmap_name, + mux_list[i].mux); + if (ret == -EBADR) + continue; + else if (ret) + return ret; + } + } + + for (i = 0; i < ARRAY_SIZE(debugcc_sdm845_hws); i++) { + clk = devm_clk_register(&pdev->dev, debugcc_sdm845_hws[i]); + if (IS_ERR(clk)) { + dev_err(&pdev->dev, "Unable to register %s, err:(%d)\n", + clk_hw_get_name(debugcc_sdm845_hws[i]), + PTR_ERR(clk)); + return PTR_ERR(clk); + } + } + + for (i = 0; i < ARRAY_SIZE(mux_list); i++) { + ret = devm_clk_register_debug_mux(&pdev->dev, mux_list[i].mux); + if (ret) { + dev_err(&pdev->dev, "Unable to register mux clk %s, err:(%d)\n", + clk_hw_get_name(&mux_list[i].mux->hw), + ret); + return ret; + } + } + + ret = clk_debug_measure_register(&gcc_debug_mux.hw); + if (ret) { + dev_err(&pdev->dev, "Could not register Measure clocks\n"); + return ret; + } + + dev_info(&pdev->dev, "Registered debug measure clocks\n"); + + return ret; +} + +static struct platform_driver clk_debug_driver = { + .probe = clk_debug_sdm845_probe, + .driver = { + .name = "sdm845-debugcc", + .of_match_table = clk_debug_match_table, + }, +}; + +static int __init clk_debug_sdm845_init(void) +{ + return platform_driver_register(&clk_debug_driver); +} +fs_initcall(clk_debug_sdm845_init); + +MODULE_DESCRIPTION("QTI DEBUG CC SDM845 Driver"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/clk/qcom/dispcc-sm8250.c b/drivers/clk/qcom/dispcc-sm8250.c index 8589c22db9c6..a5e82641ddb8 100644 --- a/drivers/clk/qcom/dispcc-sm8250.c +++ b/drivers/clk/qcom/dispcc-sm8250.c @@ -1729,6 +1729,9 @@ static int disp_cc_sm8250_probe(struct platform_device *pdev) if (IS_ERR(regmap)) return PTR_ERR(regmap); + ret = register_qcom_clks_pm(pdev, true, &disp_cc_sm8250_desc); + if (ret) + dev_err(&pdev->dev, "Failed to register for pm ops\n"); ret = disp_cc_sm8250_fixup(pdev, regmap); if (ret) @@ -1737,14 +1740,8 @@ static int disp_cc_sm8250_probe(struct platform_device *pdev) clk_lucid_pll_configure(&disp_cc_pll0, regmap, disp_cc_pll0.config); clk_lucid_pll_configure(&disp_cc_pll1, regmap, disp_cc_pll1.config); - /* Enable clock gating for MDP clocks */ - regmap_update_bits(regmap, 0x8000, 0x10, 0x10); - - /* - *Keep clocks always enabled - * disp_cc_xo_clk - */ - regmap_update_bits(regmap, 0x605c, BIT(0), BIT(0)); + /* Enabling always ON clocks */ + clk_restore_critical_clocks(&pdev->dev); ret = qcom_cc_really_probe(pdev, &disp_cc_sm8250_desc, regmap); if (ret) { @@ -1752,10 +1749,6 @@ static int disp_cc_sm8250_probe(struct platform_device *pdev) return ret; } - ret = register_qcom_clks_pm(pdev, false, &disp_cc_sm8250_desc); - if (ret) - dev_err(&pdev->dev, "Failed to register for pm ops\n"); - pm_runtime_put_sync(&pdev->dev); dev_info(&pdev->dev, "Registered DISP CC clocks\n"); diff --git a/drivers/clk/qcom/dispcc0-lemans.c b/drivers/clk/qcom/dispcc0-lemans.c index ada712b7cf37..485ebcd63251 100644 --- a/drivers/clk/qcom/dispcc0-lemans.c +++ b/drivers/clk/qcom/dispcc0-lemans.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2022, Qualcomm Innovation Center, Inc. All rights reserved. + * Copyright (c) 2022-2023, Qualcomm Innovation Center, Inc. All rights reserved. */ #include @@ -17,6 +17,7 @@ #include "clk-alpha-pll.h" #include "clk-branch.h" +#include "clk-pm.h" #include "clk-rcg.h" #include "clk-regmap.h" #include "clk-regmap-divider.h" @@ -1460,6 +1461,14 @@ static struct clk_branch mdss_0_disp_cc_sleep_clk = { }, }; +/* + * Keep the clocks always-ON + * MDSS_0_DISP_CC_XO_CLK. + */ +static struct critical_clk_offset critical_clk_list[] = { + { .offset = 0xc054, .mask = BIT(0) }, +}; + static struct clk_regmap *disp_cc_0_lemans_clocks[] = { [DISP_CC_MDSS_AHB1_CLK] = &mdss_0_disp_cc_mdss_ahb1_clk.clkr, [DISP_CC_MDSS_AHB_CLK] = &mdss_0_disp_cc_mdss_ahb_clk.clkr, @@ -1553,6 +1562,8 @@ static struct qcom_cc_desc disp_cc_0_lemans_desc = { .num_resets = ARRAY_SIZE(disp_cc_0_lemans_resets), .clk_regulators = disp_cc_0_lemans_regulators, .num_clk_regulators = ARRAY_SIZE(disp_cc_0_lemans_regulators), + .critical_clk_en = critical_clk_list, + .num_critical_clk = ARRAY_SIZE(critical_clk_list), }; static const struct of_device_id disp_cc_0_lemans_match_table[] = { @@ -1570,22 +1581,15 @@ static int disp_cc_0_lemans_probe(struct platform_device *pdev) if (IS_ERR(regmap)) return PTR_ERR(regmap); - ret = qcom_cc_runtime_init(pdev, &disp_cc_0_lemans_desc); + ret = register_qcom_clks_pm(pdev, true, &disp_cc_0_lemans_desc); if (ret) - return ret; - - ret = pm_runtime_get_sync(&pdev->dev); - if (ret) - return ret; + dev_err(&pdev->dev, "Failed register disp_cc_0_pm_rt_ops clocks\n"); clk_lucid_evo_pll_configure(&mdss_0_disp_cc_pll0, regmap, mdss_0_disp_cc_pll0.config); clk_lucid_evo_pll_configure(&mdss_0_disp_cc_pll1, regmap, mdss_0_disp_cc_pll1.config); - /* - * Keep the clocks always-ON - * MDSS_0_DISP_CC_XO_CLK. - */ - regmap_update_bits(regmap, 0xc054, BIT(0), BIT(0)); + /* Enabling always ON clocks */ + clk_restore_critical_clocks(&pdev->dev); ret = qcom_cc_really_probe(pdev, &disp_cc_0_lemans_desc, regmap); if (ret) { @@ -1604,19 +1608,12 @@ static void disp_cc_0_lemans_sync_state(struct device *dev) qcom_cc_sync_state(dev, &disp_cc_0_lemans_desc); } -static const struct dev_pm_ops disp_cc_0_lemans_pm_ops = { - SET_RUNTIME_PM_OPS(qcom_cc_runtime_suspend, qcom_cc_runtime_resume, NULL) - SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, - pm_runtime_force_resume) -}; - static struct platform_driver disp_cc_0_lemans_driver = { .probe = disp_cc_0_lemans_probe, .driver = { .name = "disp_cc_0-lemans", .of_match_table = disp_cc_0_lemans_match_table, .sync_state = disp_cc_0_lemans_sync_state, - .pm = &disp_cc_0_lemans_pm_ops, }, }; diff --git a/drivers/clk/qcom/dispcc1-lemans.c b/drivers/clk/qcom/dispcc1-lemans.c index 103695cf7a21..721f824533b6 100644 --- a/drivers/clk/qcom/dispcc1-lemans.c +++ b/drivers/clk/qcom/dispcc1-lemans.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2022, Qualcomm Innovation Center, Inc. All rights reserved. + * Copyright (c) 2022-2023, Qualcomm Innovation Center, Inc. All rights reserved. */ #include @@ -17,6 +17,7 @@ #include "clk-alpha-pll.h" #include "clk-branch.h" +#include "clk-pm.h" #include "clk-rcg.h" #include "clk-regmap.h" #include "clk-regmap-divider.h" @@ -1460,6 +1461,14 @@ static struct clk_branch mdss_1_disp_cc_sleep_clk = { }, }; +/* + * Keep the clocks always-ON + * MDSS_1_DISP_CC_XO_CLK. + */ +static struct critical_clk_offset critical_clk_list[] = { + { .offset = 0xc054, .mask = BIT(0) }, +}; + static struct clk_regmap *disp_cc_1_lemans_clocks[] = { [DISP_CC_MDSS_AHB1_CLK] = &mdss_1_disp_cc_mdss_ahb1_clk.clkr, [DISP_CC_MDSS_AHB_CLK] = &mdss_1_disp_cc_mdss_ahb_clk.clkr, @@ -1553,6 +1562,8 @@ static struct qcom_cc_desc disp_cc_1_lemans_desc = { .num_resets = ARRAY_SIZE(disp_cc_1_lemans_resets), .clk_regulators = disp_cc_1_lemans_regulators, .num_clk_regulators = ARRAY_SIZE(disp_cc_1_lemans_regulators), + .critical_clk_en = critical_clk_list, + .num_critical_clk = ARRAY_SIZE(critical_clk_list), }; static const struct of_device_id disp_cc_1_lemans_match_table[] = { @@ -1570,22 +1581,15 @@ static int disp_cc_1_lemans_probe(struct platform_device *pdev) if (IS_ERR(regmap)) return PTR_ERR(regmap); - ret = qcom_cc_runtime_init(pdev, &disp_cc_1_lemans_desc); + ret = register_qcom_clks_pm(pdev, true, &disp_cc_1_lemans_desc); if (ret) - return ret; - - ret = pm_runtime_get_sync(&pdev->dev); - if (ret) - return ret; + dev_err(&pdev->dev, "Failed register disp_cc_1_pm_rt_ops clocks\n"); clk_lucid_evo_pll_configure(&mdss_1_disp_cc_pll0, regmap, mdss_1_disp_cc_pll0.config); clk_lucid_evo_pll_configure(&mdss_1_disp_cc_pll1, regmap, mdss_1_disp_cc_pll1.config); - /* - * Keep the clocks always-ON - * MDSS_0_DISP_CC_XO_CLK. - */ - regmap_update_bits(regmap, 0xc054, BIT(0), BIT(0)); + /* Enabling always ON clocks */ + clk_restore_critical_clocks(&pdev->dev); ret = qcom_cc_really_probe(pdev, &disp_cc_1_lemans_desc, regmap); if (ret) { @@ -1604,19 +1608,12 @@ static void disp_cc_1_lemans_sync_state(struct device *dev) qcom_cc_sync_state(dev, &disp_cc_1_lemans_desc); } -static const struct dev_pm_ops disp_cc_1_lemans_pm_ops = { - SET_RUNTIME_PM_OPS(qcom_cc_runtime_suspend, qcom_cc_runtime_resume, NULL) - SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, - pm_runtime_force_resume) -}; - static struct platform_driver disp_cc_1_lemans_driver = { .probe = disp_cc_1_lemans_probe, .driver = { .name = "disp_cc_1-lemans", .of_match_table = disp_cc_1_lemans_match_table, .sync_state = disp_cc_1_lemans_sync_state, - .pm = &disp_cc_1_lemans_pm_ops, }, }; diff --git a/drivers/clk/qcom/gcc-ipq6018.c b/drivers/clk/qcom/gcc-ipq6018.c index 3f9c2f61a5d9..cde62a11f573 100644 --- a/drivers/clk/qcom/gcc-ipq6018.c +++ b/drivers/clk/qcom/gcc-ipq6018.c @@ -1654,7 +1654,7 @@ static struct clk_rcg2 sdcc1_apps_clk_src = { .name = "sdcc1_apps_clk_src", .parent_data = gcc_xo_gpll0_gpll2_gpll0_out_main_div2, .num_parents = 4, - .ops = &clk_rcg2_ops, + .ops = &clk_rcg2_floor_ops, }, }; @@ -4517,24 +4517,24 @@ static const struct qcom_reset_map gcc_ipq6018_resets[] = { [GCC_PCIE0_AHB_ARES] = { 0x75040, 5 }, [GCC_PCIE0_AXI_MASTER_STICKY_ARES] = { 0x75040, 6 }, [GCC_PCIE0_AXI_SLAVE_STICKY_ARES] = { 0x75040, 7 }, - [GCC_PPE_FULL_RESET] = { 0x68014, 0 }, - [GCC_UNIPHY0_SOFT_RESET] = { 0x56004, 0 }, + [GCC_PPE_FULL_RESET] = { .reg = 0x68014, .bitmask = 0xf0000 }, + [GCC_UNIPHY0_SOFT_RESET] = { .reg = 0x56004, .bitmask = 0x3ff2 }, [GCC_UNIPHY0_XPCS_RESET] = { 0x56004, 2 }, - [GCC_UNIPHY1_SOFT_RESET] = { 0x56104, 0 }, + [GCC_UNIPHY1_SOFT_RESET] = { .reg = 0x56104, .bitmask = 0x32 }, [GCC_UNIPHY1_XPCS_RESET] = { 0x56104, 2 }, - [GCC_EDMA_HW_RESET] = { 0x68014, 0 }, - [GCC_NSSPORT1_RESET] = { 0x68014, 0 }, - [GCC_NSSPORT2_RESET] = { 0x68014, 0 }, - [GCC_NSSPORT3_RESET] = { 0x68014, 0 }, - [GCC_NSSPORT4_RESET] = { 0x68014, 0 }, - [GCC_NSSPORT5_RESET] = { 0x68014, 0 }, - [GCC_UNIPHY0_PORT1_ARES] = { 0x56004, 0 }, - [GCC_UNIPHY0_PORT2_ARES] = { 0x56004, 0 }, - [GCC_UNIPHY0_PORT3_ARES] = { 0x56004, 0 }, - [GCC_UNIPHY0_PORT4_ARES] = { 0x56004, 0 }, - [GCC_UNIPHY0_PORT5_ARES] = { 0x56004, 0 }, - [GCC_UNIPHY0_PORT_4_5_RESET] = { 0x56004, 0 }, - [GCC_UNIPHY0_PORT_4_RESET] = { 0x56004, 0 }, + [GCC_EDMA_HW_RESET] = { .reg = 0x68014, .bitmask = 0x300000 }, + [GCC_NSSPORT1_RESET] = { .reg = 0x68014, .bitmask = 0x1000003 }, + [GCC_NSSPORT2_RESET] = { .reg = 0x68014, .bitmask = 0x200000c }, + [GCC_NSSPORT3_RESET] = { .reg = 0x68014, .bitmask = 0x4000030 }, + [GCC_NSSPORT4_RESET] = { .reg = 0x68014, .bitmask = 0x8000300 }, + [GCC_NSSPORT5_RESET] = { .reg = 0x68014, .bitmask = 0x10000c00 }, + [GCC_UNIPHY0_PORT1_ARES] = { .reg = 0x56004, .bitmask = 0x30 }, + [GCC_UNIPHY0_PORT2_ARES] = { .reg = 0x56004, .bitmask = 0xc0 }, + [GCC_UNIPHY0_PORT3_ARES] = { .reg = 0x56004, .bitmask = 0x300 }, + [GCC_UNIPHY0_PORT4_ARES] = { .reg = 0x56004, .bitmask = 0xc00 }, + [GCC_UNIPHY0_PORT5_ARES] = { .reg = 0x56004, .bitmask = 0x3000 }, + [GCC_UNIPHY0_PORT_4_5_RESET] = { .reg = 0x56004, .bitmask = 0x3c02 }, + [GCC_UNIPHY0_PORT_4_RESET] = { .reg = 0x56004, .bitmask = 0xc02 }, [GCC_LPASS_BCR] = {0x1F000, 0}, [GCC_UBI32_TBU_BCR] = {0x65000, 0}, [GCC_LPASS_TBU_BCR] = {0x6C000, 0}, diff --git a/drivers/clk/qcom/gcc-lemans.c b/drivers/clk/qcom/gcc-lemans.c index f798ddb2a3c9..9d10867b7058 100644 --- a/drivers/clk/qcom/gcc-lemans.c +++ b/drivers/clk/qcom/gcc-lemans.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2021, Qualcomm Innovation Center, Inc. All rights reserved. + * Copyright (c) 2021, 2023, Qualcomm Innovation Center, Inc. All rights reserved. */ #include @@ -16,6 +16,7 @@ #include "clk-alpha-pll.h" #include "clk-branch.h" +#include "clk-pm.h" #include "clk-rcg.h" #include "clk-regmap.h" #include "clk-regmap-divider.h" @@ -4846,6 +4847,24 @@ static struct clk_branch gcc_video_axi1_clk = { }, }; +/* + * Keep the clocks always-ON + * GCC_CAMERA_AHB_CLK, GCC_CAMERA_XO_CLK, GCC_DISP1_AHB_CLK, + * GCC_DISP1_XO_CLK, GCC_DISP_AHB_CLK, GCC_DISP_XO_CLK, + * GCC_GPU_CFG_AHB_CLK, GCC_VIDEO_AHB_CLK, GCC_VIDEO_XO_CLK. + */ +static struct critical_clk_offset critical_clk_list[] = { + { .offset = 0x32004, .mask = BIT(0) }, + { .offset = 0x32020, .mask = BIT(0) }, + { .offset = 0xc7004, .mask = BIT(0) }, + { .offset = 0xc7018, .mask = BIT(0) }, + { .offset = 0x33004, .mask = BIT(0) }, + { .offset = 0x33018, .mask = BIT(0) }, + { .offset = 0x7d004, .mask = BIT(0) }, + { .offset = 0x34004, .mask = BIT(0) }, + { .offset = 0x34024, .mask = BIT(0) }, +}; + static struct clk_regmap *gcc_lemans_clocks[] = { [GCC_AGGRE_NOC_QUPV3_AXI_CLK] = &gcc_aggre_noc_qupv3_axi_clk.clkr, [GCC_AGGRE_UFS_CARD_AXI_CLK] = &gcc_aggre_ufs_card_axi_clk.clkr, @@ -5160,7 +5179,7 @@ static const struct regmap_config gcc_lemans_regmap_config = { .fast_io = true, }; -static const struct qcom_cc_desc gcc_lemans_desc = { +static struct qcom_cc_desc gcc_lemans_desc = { .config = &gcc_lemans_regmap_config, .clks = gcc_lemans_clocks, .num_clks = ARRAY_SIZE(gcc_lemans_clocks), @@ -5168,6 +5187,8 @@ static const struct qcom_cc_desc gcc_lemans_desc = { .num_resets = ARRAY_SIZE(gcc_lemans_resets), .clk_regulators = gcc_lemans_regulators, .num_clk_regulators = ARRAY_SIZE(gcc_lemans_regulators), + .critical_clk_en = critical_clk_list, + .num_critical_clk = ARRAY_SIZE(critical_clk_list), }; static const struct of_device_id gcc_lemans_match_table[] = { @@ -5186,26 +5207,17 @@ static int gcc_lemans_probe(struct platform_device *pdev) return PTR_ERR(regmap); + ret = register_qcom_clks_pm(pdev, false, &gcc_lemans_desc); + if (ret) + dev_err(&pdev->dev, "Failed register gcc_pm_ops clocks\n"); + ret = qcom_cc_register_rcg_dfs(regmap, gcc_dfs_clocks, ARRAY_SIZE(gcc_dfs_clocks)); if (ret) return ret; - /* - * Keep the clocks always-ON - * GCC_CAMERA_AHB_CLK, GCC_CAMERA_XO_CLK, GCC_DISP1_AHB_CLK, - * GCC_DISP1_XO_CLK, GCC_DISP_AHB_CLK, GCC_DISP_XO_CLK, - * GCC_GPU_CFG_AHB_CLK, GCC_VIDEO_AHB_CLK, GCC_VIDEO_XO_CLK. - */ - regmap_update_bits(regmap, 0x32004, BIT(0), BIT(0)); - regmap_update_bits(regmap, 0x32020, BIT(0), BIT(0)); - regmap_update_bits(regmap, 0xc7004, BIT(0), BIT(0)); - regmap_update_bits(regmap, 0xc7018, BIT(0), BIT(0)); - regmap_update_bits(regmap, 0x33004, BIT(0), BIT(0)); - regmap_update_bits(regmap, 0x33018, BIT(0), BIT(0)); - regmap_update_bits(regmap, 0x7d004, BIT(0), BIT(0)); - regmap_update_bits(regmap, 0x34004, BIT(0), BIT(0)); - regmap_update_bits(regmap, 0x34024, BIT(0), BIT(0)); + /* Enabling always ON clocks */ + clk_restore_critical_clocks(&pdev->dev); ret = qcom_cc_really_probe(pdev, &gcc_lemans_desc, regmap); if (ret) { diff --git a/drivers/clk/qcom/gcc-qcs404.c b/drivers/clk/qcom/gcc-qcs404.c index c49f74b9d147..422c2884e017 100644 --- a/drivers/clk/qcom/gcc-qcs404.c +++ b/drivers/clk/qcom/gcc-qcs404.c @@ -95,7 +95,7 @@ static struct clk_alpha_pll gpll0_ao_out_main = { .hw.init = &(struct clk_init_data){ .name = "gpll0_ao_out_main", .parent_data = &(const struct clk_parent_data){ - .fw_name = "bi_tcxo", + .fw_name = "bi_tcxo_ao", }, .num_parents = 1, .ops = &clk_alpha_pll_ops, @@ -230,7 +230,7 @@ static const struct clk_parent_data gcc_parent_data_0[] = { }; static const struct clk_parent_data gcc_parent_data_ao_0[] = { - { .fw_name = "bi_tcxo" }, + { .fw_name = "bi_tcxo_ao" }, { .hw = &gpll0_ao_out_main.clkr.hw }, }; @@ -3037,11 +3037,17 @@ static int gcc_qcs404_probe(struct platform_device *pdev) return ret; } +static void gcc_qcs404_sync_state(struct device *dev) +{ + qcom_cc_sync_state(dev, &gcc_qcs404_desc); +} + static struct platform_driver gcc_qcs404_driver = { .probe = gcc_qcs404_probe, .driver = { .name = "gcc-qcs404", .of_match_table = gcc_qcs404_match_table, + .sync_state = gcc_qcs404_sync_state, }, }; diff --git a/drivers/clk/qcom/gdsc-regulator.c b/drivers/clk/qcom/gdsc-regulator.c index 17fb94630586..5c4b0e20d9b5 100644 --- a/drivers/clk/qcom/gdsc-regulator.c +++ b/drivers/clk/qcom/gdsc-regulator.c @@ -1004,6 +1004,15 @@ static int restore_hw_trig_clk_dis(struct device *dev) { struct gdsc *sc = dev_get_drvdata(dev); uint32_t regval; + int ret; + + if (sc->rdev->supply) { + ret = regulator_enable(sc->rdev->supply); + if (ret) { + dev_err(&sc->rdev->dev, "reg enable failed\n"); + return ret; + } + } regmap_read(sc->regmap, REG_OFFSET, ®val); if (sc->is_gdsc_hw_ctrl_mode) @@ -1014,7 +1023,12 @@ static int restore_hw_trig_clk_dis(struct device *dev) regval |= sc->clk_dis_wait_val; } - return regmap_write(sc->regmap, REG_OFFSET, regval); + ret = regmap_write(sc->regmap, REG_OFFSET, regval); + + if (sc->rdev->supply) + regulator_disable(sc->rdev->supply); + + return ret; } static int gdsc_pm_resume_early(struct device *dev) diff --git a/drivers/clk/qcom/gpucc-lemans.c b/drivers/clk/qcom/gpucc-lemans.c index 1d512a2ce096..e6c72d53d138 100644 --- a/drivers/clk/qcom/gpucc-lemans.c +++ b/drivers/clk/qcom/gpucc-lemans.c @@ -16,6 +16,7 @@ #include "clk-alpha-pll.h" #include "clk-branch.h" +#include "clk-pm.h" #include "clk-rcg.h" #include "clk-regmap.h" #include "clk-regmap-divider.h" @@ -576,6 +577,14 @@ static struct clk_branch gpu_cc_sleep_clk = { }, }; +/* + * Keep the clocks always-ON + * GPU_CC_CB_CLK + */ +static struct critical_clk_offset critical_clk_list[] = { + { .offset = 0x93a4, .mask = BIT(0) }, +}; + static struct clk_regmap *gpu_cc_lemans_clocks[] = { [GPU_CC_AHB_CLK] = &gpu_cc_ahb_clk.clkr, [GPU_CC_CRC_AHB_CLK] = &gpu_cc_crc_ahb_clk.clkr, @@ -611,12 +620,14 @@ static const struct regmap_config gpu_cc_lemans_regmap_config = { .fast_io = true, }; -static const struct qcom_cc_desc gpu_cc_lemans_desc = { +static struct qcom_cc_desc gpu_cc_lemans_desc = { .config = &gpu_cc_lemans_regmap_config, .clks = gpu_cc_lemans_clocks, .num_clks = ARRAY_SIZE(gpu_cc_lemans_clocks), .clk_regulators = gpu_cc_lemans_regulators, .num_clk_regulators = ARRAY_SIZE(gpu_cc_lemans_regulators), + .critical_clk_en = critical_clk_list, + .num_critical_clk = ARRAY_SIZE(critical_clk_list), }; static const struct of_device_id gpu_cc_lemans_match_table[] = { @@ -654,11 +665,12 @@ static int gpu_cc_lemans_probe(struct platform_device *pdev) clk_lucid_evo_pll_configure(&gpu_cc_pll0, regmap, gpu_cc_pll0.config); clk_lucid_evo_pll_configure(&gpu_cc_pll1, regmap, gpu_cc_pll1.config); - /* - * Keep the clocks always-ON - * GPU_CC_CB_CLK - */ - regmap_update_bits(regmap, 0x93a4, BIT(0), BIT(0)); + ret = register_qcom_clks_pm(pdev, false, &gpu_cc_lemans_desc); + if (ret) + dev_err(&pdev->dev, "Failed register gpu_cc_pm_rt_ops clocks\n"); + + /* Enabling always ON clocks */ + clk_restore_critical_clocks(&pdev->dev); ret = qcom_cc_really_probe(pdev, &gpu_cc_lemans_desc, regmap); if (ret) { diff --git a/drivers/clk/qcom/reset.c b/drivers/clk/qcom/reset.c index 819d194be8f7..0e914ec7aeae 100644 --- a/drivers/clk/qcom/reset.c +++ b/drivers/clk/qcom/reset.c @@ -13,8 +13,10 @@ static int qcom_reset(struct reset_controller_dev *rcdev, unsigned long id) { + struct qcom_reset_controller *rst = to_qcom_reset_controller(rcdev); + rcdev->ops->assert(rcdev, id); - udelay(1); + udelay(rst->reset_map[id].udelay ?: 1); /* use 1 us as default */ rcdev->ops->deassert(rcdev, id); return 0; } @@ -28,7 +30,7 @@ qcom_reset_assert(struct reset_controller_dev *rcdev, unsigned long id) rst = to_qcom_reset_controller(rcdev); map = &rst->reset_map[id]; - mask = BIT(map->bit); + mask = map->bitmask ? map->bitmask : BIT(map->bit); return regmap_update_bits(rst->regmap, map->reg, mask, mask); } @@ -42,7 +44,7 @@ qcom_reset_deassert(struct reset_controller_dev *rcdev, unsigned long id) rst = to_qcom_reset_controller(rcdev); map = &rst->reset_map[id]; - mask = BIT(map->bit); + mask = map->bitmask ? map->bitmask : BIT(map->bit); return regmap_update_bits(rst->regmap, map->reg, mask, 0); } diff --git a/drivers/clk/qcom/reset.h b/drivers/clk/qcom/reset.h index 2a08b5e282c7..9a47c838d9b1 100644 --- a/drivers/clk/qcom/reset.h +++ b/drivers/clk/qcom/reset.h @@ -11,6 +11,8 @@ struct qcom_reset_map { unsigned int reg; u8 bit; + u8 udelay; + u32 bitmask; }; struct regmap; diff --git a/drivers/clk/qcom/videocc-lemans.c b/drivers/clk/qcom/videocc-lemans.c index 0e2e0176800f..1f563c4335d6 100644 --- a/drivers/clk/qcom/videocc-lemans.c +++ b/drivers/clk/qcom/videocc-lemans.c @@ -17,6 +17,7 @@ #include "clk-alpha-pll.h" #include "clk-branch.h" +#include "clk-pm.h" #include "clk-rcg.h" #include "clk-regmap.h" #include "clk-regmap-divider.h" @@ -443,6 +444,16 @@ static struct clk_branch video_cc_sleep_clk = { }, }; +/* + * Keep clocks always enabled: + * video_cc_ahb_clk + * video_cc_xo_clk + */ +static struct critical_clk_offset critical_clk_list[] = { + { .offset = 0x80ec, .mask = BIT(0) }, + { .offset = 0x8128, .mask = BIT(0) }, +}; + static struct clk_regmap *video_cc_lemans_clocks[] = { [VIDEO_CC_AHB_CLK_SRC] = &video_cc_ahb_clk_src.clkr, [VIDEO_CC_MVS0_CLK] = &video_cc_mvs0_clk.clkr, @@ -488,6 +499,8 @@ static struct qcom_cc_desc video_cc_lemans_desc = { .num_resets = ARRAY_SIZE(video_cc_lemans_resets), .clk_regulators = video_cc_lemans_regulators, .num_clk_regulators = ARRAY_SIZE(video_cc_lemans_regulators), + .critical_clk_en = critical_clk_list, + .num_critical_clk = ARRAY_SIZE(critical_clk_list), }; static const struct of_device_id video_cc_lemans_match_table[] = { @@ -505,24 +518,15 @@ static int video_cc_lemans_probe(struct platform_device *pdev) if (IS_ERR(regmap)) return PTR_ERR(regmap); - ret = qcom_cc_runtime_init(pdev, &video_cc_lemans_desc); + ret = register_qcom_clks_pm(pdev, true, &video_cc_lemans_desc); if (ret) - return ret; - - ret = pm_runtime_get_sync(&pdev->dev); - if (ret) - return ret; + dev_err(&pdev->dev, "Failed register video_cc_pm_rt_ops clocks\n"); clk_lucid_evo_pll_configure(&video_pll0, regmap, video_pll0.config); clk_lucid_evo_pll_configure(&video_pll1, regmap, video_pll1.config); - /* - * Keep clocks always enabled: - * video_cc_ahb_clk - * video_cc_xo_clk - */ - regmap_update_bits(regmap, 0x80ec, BIT(0), BIT(0)); - regmap_update_bits(regmap, 0x8128, BIT(0), BIT(0)); + /* Enabling always ON clocks */ + clk_restore_critical_clocks(&pdev->dev); ret = qcom_cc_really_probe(pdev, &video_cc_lemans_desc, regmap); if (ret) { @@ -541,19 +545,12 @@ static void video_cc_lemans_sync_state(struct device *dev) qcom_cc_sync_state(dev, &video_cc_lemans_desc); } -static const struct dev_pm_ops video_cc_lemans_pm_ops = { - SET_RUNTIME_PM_OPS(qcom_cc_runtime_suspend, qcom_cc_runtime_resume, NULL) - SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, - pm_runtime_force_resume) -}; - static struct platform_driver video_cc_lemans_driver = { .probe = video_cc_lemans_probe, .driver = { .name = "video_cc-lemans", .of_match_table = video_cc_lemans_match_table, .sync_state = video_cc_lemans_sync_state, - .pm = &video_cc_lemans_pm_ops, }, }; diff --git a/drivers/clk/tegra/clk-tegra124-emc.c b/drivers/clk/tegra/clk-tegra124-emc.c index 219c80653dbd..2a6db0434281 100644 --- a/drivers/clk/tegra/clk-tegra124-emc.c +++ b/drivers/clk/tegra/clk-tegra124-emc.c @@ -464,6 +464,7 @@ static int load_timings_from_dt(struct tegra_clk_emc *tegra, err = load_one_timing_from_dt(tegra, timing, child); if (err) { of_node_put(child); + kfree(tegra->timings); return err; } @@ -515,6 +516,7 @@ struct clk *tegra124_clk_register_emc(void __iomem *base, struct device_node *np err = load_timings_from_dt(tegra, node, node_ram_code); if (err) { of_node_put(node); + kfree(tegra); return ERR_PTR(err); } } diff --git a/drivers/clk/ti/clkctrl.c b/drivers/clk/ti/clkctrl.c index 864c484bde1b..157abc46dcf4 100644 --- a/drivers/clk/ti/clkctrl.c +++ b/drivers/clk/ti/clkctrl.c @@ -267,6 +267,9 @@ static const char * __init clkctrl_get_clock_name(struct device_node *np, if (clkctrl_name && !legacy_naming) { clock_name = kasprintf(GFP_KERNEL, "%s-clkctrl:%04x:%d", clkctrl_name, offset, index); + if (!clock_name) + return NULL; + strreplace(clock_name, '_', '-'); return clock_name; @@ -598,6 +601,10 @@ static void __init _ti_omap4_clkctrl_setup(struct device_node *node) if (clkctrl_name) { provider->clkdm_name = kasprintf(GFP_KERNEL, "%s_clkdm", clkctrl_name); + if (!provider->clkdm_name) { + kfree(provider); + return; + } goto clkdm_found; } diff --git a/drivers/clocksource/timer-cadence-ttc.c b/drivers/clocksource/timer-cadence-ttc.c index 4efd0cf3b602..0d52e28fea4d 100644 --- a/drivers/clocksource/timer-cadence-ttc.c +++ b/drivers/clocksource/timer-cadence-ttc.c @@ -486,10 +486,10 @@ static int __init ttc_timer_probe(struct platform_device *pdev) * and use it. Note that the event timer uses the interrupt and it's the * 2nd TTC hence the irq_of_parse_and_map(,1) */ - timer_baseaddr = of_iomap(timer, 0); - if (!timer_baseaddr) { + timer_baseaddr = devm_of_iomap(&pdev->dev, timer, 0, NULL); + if (IS_ERR(timer_baseaddr)) { pr_err("ERROR: invalid timer base address\n"); - return -ENXIO; + return PTR_ERR(timer_baseaddr); } irq = irq_of_parse_and_map(timer, 1); @@ -513,20 +513,27 @@ static int __init ttc_timer_probe(struct platform_device *pdev) clk_ce = of_clk_get(timer, clksel); if (IS_ERR(clk_ce)) { pr_err("ERROR: timer input clock not found\n"); - return PTR_ERR(clk_ce); + ret = PTR_ERR(clk_ce); + goto put_clk_cs; } ret = ttc_setup_clocksource(clk_cs, timer_baseaddr, timer_width); if (ret) - return ret; + goto put_clk_ce; ret = ttc_setup_clockevent(clk_ce, timer_baseaddr + 4, irq); if (ret) - return ret; + goto put_clk_ce; pr_info("%pOFn #0 at %p, irq=%d\n", timer, timer_baseaddr, irq); return 0; + +put_clk_ce: + clk_put(clk_ce); +put_clk_cs: + clk_put(clk_cs); + return ret; } static const struct of_device_id ttc_timer_of_match[] = { diff --git a/drivers/cpufreq/intel_pstate.c b/drivers/cpufreq/intel_pstate.c index eee74a2fe317..2f5063db2f1f 100644 --- a/drivers/cpufreq/intel_pstate.c +++ b/drivers/cpufreq/intel_pstate.c @@ -824,6 +824,8 @@ static ssize_t store_energy_performance_preference( err = cpufreq_start_governor(policy); if (!ret) ret = err; + } else { + ret = 0; } } diff --git a/drivers/crypto/marvell/cesa/cipher.c b/drivers/crypto/marvell/cesa/cipher.c index c6f2fa753b7c..0f37dfd42d85 100644 --- a/drivers/crypto/marvell/cesa/cipher.c +++ b/drivers/crypto/marvell/cesa/cipher.c @@ -297,7 +297,7 @@ static int mv_cesa_des_setkey(struct crypto_skcipher *cipher, const u8 *key, static int mv_cesa_des3_ede_setkey(struct crypto_skcipher *cipher, const u8 *key, unsigned int len) { - struct mv_cesa_des_ctx *ctx = crypto_skcipher_ctx(cipher); + struct mv_cesa_des3_ctx *ctx = crypto_skcipher_ctx(cipher); int err; err = verify_skcipher_des3_key(cipher, key); diff --git a/drivers/crypto/nx/Makefile b/drivers/crypto/nx/Makefile index d00181a26dd6..483cef62acee 100644 --- a/drivers/crypto/nx/Makefile +++ b/drivers/crypto/nx/Makefile @@ -1,7 +1,6 @@ # SPDX-License-Identifier: GPL-2.0 obj-$(CONFIG_CRYPTO_DEV_NX_ENCRYPT) += nx-crypto.o nx-crypto-objs := nx.o \ - nx_debugfs.o \ nx-aes-cbc.o \ nx-aes-ecb.o \ nx-aes-gcm.o \ @@ -11,6 +10,7 @@ nx-crypto-objs := nx.o \ nx-sha256.o \ nx-sha512.o +nx-crypto-$(CONFIG_DEBUG_FS) += nx_debugfs.o obj-$(CONFIG_CRYPTO_DEV_NX_COMPRESS_PSERIES) += nx-compress-pseries.o nx-compress.o obj-$(CONFIG_CRYPTO_DEV_NX_COMPRESS_POWERNV) += nx-compress-powernv.o nx-compress.o nx-compress-objs := nx-842.o diff --git a/drivers/crypto/nx/nx.h b/drivers/crypto/nx/nx.h index c6233173c612..2697baebb6a3 100644 --- a/drivers/crypto/nx/nx.h +++ b/drivers/crypto/nx/nx.h @@ -170,8 +170,8 @@ struct nx_sg *nx_walk_and_build(struct nx_sg *, unsigned int, void nx_debugfs_init(struct nx_crypto_driver *); void nx_debugfs_fini(struct nx_crypto_driver *); #else -#define NX_DEBUGFS_INIT(drv) (0) -#define NX_DEBUGFS_FINI(drv) (0) +#define NX_DEBUGFS_INIT(drv) do {} while (0) +#define NX_DEBUGFS_FINI(drv) do {} while (0) #endif #define NX_PAGE_NUM(x) ((u64)(x) & 0xfffffffffffff000ULL) diff --git a/drivers/crypto/qat/qat_common/adf_common_drv.h b/drivers/crypto/qat/qat_common/adf_common_drv.h index 4261749fae8d..75693ca4afea 100644 --- a/drivers/crypto/qat/qat_common/adf_common_drv.h +++ b/drivers/crypto/qat/qat_common/adf_common_drv.h @@ -49,11 +49,6 @@ struct service_hndl { struct list_head list; }; -static inline int get_current_node(void) -{ - return topology_physical_package_id(raw_smp_processor_id()); -} - int adf_service_register(struct service_hndl *service); int adf_service_unregister(struct service_hndl *service); diff --git a/drivers/crypto/qat/qat_common/qat_algs.c b/drivers/crypto/qat/qat_common/qat_algs.c index 906082fbdd67..f56ee4cc5ae8 100644 --- a/drivers/crypto/qat/qat_common/qat_algs.c +++ b/drivers/crypto/qat/qat_common/qat_algs.c @@ -605,7 +605,7 @@ static int qat_alg_aead_newkey(struct crypto_aead *tfm, const u8 *key, { struct qat_alg_aead_ctx *ctx = crypto_aead_ctx(tfm); struct qat_crypto_instance *inst = NULL; - int node = get_current_node(); + int node = numa_node_id(); struct device *dev; int ret; @@ -706,7 +706,8 @@ static void qat_alg_free_bufl(struct qat_crypto_instance *inst, static int qat_alg_sgl_to_bufl(struct qat_crypto_instance *inst, struct scatterlist *sgl, struct scatterlist *sglout, - struct qat_crypto_request *qat_req) + struct qat_crypto_request *qat_req, + gfp_t flags) { struct device *dev = &GET_DEV(inst->accel_dev); int i, sg_nctr = 0; @@ -727,7 +728,7 @@ static int qat_alg_sgl_to_bufl(struct qat_crypto_instance *inst, qat_req->buf.sgl_dst_valid = false; if (n > QAT_MAX_BUFF_DESC) { - bufl = kzalloc_node(sz, GFP_ATOMIC, node); + bufl = kzalloc_node(sz, flags, node); if (unlikely(!bufl)) return -ENOMEM; } else { @@ -771,7 +772,7 @@ static int qat_alg_sgl_to_bufl(struct qat_crypto_instance *inst, sg_nctr = 0; if (n > QAT_MAX_BUFF_DESC) { - buflout = kzalloc_node(sz_out, GFP_ATOMIC, node); + buflout = kzalloc_node(sz_out, flags, node); if (unlikely(!buflout)) goto err_in; } else { @@ -972,6 +973,7 @@ static int qat_alg_aead_dec(struct aead_request *areq) struct icp_qat_fw_la_auth_req_params *auth_param; struct icp_qat_fw_la_bulk_req *msg; int digst_size = crypto_aead_authsize(aead_tfm); + gfp_t f = qat_algs_alloc_flags(&areq->base); int ret; u32 cipher_len; @@ -979,7 +981,7 @@ static int qat_alg_aead_dec(struct aead_request *areq) if (cipher_len % AES_BLOCK_SIZE != 0) return -EINVAL; - ret = qat_alg_sgl_to_bufl(ctx->inst, areq->src, areq->dst, qat_req); + ret = qat_alg_sgl_to_bufl(ctx->inst, areq->src, areq->dst, qat_req, f); if (unlikely(ret)) return ret; @@ -1014,6 +1016,7 @@ static int qat_alg_aead_enc(struct aead_request *areq) struct qat_crypto_request *qat_req = aead_request_ctx(areq); struct icp_qat_fw_la_cipher_req_params *cipher_param; struct icp_qat_fw_la_auth_req_params *auth_param; + gfp_t f = qat_algs_alloc_flags(&areq->base); struct icp_qat_fw_la_bulk_req *msg; u8 *iv = areq->iv; int ret; @@ -1021,7 +1024,7 @@ static int qat_alg_aead_enc(struct aead_request *areq) if (areq->cryptlen % AES_BLOCK_SIZE != 0) return -EINVAL; - ret = qat_alg_sgl_to_bufl(ctx->inst, areq->src, areq->dst, qat_req); + ret = qat_alg_sgl_to_bufl(ctx->inst, areq->src, areq->dst, qat_req, f); if (unlikely(ret)) return ret; @@ -1068,7 +1071,7 @@ static int qat_alg_skcipher_newkey(struct qat_alg_skcipher_ctx *ctx, { struct qat_crypto_instance *inst = NULL; struct device *dev; - int node = get_current_node(); + int node = numa_node_id(); int ret; inst = qat_crypto_get_instance_node(node); @@ -1199,13 +1202,14 @@ static int qat_alg_skcipher_encrypt(struct skcipher_request *req) struct qat_alg_skcipher_ctx *ctx = crypto_tfm_ctx(tfm); struct qat_crypto_request *qat_req = skcipher_request_ctx(req); struct icp_qat_fw_la_cipher_req_params *cipher_param; + gfp_t f = qat_algs_alloc_flags(&req->base); struct icp_qat_fw_la_bulk_req *msg; int ret; if (req->cryptlen == 0) return 0; - ret = qat_alg_sgl_to_bufl(ctx->inst, req->src, req->dst, qat_req); + ret = qat_alg_sgl_to_bufl(ctx->inst, req->src, req->dst, qat_req, f); if (unlikely(ret)) return ret; @@ -1264,13 +1268,14 @@ static int qat_alg_skcipher_decrypt(struct skcipher_request *req) struct qat_alg_skcipher_ctx *ctx = crypto_tfm_ctx(tfm); struct qat_crypto_request *qat_req = skcipher_request_ctx(req); struct icp_qat_fw_la_cipher_req_params *cipher_param; + gfp_t f = qat_algs_alloc_flags(&req->base); struct icp_qat_fw_la_bulk_req *msg; int ret; if (req->cryptlen == 0) return 0; - ret = qat_alg_sgl_to_bufl(ctx->inst, req->src, req->dst, qat_req); + ret = qat_alg_sgl_to_bufl(ctx->inst, req->src, req->dst, qat_req, f); if (unlikely(ret)) return ret; diff --git a/drivers/crypto/qat/qat_common/qat_asym_algs.c b/drivers/crypto/qat/qat_common/qat_asym_algs.c index 5f11929cf9ba..4128200a9032 100644 --- a/drivers/crypto/qat/qat_common/qat_asym_algs.c +++ b/drivers/crypto/qat/qat_common/qat_asym_algs.c @@ -170,15 +170,14 @@ static void qat_dh_cb(struct icp_qat_fw_pke_resp *resp) } areq->dst_len = req->ctx.dh->p_size; + dma_unmap_single(dev, req->out.dh.r, req->ctx.dh->p_size, + DMA_FROM_DEVICE); if (req->dst_align) { scatterwalk_map_and_copy(req->dst_align, areq->dst, 0, areq->dst_len, 1); kfree_sensitive(req->dst_align); } - dma_unmap_single(dev, req->out.dh.r, req->ctx.dh->p_size, - DMA_FROM_DEVICE); - dma_unmap_single(dev, req->phy_in, sizeof(struct qat_dh_input_params), DMA_TO_DEVICE); dma_unmap_single(dev, req->phy_out, @@ -224,9 +223,10 @@ static int qat_dh_compute_value(struct kpp_request *req) struct qat_asym_request *qat_req = PTR_ALIGN(kpp_request_ctx(req), 64); struct icp_qat_fw_pke_request *msg = &qat_req->req; - int ret; + gfp_t flags = qat_algs_alloc_flags(&req->base); int n_input_params = 0; u8 *vaddr; + int ret; if (unlikely(!ctx->xa)) return -EINVAL; @@ -291,7 +291,7 @@ static int qat_dh_compute_value(struct kpp_request *req) } else { int shift = ctx->p_size - req->src_len; - qat_req->src_align = kzalloc(ctx->p_size, GFP_KERNEL); + qat_req->src_align = kzalloc(ctx->p_size, flags); if (unlikely(!qat_req->src_align)) return ret; @@ -317,7 +317,7 @@ static int qat_dh_compute_value(struct kpp_request *req) qat_req->dst_align = NULL; vaddr = sg_virt(req->dst); } else { - qat_req->dst_align = kzalloc(ctx->p_size, GFP_KERNEL); + qat_req->dst_align = kzalloc(ctx->p_size, flags); if (unlikely(!qat_req->dst_align)) goto unmap_src; @@ -331,13 +331,13 @@ static int qat_dh_compute_value(struct kpp_request *req) qat_req->in.dh.in_tab[n_input_params] = 0; qat_req->out.dh.out_tab[1] = 0; /* Mapping in.in.b or in.in_g2.xa is the same */ - qat_req->phy_in = dma_map_single(dev, &qat_req->in.dh.in.b, + qat_req->phy_in = dma_map_single(dev, &qat_req->in.dh, sizeof(struct qat_dh_input_params), DMA_TO_DEVICE); if (unlikely(dma_mapping_error(dev, qat_req->phy_in))) goto unmap_dst; - qat_req->phy_out = dma_map_single(dev, &qat_req->out.dh.r, + qat_req->phy_out = dma_map_single(dev, &qat_req->out.dh, sizeof(struct qat_dh_output_params), DMA_TO_DEVICE); if (unlikely(dma_mapping_error(dev, qat_req->phy_out))) @@ -488,11 +488,13 @@ static int qat_dh_init_tfm(struct crypto_kpp *tfm) { struct qat_dh_ctx *ctx = kpp_tfm_ctx(tfm); struct qat_crypto_instance *inst = - qat_crypto_get_instance_node(get_current_node()); + qat_crypto_get_instance_node(numa_node_id()); if (!inst) return -EINVAL; + kpp_set_reqsize(tfm, sizeof(struct qat_asym_request) + 64); + ctx->p_size = 0; ctx->g2 = false; ctx->inst = inst; @@ -518,12 +520,14 @@ static void qat_rsa_cb(struct icp_qat_fw_pke_resp *resp) err = (err == ICP_QAT_FW_COMN_STATUS_FLAG_OK) ? 0 : -EINVAL; - kfree_sensitive(req->src_align); - dma_unmap_single(dev, req->in.rsa.enc.m, req->ctx.rsa->key_sz, DMA_TO_DEVICE); + kfree_sensitive(req->src_align); + areq->dst_len = req->ctx.rsa->key_sz; + dma_unmap_single(dev, req->out.rsa.enc.c, req->ctx.rsa->key_sz, + DMA_FROM_DEVICE); if (req->dst_align) { scatterwalk_map_and_copy(req->dst_align, areq->dst, 0, areq->dst_len, 1); @@ -531,9 +535,6 @@ static void qat_rsa_cb(struct icp_qat_fw_pke_resp *resp) kfree_sensitive(req->dst_align); } - dma_unmap_single(dev, req->out.rsa.enc.c, req->ctx.rsa->key_sz, - DMA_FROM_DEVICE); - dma_unmap_single(dev, req->phy_in, sizeof(struct qat_rsa_input_params), DMA_TO_DEVICE); dma_unmap_single(dev, req->phy_out, @@ -650,6 +651,7 @@ static int qat_rsa_enc(struct akcipher_request *req) struct qat_asym_request *qat_req = PTR_ALIGN(akcipher_request_ctx(req), 64); struct icp_qat_fw_pke_request *msg = &qat_req->req; + gfp_t flags = qat_algs_alloc_flags(&req->base); u8 *vaddr; int ret; @@ -696,7 +698,7 @@ static int qat_rsa_enc(struct akcipher_request *req) } else { int shift = ctx->key_sz - req->src_len; - qat_req->src_align = kzalloc(ctx->key_sz, GFP_KERNEL); + qat_req->src_align = kzalloc(ctx->key_sz, flags); if (unlikely(!qat_req->src_align)) return ret; @@ -714,7 +716,7 @@ static int qat_rsa_enc(struct akcipher_request *req) qat_req->dst_align = NULL; vaddr = sg_virt(req->dst); } else { - qat_req->dst_align = kzalloc(ctx->key_sz, GFP_KERNEL); + qat_req->dst_align = kzalloc(ctx->key_sz, flags); if (unlikely(!qat_req->dst_align)) goto unmap_src; vaddr = qat_req->dst_align; @@ -727,13 +729,13 @@ static int qat_rsa_enc(struct akcipher_request *req) qat_req->in.rsa.in_tab[3] = 0; qat_req->out.rsa.out_tab[1] = 0; - qat_req->phy_in = dma_map_single(dev, &qat_req->in.rsa.enc.m, + qat_req->phy_in = dma_map_single(dev, &qat_req->in.rsa, sizeof(struct qat_rsa_input_params), DMA_TO_DEVICE); if (unlikely(dma_mapping_error(dev, qat_req->phy_in))) goto unmap_dst; - qat_req->phy_out = dma_map_single(dev, &qat_req->out.rsa.enc.c, + qat_req->phy_out = dma_map_single(dev, &qat_req->out.rsa, sizeof(struct qat_rsa_output_params), DMA_TO_DEVICE); if (unlikely(dma_mapping_error(dev, qat_req->phy_out))) @@ -783,6 +785,7 @@ static int qat_rsa_dec(struct akcipher_request *req) struct qat_asym_request *qat_req = PTR_ALIGN(akcipher_request_ctx(req), 64); struct icp_qat_fw_pke_request *msg = &qat_req->req; + gfp_t flags = qat_algs_alloc_flags(&req->base); u8 *vaddr; int ret; @@ -839,7 +842,7 @@ static int qat_rsa_dec(struct akcipher_request *req) } else { int shift = ctx->key_sz - req->src_len; - qat_req->src_align = kzalloc(ctx->key_sz, GFP_KERNEL); + qat_req->src_align = kzalloc(ctx->key_sz, flags); if (unlikely(!qat_req->src_align)) return ret; @@ -857,7 +860,7 @@ static int qat_rsa_dec(struct akcipher_request *req) qat_req->dst_align = NULL; vaddr = sg_virt(req->dst); } else { - qat_req->dst_align = kzalloc(ctx->key_sz, GFP_KERNEL); + qat_req->dst_align = kzalloc(ctx->key_sz, flags); if (unlikely(!qat_req->dst_align)) goto unmap_src; vaddr = qat_req->dst_align; @@ -872,13 +875,13 @@ static int qat_rsa_dec(struct akcipher_request *req) else qat_req->in.rsa.in_tab[3] = 0; qat_req->out.rsa.out_tab[1] = 0; - qat_req->phy_in = dma_map_single(dev, &qat_req->in.rsa.dec.c, + qat_req->phy_in = dma_map_single(dev, &qat_req->in.rsa, sizeof(struct qat_rsa_input_params), DMA_TO_DEVICE); if (unlikely(dma_mapping_error(dev, qat_req->phy_in))) goto unmap_dst; - qat_req->phy_out = dma_map_single(dev, &qat_req->out.rsa.dec.m, + qat_req->phy_out = dma_map_single(dev, &qat_req->out.rsa, sizeof(struct qat_rsa_output_params), DMA_TO_DEVICE); if (unlikely(dma_mapping_error(dev, qat_req->phy_out))) @@ -1222,11 +1225,13 @@ static int qat_rsa_init_tfm(struct crypto_akcipher *tfm) { struct qat_rsa_ctx *ctx = akcipher_tfm_ctx(tfm); struct qat_crypto_instance *inst = - qat_crypto_get_instance_node(get_current_node()); + qat_crypto_get_instance_node(numa_node_id()); if (!inst) return -EINVAL; + akcipher_set_reqsize(tfm, sizeof(struct qat_asym_request) + 64); + ctx->key_sz = 0; ctx->inst = inst; return 0; @@ -1249,7 +1254,6 @@ static struct akcipher_alg rsa = { .max_size = qat_rsa_max_size, .init = qat_rsa_init_tfm, .exit = qat_rsa_exit_tfm, - .reqsize = sizeof(struct qat_asym_request) + 64, .base = { .cra_name = "rsa", .cra_driver_name = "qat-rsa", @@ -1266,7 +1270,6 @@ static struct kpp_alg dh = { .max_size = qat_dh_max_size, .init = qat_dh_init_tfm, .exit = qat_dh_exit_tfm, - .reqsize = sizeof(struct qat_asym_request) + 64, .base = { .cra_name = "dh", .cra_driver_name = "qat-dh", diff --git a/drivers/crypto/qat/qat_common/qat_crypto.h b/drivers/crypto/qat/qat_common/qat_crypto.h index 245b6d9a3650..df3c738ce323 100644 --- a/drivers/crypto/qat/qat_common/qat_crypto.h +++ b/drivers/crypto/qat/qat_common/qat_crypto.h @@ -109,4 +109,9 @@ static inline bool adf_hw_dev_has_crypto(struct adf_accel_dev *accel_dev) return true; } +static inline gfp_t qat_algs_alloc_flags(struct crypto_async_request *req) +{ + return req->flags & CRYPTO_TFM_REQ_MAY_SLEEP ? GFP_KERNEL : GFP_ATOMIC; +} + #endif diff --git a/drivers/dax/bus.c b/drivers/dax/bus.c index e75b9edc88a1..7ad61c707687 100644 --- a/drivers/dax/bus.c +++ b/drivers/dax/bus.c @@ -402,18 +402,34 @@ static void unregister_dev_dax(void *dev) put_device(dev); } +static void dax_region_free(struct kref *kref) +{ + struct dax_region *dax_region; + + dax_region = container_of(kref, struct dax_region, kref); + kfree(dax_region); +} + +void dax_region_put(struct dax_region *dax_region) +{ + kref_put(&dax_region->kref, dax_region_free); +} +EXPORT_SYMBOL_GPL(dax_region_put); + /* a return value >= 0 indicates this invocation invalidated the id */ static int __free_dev_dax_id(struct dev_dax *dev_dax) { - struct dax_region *dax_region = dev_dax->region; struct device *dev = &dev_dax->dev; + struct dax_region *dax_region; int rc = dev_dax->id; device_lock_assert(dev); - if (is_static(dax_region) || dev_dax->id < 0) + if (!dev_dax->dyn_id || dev_dax->id < 0) return -1; + dax_region = dev_dax->region; ida_free(&dax_region->ida, dev_dax->id); + dax_region_put(dax_region); dev_dax->id = -1; return rc; } @@ -429,6 +445,20 @@ static int free_dev_dax_id(struct dev_dax *dev_dax) return rc; } +static int alloc_dev_dax_id(struct dev_dax *dev_dax) +{ + struct dax_region *dax_region = dev_dax->region; + int id; + + id = ida_alloc(&dax_region->ida, GFP_KERNEL); + if (id < 0) + return id; + kref_get(&dax_region->kref); + dev_dax->dyn_id = true; + dev_dax->id = id; + return id; +} + static ssize_t delete_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t len) { @@ -516,20 +546,6 @@ static const struct attribute_group *dax_region_attribute_groups[] = { NULL, }; -static void dax_region_free(struct kref *kref) -{ - struct dax_region *dax_region; - - dax_region = container_of(kref, struct dax_region, kref); - kfree(dax_region); -} - -void dax_region_put(struct dax_region *dax_region) -{ - kref_put(&dax_region->kref, dax_region_free); -} -EXPORT_SYMBOL_GPL(dax_region_put); - static void dax_region_unregister(void *region) { struct dax_region *dax_region = region; @@ -591,10 +607,12 @@ EXPORT_SYMBOL_GPL(alloc_dax_region); static void dax_mapping_release(struct device *dev) { struct dax_mapping *mapping = to_dax_mapping(dev); - struct dev_dax *dev_dax = to_dev_dax(dev->parent); + struct device *parent = dev->parent; + struct dev_dax *dev_dax = to_dev_dax(parent); ida_free(&dev_dax->ida, mapping->id); kfree(mapping); + put_device(parent); } static void unregister_dax_mapping(void *data) @@ -734,6 +752,7 @@ static int devm_register_dax_mapping(struct dev_dax *dev_dax, int range_id) dev = &mapping->dev; device_initialize(dev); dev->parent = &dev_dax->dev; + get_device(dev->parent); dev->type = &dax_mapping_type; dev_set_name(dev, "mapping%d", mapping->id); rc = device_add(dev); @@ -1251,12 +1270,10 @@ static const struct attribute_group *dax_attribute_groups[] = { static void dev_dax_release(struct device *dev) { struct dev_dax *dev_dax = to_dev_dax(dev); - struct dax_region *dax_region = dev_dax->region; struct dax_device *dax_dev = dev_dax->dax_dev; put_dax(dax_dev); free_dev_dax_id(dev_dax); - dax_region_put(dax_region); kfree(dev_dax->pgmap); kfree(dev_dax); } @@ -1280,6 +1297,7 @@ struct dev_dax *devm_create_dev_dax(struct dev_dax_data *data) if (!dev_dax) return ERR_PTR(-ENOMEM); + dev_dax->region = dax_region; if (is_static(dax_region)) { if (dev_WARN_ONCE(parent, data->id < 0, "dynamic id specified to static region\n")) { @@ -1295,13 +1313,11 @@ struct dev_dax *devm_create_dev_dax(struct dev_dax_data *data) goto err_id; } - rc = ida_alloc(&dax_region->ida, GFP_KERNEL); + rc = alloc_dev_dax_id(dev_dax); if (rc < 0) goto err_id; - dev_dax->id = rc; } - dev_dax->region = dax_region; dev = &dev_dax->dev; device_initialize(dev); dev_set_name(dev, "dax%d.%d", dax_region->id, dev_dax->id); @@ -1339,7 +1355,6 @@ struct dev_dax *devm_create_dev_dax(struct dev_dax_data *data) dev_dax->target_node = dax_region->target_node; dev_dax->align = dax_region->align; ida_init(&dev_dax->ida); - kref_get(&dax_region->kref); inode = dax_inode(dax_dev); dev->devt = inode->i_rdev; diff --git a/drivers/dax/dax-private.h b/drivers/dax/dax-private.h index 1c974b7caae6..afcada6fd2ed 100644 --- a/drivers/dax/dax-private.h +++ b/drivers/dax/dax-private.h @@ -52,7 +52,8 @@ struct dax_mapping { * @region - parent region * @dax_dev - core dax functionality * @target_node: effective numa node if dev_dax memory range is onlined - * @id: ida allocated id + * @dyn_id: is this a dynamic or statically created instance + * @id: ida allocated id when the dax_region is not static * @ida: mapping id allocator * @dev - device core * @pgmap - pgmap for memmap setup / lifetime (driver owned) @@ -64,6 +65,7 @@ struct dev_dax { struct dax_device *dax_dev; unsigned int align; int target_node; + bool dyn_id; int id; struct ida ida; struct device dev; diff --git a/drivers/dax/kmem.c b/drivers/dax/kmem.c index 04f85f16720c..97723ee15bc6 100644 --- a/drivers/dax/kmem.c +++ b/drivers/dax/kmem.c @@ -88,7 +88,7 @@ static int dev_dax_kmem_probe(struct dev_dax *dev_dax) if (!data->res_name) goto err_res_name; - rc = memory_group_register_static(numa_node, total_len); + rc = memory_group_register_static(numa_node, PFN_UP(total_len)); if (rc < 0) goto err_reg_mgid; data->mgid = rc; diff --git a/drivers/extcon/extcon-usbc-tusb320.c b/drivers/extcon/extcon-usbc-tusb320.c index 9dfa545427ca..b408ce989c22 100644 --- a/drivers/extcon/extcon-usbc-tusb320.c +++ b/drivers/extcon/extcon-usbc-tusb320.c @@ -428,8 +428,7 @@ static int tusb320_typec_probe(struct i2c_client *client, return 0; } -static int tusb320_probe(struct i2c_client *client, - const struct i2c_device_id *id) +static int tusb320_probe(struct i2c_client *client) { struct tusb320_priv *priv; const void *match_data; @@ -502,7 +501,7 @@ static const struct of_device_id tusb320_extcon_dt_match[] = { MODULE_DEVICE_TABLE(of, tusb320_extcon_dt_match); static struct i2c_driver tusb320_extcon_driver = { - .probe = tusb320_probe, + .probe_new = tusb320_probe, .driver = { .name = "extcon-tusb320", .of_match_table = tusb320_extcon_dt_match, diff --git a/drivers/extcon/extcon.c b/drivers/extcon/extcon.c index ba8b04e5f03b..3a6514d0acc7 100644 --- a/drivers/extcon/extcon.c +++ b/drivers/extcon/extcon.c @@ -196,6 +196,14 @@ static const struct __extcon_info { * @attr_name: "name" sysfs entry * @attr_state: "state" sysfs entry * @attrs: the array pointing to attr_name and attr_state for attr_g + * @usb_propval: the array of USB connector properties + * @chg_propval: the array of charger connector properties + * @jack_propval: the array of jack connector properties + * @disp_propval: the array of display connector properties + * @usb_bits: the bit array of the USB connector property capabilities + * @chg_bits: the bit array of the charger connector property capabilities + * @jack_bits: the bit array of the jack connector property capabilities + * @disp_bits: the bit array of the display connector property capabilities */ struct extcon_cable { struct extcon_dev *edev; diff --git a/drivers/firmware/efi/libstub/efi-stub-helper.c b/drivers/firmware/efi/libstub/efi-stub-helper.c index d489bdc645fe..2a00eb627c3c 100644 --- a/drivers/firmware/efi/libstub/efi-stub-helper.c +++ b/drivers/firmware/efi/libstub/efi-stub-helper.c @@ -439,8 +439,10 @@ efi_status_t efi_exit_boot_services(void *handle, { efi_status_t status; - status = efi_get_memory_map(map); + if (efi_disable_pci_dma) + efi_pci_disable_bridge_busmaster(); + status = efi_get_memory_map(map); if (status != EFI_SUCCESS) goto fail; @@ -448,9 +450,6 @@ efi_status_t efi_exit_boot_services(void *handle, if (status != EFI_SUCCESS) goto free_map; - if (efi_disable_pci_dma) - efi_pci_disable_bridge_busmaster(); - status = efi_bs_call(exit_boot_services, handle, *map->key_ptr); if (status == EFI_INVALID_PARAMETER) { diff --git a/drivers/firmware/qcom_scm.c b/drivers/firmware/qcom_scm.c index 7cb8bf473cbf..76c5c0c2496b 100644 --- a/drivers/firmware/qcom_scm.c +++ b/drivers/firmware/qcom_scm.c @@ -60,7 +60,6 @@ struct qcom_scm { struct qcom_scm_waitq waitq; u64 dload_mode_addr; - bool legacy_dload_method; }; enum qcom_scm_custom_reset_type qcom_scm_custom_reset_type; @@ -528,10 +527,12 @@ void qcom_scm_set_download_mode(enum qcom_download_mode mode, phys_addr_t tcsr_b int ret = 0; struct device *dev = __scm ? __scm->dev : NULL; - if (__scm && __scm->legacy_dload_method) { - ret = __qcom_scm_set_dload_mode(dev, mode); - } else if (tcsr_boot_misc || (__scm && __scm->dload_mode_addr)) { + if (tcsr_boot_misc || (__scm && __scm->dload_mode_addr)) { ret = qcom_scm_io_writel(tcsr_boot_misc ? : __scm->dload_mode_addr, mode); + } else if (__qcom_scm_is_call_available(dev, + QCOM_SCM_SVC_BOOT, + QCOM_SCM_BOOT_SET_DLOAD_MODE)) { + ret = __qcom_scm_set_dload_mode(dev, mode); } else { dev_err(dev, "No available mechanism for setting download mode\n"); @@ -3045,13 +3046,6 @@ int scm_mem_protection_init_do(void) return resp; } -static bool is_dload_enabled(void) -{ - return ((IS_ENABLED(CONFIG_POWER_RESET_QCOM_DOWNLOAD_MODE) || - IS_ENABLED(CONFIG_POWER_RESET_MSM) || - download_mode)); -} - static int qcom_scm_probe(struct platform_device *pdev) { struct qcom_scm *scm; @@ -3062,21 +3056,9 @@ static int qcom_scm_probe(struct platform_device *pdev) if (!scm) return -ENOMEM; - /* - * For some target checking _qcom_scm_is_call_available on - * QCOM_SCM_BOOT_SET_DLOAD_MODE just hangs, so, to be on safer - * side, check only if the configs are enabled. - */ - if (is_dload_enabled()) { - ret = qcom_scm_find_dload_address(&pdev->dev, &scm->dload_mode_addr); - if (ret < 0) - return ret; - - if (!scm->dload_mode_addr) { - scm->legacy_dload_method = __qcom_scm_is_call_available(&pdev->dev, - QCOM_SCM_SVC_BOOT, QCOM_SCM_BOOT_SET_DLOAD_MODE); - } - } + ret = qcom_scm_find_dload_address(&pdev->dev, &scm->dload_mode_addr); + if (ret < 0) + return ret; clks = (unsigned long)of_device_get_match_data(&pdev->dev); diff --git a/drivers/firmware/qcom_scm_hab.c b/drivers/firmware/qcom_scm_hab.c index 1ef2e6d81484..b55e96167a16 100644 --- a/drivers/firmware/qcom_scm_hab.c +++ b/drivers/firmware/qcom_scm_hab.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2022, Qualcomm Innovation Center, Inc. All rights reserved. + * Copyright (c) 2022-2023, Qualcomm Innovation Center, Inc. All rights reserved. */ #include @@ -73,7 +73,7 @@ static int scm_qcpe_hab_send_receive(struct smc_params_s *smc_params, *size_bytes = sizeof(*smc_params); ret = habmm_socket_recv(handle, smc_params, size_bytes, 0, HABMM_SOCKET_RECV_FLAGS_UNINTERRUPTIBLE); - } while (-EINTR == ret); + } while (-EAGAIN == ret); if (ret) { pr_err("habmm_socket_recv failed, ret= 0x%x\n", ret); diff --git a/drivers/firmware/stratix10-svc.c b/drivers/firmware/stratix10-svc.c index 2b50dc21fba1..1bd3979abde6 100644 --- a/drivers/firmware/stratix10-svc.c +++ b/drivers/firmware/stratix10-svc.c @@ -622,7 +622,7 @@ svc_create_memory_pool(struct platform_device *pdev, end = rounddown(sh_memory->addr + sh_memory->size, PAGE_SIZE); paddr = begin; size = end - begin; - va = memremap(paddr, size, MEMREMAP_WC); + va = devm_memremap(dev, paddr, size, MEMREMAP_WC); if (!va) { dev_err(dev, "fail to remap shared memory\n"); return ERR_PTR(-EINVAL); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c index 34303dd3ada9..00a8aef48a69 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c @@ -2350,6 +2350,9 @@ int amdgpu_amdkfd_gpuvm_restore_process_bos(void *info, struct dma_fence **ef) if (!attachment->is_mapped) continue; + if (attachment->bo_va->base.bo->tbo.pin_count) + continue; + kfd_mem_dmaunmap_attachment(mem, attachment); ret = update_gpuvm_pte(mem, attachment, &sync_obj, NULL); if (ret) { diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c index d03a4519f945..8a0b652da4f4 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c @@ -685,7 +685,6 @@ int amdgpu_bo_create_vm(struct amdgpu_device *adev, * num of amdgpu_vm_pt entries. */ BUG_ON(bp->bo_ptr_size < sizeof(struct amdgpu_bo_vm)); - bp->destroy = &amdgpu_bo_vm_destroy; r = amdgpu_bo_create(adev, bp, &bo_ptr); if (r) return r; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c index 924c6d5f8620..0e4554950e07 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c @@ -2334,14 +2334,14 @@ int amdgpu_vm_bo_map(struct amdgpu_device *adev, uint64_t eaddr; /* validate the parameters */ - if (saddr & ~PAGE_MASK || offset & ~PAGE_MASK || - size == 0 || size & ~PAGE_MASK) + if (saddr & ~PAGE_MASK || offset & ~PAGE_MASK || size & ~PAGE_MASK) + return -EINVAL; + if (saddr + size <= saddr || offset + size <= offset) return -EINVAL; /* make sure object fit at this offset */ eaddr = saddr + size - 1; - if (saddr >= eaddr || - (bo && offset + size > amdgpu_bo_size(bo)) || + if ((bo && offset + size > amdgpu_bo_size(bo)) || (eaddr >= adev->vm_manager.max_pfn << AMDGPU_GPU_PAGE_SHIFT)) return -EINVAL; @@ -2400,14 +2400,14 @@ int amdgpu_vm_bo_replace_map(struct amdgpu_device *adev, int r; /* validate the parameters */ - if (saddr & ~PAGE_MASK || offset & ~PAGE_MASK || - size == 0 || size & ~PAGE_MASK) + if (saddr & ~PAGE_MASK || offset & ~PAGE_MASK || size & ~PAGE_MASK) + return -EINVAL; + if (saddr + size <= saddr || offset + size <= offset) return -EINVAL; /* make sure object fit at this offset */ eaddr = saddr + size - 1; - if (saddr >= eaddr || - (bo && offset + size > amdgpu_bo_size(bo)) || + if ((bo && offset + size > amdgpu_bo_size(bo)) || (eaddr >= adev->vm_manager.max_pfn << AMDGPU_GPU_PAGE_SHIFT)) return -EINVAL; @@ -2575,18 +2575,30 @@ int amdgpu_vm_bo_clear_mappings(struct amdgpu_device *adev, /* Insert partial mapping before the range */ if (!list_empty(&before->list)) { + struct amdgpu_bo *bo = before->bo_va->base.bo; + amdgpu_vm_it_insert(before, &vm->va); if (before->flags & AMDGPU_PTE_PRT) amdgpu_vm_prt_get(adev); + + if (bo && bo->tbo.base.resv == vm->root.bo->tbo.base.resv && + !before->bo_va->base.moved) + amdgpu_vm_bo_moved(&before->bo_va->base); } else { kfree(before); } /* Insert partial mapping after the range */ if (!list_empty(&after->list)) { + struct amdgpu_bo *bo = after->bo_va->base.bo; + amdgpu_vm_it_insert(after, &vm->va); if (after->flags & AMDGPU_PTE_PRT) amdgpu_vm_prt_get(adev); + + if (bo && bo->tbo.base.resv == vm->root.bo->tbo.base.resv && + !after->bo_va->base.moved) + amdgpu_vm_bo_moved(&after->bo_va->base); } else { kfree(after); } @@ -3274,6 +3286,10 @@ int amdgpu_vm_ioctl(struct drm_device *dev, void *data, struct drm_file *filp) long timeout = msecs_to_jiffies(2000); int r; + /* No valid flags defined yet */ + if (args->in.flags) + return -EINVAL; + switch (args->in.op) { case AMDGPU_VM_OP_RESERVE_VMID: /* We only have requirement to reserve vmid from gfxhub */ diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_v9.c b/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_v9.c index 7f4e102ff4bd..ddaafcd7b825 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_v9.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_v9.c @@ -113,18 +113,19 @@ static struct kfd_mem_obj *allocate_mqd(struct kfd_dev *kfd, &(mqd_mem_obj->gtt_mem), &(mqd_mem_obj->gpu_addr), (void *)&(mqd_mem_obj->cpu_ptr), true); + + if (retval) { + kfree(mqd_mem_obj); + return NULL; + } } else { retval = kfd_gtt_sa_allocate(kfd, sizeof(struct v9_mqd), &mqd_mem_obj); - } - - if (retval) { - kfree(mqd_mem_obj); - return NULL; + if (retval) + return NULL; } return mqd_mem_obj; - } static void init_mqd(struct mqd_manager *mm, void **mqd, diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index be863af956bb..7bd38d927b18 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -8209,13 +8209,7 @@ static int amdgpu_dm_connector_get_modes(struct drm_connector *connector) drm_add_modes_noedid(connector, 640, 480); } else { amdgpu_dm_connector_ddc_get_modes(connector, edid); - /* most eDP supports only timings from its edid, - * usually only detailed timings are available - * from eDP edid. timings which are not from edid - * may damage eDP - */ - if (connector->connector_type != DRM_MODE_CONNECTOR_eDP) - amdgpu_dm_connector_add_common_modes(encoder, connector); + amdgpu_dm_connector_add_common_modes(encoder, connector); amdgpu_dm_connector_add_freesync_modes(connector, edid); } amdgpu_dm_fbc_init(connector); @@ -10209,6 +10203,8 @@ static int dm_update_crtc_state(struct amdgpu_display_manager *dm, /* Now check if we should set freesync video mode */ if (amdgpu_freesync_vid_mode && dm_new_crtc_state->stream && + dc_is_stream_unchanged(new_stream, dm_old_crtc_state->stream) && + dc_is_stream_scaling_unchanged(new_stream, dm_old_crtc_state->stream) && is_timing_unchanged_for_freesync(new_crtc_state, old_crtc_state)) { new_crtc_state->mode_changed = false; diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn30/dcn30_clk_mgr_smu_msg.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn30/dcn30_clk_mgr_smu_msg.c index 8ecc708bcd9e..766759420eeb 100644 --- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn30/dcn30_clk_mgr_smu_msg.c +++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn30/dcn30_clk_mgr_smu_msg.c @@ -302,6 +302,9 @@ void dcn30_smu_set_display_refresh_from_mall(struct clk_mgr_internal *clk_mgr, b /* bits 8:7 for cache timer scale, bits 6:1 for cache timer delay, bit 0 = 1 for enable, = 0 for disable */ uint32_t param = (cache_timer_scale << 7) | (cache_timer_delay << 1) | (enable ? 1 : 0); + smu_print("SMU Set display refresh from mall: enable = %d, cache_timer_delay = %d, cache_timer_scale = %d\n", + enable, cache_timer_delay, cache_timer_scale); + dcn30_smu_send_msg_with_param(clk_mgr, DALSMC_MSG_SetDisplayRefreshFromMall, param, NULL); } diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn31/dcn31_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn31/dcn31_clk_mgr.c index 8f6e6496ea78..5357620627af 100644 --- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn31/dcn31_clk_mgr.c +++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn31/dcn31_clk_mgr.c @@ -81,6 +81,11 @@ int dcn31_get_active_display_cnt_wa( stream->signal == SIGNAL_TYPE_DVI_SINGLE_LINK || stream->signal == SIGNAL_TYPE_DVI_DUAL_LINK) tmds_present = true; + + /* Checking stream / link detection ensuring that PHY is active*/ + if (dc_is_dp_signal(stream->signal) && !stream->dpms_off) + display_count++; + } for (i = 0; i < dc->link_count; i++) { diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 220a26e45a28..634640d5c0ff 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -2111,9 +2111,6 @@ static enum surface_update_type det_surface_update(const struct dc *dc, enum surface_update_type overall_type = UPDATE_TYPE_FAST; union surface_update_flags *update_flags = &u->surface->update_flags; - if (u->flip_addr) - update_flags->bits.addr_update = 1; - if (!is_surface_in_context(context, u->surface) || u->surface->force_full_update) { update_flags->raw = 0xFFFFFFFF; return UPDATE_TYPE_FULL; diff --git a/drivers/gpu/drm/amd/display/dc/dcn303/dcn303_resource.c b/drivers/gpu/drm/amd/display/dc/dcn303/dcn303_resource.c index 67d83417ec33..9d9b0d343c6b 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn303/dcn303_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn303/dcn303_resource.c @@ -193,7 +193,7 @@ static const struct dc_debug_options debug_defaults_drv = { .timing_trace = false, .clock_trace = true, .disable_pplib_clock_request = true, - .pipe_split_policy = MPC_SPLIT_DYNAMIC, + .pipe_split_policy = MPC_SPLIT_AVOID, .force_single_disp_pipe_split = false, .disable_dcc = DCC_ENABLE, .vsr_support = true, diff --git a/drivers/gpu/drm/amd/display/dmub/dmub_srv.h b/drivers/gpu/drm/amd/display/dmub/dmub_srv.h index caf961bb633f..0fc4f90d9e3e 100644 --- a/drivers/gpu/drm/amd/display/dmub/dmub_srv.h +++ b/drivers/gpu/drm/amd/display/dmub/dmub_srv.h @@ -445,7 +445,7 @@ struct dmub_notification { * of a firmware to know if feature or functionality is supported or present. */ #define DMUB_FW_VERSION(major, minor, revision) \ - ((((major) & 0xFF) << 24) | (((minor) & 0xFF) << 16) | ((revision) & 0xFFFF)) + ((((major) & 0xFF) << 24) | (((minor) & 0xFF) << 16) | (((revision) & 0xFF) << 8)) /** * dmub_srv_create() - creates the DMUB service. diff --git a/drivers/gpu/drm/bridge/tc358768.c b/drivers/gpu/drm/bridge/tc358768.c index a3db532bbdd1..8b1bdffc5005 100644 --- a/drivers/gpu/drm/bridge/tc358768.c +++ b/drivers/gpu/drm/bridge/tc358768.c @@ -9,6 +9,8 @@ #include #include #include +#include +#include #include #include #include @@ -147,6 +149,7 @@ struct tc358768_priv { u32 pd_lines; /* number of Parallel Port Input Data Lines */ u32 dsi_lanes; /* number of DSI Lanes */ + u32 dsi_bpp; /* number of Bits Per Pixel over DSI */ /* Parameters for PLL programming */ u32 fbd; /* PLL feedback divider */ @@ -279,12 +282,12 @@ static void tc358768_hw_disable(struct tc358768_priv *priv) static u32 tc358768_pll_to_pclk(struct tc358768_priv *priv, u32 pll_clk) { - return (u32)div_u64((u64)pll_clk * priv->dsi_lanes, priv->pd_lines); + return (u32)div_u64((u64)pll_clk * priv->dsi_lanes, priv->dsi_bpp); } static u32 tc358768_pclk_to_pll(struct tc358768_priv *priv, u32 pclk) { - return (u32)div_u64((u64)pclk * priv->pd_lines, priv->dsi_lanes); + return (u32)div_u64((u64)pclk * priv->dsi_bpp, priv->dsi_lanes); } static int tc358768_calc_pll(struct tc358768_priv *priv, @@ -329,13 +332,17 @@ static int tc358768_calc_pll(struct tc358768_priv *priv, u32 fbd; for (fbd = 0; fbd < 512; ++fbd) { - u32 pll, diff; + u32 pll, diff, pll_in; pll = (u32)div_u64((u64)refclk * (fbd + 1), divisor); if (pll >= max_pll || pll < min_pll) continue; + pll_in = (u32)div_u64((u64)refclk, prd + 1); + if (pll_in < 4000000) + continue; + diff = max(pll, target_pll) - min(pll, target_pll); if (diff < best_diff) { @@ -417,6 +424,7 @@ static int tc358768_dsi_host_attach(struct mipi_dsi_host *host, priv->output.panel = panel; priv->dsi_lanes = dev->lanes; + priv->dsi_bpp = mipi_dsi_pixel_format_to_bpp(dev->format); /* get input ep (port0/endpoint0) */ ret = -EINVAL; @@ -428,7 +436,7 @@ static int tc358768_dsi_host_attach(struct mipi_dsi_host *host, } if (ret) - priv->pd_lines = mipi_dsi_pixel_format_to_bpp(dev->format); + priv->pd_lines = priv->dsi_bpp; drm_bridge_add(&priv->bridge); @@ -626,6 +634,7 @@ static void tc358768_bridge_pre_enable(struct drm_bridge *bridge) struct tc358768_priv *priv = bridge_to_tc358768(bridge); struct mipi_dsi_device *dsi_dev = priv->output.dev; u32 val, val2, lptxcnt, hact, data_type; + s32 raw_val; const struct drm_display_mode *mode; u32 dsibclk_nsk, dsiclk_nsk, ui_nsk, phy_delay_nsk; u32 dsiclk, dsibclk; @@ -719,25 +728,26 @@ static void tc358768_bridge_pre_enable(struct drm_bridge *bridge) /* 38ns < TCLK_PREPARE < 95ns */ val = tc358768_ns_to_cnt(65, dsibclk_nsk) - 1; - /* TCLK_PREPARE > 300ns */ - val2 = tc358768_ns_to_cnt(300 + tc358768_to_ns(3 * ui_nsk), - dsibclk_nsk); - val |= (val2 - tc358768_to_ns(phy_delay_nsk - dsibclk_nsk)) << 8; + /* TCLK_PREPARE + TCLK_ZERO > 300ns */ + val2 = tc358768_ns_to_cnt(300 - tc358768_to_ns(2 * ui_nsk), + dsibclk_nsk) - 2; + val |= val2 << 8; dev_dbg(priv->dev, "TCLK_HEADERCNT: 0x%x\n", val); tc358768_write(priv, TC358768_TCLK_HEADERCNT, val); - /* TCLK_TRAIL > 60ns + 3*UI */ - val = 60 + tc358768_to_ns(3 * ui_nsk); - val = tc358768_ns_to_cnt(val, dsibclk_nsk) - 5; + /* TCLK_TRAIL > 60ns AND TEOT <= 105 ns + 12*UI */ + raw_val = tc358768_ns_to_cnt(60 + tc358768_to_ns(2 * ui_nsk), dsibclk_nsk) - 5; + val = clamp(raw_val, 0, 127); dev_dbg(priv->dev, "TCLK_TRAILCNT: 0x%x\n", val); tc358768_write(priv, TC358768_TCLK_TRAILCNT, val); /* 40ns + 4*UI < THS_PREPARE < 85ns + 6*UI */ val = 50 + tc358768_to_ns(4 * ui_nsk); val = tc358768_ns_to_cnt(val, dsibclk_nsk) - 1; - /* THS_ZERO > 145ns + 10*UI */ - val2 = tc358768_ns_to_cnt(145 - tc358768_to_ns(ui_nsk), dsibclk_nsk); - val |= (val2 - tc358768_to_ns(phy_delay_nsk)) << 8; + /* THS_PREPARE + THS_ZERO > 145ns + 10*UI */ + raw_val = tc358768_ns_to_cnt(145 - tc358768_to_ns(3 * ui_nsk), dsibclk_nsk) - 10; + val2 = clamp(raw_val, 0, 127); + val |= val2 << 8; dev_dbg(priv->dev, "THS_HEADERCNT: 0x%x\n", val); tc358768_write(priv, TC358768_THS_HEADERCNT, val); @@ -753,9 +763,10 @@ static void tc358768_bridge_pre_enable(struct drm_bridge *bridge) dev_dbg(priv->dev, "TCLK_POSTCNT: 0x%x\n", val); tc358768_write(priv, TC358768_TCLK_POSTCNT, val); - /* 60ns + 4*UI < THS_PREPARE < 105ns + 12*UI */ - val = tc358768_ns_to_cnt(60 + tc358768_to_ns(15 * ui_nsk), - dsibclk_nsk) - 5; + /* max(60ns + 4*UI, 8*UI) < THS_TRAILCNT < 105ns + 12*UI */ + raw_val = tc358768_ns_to_cnt(60 + tc358768_to_ns(18 * ui_nsk), + dsibclk_nsk) - 4; + val = clamp(raw_val, 0, 15); dev_dbg(priv->dev, "THS_TRAILCNT: 0x%x\n", val); tc358768_write(priv, TC358768_THS_TRAILCNT, val); @@ -769,7 +780,7 @@ static void tc358768_bridge_pre_enable(struct drm_bridge *bridge) /* TXTAGOCNT[26:16] RXTASURECNT[10:0] */ val = tc358768_to_ns((lptxcnt + 1) * dsibclk_nsk * 4); - val = tc358768_ns_to_cnt(val, dsibclk_nsk) - 1; + val = tc358768_ns_to_cnt(val, dsibclk_nsk) / 4 - 1; val2 = tc358768_ns_to_cnt(tc358768_to_ns((lptxcnt + 1) * dsibclk_nsk), dsibclk_nsk) - 2; val |= val2 << 16; @@ -819,8 +830,7 @@ static void tc358768_bridge_pre_enable(struct drm_bridge *bridge) val = TC358768_DSI_CONFW_MODE_SET | TC358768_DSI_CONFW_ADDR_DSI_CONTROL; val |= (dsi_dev->lanes - 1) << 1; - if (!(dsi_dev->mode_flags & MIPI_DSI_MODE_LPM)) - val |= TC358768_DSI_CONTROL_TXMD; + val |= TC358768_DSI_CONTROL_TXMD; if (!(dsi_dev->mode_flags & MIPI_DSI_CLOCK_NON_CONTINUOUS)) val |= TC358768_DSI_CONTROL_HSCKMD; @@ -866,6 +876,44 @@ static void tc358768_bridge_enable(struct drm_bridge *bridge) } } +#define MAX_INPUT_SEL_FORMATS 1 + +static u32 * +tc358768_atomic_get_input_bus_fmts(struct drm_bridge *bridge, + struct drm_bridge_state *bridge_state, + struct drm_crtc_state *crtc_state, + struct drm_connector_state *conn_state, + u32 output_fmt, + unsigned int *num_input_fmts) +{ + struct tc358768_priv *priv = bridge_to_tc358768(bridge); + u32 *input_fmts; + + *num_input_fmts = 0; + + input_fmts = kcalloc(MAX_INPUT_SEL_FORMATS, sizeof(*input_fmts), + GFP_KERNEL); + if (!input_fmts) + return NULL; + + switch (priv->pd_lines) { + case 16: + input_fmts[0] = MEDIA_BUS_FMT_RGB565_1X16; + break; + case 18: + input_fmts[0] = MEDIA_BUS_FMT_RGB666_1X18; + break; + default: + case 24: + input_fmts[0] = MEDIA_BUS_FMT_RGB888_1X24; + break; + }; + + *num_input_fmts = MAX_INPUT_SEL_FORMATS; + + return input_fmts; +} + static const struct drm_bridge_funcs tc358768_bridge_funcs = { .attach = tc358768_bridge_attach, .mode_valid = tc358768_bridge_mode_valid, @@ -873,6 +921,11 @@ static const struct drm_bridge_funcs tc358768_bridge_funcs = { .enable = tc358768_bridge_enable, .disable = tc358768_bridge_disable, .post_disable = tc358768_bridge_post_disable, + + .atomic_duplicate_state = drm_atomic_helper_bridge_duplicate_state, + .atomic_destroy_state = drm_atomic_helper_bridge_destroy_state, + .atomic_reset = drm_atomic_helper_bridge_reset, + .atomic_get_input_bus_fmts = tc358768_atomic_get_input_bus_fmts, }; static const struct drm_bridge_timings default_tc358768_timings = { diff --git a/drivers/gpu/drm/bridge/ti-sn65dsi86.c b/drivers/gpu/drm/bridge/ti-sn65dsi86.c index bbedce0eedda..22c2ff5272c6 100644 --- a/drivers/gpu/drm/bridge/ti-sn65dsi86.c +++ b/drivers/gpu/drm/bridge/ti-sn65dsi86.c @@ -147,9 +147,9 @@ * each other's read-modify-write. */ struct ti_sn65dsi86 { - struct auxiliary_device bridge_aux; - struct auxiliary_device gpio_aux; - struct auxiliary_device aux_aux; + struct auxiliary_device *bridge_aux; + struct auxiliary_device *gpio_aux; + struct auxiliary_device *aux_aux; struct device *dev; struct regmap *regmap; @@ -412,27 +412,34 @@ static void ti_sn65dsi86_delete_aux(void *data) auxiliary_device_delete(data); } -/* - * AUX bus docs say that a non-NULL release is mandatory, but it makes no - * sense for the model used here where all of the aux devices are allocated - * in the single shared structure. We'll use this noop as a workaround. - */ -static void ti_sn65dsi86_noop(struct device *dev) {} +static void ti_sn65dsi86_aux_device_release(struct device *dev) +{ + struct auxiliary_device *aux = container_of(dev, struct auxiliary_device, dev); + + kfree(aux); +} static int ti_sn65dsi86_add_aux_device(struct ti_sn65dsi86 *pdata, - struct auxiliary_device *aux, + struct auxiliary_device **aux_out, const char *name) { struct device *dev = pdata->dev; + struct auxiliary_device *aux; int ret; + aux = kzalloc(sizeof(*aux), GFP_KERNEL); + if (!aux) + return -ENOMEM; + aux->name = name; aux->dev.parent = dev; - aux->dev.release = ti_sn65dsi86_noop; + aux->dev.release = ti_sn65dsi86_aux_device_release; device_set_of_node_from_dev(&aux->dev, dev); ret = auxiliary_device_init(aux); - if (ret) + if (ret) { + kfree(aux); return ret; + } ret = devm_add_action_or_reset(dev, ti_sn65dsi86_uninit_aux, aux); if (ret) return ret; @@ -441,6 +448,8 @@ static int ti_sn65dsi86_add_aux_device(struct ti_sn65dsi86 *pdata, if (ret) return ret; ret = devm_add_action_or_reset(dev, ti_sn65dsi86_delete_aux, aux); + if (!ret) + *aux_out = aux; return ret; } diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c index 1fcb5f8aea20..166d329de939 100644 --- a/drivers/gpu/drm/drm_atomic.c +++ b/drivers/gpu/drm/drm_atomic.c @@ -138,6 +138,12 @@ drm_atomic_state_init(struct drm_device *dev, struct drm_atomic_state *state) if (!state->planes) goto fail; + /* + * Because drm_atomic_state can be committed asynchronously we need our + * own reference and cannot rely on the on implied by drm_file in the + * ioctl call. + */ + drm_dev_get(dev); state->dev = dev; DRM_DEBUG_ATOMIC("Allocated atomic state %p\n", state); @@ -297,7 +303,8 @@ EXPORT_SYMBOL(drm_atomic_state_clear); void __drm_atomic_state_free(struct kref *ref) { struct drm_atomic_state *state = container_of(ref, typeof(*state), ref); - struct drm_mode_config *config = &state->dev->mode_config; + struct drm_device *dev = state->dev; + struct drm_mode_config *config = &dev->mode_config; drm_atomic_state_clear(state); @@ -309,6 +316,8 @@ void __drm_atomic_state_free(struct kref *ref) drm_atomic_state_default_release(state); kfree(state); } + + drm_dev_put(dev); } EXPORT_SYMBOL(__drm_atomic_state_free); diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c index 808838aa727b..c657cdc81a81 100644 --- a/drivers/gpu/drm/drm_atomic_helper.c +++ b/drivers/gpu/drm/drm_atomic_helper.c @@ -1122,7 +1122,16 @@ disable_outputs(struct drm_device *dev, struct drm_atomic_state *old_state) continue; ret = drm_crtc_vblank_get(crtc); - WARN_ONCE(ret != -EINVAL, "driver forgot to call drm_crtc_vblank_off()\n"); + /* + * Self-refresh is not a true "disable"; ensure vblank remains + * enabled. + */ + if (new_crtc_state->self_refresh_active) + WARN_ONCE(ret != 0, + "driver disabled vblank in self-refresh\n"); + else + WARN_ONCE(ret != -EINVAL, + "driver forgot to call drm_crtc_vblank_off()\n"); if (ret == 0) drm_crtc_vblank_put(crtc); } diff --git a/drivers/gpu/drm/drm_client_modeset.c b/drivers/gpu/drm/drm_client_modeset.c index ced09c7c06f9..447ea279e691 100644 --- a/drivers/gpu/drm/drm_client_modeset.c +++ b/drivers/gpu/drm/drm_client_modeset.c @@ -309,6 +309,9 @@ static bool drm_client_target_cloned(struct drm_device *dev, can_clone = true; dmt_mode = drm_mode_find_dmt(dev, 1024, 768, 60, false); + if (!dmt_mode) + goto fail; + for (i = 0; i < connector_count; i++) { if (!enabled[i]) continue; @@ -324,11 +327,13 @@ static bool drm_client_target_cloned(struct drm_device *dev, if (!modes[i]) can_clone = false; } + kfree(dmt_mode); if (can_clone) { DRM_DEBUG_KMS("can clone using 1024x768\n"); return true; } +fail: DRM_INFO("kms: can't enable cloning when we probably wanted to.\n"); return false; } @@ -860,6 +865,7 @@ int drm_client_modeset_probe(struct drm_client_dev *client, unsigned int width, break; } + kfree(modeset->mode); modeset->mode = drm_mode_duplicate(dev, mode); drm_connector_get(connector); modeset->connectors[modeset->num_connectors++] = connector; diff --git a/drivers/gpu/drm/drm_gem_vram_helper.c b/drivers/gpu/drm/drm_gem_vram_helper.c index 43cf7e887d1a..aaf4f7dcc581 100644 --- a/drivers/gpu/drm/drm_gem_vram_helper.c +++ b/drivers/gpu/drm/drm_gem_vram_helper.c @@ -43,7 +43,7 @@ static const struct drm_gem_object_funcs drm_gem_vram_object_funcs; * the frame's scanout buffer or the cursor image. If there's no more space * left in VRAM, inactive GEM objects can be moved to system memory. * - * To initialize the VRAM helper library call drmm_vram_helper_alloc_mm(). + * To initialize the VRAM helper library call drmm_vram_helper_init(). * The function allocates and initializes an instance of &struct drm_vram_mm * in &struct drm_device.vram_mm . Use &DRM_GEM_VRAM_DRIVER to initialize * &struct drm_driver and &DRM_VRAM_MM_FILE_OPERATIONS to initialize @@ -71,7 +71,7 @@ static const struct drm_gem_object_funcs drm_gem_vram_object_funcs; * // setup device, vram base and size * // ... * - * ret = drmm_vram_helper_alloc_mm(dev, vram_base, vram_size); + * ret = drmm_vram_helper_init(dev, vram_base, vram_size); * if (ret) * return ret; * return 0; @@ -84,7 +84,7 @@ static const struct drm_gem_object_funcs drm_gem_vram_object_funcs; * to userspace. * * You don't have to clean up the instance of VRAM MM. - * drmm_vram_helper_alloc_mm() is a managed interface that installs a + * drmm_vram_helper_init() is a managed interface that installs a * clean-up handler to run during the DRM device's release. * * For drawing or scanout operations, rsp. buffer objects have to be pinned diff --git a/drivers/gpu/drm/i915/display/intel_psr.c b/drivers/gpu/drm/i915/display/intel_psr.c index cf1e92486cbc..93d2fd4cd16b 100644 --- a/drivers/gpu/drm/i915/display/intel_psr.c +++ b/drivers/gpu/drm/i915/display/intel_psr.c @@ -862,9 +862,9 @@ static bool _compute_psr2_wake_times(struct intel_dp *intel_dp, } io_wake_lines = intel_usecs_to_scanlines( - &crtc_state->uapi.adjusted_mode, io_wake_time); + &crtc_state->hw.adjusted_mode, io_wake_time); fast_wake_lines = intel_usecs_to_scanlines( - &crtc_state->uapi.adjusted_mode, fast_wake_time); + &crtc_state->hw.adjusted_mode, fast_wake_time); if (io_wake_lines > max_wake_lines || fast_wake_lines > max_wake_lines) diff --git a/drivers/gpu/drm/i915/gt/intel_gtt.c b/drivers/gpu/drm/i915/gt/intel_gtt.c index 2d3a979736cc..f9d4094916e3 100644 --- a/drivers/gpu/drm/i915/gt/intel_gtt.c +++ b/drivers/gpu/drm/i915/gt/intel_gtt.c @@ -547,7 +547,7 @@ __vm_create_scratch_for_read(struct i915_address_space *vm, unsigned long size) if (IS_ERR(obj)) return ERR_CAST(obj); - i915_gem_object_set_cache_coherency(obj, I915_CACHING_CACHED); + i915_gem_object_set_cache_coherency(obj, I915_CACHE_LLC); vma = i915_vma_instance(obj, vm, NULL); if (IS_ERR(vma)) { diff --git a/drivers/gpu/drm/msm/adreno/a5xx_gpu.c b/drivers/gpu/drm/msm/adreno/a5xx_gpu.c index d92416d52628..ef62900b0612 100644 --- a/drivers/gpu/drm/msm/adreno/a5xx_gpu.c +++ b/drivers/gpu/drm/msm/adreno/a5xx_gpu.c @@ -1746,6 +1746,7 @@ struct msm_gpu *a5xx_gpu_init(struct drm_device *dev) { struct msm_drm_private *priv = dev->dev_private; struct platform_device *pdev = priv->gpu_pdev; + struct adreno_platform_config *config = pdev->dev.platform_data; struct a5xx_gpu *a5xx_gpu = NULL; struct adreno_gpu *adreno_gpu; struct msm_gpu *gpu; @@ -1772,7 +1773,7 @@ struct msm_gpu *a5xx_gpu_init(struct drm_device *dev) nr_rings = 4; - if (adreno_is_a510(adreno_gpu)) + if (adreno_cmp_rev(ADRENO_REV(5, 1, 0, ANY_ID), config->rev)) nr_rings = 1; ret = adreno_gpu_init(dev, pdev, adreno_gpu, &funcs, nr_rings); diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c index 4194689b6b35..8be941c9b6a9 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c @@ -1380,6 +1380,8 @@ static const struct drm_crtc_helper_funcs dpu_crtc_helper_funcs = { struct drm_crtc *dpu_crtc_init(struct drm_device *dev, struct drm_plane *plane, struct drm_plane *cursor) { + struct msm_drm_private *priv = dev->dev_private; + struct dpu_kms *dpu_kms = to_dpu_kms(priv->kms); struct drm_crtc *crtc = NULL; struct dpu_crtc *dpu_crtc = NULL; int i; @@ -1411,7 +1413,8 @@ struct drm_crtc *dpu_crtc_init(struct drm_device *dev, struct drm_plane *plane, drm_crtc_helper_add(crtc, &dpu_crtc_helper_funcs); - drm_crtc_enable_color_mgmt(crtc, 0, true, 0); + if (dpu_kms->catalog->dspp_count) + drm_crtc_enable_color_mgmt(crtc, 0, true, 0); /* save user friendly CRTC name for later */ snprintf(dpu_crtc->name, DPU_CRTC_NAME_SIZE, "crtc%u", crtc->base.id); diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c index 4c65259eecb9..272a3d7e1aef 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c @@ -53,9 +53,13 @@ #define INTF_SDM845_MASK (0) -#define INTF_SC7180_MASK BIT(DPU_INTF_INPUT_CTRL) | BIT(DPU_INTF_TE) +#define INTF_SC7180_MASK \ + (BIT(DPU_INTF_INPUT_CTRL) | \ + BIT(DPU_INTF_TE) | \ + BIT(DPU_INTF_STATUS_SUPPORTED) | \ + BIT(DPU_DATA_HCTL_EN)) -#define INTF_SC7280_MASK INTF_SC7180_MASK | BIT(DPU_DATA_HCTL_EN) +#define INTF_SC7280_MASK (INTF_SC7180_MASK) #define IRQ_SDM845_MASK (BIT(MDP_SSPP_TOP0_INTR) | \ BIT(MDP_SSPP_TOP0_INTR2) | \ @@ -804,7 +808,7 @@ static const struct dpu_pingpong_cfg sm8150_pp[] = { #define MERGE_3D_BLK(_name, _id, _base) \ {\ .name = _name, .id = _id, \ - .base = _base, .len = 0x100, \ + .base = _base, .len = 0x8, \ .features = MERGE_3D_SM8150_MASK, \ .sblk = NULL \ } diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h index d2a945a27cfa..321b7599fe2d 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h @@ -191,17 +191,19 @@ enum { /** * INTF sub-blocks - * @DPU_INTF_INPUT_CTRL Supports the setting of pp block from which - * pixel data arrives to this INTF - * @DPU_INTF_TE INTF block has TE configuration support - * @DPU_DATA_HCTL_EN Allows data to be transferred at different rate - than video timing + * @DPU_INTF_INPUT_CTRL Supports the setting of pp block from which + * pixel data arrives to this INTF + * @DPU_INTF_TE INTF block has TE configuration support + * @DPU_DATA_HCTL_EN Allows data to be transferred at different rate + * than video timing + * @DPU_INTF_STATUS_SUPPORTED INTF block has INTF_STATUS register * @DPU_INTF_MAX */ enum { DPU_INTF_INPUT_CTRL = 0x1, DPU_INTF_TE, DPU_DATA_HCTL_EN, + DPU_INTF_STATUS_SUPPORTED, DPU_INTF_MAX }; diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.c index 916e2a4756c0..7c09d30a62b8 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.c @@ -54,6 +54,7 @@ #define INTF_PROG_FETCH_START 0x170 #define INTF_PROG_ROT_START 0x174 #define INTF_MUX 0x25C +#define INTF_STATUS 0x26C static const struct dpu_intf_cfg *_intf_offset(enum dpu_intf intf, const struct dpu_mdss_cfg *m, @@ -259,8 +260,13 @@ static void dpu_hw_intf_get_status( struct intf_status *s) { struct dpu_hw_blk_reg_map *c = &intf->hw; + unsigned long cap = intf->cap->features; + + if (cap & BIT(DPU_INTF_STATUS_SUPPORTED)) + s->is_en = DPU_REG_READ(c, INTF_STATUS) & BIT(0); + else + s->is_en = DPU_REG_READ(c, INTF_TIMING_ENGINE_EN); - s->is_en = DPU_REG_READ(c, INTF_TIMING_ENGINE_EN); s->is_prog_fetch_en = !!(DPU_REG_READ(c, INTF_CONFIG) & BIT(31)); if (s->is_en) { s->frame_count = DPU_REG_READ(c, INTF_FRAME_COUNT); diff --git a/drivers/gpu/drm/msm/dp/dp_display.c b/drivers/gpu/drm/msm/dp/dp_display.c index 38d37345c216..bbe350fab797 100644 --- a/drivers/gpu/drm/msm/dp/dp_display.c +++ b/drivers/gpu/drm/msm/dp/dp_display.c @@ -1295,9 +1295,9 @@ static int dp_display_remove(struct platform_device *pdev) dp = container_of(g_dp_display, struct dp_display_private, dp_display); + component_del(&pdev->dev, &dp_display_comp_ops); dp_display_deinit_sub_modules(dp); - component_del(&pdev->dev, &dp_display_comp_ops); platform_set_drvdata(pdev, NULL); return 0; diff --git a/drivers/gpu/drm/msm/dsi/phy/dsi_phy_14nm.c b/drivers/gpu/drm/msm/dsi/phy/dsi_phy_14nm.c index 6d3abcdc57bf..66507eb71304 100644 --- a/drivers/gpu/drm/msm/dsi/phy/dsi_phy_14nm.c +++ b/drivers/gpu/drm/msm/dsi/phy/dsi_phy_14nm.c @@ -541,6 +541,9 @@ static int dsi_pll_14nm_vco_prepare(struct clk_hw *hw) if (unlikely(pll_14nm->phy->pll_on)) return 0; + if (dsi_pll_14nm_vco_recalc_rate(hw, VCO_REF_CLK_RATE) == 0) + dsi_pll_14nm_vco_set_rate(hw, pll_14nm->phy->cfg->min_pll_rate, VCO_REF_CLK_RATE); + dsi_phy_write(base + REG_DSI_14nm_PHY_PLL_VREF_CFG1, 0x10); dsi_phy_write(cmn_base + REG_DSI_14nm_PHY_CMN_PLL_CNTRL, 1); diff --git a/drivers/gpu/drm/panel/panel-sharp-ls043t1le01.c b/drivers/gpu/drm/panel/panel-sharp-ls043t1le01.c index 25829a0a8e80..e2f1e983ef7e 100644 --- a/drivers/gpu/drm/panel/panel-sharp-ls043t1le01.c +++ b/drivers/gpu/drm/panel/panel-sharp-ls043t1le01.c @@ -192,15 +192,15 @@ static int sharp_nt_panel_enable(struct drm_panel *panel) } static const struct drm_display_mode default_mode = { - .clock = 41118, + .clock = (540 + 48 + 32 + 80) * (960 + 3 + 10 + 15) * 60 / 1000, .hdisplay = 540, .hsync_start = 540 + 48, - .hsync_end = 540 + 48 + 80, - .htotal = 540 + 48 + 80 + 32, + .hsync_end = 540 + 48 + 32, + .htotal = 540 + 48 + 32 + 80, .vdisplay = 960, .vsync_start = 960 + 3, - .vsync_end = 960 + 3 + 15, - .vtotal = 960 + 3 + 15 + 1, + .vsync_end = 960 + 3 + 10, + .vtotal = 960 + 3 + 10 + 15, }; static int sharp_nt_panel_get_modes(struct drm_panel *panel, @@ -280,6 +280,7 @@ static int sharp_nt_panel_probe(struct mipi_dsi_device *dsi) dsi->lanes = 2; dsi->format = MIPI_DSI_FMT_RGB888; dsi->mode_flags = MIPI_DSI_MODE_VIDEO | + MIPI_DSI_MODE_VIDEO_SYNC_PULSE | MIPI_DSI_MODE_VIDEO_HSE | MIPI_DSI_CLOCK_NON_CONTINUOUS | MIPI_DSI_MODE_NO_EOT_PACKET; diff --git a/drivers/gpu/drm/panel/panel-simple.c b/drivers/gpu/drm/panel/panel-simple.c index fb785f5a106a..391d73d2638a 100644 --- a/drivers/gpu/drm/panel/panel-simple.c +++ b/drivers/gpu/drm/panel/panel-simple.c @@ -890,8 +890,8 @@ static const struct panel_desc ampire_am_480272h3tmqw_t01h = { .num_modes = 1, .bpc = 8, .size = { - .width = 105, - .height = 67, + .width = 99, + .height = 58, }, .bus_format = MEDIA_BUS_FMT_RGB888_1X24, }; @@ -2469,6 +2469,7 @@ static const struct panel_desc innolux_at043tn24 = { .height = 54, }, .bus_format = MEDIA_BUS_FMT_RGB888_1X24, + .connector_type = DRM_MODE_CONNECTOR_DPI, .bus_flags = DRM_BUS_FLAG_DE_HIGH | DRM_BUS_FLAG_PIXDATA_DRIVE_POSEDGE, }; @@ -3650,6 +3651,7 @@ static const struct drm_display_mode powertip_ph800480t013_idf02_mode = { .vsync_start = 480 + 49, .vsync_end = 480 + 49 + 2, .vtotal = 480 + 49 + 2 + 22, + .flags = DRM_MODE_FLAG_NVSYNC | DRM_MODE_FLAG_NHSYNC, }; static const struct panel_desc powertip_ph800480t013_idf02 = { diff --git a/drivers/gpu/drm/radeon/ci_dpm.c b/drivers/gpu/drm/radeon/ci_dpm.c index f0cfb58da467..4f93cc81ca7a 100644 --- a/drivers/gpu/drm/radeon/ci_dpm.c +++ b/drivers/gpu/drm/radeon/ci_dpm.c @@ -5520,6 +5520,7 @@ static int ci_parse_power_table(struct radeon_device *rdev) u8 frev, crev; u8 *power_state_offset; struct ci_ps *ps; + int ret; if (!atom_parse_data_header(mode_info->atom_context, index, NULL, &frev, &crev, &data_offset)) @@ -5549,11 +5550,15 @@ static int ci_parse_power_table(struct radeon_device *rdev) non_clock_array_index = power_state->v2.nonClockInfoIndex; non_clock_info = (struct _ATOM_PPLIB_NONCLOCK_INFO *) &non_clock_info_array->nonClockInfo[non_clock_array_index]; - if (!rdev->pm.power_state[i].clock_info) - return -EINVAL; + if (!rdev->pm.power_state[i].clock_info) { + ret = -EINVAL; + goto err_free_ps; + } ps = kzalloc(sizeof(struct ci_ps), GFP_KERNEL); - if (ps == NULL) - return -ENOMEM; + if (ps == NULL) { + ret = -ENOMEM; + goto err_free_ps; + } rdev->pm.dpm.ps[i].ps_priv = ps; ci_parse_pplib_non_clock_info(rdev, &rdev->pm.dpm.ps[i], non_clock_info, @@ -5593,6 +5598,12 @@ static int ci_parse_power_table(struct radeon_device *rdev) } return 0; + +err_free_ps: + for (i = 0; i < rdev->pm.dpm.num_ps; i++) + kfree(rdev->pm.dpm.ps[i].ps_priv); + kfree(rdev->pm.dpm.ps); + return ret; } static int ci_get_vbios_boot_values(struct radeon_device *rdev, @@ -5681,25 +5692,26 @@ int ci_dpm_init(struct radeon_device *rdev) ret = ci_get_vbios_boot_values(rdev, &pi->vbios_boot_state); if (ret) { - ci_dpm_fini(rdev); + kfree(rdev->pm.dpm.priv); return ret; } ret = r600_get_platform_caps(rdev); if (ret) { - ci_dpm_fini(rdev); + kfree(rdev->pm.dpm.priv); return ret; } ret = r600_parse_extended_power_table(rdev); if (ret) { - ci_dpm_fini(rdev); + kfree(rdev->pm.dpm.priv); return ret; } ret = ci_parse_power_table(rdev); if (ret) { - ci_dpm_fini(rdev); + kfree(rdev->pm.dpm.priv); + r600_free_extended_power_table(rdev); return ret; } diff --git a/drivers/gpu/drm/radeon/cypress_dpm.c b/drivers/gpu/drm/radeon/cypress_dpm.c index fdddbbaecbb7..72a0768df00f 100644 --- a/drivers/gpu/drm/radeon/cypress_dpm.c +++ b/drivers/gpu/drm/radeon/cypress_dpm.c @@ -557,8 +557,12 @@ static int cypress_populate_mclk_value(struct radeon_device *rdev, ASIC_INTERNAL_MEMORY_SS, vco_freq)) { u32 reference_clock = rdev->clock.mpll.reference_freq; u32 decoded_ref = rv740_get_decoded_reference_divider(dividers.ref_div); - u32 clk_s = reference_clock * 5 / (decoded_ref * ss.rate); - u32 clk_v = ss.percentage * + u32 clk_s, clk_v; + + if (!decoded_ref) + return -EINVAL; + clk_s = reference_clock * 5 / (decoded_ref * ss.rate); + clk_v = ss.percentage * (0x4000 * dividers.whole_fb_div + 0x800 * dividers.frac_fb_div) / (clk_s * 625); mpll_ss1 &= ~CLKV_MASK; diff --git a/drivers/gpu/drm/radeon/ni_dpm.c b/drivers/gpu/drm/radeon/ni_dpm.c index 672d2239293e..3e1c1a392fb7 100644 --- a/drivers/gpu/drm/radeon/ni_dpm.c +++ b/drivers/gpu/drm/radeon/ni_dpm.c @@ -2241,8 +2241,12 @@ static int ni_populate_mclk_value(struct radeon_device *rdev, ASIC_INTERNAL_MEMORY_SS, vco_freq)) { u32 reference_clock = rdev->clock.mpll.reference_freq; u32 decoded_ref = rv740_get_decoded_reference_divider(dividers.ref_div); - u32 clk_s = reference_clock * 5 / (decoded_ref * ss.rate); - u32 clk_v = ss.percentage * + u32 clk_s, clk_v; + + if (!decoded_ref) + return -EINVAL; + clk_s = reference_clock * 5 / (decoded_ref * ss.rate); + clk_v = ss.percentage * (0x4000 * dividers.whole_fb_div + 0x800 * dividers.frac_fb_div) / (clk_s * 625); mpll_ss1 &= ~CLKV_MASK; diff --git a/drivers/gpu/drm/radeon/radeon_cs.c b/drivers/gpu/drm/radeon/radeon_cs.c index 9ed2b2700e0a..e5fbe851ed93 100644 --- a/drivers/gpu/drm/radeon/radeon_cs.c +++ b/drivers/gpu/drm/radeon/radeon_cs.c @@ -270,7 +270,8 @@ int radeon_cs_parser_init(struct radeon_cs_parser *p, void *data) { struct drm_radeon_cs *cs = data; uint64_t *chunk_array_ptr; - unsigned size, i; + u64 size; + unsigned i; u32 ring = RADEON_CS_RING_GFX; s32 priority = 0; diff --git a/drivers/gpu/drm/radeon/rv740_dpm.c b/drivers/gpu/drm/radeon/rv740_dpm.c index d57a3e1df8d6..4464fd21a302 100644 --- a/drivers/gpu/drm/radeon/rv740_dpm.c +++ b/drivers/gpu/drm/radeon/rv740_dpm.c @@ -249,8 +249,12 @@ int rv740_populate_mclk_value(struct radeon_device *rdev, ASIC_INTERNAL_MEMORY_SS, vco_freq)) { u32 reference_clock = rdev->clock.mpll.reference_freq; u32 decoded_ref = rv740_get_decoded_reference_divider(dividers.ref_div); - u32 clk_s = reference_clock * 5 / (decoded_ref * ss.rate); - u32 clk_v = 0x40000 * ss.percentage * + u32 clk_s, clk_v; + + if (!decoded_ref) + return -EINVAL; + clk_s = reference_clock * 5 / (decoded_ref * ss.rate); + clk_v = 0x40000 * ss.percentage * (dividers.whole_fb_div + (dividers.frac_fb_div / 8)) / (clk_s * 10000); mpll_ss1 &= ~CLKV_MASK; diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c index d5b74ea06a45..26a3ed142b6b 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c @@ -703,13 +703,13 @@ static void vop_crtc_atomic_disable(struct drm_crtc *crtc, if (crtc->state->self_refresh_active) rockchip_drm_set_win_enabled(crtc, false); + if (crtc->state->self_refresh_active) + goto out; + mutex_lock(&vop->vop_lock); drm_crtc_vblank_off(crtc); - if (crtc->state->self_refresh_active) - goto out; - /* * Vop standby will take effect at end of current frame, * if dsp hold valid irq happen, it means standby complete. @@ -741,9 +741,9 @@ static void vop_crtc_atomic_disable(struct drm_crtc *crtc, vop_core_clks_disable(vop); pm_runtime_put(vop->dev); -out: mutex_unlock(&vop->vop_lock); +out: if (crtc->state->event && !crtc->state->active) { spin_lock_irq(&crtc->dev->event_lock); drm_crtc_send_vblank_event(crtc, crtc->state->event); diff --git a/drivers/gpu/drm/sun4i/sun4i_tcon.c b/drivers/gpu/drm/sun4i/sun4i_tcon.c index 9f06dec0fc61..bb43196d5d83 100644 --- a/drivers/gpu/drm/sun4i/sun4i_tcon.c +++ b/drivers/gpu/drm/sun4i/sun4i_tcon.c @@ -777,21 +777,19 @@ static irqreturn_t sun4i_tcon_handler(int irq, void *private) static int sun4i_tcon_init_clocks(struct device *dev, struct sun4i_tcon *tcon) { - tcon->clk = devm_clk_get(dev, "ahb"); + tcon->clk = devm_clk_get_enabled(dev, "ahb"); if (IS_ERR(tcon->clk)) { dev_err(dev, "Couldn't get the TCON bus clock\n"); return PTR_ERR(tcon->clk); } - clk_prepare_enable(tcon->clk); if (tcon->quirks->has_channel_0) { - tcon->sclk0 = devm_clk_get(dev, "tcon-ch0"); + tcon->sclk0 = devm_clk_get_enabled(dev, "tcon-ch0"); if (IS_ERR(tcon->sclk0)) { dev_err(dev, "Couldn't get the TCON channel 0 clock\n"); return PTR_ERR(tcon->sclk0); } } - clk_prepare_enable(tcon->sclk0); if (tcon->quirks->has_channel_1) { tcon->sclk1 = devm_clk_get(dev, "tcon-ch1"); @@ -804,12 +802,6 @@ static int sun4i_tcon_init_clocks(struct device *dev, return 0; } -static void sun4i_tcon_free_clocks(struct sun4i_tcon *tcon) -{ - clk_disable_unprepare(tcon->sclk0); - clk_disable_unprepare(tcon->clk); -} - static int sun4i_tcon_init_irq(struct device *dev, struct sun4i_tcon *tcon) { @@ -1224,14 +1216,14 @@ static int sun4i_tcon_bind(struct device *dev, struct device *master, ret = sun4i_tcon_init_regmap(dev, tcon); if (ret) { dev_err(dev, "Couldn't init our TCON regmap\n"); - goto err_free_clocks; + goto err_assert_reset; } if (tcon->quirks->has_channel_0) { ret = sun4i_dclk_create(dev, tcon); if (ret) { dev_err(dev, "Couldn't create our TCON dot clock\n"); - goto err_free_clocks; + goto err_assert_reset; } } @@ -1294,8 +1286,6 @@ static int sun4i_tcon_bind(struct device *dev, struct device *master, err_free_dotclock: if (tcon->quirks->has_channel_0) sun4i_dclk_free(tcon); -err_free_clocks: - sun4i_tcon_free_clocks(tcon); err_assert_reset: reset_control_assert(tcon->lcd_rst); return ret; @@ -1309,7 +1299,6 @@ static void sun4i_tcon_unbind(struct device *dev, struct device *master, list_del(&tcon->list); if (tcon->quirks->has_channel_0) sun4i_dclk_free(tcon); - sun4i_tcon_free_clocks(tcon); } static const struct component_ops sun4i_tcon_ops = { diff --git a/drivers/gpu/drm/ttm/ttm_bo.c b/drivers/gpu/drm/ttm/ttm_bo.c index 33e78f56123e..d5a2b69489e7 100644 --- a/drivers/gpu/drm/ttm/ttm_bo.c +++ b/drivers/gpu/drm/ttm/ttm_bo.c @@ -1187,6 +1187,7 @@ int ttm_bo_swapout(struct ttm_buffer_object *bo, struct ttm_operation_ctx *ctx, ret = ttm_bo_handle_move_mem(bo, evict_mem, true, &ctx, &hop); if (unlikely(ret != 0)) { WARN(ret == -EMULTIHOP, "Unexpected multihop in swaput - likely driver bug.\n"); + ttm_resource_free(bo, &evict_mem); goto out; } } diff --git a/drivers/hid/hid-logitech-hidpp.c b/drivers/hid/hid-logitech-hidpp.c index baa68ae9b9ef..c61da859cd3c 100644 --- a/drivers/hid/hid-logitech-hidpp.c +++ b/drivers/hid/hid-logitech-hidpp.c @@ -4295,7 +4295,7 @@ static const struct hid_device_id hidpp_devices[] = { { /* wireless touchpad T651 */ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_T651), - .driver_data = HIDPP_QUIRK_CLASS_WTP }, + .driver_data = HIDPP_QUIRK_CLASS_WTP | HIDPP_QUIRK_DELAYED_INIT }, { /* Mouse Logitech Anywhere MX */ LDJ_DEVICE(0x1017), .driver_data = HIDPP_QUIRK_HI_RES_SCROLL_1P0 }, { /* Mouse Logitech Cube */ diff --git a/drivers/hid/wacom_wac.c b/drivers/hid/wacom_wac.c index 5fd766ad6e45..02ca80f68d17 100644 --- a/drivers/hid/wacom_wac.c +++ b/drivers/hid/wacom_wac.c @@ -1314,7 +1314,7 @@ static void wacom_intuos_pro2_bt_pen(struct wacom_wac *wacom) struct input_dev *pen_input = wacom->pen_input; unsigned char *data = wacom->data; int number_of_valid_frames = 0; - int time_interval = 15000000; + ktime_t time_interval = 15000000; ktime_t time_packet_received = ktime_get(); int i; @@ -1348,7 +1348,7 @@ static void wacom_intuos_pro2_bt_pen(struct wacom_wac *wacom) if (number_of_valid_frames) { if (wacom->hid_data.time_delayed) time_interval = ktime_get() - wacom->hid_data.time_delayed; - time_interval /= number_of_valid_frames; + time_interval = div_u64(time_interval, number_of_valid_frames); wacom->hid_data.time_delayed = time_packet_received; } @@ -1359,7 +1359,7 @@ static void wacom_intuos_pro2_bt_pen(struct wacom_wac *wacom) bool range = frame[0] & 0x20; bool invert = frame[0] & 0x10; int frames_number_reversed = number_of_valid_frames - i - 1; - int event_timestamp = time_packet_received - frames_number_reversed * time_interval; + ktime_t event_timestamp = time_packet_received - frames_number_reversed * time_interval; if (!valid) continue; diff --git a/drivers/hid/wacom_wac.h b/drivers/hid/wacom_wac.h index dbf23e71aa72..db06084c4ed5 100644 --- a/drivers/hid/wacom_wac.h +++ b/drivers/hid/wacom_wac.h @@ -321,7 +321,7 @@ struct hid_data { int bat_connected; int ps_connected; bool pad_input_event_flag; - int time_delayed; + ktime_t time_delayed; }; struct wacom_remote_data { diff --git a/drivers/hwmon/gsc-hwmon.c b/drivers/hwmon/gsc-hwmon.c index f29ce49294da..89d036bf88df 100644 --- a/drivers/hwmon/gsc-hwmon.c +++ b/drivers/hwmon/gsc-hwmon.c @@ -82,8 +82,8 @@ static ssize_t pwm_auto_point_temp_store(struct device *dev, if (kstrtol(buf, 10, &temp)) return -EINVAL; - temp = clamp_val(temp, 0, 10000); - temp = DIV_ROUND_CLOSEST(temp, 10); + temp = clamp_val(temp, 0, 100000); + temp = DIV_ROUND_CLOSEST(temp, 100); regs[0] = temp & 0xff; regs[1] = (temp >> 8) & 0xff; @@ -100,7 +100,7 @@ static ssize_t pwm_auto_point_pwm_show(struct device *dev, { struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - return sprintf(buf, "%d\n", 255 * (50 + (attr->index * 10)) / 100); + return sprintf(buf, "%d\n", 255 * (50 + (attr->index * 10))); } static SENSOR_DEVICE_ATTR_RO(pwm1_auto_point1_pwm, pwm_auto_point_pwm, 0); diff --git a/drivers/hwmon/pmbus/adm1275.c b/drivers/hwmon/pmbus/adm1275.c index d311e0557401..b8543c06d022 100644 --- a/drivers/hwmon/pmbus/adm1275.c +++ b/drivers/hwmon/pmbus/adm1275.c @@ -37,10 +37,13 @@ enum chips { adm1075, adm1272, adm1275, adm1276, adm1278, adm1293, adm1294 }; #define ADM1272_IRANGE BIT(0) +#define ADM1278_TSFILT BIT(15) #define ADM1278_TEMP1_EN BIT(3) #define ADM1278_VIN_EN BIT(2) #define ADM1278_VOUT_EN BIT(1) +#define ADM1278_PMON_DEFCONFIG (ADM1278_VOUT_EN | ADM1278_TEMP1_EN | ADM1278_TSFILT) + #define ADM1293_IRANGE_25 0 #define ADM1293_IRANGE_50 BIT(6) #define ADM1293_IRANGE_100 BIT(7) @@ -462,6 +465,22 @@ static const struct i2c_device_id adm1275_id[] = { }; MODULE_DEVICE_TABLE(i2c, adm1275_id); +/* Enable VOUT & TEMP1 if not enabled (disabled by default) */ +static int adm1275_enable_vout_temp(struct i2c_client *client, int config) +{ + int ret; + + if ((config & ADM1278_PMON_DEFCONFIG) != ADM1278_PMON_DEFCONFIG) { + config |= ADM1278_PMON_DEFCONFIG; + ret = i2c_smbus_write_word_data(client, ADM1275_PMON_CONFIG, config); + if (ret < 0) { + dev_err(&client->dev, "Failed to enable VOUT/TEMP1 monitoring\n"); + return ret; + } + } + return 0; +} + static int adm1275_probe(struct i2c_client *client) { s32 (*config_read_fn)(const struct i2c_client *client, u8 reg); @@ -475,6 +494,7 @@ static int adm1275_probe(struct i2c_client *client) int vindex = -1, voindex = -1, cindex = -1, pindex = -1; int tindex = -1; u32 shunt; + u32 avg; if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_READ_BYTE_DATA @@ -614,19 +634,10 @@ static int adm1275_probe(struct i2c_client *client) PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT | PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP; - /* Enable VOUT & TEMP1 if not enabled (disabled by default) */ - if ((config & (ADM1278_VOUT_EN | ADM1278_TEMP1_EN)) != - (ADM1278_VOUT_EN | ADM1278_TEMP1_EN)) { - config |= ADM1278_VOUT_EN | ADM1278_TEMP1_EN; - ret = i2c_smbus_write_byte_data(client, - ADM1275_PMON_CONFIG, - config); - if (ret < 0) { - dev_err(&client->dev, - "Failed to enable VOUT monitoring\n"); - return -ENODEV; - } - } + ret = adm1275_enable_vout_temp(client, config); + if (ret) + return ret; + if (config & ADM1278_VIN_EN) info->func[0] |= PMBUS_HAVE_VIN; break; @@ -683,19 +694,9 @@ static int adm1275_probe(struct i2c_client *client) PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT | PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP; - /* Enable VOUT & TEMP1 if not enabled (disabled by default) */ - if ((config & (ADM1278_VOUT_EN | ADM1278_TEMP1_EN)) != - (ADM1278_VOUT_EN | ADM1278_TEMP1_EN)) { - config |= ADM1278_VOUT_EN | ADM1278_TEMP1_EN; - ret = i2c_smbus_write_byte_data(client, - ADM1275_PMON_CONFIG, - config); - if (ret < 0) { - dev_err(&client->dev, - "Failed to enable VOUT monitoring\n"); - return -ENODEV; - } - } + ret = adm1275_enable_vout_temp(client, config); + if (ret) + return ret; if (config & ADM1278_VIN_EN) info->func[0] |= PMBUS_HAVE_VIN; @@ -756,6 +757,43 @@ static int adm1275_probe(struct i2c_client *client) return -ENODEV; } + if (data->have_power_sampling && + of_property_read_u32(client->dev.of_node, + "adi,power-sample-average", &avg) == 0) { + if (!avg || avg > ADM1275_SAMPLES_AVG_MAX || + BIT(__fls(avg)) != avg) { + dev_err(&client->dev, + "Invalid number of power samples"); + return -EINVAL; + } + ret = adm1275_write_pmon_config(data, client, true, + ilog2(avg)); + if (ret < 0) { + dev_err(&client->dev, + "Setting power sample averaging failed with error %d", + ret); + return ret; + } + } + + if (of_property_read_u32(client->dev.of_node, + "adi,volt-curr-sample-average", &avg) == 0) { + if (!avg || avg > ADM1275_SAMPLES_AVG_MAX || + BIT(__fls(avg)) != avg) { + dev_err(&client->dev, + "Invalid number of voltage/current samples"); + return -EINVAL; + } + ret = adm1275_write_pmon_config(data, client, false, + ilog2(avg)); + if (ret < 0) { + dev_err(&client->dev, + "Setting voltage and current sample averaging failed with error %d", + ret); + return ret; + } + } + if (voindex < 0) voindex = vindex; if (vindex >= 0) { diff --git a/drivers/hwtracing/coresight/coresight-core.c b/drivers/hwtracing/coresight/coresight-core.c index b6d9eb502a27..a54d6ea142cd 100644 --- a/drivers/hwtracing/coresight/coresight-core.c +++ b/drivers/hwtracing/coresight/coresight-core.c @@ -1681,13 +1681,8 @@ static int coresight_remove_match(struct device *dev, void *data) if (csdev->dev.fwnode == conn->child_fwnode) { iterator->orphan = true; coresight_remove_links(iterator, conn); - /* - * Drop the reference to the handle for the remote - * device acquired in parsing the connections from - * platform data. - */ - fwnode_handle_put(conn->child_fwnode); - conn->child_fwnode = NULL; + + conn->child_dev = NULL; /* No need to continue */ break; } diff --git a/drivers/i2c/busses/i2c-msm-geni.c b/drivers/i2c/busses/i2c-msm-geni.c index 580a5650024d..9eb3060011ee 100644 --- a/drivers/i2c/busses/i2c-msm-geni.c +++ b/drivers/i2c/busses/i2c-msm-geni.c @@ -70,7 +70,6 @@ #define I2C_ADDR_NACK 11 #define I2C_DATA_NACK 12 #define GENI_M_CMD_FAILURE 13 -#define GENI_M_CANCEL_DONE 14 #define GENI_HW_PARAM 0x50 @@ -224,7 +223,6 @@ static struct geni_i2c_err_log gi2c_log[] = { [GENI_TIMEOUT] = {-ETIMEDOUT, "I2C TXN timed out"}, [GENI_SPURIOUS_IRQ] = {-EINVAL, "Received unexpected interrupt"}, [GENI_M_CMD_FAILURE] = {-EINVAL, "Master command failure"}, - [GENI_M_CANCEL_DONE] = {-EINVAL, "Master cancel done"}, }; struct geni_i2c_clk_fld { @@ -754,10 +752,13 @@ static irqreturn_t geni_i2c_irq(int irq, void *dev) (m_stat & M_GP_IRQ_3_EN) || (m_stat & M_GP_IRQ_4_EN)) { if (m_stat & M_GP_IRQ_1_EN) { - if (readl_relaxed(gi2c->base + SE_GENI_M_GP_LENGTH)) - geni_i2c_err(gi2c, I2C_DATA_NACK); - else + if (readl_relaxed(gi2c->base + SE_GENI_M_GP_LENGTH)) { + /* only process for write operation. */ + if (!(gi2c->cur->flags & I2C_M_RD)) + geni_i2c_err(gi2c, I2C_DATA_NACK); + } else { geni_i2c_err(gi2c, I2C_ADDR_NACK); + } } if (m_stat & M_GP_IRQ_3_EN) geni_i2c_err(gi2c, I2C_BUS_PROTO); @@ -769,12 +770,23 @@ static irqreturn_t geni_i2c_irq(int irq, void *dev) geni_i2c_err(gi2c, GENI_ILLEGAL_CMD); if (m_stat & M_CMD_ABORT_EN) geni_i2c_err(gi2c, GENI_ABORT_DONE); - if (m_stat & M_CMD_FAILURE_EN) - geni_i2c_err(gi2c, GENI_M_CMD_FAILURE); - if (m_stat & M_CMD_CANCEL_EN) { - geni_i2c_err(gi2c, GENI_M_CANCEL_DONE); - m_cancel_done = true; + + /* This bit(M_CMD_FAILURE_EN) is set when command execution has been + * completed with failure. + */ + if (m_stat & M_CMD_FAILURE_EN) { + /* Log error else do not override previous set error */ + if (!gi2c->err) + geni_i2c_err(gi2c, GENI_M_CMD_FAILURE); + else + I2C_LOG_DBG(gi2c->ipcl, false, gi2c->dev, + "%s:GENI_M_CMD_FAILURE\n", __func__); } + + /* This bit is set when command cancel request by SW is completed */ + if (m_stat & M_CMD_CANCEL_EN) + m_cancel_done = true; + gi2c->cmd_done = true; is_clear_watermark = true; goto irqret; @@ -834,10 +846,13 @@ static void gi2c_ev_cb(struct dma_chan *ch, struct msm_gpi_cb const *cb_str, break; case MSM_GPI_QUP_NOTIFY: if (m_stat & M_GP_IRQ_1_EN) { - if (readl_relaxed(gi2c->base + SE_GENI_M_GP_LENGTH)) - geni_i2c_err(gi2c, I2C_DATA_NACK); - else + if (readl_relaxed(gi2c->base + SE_GENI_M_GP_LENGTH)) { + /* only process for write operation. */ + if (!(gi2c->cur->flags & I2C_M_RD)) + geni_i2c_err(gi2c, I2C_DATA_NACK); + } else { geni_i2c_err(gi2c, I2C_ADDR_NACK); + } } if (m_stat & M_GP_IRQ_3_EN) geni_i2c_err(gi2c, I2C_BUS_PROTO); @@ -868,10 +883,13 @@ static void gi2c_gsi_cb_err(struct msm_gpi_dma_async_tx_cb_param *cb, "%s TCE Unexpected Err, stat:0x%x\n", xfer, cb->status); if (cb->status & (BIT(GP_IRQ1) << 5)) { - if (readl_relaxed(gi2c->base + SE_GENI_M_GP_LENGTH)) - geni_i2c_err(gi2c, I2C_DATA_NACK); - else + if (readl_relaxed(gi2c->base + SE_GENI_M_GP_LENGTH)) { + /* only process for write operation. */ + if (!(gi2c->cur->flags & I2C_M_RD)) + geni_i2c_err(gi2c, I2C_DATA_NACK); + } else { geni_i2c_err(gi2c, I2C_ADDR_NACK); + } } if (cb->status & (BIT(GP_IRQ3) << 5)) geni_i2c_err(gi2c, I2C_BUS_PROTO); @@ -1831,6 +1849,98 @@ static int get_geni_se_i2c_hub(struct geni_i2c_dev *gi2c) } #endif +/** + * geni_i2c_resources_init: initialize clk, icc vote, read dt property + * @pdev: Platform driver handle + * @gi2c: geni i2c structure as a pointer + * + * Function to initialize clock and icc vote configuration and read require + * DTSI property. + * + * Return: 0 on success OR negative error code for failure. + */ +static int geni_i2c_resources_init(struct platform_device *pdev, struct geni_i2c_dev *gi2c) +{ + int ret; + + /* + * For LE, clocks, gpio and icb voting will be provided by + * LA. The I2C operates in GSI mode only for LE usecase, + * se irq not required. Below properties will not be present + * in I2C LE dt. + */ + if (gi2c->is_le_vm) + return 0; + + gi2c->i2c_rsc.clk = devm_clk_get(&pdev->dev, "se-clk"); + if (IS_ERR(gi2c->i2c_rsc.clk)) { + ret = PTR_ERR(gi2c->i2c_rsc.clk); + dev_err(&pdev->dev, "Err getting SE Core clk %d\n", ret); + return ret; + } + + gi2c->m_ahb_clk = devm_clk_get(gi2c->dev->parent, "m-ahb"); + if (IS_ERR(gi2c->m_ahb_clk)) { + ret = PTR_ERR(gi2c->m_ahb_clk); + dev_err(&pdev->dev, "Err getting M AHB clk %d\n", ret); + return ret; + } + + gi2c->s_ahb_clk = devm_clk_get(gi2c->dev->parent, "s-ahb"); + if (IS_ERR(gi2c->s_ahb_clk)) { + ret = PTR_ERR(gi2c->s_ahb_clk); + dev_err(&pdev->dev, "Err getting S AHB clk %d\n", ret); + return ret; + } + + gi2c->is_i2c_hub = of_property_read_bool(pdev->dev.of_node, "qcom,i2c-hub"); + /* + * For I2C_HUB, qup-ddr voting not required and + * core clk should be voted explicitly. + */ + if (gi2c->is_i2c_hub) { + gi2c->core_clk = devm_clk_get(&pdev->dev, "core-clk"); + if (IS_ERR(gi2c->core_clk)) { + ret = PTR_ERR(gi2c->core_clk); + dev_err(&pdev->dev, "Err getting core-clk %d\n", ret); + return ret; + } + ret = geni_icc_get(&gi2c->i2c_rsc, NULL); + if (ret) { + dev_err(&pdev->dev, "%s: Error - geni_icc_get ret:%d\n", __func__, ret); + return ret; + } + gi2c->i2c_rsc.icc_paths[GENI_TO_CORE].avg_bw = GENI_DEFAULT_BW; + gi2c->i2c_rsc.icc_paths[CPU_TO_GENI].avg_bw = GENI_DEFAULT_BW; + + /* For I2C HUB, we don't have HW reg to identify RTL/SW base SE. + * Hence setting flag for all I2C HUB instances. + */ + gi2c->is_i2c_rtl_based = true; + dev_info(gi2c->dev, "%s: RTL based SE\n", __func__); + } else { + ret = geni_se_common_resources_init(&gi2c->i2c_rsc, + GENI_DEFAULT_BW, GENI_DEFAULT_BW, + (DEFAULT_SE_CLK * DEFAULT_BUS_WIDTH)); + if (ret) { + dev_err(&pdev->dev, "%s: Error - resources_init ret:%d\n", __func__, ret); + return ret; + } + } + + gi2c->irq = platform_get_irq(pdev, 0); + if (gi2c->irq < 0) + return gi2c->irq; + + irq_set_status_flags(gi2c->irq, IRQ_NOAUTOEN); + ret = devm_request_irq(gi2c->dev, gi2c->irq, geni_i2c_irq, 0, "i2c_geni", gi2c); + if (ret) { + dev_err(gi2c->dev, "Request_irq failed:%d: err:%d\n", gi2c->irq, ret); + return ret; + } + + return 0; +} static int geni_i2c_probe(struct platform_device *pdev) { struct geni_i2c_dev *gi2c; @@ -1906,80 +2016,9 @@ static int geni_i2c_probe(struct platform_device *pdev) * se irq not required. Below properties will not be present * in I2C LE dt. */ - if (!gi2c->is_le_vm) { - gi2c->i2c_rsc.clk = devm_clk_get(&pdev->dev, "se-clk"); - if (IS_ERR(gi2c->i2c_rsc.clk)) { - ret = PTR_ERR(gi2c->i2c_rsc.clk); - dev_err(&pdev->dev, "Err getting SE Core clk %d\n", - ret); - return ret; - } - - gi2c->m_ahb_clk = devm_clk_get(dev->parent, "m-ahb"); - if (IS_ERR(gi2c->m_ahb_clk)) { - ret = PTR_ERR(gi2c->m_ahb_clk); - dev_err(&pdev->dev, "Err getting M AHB clk %d\n", ret); - return ret; - } - - gi2c->s_ahb_clk = devm_clk_get(dev->parent, "s-ahb"); - if (IS_ERR(gi2c->s_ahb_clk)) { - ret = PTR_ERR(gi2c->s_ahb_clk); - dev_err(&pdev->dev, "Err getting S AHB clk %d\n", ret); - return ret; - } - - gi2c->is_i2c_hub = of_property_read_bool(pdev->dev.of_node, - "qcom,i2c-hub"); - /* - * For I2C_HUB, qup-ddr voting not required and - * core clk should be voted explicitly. - */ - if (gi2c->is_i2c_hub) { - gi2c->core_clk = devm_clk_get(&pdev->dev, "core-clk"); - if (IS_ERR(gi2c->core_clk)) { - ret = PTR_ERR(gi2c->core_clk); - dev_err(&pdev->dev, "Err getting core-clk %d\n", ret); - return ret; - } - ret = geni_icc_get(&gi2c->i2c_rsc, NULL); - if (ret) { - dev_err(&pdev->dev, "%s: Error - geni_icc_get ret:%d\n", - __func__, ret); - return ret; - } - gi2c->i2c_rsc.icc_paths[GENI_TO_CORE].avg_bw = GENI_DEFAULT_BW; - gi2c->i2c_rsc.icc_paths[CPU_TO_GENI].avg_bw = GENI_DEFAULT_BW; - - /* For I2C HUB, we don't have HW reg to identify RTL/SW base SE. - * Hence setting flag for all I2C HUB instances. - */ - gi2c->is_i2c_rtl_based = true; - dev_info(gi2c->dev, "%s: RTL based SE\n", __func__); - } else { - ret = geni_se_common_resources_init(&gi2c->i2c_rsc, - GENI_DEFAULT_BW, GENI_DEFAULT_BW, - (DEFAULT_SE_CLK * DEFAULT_BUS_WIDTH)); - if (ret) { - dev_err(&pdev->dev, "%s: Error - resources_init ret:%d\n", - __func__, ret); - return ret; - } - } - - gi2c->irq = platform_get_irq(pdev, 0); - if (gi2c->irq < 0) - return gi2c->irq; - - irq_set_status_flags(gi2c->irq, IRQ_NOAUTOEN); - ret = devm_request_irq(gi2c->dev, gi2c->irq, geni_i2c_irq, - 0, "i2c_geni", gi2c); - if (ret) { - dev_err(gi2c->dev, "Request_irq failed:%d: err:%d\n", - gi2c->irq, ret); - return ret; - } - } + ret = geni_i2c_resources_init(pdev, gi2c); + if (ret) + return ret; if (of_property_read_bool(pdev->dev.of_node, "qcom,shared")) { gi2c->is_shared = true; diff --git a/drivers/i2c/busses/i2c-msm-v2.c b/drivers/i2c/busses/i2c-msm-v2.c index 502466581342..4ff3d18541ae 100644 --- a/drivers/i2c/busses/i2c-msm-v2.c +++ b/drivers/i2c/busses/i2c-msm-v2.c @@ -1817,12 +1817,12 @@ static irqreturn_t i2c_msm_qup_isr(int irq, void *devid) * State reset */ wmb(); - usleep_range(100, 101); + udelay(100); state = readl_relaxed(ctrl->rsrcs.base + QUP_STATE); while (!(state & QUP_I2C_FLUSH)) { state = readl_relaxed(ctrl->rsrcs.base + QUP_STATE); - usleep_range(50, 51); + udelay(50); if (++temp_cnt >= 500) break; } diff --git a/drivers/i2c/busses/i2c-qup.c b/drivers/i2c/busses/i2c-qup.c index fcd35e8de83c..b89eca2398d9 100644 --- a/drivers/i2c/busses/i2c-qup.c +++ b/drivers/i2c/busses/i2c-qup.c @@ -1752,16 +1752,21 @@ nodma: if (!clk_freq || clk_freq > I2C_MAX_FAST_MODE_PLUS_FREQ) { dev_err(qup->dev, "clock frequency not supported %d\n", clk_freq); - return -EINVAL; + ret = -EINVAL; + goto fail_dma; } qup->base = devm_platform_ioremap_resource(pdev, 0); - if (IS_ERR(qup->base)) - return PTR_ERR(qup->base); + if (IS_ERR(qup->base)) { + ret = PTR_ERR(qup->base); + goto fail_dma; + } qup->irq = platform_get_irq(pdev, 0); - if (qup->irq < 0) - return qup->irq; + if (qup->irq < 0) { + ret = qup->irq; + goto fail_dma; + } if (has_acpi_companion(qup->dev)) { ret = device_property_read_u32(qup->dev, @@ -1775,13 +1780,15 @@ nodma: qup->clk = devm_clk_get(qup->dev, "core"); if (IS_ERR(qup->clk)) { dev_err(qup->dev, "Could not get core clock\n"); - return PTR_ERR(qup->clk); + ret = PTR_ERR(qup->clk); + goto fail_dma; } qup->pclk = devm_clk_get(qup->dev, "iface"); if (IS_ERR(qup->pclk)) { dev_err(qup->dev, "Could not get iface clock\n"); - return PTR_ERR(qup->pclk); + ret = PTR_ERR(qup->pclk); + goto fail_dma; } qup_i2c_enable_clocks(qup); src_clk_freq = clk_get_rate(qup->clk); diff --git a/drivers/i2c/busses/i2c-xiic.c b/drivers/i2c/busses/i2c-xiic.c index 34b8da949462..9652e8bea2d0 100644 --- a/drivers/i2c/busses/i2c-xiic.c +++ b/drivers/i2c/busses/i2c-xiic.c @@ -375,6 +375,9 @@ static irqreturn_t xiic_process(int irq, void *dev_id) struct xiic_i2c *i2c = dev_id; u32 pend, isr, ier; u32 clr = 0; + int xfer_more = 0; + int wakeup_req = 0; + int wakeup_code = 0; /* Get the interrupt Status from the IPIF. There is no clearing of * interrupts in the IPIF. Interrupts must be cleared at the source. @@ -411,10 +414,16 @@ static irqreturn_t xiic_process(int irq, void *dev_id) */ xiic_reinit(i2c); - if (i2c->rx_msg) - xiic_wakeup(i2c, STATE_ERROR); - if (i2c->tx_msg) - xiic_wakeup(i2c, STATE_ERROR); + if (i2c->rx_msg) { + wakeup_req = 1; + wakeup_code = STATE_ERROR; + } + if (i2c->tx_msg) { + wakeup_req = 1; + wakeup_code = STATE_ERROR; + } + /* don't try to handle other events */ + goto out; } if (pend & XIIC_INTR_RX_FULL_MASK) { /* Receive register/FIFO is full */ @@ -448,8 +457,7 @@ static irqreturn_t xiic_process(int irq, void *dev_id) i2c->tx_msg++; dev_dbg(i2c->adap.dev.parent, "%s will start next...\n", __func__); - - __xiic_start_xfer(i2c); + xfer_more = 1; } } } @@ -463,11 +471,13 @@ static irqreturn_t xiic_process(int irq, void *dev_id) if (!i2c->tx_msg) goto out; - if ((i2c->nmsgs == 1) && !i2c->rx_msg && - xiic_tx_space(i2c) == 0) - xiic_wakeup(i2c, STATE_DONE); + wakeup_req = 1; + + if (i2c->nmsgs == 1 && !i2c->rx_msg && + xiic_tx_space(i2c) == 0) + wakeup_code = STATE_DONE; else - xiic_wakeup(i2c, STATE_ERROR); + wakeup_code = STATE_ERROR; } if (pend & (XIIC_INTR_TX_EMPTY_MASK | XIIC_INTR_TX_HALF_MASK)) { /* Transmit register/FIFO is empty or ½ empty */ @@ -491,7 +501,7 @@ static irqreturn_t xiic_process(int irq, void *dev_id) if (i2c->nmsgs > 1) { i2c->nmsgs--; i2c->tx_msg++; - __xiic_start_xfer(i2c); + xfer_more = 1; } else { xiic_irq_dis(i2c, XIIC_INTR_TX_HALF_MASK); @@ -509,6 +519,13 @@ out: dev_dbg(i2c->adap.dev.parent, "%s clr: 0x%x\n", __func__, clr); xiic_setreg32(i2c, XIIC_IISR_OFFSET, clr); + if (xfer_more) + __xiic_start_xfer(i2c); + if (wakeup_req) + xiic_wakeup(i2c, wakeup_code); + + WARN_ON(xfer_more && wakeup_req); + mutex_unlock(&i2c->lock); return IRQ_HANDLED; } diff --git a/drivers/iio/accel/fxls8962af-core.c b/drivers/iio/accel/fxls8962af-core.c index a2d29cabb389..548a8c4269e7 100644 --- a/drivers/iio/accel/fxls8962af-core.c +++ b/drivers/iio/accel/fxls8962af-core.c @@ -486,8 +486,7 @@ static int fxls8962af_set_watermark(struct iio_dev *indio_dev, unsigned val) .sign = 's', \ .realbits = 12, \ .storagebits = 16, \ - .shift = 4, \ - .endianness = IIO_BE, \ + .endianness = IIO_LE, \ }, \ } @@ -656,9 +655,10 @@ static int fxls8962af_fifo_transfer(struct fxls8962af_data *data, int total_length = samples * sample_length; int ret; - if (i2c_verify_client(dev)) + if (i2c_verify_client(dev) && + data->chip_info->chip_id == FXLS8962AF_DEVICE_ID) /* - * Due to errata bug: + * Due to errata bug (only applicable on fxls8962af): * E3: FIFO burst read operation error using I2C interface * We have to avoid burst reads on I2C.. */ diff --git a/drivers/iio/adc/ad7192.c b/drivers/iio/adc/ad7192.c index 4b6b7bc86100..6df435e3c421 100644 --- a/drivers/iio/adc/ad7192.c +++ b/drivers/iio/adc/ad7192.c @@ -327,7 +327,7 @@ static int ad7192_of_clock_select(struct ad7192_state *st) clock_sel = AD7192_CLK_INT; /* use internal clock */ - if (st->mclk) { + if (!st->mclk) { if (of_property_read_bool(np, "adi,int-clock-output-enable")) clock_sel = AD7192_CLK_INT_CO; } else { @@ -340,9 +340,9 @@ static int ad7192_of_clock_select(struct ad7192_state *st) return clock_sel; } -static int ad7192_setup(struct ad7192_state *st, struct device_node *np) +static int ad7192_setup(struct iio_dev *indio_dev, struct device_node *np) { - struct iio_dev *indio_dev = spi_get_drvdata(st->sd.spi); + struct ad7192_state *st = iio_priv(indio_dev); bool rej60_en, refin2_en; bool buf_en, bipolar, burnout_curr_en; unsigned long long scale_uv; @@ -1015,7 +1015,7 @@ static int ad7192_probe(struct spi_device *spi) } } - ret = ad7192_setup(st, spi->dev.of_node); + ret = ad7192_setup(indio_dev, spi->dev.of_node); if (ret) return ret; diff --git a/drivers/iio/adc/meson_saradc.c b/drivers/iio/adc/meson_saradc.c index 705d5e11a54b..36ec07ad7017 100644 --- a/drivers/iio/adc/meson_saradc.c +++ b/drivers/iio/adc/meson_saradc.c @@ -71,7 +71,7 @@ #define MESON_SAR_ADC_REG3_PANEL_DETECT_COUNT_MASK GENMASK(20, 18) #define MESON_SAR_ADC_REG3_PANEL_DETECT_FILTER_TB_MASK GENMASK(17, 16) #define MESON_SAR_ADC_REG3_ADC_CLK_DIV_SHIFT 10 - #define MESON_SAR_ADC_REG3_ADC_CLK_DIV_WIDTH 5 + #define MESON_SAR_ADC_REG3_ADC_CLK_DIV_WIDTH 6 #define MESON_SAR_ADC_REG3_BLOCK_DLY_SEL_MASK GENMASK(9, 8) #define MESON_SAR_ADC_REG3_BLOCK_DLY_MASK GENMASK(7, 0) diff --git a/drivers/iio/adc/qcom-spmi-adc5-gen3.c b/drivers/iio/adc/qcom-spmi-adc5-gen3.c index 72df9eb6bd9f..956465619455 100644 --- a/drivers/iio/adc/qcom-spmi-adc5-gen3.c +++ b/drivers/iio/adc/qcom-spmi-adc5-gen3.c @@ -21,6 +21,7 @@ #include #include #include +#include #include #include @@ -1862,9 +1863,27 @@ static void adc5_gen3_shutdown(struct platform_device *pdev) } } +static int adc5_gen3_suspend(struct device *dev) +{ + if (pm_suspend_via_firmware()) + return adc5_gen3_freeze(dev); + + return 0; +} + +static int adc5_gen3_resume(struct device *dev) +{ + if (pm_suspend_via_firmware()) + return adc5_gen3_restore(dev); + + return 0; +} + static const struct dev_pm_ops adc5_gen3_pm_ops = { .freeze = adc5_gen3_freeze, .restore = adc5_gen3_restore, + .suspend = adc5_gen3_suspend, + .resume = adc5_gen3_resume, }; static struct platform_driver adc5_gen3_driver = { diff --git a/drivers/iio/proximity/inv_ch101/ch101_i2c.c b/drivers/iio/proximity/inv_ch101/ch101_i2c.c index 88141d9a2ec5..1eee70f17f87 100644 --- a/drivers/iio/proximity/inv_ch101/ch101_i2c.c +++ b/drivers/iio/proximity/inv_ch101/ch101_i2c.c @@ -26,6 +26,9 @@ #include "ch101_reg.h" #define SX1508_DEVICE_ID "sx1508q" +#define CH101_DEFER_PROBE_CNT 10 + +u8 ch101_deferred_probe_cnt; // Device tree RP4 // @@ -319,6 +322,19 @@ static int ch101_i2c_probe(struct i2c_client *client, dev = &client->dev; + gpio = get_gpio_exp(); + if (!gpio) { + ch101_deferred_probe_cnt++; + if (ch101_deferred_probe_cnt > CH101_DEFER_PROBE_CNT) { + dev_err(dev, "Error initializing expander: %s\n", + SX1508_DEVICE_ID); + return -ENODEV; + } + dev_info(dev, "Wait initializing expander: %s retry %d\n", + SX1508_DEVICE_ID, ch101_deferred_probe_cnt); + return -EPROBE_DEFER; + } + cbk = devm_kmalloc(dev, sizeof(struct ch101_callbacks), GFP_KERNEL); if (!cbk) return -ENOMEM; @@ -331,13 +347,6 @@ static int ch101_i2c_probe(struct i2c_client *client, dev_info(dev, "%s: IRQ: %d\n", __func__, irq); - gpio = get_gpio_exp(); - if (!gpio) { - dev_err(dev, "Error initializing expander: %s\n", - SX1508_DEVICE_ID); - return -ENODEV; - } - cbk->read_reg = read_reg; cbk->write_reg = write_reg; cbk->read_sync = read_sync; diff --git a/drivers/infiniband/hw/bnxt_re/main.c b/drivers/infiniband/hw/bnxt_re/main.c index 66268e41b470..7b85eef113fc 100644 --- a/drivers/infiniband/hw/bnxt_re/main.c +++ b/drivers/infiniband/hw/bnxt_re/main.c @@ -331,15 +331,21 @@ static void bnxt_re_start_irq(void *handle, struct bnxt_msix_entry *ent) for (indx = 0; indx < rdev->num_msix; indx++) rdev->msix_entries[indx].vector = ent[indx].vector; - bnxt_qplib_rcfw_start_irq(rcfw, msix_ent[BNXT_RE_AEQ_IDX].vector, - false); + rc = bnxt_qplib_rcfw_start_irq(rcfw, msix_ent[BNXT_RE_AEQ_IDX].vector, + false); + if (rc) { + ibdev_warn(&rdev->ibdev, "Failed to reinit CREQ\n"); + return; + } for (indx = BNXT_RE_NQ_IDX ; indx < rdev->num_msix; indx++) { nq = &rdev->nq[indx - 1]; rc = bnxt_qplib_nq_start_irq(nq, indx - 1, msix_ent[indx].vector, false); - if (rc) + if (rc) { ibdev_warn(&rdev->ibdev, "Failed to reinit NQ index %d\n", indx - 1); + return; + } } } @@ -1173,12 +1179,6 @@ static int bnxt_re_update_gid(struct bnxt_re_dev *rdev) if (!ib_device_try_get(&rdev->ibdev)) return 0; - if (!sgid_tbl) { - ibdev_err(&rdev->ibdev, "QPLIB: SGID table not allocated"); - rc = -EINVAL; - goto out; - } - for (index = 0; index < sgid_tbl->active; index++) { gid_idx = sgid_tbl->hw_id[index]; @@ -1196,7 +1196,7 @@ static int bnxt_re_update_gid(struct bnxt_re_dev *rdev) rc = bnxt_qplib_update_sgid(sgid_tbl, &gid, gid_idx, rdev->qplib_res.netdev->dev_addr); } -out: + ib_device_put(&rdev->ibdev); return rc; } diff --git a/drivers/infiniband/hw/bnxt_re/qplib_fp.c b/drivers/infiniband/hw/bnxt_re/qplib_fp.c index b26a89187a19..d44b6a5c90b5 100644 --- a/drivers/infiniband/hw/bnxt_re/qplib_fp.c +++ b/drivers/infiniband/hw/bnxt_re/qplib_fp.c @@ -404,6 +404,9 @@ static irqreturn_t bnxt_qplib_nq_irq(int irq, void *dev_instance) void bnxt_qplib_nq_stop_irq(struct bnxt_qplib_nq *nq, bool kill) { + if (!nq->requested) + return; + tasklet_disable(&nq->nq_tasklet); /* Mask h/w interrupt */ bnxt_qplib_ring_nq_db(&nq->nq_db.dbinfo, nq->res->cctx, false); @@ -411,11 +414,12 @@ void bnxt_qplib_nq_stop_irq(struct bnxt_qplib_nq *nq, bool kill) synchronize_irq(nq->msix_vec); if (kill) tasklet_kill(&nq->nq_tasklet); - if (nq->requested) { - irq_set_affinity_hint(nq->msix_vec, NULL); - free_irq(nq->msix_vec, nq); - nq->requested = false; - } + + irq_set_affinity_hint(nq->msix_vec, NULL); + free_irq(nq->msix_vec, nq); + kfree(nq->name); + nq->name = NULL; + nq->requested = false; } void bnxt_qplib_disable_nq(struct bnxt_qplib_nq *nq) @@ -441,6 +445,7 @@ void bnxt_qplib_disable_nq(struct bnxt_qplib_nq *nq) int bnxt_qplib_nq_start_irq(struct bnxt_qplib_nq *nq, int nq_indx, int msix_vector, bool need_init) { + struct bnxt_qplib_res *res = nq->res; int rc; if (nq->requested) @@ -452,10 +457,17 @@ int bnxt_qplib_nq_start_irq(struct bnxt_qplib_nq *nq, int nq_indx, else tasklet_enable(&nq->nq_tasklet); - snprintf(nq->name, sizeof(nq->name), "bnxt_qplib_nq-%d", nq_indx); + nq->name = kasprintf(GFP_KERNEL, "bnxt_re-nq-%d@pci:%s", + nq_indx, pci_name(res->pdev)); + if (!nq->name) + return -ENOMEM; rc = request_irq(nq->msix_vec, bnxt_qplib_nq_irq, 0, nq->name, nq); - if (rc) + if (rc) { + kfree(nq->name); + nq->name = NULL; + tasklet_disable(&nq->nq_tasklet); return rc; + } cpumask_clear(&nq->mask); cpumask_set_cpu(nq_indx, &nq->mask); @@ -466,7 +478,7 @@ int bnxt_qplib_nq_start_irq(struct bnxt_qplib_nq *nq, int nq_indx, nq->msix_vec, nq_indx); } nq->requested = true; - bnxt_qplib_ring_nq_db(&nq->nq_db.dbinfo, nq->res->cctx, true); + bnxt_qplib_ring_nq_db(&nq->nq_db.dbinfo, res->cctx, true); return rc; } @@ -1599,7 +1611,7 @@ static int bnxt_qplib_put_inline(struct bnxt_qplib_qp *qp, il_src = (void *)wqe->sg_list[indx].addr; t_len += len; if (t_len > qp->max_inline_data) - goto bad; + return -ENOMEM; while (len) { if (pull_dst) { pull_dst = false; @@ -1623,8 +1635,6 @@ static int bnxt_qplib_put_inline(struct bnxt_qplib_qp *qp, } return t_len; -bad: - return -ENOMEM; } static u32 bnxt_qplib_put_sges(struct bnxt_qplib_hwq *hwq, @@ -2054,7 +2064,7 @@ int bnxt_qplib_create_cq(struct bnxt_qplib_res *res, struct bnxt_qplib_cq *cq) hwq_attr.sginfo = &cq->sg_info; rc = bnxt_qplib_alloc_init_hwq(&cq->hwq, &hwq_attr); if (rc) - goto exit; + return rc; RCFW_CMD_PREP(req, CREATE_CQ, cmd_flags); @@ -2095,7 +2105,6 @@ int bnxt_qplib_create_cq(struct bnxt_qplib_res *res, struct bnxt_qplib_cq *cq) fail: bnxt_qplib_free_hwq(res, &cq->hwq); -exit: return rc; } @@ -2723,11 +2732,8 @@ static int bnxt_qplib_cq_process_terminal(struct bnxt_qplib_cq *cq, qp = (struct bnxt_qplib_qp *)((unsigned long) le64_to_cpu(hwcqe->qp_handle)); - if (!qp) { - dev_err(&cq->hwq.pdev->dev, - "FP: CQ Process terminal qp is NULL\n"); + if (!qp) return -EINVAL; - } /* Must block new posting of SQ and RQ */ qp->state = CMDQ_MODIFY_QP_NEW_STATE_ERR; diff --git a/drivers/infiniband/hw/bnxt_re/qplib_fp.h b/drivers/infiniband/hw/bnxt_re/qplib_fp.h index 037501952543..f859710f9a7f 100644 --- a/drivers/infiniband/hw/bnxt_re/qplib_fp.h +++ b/drivers/infiniband/hw/bnxt_re/qplib_fp.h @@ -471,7 +471,7 @@ typedef int (*srqn_handler_t)(struct bnxt_qplib_nq *nq, struct bnxt_qplib_nq { struct pci_dev *pdev; struct bnxt_qplib_res *res; - char name[32]; + char *name; struct bnxt_qplib_hwq hwq; struct bnxt_qplib_nq_db nq_db; u16 ring_id; diff --git a/drivers/infiniband/hw/bnxt_re/qplib_rcfw.c b/drivers/infiniband/hw/bnxt_re/qplib_rcfw.c index d2d39126f185..3b8cb46551bf 100644 --- a/drivers/infiniband/hw/bnxt_re/qplib_rcfw.c +++ b/drivers/infiniband/hw/bnxt_re/qplib_rcfw.c @@ -181,7 +181,7 @@ static int __send_message(struct bnxt_qplib_rcfw *rcfw, struct cmdq_base *req, } while (size > 0); cmdq->seq_num++; - cmdq_prod = hwq->prod; + cmdq_prod = hwq->prod & 0xFFFF; if (test_bit(FIRMWARE_FIRST_FLAG, &cmdq->flags)) { /* The very first doorbell write * is required to set this flag @@ -299,7 +299,8 @@ static int bnxt_qplib_process_func_event(struct bnxt_qplib_rcfw *rcfw, } static int bnxt_qplib_process_qp_event(struct bnxt_qplib_rcfw *rcfw, - struct creq_qp_event *qp_event) + struct creq_qp_event *qp_event, + u32 *num_wait) { struct creq_qp_error_notification *err_event; struct bnxt_qplib_hwq *hwq = &rcfw->cmdq.hwq; @@ -308,6 +309,7 @@ static int bnxt_qplib_process_qp_event(struct bnxt_qplib_rcfw *rcfw, u16 cbit, blocked = 0; struct pci_dev *pdev; unsigned long flags; + u32 wait_cmds = 0; __le16 mcookie; u16 cookie; int rc = 0; @@ -367,9 +369,10 @@ static int bnxt_qplib_process_qp_event(struct bnxt_qplib_rcfw *rcfw, crsqe->req_size = 0; if (!blocked) - wake_up(&rcfw->cmdq.waitq); + wait_cmds++; spin_unlock_irqrestore(&hwq->lock, flags); } + *num_wait += wait_cmds; return rc; } @@ -383,6 +386,7 @@ static void bnxt_qplib_service_creq(struct tasklet_struct *t) struct creq_base *creqe; u32 sw_cons, raw_cons; unsigned long flags; + u32 num_wakeup = 0; /* Service the CREQ until budget is over */ spin_lock_irqsave(&hwq->lock, flags); @@ -401,7 +405,8 @@ static void bnxt_qplib_service_creq(struct tasklet_struct *t) switch (type) { case CREQ_BASE_TYPE_QP_EVENT: bnxt_qplib_process_qp_event - (rcfw, (struct creq_qp_event *)creqe); + (rcfw, (struct creq_qp_event *)creqe, + &num_wakeup); creq->stats.creq_qp_event_processed++; break; case CREQ_BASE_TYPE_FUNC_EVENT: @@ -429,6 +434,8 @@ static void bnxt_qplib_service_creq(struct tasklet_struct *t) rcfw->res->cctx, true); } spin_unlock_irqrestore(&hwq->lock, flags); + if (num_wakeup) + wake_up_nr(&rcfw->cmdq.waitq, num_wakeup); } static irqreturn_t bnxt_qplib_creq_irq(int irq, void *dev_instance) @@ -599,7 +606,7 @@ int bnxt_qplib_alloc_rcfw_channel(struct bnxt_qplib_res *res, rcfw->cmdq_depth = BNXT_QPLIB_CMDQE_MAX_CNT_8192; sginfo.pgsize = bnxt_qplib_cmdqe_page_size(rcfw->cmdq_depth); - hwq_attr.depth = rcfw->cmdq_depth; + hwq_attr.depth = rcfw->cmdq_depth & 0x7FFFFFFF; hwq_attr.stride = BNXT_QPLIB_CMDQE_UNITS; hwq_attr.type = HWQ_TYPE_CTX; if (bnxt_qplib_alloc_init_hwq(&cmdq->hwq, &hwq_attr)) { @@ -637,6 +644,10 @@ void bnxt_qplib_rcfw_stop_irq(struct bnxt_qplib_rcfw *rcfw, bool kill) struct bnxt_qplib_creq_ctx *creq; creq = &rcfw->creq; + + if (!creq->requested) + return; + tasklet_disable(&creq->creq_tasklet); /* Mask h/w interrupts */ bnxt_qplib_ring_nq_db(&creq->creq_db.dbinfo, rcfw->res->cctx, false); @@ -645,10 +656,10 @@ void bnxt_qplib_rcfw_stop_irq(struct bnxt_qplib_rcfw *rcfw, bool kill) if (kill) tasklet_kill(&creq->creq_tasklet); - if (creq->requested) { - free_irq(creq->msix_vec, rcfw); - creq->requested = false; - } + free_irq(creq->msix_vec, rcfw); + kfree(creq->irq_name); + creq->irq_name = NULL; + creq->requested = false; } void bnxt_qplib_disable_rcfw_channel(struct bnxt_qplib_rcfw *rcfw) @@ -680,9 +691,11 @@ int bnxt_qplib_rcfw_start_irq(struct bnxt_qplib_rcfw *rcfw, int msix_vector, bool need_init) { struct bnxt_qplib_creq_ctx *creq; + struct bnxt_qplib_res *res; int rc; creq = &rcfw->creq; + res = rcfw->res; if (creq->requested) return -EFAULT; @@ -692,13 +705,22 @@ int bnxt_qplib_rcfw_start_irq(struct bnxt_qplib_rcfw *rcfw, int msix_vector, tasklet_setup(&creq->creq_tasklet, bnxt_qplib_service_creq); else tasklet_enable(&creq->creq_tasklet); + + creq->irq_name = kasprintf(GFP_KERNEL, "bnxt_re-creq@pci:%s", + pci_name(res->pdev)); + if (!creq->irq_name) + return -ENOMEM; rc = request_irq(creq->msix_vec, bnxt_qplib_creq_irq, 0, - "bnxt_qplib_creq", rcfw); - if (rc) + creq->irq_name, rcfw); + if (rc) { + kfree(creq->irq_name); + creq->irq_name = NULL; + tasklet_disable(&creq->creq_tasklet); return rc; + } creq->requested = true; - bnxt_qplib_ring_nq_db(&creq->creq_db.dbinfo, rcfw->res->cctx, true); + bnxt_qplib_ring_nq_db(&creq->creq_db.dbinfo, res->cctx, true); return 0; } diff --git a/drivers/infiniband/hw/bnxt_re/qplib_rcfw.h b/drivers/infiniband/hw/bnxt_re/qplib_rcfw.h index 0c6d0b70ce89..2acdec55a667 100644 --- a/drivers/infiniband/hw/bnxt_re/qplib_rcfw.h +++ b/drivers/infiniband/hw/bnxt_re/qplib_rcfw.h @@ -174,6 +174,7 @@ struct bnxt_qplib_creq_ctx { u16 ring_id; int msix_vec; bool requested; /*irq handler installed */ + char *irq_name; }; /* RCFW Communication Channels */ diff --git a/drivers/infiniband/hw/hfi1/ipoib_tx.c b/drivers/infiniband/hw/hfi1/ipoib_tx.c index 33ffb00c6382..a89d1bd99a33 100644 --- a/drivers/infiniband/hw/hfi1/ipoib_tx.c +++ b/drivers/infiniband/hw/hfi1/ipoib_tx.c @@ -251,11 +251,11 @@ static int hfi1_ipoib_build_ulp_payload(struct ipoib_txreq *tx, const skb_frag_t *frag = &skb_shinfo(skb)->frags[i]; ret = sdma_txadd_page(dd, - NULL, txreq, skb_frag_page(frag), frag->bv_offset, - skb_frag_size(frag)); + skb_frag_size(frag), + NULL, NULL, NULL); if (unlikely(ret)) break; } diff --git a/drivers/infiniband/hw/hfi1/mmu_rb.c b/drivers/infiniband/hw/hfi1/mmu_rb.c index 71b9ac018887..94f170166730 100644 --- a/drivers/infiniband/hw/hfi1/mmu_rb.c +++ b/drivers/infiniband/hw/hfi1/mmu_rb.c @@ -19,8 +19,7 @@ static int mmu_notifier_range_start(struct mmu_notifier *, const struct mmu_notifier_range *); static struct mmu_rb_node *__mmu_rb_search(struct mmu_rb_handler *, unsigned long, unsigned long); -static void do_remove(struct mmu_rb_handler *handler, - struct list_head *del_list); +static void release_immediate(struct kref *refcount); static void handle_remove(struct work_struct *work); static const struct mmu_notifier_ops mn_opts = { @@ -103,7 +102,11 @@ void hfi1_mmu_rb_unregister(struct mmu_rb_handler *handler) } spin_unlock_irqrestore(&handler->lock, flags); - do_remove(handler, &del_list); + while (!list_empty(&del_list)) { + rbnode = list_first_entry(&del_list, struct mmu_rb_node, list); + list_del(&rbnode->list); + kref_put(&rbnode->refcount, release_immediate); + } /* Now the mm may be freed. */ mmdrop(handler->mn.mm); @@ -131,12 +134,6 @@ int hfi1_mmu_rb_insert(struct mmu_rb_handler *handler, } __mmu_int_rb_insert(mnode, &handler->root); list_add_tail(&mnode->list, &handler->lru_list); - - ret = handler->ops->insert(handler->ops_arg, mnode); - if (ret) { - __mmu_int_rb_remove(mnode, &handler->root); - list_del(&mnode->list); /* remove from LRU list */ - } mnode->handler = handler; unlock: spin_unlock_irqrestore(&handler->lock, flags); @@ -180,6 +177,48 @@ static struct mmu_rb_node *__mmu_rb_search(struct mmu_rb_handler *handler, return node; } +/* + * Must NOT call while holding mnode->handler->lock. + * mnode->handler->ops->remove() may sleep and mnode->handler->lock is a + * spinlock. + */ +static void release_immediate(struct kref *refcount) +{ + struct mmu_rb_node *mnode = + container_of(refcount, struct mmu_rb_node, refcount); + mnode->handler->ops->remove(mnode->handler->ops_arg, mnode); +} + +/* Caller must hold mnode->handler->lock */ +static void release_nolock(struct kref *refcount) +{ + struct mmu_rb_node *mnode = + container_of(refcount, struct mmu_rb_node, refcount); + list_move(&mnode->list, &mnode->handler->del_list); + queue_work(mnode->handler->wq, &mnode->handler->del_work); +} + +/* + * struct mmu_rb_node->refcount kref_put() callback. + * Adds mmu_rb_node to mmu_rb_node->handler->del_list and queues + * handler->del_work on handler->wq. + * Does not remove mmu_rb_node from handler->lru_list or handler->rb_root. + * Acquires mmu_rb_node->handler->lock; do not call while already holding + * handler->lock. + */ +void hfi1_mmu_rb_release(struct kref *refcount) +{ + struct mmu_rb_node *mnode = + container_of(refcount, struct mmu_rb_node, refcount); + struct mmu_rb_handler *handler = mnode->handler; + unsigned long flags; + + spin_lock_irqsave(&handler->lock, flags); + list_move(&mnode->list, &mnode->handler->del_list); + spin_unlock_irqrestore(&handler->lock, flags); + queue_work(handler->wq, &handler->del_work); +} + void hfi1_mmu_rb_evict(struct mmu_rb_handler *handler, void *evict_arg) { struct mmu_rb_node *rbnode, *ptr; @@ -194,6 +233,10 @@ void hfi1_mmu_rb_evict(struct mmu_rb_handler *handler, void *evict_arg) spin_lock_irqsave(&handler->lock, flags); list_for_each_entry_safe(rbnode, ptr, &handler->lru_list, list) { + /* refcount == 1 implies mmu_rb_handler has only rbnode ref */ + if (kref_read(&rbnode->refcount) > 1) + continue; + if (handler->ops->evict(handler->ops_arg, rbnode, evict_arg, &stop)) { __mmu_int_rb_remove(rbnode, &handler->root); @@ -206,7 +249,7 @@ void hfi1_mmu_rb_evict(struct mmu_rb_handler *handler, void *evict_arg) spin_unlock_irqrestore(&handler->lock, flags); list_for_each_entry_safe(rbnode, ptr, &del_list, list) { - handler->ops->remove(handler->ops_arg, rbnode); + kref_put(&rbnode->refcount, release_immediate); } } @@ -218,7 +261,6 @@ static int mmu_notifier_range_start(struct mmu_notifier *mn, struct rb_root_cached *root = &handler->root; struct mmu_rb_node *node, *ptr = NULL; unsigned long flags; - bool added = false; spin_lock_irqsave(&handler->lock, flags); for (node = __mmu_int_rb_iter_first(root, range->start, range->end-1); @@ -227,38 +269,16 @@ static int mmu_notifier_range_start(struct mmu_notifier *mn, ptr = __mmu_int_rb_iter_next(node, range->start, range->end - 1); trace_hfi1_mmu_mem_invalidate(node->addr, node->len); - if (handler->ops->invalidate(handler->ops_arg, node)) { - __mmu_int_rb_remove(node, root); - /* move from LRU list to delete list */ - list_move(&node->list, &handler->del_list); - added = true; - } + /* Remove from rb tree and lru_list. */ + __mmu_int_rb_remove(node, root); + list_del_init(&node->list); + kref_put(&node->refcount, release_nolock); } spin_unlock_irqrestore(&handler->lock, flags); - if (added) - queue_work(handler->wq, &handler->del_work); - return 0; } -/* - * Call the remove function for the given handler and the list. This - * is expected to be called with a delete list extracted from handler. - * The caller should not be holding the handler lock. - */ -static void do_remove(struct mmu_rb_handler *handler, - struct list_head *del_list) -{ - struct mmu_rb_node *node; - - while (!list_empty(del_list)) { - node = list_first_entry(del_list, struct mmu_rb_node, list); - list_del(&node->list); - handler->ops->remove(handler->ops_arg, node); - } -} - /* * Work queue function to remove all nodes that have been queued up to * be removed. The key feature is that mm->mmap_lock is not being held @@ -271,11 +291,16 @@ static void handle_remove(struct work_struct *work) del_work); struct list_head del_list; unsigned long flags; + struct mmu_rb_node *node; /* remove anything that is queued to get removed */ spin_lock_irqsave(&handler->lock, flags); list_replace_init(&handler->del_list, &del_list); spin_unlock_irqrestore(&handler->lock, flags); - do_remove(handler, &del_list); + while (!list_empty(&del_list)) { + node = list_first_entry(&del_list, struct mmu_rb_node, list); + list_del(&node->list); + handler->ops->remove(handler->ops_arg, node); + } } diff --git a/drivers/infiniband/hw/hfi1/mmu_rb.h b/drivers/infiniband/hw/hfi1/mmu_rb.h index ed75acdb7b83..dd2c4a0ae95b 100644 --- a/drivers/infiniband/hw/hfi1/mmu_rb.h +++ b/drivers/infiniband/hw/hfi1/mmu_rb.h @@ -16,6 +16,7 @@ struct mmu_rb_node { struct rb_node node; struct mmu_rb_handler *handler; struct list_head list; + struct kref refcount; }; /* @@ -51,6 +52,8 @@ int hfi1_mmu_rb_register(void *ops_arg, void hfi1_mmu_rb_unregister(struct mmu_rb_handler *handler); int hfi1_mmu_rb_insert(struct mmu_rb_handler *handler, struct mmu_rb_node *mnode); +void hfi1_mmu_rb_release(struct kref *refcount); + void hfi1_mmu_rb_evict(struct mmu_rb_handler *handler, void *evict_arg); struct mmu_rb_node *hfi1_mmu_rb_get_first(struct mmu_rb_handler *handler, unsigned long addr, diff --git a/drivers/infiniband/hw/hfi1/sdma.c b/drivers/infiniband/hw/hfi1/sdma.c index bb2552dd29c1..26c62162759b 100644 --- a/drivers/infiniband/hw/hfi1/sdma.c +++ b/drivers/infiniband/hw/hfi1/sdma.c @@ -1593,7 +1593,20 @@ static inline void sdma_unmap_desc( struct hfi1_devdata *dd, struct sdma_desc *descp) { - system_descriptor_complete(dd, descp); + switch (sdma_mapping_type(descp)) { + case SDMA_MAP_SINGLE: + dma_unmap_single(&dd->pcidev->dev, sdma_mapping_addr(descp), + sdma_mapping_len(descp), DMA_TO_DEVICE); + break; + case SDMA_MAP_PAGE: + dma_unmap_page(&dd->pcidev->dev, sdma_mapping_addr(descp), + sdma_mapping_len(descp), DMA_TO_DEVICE); + break; + } + + if (descp->pinning_ctx && descp->ctx_put) + descp->ctx_put(descp->pinning_ctx); + descp->pinning_ctx = NULL; } /* @@ -3113,8 +3126,8 @@ int ext_coal_sdma_tx_descs(struct hfi1_devdata *dd, struct sdma_txreq *tx, /* Add descriptor for coalesce buffer */ tx->desc_limit = MAX_DESC; - return _sdma_txadd_daddr(dd, SDMA_MAP_SINGLE, NULL, tx, - addr, tx->tlen); + return _sdma_txadd_daddr(dd, SDMA_MAP_SINGLE, tx, + addr, tx->tlen, NULL, NULL, NULL); } return 1; @@ -3157,9 +3170,9 @@ int _pad_sdma_tx_descs(struct hfi1_devdata *dd, struct sdma_txreq *tx) make_tx_sdma_desc( tx, SDMA_MAP_NONE, - NULL, dd->sdma_pad_phys, - sizeof(u32) - (tx->packet_len & (sizeof(u32) - 1))); + sizeof(u32) - (tx->packet_len & (sizeof(u32) - 1)), + NULL, NULL, NULL); tx->num_desc++; _sdma_close_tx(dd, tx); return rval; diff --git a/drivers/infiniband/hw/hfi1/sdma.h b/drivers/infiniband/hw/hfi1/sdma.h index 95aaec14c6c2..7fdebab202c4 100644 --- a/drivers/infiniband/hw/hfi1/sdma.h +++ b/drivers/infiniband/hw/hfi1/sdma.h @@ -594,9 +594,11 @@ static inline dma_addr_t sdma_mapping_addr(struct sdma_desc *d) static inline void make_tx_sdma_desc( struct sdma_txreq *tx, int type, - void *pinning_ctx, dma_addr_t addr, - size_t len) + size_t len, + void *pinning_ctx, + void (*ctx_get)(void *), + void (*ctx_put)(void *)) { struct sdma_desc *desc = &tx->descp[tx->num_desc]; @@ -613,7 +615,11 @@ static inline void make_tx_sdma_desc( << SDMA_DESC0_PHY_ADDR_SHIFT) | (((u64)len & SDMA_DESC0_BYTE_COUNT_MASK) << SDMA_DESC0_BYTE_COUNT_SHIFT); + desc->pinning_ctx = pinning_ctx; + desc->ctx_put = ctx_put; + if (pinning_ctx && ctx_get) + ctx_get(pinning_ctx); } /* helper to extend txreq */ @@ -645,18 +651,20 @@ static inline void _sdma_close_tx(struct hfi1_devdata *dd, static inline int _sdma_txadd_daddr( struct hfi1_devdata *dd, int type, - void *pinning_ctx, struct sdma_txreq *tx, dma_addr_t addr, - u16 len) + u16 len, + void *pinning_ctx, + void (*ctx_get)(void *), + void (*ctx_put)(void *)) { int rval = 0; make_tx_sdma_desc( tx, type, - pinning_ctx, - addr, len); + addr, len, + pinning_ctx, ctx_get, ctx_put); WARN_ON(len > tx->tlen); tx->num_desc++; tx->tlen -= len; @@ -676,11 +684,18 @@ static inline int _sdma_txadd_daddr( /** * sdma_txadd_page() - add a page to the sdma_txreq * @dd: the device to use for mapping - * @pinning_ctx: context to be released at descriptor retirement * @tx: tx request to which the page is added * @page: page to map * @offset: offset within the page * @len: length in bytes + * @pinning_ctx: context to be stored on struct sdma_desc .pinning_ctx. Not + * added if coalesce buffer is used. E.g. pointer to pinned-page + * cache entry for the sdma_desc. + * @ctx_get: optional function to take reference to @pinning_ctx. Not called if + * @pinning_ctx is NULL. + * @ctx_put: optional function to release reference to @pinning_ctx after + * sdma_desc completes. May be called in interrupt context so must + * not sleep. Not called if @pinning_ctx is NULL. * * This is used to add a page/offset/length descriptor. * @@ -692,11 +707,13 @@ static inline int _sdma_txadd_daddr( */ static inline int sdma_txadd_page( struct hfi1_devdata *dd, - void *pinning_ctx, struct sdma_txreq *tx, struct page *page, unsigned long offset, - u16 len) + u16 len, + void *pinning_ctx, + void (*ctx_get)(void *), + void (*ctx_put)(void *)) { dma_addr_t addr; int rval; @@ -720,7 +737,8 @@ static inline int sdma_txadd_page( return -ENOSPC; } - return _sdma_txadd_daddr(dd, SDMA_MAP_PAGE, pinning_ctx, tx, addr, len); + return _sdma_txadd_daddr(dd, SDMA_MAP_PAGE, tx, addr, len, + pinning_ctx, ctx_get, ctx_put); } /** @@ -754,8 +772,8 @@ static inline int sdma_txadd_daddr( return rval; } - return _sdma_txadd_daddr(dd, SDMA_MAP_NONE, NULL, tx, - addr, len); + return _sdma_txadd_daddr(dd, SDMA_MAP_NONE, tx, addr, len, + NULL, NULL, NULL); } /** @@ -801,7 +819,8 @@ static inline int sdma_txadd_kvaddr( return -ENOSPC; } - return _sdma_txadd_daddr(dd, SDMA_MAP_SINGLE, NULL, tx, addr, len); + return _sdma_txadd_daddr(dd, SDMA_MAP_SINGLE, tx, addr, len, + NULL, NULL, NULL); } struct iowait_work; @@ -1034,6 +1053,4 @@ u16 sdma_get_descq_cnt(void); extern uint mod_num_sdma; void sdma_update_lmc(struct hfi1_devdata *dd, u64 mask, u32 lid); - -void system_descriptor_complete(struct hfi1_devdata *dd, struct sdma_desc *descp); #endif diff --git a/drivers/infiniband/hw/hfi1/sdma_txreq.h b/drivers/infiniband/hw/hfi1/sdma_txreq.h index fad946cb5e0d..85ae7293c274 100644 --- a/drivers/infiniband/hw/hfi1/sdma_txreq.h +++ b/drivers/infiniband/hw/hfi1/sdma_txreq.h @@ -20,6 +20,8 @@ struct sdma_desc { /* private: don't use directly */ u64 qw[2]; void *pinning_ctx; + /* Release reference to @pinning_ctx. May be called in interrupt context. Must not sleep. */ + void (*ctx_put)(void *ctx); }; /** diff --git a/drivers/infiniband/hw/hfi1/user_sdma.c b/drivers/infiniband/hw/hfi1/user_sdma.c index a932ae1e03af..02bd62b857b7 100644 --- a/drivers/infiniband/hw/hfi1/user_sdma.c +++ b/drivers/infiniband/hw/hfi1/user_sdma.c @@ -62,18 +62,14 @@ static int defer_packet_queue( static void activate_packet_queue(struct iowait *wait, int reason); static bool sdma_rb_filter(struct mmu_rb_node *node, unsigned long addr, unsigned long len); -static int sdma_rb_insert(void *arg, struct mmu_rb_node *mnode); static int sdma_rb_evict(void *arg, struct mmu_rb_node *mnode, void *arg2, bool *stop); static void sdma_rb_remove(void *arg, struct mmu_rb_node *mnode); -static int sdma_rb_invalidate(void *arg, struct mmu_rb_node *mnode); static struct mmu_rb_ops sdma_rb_ops = { .filter = sdma_rb_filter, - .insert = sdma_rb_insert, .evict = sdma_rb_evict, .remove = sdma_rb_remove, - .invalidate = sdma_rb_invalidate }; static int add_system_pages_to_sdma_packet(struct user_sdma_request *req, @@ -161,9 +157,7 @@ int hfi1_user_sdma_alloc_queues(struct hfi1_ctxtdata *uctxt, if (!pq->reqs) goto pq_reqs_nomem; - pq->req_in_use = kcalloc(BITS_TO_LONGS(hfi1_sdma_comp_ring_size), - sizeof(*pq->req_in_use), - GFP_KERNEL); + pq->req_in_use = bitmap_zalloc(hfi1_sdma_comp_ring_size, GFP_KERNEL); if (!pq->req_in_use) goto pq_reqs_no_in_use; @@ -210,7 +204,7 @@ cq_comps_nomem: cq_nomem: kmem_cache_destroy(pq->txreq_cache); pq_txreq_nomem: - kfree(pq->req_in_use); + bitmap_free(pq->req_in_use); pq_reqs_no_in_use: kfree(pq->reqs); pq_reqs_nomem: @@ -249,15 +243,15 @@ int hfi1_user_sdma_free_queues(struct hfi1_filedata *fd, spin_unlock(&fd->pq_rcu_lock); synchronize_srcu(&fd->pq_srcu); /* at this point there can be no more new requests */ - if (pq->handler) - hfi1_mmu_rb_unregister(pq->handler); iowait_sdma_drain(&pq->busy); /* Wait until all requests have been freed. */ wait_event_interruptible( pq->wait, !atomic_read(&pq->n_reqs)); kfree(pq->reqs); - kfree(pq->req_in_use); + if (pq->handler) + hfi1_mmu_rb_unregister(pq->handler); + bitmap_free(pq->req_in_use); kmem_cache_destroy(pq->txreq_cache); flush_pq_iowait(pq); kfree(pq); @@ -1277,25 +1271,17 @@ static void free_system_node(struct sdma_mmu_node *node) kfree(node); } -static inline void acquire_node(struct sdma_mmu_node *node) -{ - atomic_inc(&node->refcount); - WARN_ON(atomic_read(&node->refcount) < 0); -} - -static inline void release_node(struct mmu_rb_handler *handler, - struct sdma_mmu_node *node) -{ - atomic_dec(&node->refcount); - WARN_ON(atomic_read(&node->refcount) < 0); -} - +/* + * kref_get()'s an additional kref on the returned rb_node to prevent rb_node + * from being released until after rb_node is assigned to an SDMA descriptor + * (struct sdma_desc) under add_system_iovec_to_sdma_packet(), even if the + * virtual address range for rb_node is invalidated between now and then. + */ static struct sdma_mmu_node *find_system_node(struct mmu_rb_handler *handler, unsigned long start, unsigned long end) { struct mmu_rb_node *rb_node; - struct sdma_mmu_node *node; unsigned long flags; spin_lock_irqsave(&handler->lock, flags); @@ -1304,11 +1290,12 @@ static struct sdma_mmu_node *find_system_node(struct mmu_rb_handler *handler, spin_unlock_irqrestore(&handler->lock, flags); return NULL; } - node = container_of(rb_node, struct sdma_mmu_node, rb); - acquire_node(node); + + /* "safety" kref to prevent release before add_system_iovec_to_sdma_packet() */ + kref_get(&rb_node->refcount); spin_unlock_irqrestore(&handler->lock, flags); - return node; + return container_of(rb_node, struct sdma_mmu_node, rb); } static int pin_system_pages(struct user_sdma_request *req, @@ -1357,6 +1344,13 @@ retry: return 0; } +/* + * kref refcount on *node_p will be 2 on successful addition: one kref from + * kref_init() for mmu_rb_handler and one kref to prevent *node_p from being + * released until after *node_p is assigned to an SDMA descriptor (struct + * sdma_desc) under add_system_iovec_to_sdma_packet(), even if the virtual + * address range for *node_p is invalidated between now and then. + */ static int add_system_pinning(struct user_sdma_request *req, struct sdma_mmu_node **node_p, unsigned long start, unsigned long len) @@ -1370,6 +1364,12 @@ static int add_system_pinning(struct user_sdma_request *req, if (!node) return -ENOMEM; + /* First kref "moves" to mmu_rb_handler */ + kref_init(&node->rb.refcount); + + /* "safety" kref to prevent release before add_system_iovec_to_sdma_packet() */ + kref_get(&node->rb.refcount); + node->pq = pq; ret = pin_system_pages(req, start, len, node, PFN_DOWN(len)); if (ret == 0) { @@ -1433,15 +1433,15 @@ static int get_system_cache_entry(struct user_sdma_request *req, return 0; } - SDMA_DBG(req, "prepend: node->rb.addr %lx, node->refcount %d", - node->rb.addr, atomic_read(&node->refcount)); + SDMA_DBG(req, "prepend: node->rb.addr %lx, node->rb.refcount %d", + node->rb.addr, kref_read(&node->rb.refcount)); prepend_len = node->rb.addr - start; /* * This node will not be returned, instead a new node * will be. So release the reference. */ - release_node(handler, node); + kref_put(&node->rb.refcount, hfi1_mmu_rb_release); /* Prepend a node to cover the beginning of the allocation */ ret = add_system_pinning(req, node_p, start, prepend_len); @@ -1453,6 +1453,20 @@ static int get_system_cache_entry(struct user_sdma_request *req, } } +static void sdma_mmu_rb_node_get(void *ctx) +{ + struct mmu_rb_node *node = ctx; + + kref_get(&node->refcount); +} + +static void sdma_mmu_rb_node_put(void *ctx) +{ + struct sdma_mmu_node *node = ctx; + + kref_put(&node->rb.refcount, hfi1_mmu_rb_release); +} + static int add_mapping_to_sdma_packet(struct user_sdma_request *req, struct user_sdma_txreq *tx, struct sdma_mmu_node *cache_entry, @@ -1496,9 +1510,12 @@ static int add_mapping_to_sdma_packet(struct user_sdma_request *req, ctx = cache_entry; } - ret = sdma_txadd_page(pq->dd, ctx, &tx->txreq, + ret = sdma_txadd_page(pq->dd, &tx->txreq, cache_entry->pages[page_index], - page_offset, from_this_page); + page_offset, from_this_page, + ctx, + sdma_mmu_rb_node_get, + sdma_mmu_rb_node_put); if (ret) { /* * When there's a failure, the entire request is freed by @@ -1520,8 +1537,6 @@ static int add_system_iovec_to_sdma_packet(struct user_sdma_request *req, struct user_sdma_iovec *iovec, size_t from_this_iovec) { - struct mmu_rb_handler *handler = req->pq->handler; - while (from_this_iovec > 0) { struct sdma_mmu_node *cache_entry; size_t from_this_cache_entry; @@ -1542,15 +1557,15 @@ static int add_system_iovec_to_sdma_packet(struct user_sdma_request *req, ret = add_mapping_to_sdma_packet(req, tx, cache_entry, start, from_this_cache_entry); + + /* + * Done adding cache_entry to zero or more sdma_desc. Can + * kref_put() the "safety" kref taken under + * get_system_cache_entry(). + */ + kref_put(&cache_entry->rb.refcount, hfi1_mmu_rb_release); + if (ret) { - /* - * We're guaranteed that there will be no descriptor - * completion callback that releases this node - * because only the last descriptor referencing it - * has a context attached, and a failure means the - * last descriptor was never added. - */ - release_node(handler, cache_entry); SDMA_DBG(req, "add system segment failed %d", ret); return ret; } @@ -1601,42 +1616,12 @@ static int add_system_pages_to_sdma_packet(struct user_sdma_request *req, return 0; } -void system_descriptor_complete(struct hfi1_devdata *dd, - struct sdma_desc *descp) -{ - switch (sdma_mapping_type(descp)) { - case SDMA_MAP_SINGLE: - dma_unmap_single(&dd->pcidev->dev, sdma_mapping_addr(descp), - sdma_mapping_len(descp), DMA_TO_DEVICE); - break; - case SDMA_MAP_PAGE: - dma_unmap_page(&dd->pcidev->dev, sdma_mapping_addr(descp), - sdma_mapping_len(descp), DMA_TO_DEVICE); - break; - } - - if (descp->pinning_ctx) { - struct sdma_mmu_node *node = descp->pinning_ctx; - - release_node(node->rb.handler, node); - } -} - static bool sdma_rb_filter(struct mmu_rb_node *node, unsigned long addr, unsigned long len) { return (bool)(node->addr == addr); } -static int sdma_rb_insert(void *arg, struct mmu_rb_node *mnode) -{ - struct sdma_mmu_node *node = - container_of(mnode, struct sdma_mmu_node, rb); - - atomic_inc(&node->refcount); - return 0; -} - /* * Return 1 to remove the node from the rb tree and call the remove op. * @@ -1649,10 +1634,6 @@ static int sdma_rb_evict(void *arg, struct mmu_rb_node *mnode, container_of(mnode, struct sdma_mmu_node, rb); struct evict_data *evict_data = evict_arg; - /* is this node still being used? */ - if (atomic_read(&node->refcount)) - return 0; /* keep this node */ - /* this node will be evicted, add its pages to our count */ evict_data->cleared += node->npages; @@ -1670,13 +1651,3 @@ static void sdma_rb_remove(void *arg, struct mmu_rb_node *mnode) free_system_node(node); } - -static int sdma_rb_invalidate(void *arg, struct mmu_rb_node *mnode) -{ - struct sdma_mmu_node *node = - container_of(mnode, struct sdma_mmu_node, rb); - - if (!atomic_read(&node->refcount)) - return 1; - return 0; -} diff --git a/drivers/infiniband/hw/hfi1/user_sdma.h b/drivers/infiniband/hw/hfi1/user_sdma.h index a241836371dc..548347d4c5bc 100644 --- a/drivers/infiniband/hw/hfi1/user_sdma.h +++ b/drivers/infiniband/hw/hfi1/user_sdma.h @@ -104,7 +104,6 @@ struct hfi1_user_sdma_comp_q { struct sdma_mmu_node { struct mmu_rb_node rb; struct hfi1_user_sdma_pkt_q *pq; - atomic_t refcount; struct page **pages; unsigned int npages; }; diff --git a/drivers/infiniband/hw/hfi1/vnic_sdma.c b/drivers/infiniband/hw/hfi1/vnic_sdma.c index 727eedfba332..cc6324d2d1dd 100644 --- a/drivers/infiniband/hw/hfi1/vnic_sdma.c +++ b/drivers/infiniband/hw/hfi1/vnic_sdma.c @@ -64,11 +64,11 @@ static noinline int build_vnic_ulp_payload(struct sdma_engine *sde, /* combine physically continuous fragments later? */ ret = sdma_txadd_page(sde->dd, - NULL, &tx->txreq, skb_frag_page(frag), skb_frag_off(frag), - skb_frag_size(frag)); + skb_frag_size(frag), + NULL, NULL, NULL); if (unlikely(ret)) goto bail_txadd; } diff --git a/drivers/infiniband/hw/hns/hns_roce_hem.c b/drivers/infiniband/hw/hns/hns_roce_hem.c index fa15d79eabb3..267474070f27 100644 --- a/drivers/infiniband/hw/hns/hns_roce_hem.c +++ b/drivers/infiniband/hw/hns/hns_roce_hem.c @@ -597,11 +597,12 @@ int hns_roce_table_get(struct hns_roce_dev *hr_dev, } /* Set HEM base address(128K/page, pa) to Hardware */ - if (hr_dev->hw->set_hem(hr_dev, table, obj, HEM_HOP_STEP_DIRECT)) { + ret = hr_dev->hw->set_hem(hr_dev, table, obj, HEM_HOP_STEP_DIRECT); + if (ret) { hns_roce_free_hem(hr_dev, table->hem[i]); table->hem[i] = NULL; - ret = -ENODEV; - dev_err(dev, "set HEM base address to HW failed.\n"); + dev_err(dev, "set HEM base address to HW failed, ret = %d.\n", + ret); goto out; } diff --git a/drivers/infiniband/hw/irdma/uk.c b/drivers/infiniband/hw/irdma/uk.c index aecd64a7dbba..a348f0c010ab 100644 --- a/drivers/infiniband/hw/irdma/uk.c +++ b/drivers/infiniband/hw/irdma/uk.c @@ -94,16 +94,18 @@ static enum irdma_status_code irdma_nop_1(struct irdma_qp_uk *qp) */ void irdma_clr_wqes(struct irdma_qp_uk *qp, u32 qp_wqe_idx) { - __le64 *wqe; + struct irdma_qp_quanta *sq; u32 wqe_idx; if (!(qp_wqe_idx & 0x7F)) { wqe_idx = (qp_wqe_idx + 128) % qp->sq_ring.size; - wqe = qp->sq_base[wqe_idx].elem; + sq = qp->sq_base + wqe_idx; if (wqe_idx) - memset(wqe, qp->swqe_polarity ? 0 : 0xFF, 0x1000); + memset(sq, qp->swqe_polarity ? 0 : 0xFF, + 128 * sizeof(*sq)); else - memset(wqe, qp->swqe_polarity ? 0xFF : 0, 0x1000); + memset(sq, qp->swqe_polarity ? 0xFF : 0, + 128 * sizeof(*sq)); } } diff --git a/drivers/input/misc/adxl34x.c b/drivers/input/misc/adxl34x.c index 4cc4e8ff42b3..ad035c342cd3 100644 --- a/drivers/input/misc/adxl34x.c +++ b/drivers/input/misc/adxl34x.c @@ -811,8 +811,7 @@ struct adxl34x *adxl34x_probe(struct device *dev, int irq, AC_WRITE(ac, POWER_CTL, 0); err = request_threaded_irq(ac->irq, NULL, adxl34x_irq, - IRQF_TRIGGER_HIGH | IRQF_ONESHOT, - dev_name(dev), ac); + IRQF_ONESHOT, dev_name(dev), ac); if (err) { dev_err(dev, "irq %d busy?\n", ac->irq); goto err_free_mem; diff --git a/drivers/input/misc/drv260x.c b/drivers/input/misc/drv260x.c index 0efe56f49aa9..1923924fdd44 100644 --- a/drivers/input/misc/drv260x.c +++ b/drivers/input/misc/drv260x.c @@ -435,6 +435,7 @@ static int drv260x_init(struct drv260x_data *haptics) } do { + usleep_range(15000, 15500); error = regmap_read(haptics->regmap, DRV260X_GO, &cal_buf); if (error) { dev_err(&haptics->client->dev, diff --git a/drivers/input/misc/qcom-hv-haptics.c b/drivers/input/misc/qcom-hv-haptics.c index e3d71c78fb5c..fed7dd9acbdb 100644 --- a/drivers/input/misc/qcom-hv-haptics.c +++ b/drivers/input/misc/qcom-hv-haptics.c @@ -3489,6 +3489,11 @@ static ssize_t pattern_s_dbgfs_write(struct file *fp, goto exit; } + if (i >= ARRAY_SIZE(tmp)) { + pr_err("too many patterns in input string\n"); + rc = -EINVAL; + goto exit; + } tmp[i++] = val; } diff --git a/drivers/interconnect/qcom/Kconfig b/drivers/interconnect/qcom/Kconfig index 2ca0c3a31c8c..cba17307a05e 100644 --- a/drivers/interconnect/qcom/Kconfig +++ b/drivers/interconnect/qcom/Kconfig @@ -162,6 +162,19 @@ config INTERCONNECT_QCOM_SDM660 This is a driver for the Qualcomm Network-on-Chip on sdm660-based platforms. +config INTERCONNECT_QCOM_SDM670 + tristate "SDM670 interconnect driver" + depends on INTERCONNECT_QCOM + depends on QCOM_RPMH && QCOM_COMMAND_DB && OF + select INTERCONNECT_QCOM_BCM_VOTER + select INTERCONNECT_QCOM_RPMH + select INTERCONNECT_QCOM_QOS + help + This is a driver for the Qualcomm Technologies, Inc. Network-on-Chip + on sdm670-based platforms. The interconnect provider collects and + aggregates the consumer bandwidth requests to satisfy constraints + placed on Network-on-Chip performance states. + config INTERCONNECT_QCOM_SDM845 tristate "Qualcomm SDM845 interconnect driver" depends on INTERCONNECT_QCOM_RPMH_POSSIBLE diff --git a/drivers/interconnect/qcom/Makefile b/drivers/interconnect/qcom/Makefile index a7e3b0f9f3b5..e97c8c2f90db 100644 --- a/drivers/interconnect/qcom/Makefile +++ b/drivers/interconnect/qcom/Makefile @@ -16,6 +16,7 @@ qnoc-sc7280-objs := sc7280.o qnoc-sc8180x-objs := sc8180x.o qnoc-sdm660-objs := sdm660.o qnoc-sdm845-objs := sdm845.o +qnoc-sdm670-objs := sdm670.o qnoc-scuba-objs := scuba.o qnoc-sdx55-objs := sdx55.o qnoc-lemans-objs := lemans.o @@ -55,6 +56,7 @@ obj-$(CONFIG_INTERCONNECT_QCOM_SC7280) += qnoc-sc7280.o obj-$(CONFIG_INTERCONNECT_QCOM_SC8180X) += qnoc-sc8180x.o obj-$(CONFIG_INTERCONNECT_QCOM_SDM660) += qnoc-sdm660.o obj-$(CONFIG_INTERCONNECT_QCOM_SDM845) += qnoc-sdm845.o +obj-$(CONFIG_INTERCONNECT_QCOM_SDM670) += qnoc-sdm670.o obj-$(CONFIG_INTERCONNECT_QCOM_SDX55) += qnoc-sdx55.o obj-$(CONFIG_INTERCONNECT_QCOM_SM8150) += qnoc-sm8150.o obj-$(CONFIG_INTERCONNECT_QCOM_SM8250) += qnoc-sm8250.o diff --git a/drivers/interconnect/qcom/lemans.c b/drivers/interconnect/qcom/lemans.c index 54e085fd61de..46a2806fc3ac 100644 --- a/drivers/interconnect/qcom/lemans.c +++ b/drivers/interconnect/qcom/lemans.c @@ -15,6 +15,7 @@ #include #include #include +#include #include "icc-rpmh.h" #include "qnoc-qos.h" @@ -3238,6 +3239,21 @@ static int qnoc_probe(struct platform_device *pdev) return ret; } +static int qnoc_lemans_resume(struct device *dev) +{ + struct platform_device *pdev = to_platform_device(dev); + struct qcom_icc_provider *qp = platform_get_drvdata(pdev); + + if (pm_suspend_via_firmware()) + return qcom_icc_rpmh_configure_qos(qp); + + return 0; +} + +static const struct dev_pm_ops qnoc_lemans_pm_ops = { + .resume = qnoc_lemans_resume, +}; + static const struct of_device_id qnoc_of_match[] = { { .compatible = "qcom,lemans-aggre1_noc", .data = &lemans_aggre1_noc}, @@ -3277,6 +3293,7 @@ static struct platform_driver qnoc_driver = { .driver = { .name = "qnoc-lemans", .of_match_table = qnoc_of_match, + .pm = &qnoc_lemans_pm_ops, .sync_state = qcom_icc_rpmh_sync_state, }, }; diff --git a/drivers/interconnect/qcom/sdm670.c b/drivers/interconnect/qcom/sdm670.c new file mode 100644 index 000000000000..899a3eddf36e --- /dev/null +++ b/drivers/interconnect/qcom/sdm670.c @@ -0,0 +1,2311 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2023, Qualcomm Innovation Center, Inc. All rights reserved. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "icc-rpmh.h" +#include "qnoc-qos.h" + +enum { + VOTER_IDX_HLOS, + VOTER_IDX_DISP, +}; + +static const struct regmap_config icc_regmap_config = { + .reg_bits = 32, + .reg_stride = 4, + .val_bits = 32, +}; + +static struct qcom_icc_node qhm_a1noc_cfg = { + .name = "qhm_a1noc_cfg", + .id = MASTER_A1NOC_CFG, + .channels = 1, + .buswidth = 4, + .noc_ops = &qcom_qnoc4_ops, + .num_links = 1, + .links = { SLAVE_SERVICE_A1NOC }, +}; + +static struct qcom_icc_node qhm_qup1 = { + .name = "qhm_qup1", + .id = MASTER_BLSP_1, + .channels = 1, + .buswidth = 4, + .noc_ops = &qcom_qnoc4_ops, + .num_links = 1, + .links = { SLAVE_A1NOC_SNOC }, +}; + +static struct qcom_icc_node qhm_tsif = { + .name = "qhm_tsif", + .id = MASTER_TSIF, + .channels = 1, + .buswidth = 4, + .noc_ops = &qcom_qnoc4_ops, + .num_links = 1, + .links = { SLAVE_A1NOC_SNOC }, +}; + +static struct qcom_icc_qosbox xm_emmc_qos = { + .regs = icc_qnoc_qos_regs[ICC_QNOC_QOSGEN_TYPE_RPMH], + .num_ports = 1, + .offsets = { 0x7000 }, + .config = &(struct qos_config) { + .prio = 0, + .urg_fwd = 0, + }, +}; + +static struct qcom_icc_node xm_emmc = { + .name = "xm_emmc", + .id = MASTER_EMMC, + .channels = 1, + .buswidth = 8, + .noc_ops = &qcom_qnoc4_ops, + .qosbox = &xm_emmc_qos, + .num_links = 1, + .links = { SLAVE_A1NOC_SNOC }, +}; + +static struct qcom_icc_qosbox xm_sdc2_qos = { + .regs = icc_qnoc_qos_regs[ICC_QNOC_QOSGEN_TYPE_RPMH], + .num_ports = 1, + .offsets = { 0x5000 }, + .config = &(struct qos_config) { + .prio = 1, + .urg_fwd = 0, + }, +}; + +static struct qcom_icc_node xm_sdc2 = { + .name = "xm_sdc2", + .id = MASTER_SDCC_2, + .channels = 1, + .buswidth = 8, + .noc_ops = &qcom_qnoc4_ops, + .qosbox = &xm_sdc2_qos, + .num_links = 1, + .links = { SLAVE_A1NOC_SNOC }, +}; + +static struct qcom_icc_qosbox xm_sdc4_qos = { + .regs = icc_qnoc_qos_regs[ICC_QNOC_QOSGEN_TYPE_RPMH], + .num_ports = 1, + .offsets = { 0x6000 }, + .config = &(struct qos_config) { + .prio = 1, + .urg_fwd = 0, + }, +}; + +static struct qcom_icc_node xm_sdc4 = { + .name = "xm_sdc4", + .id = MASTER_SDCC_4, + .channels = 1, + .buswidth = 8, + .noc_ops = &qcom_qnoc4_ops, + .qosbox = &xm_sdc4_qos, + .num_links = 1, + .links = { SLAVE_A1NOC_SNOC }, +}; + +static struct qcom_icc_qosbox xm_ufs_mem_qos = { + .regs = icc_qnoc_qos_regs[ICC_QNOC_QOSGEN_TYPE_RPMH], + .num_ports = 1, + .offsets = { 0x8000 }, + .config = &(struct qos_config) { + .prio = 2, + .urg_fwd = 0, + }, +}; + +static struct qcom_icc_node xm_ufs_mem = { + .name = "xm_ufs_mem", + .id = MASTER_UFS_MEM, + .channels = 1, + .buswidth = 8, + .noc_ops = &qcom_qnoc4_ops, + .qosbox = &xm_ufs_mem_qos, + .num_links = 1, + .links = { SLAVE_A1NOC_SNOC }, +}; + +static struct qcom_icc_node qhm_a2noc_cfg = { + .name = "qhm_a2noc_cfg", + .id = MASTER_A2NOC_CFG, + .channels = 1, + .buswidth = 4, + .noc_ops = &qcom_qnoc4_ops, + .num_links = 1, + .links = { SLAVE_SERVICE_A2NOC }, +}; + +static struct qcom_icc_qosbox qhm_qdss_bam_qos = { + .regs = icc_qnoc_qos_regs[ICC_QNOC_QOSGEN_TYPE_RPMH], + .num_ports = 1, + .offsets = { 0xb800 }, + .config = &(struct qos_config) { + .prio = 2, + .urg_fwd = 0, + }, +}; + +static struct qcom_icc_node qhm_qdss_bam = { + .name = "qhm_qdss_bam", + .id = MASTER_QDSS_BAM, + .channels = 1, + .buswidth = 4, + .noc_ops = &qcom_qnoc4_ops, + .qosbox = &qhm_qdss_bam_qos, + .num_links = 1, + .links = { SLAVE_A2NOC_SNOC }, +}; + +static struct qcom_icc_node qhm_qup2 = { + .name = "qhm_qup2", + .id = MASTER_BLSP_2, + .channels = 1, + .buswidth = 4, + .noc_ops = &qcom_qnoc4_ops, + .num_links = 1, + .links = { SLAVE_A2NOC_SNOC }, +}; + +static struct qcom_icc_qosbox qnm_cnoc_qos = { + .regs = icc_qnoc_qos_regs[ICC_QNOC_QOSGEN_TYPE_RPMH], + .num_ports = 1, + .offsets = { 0x4000 }, + .config = &(struct qos_config) { + .prio = 1, + .urg_fwd = 0, + }, +}; + +static struct qcom_icc_node qnm_cnoc = { + .name = "qnm_cnoc", + .id = MASTER_CNOC_A2NOC, + .channels = 1, + .buswidth = 8, + .noc_ops = &qcom_qnoc4_ops, + .qosbox = &qnm_cnoc_qos, + .num_links = 1, + .links = { SLAVE_A2NOC_SNOC }, +}; + +static struct qcom_icc_qosbox qxm_crypto_qos = { + .regs = icc_qnoc_qos_regs[ICC_QNOC_QOSGEN_TYPE_RPMH], + .num_ports = 1, + .offsets = { 0x5000 }, + .config = &(struct qos_config) { + .prio = 2, + .urg_fwd = 0, + }, +}; + +static struct qcom_icc_node qxm_crypto = { + .name = "qxm_crypto", + .id = MASTER_CRYPTO, + .channels = 1, + .buswidth = 8, + .noc_ops = &qcom_qnoc4_ops, + .qosbox = &qxm_crypto_qos, + .num_links = 1, + .links = { SLAVE_A2NOC_SNOC }, +}; + +static struct qcom_icc_qosbox qxm_ipa_qos = { + .regs = icc_qnoc_qos_regs[ICC_QNOC_QOSGEN_TYPE_RPMH], + .num_ports = 1, + .offsets = { 0x6000 }, + .config = &(struct qos_config) { + .prio = 2, + .urg_fwd = 0, + }, +}; + +static struct qcom_icc_node qxm_ipa = { + .name = "qxm_ipa", + .id = MASTER_IPA, + .channels = 1, + .buswidth = 8, + .noc_ops = &qcom_qnoc4_ops, + .qosbox = &qxm_ipa_qos, + .num_links = 1, + .links = { SLAVE_A2NOC_SNOC }, +}; + +static struct qcom_icc_qosbox xm_qdss_etr_qos = { + .regs = icc_qnoc_qos_regs[ICC_QNOC_QOSGEN_TYPE_RPMH], + .num_ports = 1, + .offsets = { 0xb000 }, + .config = &(struct qos_config) { + .prio = 2, + .urg_fwd = 0, + }, +}; + +static struct qcom_icc_node xm_qdss_etr = { + .name = "xm_qdss_etr", + .id = MASTER_QDSS_ETR, + .channels = 1, + .buswidth = 8, + .noc_ops = &qcom_qnoc4_ops, + .qosbox = &xm_qdss_etr_qos, + .num_links = 1, + .links = { SLAVE_A2NOC_SNOC }, +}; + +static struct qcom_icc_qosbox xm_usb3_0_qos = { + .regs = icc_qnoc_qos_regs[ICC_QNOC_QOSGEN_TYPE_RPMH], + .num_ports = 1, + .offsets = { 0xe000 }, + .config = &(struct qos_config) { + .prio = 2, + .urg_fwd = 0, + }, +}; + +static struct qcom_icc_node xm_usb3_0 = { + .name = "xm_usb3_0", + .id = MASTER_USB3_0, + .channels = 1, + .buswidth = 8, + .noc_ops = &qcom_qnoc4_ops, + .qosbox = &xm_usb3_0_qos, + .num_links = 1, + .links = { SLAVE_A2NOC_SNOC }, +}; + +static struct qcom_icc_node qxm_camnoc_hf0_uncomp = { + .name = "qxm_camnoc_hf0_uncomp", + .id = MASTER_CAMNOC_HF0_UNCOMP, + .channels = 1, + .buswidth = 32, + .noc_ops = &qcom_qnoc4_ops, + .num_links = 1, + .links = { SLAVE_CAMNOC_UNCOMP }, +}; + +static struct qcom_icc_node qxm_camnoc_hf1_uncomp = { + .name = "qxm_camnoc_hf1_uncomp", + .id = MASTER_CAMNOC_HF1_UNCOMP, + .channels = 1, + .buswidth = 32, + .noc_ops = &qcom_qnoc4_ops, + .num_links = 1, + .links = { SLAVE_CAMNOC_UNCOMP }, +}; + +static struct qcom_icc_node qxm_camnoc_sf_uncomp = { + .name = "qxm_camnoc_sf_uncomp", + .id = MASTER_CAMNOC_SF_UNCOMP, + .channels = 1, + .buswidth = 32, + .noc_ops = &qcom_qnoc4_ops, + .num_links = 1, + .links = { SLAVE_CAMNOC_UNCOMP }, +}; + +static struct qcom_icc_node qhm_spdm = { + .name = "qhm_spdm", + .id = MASTER_SPDM, + .channels = 1, + .buswidth = 4, + .noc_ops = &qcom_qnoc4_ops, + .num_links = 1, + .links = { SLAVE_CNOC_A2NOC }, +}; + +static struct qcom_icc_node qhm_tic = { + .name = "qhm_tic", + .id = MASTER_TIC, + .channels = 1, + .buswidth = 4, + .noc_ops = &qcom_qnoc4_ops, + .num_links = 39, + .links = { SLAVE_A1NOC_CFG, SLAVE_A2NOC_CFG, + SLAVE_AOP, SLAVE_AOSS, + SLAVE_CAMERA_CFG, SLAVE_CLK_CTL, + SLAVE_CDSP_CFG, SLAVE_RBCPR_CX_CFG, + SLAVE_CRYPTO_0_CFG, SLAVE_DCC_CFG, + SLAVE_CNOC_DDRSS, SLAVE_DISPLAY_CFG, + SLAVE_EMMC_CFG, SLAVE_GLM, + SLAVE_GFX3D_CFG, SLAVE_IMEM_CFG, + SLAVE_IPA_CFG, SLAVE_CNOC_MNOC_CFG, + SLAVE_PDM, SLAVE_SOUTH_PHY_CFG, + SLAVE_PIMEM_CFG, SLAVE_PRNG, + SLAVE_QDSS_CFG, SLAVE_BLSP_2, + SLAVE_BLSP_1, SLAVE_SDCC_2, + SLAVE_SDCC_4, SLAVE_SNOC_CFG, + SLAVE_SPDM_WRAPPER, SLAVE_TCSR, + SLAVE_TLMM_NORTH, SLAVE_TLMM_SOUTH, + SLAVE_TSIF, SLAVE_UFS_MEM_CFG, + SLAVE_USB3_0, SLAVE_VENUS_CFG, + SLAVE_VSENSE_CTRL_CFG, SLAVE_CNOC_A2NOC, + SLAVE_SERVICE_CNOC }, +}; + +static struct qcom_icc_node qnm_snoc = { + .name = "qnm_snoc", + .id = MASTER_SNOC_CNOC, + .channels = 1, + .buswidth = 8, + .noc_ops = &qcom_qnoc4_ops, + .num_links = 38, + .links = { SLAVE_A1NOC_CFG, SLAVE_A2NOC_CFG, + SLAVE_AOP, SLAVE_AOSS, + SLAVE_CAMERA_CFG, SLAVE_CLK_CTL, + SLAVE_CDSP_CFG, SLAVE_RBCPR_CX_CFG, + SLAVE_CRYPTO_0_CFG, SLAVE_DCC_CFG, + SLAVE_CNOC_DDRSS, SLAVE_DISPLAY_CFG, + SLAVE_EMMC_CFG, SLAVE_GLM, + SLAVE_GFX3D_CFG, SLAVE_IMEM_CFG, + SLAVE_IPA_CFG, SLAVE_CNOC_MNOC_CFG, + SLAVE_PDM, SLAVE_SOUTH_PHY_CFG, + SLAVE_PIMEM_CFG, SLAVE_PRNG, + SLAVE_QDSS_CFG, SLAVE_BLSP_2, + SLAVE_BLSP_1, SLAVE_SDCC_2, + SLAVE_SDCC_4, SLAVE_SNOC_CFG, + SLAVE_SPDM_WRAPPER, SLAVE_TCSR, + SLAVE_TLMM_NORTH, SLAVE_TLMM_SOUTH, + SLAVE_TSIF, SLAVE_UFS_MEM_CFG, + SLAVE_USB3_0, SLAVE_VENUS_CFG, + SLAVE_VSENSE_CTRL_CFG, SLAVE_SERVICE_CNOC }, +}; + +static struct qcom_icc_node xm_qdss_dap = { + .name = "xm_qdss_dap", + .id = MASTER_QDSS_DAP, + .channels = 1, + .buswidth = 8, + .noc_ops = &qcom_qnoc4_ops, + .num_links = 39, + .links = { SLAVE_A1NOC_CFG, SLAVE_A2NOC_CFG, + SLAVE_AOP, SLAVE_AOSS, + SLAVE_CAMERA_CFG, SLAVE_CLK_CTL, + SLAVE_CDSP_CFG, SLAVE_RBCPR_CX_CFG, + SLAVE_CRYPTO_0_CFG, SLAVE_DCC_CFG, + SLAVE_CNOC_DDRSS, SLAVE_DISPLAY_CFG, + SLAVE_EMMC_CFG, SLAVE_GLM, + SLAVE_GFX3D_CFG, SLAVE_IMEM_CFG, + SLAVE_IPA_CFG, SLAVE_CNOC_MNOC_CFG, + SLAVE_PDM, SLAVE_SOUTH_PHY_CFG, + SLAVE_PIMEM_CFG, SLAVE_PRNG, + SLAVE_QDSS_CFG, SLAVE_BLSP_2, + SLAVE_BLSP_1, SLAVE_SDCC_2, + SLAVE_SDCC_4, SLAVE_SNOC_CFG, + SLAVE_SPDM_WRAPPER, SLAVE_TCSR, + SLAVE_TLMM_NORTH, SLAVE_TLMM_SOUTH, + SLAVE_TSIF, SLAVE_UFS_MEM_CFG, + SLAVE_USB3_0, SLAVE_VENUS_CFG, + SLAVE_VSENSE_CTRL_CFG, SLAVE_CNOC_A2NOC, + SLAVE_SERVICE_CNOC }, +}; + +static struct qcom_icc_node qhm_cnoc = { + .name = "qhm_cnoc", + .id = MASTER_CNOC_DC_NOC, + .channels = 1, + .buswidth = 4, + .noc_ops = &qcom_qnoc4_ops, + .num_links = 2, + .links = { SLAVE_LLCC_CFG, SLAVE_MEM_NOC_CFG }, +}; + +static struct qcom_icc_node acm_l3 = { + .name = "acm_l3", + .id = MASTER_APPSS_PROC, + .channels = 1, + .buswidth = 16, + .noc_ops = &qcom_qnoc4_ops, + .num_links = 3, + .links = { SLAVE_GNOC_SNOC, SLAVE_GNOC_MEM_NOC, + SLAVE_SERVICE_GNOC }, +}; + +static struct qcom_icc_node pm_gnoc_cfg = { + .name = "pm_gnoc_cfg", + .id = MASTER_GNOC_CFG, + .channels = 1, + .buswidth = 4, + .noc_ops = &qcom_qnoc4_ops, + .num_links = 1, + .links = { SLAVE_SERVICE_GNOC }, +}; + +static struct qcom_icc_node llcc_mc = { + .name = "llcc_mc", + .id = MASTER_LLCC, + .channels = 2, + .buswidth = 4, + .noc_ops = &qcom_qnoc4_ops, + .num_links = 1, + .links = { SLAVE_EBI1 }, +}; + +static struct qcom_icc_qosbox acm_tcu_qos = { + .regs = icc_qnoc_qos_regs[ICC_QNOC_QOSGEN_TYPE_RPMH], + .num_ports = 1, + .offsets = { 0x10000 }, + .config = &(struct qos_config) { + .prio = 7, + .urg_fwd = 0, + }, +}; + +static struct qcom_icc_node acm_tcu = { + .name = "acm_tcu", + .id = MASTER_TCU_0, + .channels = 1, + .buswidth = 8, + .noc_ops = &qcom_qnoc4_ops, + .qosbox = &acm_tcu_qos, + .num_links = 3, + .links = { SLAVE_MEM_NOC_GNOC, SLAVE_LLCC, + SLAVE_MEM_NOC_SNOC }, +}; + +static struct qcom_icc_node qhm_memnoc_cfg = { + .name = "qhm_memnoc_cfg", + .id = MASTER_MEM_NOC_CFG, + .channels = 1, + .buswidth = 4, + .noc_ops = &qcom_qnoc4_ops, + .num_links = 2, + .links = { SLAVE_MSS_PROC_MS_MPU_CFG, SLAVE_SERVICE_MEM_NOC }, +}; + +static struct qcom_icc_qosbox qnm_apps_qos = { + .regs = icc_qnoc_qos_regs[ICC_QNOC_QOSGEN_TYPE_RPMH], + .num_ports = 2, + .offsets = { 0x12000, 0x13000 }, + .config = &(struct qos_config) { + .prio = 0, + .urg_fwd = 0, + }, +}; + +static struct qcom_icc_node qnm_apps = { + .name = "qnm_apps", + .id = MASTER_GNOC_MEM_NOC, + .channels = 2, + .buswidth = 32, + .noc_ops = &qcom_qnoc4_ops, + .qosbox = &qnm_apps_qos, + .num_links = 1, + .links = { SLAVE_LLCC }, +}; + +static struct qcom_icc_qosbox qnm_mnoc_hf_qos = { + .regs = icc_qnoc_qos_regs[ICC_QNOC_QOSGEN_TYPE_RPMH], + .num_ports = 2, + .offsets = { 0x14000, 0x15000 }, + .config = &(struct qos_config) { + .prio = 0, + .urg_fwd = 1, + }, +}; + +static struct qcom_icc_node qnm_mnoc_hf = { + .name = "qnm_mnoc_hf", + .id = MASTER_MNOC_HF_MEM_NOC, + .channels = 2, + .buswidth = 32, + .noc_ops = &qcom_qnoc4_ops, + .qosbox = &qnm_mnoc_hf_qos, + .num_links = 1, + .links = { SLAVE_LLCC }, +}; + +static struct qcom_icc_qosbox qnm_mnoc_sf_qos = { + .regs = icc_qnoc_qos_regs[ICC_QNOC_QOSGEN_TYPE_RPMH], + .num_ports = 1, + .offsets = { 0x17000 }, + .config = &(struct qos_config) { + .prio = 0, + .urg_fwd = 1, + }, +}; + +static struct qcom_icc_node qnm_mnoc_sf = { + .name = "qnm_mnoc_sf", + .id = MASTER_MNOC_SF_MEM_NOC, + .channels = 1, + .buswidth = 32, + .noc_ops = &qcom_qnoc4_ops, + .qosbox = &qnm_mnoc_sf_qos, + .num_links = 3, + .links = { SLAVE_MEM_NOC_GNOC, SLAVE_LLCC, + SLAVE_MEM_NOC_SNOC }, +}; + +static struct qcom_icc_qosbox qnm_snoc_gc_qos = { + .regs = icc_qnoc_qos_regs[ICC_QNOC_QOSGEN_TYPE_RPMH], + .num_ports = 1, + .offsets = { 0x18000 }, + .config = &(struct qos_config) { + .prio = 0, + .urg_fwd = 1, + }, +}; + +static struct qcom_icc_node qnm_snoc_gc = { + .name = "qnm_snoc_gc", + .id = MASTER_SNOC_GC_MEM_NOC, + .channels = 1, + .buswidth = 8, + .noc_ops = &qcom_qnoc4_ops, + .qosbox = &qnm_snoc_gc_qos, + .num_links = 1, + .links = { SLAVE_LLCC }, +}; + +static struct qcom_icc_qosbox qnm_snoc_sf_qos = { + .regs = icc_qnoc_qos_regs[ICC_QNOC_QOSGEN_TYPE_RPMH], + .num_ports = 1, + .offsets = { 0x19000 }, + .config = &(struct qos_config) { + .prio = 0, + .urg_fwd = 1, + }, +}; + +static struct qcom_icc_node qnm_snoc_sf = { + .name = "qnm_snoc_sf", + .id = MASTER_SNOC_SF_MEM_NOC, + .channels = 1, + .buswidth = 16, + .noc_ops = &qcom_qnoc4_ops, + .qosbox = &qnm_snoc_sf_qos, + .num_links = 2, + .links = { SLAVE_MEM_NOC_GNOC, SLAVE_LLCC }, +}; + +static struct qcom_icc_qosbox qxm_gpu_qos = { + .regs = icc_qnoc_qos_regs[ICC_QNOC_QOSGEN_TYPE_RPMH], + .num_ports = 2, + .offsets = { 0x1a000, 0x1b000 }, + .config = &(struct qos_config) { + .prio = 0, + .urg_fwd = 0, + }, +}; + +static struct qcom_icc_node qxm_gpu = { + .name = "qxm_gpu", + .id = MASTER_GFX3D, + .channels = 2, + .buswidth = 32, + .noc_ops = &qcom_qnoc4_ops, + .qosbox = &qxm_gpu_qos, + .num_links = 3, + .links = { SLAVE_MEM_NOC_GNOC, SLAVE_LLCC, + SLAVE_MEM_NOC_SNOC }, +}; + +static struct qcom_icc_node qhm_mnoc_cfg = { + .name = "qhm_mnoc_cfg", + .id = MASTER_CNOC_MNOC_CFG, + .channels = 1, + .buswidth = 4, + .noc_ops = &qcom_qnoc4_ops, + .num_links = 1, + .links = { SLAVE_SERVICE_MNOC }, +}; + +static struct qcom_icc_qosbox qxm_camnoc_hf0_qos = { + .regs = icc_qnoc_qos_regs[ICC_QNOC_QOSGEN_TYPE_RPMH], + .num_ports = 1, + .offsets = { 0xa000 }, + .config = &(struct qos_config) { + .prio = 0, + .urg_fwd = 1, + }, +}; + +static struct qcom_icc_node qxm_camnoc_hf0 = { + .name = "qxm_camnoc_hf0", + .id = MASTER_CAMNOC_HF0, + .channels = 1, + .buswidth = 32, + .noc_ops = &qcom_qnoc4_ops, + .qosbox = &qxm_camnoc_hf0_qos, + .num_links = 1, + .links = { SLAVE_MNOC_HF_MEM_NOC }, +}; + +static struct qcom_icc_qosbox qxm_camnoc_hf1_qos = { + .regs = icc_qnoc_qos_regs[ICC_QNOC_QOSGEN_TYPE_RPMH], + .num_ports = 1, + .offsets = { 0xb000 }, + .config = &(struct qos_config) { + .prio = 0, + .urg_fwd = 1, + }, +}; + +static struct qcom_icc_node qxm_camnoc_hf1 = { + .name = "qxm_camnoc_hf1", + .id = MASTER_CAMNOC_HF1, + .channels = 1, + .buswidth = 32, + .noc_ops = &qcom_qnoc4_ops, + .qosbox = &qxm_camnoc_hf1_qos, + .num_links = 1, + .links = { SLAVE_MNOC_HF_MEM_NOC }, +}; + +static struct qcom_icc_qosbox qxm_camnoc_sf_qos = { + .regs = icc_qnoc_qos_regs[ICC_QNOC_QOSGEN_TYPE_RPMH], + .num_ports = 1, + .offsets = { 0x9000 }, + .config = &(struct qos_config) { + .prio = 0, + .urg_fwd = 1, + }, +}; + +static struct qcom_icc_node qxm_camnoc_sf = { + .name = "qxm_camnoc_sf", + .id = MASTER_CAMNOC_SF, + .channels = 1, + .buswidth = 32, + .noc_ops = &qcom_qnoc4_ops, + .qosbox = &qxm_camnoc_sf_qos, + .num_links = 1, + .links = { SLAVE_MNOC_SF_MEM_NOC }, +}; + +static struct qcom_icc_qosbox qxm_mdp0_qos = { + .regs = icc_qnoc_qos_regs[ICC_QNOC_QOSGEN_TYPE_RPMH], + .num_ports = 1, + .offsets = { 0xc000 }, + .config = &(struct qos_config) { + .prio = 0, + .urg_fwd = 1, + }, +}; + +static struct qcom_icc_node qxm_mdp0 = { + .name = "qxm_mdp0", + .id = MASTER_MDP0, + .channels = 1, + .buswidth = 32, + .noc_ops = &qcom_qnoc4_ops, + .qosbox = &qxm_mdp0_qos, + .num_links = 1, + .links = { SLAVE_MNOC_HF_MEM_NOC }, +}; + +static struct qcom_icc_qosbox qxm_mdp1_qos = { + .regs = icc_qnoc_qos_regs[ICC_QNOC_QOSGEN_TYPE_RPMH], + .num_ports = 1, + .offsets = { 0xd000 }, + .config = &(struct qos_config) { + .prio = 0, + .urg_fwd = 1, + }, +}; + +static struct qcom_icc_node qxm_mdp1 = { + .name = "qxm_mdp1", + .id = MASTER_MDP1, + .channels = 1, + .buswidth = 32, + .noc_ops = &qcom_qnoc4_ops, + .qosbox = &qxm_mdp1_qos, + .num_links = 1, + .links = { SLAVE_MNOC_HF_MEM_NOC }, +}; + +static struct qcom_icc_qosbox qxm_rot_qos = { + .regs = icc_qnoc_qos_regs[ICC_QNOC_QOSGEN_TYPE_RPMH], + .num_ports = 1, + .offsets = { 0xe000 }, + .config = &(struct qos_config) { + .prio = 0, + .urg_fwd = 1, + }, +}; + +static struct qcom_icc_node qxm_rot = { + .name = "qxm_rot", + .id = MASTER_ROTATOR, + .channels = 1, + .buswidth = 32, + .noc_ops = &qcom_qnoc4_ops, + .qosbox = &qxm_rot_qos, + .num_links = 1, + .links = { SLAVE_MNOC_SF_MEM_NOC }, +}; + +static struct qcom_icc_qosbox qxm_venus0_qos = { + .regs = icc_qnoc_qos_regs[ICC_QNOC_QOSGEN_TYPE_RPMH], + .num_ports = 1, + .offsets = { 0xf000 }, + .config = &(struct qos_config) { + .prio = 0, + .urg_fwd = 1, + }, +}; + +static struct qcom_icc_node qxm_venus0 = { + .name = "qxm_venus0", + .id = MASTER_VIDEO_P0, + .channels = 1, + .buswidth = 32, + .noc_ops = &qcom_qnoc4_ops, + .qosbox = &qxm_venus0_qos, + .num_links = 1, + .links = { SLAVE_MNOC_SF_MEM_NOC }, +}; + +static struct qcom_icc_qosbox qxm_venus1_qos = { + .regs = icc_qnoc_qos_regs[ICC_QNOC_QOSGEN_TYPE_RPMH], + .num_ports = 1, + .offsets = { 0x10000 }, + .config = &(struct qos_config) { + .prio = 0, + .urg_fwd = 1, + }, +}; + +static struct qcom_icc_node qxm_venus1 = { + .name = "qxm_venus1", + .id = MASTER_VIDEO_P1, + .channels = 1, + .buswidth = 32, + .noc_ops = &qcom_qnoc4_ops, + .qosbox = &qxm_venus1_qos, + .num_links = 1, + .links = { SLAVE_MNOC_SF_MEM_NOC }, +}; + +static struct qcom_icc_qosbox qxm_venus_arm9_qos = { + .regs = icc_qnoc_qos_regs[ICC_QNOC_QOSGEN_TYPE_RPMH], + .num_ports = 1, + .offsets = { 0x11000 }, + .config = &(struct qos_config) { + .prio = 0, + .urg_fwd = 1, + }, +}; + +static struct qcom_icc_node qxm_venus_arm9 = { + .name = "qxm_venus_arm9", + .id = MASTER_VIDEO_PROC, + .channels = 1, + .buswidth = 8, + .noc_ops = &qcom_qnoc4_ops, + .qosbox = &qxm_venus_arm9_qos, + .num_links = 1, + .links = { SLAVE_MNOC_SF_MEM_NOC }, +}; + +static struct qcom_icc_node qhm_snoc_cfg = { + .name = "qhm_snoc_cfg", + .id = MASTER_SNOC_CFG, + .channels = 1, + .buswidth = 4, + .noc_ops = &qcom_qnoc4_ops, + .num_links = 1, + .links = { SLAVE_SERVICE_SNOC }, +}; + +static struct qcom_icc_node qnm_aggre1_noc = { + .name = "qnm_aggre1_noc", + .id = MASTER_A1NOC_SNOC, + .channels = 1, + .buswidth = 16, + .noc_ops = &qcom_qnoc4_ops, + .num_links = 6, + .links = { SLAVE_APPSS, SLAVE_SNOC_CNOC, + SLAVE_SNOC_MEM_NOC_SF, SLAVE_IMEM, + SLAVE_PIMEM, SLAVE_QDSS_STM }, +}; + +static struct qcom_icc_node qnm_aggre2_noc = { + .name = "qnm_aggre2_noc", + .id = MASTER_A2NOC_SNOC, + .channels = 1, + .buswidth = 16, + .noc_ops = &qcom_qnoc4_ops, + .num_links = 7, + .links = { SLAVE_APPSS, SLAVE_SNOC_CNOC, + SLAVE_SNOC_MEM_NOC_SF, SLAVE_IMEM, + SLAVE_PIMEM, SLAVE_QDSS_STM, + SLAVE_TCU }, +}; + +static struct qcom_icc_node qnm_gladiator_sodv = { + .name = "qnm_gladiator_sodv", + .id = MASTER_GNOC_SNOC, + .channels = 1, + .buswidth = 8, + .noc_ops = &qcom_qnoc4_ops, + .num_links = 6, + .links = { SLAVE_APPSS, SLAVE_SNOC_CNOC, + SLAVE_IMEM, SLAVE_PIMEM, + SLAVE_QDSS_STM, SLAVE_TCU }, +}; + +static struct qcom_icc_node qnm_memnoc = { + .name = "qnm_memnoc", + .id = MASTER_MEM_NOC_SNOC, + .channels = 1, + .buswidth = 8, + .noc_ops = &qcom_qnoc4_ops, + .num_links = 5, + .links = { SLAVE_APPSS, SLAVE_SNOC_CNOC, + SLAVE_IMEM, SLAVE_PIMEM, + SLAVE_QDSS_STM }, +}; + +static struct qcom_icc_qosbox qxm_pimem_qos = { + .regs = icc_qnoc_qos_regs[ICC_QNOC_QOSGEN_TYPE_RPMH], + .num_ports = 1, + .offsets = { 0xc000 }, + .config = &(struct qos_config) { + .prio = 2, + .urg_fwd = 0, + }, +}; + +static struct qcom_icc_node qxm_pimem = { + .name = "qxm_pimem", + .id = MASTER_PIMEM, + .channels = 1, + .buswidth = 8, + .noc_ops = &qcom_qnoc4_ops, + .qosbox = &qxm_pimem_qos, + .num_links = 2, + .links = { SLAVE_SNOC_MEM_NOC_GC, SLAVE_IMEM }, +}; + +static struct qcom_icc_qosbox xm_gic_qos = { + .regs = icc_qnoc_qos_regs[ICC_QNOC_QOSGEN_TYPE_RPMH], + .num_ports = 1, + .offsets = { 0x9000 }, + .config = &(struct qos_config) { + .prio = 1, + .urg_fwd = 0, + }, +}; + +static struct qcom_icc_node xm_gic = { + .name = "xm_gic", + .id = MASTER_GIC, + .channels = 1, + .buswidth = 8, + .noc_ops = &qcom_qnoc4_ops, + .qosbox = &xm_gic_qos, + .num_links = 2, + .links = { SLAVE_SNOC_MEM_NOC_GC, SLAVE_IMEM }, +}; + +static struct qcom_icc_node llcc_mc_disp = { + .name = "llcc_mc_disp", + .id = MASTER_LLCC_DISP, + .channels = 2, + .buswidth = 4, + .noc_ops = &qcom_qnoc4_ops, + .num_links = 1, + .links = { SLAVE_EBI1_DISP }, +}; + +static struct qcom_icc_node qnm_mnoc_hf_disp = { + .name = "qnm_mnoc_hf_disp", + .id = MASTER_MNOC_HF_MEM_NOC_DISP, + .channels = 2, + .buswidth = 32, + .noc_ops = &qcom_qnoc4_ops, + .num_links = 1, + .links = { SLAVE_LLCC_DISP }, +}; + +static struct qcom_icc_node qnm_mnoc_sf_disp = { + .name = "qnm_mnoc_sf_disp", + .id = MASTER_MNOC_SF_MEM_NOC_DISP, + .channels = 1, + .buswidth = 32, + .noc_ops = &qcom_qnoc4_ops, + .num_links = 1, + .links = { SLAVE_LLCC_DISP }, +}; + +static struct qcom_icc_node qxm_mdp0_disp = { + .name = "qxm_mdp0_disp", + .id = MASTER_MDP0_DISP, + .channels = 1, + .buswidth = 32, + .noc_ops = &qcom_qnoc4_ops, + .num_links = 1, + .links = { SLAVE_MNOC_HF_MEM_NOC_DISP }, +}; + +static struct qcom_icc_node qxm_mdp1_disp = { + .name = "qxm_mdp1_disp", + .id = MASTER_MDP1_DISP, + .channels = 1, + .buswidth = 32, + .noc_ops = &qcom_qnoc4_ops, + .num_links = 1, + .links = { SLAVE_MNOC_HF_MEM_NOC_DISP }, +}; + +static struct qcom_icc_node qxm_rot_disp = { + .name = "qxm_rot_disp", + .id = MASTER_ROTATOR_DISP, + .channels = 1, + .buswidth = 32, + .noc_ops = &qcom_qnoc4_ops, + .num_links = 1, + .links = { SLAVE_MNOC_SF_MEM_NOC_DISP }, +}; + +static struct qcom_icc_node qns_a1noc_snoc = { + .name = "qns_a1noc_snoc", + .id = SLAVE_A1NOC_SNOC, + .channels = 1, + .buswidth = 16, + .noc_ops = &qcom_qnoc4_ops, + .num_links = 1, + .links = { MASTER_A1NOC_SNOC }, +}; + +static struct qcom_icc_node srvc_aggre1_noc = { + .name = "srvc_aggre1_noc", + .id = SLAVE_SERVICE_A1NOC, + .channels = 1, + .buswidth = 4, + .noc_ops = &qcom_qnoc4_ops, + .num_links = 0, +}; + +static struct qcom_icc_node qns_a2noc_snoc = { + .name = "qns_a2noc_snoc", + .id = SLAVE_A2NOC_SNOC, + .channels = 1, + .buswidth = 16, + .noc_ops = &qcom_qnoc4_ops, + .num_links = 1, + .links = { MASTER_A2NOC_SNOC }, +}; + +static struct qcom_icc_node srvc_aggre2_noc = { + .name = "srvc_aggre2_noc", + .id = SLAVE_SERVICE_A2NOC, + .channels = 1, + .buswidth = 4, + .noc_ops = &qcom_qnoc4_ops, + .num_links = 0, +}; + +static struct qcom_icc_node qns_camnoc_uncomp = { + .name = "qns_camnoc_uncomp", + .id = SLAVE_CAMNOC_UNCOMP, + .channels = 1, + .buswidth = 32, + .noc_ops = &qcom_qnoc4_ops, + .num_links = 0, +}; + +static struct qcom_icc_node qhs_a1_noc_cfg = { + .name = "qhs_a1_noc_cfg", + .id = SLAVE_A1NOC_CFG, + .channels = 1, + .buswidth = 4, + .noc_ops = &qcom_qnoc4_ops, + .num_links = 1, + .links = { MASTER_A1NOC_CFG }, +}; + +static struct qcom_icc_node qhs_a2_noc_cfg = { + .name = "qhs_a2_noc_cfg", + .id = SLAVE_A2NOC_CFG, + .channels = 1, + .buswidth = 4, + .noc_ops = &qcom_qnoc4_ops, + .num_links = 1, + .links = { MASTER_A2NOC_CFG }, +}; + +static struct qcom_icc_node qhs_aop = { + .name = "qhs_aop", + .id = SLAVE_AOP, + .channels = 1, + .buswidth = 4, + .noc_ops = &qcom_qnoc4_ops, + .num_links = 0, +}; + +static struct qcom_icc_node qhs_aoss = { + .name = "qhs_aoss", + .id = SLAVE_AOSS, + .channels = 1, + .buswidth = 4, + .noc_ops = &qcom_qnoc4_ops, + .num_links = 0, +}; + +static struct qcom_icc_node qhs_camera_cfg = { + .name = "qhs_camera_cfg", + .id = SLAVE_CAMERA_CFG, + .channels = 1, + .buswidth = 4, + .noc_ops = &qcom_qnoc4_ops, + .num_links = 0, +}; + +static struct qcom_icc_node qhs_clk_ctl = { + .name = "qhs_clk_ctl", + .id = SLAVE_CLK_CTL, + .channels = 1, + .buswidth = 4, + .noc_ops = &qcom_qnoc4_ops, + .num_links = 0, +}; + +static struct qcom_icc_node qhs_compute_dsp_cfg = { + .name = "qhs_compute_dsp_cfg", + .id = SLAVE_CDSP_CFG, + .channels = 1, + .buswidth = 4, + .noc_ops = &qcom_qnoc4_ops, + .num_links = 0, +}; + +static struct qcom_icc_node qhs_cpr_cx = { + .name = "qhs_cpr_cx", + .id = SLAVE_RBCPR_CX_CFG, + .channels = 1, + .buswidth = 4, + .noc_ops = &qcom_qnoc4_ops, + .num_links = 0, +}; + +static struct qcom_icc_node qhs_crypto0_cfg = { + .name = "qhs_crypto0_cfg", + .id = SLAVE_CRYPTO_0_CFG, + .channels = 1, + .buswidth = 4, + .noc_ops = &qcom_qnoc4_ops, + .num_links = 0, +}; + +static struct qcom_icc_node qhs_dcc_cfg = { + .name = "qhs_dcc_cfg", + .id = SLAVE_DCC_CFG, + .channels = 1, + .buswidth = 4, + .noc_ops = &qcom_qnoc4_ops, + .num_links = 1, + .links = { MASTER_CNOC_DC_NOC }, +}; + +static struct qcom_icc_node qhs_ddrss_cfg = { + .name = "qhs_ddrss_cfg", + .id = SLAVE_CNOC_DDRSS, + .channels = 1, + .buswidth = 4, + .noc_ops = &qcom_qnoc4_ops, + .num_links = 0, +}; + +static struct qcom_icc_node qhs_display_cfg = { + .name = "qhs_display_cfg", + .id = SLAVE_DISPLAY_CFG, + .channels = 1, + .buswidth = 4, + .noc_ops = &qcom_qnoc4_ops, + .num_links = 0, +}; + +static struct qcom_icc_node qhs_emmc_cfg = { + .name = "qhs_emmc_cfg", + .id = SLAVE_EMMC_CFG, + .channels = 1, + .buswidth = 4, + .noc_ops = &qcom_qnoc4_ops, + .num_links = 0, +}; + +static struct qcom_icc_node qhs_glm = { + .name = "qhs_glm", + .id = SLAVE_GLM, + .channels = 1, + .buswidth = 4, + .noc_ops = &qcom_qnoc4_ops, + .num_links = 0, +}; + +static struct qcom_icc_node qhs_gpuss_cfg = { + .name = "qhs_gpuss_cfg", + .id = SLAVE_GFX3D_CFG, + .channels = 1, + .buswidth = 8, + .noc_ops = &qcom_qnoc4_ops, + .num_links = 0, +}; + +static struct qcom_icc_node qhs_imem_cfg = { + .name = "qhs_imem_cfg", + .id = SLAVE_IMEM_CFG, + .channels = 1, + .buswidth = 4, + .noc_ops = &qcom_qnoc4_ops, + .num_links = 0, +}; + +static struct qcom_icc_node qhs_ipa = { + .name = "qhs_ipa", + .id = SLAVE_IPA_CFG, + .channels = 1, + .buswidth = 4, + .noc_ops = &qcom_qnoc4_ops, + .num_links = 0, +}; + +static struct qcom_icc_node qhs_mnoc_cfg = { + .name = "qhs_mnoc_cfg", + .id = SLAVE_CNOC_MNOC_CFG, + .channels = 1, + .buswidth = 4, + .noc_ops = &qcom_qnoc4_ops, + .num_links = 1, + .links = { MASTER_CNOC_MNOC_CFG }, +}; + +static struct qcom_icc_node qhs_pdm = { + .name = "qhs_pdm", + .id = SLAVE_PDM, + .channels = 1, + .buswidth = 4, + .noc_ops = &qcom_qnoc4_ops, + .num_links = 0, +}; + +static struct qcom_icc_node qhs_phy_refgen_south = { + .name = "qhs_phy_refgen_south", + .id = SLAVE_SOUTH_PHY_CFG, + .channels = 1, + .buswidth = 4, + .noc_ops = &qcom_qnoc4_ops, + .num_links = 0, +}; + +static struct qcom_icc_node qhs_pimem_cfg = { + .name = "qhs_pimem_cfg", + .id = SLAVE_PIMEM_CFG, + .channels = 1, + .buswidth = 4, + .noc_ops = &qcom_qnoc4_ops, + .num_links = 0, +}; + +static struct qcom_icc_node qhs_prng = { + .name = "qhs_prng", + .id = SLAVE_PRNG, + .channels = 1, + .buswidth = 4, + .noc_ops = &qcom_qnoc4_ops, + .num_links = 0, +}; + +static struct qcom_icc_node qhs_qdss_cfg = { + .name = "qhs_qdss_cfg", + .id = SLAVE_QDSS_CFG, + .channels = 1, + .buswidth = 4, + .noc_ops = &qcom_qnoc4_ops, + .num_links = 0, +}; + +static struct qcom_icc_node qhs_qupv3_north = { + .name = "qhs_qupv3_north", + .id = SLAVE_BLSP_2, + .channels = 1, + .buswidth = 4, + .noc_ops = &qcom_qnoc4_ops, + .num_links = 0, +}; + +static struct qcom_icc_node qhs_qupv3_south = { + .name = "qhs_qupv3_south", + .id = SLAVE_BLSP_1, + .channels = 1, + .buswidth = 4, + .noc_ops = &qcom_qnoc4_ops, + .num_links = 0, +}; + +static struct qcom_icc_node qhs_sdc2 = { + .name = "qhs_sdc2", + .id = SLAVE_SDCC_2, + .channels = 1, + .buswidth = 4, + .noc_ops = &qcom_qnoc4_ops, + .num_links = 0, +}; + +static struct qcom_icc_node qhs_sdc4 = { + .name = "qhs_sdc4", + .id = SLAVE_SDCC_4, + .channels = 1, + .buswidth = 4, + .noc_ops = &qcom_qnoc4_ops, + .num_links = 0, +}; + +static struct qcom_icc_node qhs_snoc_cfg = { + .name = "qhs_snoc_cfg", + .id = SLAVE_SNOC_CFG, + .channels = 1, + .buswidth = 4, + .noc_ops = &qcom_qnoc4_ops, + .num_links = 1, + .links = { MASTER_SNOC_CFG }, +}; + +static struct qcom_icc_node qhs_spdm = { + .name = "qhs_spdm", + .id = SLAVE_SPDM_WRAPPER, + .channels = 1, + .buswidth = 4, + .noc_ops = &qcom_qnoc4_ops, + .num_links = 0, +}; + +static struct qcom_icc_node qhs_tcsr = { + .name = "qhs_tcsr", + .id = SLAVE_TCSR, + .channels = 1, + .buswidth = 4, + .noc_ops = &qcom_qnoc4_ops, + .num_links = 0, +}; + +static struct qcom_icc_node qhs_tlmm_north = { + .name = "qhs_tlmm_north", + .id = SLAVE_TLMM_NORTH, + .channels = 1, + .buswidth = 4, + .noc_ops = &qcom_qnoc4_ops, + .num_links = 0, +}; + +static struct qcom_icc_node qhs_tlmm_south = { + .name = "qhs_tlmm_south", + .id = SLAVE_TLMM_SOUTH, + .channels = 1, + .buswidth = 4, + .noc_ops = &qcom_qnoc4_ops, + .num_links = 0, +}; + +static struct qcom_icc_node qhs_tsif = { + .name = "qhs_tsif", + .id = SLAVE_TSIF, + .channels = 1, + .buswidth = 4, + .noc_ops = &qcom_qnoc4_ops, + .num_links = 0, +}; + +static struct qcom_icc_node qhs_ufs_mem_cfg = { + .name = "qhs_ufs_mem_cfg", + .id = SLAVE_UFS_MEM_CFG, + .channels = 1, + .buswidth = 4, + .noc_ops = &qcom_qnoc4_ops, + .num_links = 0, +}; + +static struct qcom_icc_node qhs_usb3_0 = { + .name = "qhs_usb3_0", + .id = SLAVE_USB3_0, + .channels = 1, + .buswidth = 4, + .noc_ops = &qcom_qnoc4_ops, + .num_links = 0, +}; + +static struct qcom_icc_node qhs_venus_cfg = { + .name = "qhs_venus_cfg", + .id = SLAVE_VENUS_CFG, + .channels = 1, + .buswidth = 4, + .noc_ops = &qcom_qnoc4_ops, + .num_links = 0, +}; + +static struct qcom_icc_node qhs_vsense_ctrl_cfg = { + .name = "qhs_vsense_ctrl_cfg", + .id = SLAVE_VSENSE_CTRL_CFG, + .channels = 1, + .buswidth = 4, + .noc_ops = &qcom_qnoc4_ops, + .num_links = 0, +}; + +static struct qcom_icc_node qns_cnoc_a2noc = { + .name = "qns_cnoc_a2noc", + .id = SLAVE_CNOC_A2NOC, + .channels = 1, + .buswidth = 8, + .noc_ops = &qcom_qnoc4_ops, + .num_links = 1, + .links = { MASTER_CNOC_A2NOC }, +}; + +static struct qcom_icc_node srvc_cnoc = { + .name = "srvc_cnoc", + .id = SLAVE_SERVICE_CNOC, + .channels = 1, + .buswidth = 4, + .noc_ops = &qcom_qnoc4_ops, + .num_links = 0, +}; + +static struct qcom_icc_node qhs_llcc = { + .name = "qhs_llcc", + .id = SLAVE_LLCC_CFG, + .channels = 1, + .buswidth = 4, + .noc_ops = &qcom_qnoc4_ops, + .num_links = 0, +}; + +static struct qcom_icc_node qhs_memnoc = { + .name = "qhs_memnoc", + .id = SLAVE_MEM_NOC_CFG, + .channels = 1, + .buswidth = 4, + .noc_ops = &qcom_qnoc4_ops, + .num_links = 1, + .links = { MASTER_MEM_NOC_CFG }, +}; + +static struct qcom_icc_node qns_gladiator_sodv = { + .name = "qns_gladiator_sodv", + .id = SLAVE_GNOC_SNOC, + .channels = 1, + .buswidth = 8, + .noc_ops = &qcom_qnoc4_ops, + .num_links = 1, + .links = { MASTER_GNOC_SNOC }, +}; + +static struct qcom_icc_node qns_gnoc_memnoc = { + .name = "qns_gnoc_memnoc", + .id = SLAVE_GNOC_MEM_NOC, + .channels = 2, + .buswidth = 32, + .noc_ops = &qcom_qnoc4_ops, + .num_links = 1, + .links = { MASTER_GNOC_MEM_NOC }, +}; + +static struct qcom_icc_node srvc_gnoc = { + .name = "srvc_gnoc", + .id = SLAVE_SERVICE_GNOC, + .channels = 1, + .buswidth = 4, + .noc_ops = &qcom_qnoc4_ops, + .num_links = 0, +}; + +static struct qcom_icc_node ebi = { + .name = "ebi", + .id = SLAVE_EBI1, + .channels = 2, + .buswidth = 4, + .noc_ops = &qcom_qnoc4_ops, + .num_links = 0, +}; + +static struct qcom_icc_node qhs_mdsp_ms_mpu_cfg = { + .name = "qhs_mdsp_ms_mpu_cfg", + .id = SLAVE_MSS_PROC_MS_MPU_CFG, + .channels = 1, + .buswidth = 4, + .noc_ops = &qcom_qnoc4_ops, + .num_links = 0, +}; + +static struct qcom_icc_node qns_apps_io = { + .name = "qns_apps_io", + .id = SLAVE_MEM_NOC_GNOC, + .channels = 1, + .buswidth = 32, + .noc_ops = &qcom_qnoc4_ops, + .num_links = 0, +}; + +static struct qcom_icc_node qns_llcc = { + .name = "qns_llcc", + .id = SLAVE_LLCC, + .channels = 2, + .buswidth = 16, + .noc_ops = &qcom_qnoc4_ops, + .num_links = 1, + .links = { MASTER_LLCC }, +}; + +static struct qcom_icc_node qns_memnoc_snoc = { + .name = "qns_memnoc_snoc", + .id = SLAVE_MEM_NOC_SNOC, + .channels = 1, + .buswidth = 8, + .noc_ops = &qcom_qnoc4_ops, + .num_links = 1, + .links = { MASTER_MEM_NOC_SNOC }, +}; + +static struct qcom_icc_node srvc_memnoc = { + .name = "srvc_memnoc", + .id = SLAVE_SERVICE_MEM_NOC, + .channels = 1, + .buswidth = 4, + .noc_ops = &qcom_qnoc4_ops, + .num_links = 0, +}; + +static struct qcom_icc_node qns2_mem_noc = { + .name = "qns2_mem_noc", + .id = SLAVE_MNOC_SF_MEM_NOC, + .channels = 1, + .buswidth = 32, + .noc_ops = &qcom_qnoc4_ops, + .num_links = 1, + .links = { MASTER_MNOC_SF_MEM_NOC }, +}; + +static struct qcom_icc_node qns_mem_noc_hf = { + .name = "qns_mem_noc_hf", + .id = SLAVE_MNOC_HF_MEM_NOC, + .channels = 2, + .buswidth = 32, + .noc_ops = &qcom_qnoc4_ops, + .num_links = 1, + .links = { MASTER_MNOC_HF_MEM_NOC }, +}; + +static struct qcom_icc_node srvc_mnoc = { + .name = "srvc_mnoc", + .id = SLAVE_SERVICE_MNOC, + .channels = 1, + .buswidth = 4, + .noc_ops = &qcom_qnoc4_ops, + .num_links = 0, +}; + +static struct qcom_icc_node qhs_apss = { + .name = "qhs_apss", + .id = SLAVE_APPSS, + .channels = 1, + .buswidth = 8, + .noc_ops = &qcom_qnoc4_ops, + .num_links = 0, +}; + +static struct qcom_icc_node qns_cnoc = { + .name = "qns_cnoc", + .id = SLAVE_SNOC_CNOC, + .channels = 1, + .buswidth = 8, + .noc_ops = &qcom_qnoc4_ops, + .num_links = 1, + .links = { MASTER_SNOC_CNOC }, +}; + +static struct qcom_icc_node qns_memnoc_gc = { + .name = "qns_memnoc_gc", + .id = SLAVE_SNOC_MEM_NOC_GC, + .channels = 1, + .buswidth = 8, + .noc_ops = &qcom_qnoc4_ops, + .num_links = 1, + .links = { MASTER_SNOC_GC_MEM_NOC }, +}; + +static struct qcom_icc_node qns_memnoc_sf = { + .name = "qns_memnoc_sf", + .id = SLAVE_SNOC_MEM_NOC_SF, + .channels = 1, + .buswidth = 16, + .noc_ops = &qcom_qnoc4_ops, + .num_links = 1, + .links = { MASTER_SNOC_SF_MEM_NOC }, +}; + +static struct qcom_icc_node qxs_imem = { + .name = "qxs_imem", + .id = SLAVE_IMEM, + .channels = 1, + .buswidth = 8, + .noc_ops = &qcom_qnoc4_ops, + .num_links = 0, +}; + +static struct qcom_icc_node qxs_pimem = { + .name = "qxs_pimem", + .id = SLAVE_PIMEM, + .channels = 1, + .buswidth = 8, + .noc_ops = &qcom_qnoc4_ops, + .num_links = 0, +}; + +static struct qcom_icc_node srvc_snoc = { + .name = "srvc_snoc", + .id = SLAVE_SERVICE_SNOC, + .channels = 1, + .buswidth = 4, + .noc_ops = &qcom_qnoc4_ops, + .num_links = 0, +}; + +static struct qcom_icc_node xs_qdss_stm = { + .name = "xs_qdss_stm", + .id = SLAVE_QDSS_STM, + .channels = 1, + .buswidth = 4, + .noc_ops = &qcom_qnoc4_ops, + .num_links = 0, +}; + +static struct qcom_icc_node xs_sys_tcu_cfg = { + .name = "xs_sys_tcu_cfg", + .id = SLAVE_TCU, + .channels = 1, + .buswidth = 8, + .noc_ops = &qcom_qnoc4_ops, + .num_links = 0, +}; + +static struct qcom_icc_node ebi_disp = { + .name = "ebi_disp", + .id = SLAVE_EBI1_DISP, + .channels = 2, + .buswidth = 4, + .noc_ops = &qcom_qnoc4_ops, + .num_links = 0, +}; + +static struct qcom_icc_node qns_llcc_disp = { + .name = "qns_llcc_disp", + .id = SLAVE_LLCC_DISP, + .channels = 2, + .buswidth = 16, + .noc_ops = &qcom_qnoc4_ops, + .num_links = 1, + .links = { MASTER_LLCC_DISP }, +}; + +static struct qcom_icc_node qns2_mem_noc_disp = { + .name = "qns2_mem_noc_disp", + .id = SLAVE_MNOC_SF_MEM_NOC_DISP, + .channels = 1, + .buswidth = 32, + .noc_ops = &qcom_qnoc4_ops, + .num_links = 1, + .links = { MASTER_MNOC_SF_MEM_NOC_DISP }, +}; + +static struct qcom_icc_node qns_mem_noc_hf_disp = { + .name = "qns_mem_noc_hf_disp", + .id = SLAVE_MNOC_HF_MEM_NOC_DISP, + .channels = 2, + .buswidth = 32, + .noc_ops = &qcom_qnoc4_ops, + .num_links = 1, + .links = { MASTER_MNOC_HF_MEM_NOC_DISP }, +}; + +static struct qcom_icc_bcm bcm_acv = { + .name = "ACV", + .voter_idx = VOTER_IDX_HLOS, + .enable_mask = 0x8, + .num_nodes = 1, + .nodes = { &ebi }, +}; + +static struct qcom_icc_bcm bcm_ce0 = { + .name = "CE0", + .voter_idx = VOTER_IDX_HLOS, + .num_nodes = 1, + .nodes = { &qxm_crypto }, +}; + +static struct qcom_icc_bcm bcm_cn0 = { + .name = "CN0", + .voter_idx = VOTER_IDX_HLOS, + .keepalive = true, + .num_nodes = 43, + .nodes = { &qhm_spdm, &qhm_tic, + &qnm_snoc, &xm_qdss_dap, + &qhs_a1_noc_cfg, &qhs_a2_noc_cfg, + &qhs_aop, &qhs_aoss, + &qhs_camera_cfg, &qhs_clk_ctl, + &qhs_compute_dsp_cfg, &qhs_cpr_cx, + &qhs_crypto0_cfg, &qhs_dcc_cfg, + &qhs_ddrss_cfg, &qhs_display_cfg, + &qhs_emmc_cfg, &qhs_glm, + &qhs_gpuss_cfg, &qhs_imem_cfg, + &qhs_ipa, &qhs_mnoc_cfg, + &qhs_pdm, &qhs_phy_refgen_south, + &qhs_pimem_cfg, &qhs_prng, + &qhs_qdss_cfg, &qhs_qupv3_north, + &qhs_qupv3_south, &qhs_sdc2, + &qhs_sdc4, &qhs_snoc_cfg, + &qhs_spdm, &qhs_tcsr, + &qhs_tlmm_north, &qhs_tlmm_south, + &qhs_tsif, &qhs_ufs_mem_cfg, + &qhs_usb3_0, &qhs_venus_cfg, + &qhs_vsense_ctrl_cfg, &qns_cnoc_a2noc, + &srvc_cnoc }, +}; + +static struct qcom_icc_bcm bcm_mc0 = { + .name = "MC0", + .voter_idx = VOTER_IDX_HLOS, + .keepalive = true, + .num_nodes = 1, + .nodes = { &ebi }, +}; + +static struct qcom_icc_bcm bcm_mm0 = { + .name = "MM0", + .voter_idx = VOTER_IDX_HLOS, + .keepalive = true, + .num_nodes = 1, + .nodes = { &qns_mem_noc_hf }, +}; + +static struct qcom_icc_bcm bcm_mm1 = { + .name = "MM1", + .voter_idx = VOTER_IDX_HLOS, + .num_nodes = 7, + .nodes = { &qxm_camnoc_hf0_uncomp, &qxm_camnoc_hf1_uncomp, + &qxm_camnoc_sf_uncomp, &qxm_camnoc_hf0, + &qxm_camnoc_hf1, &qxm_mdp0, + &qxm_mdp1 }, +}; + +static struct qcom_icc_bcm bcm_mm2 = { + .name = "MM2", + .voter_idx = VOTER_IDX_HLOS, + .num_nodes = 1, + .nodes = { &qns2_mem_noc }, +}; + +static struct qcom_icc_bcm bcm_mm3 = { + .name = "MM3", + .voter_idx = VOTER_IDX_HLOS, + .num_nodes = 5, + .nodes = { &qxm_camnoc_sf, &qxm_rot, + &qxm_venus0, &qxm_venus1, + &qxm_venus_arm9 }, +}; + +static struct qcom_icc_bcm bcm_qup0 = { + .name = "QUP0", + .voter_idx = VOTER_IDX_HLOS, + .keepalive = true, + .vote_scale = 1, + .num_nodes = 2, + .nodes = { &qhm_qup1, &qhm_qup2 }, +}; + +static struct qcom_icc_bcm bcm_sh0 = { + .name = "SH0", + .voter_idx = VOTER_IDX_HLOS, + .keepalive = true, + .num_nodes = 1, + .nodes = { &qns_llcc }, +}; + +static struct qcom_icc_bcm bcm_sh1 = { + .name = "SH1", + .voter_idx = VOTER_IDX_HLOS, + .num_nodes = 1, + .nodes = { &qns_apps_io }, +}; + +static struct qcom_icc_bcm bcm_sh2 = { + .name = "SH2", + .voter_idx = VOTER_IDX_HLOS, + .num_nodes = 1, + .nodes = { &qns_memnoc_snoc }, +}; + +static struct qcom_icc_bcm bcm_sh3 = { + .name = "SH3", + .voter_idx = VOTER_IDX_HLOS, + .num_nodes = 1, + .nodes = { &acm_tcu }, +}; + +static struct qcom_icc_bcm bcm_sh5 = { + .name = "SH5", + .voter_idx = VOTER_IDX_HLOS, + .num_nodes = 1, + .nodes = { &qnm_apps }, +}; + +static struct qcom_icc_bcm bcm_sn0 = { + .name = "SN0", + .voter_idx = VOTER_IDX_HLOS, + .keepalive = true, + .num_nodes = 1, + .nodes = { &qns_memnoc_sf }, +}; + +static struct qcom_icc_bcm bcm_sn1 = { + .name = "SN1", + .voter_idx = VOTER_IDX_HLOS, + .num_nodes = 1, + .nodes = { &qxs_imem }, +}; + +static struct qcom_icc_bcm bcm_sn2 = { + .name = "SN2", + .voter_idx = VOTER_IDX_HLOS, + .num_nodes = 1, + .nodes = { &qns_memnoc_gc }, +}; + +static struct qcom_icc_bcm bcm_sn3 = { + .name = "SN3", + .voter_idx = VOTER_IDX_HLOS, + .num_nodes = 1, + .nodes = { &qns_cnoc }, +}; + +static struct qcom_icc_bcm bcm_sn4 = { + .name = "SN4", + .voter_idx = VOTER_IDX_HLOS, + .num_nodes = 2, + .nodes = { &qxm_pimem, &qxs_pimem }, +}; + +static struct qcom_icc_bcm bcm_sn5 = { + .name = "SN5", + .voter_idx = VOTER_IDX_HLOS, + .num_nodes = 1, + .nodes = { &xs_qdss_stm }, +}; + +static struct qcom_icc_bcm bcm_sn8 = { + .name = "SN8", + .voter_idx = VOTER_IDX_HLOS, + .num_nodes = 2, + .nodes = { &srvc_aggre1_noc, &qnm_aggre1_noc }, +}; + +static struct qcom_icc_bcm bcm_sn10 = { + .name = "SN10", + .voter_idx = VOTER_IDX_HLOS, + .num_nodes = 2, + .nodes = { &srvc_aggre2_noc, &qnm_aggre2_noc }, +}; + +static struct qcom_icc_bcm bcm_sn11 = { + .name = "SN11", + .voter_idx = VOTER_IDX_HLOS, + .num_nodes = 2, + .nodes = { &qnm_gladiator_sodv, &xm_gic }, +}; + +static struct qcom_icc_bcm bcm_sn13 = { + .name = "SN13", + .voter_idx = VOTER_IDX_HLOS, + .num_nodes = 1, + .nodes = { &qnm_memnoc }, +}; + +static struct qcom_icc_bcm bcm_acv_disp = { + .name = "ACV", + .voter_idx = VOTER_IDX_DISP, + .enable_mask = 0x1, + .num_nodes = 1, + .nodes = { &ebi_disp }, +}; + +static struct qcom_icc_bcm bcm_mc0_disp = { + .name = "MC0", + .voter_idx = VOTER_IDX_DISP, + .num_nodes = 1, + .nodes = { &ebi_disp }, +}; + +static struct qcom_icc_bcm bcm_mm0_disp = { + .name = "MM0", + .voter_idx = VOTER_IDX_DISP, + .num_nodes = 1, + .nodes = { &qns_mem_noc_hf_disp }, +}; + +static struct qcom_icc_bcm bcm_mm1_disp = { + .name = "MM1", + .voter_idx = VOTER_IDX_DISP, + .num_nodes = 2, + .nodes = { &qxm_mdp0_disp, &qxm_mdp1_disp }, +}; + +static struct qcom_icc_bcm bcm_mm2_disp = { + .name = "MM2", + .voter_idx = VOTER_IDX_DISP, + .num_nodes = 1, + .nodes = { &qns2_mem_noc_disp }, +}; + +static struct qcom_icc_bcm bcm_mm3_disp = { + .name = "MM3", + .voter_idx = VOTER_IDX_DISP, + .num_nodes = 1, + .nodes = { &qxm_rot_disp }, +}; + +static struct qcom_icc_bcm bcm_sh0_disp = { + .name = "SH0", + .voter_idx = VOTER_IDX_DISP, + .num_nodes = 1, + .nodes = { &qns_llcc_disp }, +}; + +static struct qcom_icc_bcm *aggre1_noc_bcms[] = { + &bcm_qup0, + &bcm_sn8, +}; + +static struct qcom_icc_node *aggre1_noc_nodes[] = { + [MASTER_A1NOC_CFG] = &qhm_a1noc_cfg, + [MASTER_BLSP_1] = &qhm_qup1, + [MASTER_TSIF] = &qhm_tsif, + [MASTER_EMMC] = &xm_emmc, + [MASTER_SDCC_2] = &xm_sdc2, + [MASTER_SDCC_4] = &xm_sdc4, + [MASTER_UFS_MEM] = &xm_ufs_mem, + [SLAVE_A1NOC_SNOC] = &qns_a1noc_snoc, + [SLAVE_SERVICE_A1NOC] = &srvc_aggre1_noc, +}; + +static char *aggre1_noc_voters[] = { + [VOTER_IDX_HLOS] = "hlos", +}; + +static struct qcom_icc_desc sdm670_aggre1_noc = { + .config = &icc_regmap_config, + .nodes = aggre1_noc_nodes, + .num_nodes = ARRAY_SIZE(aggre1_noc_nodes), + .bcms = aggre1_noc_bcms, + .num_bcms = ARRAY_SIZE(aggre1_noc_bcms), + .voters = aggre1_noc_voters, + .num_voters = ARRAY_SIZE(aggre1_noc_voters), +}; + +static struct qcom_icc_bcm *aggre2_noc_bcms[] = { + &bcm_ce0, + &bcm_qup0, + &bcm_sn10, +}; + +static struct qcom_icc_node *aggre2_noc_nodes[] = { + [MASTER_A2NOC_CFG] = &qhm_a2noc_cfg, + [MASTER_QDSS_BAM] = &qhm_qdss_bam, + [MASTER_BLSP_2] = &qhm_qup2, + [MASTER_CNOC_A2NOC] = &qnm_cnoc, + [MASTER_CRYPTO] = &qxm_crypto, + [MASTER_IPA] = &qxm_ipa, + [MASTER_QDSS_ETR] = &xm_qdss_etr, + [MASTER_USB3_0] = &xm_usb3_0, + [SLAVE_A2NOC_SNOC] = &qns_a2noc_snoc, + [SLAVE_SERVICE_A2NOC] = &srvc_aggre2_noc, +}; + +static char *aggre2_noc_voters[] = { + [VOTER_IDX_HLOS] = "hlos", +}; + +static struct qcom_icc_desc sdm670_aggre2_noc = { + .config = &icc_regmap_config, + .nodes = aggre2_noc_nodes, + .num_nodes = ARRAY_SIZE(aggre2_noc_nodes), + .bcms = aggre2_noc_bcms, + .num_bcms = ARRAY_SIZE(aggre2_noc_bcms), + .voters = aggre2_noc_voters, + .num_voters = ARRAY_SIZE(aggre2_noc_voters), +}; + +static struct qcom_icc_bcm *camnoc_virt_bcms[] = { + &bcm_mm1, +}; + +static struct qcom_icc_node *camnoc_virt_nodes[] = { + [MASTER_CAMNOC_HF0_UNCOMP] = &qxm_camnoc_hf0_uncomp, + [MASTER_CAMNOC_HF1_UNCOMP] = &qxm_camnoc_hf1_uncomp, + [MASTER_CAMNOC_SF_UNCOMP] = &qxm_camnoc_sf_uncomp, + [SLAVE_CAMNOC_UNCOMP] = &qns_camnoc_uncomp, +}; + +static char *camnoc_virt_voters[] = { + [VOTER_IDX_HLOS] = "hlos", +}; + +static struct qcom_icc_desc sdm670_camnoc_virt = { + .config = &icc_regmap_config, + .nodes = camnoc_virt_nodes, + .num_nodes = ARRAY_SIZE(camnoc_virt_nodes), + .bcms = camnoc_virt_bcms, + .num_bcms = ARRAY_SIZE(camnoc_virt_bcms), + .voters = camnoc_virt_voters, + .num_voters = ARRAY_SIZE(camnoc_virt_voters), +}; + +static struct qcom_icc_bcm *config_noc_bcms[] = { + &bcm_cn0, +}; + +static struct qcom_icc_node *config_noc_nodes[] = { + [MASTER_SPDM] = &qhm_spdm, + [MASTER_TIC] = &qhm_tic, + [MASTER_SNOC_CNOC] = &qnm_snoc, + [MASTER_QDSS_DAP] = &xm_qdss_dap, + [SLAVE_A1NOC_CFG] = &qhs_a1_noc_cfg, + [SLAVE_A2NOC_CFG] = &qhs_a2_noc_cfg, + [SLAVE_AOP] = &qhs_aop, + [SLAVE_AOSS] = &qhs_aoss, + [SLAVE_CAMERA_CFG] = &qhs_camera_cfg, + [SLAVE_CLK_CTL] = &qhs_clk_ctl, + [SLAVE_CDSP_CFG] = &qhs_compute_dsp_cfg, + [SLAVE_RBCPR_CX_CFG] = &qhs_cpr_cx, + [SLAVE_CRYPTO_0_CFG] = &qhs_crypto0_cfg, + [SLAVE_DCC_CFG] = &qhs_dcc_cfg, + [SLAVE_CNOC_DDRSS] = &qhs_ddrss_cfg, + [SLAVE_DISPLAY_CFG] = &qhs_display_cfg, + [SLAVE_EMMC_CFG] = &qhs_emmc_cfg, + [SLAVE_GLM] = &qhs_glm, + [SLAVE_GFX3D_CFG] = &qhs_gpuss_cfg, + [SLAVE_IMEM_CFG] = &qhs_imem_cfg, + [SLAVE_IPA_CFG] = &qhs_ipa, + [SLAVE_CNOC_MNOC_CFG] = &qhs_mnoc_cfg, + [SLAVE_PDM] = &qhs_pdm, + [SLAVE_SOUTH_PHY_CFG] = &qhs_phy_refgen_south, + [SLAVE_PIMEM_CFG] = &qhs_pimem_cfg, + [SLAVE_PRNG] = &qhs_prng, + [SLAVE_QDSS_CFG] = &qhs_qdss_cfg, + [SLAVE_BLSP_2] = &qhs_qupv3_north, + [SLAVE_BLSP_1] = &qhs_qupv3_south, + [SLAVE_SDCC_2] = &qhs_sdc2, + [SLAVE_SDCC_4] = &qhs_sdc4, + [SLAVE_SNOC_CFG] = &qhs_snoc_cfg, + [SLAVE_SPDM_WRAPPER] = &qhs_spdm, + [SLAVE_TCSR] = &qhs_tcsr, + [SLAVE_TLMM_NORTH] = &qhs_tlmm_north, + [SLAVE_TLMM_SOUTH] = &qhs_tlmm_south, + [SLAVE_TSIF] = &qhs_tsif, + [SLAVE_UFS_MEM_CFG] = &qhs_ufs_mem_cfg, + [SLAVE_USB3_0] = &qhs_usb3_0, + [SLAVE_VENUS_CFG] = &qhs_venus_cfg, + [SLAVE_VSENSE_CTRL_CFG] = &qhs_vsense_ctrl_cfg, + [SLAVE_CNOC_A2NOC] = &qns_cnoc_a2noc, + [SLAVE_SERVICE_CNOC] = &srvc_cnoc, +}; + +static char *config_noc_voters[] = { + [VOTER_IDX_HLOS] = "hlos", +}; + +static struct qcom_icc_desc sdm670_config_noc = { + .config = &icc_regmap_config, + .nodes = config_noc_nodes, + .num_nodes = ARRAY_SIZE(config_noc_nodes), + .bcms = config_noc_bcms, + .num_bcms = ARRAY_SIZE(config_noc_bcms), + .voters = config_noc_voters, + .num_voters = ARRAY_SIZE(config_noc_voters), +}; + +static struct qcom_icc_bcm *dc_noc_bcms[] = { +}; + +static struct qcom_icc_node *dc_noc_nodes[] = { + [MASTER_CNOC_DC_NOC] = &qhm_cnoc, + [SLAVE_LLCC_CFG] = &qhs_llcc, + [SLAVE_MEM_NOC_CFG] = &qhs_memnoc, +}; + +static char *dc_noc_voters[] = { + [VOTER_IDX_HLOS] = "hlos", +}; + +static struct qcom_icc_desc sdm670_dc_noc = { + .config = &icc_regmap_config, + .nodes = dc_noc_nodes, + .num_nodes = ARRAY_SIZE(dc_noc_nodes), + .bcms = dc_noc_bcms, + .num_bcms = ARRAY_SIZE(dc_noc_bcms), + .voters = dc_noc_voters, + .num_voters = ARRAY_SIZE(dc_noc_voters), +}; + +static struct qcom_icc_bcm *gladiator_noc_bcms[] = { +}; + +static struct qcom_icc_node *gladiator_noc_nodes[] = { + [MASTER_APPSS_PROC] = &acm_l3, + [MASTER_GNOC_CFG] = &pm_gnoc_cfg, + [SLAVE_GNOC_SNOC] = &qns_gladiator_sodv, + [SLAVE_GNOC_MEM_NOC] = &qns_gnoc_memnoc, + [SLAVE_SERVICE_GNOC] = &srvc_gnoc, +}; + +static char *gladiator_noc_voters[] = { + [VOTER_IDX_HLOS] = "hlos", +}; + +static struct qcom_icc_desc sdm670_gladiator_noc = { + .config = &icc_regmap_config, + .nodes = gladiator_noc_nodes, + .num_nodes = ARRAY_SIZE(gladiator_noc_nodes), + .bcms = gladiator_noc_bcms, + .num_bcms = ARRAY_SIZE(gladiator_noc_bcms), + .voters = gladiator_noc_voters, + .num_voters = ARRAY_SIZE(gladiator_noc_voters), +}; + +static struct qcom_icc_bcm *mc_virt_bcms[] = { + &bcm_acv, + &bcm_mc0, + &bcm_acv_disp, + &bcm_mc0_disp, +}; + +static struct qcom_icc_node *mc_virt_nodes[] = { + [MASTER_LLCC] = &llcc_mc, + [SLAVE_EBI1] = &ebi, + [MASTER_LLCC_DISP] = &llcc_mc_disp, + [SLAVE_EBI1_DISP] = &ebi_disp, +}; + +static char *mc_virt_voters[] = { + [VOTER_IDX_HLOS] = "hlos", + [VOTER_IDX_DISP] = "disp", +}; + +static struct qcom_icc_desc sdm670_mc_virt = { + .config = &icc_regmap_config, + .nodes = mc_virt_nodes, + .num_nodes = ARRAY_SIZE(mc_virt_nodes), + .bcms = mc_virt_bcms, + .num_bcms = ARRAY_SIZE(mc_virt_bcms), + .voters = mc_virt_voters, + .num_voters = ARRAY_SIZE(mc_virt_voters), +}; + +static struct qcom_icc_bcm *mem_noc_bcms[] = { + &bcm_sh0, + &bcm_sh1, + &bcm_sh2, + &bcm_sh3, + &bcm_sh5, + &bcm_sh0_disp, +}; + +static struct qcom_icc_node *mem_noc_nodes[] = { + [MASTER_TCU_0] = &acm_tcu, + [MASTER_MEM_NOC_CFG] = &qhm_memnoc_cfg, + [MASTER_GNOC_MEM_NOC] = &qnm_apps, + [MASTER_MNOC_HF_MEM_NOC] = &qnm_mnoc_hf, + [MASTER_MNOC_SF_MEM_NOC] = &qnm_mnoc_sf, + [MASTER_SNOC_GC_MEM_NOC] = &qnm_snoc_gc, + [MASTER_SNOC_SF_MEM_NOC] = &qnm_snoc_sf, + [MASTER_GFX3D] = &qxm_gpu, + [SLAVE_MSS_PROC_MS_MPU_CFG] = &qhs_mdsp_ms_mpu_cfg, + [SLAVE_MEM_NOC_GNOC] = &qns_apps_io, + [SLAVE_LLCC] = &qns_llcc, + [SLAVE_MEM_NOC_SNOC] = &qns_memnoc_snoc, + [SLAVE_SERVICE_MEM_NOC] = &srvc_memnoc, + [MASTER_MNOC_HF_MEM_NOC_DISP] = &qnm_mnoc_hf_disp, + [MASTER_MNOC_SF_MEM_NOC_DISP] = &qnm_mnoc_sf_disp, + [SLAVE_LLCC_DISP] = &qns_llcc_disp, +}; + +static char *mem_noc_voters[] = { + [VOTER_IDX_HLOS] = "hlos", + [VOTER_IDX_DISP] = "disp", +}; + +static struct qcom_icc_desc sdm670_mem_noc = { + .config = &icc_regmap_config, + .nodes = mem_noc_nodes, + .num_nodes = ARRAY_SIZE(mem_noc_nodes), + .bcms = mem_noc_bcms, + .num_bcms = ARRAY_SIZE(mem_noc_bcms), + .voters = mem_noc_voters, + .num_voters = ARRAY_SIZE(mem_noc_voters), +}; + +static struct qcom_icc_bcm *mmss_noc_bcms[] = { + &bcm_mm0, + &bcm_mm1, + &bcm_mm2, + &bcm_mm3, + &bcm_mm0_disp, + &bcm_mm1_disp, + &bcm_mm2_disp, + &bcm_mm3_disp, +}; + +static struct qcom_icc_node *mmss_noc_nodes[] = { + [MASTER_CNOC_MNOC_CFG] = &qhm_mnoc_cfg, + [MASTER_CAMNOC_HF0] = &qxm_camnoc_hf0, + [MASTER_CAMNOC_HF1] = &qxm_camnoc_hf1, + [MASTER_CAMNOC_SF] = &qxm_camnoc_sf, + [MASTER_MDP0] = &qxm_mdp0, + [MASTER_MDP1] = &qxm_mdp1, + [MASTER_ROTATOR] = &qxm_rot, + [MASTER_VIDEO_P0] = &qxm_venus0, + [MASTER_VIDEO_P1] = &qxm_venus1, + [MASTER_VIDEO_PROC] = &qxm_venus_arm9, + [SLAVE_MNOC_SF_MEM_NOC] = &qns2_mem_noc, + [SLAVE_MNOC_HF_MEM_NOC] = &qns_mem_noc_hf, + [SLAVE_SERVICE_MNOC] = &srvc_mnoc, + [MASTER_MDP0_DISP] = &qxm_mdp0_disp, + [MASTER_MDP1_DISP] = &qxm_mdp1_disp, + [MASTER_ROTATOR_DISP] = &qxm_rot_disp, + [SLAVE_MNOC_SF_MEM_NOC_DISP] = &qns2_mem_noc_disp, + [SLAVE_MNOC_HF_MEM_NOC_DISP] = &qns_mem_noc_hf_disp, +}; + +static char *mmss_noc_voters[] = { + [VOTER_IDX_HLOS] = "hlos", + [VOTER_IDX_DISP] = "disp", +}; + +static struct qcom_icc_desc sdm670_mmss_noc = { + .config = &icc_regmap_config, + .nodes = mmss_noc_nodes, + .num_nodes = ARRAY_SIZE(mmss_noc_nodes), + .bcms = mmss_noc_bcms, + .num_bcms = ARRAY_SIZE(mmss_noc_bcms), + .voters = mmss_noc_voters, + .num_voters = ARRAY_SIZE(mmss_noc_voters), +}; + +static struct qcom_icc_bcm *system_noc_bcms[] = { + &bcm_sn0, + &bcm_sn1, + &bcm_sn2, + &bcm_sn3, + &bcm_sn4, + &bcm_sn5, + &bcm_sn8, + &bcm_sn10, + &bcm_sn11, + &bcm_sn13, +}; + +static struct qcom_icc_node *system_noc_nodes[] = { + [MASTER_SNOC_CFG] = &qhm_snoc_cfg, + [MASTER_A1NOC_SNOC] = &qnm_aggre1_noc, + [MASTER_A2NOC_SNOC] = &qnm_aggre2_noc, + [MASTER_GNOC_SNOC] = &qnm_gladiator_sodv, + [MASTER_MEM_NOC_SNOC] = &qnm_memnoc, + [MASTER_PIMEM] = &qxm_pimem, + [MASTER_GIC] = &xm_gic, + [SLAVE_APPSS] = &qhs_apss, + [SLAVE_SNOC_CNOC] = &qns_cnoc, + [SLAVE_SNOC_MEM_NOC_GC] = &qns_memnoc_gc, + [SLAVE_SNOC_MEM_NOC_SF] = &qns_memnoc_sf, + [SLAVE_IMEM] = &qxs_imem, + [SLAVE_PIMEM] = &qxs_pimem, + [SLAVE_SERVICE_SNOC] = &srvc_snoc, + [SLAVE_QDSS_STM] = &xs_qdss_stm, + [SLAVE_TCU] = &xs_sys_tcu_cfg, +}; + +static char *system_noc_voters[] = { + [VOTER_IDX_HLOS] = "hlos", +}; + +static struct qcom_icc_desc sdm670_system_noc = { + .config = &icc_regmap_config, + .nodes = system_noc_nodes, + .num_nodes = ARRAY_SIZE(system_noc_nodes), + .bcms = system_noc_bcms, + .num_bcms = ARRAY_SIZE(system_noc_bcms), + .voters = system_noc_voters, + .num_voters = ARRAY_SIZE(system_noc_voters), +}; + +static int qnoc_probe(struct platform_device *pdev) +{ + int ret; + + ret = qcom_icc_rpmh_probe(pdev); + if (ret) + dev_err(&pdev->dev, "failed to register ICC provider: %d\n", ret); + else + dev_info(&pdev->dev, "Registered ICC provider\n"); + + return ret; +} + +static const struct of_device_id qnoc_of_match[] = { + { .compatible = "qcom,sdm670-aggre1_noc", + .data = &sdm670_aggre1_noc}, + { .compatible = "qcom,sdm670-aggre2_noc", + .data = &sdm670_aggre2_noc}, + { .compatible = "qcom,sdm670-camnoc_virt", + .data = &sdm670_camnoc_virt}, + { .compatible = "qcom,sdm670-config_noc", + .data = &sdm670_config_noc}, + { .compatible = "qcom,sdm670-dc_noc", + .data = &sdm670_dc_noc}, + { .compatible = "qcom,sdm670-gladiator_noc", + .data = &sdm670_gladiator_noc}, + { .compatible = "qcom,sdm670-mc_virt", + .data = &sdm670_mc_virt}, + { .compatible = "qcom,sdm670-mem_noc", + .data = &sdm670_mem_noc}, + { .compatible = "qcom,sdm670-mmss_noc", + .data = &sdm670_mmss_noc}, + { .compatible = "qcom,sdm670-system_noc", + .data = &sdm670_system_noc}, + { } +}; +MODULE_DEVICE_TABLE(of, qnoc_of_match); + +static struct platform_driver qnoc_driver = { + .probe = qnoc_probe, + .remove = qcom_icc_rpmh_remove, + .driver = { + .name = "qnoc-sdm670", + .of_match_table = qnoc_of_match, + .sync_state = qcom_icc_rpmh_sync_state, + }, +}; + +static int __init qnoc_driver_init(void) +{ + return platform_driver_register(&qnoc_driver); +} +core_initcall(qnoc_driver_init); + +MODULE_DESCRIPTION("Sdm670 NoC driver"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/iommu/arm/arm-smmu-v3/virt-arm-smmu-v3.c b/drivers/iommu/arm/arm-smmu-v3/virt-arm-smmu-v3.c index dc47e3e5a2e2..5915e22bfb2f 100644 --- a/drivers/iommu/arm/arm-smmu-v3/virt-arm-smmu-v3.c +++ b/drivers/iommu/arm/arm-smmu-v3/virt-arm-smmu-v3.c @@ -506,7 +506,7 @@ static unsigned long get_sid_from_smmu_domain(struct virt_arm_smmu_domain *smmu_ { struct virt_arm_smmu_master *master; unsigned long flags; - u64 sid; + u64 sid = 0; u16 i; spin_lock_irqsave(&smmu_domain->devices_lock, flags); diff --git a/drivers/iommu/arm/arm-smmu/arm-smmu.c b/drivers/iommu/arm/arm-smmu/arm-smmu.c index c3b7306633d2..e2eac342c8c0 100644 --- a/drivers/iommu/arm/arm-smmu/arm-smmu.c +++ b/drivers/iommu/arm/arm-smmu/arm-smmu.c @@ -4121,10 +4121,9 @@ static int __maybe_unused arm_smmu_pm_restore_early(struct device *dev) smmu_domain->pgtbl_ops = pgtbl_ops; arm_smmu_init_context_bank(smmu_domain, pgtbl_cfg); } - arm_smmu_pm_resume_common(dev); - ret = arm_smmu_runtime_suspend(dev); + ret = arm_smmu_pm_resume_common(dev); if (ret) { - dev_err(dev, "Failed to suspend\n"); + dev_err(dev, "Failed to resume\n"); return ret; } return 0; @@ -4135,7 +4134,7 @@ static int __maybe_unused arm_smmu_pm_freeze_late(struct device *dev) struct arm_smmu_device *smmu = dev_get_drvdata(dev); struct arm_smmu_domain *smmu_domain; struct arm_smmu_cb *cb; - int idx; + int idx, ret; for (idx = 0; idx < smmu->num_context_banks; idx++) { cb = &smmu->cbs[idx]; @@ -4147,6 +4146,11 @@ static int __maybe_unused arm_smmu_pm_freeze_late(struct device *dev) } } } + ret = arm_smmu_runtime_suspend(dev); + if (ret) { + dev_err(dev, "Failed to suspend\n"); + return ret; + } return 0; } @@ -4175,7 +4179,7 @@ static int __maybe_unused arm_smmu_pm_suspend(struct device *dev) struct arm_smmu_device *smmu = dev_get_drvdata(dev); if (pm_suspend_via_firmware()) - arm_smmu_pm_freeze_late(dev); + return arm_smmu_pm_freeze_late(dev); if (pm_runtime_suspended(dev)) goto clk_unprepare; diff --git a/drivers/iommu/dma-iommu.c b/drivers/iommu/dma-iommu.c index c62745c1055d..7e7064ff572e 100644 --- a/drivers/iommu/dma-iommu.c +++ b/drivers/iommu/dma-iommu.c @@ -628,6 +628,7 @@ static struct page **__iommu_dma_alloc_pages(struct device *dev, order_size = 1U << order; if (order_mask > order_size) alloc_flags |= __GFP_NORETRY; + trace_android_vh_adjust_alloc_flags(order, &alloc_flags); page = alloc_pages_node(nid, alloc_flags, order); if (!page) continue; diff --git a/drivers/iommu/dma-mapping-fast.c b/drivers/iommu/dma-mapping-fast.c index 075dfbf98e1f..d5ae14b1b011 100644 --- a/drivers/iommu/dma-mapping-fast.c +++ b/drivers/iommu/dma-mapping-fast.c @@ -16,7 +16,7 @@ #include #include #include -#include +#include #include #include #include "qcom-dma-iommu-generic.h" diff --git a/drivers/irqchip/irq-jcore-aic.c b/drivers/irqchip/irq-jcore-aic.c index 5f47d8ee4ae3..b9dcc8e78c75 100644 --- a/drivers/irqchip/irq-jcore-aic.c +++ b/drivers/irqchip/irq-jcore-aic.c @@ -68,6 +68,7 @@ static int __init aic_irq_of_init(struct device_node *node, unsigned min_irq = JCORE_AIC2_MIN_HWIRQ; unsigned dom_sz = JCORE_AIC_MAX_HWIRQ+1; struct irq_domain *domain; + int ret; pr_info("Initializing J-Core AIC\n"); @@ -100,6 +101,12 @@ static int __init aic_irq_of_init(struct device_node *node, jcore_aic.irq_unmask = noop; jcore_aic.name = "AIC"; + ret = irq_alloc_descs(-1, min_irq, dom_sz - min_irq, + of_node_to_nid(node)); + + if (ret < 0) + return ret; + domain = irq_domain_add_legacy(node, dom_sz - min_irq, min_irq, min_irq, &jcore_aic_irqdomain_ops, &jcore_aic); diff --git a/drivers/irqchip/qcom-mpm.c b/drivers/irqchip/qcom-mpm.c index 94b00afd0c6a..efaa7b74c3ff 100644 --- a/drivers/irqchip/qcom-mpm.c +++ b/drivers/irqchip/qcom-mpm.c @@ -691,7 +691,7 @@ const struct mpm_pin mpm_monaco_gic_chip_data[] = { }; const struct mpm_pin mpm_trinket_gic_chip_data[] = { - {2, 190}, + {2, 275}, {12, 422}, /* b3_lfps_rxterm_irq */ {86, 183}, /* mpm_wake,spmi_m */ {90, 260}, /* eud_p0_dpse_int_mx */ diff --git a/drivers/leds/trigger/ledtrig-netdev.c b/drivers/leds/trigger/ledtrig-netdev.c index d5e774d83021..f4d670ec30bc 100644 --- a/drivers/leds/trigger/ledtrig-netdev.c +++ b/drivers/leds/trigger/ledtrig-netdev.c @@ -318,6 +318,9 @@ static int netdev_trig_notify(struct notifier_block *nb, clear_bit(NETDEV_LED_MODE_LINKUP, &trigger_data->mode); switch (evt) { case NETDEV_CHANGENAME: + if (netif_carrier_ok(dev)) + set_bit(NETDEV_LED_MODE_LINKUP, &trigger_data->mode); + fallthrough; case NETDEV_REGISTER: if (trigger_data->net_dev) dev_put(trigger_data->net_dev); diff --git a/drivers/mailbox/msm_qmp.c b/drivers/mailbox/msm_qmp.c index 2941ba08ce20..339afead370d 100644 --- a/drivers/mailbox/msm_qmp.c +++ b/drivers/mailbox/msm_qmp.c @@ -1,6 +1,7 @@ // SPDX-License-Identifier: GPL-2.0-only /* * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved. + * Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved. */ #include @@ -20,6 +21,7 @@ #include #include #include +#include #define QMP_MAGIC 0x4d41494c /* MAIL */ #define QMP_VERSION 0x1 @@ -190,6 +192,7 @@ struct qmp_mbox { * @tx_irq_count: Number of tx interrupts triggered * @rx_irq_count: Number of rx interrupts received * @ilc: IPC logging context + * @ds_entry: Deep sleep entry flag */ struct qmp_device { struct device *dev; @@ -212,6 +215,7 @@ struct qmp_device { void *ilc; bool early_boot; + bool ds_entry; }; /** @@ -392,6 +396,9 @@ static int qmp_send_data(struct mbox_chan *chan, void *data) mdev = mbox->mdev; + if (mdev->ds_entry) + return -ENXIO; + spin_lock_irqsave(&mbox->tx_lock, flags); addr = mbox->desc + mbox->mcore_mbox_offset; if (mbox->tx_sent) { @@ -858,6 +865,9 @@ static int qmp_shim_send_data(struct mbox_chan *chan, void *data) mdev = mbox->mdev; + if (mdev->ds_entry) + return -ENXIO; + if (pkt->size > SZ_4K) return -EINVAL; @@ -972,6 +982,7 @@ static int qmp_mbox_init(struct device_node *n, struct qmp_device *mdev) INIT_DELAYED_WORK(&mbox->dwork, qmp_notify_timeout); mbox->suspend_flag = false; + mdev->ds_entry = false; mdev_add_mbox(mdev, mbox); return 0; } @@ -1074,6 +1085,8 @@ static int qmp_shim_init(struct platform_device *pdev, struct qmp_device *mdev) mdev->ilc = ipc_log_context_create(QMP_IPC_LOG_PAGE_CNT, mdev->name, 0); + mdev->ds_entry = false; + return 0; } @@ -1233,6 +1246,11 @@ static int qmp_mbox_restore(struct device *dev) { struct qmp_device *mdev = dev_get_drvdata(dev); struct qmp_mbox *mbox; + struct device_node *edge_node = dev->of_node; + + /* skip negotiation if device has shim layer */ + if (of_parse_phandle(edge_node, "qcom,qmp", 0)) + goto end; list_for_each_entry(mbox, &mdev->mboxes, list) { mbox->local_state = LINK_DISCONNECTED; @@ -1250,13 +1268,42 @@ static int qmp_mbox_restore(struct device *dev) if (mdev->early_boot) __qmp_rx_worker(mbox); } +end: + if (mdev->ds_entry) + mdev->ds_entry = false; return 0; } +static int qmp_mbox_suspend_noirq(struct device *dev) +{ + struct qmp_device *mdev = dev_get_drvdata(dev); + + if (pm_suspend_via_firmware()) { + mdev->ds_entry = true; + dev_info(dev, "QMP: Deep sleep entry\n"); + } + + return 0; +} + +static int qmp_mbox_resume_noirq(struct device *dev) +{ + int ret = 0; + + if (pm_suspend_via_firmware()) { + ret = qmp_mbox_restore(dev); + dev_info(dev, "QMP: Deep sleep exit\n"); + } + + return ret; +} + static const struct dev_pm_ops qmp_mbox_pm_ops = { .freeze_late = qmp_mbox_freeze, .restore_early = qmp_mbox_restore, + .suspend_noirq = qmp_mbox_suspend_noirq, + .resume_noirq = qmp_mbox_resume_noirq, }; static const struct of_device_id qmp_mbox_dt_match[] = { diff --git a/drivers/mailbox/ti-msgmgr.c b/drivers/mailbox/ti-msgmgr.c index efb43b038596..fa71ae837d23 100644 --- a/drivers/mailbox/ti-msgmgr.c +++ b/drivers/mailbox/ti-msgmgr.c @@ -385,14 +385,20 @@ static int ti_msgmgr_send_data(struct mbox_chan *chan, void *data) /* Ensure all unused data is 0 */ data_trail &= 0xFFFFFFFF >> (8 * (sizeof(u32) - trail_bytes)); writel(data_trail, data_reg); - data_reg++; + data_reg += sizeof(u32); } + /* * 'data_reg' indicates next register to write. If we did not already * write on tx complete reg(last reg), we must do so for transmit + * In addition, we also need to make sure all intermediate data + * registers(if any required), are reset to 0 for TISCI backward + * compatibility to be maintained. */ - if (data_reg <= qinst->queue_buff_end) - writel(0, qinst->queue_buff_end); + while (data_reg <= qinst->queue_buff_end) { + writel(0, data_reg); + data_reg += sizeof(u32); + } return 0; } diff --git a/drivers/md/bcache/btree.c b/drivers/md/bcache/btree.c index 98daa9d200f7..88097d1892ac 100644 --- a/drivers/md/bcache/btree.c +++ b/drivers/md/bcache/btree.c @@ -885,7 +885,7 @@ static struct btree *mca_cannibalize(struct cache_set *c, struct btree_op *op, * cannibalize_bucket() will take. This means every time we unlock the root of * the btree, we need to release this lock if we have it held. */ -static void bch_cannibalize_unlock(struct cache_set *c) +void bch_cannibalize_unlock(struct cache_set *c) { spin_lock(&c->btree_cannibalize_lock); if (c->btree_cache_alloc_lock == current) { @@ -1090,10 +1090,12 @@ struct btree *__bch_btree_node_alloc(struct cache_set *c, struct btree_op *op, struct btree *parent) { BKEY_PADDED(key) k; - struct btree *b = ERR_PTR(-EAGAIN); + struct btree *b; mutex_lock(&c->bucket_lock); retry: + /* return ERR_PTR(-EAGAIN) when it fails */ + b = ERR_PTR(-EAGAIN); if (__bch_bucket_alloc_set(c, RESERVE_BTREE, &k.key, wait)) goto err; @@ -1138,7 +1140,7 @@ static struct btree *btree_node_alloc_replacement(struct btree *b, { struct btree *n = bch_btree_node_alloc(b->c, op, b->level, b->parent); - if (!IS_ERR_OR_NULL(n)) { + if (!IS_ERR(n)) { mutex_lock(&n->write_lock); bch_btree_sort_into(&b->keys, &n->keys, &b->c->sort); bkey_copy_key(&n->key, &b->key); @@ -1340,7 +1342,7 @@ static int btree_gc_coalesce(struct btree *b, struct btree_op *op, memset(new_nodes, 0, sizeof(new_nodes)); closure_init_stack(&cl); - while (nodes < GC_MERGE_NODES && !IS_ERR_OR_NULL(r[nodes].b)) + while (nodes < GC_MERGE_NODES && !IS_ERR(r[nodes].b)) keys += r[nodes++].keys; blocks = btree_default_blocks(b->c) * 2 / 3; @@ -1352,7 +1354,7 @@ static int btree_gc_coalesce(struct btree *b, struct btree_op *op, for (i = 0; i < nodes; i++) { new_nodes[i] = btree_node_alloc_replacement(r[i].b, NULL); - if (IS_ERR_OR_NULL(new_nodes[i])) + if (IS_ERR(new_nodes[i])) goto out_nocoalesce; } @@ -1487,7 +1489,7 @@ out_nocoalesce: bch_keylist_free(&keylist); for (i = 0; i < nodes; i++) - if (!IS_ERR_OR_NULL(new_nodes[i])) { + if (!IS_ERR(new_nodes[i])) { btree_node_free(new_nodes[i]); rw_unlock(true, new_nodes[i]); } @@ -1669,7 +1671,7 @@ static int bch_btree_gc_root(struct btree *b, struct btree_op *op, if (should_rewrite) { n = btree_node_alloc_replacement(b, NULL); - if (!IS_ERR_OR_NULL(n)) { + if (!IS_ERR(n)) { bch_btree_node_write_sync(n); bch_btree_set_root(n); @@ -1968,6 +1970,15 @@ static int bch_btree_check_thread(void *arg) c->gc_stats.nodes++; bch_btree_op_init(&op, 0); ret = bcache_btree(check_recurse, p, c->root, &op); + /* + * The op may be added to cache_set's btree_cache_wait + * in mca_cannibalize(), must ensure it is removed from + * the list and release btree_cache_alloc_lock before + * free op memory. + * Otherwise, the btree_cache_wait will be damaged. + */ + bch_cannibalize_unlock(c); + finish_wait(&c->btree_cache_wait, &(&op)->wait); if (ret) goto out; } diff --git a/drivers/md/bcache/btree.h b/drivers/md/bcache/btree.h index 1b5fdbc0d83e..a2920bbfcad5 100644 --- a/drivers/md/bcache/btree.h +++ b/drivers/md/bcache/btree.h @@ -282,6 +282,7 @@ void bch_initial_gc_finish(struct cache_set *c); void bch_moving_gc(struct cache_set *c); int bch_btree_check(struct cache_set *c); void bch_initial_mark_key(struct cache_set *c, int level, struct bkey *k); +void bch_cannibalize_unlock(struct cache_set *c); static inline void wake_up_gc(struct cache_set *c) { diff --git a/drivers/md/bcache/super.c b/drivers/md/bcache/super.c index af4fa8071cbc..9e7a6c3faa42 100644 --- a/drivers/md/bcache/super.c +++ b/drivers/md/bcache/super.c @@ -1729,7 +1729,7 @@ static void cache_set_flush(struct closure *cl) if (!IS_ERR_OR_NULL(c->gc_thread)) kthread_stop(c->gc_thread); - if (!IS_ERR_OR_NULL(c->root)) + if (!IS_ERR(c->root)) list_add(&c->root->list, &c->btree_cache); /* @@ -2093,7 +2093,7 @@ static int run_cache_set(struct cache_set *c) err = "cannot allocate new btree root"; c->root = __bch_btree_node_alloc(c, NULL, 0, true, NULL); - if (IS_ERR_OR_NULL(c->root)) + if (IS_ERR(c->root)) goto err; mutex_lock(&c->root->write_lock); diff --git a/drivers/md/bcache/writeback.c b/drivers/md/bcache/writeback.c index ee7ad999e924..4dcbaf9a2149 100644 --- a/drivers/md/bcache/writeback.c +++ b/drivers/md/bcache/writeback.c @@ -880,6 +880,16 @@ static int bch_root_node_dirty_init(struct cache_set *c, if (ret < 0) pr_warn("sectors dirty init failed, ret=%d!\n", ret); + /* + * The op may be added to cache_set's btree_cache_wait + * in mca_cannibalize(), must ensure it is removed from + * the list and release btree_cache_alloc_lock before + * free op memory. + * Otherwise, the btree_cache_wait will be damaged. + */ + bch_cannibalize_unlock(c); + finish_wait(&c->btree_cache_wait, &(&op.op)->wait); + return ret; } diff --git a/drivers/md/dm-bow.c b/drivers/md/dm-bow.c index 70d56ad4e9d4..31ee9e7e3781 100644 --- a/drivers/md/dm-bow.c +++ b/drivers/md/dm-bow.c @@ -611,6 +611,7 @@ static void dm_bow_dtr(struct dm_target *ti) wait_for_completion(dm_get_completion_from_kobject(kobj)); } + mutex_lock(&bc->ranges_lock); while (rb_first(&bc->ranges)) { struct bow_range *br = container_of(rb_first(&bc->ranges), struct bow_range, node); @@ -618,6 +619,7 @@ static void dm_bow_dtr(struct dm_target *ti) rb_erase(&br->node, &bc->ranges); kfree(br); } + mutex_unlock(&bc->ranges_lock); mutex_destroy(&bc->ranges_lock); kfree(bc->log_sector); @@ -1191,6 +1193,7 @@ static void dm_bow_tablestatus(struct dm_target *ti, char *result, return; } + mutex_lock(&bc->ranges_lock); for (i = rb_first(&bc->ranges); i; i = rb_next(i)) { struct bow_range *br = container_of(i, struct bow_range, node); @@ -1198,11 +1201,11 @@ static void dm_bow_tablestatus(struct dm_target *ti, char *result, readable_type[br->type], (unsigned long long)br->sector); if (result >= end) - return; + goto unlock; result += scnprintf(result, end - result, "\n"); if (result >= end) - return; + goto unlock; if (br->type == TRIMMED) ++trimmed_range_count; @@ -1224,19 +1227,22 @@ static void dm_bow_tablestatus(struct dm_target *ti, char *result, if (!rb_next(i)) { scnprintf(result, end - result, "\nERROR: Last range not of type TOP"); - return; + goto unlock; } if (br->sector > range_top(br)) { scnprintf(result, end - result, "\nERROR: sectors out of order"); - return; + goto unlock; } } if (trimmed_range_count != trimmed_list_length) scnprintf(result, end - result, "\nERROR: not all trimmed ranges in trimmed list"); + +unlock: + mutex_unlock(&bc->ranges_lock); } static void dm_bow_status(struct dm_target *ti, status_type_t type, diff --git a/drivers/md/dm-init.c b/drivers/md/dm-init.c index b0c45c6ebe0b..dc4381d68313 100644 --- a/drivers/md/dm-init.c +++ b/drivers/md/dm-init.c @@ -8,6 +8,7 @@ */ #include +#include #include #include #include @@ -18,12 +19,17 @@ #define DM_MAX_DEVICES 256 #define DM_MAX_TARGETS 256 #define DM_MAX_STR_SIZE 4096 +#define DM_MAX_WAITFOR 256 static char *create; +static char *waitfor[DM_MAX_WAITFOR]; + /* * Format: dm-mod.create=,,,,[,
+][;,,,,
[,
+]+] * Table format: + * Block devices to wait for to become available before setting up tables: + * dm-mod.waitfor=[,..,] * * See Documentation/admin-guide/device-mapper/dm-init.rst for dm-mod.create="..." format * details. @@ -266,7 +272,7 @@ static int __init dm_init_init(void) struct dm_device *dev; LIST_HEAD(devices); char *str; - int r; + int i, r; if (!create) return 0; @@ -286,6 +292,17 @@ static int __init dm_init_init(void) DMINFO("waiting for all devices to be available before creating mapped devices"); wait_for_device_probe(); + for (i = 0; i < ARRAY_SIZE(waitfor); i++) { + if (waitfor[i]) { + DMINFO("waiting for device %s ...", waitfor[i]); + while (!dm_get_dev_t(waitfor[i])) + msleep(5); + } + } + + if (waitfor[0]) + DMINFO("all devices available"); + list_for_each_entry(dev, &devices, list) { if (dm_early_create(&dev->dmi, dev->table, dev->target_args_array)) @@ -301,3 +318,6 @@ late_initcall(dm_init_init); module_param(create, charp, 0); MODULE_PARM_DESC(create, "Create a mapped device in early boot"); + +module_param_array(waitfor, charp, NULL, 0); +MODULE_PARM_DESC(waitfor, "Devices to wait for before setting up tables"); diff --git a/drivers/md/dm-integrity.c b/drivers/md/dm-integrity.c index c09693daabd8..455788b6e5a1 100644 --- a/drivers/md/dm-integrity.c +++ b/drivers/md/dm-integrity.c @@ -31,11 +31,11 @@ #define DEFAULT_BUFFER_SECTORS 128 #define DEFAULT_JOURNAL_WATERMARK 50 #define DEFAULT_SYNC_MSEC 10000 -#define DEFAULT_MAX_JOURNAL_SECTORS 131072 +#define DEFAULT_MAX_JOURNAL_SECTORS (IS_ENABLED(CONFIG_64BIT) ? 131072 : 8192) #define MIN_LOG2_INTERLEAVE_SECTORS 3 #define MAX_LOG2_INTERLEAVE_SECTORS 31 #define METADATA_WORKQUEUE_MAX_ACTIVE 16 -#define RECALC_SECTORS 32768 +#define RECALC_SECTORS (IS_ENABLED(CONFIG_64BIT) ? 32768 : 2048) #define RECALC_WRITE_SUPER 16 #define BITMAP_BLOCK_SIZE 4096 /* don't change it */ #define BITMAP_FLUSH_INTERVAL (10 * HZ) diff --git a/drivers/md/md-bitmap.c b/drivers/md/md-bitmap.c index 062142559caa..adada558a1b0 100644 --- a/drivers/md/md-bitmap.c +++ b/drivers/md/md-bitmap.c @@ -54,14 +54,7 @@ __acquires(bitmap->lock) { unsigned char *mappage; - if (page >= bitmap->pages) { - /* This can happen if bitmap_start_sync goes beyond - * End-of-device while looking for a whole page. - * It is harmless. - */ - return -EINVAL; - } - + WARN_ON_ONCE(page >= bitmap->pages); if (bitmap->bp[page].hijacked) /* it's hijacked, don't try to alloc */ return 0; @@ -1365,6 +1358,14 @@ __acquires(bitmap->lock) sector_t csize; int err; + if (page >= bitmap->pages) { + /* + * This can happen if bitmap_start_sync goes beyond + * End-of-device while looking for a whole page or + * user set a huge number to sysfs bitmap_set_bits. + */ + return NULL; + } err = md_bitmap_checkpage(bitmap, page, create, 0); if (bitmap->bp[page].hijacked || diff --git a/drivers/md/md.c b/drivers/md/md.c index bd0c9dfac981..5a21aeedc1ba 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -3872,8 +3872,9 @@ int strict_strtoul_scaled(const char *cp, unsigned long *res, int scale) static ssize_t safe_delay_show(struct mddev *mddev, char *page) { - int msec = (mddev->safemode_delay*1000)/HZ; - return sprintf(page, "%d.%03d\n", msec/1000, msec%1000); + unsigned int msec = ((unsigned long)mddev->safemode_delay*1000)/HZ; + + return sprintf(page, "%u.%03u\n", msec/1000, msec%1000); } static ssize_t safe_delay_store(struct mddev *mddev, const char *cbuf, size_t len) @@ -3885,7 +3886,7 @@ safe_delay_store(struct mddev *mddev, const char *cbuf, size_t len) return -EINVAL; } - if (strict_strtoul_scaled(cbuf, &msec, 3) < 0) + if (strict_strtoul_scaled(cbuf, &msec, 3) < 0 || msec > UINT_MAX / HZ) return -EINVAL; if (msec == 0) mddev->safemode_delay = 0; @@ -4555,6 +4556,8 @@ max_corrected_read_errors_store(struct mddev *mddev, const char *buf, size_t len rv = kstrtouint(buf, 10, &n); if (rv < 0) return rv; + if (n > INT_MAX) + return -EINVAL; atomic_set(&mddev->max_corr_read_errors, n); return len; } diff --git a/drivers/md/raid0.c b/drivers/md/raid0.c index c16fa65a3ffd..dca912387ec1 100644 --- a/drivers/md/raid0.c +++ b/drivers/md/raid0.c @@ -274,6 +274,18 @@ static int create_strip_zones(struct mddev *mddev, struct r0conf **private_conf) goto abort; } + if (conf->layout == RAID0_ORIG_LAYOUT) { + for (i = 1; i < conf->nr_strip_zones; i++) { + sector_t first_sector = conf->strip_zone[i-1].zone_end; + + sector_div(first_sector, mddev->chunk_sectors); + zone = conf->strip_zone + i; + /* disk_shift is first disk index used in the zone */ + zone->disk_shift = sector_div(first_sector, + zone->nb_dev); + } + } + pr_debug("md/raid0:%s: done.\n", mdname(mddev)); *private_conf = conf; @@ -444,6 +456,20 @@ exit_acct_set: return ret; } +/* + * Convert disk_index to the disk order in which it is read/written. + * For example, if we have 4 disks, they are numbered 0,1,2,3. If we + * write the disks starting at disk 3, then the read/write order would + * be disk 3, then 0, then 1, and then disk 2 and we want map_disk_shift() + * to map the disks as follows 0,1,2,3 => 1,2,3,0. So disk 0 would map + * to 1, 1 to 2, 2 to 3, and 3 to 0. That way we can compare disks in + * that 'output' space to understand the read/write disk ordering. + */ +static int map_disk_shift(int disk_index, int num_disks, int disk_shift) +{ + return ((disk_index + num_disks - disk_shift) % num_disks); +} + static void raid0_handle_discard(struct mddev *mddev, struct bio *bio) { struct r0conf *conf = mddev->private; @@ -457,7 +483,9 @@ static void raid0_handle_discard(struct mddev *mddev, struct bio *bio) sector_t end_disk_offset; unsigned int end_disk_index; unsigned int disk; + sector_t orig_start, orig_end; + orig_start = start; zone = find_zone(conf, &start); if (bio_end_sector(bio) > zone->zone_end) { @@ -471,6 +499,7 @@ static void raid0_handle_discard(struct mddev *mddev, struct bio *bio) } else end = bio_end_sector(bio); + orig_end = end; if (zone != conf->strip_zone) end = end - zone[-1].zone_end; @@ -482,13 +511,26 @@ static void raid0_handle_discard(struct mddev *mddev, struct bio *bio) last_stripe_index = end; sector_div(last_stripe_index, stripe_size); - start_disk_index = (int)(start - first_stripe_index * stripe_size) / - mddev->chunk_sectors; + /* In the first zone the original and alternate layouts are the same */ + if ((conf->layout == RAID0_ORIG_LAYOUT) && (zone != conf->strip_zone)) { + sector_div(orig_start, mddev->chunk_sectors); + start_disk_index = sector_div(orig_start, zone->nb_dev); + start_disk_index = map_disk_shift(start_disk_index, + zone->nb_dev, + zone->disk_shift); + sector_div(orig_end, mddev->chunk_sectors); + end_disk_index = sector_div(orig_end, zone->nb_dev); + end_disk_index = map_disk_shift(end_disk_index, + zone->nb_dev, zone->disk_shift); + } else { + start_disk_index = (int)(start - first_stripe_index * stripe_size) / + mddev->chunk_sectors; + end_disk_index = (int)(end - last_stripe_index * stripe_size) / + mddev->chunk_sectors; + } start_disk_offset = ((int)(start - first_stripe_index * stripe_size) % mddev->chunk_sectors) + first_stripe_index * mddev->chunk_sectors; - end_disk_index = (int)(end - last_stripe_index * stripe_size) / - mddev->chunk_sectors; end_disk_offset = ((int)(end - last_stripe_index * stripe_size) % mddev->chunk_sectors) + last_stripe_index * mddev->chunk_sectors; @@ -496,18 +538,22 @@ static void raid0_handle_discard(struct mddev *mddev, struct bio *bio) for (disk = 0; disk < zone->nb_dev; disk++) { sector_t dev_start, dev_end; struct md_rdev *rdev; + int compare_disk; - if (disk < start_disk_index) + compare_disk = map_disk_shift(disk, zone->nb_dev, + zone->disk_shift); + + if (compare_disk < start_disk_index) dev_start = (first_stripe_index + 1) * mddev->chunk_sectors; - else if (disk > start_disk_index) + else if (compare_disk > start_disk_index) dev_start = first_stripe_index * mddev->chunk_sectors; else dev_start = start_disk_offset; - if (disk < end_disk_index) + if (compare_disk < end_disk_index) dev_end = (last_stripe_index + 1) * mddev->chunk_sectors; - else if (disk > end_disk_index) + else if (compare_disk > end_disk_index) dev_end = last_stripe_index * mddev->chunk_sectors; else dev_end = end_disk_offset; diff --git a/drivers/md/raid0.h b/drivers/md/raid0.h index 3816e5477db1..8cc761ca7423 100644 --- a/drivers/md/raid0.h +++ b/drivers/md/raid0.h @@ -6,6 +6,7 @@ struct strip_zone { sector_t zone_end; /* Start of the next zone (in sectors) */ sector_t dev_start; /* Zone offset in real dev (in sectors) */ int nb_dev; /* # of devices attached to the zone */ + int disk_shift; /* start disk for the original layout */ }; /* Linux 3.14 (20d0189b101) made an unintended change to diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c index 1f5589c5294d..edd3b65c447d 100644 --- a/drivers/md/raid10.c +++ b/drivers/md/raid10.c @@ -297,7 +297,7 @@ static void raid_end_bio_io(struct r10bio *r10_bio) if (!test_bit(R10BIO_Uptodate, &r10_bio->state)) bio->bi_status = BLK_STS_IOERR; - if (blk_queue_io_stat(bio->bi_bdev->bd_disk->queue)) + if (r10_bio->start_time) bio_end_io_acct(bio, r10_bio->start_time); bio_endio(bio); /* @@ -752,8 +752,16 @@ static struct md_rdev *read_balance(struct r10conf *conf, disk = r10_bio->devs[slot].devnum; rdev = rcu_dereference(conf->mirrors[disk].replacement); if (rdev == NULL || test_bit(Faulty, &rdev->flags) || - r10_bio->devs[slot].addr + sectors > rdev->recovery_offset) + r10_bio->devs[slot].addr + sectors > + rdev->recovery_offset) { + /* + * Read replacement first to prevent reading both rdev + * and replacement as NULL during replacement replace + * rdev. + */ + smp_mb(); rdev = rcu_dereference(conf->mirrors[disk].rdev); + } if (rdev == NULL || test_bit(Faulty, &rdev->flags)) continue; @@ -1449,9 +1457,15 @@ static void raid10_write_request(struct mddev *mddev, struct bio *bio, for (i = 0; i < conf->copies; i++) { int d = r10_bio->devs[i].devnum; - struct md_rdev *rdev = rcu_dereference(conf->mirrors[d].rdev); - struct md_rdev *rrdev = rcu_dereference( - conf->mirrors[d].replacement); + struct md_rdev *rdev, *rrdev; + + rrdev = rcu_dereference(conf->mirrors[d].replacement); + /* + * Read replacement first to prevent reading both rdev and + * replacement as NULL during replacement replace rdev. + */ + smp_mb(); + rdev = rcu_dereference(conf->mirrors[d].rdev); if (rdev == rrdev) rrdev = NULL; if (rdev && (test_bit(Faulty, &rdev->flags))) @@ -3412,7 +3426,6 @@ static sector_t raid10_sync_request(struct mddev *mddev, sector_t sector_nr, int must_sync; int any_working; int need_recover = 0; - int need_replace = 0; struct raid10_info *mirror = &conf->mirrors[i]; struct md_rdev *mrdev, *mreplace; @@ -3424,11 +3437,10 @@ static sector_t raid10_sync_request(struct mddev *mddev, sector_t sector_nr, !test_bit(Faulty, &mrdev->flags) && !test_bit(In_sync, &mrdev->flags)) need_recover = 1; - if (mreplace != NULL && - !test_bit(Faulty, &mreplace->flags)) - need_replace = 1; + if (mreplace && test_bit(Faulty, &mreplace->flags)) + mreplace = NULL; - if (!need_recover && !need_replace) { + if (!need_recover && !mreplace) { rcu_read_unlock(); continue; } @@ -3444,8 +3456,6 @@ static sector_t raid10_sync_request(struct mddev *mddev, sector_t sector_nr, rcu_read_unlock(); continue; } - if (mreplace && test_bit(Faulty, &mreplace->flags)) - mreplace = NULL; /* Unless we are doing a full sync, or a replacement * we only need to recover the block if it is set in * the bitmap @@ -3568,11 +3578,11 @@ static sector_t raid10_sync_request(struct mddev *mddev, sector_t sector_nr, bio = r10_bio->devs[1].repl_bio; if (bio) bio->bi_end_io = NULL; - /* Note: if need_replace, then bio + /* Note: if replace is not NULL, then bio * cannot be NULL as r10buf_pool_alloc will * have allocated it. */ - if (!need_replace) + if (!mreplace) break; bio->bi_next = biolist; biolist = bio; diff --git a/drivers/media/cec/i2c/Kconfig b/drivers/media/cec/i2c/Kconfig index 70432a1d6918..d912d143fb31 100644 --- a/drivers/media/cec/i2c/Kconfig +++ b/drivers/media/cec/i2c/Kconfig @@ -5,6 +5,7 @@ config CEC_CH7322 tristate "Chrontel CH7322 CEC controller" depends on I2C + select REGMAP select REGMAP_I2C select CEC_CORE help diff --git a/drivers/media/i2c/st-mipid02.c b/drivers/media/i2c/st-mipid02.c index f630b88cbfaa..cf55c57a7970 100644 --- a/drivers/media/i2c/st-mipid02.c +++ b/drivers/media/i2c/st-mipid02.c @@ -710,8 +710,13 @@ static void mipid02_set_fmt_source(struct v4l2_subdev *sd, { struct mipid02_dev *bridge = to_mipid02_dev(sd); - /* source pad mirror active sink pad */ - format->format = bridge->fmt; + /* source pad mirror sink pad */ + if (format->which == V4L2_SUBDEV_FORMAT_ACTIVE) + format->format = bridge->fmt; + else + format->format = *v4l2_subdev_get_try_format(sd, sd_state, + MIPID02_SINK_0); + /* but code may need to be converted */ format->format.code = serial_to_parallel_code(format->format.code); diff --git a/drivers/media/platform/qcom/venus/helpers.c b/drivers/media/platform/qcom/venus/helpers.c index 8012f5c7bf34..ff705d513aae 100644 --- a/drivers/media/platform/qcom/venus/helpers.c +++ b/drivers/media/platform/qcom/venus/helpers.c @@ -981,8 +981,8 @@ static u32 get_framesize_raw_yuv420_tp10_ubwc(u32 width, u32 height) u32 extradata = SZ_16K; u32 size; - y_stride = ALIGN(ALIGN(width, 192) * 4 / 3, 256); - uv_stride = ALIGN(ALIGN(width, 192) * 4 / 3, 256); + y_stride = ALIGN(width * 4 / 3, 256); + uv_stride = ALIGN(width * 4 / 3, 256); y_sclines = ALIGN(height, 16); uv_sclines = ALIGN((height + 1) >> 1, 16); diff --git a/drivers/media/platform/qcom/venus/hfi_msgs.c b/drivers/media/platform/qcom/venus/hfi_msgs.c index 9a2bdb002edc..68f208e3071d 100644 --- a/drivers/media/platform/qcom/venus/hfi_msgs.c +++ b/drivers/media/platform/qcom/venus/hfi_msgs.c @@ -367,7 +367,7 @@ session_get_prop_buf_req(struct hfi_msg_session_property_info_pkt *pkt, memcpy(&bufreq[idx], buf_req, sizeof(*bufreq)); idx++; - if (idx > HFI_BUFFER_TYPE_MAX) + if (idx >= HFI_BUFFER_TYPE_MAX) return HFI_ERR_SESSION_INVALID_PARAMETER; req_bytes -= sizeof(struct hfi_buffer_requirements); diff --git a/drivers/media/platform/qcom/venus/hfi_parser.c b/drivers/media/platform/qcom/venus/hfi_parser.c index 5b8389b98299..2655188b5060 100644 --- a/drivers/media/platform/qcom/venus/hfi_parser.c +++ b/drivers/media/platform/qcom/venus/hfi_parser.c @@ -19,6 +19,10 @@ static void init_codecs(struct venus_core *core) struct hfi_plat_caps *caps = core->caps, *cap; unsigned long bit; + if (hweight_long(core->dec_codecs) + + hweight_long(core->enc_codecs) > MAX_CODEC_NUM) + return; + for_each_set_bit(bit, &core->dec_codecs, MAX_CODEC_NUM) { cap = &caps[core->codecs_count++]; cap->codec = BIT(bit); @@ -86,6 +90,9 @@ static void fill_profile_level(struct hfi_plat_caps *cap, const void *data, { const struct hfi_profile_level *pl = data; + if (cap->num_pl + num >= HFI_MAX_PROFILE_COUNT) + return; + memcpy(&cap->pl[cap->num_pl], pl, num * sizeof(*pl)); cap->num_pl += num; } @@ -111,6 +118,9 @@ fill_caps(struct hfi_plat_caps *cap, const void *data, unsigned int num) { const struct hfi_capability *caps = data; + if (cap->num_caps + num >= MAX_CAP_ENTRIES) + return; + memcpy(&cap->caps[cap->num_caps], caps, num * sizeof(*caps)); cap->num_caps += num; } @@ -137,6 +147,9 @@ static void fill_raw_fmts(struct hfi_plat_caps *cap, const void *fmts, { const struct raw_formats *formats = fmts; + if (cap->num_fmts + num_fmts >= MAX_FMT_ENTRIES) + return; + memcpy(&cap->fmts[cap->num_fmts], formats, num_fmts * sizeof(*formats)); cap->num_fmts += num_fmts; } @@ -159,6 +172,9 @@ parse_raw_formats(struct venus_core *core, u32 codecs, u32 domain, void *data) rawfmts[i].buftype = fmt->buffer_type; i++; + if (i >= MAX_FMT_ENTRIES) + return; + if (pinfo->num_planes > MAX_PLANES) break; diff --git a/drivers/media/platform/qcom/venus/hfi_venus.c b/drivers/media/platform/qcom/venus/hfi_venus.c index ce98c523b3c6..609f54243f5a 100644 --- a/drivers/media/platform/qcom/venus/hfi_venus.c +++ b/drivers/media/platform/qcom/venus/hfi_venus.c @@ -206,6 +206,11 @@ static int venus_write_queue(struct venus_hfi_device *hdev, new_wr_idx = wr_idx + dwords; wr_ptr = (u32 *)(queue->qmem.kva + (wr_idx << 2)); + + if (wr_ptr < (u32 *)queue->qmem.kva || + wr_ptr > (u32 *)(queue->qmem.kva + queue->qmem.size - sizeof(*wr_ptr))) + return -EINVAL; + if (new_wr_idx < qsize) { memcpy(wr_ptr, packet, dwords << 2); } else { @@ -273,6 +278,11 @@ static int venus_read_queue(struct venus_hfi_device *hdev, } rd_ptr = (u32 *)(queue->qmem.kva + (rd_idx << 2)); + + if (rd_ptr < (u32 *)queue->qmem.kva || + rd_ptr > (u32 *)(queue->qmem.kva + queue->qmem.size - sizeof(*rd_ptr))) + return -EINVAL; + dwords = *rd_ptr >> 2; if (!dwords) return -EINVAL; diff --git a/drivers/media/usb/dvb-usb-v2/az6007.c b/drivers/media/usb/dvb-usb-v2/az6007.c index 62ee09f28a0b..7524c90f5da6 100644 --- a/drivers/media/usb/dvb-usb-v2/az6007.c +++ b/drivers/media/usb/dvb-usb-v2/az6007.c @@ -202,7 +202,8 @@ static int az6007_rc_query(struct dvb_usb_device *d) unsigned code; enum rc_proto proto; - az6007_read(d, AZ6007_READ_IR, 0, 0, st->data, 10); + if (az6007_read(d, AZ6007_READ_IR, 0, 0, st->data, 10) < 0) + return -EIO; if (st->data[1] == 0x44) return 0; diff --git a/drivers/media/usb/siano/smsusb.c b/drivers/media/usb/siano/smsusb.c index 1babfe6e2c36..5c223b5498b4 100644 --- a/drivers/media/usb/siano/smsusb.c +++ b/drivers/media/usb/siano/smsusb.c @@ -179,7 +179,8 @@ static void smsusb_stop_streaming(struct smsusb_device_t *dev) for (i = 0; i < MAX_URBS; i++) { usb_kill_urb(&dev->surbs[i].urb); - cancel_work_sync(&dev->surbs[i].wq); + if (dev->surbs[i].wq.func) + cancel_work_sync(&dev->surbs[i].wq); if (dev->surbs[i].cb) { smscore_putbuffer(dev->coredev, dev->surbs[i].cb); diff --git a/drivers/memory/brcmstb_dpfe.c b/drivers/memory/brcmstb_dpfe.c index f43ba69fbb3e..2daae2e0cb19 100644 --- a/drivers/memory/brcmstb_dpfe.c +++ b/drivers/memory/brcmstb_dpfe.c @@ -434,15 +434,17 @@ static void __finalize_command(struct brcmstb_dpfe_priv *priv) static int __send_command(struct brcmstb_dpfe_priv *priv, unsigned int cmd, u32 result[]) { - const u32 *msg = priv->dpfe_api->command[cmd]; void __iomem *regs = priv->regs; unsigned int i, chksum, chksum_idx; + const u32 *msg; int ret = 0; u32 resp; if (cmd >= DPFE_CMD_MAX) return -1; + msg = priv->dpfe_api->command[cmd]; + mutex_lock(&priv->lock); /* Wait for DCPU to become ready */ diff --git a/drivers/memstick/host/r592.c b/drivers/memstick/host/r592.c index 42bfc46842b8..461f5ffd02bc 100644 --- a/drivers/memstick/host/r592.c +++ b/drivers/memstick/host/r592.c @@ -44,12 +44,10 @@ static const char *tpc_names[] = { * memstick_debug_get_tpc_name - debug helper that returns string for * a TPC number */ -const char *memstick_debug_get_tpc_name(int tpc) +static __maybe_unused const char *memstick_debug_get_tpc_name(int tpc) { return tpc_names[tpc-1]; } -EXPORT_SYMBOL(memstick_debug_get_tpc_name); - /* Read a register*/ static inline u32 r592_read_reg(struct r592_device *dev, int address) diff --git a/drivers/mfd/intel-lpss-acpi.c b/drivers/mfd/intel-lpss-acpi.c index f2ea6540a01e..4c43d71cddbd 100644 --- a/drivers/mfd/intel-lpss-acpi.c +++ b/drivers/mfd/intel-lpss-acpi.c @@ -148,6 +148,9 @@ static int intel_lpss_acpi_probe(struct platform_device *pdev) return -ENOMEM; info->mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!info->mem) + return -ENODEV; + info->irq = platform_get_irq(pdev, 0); ret = intel_lpss_probe(&pdev->dev, info); diff --git a/drivers/mfd/qcom-pm8008.c b/drivers/mfd/qcom-pm8008.c index 9f3c4a01b4c1..4af1d368c321 100644 --- a/drivers/mfd/qcom-pm8008.c +++ b/drivers/mfd/qcom-pm8008.c @@ -233,6 +233,7 @@ static const struct of_device_id pm8008_match[] = { { .compatible = "qcom,pm8008", }, { }, }; +MODULE_DEVICE_TABLE(of, pm8008_match); static struct i2c_driver pm8008_mfd_driver = { .driver = { diff --git a/drivers/mfd/rt5033.c b/drivers/mfd/rt5033.c index f1236a9acf30..df095e91e266 100644 --- a/drivers/mfd/rt5033.c +++ b/drivers/mfd/rt5033.c @@ -41,9 +41,6 @@ static const struct mfd_cell rt5033_devs[] = { { .name = "rt5033-charger", .of_compatible = "richtek,rt5033-charger", - }, { - .name = "rt5033-battery", - .of_compatible = "richtek,rt5033-battery", }, { .name = "rt5033-led", .of_compatible = "richtek,rt5033-led", diff --git a/drivers/mfd/stmfx.c b/drivers/mfd/stmfx.c index e095a3930142..9852f49c3f88 100644 --- a/drivers/mfd/stmfx.c +++ b/drivers/mfd/stmfx.c @@ -330,9 +330,8 @@ static int stmfx_chip_init(struct i2c_client *client) stmfx->vdd = devm_regulator_get_optional(&client->dev, "vdd"); ret = PTR_ERR_OR_ZERO(stmfx->vdd); if (ret) { - if (ret == -ENODEV) - stmfx->vdd = NULL; - else + stmfx->vdd = NULL; + if (ret != -ENODEV) return dev_err_probe(&client->dev, ret, "Failed to get VDD regulator\n"); } @@ -387,7 +386,7 @@ static int stmfx_chip_init(struct i2c_client *client) err: if (stmfx->vdd) - return regulator_disable(stmfx->vdd); + regulator_disable(stmfx->vdd); return ret; } diff --git a/drivers/mfd/stmpe.c b/drivers/mfd/stmpe.c index 58d09c615e67..743afbe4e99b 100644 --- a/drivers/mfd/stmpe.c +++ b/drivers/mfd/stmpe.c @@ -1498,9 +1498,9 @@ int stmpe_probe(struct stmpe_client_info *ci, enum stmpe_partnum partnum) int stmpe_remove(struct stmpe *stmpe) { - if (!IS_ERR(stmpe->vio)) + if (!IS_ERR(stmpe->vio) && regulator_is_enabled(stmpe->vio)) regulator_disable(stmpe->vio); - if (!IS_ERR(stmpe->vcc)) + if (!IS_ERR(stmpe->vcc) && regulator_is_enabled(stmpe->vcc)) regulator_disable(stmpe->vcc); __stmpe_disable(stmpe, STMPE_BLOCK_ADC); diff --git a/drivers/misc/fastrpc.c b/drivers/misc/fastrpc.c index 0fdf5bbd76ac..24dfc069dbc6 100644 --- a/drivers/misc/fastrpc.c +++ b/drivers/misc/fastrpc.c @@ -1108,7 +1108,7 @@ static int fastrpc_init_create_process(struct fastrpc_user *fl, sc = FASTRPC_SCALARS(FASTRPC_RMID_INIT_CREATE, 4, 0); if (init.attrs) - sc = FASTRPC_SCALARS(FASTRPC_RMID_INIT_CREATE_ATTR, 6, 0); + sc = FASTRPC_SCALARS(FASTRPC_RMID_INIT_CREATE_ATTR, 4, 0); err = fastrpc_internal_invoke(fl, true, FASTRPC_INIT_HANDLE, sc, args); diff --git a/drivers/misc/pci_endpoint_test.c b/drivers/misc/pci_endpoint_test.c index 4e4c0884d35e..2ad28f1b1461 100644 --- a/drivers/misc/pci_endpoint_test.c +++ b/drivers/misc/pci_endpoint_test.c @@ -728,6 +728,10 @@ static long pci_endpoint_test_ioctl(struct file *file, unsigned int cmd, struct pci_dev *pdev = test->pdev; mutex_lock(&test->mutex); + + reinit_completion(&test->irq_raised); + test->last_irq = -ENODATA; + switch (cmd) { case PCITEST_BAR: bar = arg; @@ -937,6 +941,9 @@ static void pci_endpoint_test_remove(struct pci_dev *pdev) if (id < 0) return; + pci_endpoint_test_release_irq(test); + pci_endpoint_test_free_irq_vectors(test); + misc_deregister(&test->miscdev); kfree(misc_device->name); kfree(test->name); @@ -946,9 +953,6 @@ static void pci_endpoint_test_remove(struct pci_dev *pdev) pci_iounmap(pdev, test->bar[bar]); } - pci_endpoint_test_release_irq(test); - pci_endpoint_test_free_irq_vectors(test); - pci_release_regions(pdev); pci_disable_device(pdev); } diff --git a/drivers/misc/qrc/qrc_core.c b/drivers/misc/qrc/qrc_core.c index 20ee50521c11..a3a034a05b58 100644 --- a/drivers/misc/qrc/qrc_core.c +++ b/drivers/misc/qrc/qrc_core.c @@ -308,7 +308,7 @@ void qrc_unregister(struct qrc_dev *qdev) { device_destroy(qrc_class, qdev->dev->devt); qrc_control_gpio_uninit(qdev); - dev_info(qdev->dev, "qrc drv unregistered\n"); + pr_err("qrc drv unregistered\n"); } MODULE_DESCRIPTION("Qualcomm Technologies, Inc. QRC Uart Driver"); diff --git a/drivers/misc/qrc/qrc_core.h b/drivers/misc/qrc/qrc_core.h index 2d5d905db30b..30f67c61937a 100644 --- a/drivers/misc/qrc/qrc_core.h +++ b/drivers/misc/qrc/qrc_core.h @@ -106,6 +106,7 @@ struct qrc_dev { * @tx_head: String head in XMIT queue. * @tx_left: Bytes left in XMIT queue. * @tx_buffer: XMIT buffer. + * @is_open: Flag shows if the device is open. * This structure is used to define robotic controller uart device. */ struct qrcuart { @@ -117,6 +118,7 @@ struct qrcuart { unsigned char *tx_head; int tx_left; unsigned char *tx_buffer; + bool is_open; }; struct qrcspi { diff --git a/drivers/misc/qrc/qrc_uart.c b/drivers/misc/qrc/qrc_uart.c index c8757c700203..3630259ef351 100644 --- a/drivers/misc/qrc/qrc_uart.c +++ b/drivers/misc/qrc/qrc_uart.c @@ -100,13 +100,16 @@ static int qrcuart_open(struct qrc_dev *dev) struct serdev_device *serdev = qrc->serdev; int ret; - ret = serdev_device_open(serdev); - if (ret) { - pr_err("qrcuart :Unable to open device\n"); - return ret; + if (!qrc->is_open) { + ret = serdev_device_open(serdev); + if (ret) { + pr_err("qrcuart :Unable to open device\n"); + return ret; + } + serdev_device_set_baudrate(serdev, 115200); + serdev_device_set_flow_control(serdev, false); + qrc->is_open = true; } - serdev_device_set_baudrate(serdev, 115200); - serdev_device_set_flow_control(serdev, false); return 0; } @@ -120,7 +123,11 @@ static int qrcuart_close(struct qrc_dev *dev) spin_lock_bh(&qrc->lock); qrc->tx_left = 0; spin_unlock_bh(&qrc->lock); - serdev_device_close(serdev); + if (qrc->is_open) { + serdev_device_close(serdev); + qrc->is_open = false; + } + return 0; } @@ -286,6 +293,7 @@ static int qrc_uart_probe(struct serdev_device *serdev) goto free; } serdev_device_close(serdev); + qrc->is_open = false; ret = qrc_register_device(qdev, &serdev->dev); @@ -307,13 +315,14 @@ static void qrc_uart_remove(struct serdev_device *serdev) { struct qrcuart *qrc = serdev_device_get_drvdata(serdev); - serdev_device_close(serdev); + if (qrc->is_open) + serdev_device_close(serdev); + qrcuart_uninit(qrc->qrc_dev); cancel_work_sync(&qrc->tx_work); qrc_unregister(qrc->qrc_dev); kfree(qrc->qrc_dev); kfree(qrc); - dev_info(&serdev->dev, "qrcuart drv removed\n"); } static const struct of_device_id qrc_uart_of_match[] = { diff --git a/drivers/misc/uid_sys_stats.c b/drivers/misc/uid_sys_stats.c index 985e7b02ab3c..5459b83825fe 100644 --- a/drivers/misc/uid_sys_stats.c +++ b/drivers/misc/uid_sys_stats.c @@ -19,20 +19,24 @@ #include #include #include +#include #include #include #include -#include #include #include #include #include - +#include #define UID_HASH_BITS 10 +#define UID_HASH_NUMS (1 << UID_HASH_BITS) DECLARE_HASHTABLE(hash_table, UID_HASH_BITS); +/* + * uid_lock[bkt] ensure consistency of hash_table[bkt] + */ +spinlock_t uid_lock[UID_HASH_NUMS]; -static DEFINE_RT_MUTEX(uid_lock); static struct proc_dir_entry *cpu_parent; static struct proc_dir_entry *io_parent; static struct proc_dir_entry *proc_parent; @@ -77,6 +81,32 @@ struct uid_entry { #endif }; +static inline int trylock_uid(uid_t uid) +{ + return spin_trylock( + &uid_lock[hash_min(uid, HASH_BITS(hash_table))]); +} + +static inline void lock_uid(uid_t uid) +{ + spin_lock(&uid_lock[hash_min(uid, HASH_BITS(hash_table))]); +} + +static inline void unlock_uid(uid_t uid) +{ + spin_unlock(&uid_lock[hash_min(uid, HASH_BITS(hash_table))]); +} + +static inline void lock_uid_by_bkt(u32 bkt) +{ + spin_lock(&uid_lock[bkt]); +} + +static inline void unlock_uid_by_bkt(u32 bkt) +{ + spin_unlock(&uid_lock[bkt]); +} + static u64 compute_write_bytes(struct task_io_accounting *ioac) { if (ioac->write_bytes <= ioac->cancelled_write_bytes) @@ -332,24 +362,29 @@ static int uid_cputime_show(struct seq_file *m, void *v) struct user_namespace *user_ns = current_user_ns(); u64 utime; u64 stime; - unsigned long bkt; + u32 bkt; uid_t uid; - rt_mutex_lock(&uid_lock); - - hash_for_each(hash_table, bkt, uid_entry, hash) { - uid_entry->active_stime = 0; - uid_entry->active_utime = 0; + for (bkt = 0, uid_entry = NULL; uid_entry == NULL && + bkt < HASH_SIZE(hash_table); bkt++) { + lock_uid_by_bkt(bkt); + hlist_for_each_entry(uid_entry, &hash_table[bkt], hash) { + uid_entry->active_stime = 0; + uid_entry->active_utime = 0; + } + unlock_uid_by_bkt(bkt); } rcu_read_lock(); do_each_thread(temp, task) { uid = from_kuid_munged(user_ns, task_uid(task)); + lock_uid(uid); + if (!uid_entry || uid_entry->uid != uid) uid_entry = find_or_register_uid(uid); if (!uid_entry) { rcu_read_unlock(); - rt_mutex_unlock(&uid_lock); + unlock_uid(uid); pr_err("%s: failed to find the uid_entry for uid %d\n", __func__, uid); return -ENOMEM; @@ -360,19 +395,24 @@ static int uid_cputime_show(struct seq_file *m, void *v) uid_entry->active_utime += utime; uid_entry->active_stime += stime; } + unlock_uid(uid); } while_each_thread(temp, task); rcu_read_unlock(); - hash_for_each(hash_table, bkt, uid_entry, hash) { - u64 total_utime = uid_entry->utime + - uid_entry->active_utime; - u64 total_stime = uid_entry->stime + - uid_entry->active_stime; - seq_printf(m, "%d: %llu %llu\n", uid_entry->uid, - ktime_to_us(total_utime), ktime_to_us(total_stime)); + for (bkt = 0, uid_entry = NULL; uid_entry == NULL && + bkt < HASH_SIZE(hash_table); bkt++) { + lock_uid_by_bkt(bkt); + hlist_for_each_entry(uid_entry, &hash_table[bkt], hash) { + u64 total_utime = uid_entry->utime + + uid_entry->active_utime; + u64 total_stime = uid_entry->stime + + uid_entry->active_stime; + seq_printf(m, "%d: %llu %llu\n", uid_entry->uid, + ktime_to_us(total_utime), ktime_to_us(total_stime)); + } + unlock_uid_by_bkt(bkt); } - rt_mutex_unlock(&uid_lock); return 0; } @@ -420,9 +460,8 @@ static ssize_t uid_remove_write(struct file *file, return -EINVAL; } - rt_mutex_lock(&uid_lock); - for (; uid_start <= uid_end; uid_start++) { + lock_uid(uid_start); hash_for_each_possible_safe(hash_table, uid_entry, tmp, hash, (uid_t)uid_start) { if (uid_start == uid_entry->uid) { @@ -431,9 +470,9 @@ static ssize_t uid_remove_write(struct file *file, kfree(uid_entry); } } + unlock_uid(uid_start); } - rt_mutex_unlock(&uid_lock); return count; } @@ -471,41 +510,59 @@ static void add_uid_io_stats(struct uid_entry *uid_entry, __add_uid_io_stats(uid_entry, &task->ioac, slot); } -static void update_io_stats_all_locked(void) +static void update_io_stats_all(void) { struct uid_entry *uid_entry = NULL; struct task_struct *task, *temp; struct user_namespace *user_ns = current_user_ns(); - unsigned long bkt; + u32 bkt; uid_t uid; - hash_for_each(hash_table, bkt, uid_entry, hash) { - memset(&uid_entry->io[UID_STATE_TOTAL_CURR], 0, - sizeof(struct io_stats)); - set_io_uid_tasks_zero(uid_entry); + for (bkt = 0, uid_entry = NULL; uid_entry == NULL && bkt < HASH_SIZE(hash_table); + bkt++) { + lock_uid_by_bkt(bkt); + hlist_for_each_entry(uid_entry, &hash_table[bkt], hash) { + memset(&uid_entry->io[UID_STATE_TOTAL_CURR], 0, + sizeof(struct io_stats)); + set_io_uid_tasks_zero(uid_entry); + } + unlock_uid_by_bkt(bkt); } rcu_read_lock(); do_each_thread(temp, task) { uid = from_kuid_munged(user_ns, task_uid(task)); + lock_uid(uid); if (!uid_entry || uid_entry->uid != uid) uid_entry = find_or_register_uid(uid); - if (!uid_entry) + if (!uid_entry) { + unlock_uid(uid); continue; + } add_uid_io_stats(uid_entry, task, UID_STATE_TOTAL_CURR); + unlock_uid(uid); } while_each_thread(temp, task); rcu_read_unlock(); - hash_for_each(hash_table, bkt, uid_entry, hash) { - compute_io_bucket_stats(&uid_entry->io[uid_entry->state], - &uid_entry->io[UID_STATE_TOTAL_CURR], - &uid_entry->io[UID_STATE_TOTAL_LAST], - &uid_entry->io[UID_STATE_DEAD_TASKS]); - compute_io_uid_tasks(uid_entry); + for (bkt = 0, uid_entry = NULL; uid_entry == NULL && bkt < HASH_SIZE(hash_table); + bkt++) { + lock_uid_by_bkt(bkt); + hlist_for_each_entry(uid_entry, &hash_table[bkt], hash) { + compute_io_bucket_stats(&uid_entry->io[uid_entry->state], + &uid_entry->io[UID_STATE_TOTAL_CURR], + &uid_entry->io[UID_STATE_TOTAL_LAST], + &uid_entry->io[UID_STATE_DEAD_TASKS]); + compute_io_uid_tasks(uid_entry); + } + unlock_uid_by_bkt(bkt); } } +#ifndef CONFIG_UID_SYS_STATS_DEBUG +static void update_io_stats_uid(struct uid_entry *uid_entry) +#else static void update_io_stats_uid_locked(struct uid_entry *uid_entry) +#endif { struct task_struct *task, *temp; struct user_namespace *user_ns = current_user_ns(); @@ -533,14 +590,15 @@ static void update_io_stats_uid_locked(struct uid_entry *uid_entry) static int uid_io_show(struct seq_file *m, void *v) { struct uid_entry *uid_entry; - unsigned long bkt; + u32 bkt; - rt_mutex_lock(&uid_lock); + update_io_stats_all(); + for (bkt = 0, uid_entry = NULL; uid_entry == NULL && bkt < HASH_SIZE(hash_table); + bkt++) { - update_io_stats_all_locked(); - - hash_for_each(hash_table, bkt, uid_entry, hash) { - seq_printf(m, "%d %llu %llu %llu %llu %llu %llu %llu %llu %llu %llu\n", + lock_uid_by_bkt(bkt); + hlist_for_each_entry(uid_entry, &hash_table[bkt], hash) { + seq_printf(m, "%d %llu %llu %llu %llu %llu %llu %llu %llu %llu %llu\n", uid_entry->uid, uid_entry->io[UID_STATE_FOREGROUND].rchar, uid_entry->io[UID_STATE_FOREGROUND].wchar, @@ -553,10 +611,11 @@ static int uid_io_show(struct seq_file *m, void *v) uid_entry->io[UID_STATE_FOREGROUND].fsync, uid_entry->io[UID_STATE_BACKGROUND].fsync); - show_io_uid_tasks(m, uid_entry); + show_io_uid_tasks(m, uid_entry); + } + unlock_uid_by_bkt(bkt); } - rt_mutex_unlock(&uid_lock); return 0; } @@ -584,6 +643,9 @@ static ssize_t uid_procstat_write(struct file *file, uid_t uid; int argc, state; char input[128]; +#ifndef CONFIG_UID_SYS_STATS_DEBUG + struct uid_entry uid_entry_tmp; +#endif if (count >= sizeof(input)) return -EINVAL; @@ -600,24 +662,51 @@ static ssize_t uid_procstat_write(struct file *file, if (state != UID_STATE_BACKGROUND && state != UID_STATE_FOREGROUND) return -EINVAL; - rt_mutex_lock(&uid_lock); - + lock_uid(uid); uid_entry = find_or_register_uid(uid); if (!uid_entry) { - rt_mutex_unlock(&uid_lock); + unlock_uid(uid); return -EINVAL; } if (uid_entry->state == state) { - rt_mutex_unlock(&uid_lock); + unlock_uid(uid); return count; } +#ifndef CONFIG_UID_SYS_STATS_DEBUG + /* + * Update_io_stats_uid_locked would take a long lock-time of uid_lock + * due to call do_each_thread to compute uid_entry->io, which would + * cause to lock competition sometime. + * + * Using uid_entry_tmp to get the result of Update_io_stats_uid, + * so that we can unlock_uid during update_io_stats_uid, in order + * to avoid the unnecessary lock-time of uid_lock. + */ + uid_entry_tmp.uid = uid_entry->uid; + memcpy(uid_entry_tmp.io, uid_entry->io, + sizeof(struct io_stats) * UID_STATE_SIZE); + unlock_uid(uid); + update_io_stats_uid(&uid_entry_tmp); + + lock_uid(uid); + hlist_for_each_entry(uid_entry, &hash_table[hash_min(uid, HASH_BITS(hash_table))], hash) { + if (uid_entry->uid == uid_entry_tmp.uid) { + memcpy(uid_entry->io, uid_entry_tmp.io, + sizeof(struct io_stats) * UID_STATE_SIZE); + uid_entry->state = state; + break; + } + } + unlock_uid(uid); +#else update_io_stats_uid_locked(uid_entry); uid_entry->state = state; - rt_mutex_unlock(&uid_lock); + unlock_uid(uid); +#endif return count; } @@ -629,7 +718,6 @@ static const struct proc_ops uid_procstat_fops = { }; struct update_stats_work { - struct work_struct work; uid_t uid; #ifdef CONFIG_UID_SYS_STATS_DEBUG struct task_struct *task; @@ -637,38 +725,46 @@ struct update_stats_work { struct task_io_accounting ioac; u64 utime; u64 stime; + struct llist_node node; }; +static LLIST_HEAD(work_usw); + static void update_stats_workfn(struct work_struct *work) { - struct update_stats_work *usw = - container_of(work, struct update_stats_work, work); + struct update_stats_work *usw, *t; struct uid_entry *uid_entry; struct task_entry *task_entry __maybe_unused; + struct llist_node *node; - rt_mutex_lock(&uid_lock); - uid_entry = find_uid_entry(usw->uid); - if (!uid_entry) - goto exit; + node = llist_del_all(&work_usw); + llist_for_each_entry_safe(usw, t, node, node) { + lock_uid(usw->uid); + uid_entry = find_uid_entry(usw->uid); + if (!uid_entry) + goto next; - uid_entry->utime += usw->utime; - uid_entry->stime += usw->stime; + uid_entry->utime += usw->utime; + uid_entry->stime += usw->stime; #ifdef CONFIG_UID_SYS_STATS_DEBUG - task_entry = find_task_entry(uid_entry, usw->task); - if (!task_entry) - goto exit; - add_uid_tasks_io_stats(task_entry, &usw->ioac, - UID_STATE_DEAD_TASKS); + task_entry = find_task_entry(uid_entry, usw->task); + if (!task_entry) + goto next; + add_uid_tasks_io_stats(task_entry, &usw->ioac, + UID_STATE_DEAD_TASKS); #endif - __add_uid_io_stats(uid_entry, &usw->ioac, UID_STATE_DEAD_TASKS); -exit: - rt_mutex_unlock(&uid_lock); + __add_uid_io_stats(uid_entry, &usw->ioac, UID_STATE_DEAD_TASKS); +next: + unlock_uid(usw->uid); #ifdef CONFIG_UID_SYS_STATS_DEBUG - put_task_struct(usw->task); + put_task_struct(usw->task); #endif - kfree(usw); + kfree(usw); + } + } +static DECLARE_WORK(update_stats_work, update_stats_workfn); static int process_notifier(struct notifier_block *self, unsigned long cmd, void *v) @@ -682,12 +778,11 @@ static int process_notifier(struct notifier_block *self, return NOTIFY_OK; uid = from_kuid_munged(current_user_ns(), task_uid(task)); - if (!rt_mutex_trylock(&uid_lock)) { + if (!trylock_uid(uid)) { struct update_stats_work *usw; usw = kmalloc(sizeof(struct update_stats_work), GFP_KERNEL); if (usw) { - INIT_WORK(&usw->work, update_stats_workfn); usw->uid = uid; #ifdef CONFIG_UID_SYS_STATS_DEBUG usw->task = get_task_struct(task); @@ -698,7 +793,8 @@ static int process_notifier(struct notifier_block *self, */ usw->ioac = task->ioac; task_cputime_adjusted(task, &usw->utime, &usw->stime); - schedule_work(&usw->work); + llist_add(&usw->node, &work_usw); + schedule_work(&update_stats_work); } return NOTIFY_OK; } @@ -716,7 +812,7 @@ static int process_notifier(struct notifier_block *self, add_uid_io_stats(uid_entry, task, UID_STATE_DEAD_TASKS); exit: - rt_mutex_unlock(&uid_lock); + unlock_uid(uid); return NOTIFY_OK; } @@ -724,9 +820,18 @@ static struct notifier_block process_notifier_block = { .notifier_call = process_notifier, }; +static void init_hash_table_and_lock(void) +{ + int i; + + hash_init(hash_table); + for (i = 0; i < UID_HASH_NUMS; i++) + spin_lock_init(&uid_lock[i]); +} + static int __init proc_uid_sys_stats_init(void) { - hash_init(hash_table); + init_hash_table_and_lock(); cpu_parent = proc_mkdir("uid_cputime", NULL); if (!cpu_parent) { diff --git a/drivers/mmc/core/block.c b/drivers/mmc/core/block.c index 1f4b4fcb0aad..1cfc9937ce75 100644 --- a/drivers/mmc/core/block.c +++ b/drivers/mmc/core/block.c @@ -2086,14 +2086,14 @@ static void mmc_blk_mq_poll_completion(struct mmc_queue *mq, mmc_blk_urgent_bkops(mq, mqrq); } -static void mmc_blk_mq_dec_in_flight(struct mmc_queue *mq, struct request *req) +static void mmc_blk_mq_dec_in_flight(struct mmc_queue *mq, enum mmc_issue_type issue_type) { unsigned long flags; bool put_card; spin_lock_irqsave(&mq->lock, flags); - mq->in_flight[mmc_issue_type(mq, req)] -= 1; + mq->in_flight[issue_type] -= 1; put_card = (mmc_tot_in_flight(mq) == 0); @@ -2105,6 +2105,7 @@ static void mmc_blk_mq_dec_in_flight(struct mmc_queue *mq, struct request *req) static void mmc_blk_mq_post_req(struct mmc_queue *mq, struct request *req) { + enum mmc_issue_type issue_type = mmc_issue_type(mq, req); struct mmc_queue_req *mqrq = req_to_mmc_queue_req(req); struct mmc_request *mrq = &mqrq->brq.mrq; struct mmc_host *host = mq->card->host; @@ -2120,7 +2121,7 @@ static void mmc_blk_mq_post_req(struct mmc_queue *mq, struct request *req) else if (likely(!blk_should_fake_timeout(req->q))) blk_mq_complete_request(req); - mmc_blk_mq_dec_in_flight(mq, req); + mmc_blk_mq_dec_in_flight(mq, issue_type); } void mmc_blk_mq_recovery(struct mmc_queue *mq) diff --git a/drivers/mmc/core/quirks.h b/drivers/mmc/core/quirks.h index c8c0f50a2076..afe8d8c5fa8a 100644 --- a/drivers/mmc/core/quirks.h +++ b/drivers/mmc/core/quirks.h @@ -99,6 +99,20 @@ static const struct mmc_fixup __maybe_unused mmc_blk_fixups[] = { MMC_FIXUP("V10016", CID_MANFID_KINGSTON, CID_OEMID_ANY, add_quirk_mmc, MMC_QUIRK_TRIM_BROKEN), + /* + * Kingston EMMC04G-M627 advertises TRIM but it does not seems to + * support being used to offload WRITE_ZEROES. + */ + MMC_FIXUP("M62704", CID_MANFID_KINGSTON, 0x0100, add_quirk_mmc, + MMC_QUIRK_TRIM_BROKEN), + + /* + * Micron MTFC4GACAJCN-1M advertises TRIM but it does not seems to + * support being used to offload WRITE_ZEROES. + */ + MMC_FIXUP("Q2J54A", CID_MANFID_MICRON, 0x014e, add_quirk_mmc, + MMC_QUIRK_TRIM_BROKEN), + /* * Some SD cards reports discard support while they don't */ diff --git a/drivers/mmc/host/cqhci-crypto-qti.c b/drivers/mmc/host/cqhci-crypto-qti.c index 59a7dcece661..13555e1df961 100644 --- a/drivers/mmc/host/cqhci-crypto-qti.c +++ b/drivers/mmc/host/cqhci-crypto-qti.c @@ -88,7 +88,7 @@ static int cqhci_crypto_qti_keyslot_program(struct blk_keyslot_manager *ksm, get_mmio_data(&mmio_data, cq_host); err = crypto_qti_keyslot_program(&mmio_data, key, - slot, data_unit_mask, cap_idx); + slot, data_unit_mask, cap_idx, SDCC_CE); if (err) pr_err("%s: failed with error %d\n", __func__, err); @@ -105,7 +105,7 @@ static int cqhci_crypto_qti_keyslot_evict(struct blk_keyslot_manager *ksm, get_mmio_data(&mmio_data, host); - err = crypto_qti_keyslot_evict(&mmio_data, slot); + err = crypto_qti_keyslot_evict(&mmio_data, slot, SDCC_CE); if (err) pr_err("%s: failed with error %d\n", __func__, err); diff --git a/drivers/mmc/host/mmci.c b/drivers/mmc/host/mmci.c index 090246aa6f03..1ffb9dbdf78e 100644 --- a/drivers/mmc/host/mmci.c +++ b/drivers/mmc/host/mmci.c @@ -2449,6 +2449,7 @@ static struct amba_driver mmci_driver = { .drv = { .name = DRIVER_NAME, .pm = &mmci_dev_pm_ops, + .probe_type = PROBE_PREFER_ASYNCHRONOUS, }, .probe = mmci_probe, .remove = mmci_remove, diff --git a/drivers/mmc/host/sdhci-msm-scaling.c b/drivers/mmc/host/sdhci-msm-scaling.c index 201a0291e77f..4a9ec4a4f9d0 100644 --- a/drivers/mmc/host/sdhci-msm-scaling.c +++ b/drivers/mmc/host/sdhci-msm-scaling.c @@ -60,7 +60,7 @@ void sdhci_msm_scale_parse_dt(struct device *dev, struct sdhci_msm_host *msm_hos pr_debug("%s: no clock scaling frequencies were supplied\n", dev_name(dev)); else if (!msm_host->clk_scaling.pltfm_freq_table || - msm_host->clk_scaling.pltfm_freq_table_sz) + !msm_host->clk_scaling.pltfm_freq_table_sz) dev_info(dev, "bad dts clock scaling frequencies\n"); /* diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c index 01f7eeb77f6c..7cd7b6ac2ce8 100644 --- a/drivers/mmc/host/sdhci.c +++ b/drivers/mmc/host/sdhci.c @@ -1147,6 +1147,8 @@ static void sdhci_prepare_data(struct sdhci_host *host, struct mmc_command *cmd) } } + sdhci_config_dma(host); + if (host->flags & SDHCI_REQ_USE_DMA) { int sg_cnt = sdhci_pre_dma_transfer(host, data, COOKIE_MAPPED); @@ -1166,8 +1168,6 @@ static void sdhci_prepare_data(struct sdhci_host *host, struct mmc_command *cmd) } } - sdhci_config_dma(host); - if (!(host->flags & SDHCI_REQ_USE_DMA)) { int flags; diff --git a/drivers/mtd/devices/msm_qpic_nand.c b/drivers/mtd/devices/msm_qpic_nand.c index b39149c0c076..ff69c39eb248 100644 --- a/drivers/mtd/devices/msm_qpic_nand.c +++ b/drivers/mtd/devices/msm_qpic_nand.c @@ -1758,6 +1758,8 @@ static int msm_nand_is_erased_page_ps(struct mtd_info *mtd, loff_t from, memcpy(&raw_ops, ops, sizeof(struct mtd_oob_ops)); raw_ops.mode = MTD_OPS_RAW; ecc = kzalloc(total_ecc_byte_cnt, GFP_KERNEL); + if (!ecc) + return -ENOMEM; wait_event(chip->dma_wait_queue, (dma_buffer = msm_nand_get_dma_buffer( chip, sizeof(*dma_buffer)))); @@ -2382,6 +2384,8 @@ static int msm_nand_is_erased_page(struct mtd_info *mtd, loff_t from, memcpy(&raw_ops, ops, sizeof(struct mtd_oob_ops)); raw_ops.mode = MTD_OPS_RAW; ecc = kzalloc(total_ecc_byte_cnt, GFP_KERNEL); + if (!ecc) + return -ENOMEM; wait_event(chip->dma_wait_queue, (dma_buffer = msm_nand_get_dma_buffer( chip, sizeof(*dma_buffer)))); @@ -3797,7 +3801,7 @@ static int msm_nand_block_markbad(struct mtd_info *mtd, loff_t ofs) int ret, mark_block_bad_page = 0; uint8_t *buf; size_t len; - uint32_t pages_per_block; + uint32_t pages_per_block = 0; if (ofs > mtd->size) { pr_err("Invalid offset 0x%llx\n", ofs); diff --git a/drivers/mtd/nand/raw/meson_nand.c b/drivers/mtd/nand/raw/meson_nand.c index c66edabec9f1..bb256a3bb9be 100644 --- a/drivers/mtd/nand/raw/meson_nand.c +++ b/drivers/mtd/nand/raw/meson_nand.c @@ -72,6 +72,7 @@ #define GENCMDIADDRH(aih, addr) ((aih) | (((addr) >> 16) & 0xffff)) #define DMA_DIR(dir) ((dir) ? NFC_CMD_N2M : NFC_CMD_M2N) +#define DMA_ADDR_ALIGN 8 #define ECC_CHECK_RETURN_FF (-1) @@ -838,6 +839,9 @@ static int meson_nfc_read_oob(struct nand_chip *nand, int page) static bool meson_nfc_is_buffer_dma_safe(const void *buffer) { + if ((uintptr_t)buffer % DMA_ADDR_ALIGN) + return false; + if (virt_addr_valid(buffer) && (!object_is_on_stack(buffer))) return true; return false; diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index b4d613bdbc06..7b0b4049bd29 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c @@ -3900,7 +3900,7 @@ u32 bond_xmit_hash(struct bonding *bond, struct sk_buff *skb) return skb->hash; return __bond_xmit_hash(bond, skb, skb->data, skb->protocol, - skb_mac_offset(skb), skb_network_offset(skb), + 0, skb_network_offset(skb), skb_headlen(skb)); } diff --git a/drivers/net/dsa/vitesse-vsc73xx-core.c b/drivers/net/dsa/vitesse-vsc73xx-core.c index a4b1447ff055..0c0bc78b1788 100644 --- a/drivers/net/dsa/vitesse-vsc73xx-core.c +++ b/drivers/net/dsa/vitesse-vsc73xx-core.c @@ -1025,17 +1025,17 @@ static int vsc73xx_change_mtu(struct dsa_switch *ds, int port, int new_mtu) struct vsc73xx *vsc = ds->priv; return vsc73xx_write(vsc, VSC73XX_BLOCK_MAC, port, - VSC73XX_MAXLEN, new_mtu); + VSC73XX_MAXLEN, new_mtu + ETH_HLEN + ETH_FCS_LEN); } /* According to application not "VSC7398 Jumbo Frames" setting - * up the MTU to 9.6 KB does not affect the performance on standard + * up the frame size to 9.6 KB does not affect the performance on standard * frames. It is clear from the application note that * "9.6 kilobytes" == 9600 bytes. */ static int vsc73xx_get_max_mtu(struct dsa_switch *ds, int port) { - return 9600; + return 9600 - ETH_HLEN - ETH_FCS_LEN; } static const struct dsa_switch_ops vsc73xx_ds_ops = { diff --git a/drivers/net/ethernet/agere/et131x.c b/drivers/net/ethernet/agere/et131x.c index 920633161174..f4edc616388c 100644 --- a/drivers/net/ethernet/agere/et131x.c +++ b/drivers/net/ethernet/agere/et131x.c @@ -3863,7 +3863,7 @@ static int et131x_change_mtu(struct net_device *netdev, int new_mtu) et131x_init_send(adapter); et131x_hwaddr_init(adapter); - ether_addr_copy(netdev->dev_addr, adapter->addr); + eth_hw_addr_set(netdev, adapter->addr); /* Init the device with the new settings */ et131x_adapter_setup(adapter); @@ -3966,7 +3966,7 @@ static int et131x_pci_setup(struct pci_dev *pdev, netif_napi_add(netdev, &adapter->napi, et131x_poll, 64); - ether_addr_copy(netdev->dev_addr, adapter->addr); + eth_hw_addr_set(netdev, adapter->addr); rc = -ENOMEM; diff --git a/drivers/net/ethernet/alacritech/slicoss.c b/drivers/net/ethernet/alacritech/slicoss.c index 696517eae77f..82f4f2608102 100644 --- a/drivers/net/ethernet/alacritech/slicoss.c +++ b/drivers/net/ethernet/alacritech/slicoss.c @@ -1660,7 +1660,7 @@ static int slic_read_eeprom(struct slic_device *sdev) goto free_eeprom; } /* set mac address */ - ether_addr_copy(sdev->netdev->dev_addr, mac[devfn]); + eth_hw_addr_set(sdev->netdev, mac[devfn]); free_eeprom: dma_free_coherent(&sdev->pdev->dev, SLIC_EEPROM_SIZE, eeprom, paddr); diff --git a/drivers/net/ethernet/allwinner/sun4i-emac.c b/drivers/net/ethernet/allwinner/sun4i-emac.c index 037baea1c738..ef218a6d477c 100644 --- a/drivers/net/ethernet/allwinner/sun4i-emac.c +++ b/drivers/net/ethernet/allwinner/sun4i-emac.c @@ -852,7 +852,7 @@ static int emac_probe(struct platform_device *pdev) } /* Read MAC-address from DT */ - ret = of_get_mac_address(np, ndev->dev_addr); + ret = of_get_ethdev_address(np, ndev); if (ret) { /* if the MAC address is invalid get a random one */ eth_hw_addr_random(ndev); diff --git a/drivers/net/ethernet/altera/altera_tse_main.c b/drivers/net/ethernet/altera/altera_tse_main.c index b51f5b9577e0..9e721436f06f 100644 --- a/drivers/net/ethernet/altera/altera_tse_main.c +++ b/drivers/net/ethernet/altera/altera_tse_main.c @@ -1531,7 +1531,7 @@ static int altera_tse_probe(struct platform_device *pdev) priv->rx_dma_buf_sz = ALTERA_RXDMABUFFER_SIZE; /* get default MAC address from device tree */ - ret = of_get_mac_address(pdev->dev.of_node, ndev->dev_addr); + ret = of_get_ethdev_address(pdev->dev.of_node, ndev); if (ret) eth_hw_addr_random(ndev); diff --git a/drivers/net/ethernet/amazon/ena/ena_com.c b/drivers/net/ethernet/amazon/ena/ena_com.c index f0faad149a3b..7979b1019242 100644 --- a/drivers/net/ethernet/amazon/ena/ena_com.c +++ b/drivers/net/ethernet/amazon/ena/ena_com.c @@ -35,6 +35,8 @@ #define ENA_REGS_ADMIN_INTR_MASK 1 +#define ENA_MAX_BACKOFF_DELAY_EXP 16U + #define ENA_MIN_ADMIN_POLL_US 100 #define ENA_MAX_ADMIN_POLL_US 5000 @@ -536,6 +538,7 @@ static int ena_com_comp_status_to_errno(struct ena_com_admin_queue *admin_queue, static void ena_delay_exponential_backoff_us(u32 exp, u32 delay_us) { + exp = min_t(u32, exp, ENA_MAX_BACKOFF_DELAY_EXP); delay_us = max_t(u32, ENA_MIN_ADMIN_POLL_US, delay_us); delay_us = min_t(u32, delay_us * (1U << exp), ENA_MAX_ADMIN_POLL_US); usleep_range(delay_us, 2 * delay_us); diff --git a/drivers/net/ethernet/amazon/ena/ena_netdev.c b/drivers/net/ethernet/amazon/ena/ena_netdev.c index 23c9750850e9..f3673be4fc08 100644 --- a/drivers/net/ethernet/amazon/ena/ena_netdev.c +++ b/drivers/net/ethernet/amazon/ena/ena_netdev.c @@ -4119,7 +4119,7 @@ static void ena_set_conf_feat_params(struct ena_adapter *adapter, ether_addr_copy(adapter->mac_addr, netdev->dev_addr); } else { ether_addr_copy(adapter->mac_addr, feat->dev_attr.mac_addr); - ether_addr_copy(netdev->dev_addr, adapter->mac_addr); + eth_hw_addr_set(netdev, adapter->mac_addr); } /* Set offload features */ diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_nic.c b/drivers/net/ethernet/aquantia/atlantic/aq_nic.c index ea2e7cd8946d..c52093589d7c 100644 --- a/drivers/net/ethernet/aquantia/atlantic/aq_nic.c +++ b/drivers/net/ethernet/aquantia/atlantic/aq_nic.c @@ -330,7 +330,7 @@ int aq_nic_ndev_register(struct aq_nic_s *self) { static u8 mac_addr_permanent[] = AQ_CFG_MAC_ADDR_PERMANENT; - ether_addr_copy(self->ndev->dev_addr, mac_addr_permanent); + eth_hw_addr_set(self->ndev, mac_addr_permanent); } #endif diff --git a/drivers/net/ethernet/arc/emac_main.c b/drivers/net/ethernet/arc/emac_main.c index 38c288ec9059..333333692caa 100644 --- a/drivers/net/ethernet/arc/emac_main.c +++ b/drivers/net/ethernet/arc/emac_main.c @@ -941,7 +941,7 @@ int arc_emac_probe(struct net_device *ndev, int interface) } /* Get MAC address from device tree */ - err = of_get_mac_address(dev->of_node, ndev->dev_addr); + err = of_get_ethdev_address(dev->of_node, ndev); if (err) eth_hw_addr_random(ndev); diff --git a/drivers/net/ethernet/atheros/ag71xx.c b/drivers/net/ethernet/atheros/ag71xx.c index 7295244b78d0..9d8b214c129d 100644 --- a/drivers/net/ethernet/atheros/ag71xx.c +++ b/drivers/net/ethernet/atheros/ag71xx.c @@ -1964,7 +1964,7 @@ static int ag71xx_probe(struct platform_device *pdev) ag->stop_desc->ctrl = 0; ag->stop_desc->next = (u32)ag->stop_desc_dma; - err = of_get_mac_address(np, ndev->dev_addr); + err = of_get_ethdev_address(np, ndev); if (err) { netif_err(ag, probe, ndev, "invalid MAC address, using random address\n"); eth_random_addr(ndev->dev_addr); diff --git a/drivers/net/ethernet/broadcom/bcm4908_enet.c b/drivers/net/ethernet/broadcom/bcm4908_enet.c index 7e89664943ce..ba48ddff5e7c 100644 --- a/drivers/net/ethernet/broadcom/bcm4908_enet.c +++ b/drivers/net/ethernet/broadcom/bcm4908_enet.c @@ -719,7 +719,7 @@ static int bcm4908_enet_probe(struct platform_device *pdev) return err; SET_NETDEV_DEV(netdev, &pdev->dev); - err = of_get_mac_address(dev->of_node, netdev->dev_addr); + err = of_get_ethdev_address(dev->of_node, netdev); if (err) eth_hw_addr_random(netdev); netdev->netdev_ops = &bcm4908_enet_netdev_ops; diff --git a/drivers/net/ethernet/broadcom/bcmsysport.c b/drivers/net/ethernet/broadcom/bcmsysport.c index 4c7f828c69c6..25466d73b432 100644 --- a/drivers/net/ethernet/broadcom/bcmsysport.c +++ b/drivers/net/ethernet/broadcom/bcmsysport.c @@ -2561,7 +2561,7 @@ static int bcm_sysport_probe(struct platform_device *pdev) } /* Initialize netdevice members */ - ret = of_get_mac_address(dn, dev->dev_addr); + ret = of_get_ethdev_address(dn, dev); if (ret) { dev_warn(&pdev->dev, "using random Ethernet MAC\n"); eth_hw_addr_random(dev); diff --git a/drivers/net/ethernet/broadcom/bgmac-bcma.c b/drivers/net/ethernet/broadcom/bgmac-bcma.c index 92453e68d381..678cc6a3617c 100644 --- a/drivers/net/ethernet/broadcom/bgmac-bcma.c +++ b/drivers/net/ethernet/broadcom/bgmac-bcma.c @@ -128,7 +128,7 @@ static int bgmac_probe(struct bcma_device *core) bcma_set_drvdata(core, bgmac); - err = of_get_mac_address(bgmac->dev->of_node, bgmac->net_dev->dev_addr); + err = of_get_ethdev_address(bgmac->dev->of_node, bgmac->net_dev); if (err == -EPROBE_DEFER) return err; @@ -150,7 +150,7 @@ static int bgmac_probe(struct bcma_device *core) err = -ENOTSUPP; goto err; } - ether_addr_copy(bgmac->net_dev->dev_addr, mac); + eth_hw_addr_set(bgmac->net_dev, mac); } /* On BCM4706 we need common core to access PHY */ diff --git a/drivers/net/ethernet/broadcom/bgmac-platform.c b/drivers/net/ethernet/broadcom/bgmac-platform.c index 94eb3a42158e..b4381cd41979 100644 --- a/drivers/net/ethernet/broadcom/bgmac-platform.c +++ b/drivers/net/ethernet/broadcom/bgmac-platform.c @@ -192,7 +192,7 @@ static int bgmac_probe(struct platform_device *pdev) bgmac->dev = &pdev->dev; bgmac->dma_dev = &pdev->dev; - ret = of_get_mac_address(np, bgmac->net_dev->dev_addr); + ret = of_get_ethdev_address(np, bgmac->net_dev); if (ret == -EPROBE_DEFER) return ret; diff --git a/drivers/net/ethernet/broadcom/bgmac.c b/drivers/net/ethernet/broadcom/bgmac.c index f8fd65ab663e..a9c99ac81730 100644 --- a/drivers/net/ethernet/broadcom/bgmac.c +++ b/drivers/net/ethernet/broadcom/bgmac.c @@ -1241,7 +1241,7 @@ static int bgmac_set_mac_address(struct net_device *net_dev, void *addr) if (ret < 0) return ret; - ether_addr_copy(net_dev->dev_addr, sa->sa_data); + eth_hw_addr_set(net_dev, sa->sa_data); bgmac_write_mac_address(bgmac, net_dev->dev_addr); eth_commit_mac_addr_change(net_dev, addr); @@ -1492,8 +1492,6 @@ int bgmac_enet_probe(struct bgmac *bgmac) bgmac->in_init = true; - bgmac_chip_intrs_off(bgmac); - net_dev->irq = bgmac->irq; SET_NETDEV_DEV(net_dev, bgmac->dev); dev_set_drvdata(bgmac->dev, bgmac); @@ -1511,6 +1509,8 @@ int bgmac_enet_probe(struct bgmac *bgmac) */ bgmac_clk_enable(bgmac, 0); + bgmac_chip_intrs_off(bgmac); + /* This seems to be fixing IRQ by assigning OOB #6 to the core */ if (!(bgmac->feature_flags & BGMAC_FEAT_IDM_MASK)) { if (bgmac->feature_flags & BGMAC_FEAT_IRQ_ID_OOB_6) diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_vfr.c b/drivers/net/ethernet/broadcom/bnxt/bnxt_vfr.c index 9401936b74fa..8eb28e088582 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt_vfr.c +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_vfr.c @@ -475,7 +475,7 @@ static void bnxt_vf_rep_netdev_init(struct bnxt *bp, struct bnxt_vf_rep *vf_rep, dev->features |= pf_dev->features; bnxt_vf_rep_eth_addr_gen(bp->pf.mac_addr, vf_rep->vf_idx, dev->perm_addr); - ether_addr_copy(dev->dev_addr, dev->perm_addr); + eth_hw_addr_set(dev, dev->perm_addr); /* Set VF-Rep's max-mtu to the corresponding VF's max-mtu */ if (!bnxt_hwrm_vfr_qcfg(bp, vf_rep, &max_mtu)) dev->max_mtu = max_mtu; diff --git a/drivers/net/ethernet/broadcom/genet/bcmgenet.c b/drivers/net/ethernet/broadcom/genet/bcmgenet.c index 9d4f406408c9..e036a244b78b 100644 --- a/drivers/net/ethernet/broadcom/genet/bcmgenet.c +++ b/drivers/net/ethernet/broadcom/genet/bcmgenet.c @@ -3610,7 +3610,7 @@ static int bcmgenet_set_mac_addr(struct net_device *dev, void *p) if (netif_running(dev)) return -EBUSY; - ether_addr_copy(dev->dev_addr, addr->sa_data); + eth_hw_addr_set(dev, addr->sa_data); return 0; } @@ -4060,7 +4060,7 @@ static int bcmgenet_probe(struct platform_device *pdev) bcmgenet_power_up(priv, GENET_POWER_PASSIVE); if (pd && !IS_ERR_OR_NULL(pd->mac_address)) - ether_addr_copy(dev->dev_addr, pd->mac_address); + eth_hw_addr_set(dev, pd->mac_address); else if (!device_get_mac_address(&pdev->dev, dev->dev_addr, ETH_ALEN)) if (has_acpi_companion(&pdev->dev)) diff --git a/drivers/net/ethernet/broadcom/genet/bcmmii.c b/drivers/net/ethernet/broadcom/genet/bcmmii.c index f61f832ea19c..8c800d9c11b7 100644 --- a/drivers/net/ethernet/broadcom/genet/bcmmii.c +++ b/drivers/net/ethernet/broadcom/genet/bcmmii.c @@ -627,5 +627,7 @@ void bcmgenet_mii_exit(struct net_device *dev) if (of_phy_is_fixed_link(dn)) of_phy_deregister_fixed_link(dn); of_node_put(priv->phy_dn); + clk_prepare_enable(priv->clk); platform_device_unregister(priv->mii_pdev); + clk_disable_unprepare(priv->clk); } diff --git a/drivers/net/ethernet/broadcom/tg3.c b/drivers/net/ethernet/broadcom/tg3.c index 50f86bebbc19..70b1a855273e 100644 --- a/drivers/net/ethernet/broadcom/tg3.c +++ b/drivers/net/ethernet/broadcom/tg3.c @@ -224,6 +224,7 @@ MODULE_AUTHOR("David S. Miller (davem@redhat.com) and Jeff Garzik (jgarzik@pobox MODULE_DESCRIPTION("Broadcom Tigon3 ethernet driver"); MODULE_LICENSE("GPL"); MODULE_FIRMWARE(FIRMWARE_TG3); +MODULE_FIRMWARE(FIRMWARE_TG357766); MODULE_FIRMWARE(FIRMWARE_TG3TSO); MODULE_FIRMWARE(FIRMWARE_TG3TSO5); diff --git a/drivers/net/ethernet/brocade/bna/bnad.c b/drivers/net/ethernet/brocade/bna/bnad.c index ba47777d9cff..b1947fd9a07c 100644 --- a/drivers/net/ethernet/brocade/bna/bnad.c +++ b/drivers/net/ethernet/brocade/bna/bnad.c @@ -875,7 +875,7 @@ bnad_set_netdev_perm_addr(struct bnad *bnad) ether_addr_copy(netdev->perm_addr, bnad->perm_addr); if (is_zero_ether_addr(netdev->dev_addr)) - ether_addr_copy(netdev->dev_addr, bnad->perm_addr); + eth_hw_addr_set(netdev, bnad->perm_addr); } /* Control Path Handlers */ @@ -3249,7 +3249,7 @@ bnad_set_mac_address(struct net_device *netdev, void *addr) err = bnad_mac_addr_set_locked(bnad, sa->sa_data); if (!err) - ether_addr_copy(netdev->dev_addr, sa->sa_data); + eth_hw_addr_set(netdev, sa->sa_data); spin_unlock_irqrestore(&bnad->bna_lock, flags); diff --git a/drivers/net/ethernet/cadence/macb_main.c b/drivers/net/ethernet/cadence/macb_main.c index d86ea6b6c3ef..1ffd0ef39f89 100644 --- a/drivers/net/ethernet/cadence/macb_main.c +++ b/drivers/net/ethernet/cadence/macb_main.c @@ -4834,7 +4834,7 @@ static int macb_probe(struct platform_device *pdev) if (bp->caps & MACB_CAPS_NEEDS_RSTONUBR) bp->rx_intr_mask |= MACB_BIT(RXUBR); - err = of_get_mac_address(np, bp->dev->dev_addr); + err = of_get_ethdev_address(np, bp->dev); if (err == -EPROBE_DEFER) goto err_out_free_netdev; else if (err) diff --git a/drivers/net/ethernet/cavium/liquidio/lio_core.c b/drivers/net/ethernet/cavium/liquidio/lio_core.c index 2a0d64e5797c..ec7928b54e4a 100644 --- a/drivers/net/ethernet/cavium/liquidio/lio_core.c +++ b/drivers/net/ethernet/cavium/liquidio/lio_core.c @@ -411,7 +411,7 @@ void octeon_pf_changed_vf_macaddr(struct octeon_device *oct, u8 *mac) if (!ether_addr_equal(netdev->dev_addr, mac)) { macaddr_changed = true; - ether_addr_copy(netdev->dev_addr, mac); + eth_hw_addr_set(netdev, mac); ether_addr_copy(((u8 *)&lio->linfo.hw_addr) + 2, mac); call_netdevice_notifiers(NETDEV_CHANGEADDR, netdev); } diff --git a/drivers/net/ethernet/cavium/liquidio/lio_main.c b/drivers/net/ethernet/cavium/liquidio/lio_main.c index ae68821dd56d..443755729d79 100644 --- a/drivers/net/ethernet/cavium/liquidio/lio_main.c +++ b/drivers/net/ethernet/cavium/liquidio/lio_main.c @@ -3650,7 +3650,7 @@ static int setup_nic_devices(struct octeon_device *octeon_dev) /* Copy MAC Address to OS network device structure */ - ether_addr_copy(netdev->dev_addr, mac); + eth_hw_addr_set(netdev, mac); /* By default all interfaces on a single Octeon uses the same * tx and rx queues diff --git a/drivers/net/ethernet/cavium/liquidio/lio_vf_main.c b/drivers/net/ethernet/cavium/liquidio/lio_vf_main.c index f6396ac64006..8a969a9d4b63 100644 --- a/drivers/net/ethernet/cavium/liquidio/lio_vf_main.c +++ b/drivers/net/ethernet/cavium/liquidio/lio_vf_main.c @@ -2148,7 +2148,7 @@ static int setup_nic_devices(struct octeon_device *octeon_dev) mac[j] = *((u8 *)(((u8 *)&lio->linfo.hw_addr) + 2 + j)); /* Copy MAC Address to OS network device structure */ - ether_addr_copy(netdev->dev_addr, mac); + eth_hw_addr_set(netdev, mac); if (liquidio_setup_io_queues(octeon_dev, i, lio->linfo.num_txpciq, diff --git a/drivers/net/ethernet/cavium/octeon/octeon_mgmt.c b/drivers/net/ethernet/cavium/octeon/octeon_mgmt.c index 30463a6d1f8c..4e39d712e121 100644 --- a/drivers/net/ethernet/cavium/octeon/octeon_mgmt.c +++ b/drivers/net/ethernet/cavium/octeon/octeon_mgmt.c @@ -1501,7 +1501,7 @@ static int octeon_mgmt_probe(struct platform_device *pdev) netdev->min_mtu = 64 - OCTEON_MGMT_RX_HEADROOM; netdev->max_mtu = 16383 - OCTEON_MGMT_RX_HEADROOM - VLAN_HLEN; - result = of_get_mac_address(pdev->dev.of_node, netdev->dev_addr); + result = of_get_ethdev_address(pdev->dev.of_node, netdev); if (result) eth_hw_addr_random(netdev); diff --git a/drivers/net/ethernet/cavium/thunder/nicvf_main.c b/drivers/net/ethernet/cavium/thunder/nicvf_main.c index b43b97e15a6f..8418797be205 100644 --- a/drivers/net/ethernet/cavium/thunder/nicvf_main.c +++ b/drivers/net/ethernet/cavium/thunder/nicvf_main.c @@ -221,8 +221,7 @@ static void nicvf_handle_mbx_intr(struct nicvf *nic) nic->tns_mode = mbx.nic_cfg.tns_mode & 0x7F; nic->node = mbx.nic_cfg.node_id; if (!nic->set_mac_pending) - ether_addr_copy(nic->netdev->dev_addr, - mbx.nic_cfg.mac_addr); + eth_hw_addr_set(nic->netdev, mbx.nic_cfg.mac_addr); nic->sqs_mode = mbx.nic_cfg.sqs_mode; nic->loopback_supported = mbx.nic_cfg.loopback_supported; nic->link_up = false; diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c index e874b907bfbd..3ccb955eb6f2 100644 --- a/drivers/net/ethernet/emulex/benet/be_main.c +++ b/drivers/net/ethernet/emulex/benet/be_main.c @@ -369,7 +369,7 @@ static int be_mac_addr_set(struct net_device *netdev, void *p) /* Remember currently programmed MAC */ ether_addr_copy(adapter->dev_mac, addr->sa_data); done: - ether_addr_copy(netdev->dev_addr, addr->sa_data); + eth_hw_addr_set(netdev, addr->sa_data); dev_info(dev, "MAC address changed to %pM\n", addr->sa_data); return 0; err: diff --git a/drivers/net/ethernet/ethoc.c b/drivers/net/ethernet/ethoc.c index ed1ed48e7483..7f456297fc45 100644 --- a/drivers/net/ethernet/ethoc.c +++ b/drivers/net/ethernet/ethoc.c @@ -1148,10 +1148,10 @@ static int ethoc_probe(struct platform_device *pdev) /* Allow the platform setup code to pass in a MAC address. */ if (pdata) { - ether_addr_copy(netdev->dev_addr, pdata->hwaddr); + eth_hw_addr_set(netdev, pdata->hwaddr); priv->phy_id = pdata->phy_id; } else { - of_get_mac_address(pdev->dev.of_node, netdev->dev_addr); + of_get_ethdev_address(pdev->dev.of_node, netdev); priv->phy_id = -1; } diff --git a/drivers/net/ethernet/ezchip/nps_enet.c b/drivers/net/ethernet/ezchip/nps_enet.c index f9a288a6ec8c..323340826dab 100644 --- a/drivers/net/ethernet/ezchip/nps_enet.c +++ b/drivers/net/ethernet/ezchip/nps_enet.c @@ -421,7 +421,7 @@ static s32 nps_enet_set_mac_address(struct net_device *ndev, void *p) res = eth_mac_addr(ndev, p); if (!res) { - ether_addr_copy(ndev->dev_addr, addr->sa_data); + eth_hw_addr_set(ndev, addr->sa_data); nps_enet_set_hw_mac_address(ndev); } @@ -601,7 +601,7 @@ static s32 nps_enet_probe(struct platform_device *pdev) dev_dbg(dev, "Registers base address is 0x%p\n", priv->regs_base); /* set kernel MAC address to dev */ - err = of_get_mac_address(dev->of_node, ndev->dev_addr); + err = of_get_ethdev_address(dev->of_node, ndev); if (err) eth_hw_addr_random(ndev); diff --git a/drivers/net/ethernet/faraday/ftgmac100.c b/drivers/net/ethernet/faraday/ftgmac100.c index 4a2dadb91f02..11f76e56d031 100644 --- a/drivers/net/ethernet/faraday/ftgmac100.c +++ b/drivers/net/ethernet/faraday/ftgmac100.c @@ -186,7 +186,7 @@ static void ftgmac100_initial_mac(struct ftgmac100 *priv) addr = device_get_mac_address(priv->dev, mac, ETH_ALEN); if (addr) { - ether_addr_copy(priv->netdev->dev_addr, mac); + eth_hw_addr_set(priv->netdev, mac); dev_info(priv->dev, "Read MAC address %pM from device tree\n", mac); return; @@ -203,7 +203,7 @@ static void ftgmac100_initial_mac(struct ftgmac100 *priv) mac[5] = l & 0xff; if (is_valid_ether_addr(mac)) { - ether_addr_copy(priv->netdev->dev_addr, mac); + eth_hw_addr_set(priv->netdev, mac); dev_info(priv->dev, "Read MAC address %pM from chip\n", mac); } else { eth_hw_addr_random(priv->netdev); diff --git a/drivers/net/ethernet/freescale/fec_mpc52xx.c b/drivers/net/ethernet/freescale/fec_mpc52xx.c index 73ff359a15f1..2777dd2b4dd7 100644 --- a/drivers/net/ethernet/freescale/fec_mpc52xx.c +++ b/drivers/net/ethernet/freescale/fec_mpc52xx.c @@ -890,7 +890,7 @@ static int mpc52xx_fec_probe(struct platform_device *op) * * First try to read MAC address from DT */ - rv = of_get_mac_address(np, ndev->dev_addr); + rv = of_get_ethdev_address(np, ndev); if (rv) { struct mpc52xx_fec __iomem *fec = priv->fec; diff --git a/drivers/net/ethernet/freescale/fs_enet/fs_enet-main.c b/drivers/net/ethernet/freescale/fs_enet/fs_enet-main.c index 2db6e38a772e..bacf25318f87 100644 --- a/drivers/net/ethernet/freescale/fs_enet/fs_enet-main.c +++ b/drivers/net/ethernet/freescale/fs_enet/fs_enet-main.c @@ -1005,7 +1005,7 @@ static int fs_enet_probe(struct platform_device *ofdev) spin_lock_init(&fep->lock); spin_lock_init(&fep->tx_lock); - of_get_mac_address(ofdev->dev.of_node, ndev->dev_addr); + of_get_ethdev_address(ofdev->dev.of_node, ndev); ret = fep->ops->allocate_bd(ndev); if (ret) diff --git a/drivers/net/ethernet/freescale/gianfar.c b/drivers/net/ethernet/freescale/gianfar.c index af6ad94bf24a..acab58fd3db3 100644 --- a/drivers/net/ethernet/freescale/gianfar.c +++ b/drivers/net/ethernet/freescale/gianfar.c @@ -753,7 +753,7 @@ static int gfar_of_init(struct platform_device *ofdev, struct net_device **pdev) if (stash_len || stash_idx) priv->device_flags |= FSL_GIANFAR_DEV_HAS_BUF_STASHING; - err = of_get_mac_address(np, dev->dev_addr); + err = of_get_ethdev_address(np, dev); if (err) { eth_hw_addr_random(dev); dev_info(&ofdev->dev, "Using random MAC address: %pM\n", dev->dev_addr); diff --git a/drivers/net/ethernet/freescale/ucc_geth.c b/drivers/net/ethernet/freescale/ucc_geth.c index 3eb288d10b0c..e0036fd2b56c 100644 --- a/drivers/net/ethernet/freescale/ucc_geth.c +++ b/drivers/net/ethernet/freescale/ucc_geth.c @@ -3731,7 +3731,7 @@ static int ucc_geth_probe(struct platform_device* ofdev) goto err_free_netdev; } - of_get_mac_address(np, dev->dev_addr); + of_get_ethdev_address(np, dev); ugeth->ug_info = ug_info; ugeth->dev = device; diff --git a/drivers/net/ethernet/google/gve/gve_adminq.c b/drivers/net/ethernet/google/gve/gve_adminq.c index ce507464f3d6..54d649e5ee65 100644 --- a/drivers/net/ethernet/google/gve/gve_adminq.c +++ b/drivers/net/ethernet/google/gve/gve_adminq.c @@ -733,7 +733,7 @@ int gve_adminq_describe_device(struct gve_priv *priv) } priv->dev->max_mtu = mtu; priv->num_event_counters = be16_to_cpu(descriptor->counters); - ether_addr_copy(priv->dev->dev_addr, descriptor->mac); + eth_hw_addr_set(priv->dev, descriptor->mac); mac = descriptor->mac; dev_info(&priv->pdev->dev, "MAC addr: %pM\n", mac); priv->tx_pages_per_qpl = be16_to_cpu(descriptor->tx_pages_per_qpl); diff --git a/drivers/net/ethernet/google/gve/gve_ethtool.c b/drivers/net/ethernet/google/gve/gve_ethtool.c index 6a0663aadd1e..1f8cc722aae3 100644 --- a/drivers/net/ethernet/google/gve/gve_ethtool.c +++ b/drivers/net/ethernet/google/gve/gve_ethtool.c @@ -532,6 +532,9 @@ static int gve_get_link_ksettings(struct net_device *netdev, err = gve_adminq_report_link_speed(priv); cmd->base.speed = priv->link_speed; + + cmd->base.duplex = DUPLEX_FULL; + return err; } diff --git a/drivers/net/ethernet/hisilicon/hisi_femac.c b/drivers/net/ethernet/hisilicon/hisi_femac.c index ea3e67cf5ffa..05cb4582a58d 100644 --- a/drivers/net/ethernet/hisilicon/hisi_femac.c +++ b/drivers/net/ethernet/hisilicon/hisi_femac.c @@ -841,7 +841,7 @@ static int hisi_femac_drv_probe(struct platform_device *pdev) (unsigned long)phy->phy_id, phy_modes(phy->interface)); - ret = of_get_mac_address(node, ndev->dev_addr); + ret = of_get_ethdev_address(node, ndev); if (ret) { eth_hw_addr_random(ndev); dev_warn(dev, "using random MAC address %pM\n", diff --git a/drivers/net/ethernet/hisilicon/hix5hd2_gmac.c b/drivers/net/ethernet/hisilicon/hix5hd2_gmac.c index 0a70fb979f0c..923191b9a87d 100644 --- a/drivers/net/ethernet/hisilicon/hix5hd2_gmac.c +++ b/drivers/net/ethernet/hisilicon/hix5hd2_gmac.c @@ -1219,7 +1219,7 @@ static int hix5hd2_dev_probe(struct platform_device *pdev) goto out_phy_node; } - ret = of_get_mac_address(node, ndev->dev_addr); + ret = of_get_ethdev_address(node, ndev); if (ret) { eth_hw_addr_random(ndev); netdev_warn(ndev, "using random MAC address %pM\n", diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c index dc835f316d47..2acf50ed6025 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c @@ -2251,7 +2251,7 @@ static int hns3_nic_net_set_mac_address(struct net_device *netdev, void *p) return ret; } - ether_addr_copy(netdev->dev_addr, mac_addr->sa_data); + eth_hw_addr_set(netdev, mac_addr->sa_data); return 0; } @@ -4921,7 +4921,7 @@ static int hns3_init_mac_addr(struct net_device *netdev) dev_warn(priv->dev, "using random MAC address %s\n", format_mac_addr); } else if (!ether_addr_equal(netdev->dev_addr, mac_addr_temp)) { - ether_addr_copy(netdev->dev_addr, mac_addr_temp); + eth_hw_addr_set(netdev, mac_addr_temp); ether_addr_copy(netdev->perm_addr, mac_addr_temp); } else { return 0; diff --git a/drivers/net/ethernet/ibm/ibmveth.c b/drivers/net/ethernet/ibm/ibmveth.c index 3d9b4f99d357..77d8db9b8a1d 100644 --- a/drivers/net/ethernet/ibm/ibmveth.c +++ b/drivers/net/ethernet/ibm/ibmveth.c @@ -1620,7 +1620,7 @@ static int ibmveth_set_mac_addr(struct net_device *dev, void *p) return rc; } - ether_addr_copy(dev->dev_addr, addr->sa_data); + eth_hw_addr_set(dev, addr->sa_data); return 0; } diff --git a/drivers/net/ethernet/ibm/ibmvnic.c b/drivers/net/ethernet/ibm/ibmvnic.c index 8a92c6a6e764..450b4fd9aa7f 100644 --- a/drivers/net/ethernet/ibm/ibmvnic.c +++ b/drivers/net/ethernet/ibm/ibmvnic.c @@ -1240,7 +1240,14 @@ static int __ibmvnic_open(struct net_device *netdev) if (prev_state == VNIC_CLOSED) enable_irq(adapter->tx_scrq[i]->irq); enable_scrq_irq(adapter, adapter->tx_scrq[i]); - netdev_tx_reset_queue(netdev_get_tx_queue(netdev, i)); + /* netdev_tx_reset_queue will reset dql stats. During NON_FATAL + * resets, don't reset the stats because there could be batched + * skb's waiting to be sent. If we reset dql stats, we risk + * num_completed being greater than num_queued. This will cause + * a BUG_ON in dql_completed(). + */ + if (adapter->reset_reason != VNIC_RESET_NON_FATAL) + netdev_tx_reset_queue(netdev_get_tx_queue(netdev, i)); } rc = set_link_state(adapter, IBMVNIC_LOGICAL_LNK_UP); @@ -4682,8 +4689,7 @@ static int handle_change_mac_rsp(union ibmvnic_crq *crq, /* crq->change_mac_addr.mac_addr is the requested one * crq->change_mac_addr_rsp.mac_addr is the returned valid one. */ - ether_addr_copy(netdev->dev_addr, - &crq->change_mac_addr_rsp.mac_addr[0]); + eth_hw_addr_set(netdev, &crq->change_mac_addr_rsp.mac_addr[0]); ether_addr_copy(adapter->mac_addr, &crq->change_mac_addr_rsp.mac_addr[0]); out: @@ -5651,7 +5657,7 @@ static int ibmvnic_probe(struct vio_dev *dev, const struct vio_device_id *id) adapter->login_pending = false; ether_addr_copy(adapter->mac_addr, mac_addr_p); - ether_addr_copy(netdev->dev_addr, adapter->mac_addr); + eth_hw_addr_set(netdev, adapter->mac_addr); netdev->irq = dev->irq; netdev->netdev_ops = &ibmvnic_netdev_ops; netdev->ethtool_ops = &ibmvnic_ethtool_ops; diff --git a/drivers/net/ethernet/intel/fm10k/fm10k_netdev.c b/drivers/net/ethernet/intel/fm10k/fm10k_netdev.c index 2fb52bd6fc0e..2cca9e84e31e 100644 --- a/drivers/net/ethernet/intel/fm10k/fm10k_netdev.c +++ b/drivers/net/ethernet/intel/fm10k/fm10k_netdev.c @@ -990,7 +990,7 @@ static int fm10k_set_mac(struct net_device *dev, void *p) } if (!err) { - ether_addr_copy(dev->dev_addr, addr->sa_data); + eth_hw_addr_set(dev, addr->sa_data); ether_addr_copy(hw->mac.addr, addr->sa_data); dev->addr_assign_type &= ~NET_ADDR_RANDOM; } diff --git a/drivers/net/ethernet/intel/fm10k/fm10k_pci.c b/drivers/net/ethernet/intel/fm10k/fm10k_pci.c index adfa2768f024..b473cb7d7c57 100644 --- a/drivers/net/ethernet/intel/fm10k/fm10k_pci.c +++ b/drivers/net/ethernet/intel/fm10k/fm10k_pci.c @@ -300,7 +300,7 @@ static int fm10k_handle_reset(struct fm10k_intfc *interface) if (is_valid_ether_addr(hw->mac.perm_addr)) { ether_addr_copy(hw->mac.addr, hw->mac.perm_addr); ether_addr_copy(netdev->perm_addr, hw->mac.perm_addr); - ether_addr_copy(netdev->dev_addr, hw->mac.perm_addr); + eth_hw_addr_set(netdev, hw->mac.perm_addr); netdev->addr_assign_type &= ~NET_ADDR_RANDOM; } @@ -2045,7 +2045,7 @@ static int fm10k_sw_init(struct fm10k_intfc *interface, netdev->addr_assign_type |= NET_ADDR_RANDOM; } - ether_addr_copy(netdev->dev_addr, hw->mac.addr); + eth_hw_addr_set(netdev, hw->mac.addr); ether_addr_copy(netdev->perm_addr, hw->mac.addr); if (!is_valid_ether_addr(netdev->perm_addr)) { diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c index 8411f277d135..d3f3874220a3 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_main.c +++ b/drivers/net/ethernet/intel/i40e/i40e_main.c @@ -1686,7 +1686,7 @@ static int i40e_set_mac(struct net_device *netdev, void *p) */ spin_lock_bh(&vsi->mac_filter_hash_lock); i40e_del_mac_filter(vsi, netdev->dev_addr); - ether_addr_copy(netdev->dev_addr, addr->sa_data); + eth_hw_addr_set(netdev, addr->sa_data); i40e_add_mac_filter(vsi, netdev->dev_addr); spin_unlock_bh(&vsi->mac_filter_hash_lock); @@ -13659,7 +13659,7 @@ static int i40e_config_netdev(struct i40e_vsi *vsi) i40e_add_mac_filter(vsi, broadcast); spin_unlock_bh(&vsi->mac_filter_hash_lock); - ether_addr_copy(netdev->dev_addr, mac_addr); + eth_hw_addr_set(netdev, mac_addr); ether_addr_copy(netdev->perm_addr, mac_addr); /* i40iw_net_event() reads 16 bytes from neigh->primary_key */ diff --git a/drivers/net/ethernet/intel/iavf/iavf_ethtool.c b/drivers/net/ethernet/intel/iavf/iavf_ethtool.c index 461f5237a2f8..5af3ae68b7a1 100644 --- a/drivers/net/ethernet/intel/iavf/iavf_ethtool.c +++ b/drivers/net/ethernet/intel/iavf/iavf_ethtool.c @@ -1855,7 +1855,7 @@ static int iavf_set_channels(struct net_device *netdev, } if (i == IAVF_RESET_WAIT_COMPLETE_COUNT) { adapter->flags &= ~IAVF_FLAG_REINIT_ITR_NEEDED; - adapter->num_active_queues = num_req; + adapter->num_req_queues = 0; return -EOPNOTSUPP; } diff --git a/drivers/net/ethernet/intel/iavf/iavf_main.c b/drivers/net/ethernet/intel/iavf/iavf_main.c index a3caab0b6fa2..bcceb2ddfea6 100644 --- a/drivers/net/ethernet/intel/iavf/iavf_main.c +++ b/drivers/net/ethernet/intel/iavf/iavf_main.c @@ -1507,19 +1507,16 @@ static int iavf_alloc_q_vectors(struct iavf_adapter *adapter) static void iavf_free_q_vectors(struct iavf_adapter *adapter) { int q_idx, num_q_vectors; - int napi_vectors; if (!adapter->q_vectors) return; num_q_vectors = adapter->num_msix_vectors - NONQ_VECS; - napi_vectors = adapter->num_active_queues; for (q_idx = 0; q_idx < num_q_vectors; q_idx++) { struct iavf_q_vector *q_vector = &adapter->q_vectors[q_idx]; - if (q_idx < napi_vectors) - netif_napi_del(&q_vector->napi); + netif_napi_del(&q_vector->napi); } kfree(adapter->q_vectors); adapter->q_vectors = NULL; @@ -1963,7 +1960,7 @@ static void iavf_init_get_resources(struct iavf_adapter *adapter) eth_hw_addr_random(netdev); ether_addr_copy(adapter->hw.mac.addr, netdev->dev_addr); } else { - ether_addr_copy(netdev->dev_addr, adapter->hw.mac.addr); + eth_hw_addr_set(netdev, adapter->hw.mac.addr); ether_addr_copy(netdev->perm_addr, adapter->hw.mac.addr); } diff --git a/drivers/net/ethernet/intel/iavf/iavf_virtchnl.c b/drivers/net/ethernet/intel/iavf/iavf_virtchnl.c index c6eb0d0748ea..262482c69458 100644 --- a/drivers/net/ethernet/intel/iavf/iavf_virtchnl.c +++ b/drivers/net/ethernet/intel/iavf/iavf_virtchnl.c @@ -1726,7 +1726,7 @@ void iavf_virtchnl_completion(struct iavf_adapter *adapter, if (!v_retval) iavf_mac_add_ok(adapter); if (!ether_addr_equal(netdev->dev_addr, adapter->hw.mac.addr)) - ether_addr_copy(netdev->dev_addr, adapter->hw.mac.addr); + eth_hw_addr_set(netdev, adapter->hw.mac.addr); break; case VIRTCHNL_OP_GET_STATS: { struct iavf_eth_stats *stats = @@ -1757,7 +1757,7 @@ void iavf_virtchnl_completion(struct iavf_adapter *adapter, ether_addr_copy(adapter->hw.mac.addr, netdev->dev_addr); } else { /* refresh current mac address if changed */ - ether_addr_copy(netdev->dev_addr, adapter->hw.mac.addr); + eth_hw_addr_set(netdev, adapter->hw.mac.addr); ether_addr_copy(netdev->perm_addr, adapter->hw.mac.addr); } diff --git a/drivers/net/ethernet/intel/ice/ice_main.c b/drivers/net/ethernet/intel/ice/ice_main.c index bf9fe385274e..a18fa054b4fa 100644 --- a/drivers/net/ethernet/intel/ice/ice_main.c +++ b/drivers/net/ethernet/intel/ice/ice_main.c @@ -3183,7 +3183,7 @@ static int ice_cfg_netdev(struct ice_vsi *vsi) if (vsi->type == ICE_VSI_PF) { SET_NETDEV_DEV(netdev, ice_pf_to_dev(vsi->back)); ether_addr_copy(mac_addr, vsi->port_info->mac.perm_addr); - ether_addr_copy(netdev->dev_addr, mac_addr); + eth_hw_addr_set(netdev, mac_addr); ether_addr_copy(netdev->perm_addr, mac_addr); } @@ -5225,7 +5225,7 @@ err_update_filters: netdev_err(netdev, "can't set MAC %pM. filter update failed\n", mac); netif_addr_lock_bh(netdev); - ether_addr_copy(netdev->dev_addr, old_mac); + eth_hw_addr_set(netdev, old_mac); netif_addr_unlock_bh(netdev); return err; } diff --git a/drivers/net/ethernet/intel/igb/igb_main.c b/drivers/net/ethernet/intel/igb/igb_main.c index bff9649d8abd..83daf86c1674 100644 --- a/drivers/net/ethernet/intel/igb/igb_main.c +++ b/drivers/net/ethernet/intel/igb/igb_main.c @@ -4737,6 +4737,10 @@ void igb_configure_rx_ring(struct igb_adapter *adapter, static void igb_set_rx_buffer_len(struct igb_adapter *adapter, struct igb_ring *rx_ring) { +#if (PAGE_SIZE < 8192) + struct e1000_hw *hw = &adapter->hw; +#endif + /* set build_skb and buffer size flags */ clear_ring_build_skb_enabled(rx_ring); clear_ring_uses_large_buffer(rx_ring); @@ -4747,10 +4751,9 @@ static void igb_set_rx_buffer_len(struct igb_adapter *adapter, set_ring_build_skb_enabled(rx_ring); #if (PAGE_SIZE < 8192) - if (adapter->max_frame_size <= IGB_MAX_FRAME_BUILD_SKB) - return; - - set_ring_uses_large_buffer(rx_ring); + if (adapter->max_frame_size > IGB_MAX_FRAME_BUILD_SKB || + rd32(E1000_RCTL) & E1000_RCTL_SBP) + set_ring_uses_large_buffer(rx_ring); #endif } diff --git a/drivers/net/ethernet/intel/igc/igc.h b/drivers/net/ethernet/intel/igc/igc.h index 66678cd72a6c..192fee9e72b0 100644 --- a/drivers/net/ethernet/intel/igc/igc.h +++ b/drivers/net/ethernet/intel/igc/igc.h @@ -13,6 +13,7 @@ #include #include #include +#include #include "igc_hw.h" @@ -227,6 +228,10 @@ struct igc_adapter { struct ptp_clock *ptp_clock; struct ptp_clock_info ptp_caps; struct work_struct ptp_tx_work; + /* Access to ptp_tx_skb and ptp_tx_start are protected by the + * ptp_tx_lock. + */ + spinlock_t ptp_tx_lock; struct sk_buff *ptp_tx_skb; struct hwtstamp_config tstamp_config; unsigned long ptp_tx_start; @@ -312,6 +317,33 @@ extern char igc_driver_name[]; #define IGC_MRQC_RSS_FIELD_IPV4_UDP 0x00400000 #define IGC_MRQC_RSS_FIELD_IPV6_UDP 0x00800000 +/* RX-desc Write-Back format RSS Type's */ +enum igc_rss_type_num { + IGC_RSS_TYPE_NO_HASH = 0, + IGC_RSS_TYPE_HASH_TCP_IPV4 = 1, + IGC_RSS_TYPE_HASH_IPV4 = 2, + IGC_RSS_TYPE_HASH_TCP_IPV6 = 3, + IGC_RSS_TYPE_HASH_IPV6_EX = 4, + IGC_RSS_TYPE_HASH_IPV6 = 5, + IGC_RSS_TYPE_HASH_TCP_IPV6_EX = 6, + IGC_RSS_TYPE_HASH_UDP_IPV4 = 7, + IGC_RSS_TYPE_HASH_UDP_IPV6 = 8, + IGC_RSS_TYPE_HASH_UDP_IPV6_EX = 9, + IGC_RSS_TYPE_MAX = 10, +}; +#define IGC_RSS_TYPE_MAX_TABLE 16 +#define IGC_RSS_TYPE_MASK GENMASK(3,0) /* 4-bits (3:0) = mask 0x0F */ + +/* igc_rss_type - Rx descriptor RSS type field */ +static inline u32 igc_rss_type(const union igc_adv_rx_desc *rx_desc) +{ + /* RSS Type 4-bits (3:0) number: 0-9 (above 9 is reserved) + * Accessing the same bits via u16 (wb.lower.lo_dword.hs_rss.pkt_info) + * is slightly slower than via u32 (wb.lower.lo_dword.data) + */ + return le32_get_bits(rx_desc->wb.lower.lo_dword.data, IGC_RSS_TYPE_MASK); +} + /* Interrupt defines */ #define IGC_START_ITR 648 /* ~6000 ints/sec */ #define IGC_4K_ITR 980 @@ -402,7 +434,6 @@ enum igc_state_t { __IGC_TESTING, __IGC_RESETTING, __IGC_DOWN, - __IGC_PTP_TX_IN_PROGRESS, }; enum igc_tx_flags { diff --git a/drivers/net/ethernet/intel/igc/igc_ethtool.c b/drivers/net/ethernet/intel/igc/igc_ethtool.c index e0a76ac1bbbc..859ddc07fbbf 100644 --- a/drivers/net/ethernet/intel/igc/igc_ethtool.c +++ b/drivers/net/ethernet/intel/igc/igc_ethtool.c @@ -1701,6 +1701,8 @@ static int igc_ethtool_get_link_ksettings(struct net_device *netdev, /* twisted pair */ cmd->base.port = PORT_TP; cmd->base.phy_address = hw->phy.addr; + ethtool_link_ksettings_add_link_mode(cmd, supported, TP); + ethtool_link_ksettings_add_link_mode(cmd, advertising, TP); /* advertising link modes */ if (hw->phy.autoneg_advertised & ADVERTISE_10_HALF) diff --git a/drivers/net/ethernet/intel/igc/igc_main.c b/drivers/net/ethernet/intel/igc/igc_main.c index eb7aa8c13f7e..bcc1c428b4cc 100644 --- a/drivers/net/ethernet/intel/igc/igc_main.c +++ b/drivers/net/ethernet/intel/igc/igc_main.c @@ -708,7 +708,6 @@ static void igc_configure_tx_ring(struct igc_adapter *adapter, /* disable the queue */ wr32(IGC_TXDCTL(reg_idx), 0); wrfl(); - mdelay(10); wr32(IGC_TDLEN(reg_idx), ring->count * sizeof(union igc_adv_tx_desc)); @@ -1014,7 +1013,7 @@ static __le32 igc_tx_launchtime(struct igc_ring *ring, ktime_t txtime, ktime_t base_time = adapter->base_time; ktime_t now = ktime_get_clocktai(); ktime_t baset_est, end_of_cycle; - u32 launchtime; + s32 launchtime; s64 n; n = div64_s64(ktime_sub_ns(now, base_time), cycle_time); @@ -1027,7 +1026,7 @@ static __le32 igc_tx_launchtime(struct igc_ring *ring, ktime_t txtime, *first_flag = true; ring->last_ff_cycle = baset_est; - if (ktime_compare(txtime, ring->last_tx_cycle) > 0) + if (ktime_compare(end_of_cycle, ring->last_tx_cycle) > 0) *insert_empty = true; } } @@ -1576,9 +1575,10 @@ done: * the other timer registers before skipping the * timestamping request. */ - if (adapter->tstamp_config.tx_type == HWTSTAMP_TX_ON && - !test_and_set_bit_lock(__IGC_PTP_TX_IN_PROGRESS, - &adapter->state)) { + unsigned long flags; + + spin_lock_irqsave(&adapter->ptp_tx_lock, flags); + if (adapter->tstamp_config.tx_type == HWTSTAMP_TX_ON && !adapter->ptp_tx_skb) { skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS; tx_flags |= IGC_TX_FLAGS_TSTAMP; @@ -1587,6 +1587,8 @@ done: } else { adapter->tx_hwtstamp_skipped++; } + + spin_unlock_irqrestore(&adapter->ptp_tx_lock, flags); } if (skb_vlan_tag_present(skb)) { @@ -1683,14 +1685,36 @@ static void igc_rx_checksum(struct igc_ring *ring, le32_to_cpu(rx_desc->wb.upper.status_error)); } +/* Mapping HW RSS Type to enum pkt_hash_types */ +static const enum pkt_hash_types igc_rss_type_table[IGC_RSS_TYPE_MAX_TABLE] = { + [IGC_RSS_TYPE_NO_HASH] = PKT_HASH_TYPE_L2, + [IGC_RSS_TYPE_HASH_TCP_IPV4] = PKT_HASH_TYPE_L4, + [IGC_RSS_TYPE_HASH_IPV4] = PKT_HASH_TYPE_L3, + [IGC_RSS_TYPE_HASH_TCP_IPV6] = PKT_HASH_TYPE_L4, + [IGC_RSS_TYPE_HASH_IPV6_EX] = PKT_HASH_TYPE_L3, + [IGC_RSS_TYPE_HASH_IPV6] = PKT_HASH_TYPE_L3, + [IGC_RSS_TYPE_HASH_TCP_IPV6_EX] = PKT_HASH_TYPE_L4, + [IGC_RSS_TYPE_HASH_UDP_IPV4] = PKT_HASH_TYPE_L4, + [IGC_RSS_TYPE_HASH_UDP_IPV6] = PKT_HASH_TYPE_L4, + [IGC_RSS_TYPE_HASH_UDP_IPV6_EX] = PKT_HASH_TYPE_L4, + [10] = PKT_HASH_TYPE_NONE, /* RSS Type above 9 "Reserved" by HW */ + [11] = PKT_HASH_TYPE_NONE, /* keep array sized for SW bit-mask */ + [12] = PKT_HASH_TYPE_NONE, /* to handle future HW revisons */ + [13] = PKT_HASH_TYPE_NONE, + [14] = PKT_HASH_TYPE_NONE, + [15] = PKT_HASH_TYPE_NONE, +}; + static inline void igc_rx_hash(struct igc_ring *ring, union igc_adv_rx_desc *rx_desc, struct sk_buff *skb) { - if (ring->netdev->features & NETIF_F_RXHASH) - skb_set_hash(skb, - le32_to_cpu(rx_desc->wb.lower.hi_dword.rss), - PKT_HASH_TYPE_L3); + if (ring->netdev->features & NETIF_F_RXHASH) { + u32 rss_hash = le32_to_cpu(rx_desc->wb.lower.hi_dword.rss); + u32 rss_type = igc_rss_type(rx_desc); + + skb_set_hash(skb, rss_hash, igc_rss_type_table[rss_type]); + } } static void igc_rx_vlan(struct igc_ring *rx_ring, @@ -2724,15 +2748,15 @@ static void igc_xdp_xmit_zc(struct igc_ring *ring) struct netdev_queue *nq = txring_txq(ring); union igc_adv_tx_desc *tx_desc = NULL; int cpu = smp_processor_id(); - u16 ntu = ring->next_to_use; struct xdp_desc xdp_desc; - u16 budget; + u16 budget, ntu; if (!netif_carrier_ok(ring->netdev)) return; __netif_tx_lock(nq, cpu); + ntu = ring->next_to_use; budget = igc_desc_unused(ring); while (xsk_tx_peek_desc(pool, &xdp_desc) && budget--) { @@ -6525,6 +6549,7 @@ static int igc_probe(struct pci_dev *pdev, netdev->features |= NETIF_F_TSO; netdev->features |= NETIF_F_TSO6; netdev->features |= NETIF_F_TSO_ECN; + netdev->features |= NETIF_F_RXHASH; netdev->features |= NETIF_F_RXCSUM; netdev->features |= NETIF_F_HW_CSUM; netdev->features |= NETIF_F_SCTP_CRC; diff --git a/drivers/net/ethernet/intel/igc/igc_ptp.c b/drivers/net/ethernet/intel/igc/igc_ptp.c index 743c31659709..556750b61c98 100644 --- a/drivers/net/ethernet/intel/igc/igc_ptp.c +++ b/drivers/net/ethernet/intel/igc/igc_ptp.c @@ -357,16 +357,35 @@ static int igc_ptp_feature_enable_i225(struct ptp_clock_info *ptp, tsim &= ~IGC_TSICR_TT0; } if (on) { + struct timespec64 safe_start; int i = rq->perout.index; igc_pin_perout(igc, i, pin, use_freq); - igc->perout[i].start.tv_sec = rq->perout.start.sec; + igc_ptp_read(igc, &safe_start); + + /* PPS output start time is triggered by Target time(TT) + * register. Programming any past time value into TT + * register will cause PPS to never start. Need to make + * sure we program the TT register a time ahead in + * future. There isn't a stringent need to fire PPS out + * right away. Adding +2 seconds should take care of + * corner cases. Let's say if the SYSTIML is close to + * wrap up and the timer keeps ticking as we program the + * register, adding +2seconds is safe bet. + */ + safe_start.tv_sec += 2; + + if (rq->perout.start.sec < safe_start.tv_sec) + igc->perout[i].start.tv_sec = safe_start.tv_sec; + else + igc->perout[i].start.tv_sec = rq->perout.start.sec; igc->perout[i].start.tv_nsec = rq->perout.start.nsec; igc->perout[i].period.tv_sec = ts.tv_sec; igc->perout[i].period.tv_nsec = ts.tv_nsec; - wr32(trgttimh, rq->perout.start.sec); + wr32(trgttimh, (u32)igc->perout[i].start.tv_sec); /* For now, always select timer 0 as source. */ - wr32(trgttiml, rq->perout.start.nsec | IGC_TT_IO_TIMER_SEL_SYSTIM0); + wr32(trgttiml, (u32)(igc->perout[i].start.tv_nsec | + IGC_TT_IO_TIMER_SEL_SYSTIM0)); if (use_freq) wr32(freqout, ns); tsauxc |= tsauxc_mask; @@ -608,6 +627,7 @@ static int igc_ptp_set_timestamp_mode(struct igc_adapter *adapter, return 0; } +/* Requires adapter->ptp_tx_lock held by caller. */ static void igc_ptp_tx_timeout(struct igc_adapter *adapter) { struct igc_hw *hw = &adapter->hw; @@ -615,7 +635,6 @@ static void igc_ptp_tx_timeout(struct igc_adapter *adapter) dev_kfree_skb_any(adapter->ptp_tx_skb); adapter->ptp_tx_skb = NULL; adapter->tx_hwtstamp_timeouts++; - clear_bit_unlock(__IGC_PTP_TX_IN_PROGRESS, &adapter->state); /* Clear the tx valid bit in TSYNCTXCTL register to enable interrupt. */ rd32(IGC_TXSTMPH); netdev_warn(adapter->netdev, "Tx timestamp timeout\n"); @@ -623,20 +642,20 @@ static void igc_ptp_tx_timeout(struct igc_adapter *adapter) void igc_ptp_tx_hang(struct igc_adapter *adapter) { - bool timeout = time_is_before_jiffies(adapter->ptp_tx_start + - IGC_PTP_TX_TIMEOUT); + unsigned long flags; - if (!test_bit(__IGC_PTP_TX_IN_PROGRESS, &adapter->state)) - return; + spin_lock_irqsave(&adapter->ptp_tx_lock, flags); - /* If we haven't received a timestamp within the timeout, it is - * reasonable to assume that it will never occur, so we can unlock the - * timestamp bit when this occurs. - */ - if (timeout) { - cancel_work_sync(&adapter->ptp_tx_work); - igc_ptp_tx_timeout(adapter); - } + if (!adapter->ptp_tx_skb) + goto unlock; + + if (time_is_after_jiffies(adapter->ptp_tx_start + IGC_PTP_TX_TIMEOUT)) + goto unlock; + + igc_ptp_tx_timeout(adapter); + +unlock: + spin_unlock_irqrestore(&adapter->ptp_tx_lock, flags); } /** @@ -646,6 +665,8 @@ void igc_ptp_tx_hang(struct igc_adapter *adapter) * If we were asked to do hardware stamping and such a time stamp is * available, then it must have been for this skb here because we only * allow only one such packet into the queue. + * + * Context: Expects adapter->ptp_tx_lock to be held by caller. */ static void igc_ptp_tx_hwtstamp(struct igc_adapter *adapter) { @@ -681,13 +702,7 @@ static void igc_ptp_tx_hwtstamp(struct igc_adapter *adapter) shhwtstamps.hwtstamp = ktime_add_ns(shhwtstamps.hwtstamp, adjust); - /* Clear the lock early before calling skb_tstamp_tx so that - * applications are not woken up before the lock bit is clear. We use - * a copy of the skb pointer to ensure other threads can't change it - * while we're notifying the stack. - */ adapter->ptp_tx_skb = NULL; - clear_bit_unlock(__IGC_PTP_TX_IN_PROGRESS, &adapter->state); /* Notify the stack and free the skb after we've unlocked */ skb_tstamp_tx(skb, &shhwtstamps); @@ -698,24 +713,33 @@ static void igc_ptp_tx_hwtstamp(struct igc_adapter *adapter) * igc_ptp_tx_work * @work: pointer to work struct * - * This work function polls the TSYNCTXCTL valid bit to determine when a - * timestamp has been taken for the current stored skb. + * This work function checks the TSYNCTXCTL valid bit to determine when + * a timestamp has been taken for the current stored skb. */ static void igc_ptp_tx_work(struct work_struct *work) { struct igc_adapter *adapter = container_of(work, struct igc_adapter, ptp_tx_work); struct igc_hw *hw = &adapter->hw; + unsigned long flags; u32 tsynctxctl; - if (!test_bit(__IGC_PTP_TX_IN_PROGRESS, &adapter->state)) - return; + spin_lock_irqsave(&adapter->ptp_tx_lock, flags); + + if (!adapter->ptp_tx_skb) + goto unlock; tsynctxctl = rd32(IGC_TSYNCTXCTL); - if (WARN_ON_ONCE(!(tsynctxctl & IGC_TSYNCTXCTL_TXTT_0))) - return; + tsynctxctl &= IGC_TSYNCTXCTL_TXTT_0; + if (!tsynctxctl) { + WARN_ONCE(1, "Received a TSTAMP interrupt but no TSTAMP is ready.\n"); + goto unlock; + } igc_ptp_tx_hwtstamp(adapter); + +unlock: + spin_unlock_irqrestore(&adapter->ptp_tx_lock, flags); } /** @@ -964,6 +988,7 @@ void igc_ptp_init(struct igc_adapter *adapter) return; } + spin_lock_init(&adapter->ptp_tx_lock); spin_lock_init(&adapter->tmreg_lock); INIT_WORK(&adapter->ptp_tx_work, igc_ptp_tx_work); @@ -1028,7 +1053,6 @@ void igc_ptp_suspend(struct igc_adapter *adapter) cancel_work_sync(&adapter->ptp_tx_work); dev_kfree_skb_any(adapter->ptp_tx_skb); adapter->ptp_tx_skb = NULL; - clear_bit_unlock(__IGC_PTP_TX_IN_PROGRESS, &adapter->state); if (pci_device_is_present(adapter->pdev)) { igc_ptp_time_save(adapter); diff --git a/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c b/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c index 0e7ff15af968..3a05e458ded2 100644 --- a/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c +++ b/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c @@ -2541,7 +2541,7 @@ void ixgbevf_reset(struct ixgbevf_adapter *adapter) } if (is_valid_ether_addr(adapter->hw.mac.addr)) { - ether_addr_copy(netdev->dev_addr, adapter->hw.mac.addr); + eth_hw_addr_set(netdev, adapter->hw.mac.addr); ether_addr_copy(netdev->perm_addr, adapter->hw.mac.addr); } @@ -3055,7 +3055,7 @@ static int ixgbevf_sw_init(struct ixgbevf_adapter *adapter) else if (is_zero_ether_addr(adapter->hw.mac.addr)) dev_info(&pdev->dev, "MAC address not assigned by administrator.\n"); - ether_addr_copy(netdev->dev_addr, hw->mac.addr); + eth_hw_addr_set(netdev, hw->mac.addr); } if (!is_valid_ether_addr(netdev->dev_addr)) { @@ -4232,7 +4232,7 @@ static int ixgbevf_set_mac(struct net_device *netdev, void *p) ether_addr_copy(hw->mac.addr, addr->sa_data); ether_addr_copy(hw->mac.perm_addr, addr->sa_data); - ether_addr_copy(netdev->dev_addr, addr->sa_data); + eth_hw_addr_set(netdev, addr->sa_data); return 0; } diff --git a/drivers/net/ethernet/korina.c b/drivers/net/ethernet/korina.c index 3e9f324f1061..df9a8eefa007 100644 --- a/drivers/net/ethernet/korina.c +++ b/drivers/net/ethernet/korina.c @@ -1297,8 +1297,8 @@ static int korina_probe(struct platform_device *pdev) lp = netdev_priv(dev); if (mac_addr) - ether_addr_copy(dev->dev_addr, mac_addr); - else if (of_get_mac_address(pdev->dev.of_node, dev->dev_addr) < 0) + eth_hw_addr_set(dev, mac_addr); + else if (of_get_ethdev_address(pdev->dev.of_node, dev) < 0) eth_hw_addr_random(dev); clk = devm_clk_get_optional(&pdev->dev, "mdioclk"); diff --git a/drivers/net/ethernet/lantiq_xrx200.c b/drivers/net/ethernet/lantiq_xrx200.c index b02f796b5422..fa0ef1852fb7 100644 --- a/drivers/net/ethernet/lantiq_xrx200.c +++ b/drivers/net/ethernet/lantiq_xrx200.c @@ -474,7 +474,7 @@ static int xrx200_probe(struct platform_device *pdev) return PTR_ERR(priv->clk); } - err = of_get_mac_address(np, net_dev->dev_addr); + err = of_get_ethdev_address(np, net_dev); if (err) eth_hw_addr_random(net_dev); diff --git a/drivers/net/ethernet/litex/litex_liteeth.c b/drivers/net/ethernet/litex/litex_liteeth.c index 5bb1cc8a2ce1..24ed6e180c75 100644 --- a/drivers/net/ethernet/litex/litex_liteeth.c +++ b/drivers/net/ethernet/litex/litex_liteeth.c @@ -266,7 +266,7 @@ static int liteeth_probe(struct platform_device *pdev) priv->tx_base = buf_base + priv->num_rx_slots * priv->slot_size; priv->tx_slot = 0; - err = of_get_mac_address(pdev->dev.of_node, netdev->dev_addr); + err = of_get_ethdev_address(pdev->dev.of_node, netdev); if (err) eth_hw_addr_random(netdev); diff --git a/drivers/net/ethernet/marvell/mvneta.c b/drivers/net/ethernet/marvell/mvneta.c index 5c431a369762..5fa81322a44b 100644 --- a/drivers/net/ethernet/marvell/mvneta.c +++ b/drivers/net/ethernet/marvell/mvneta.c @@ -1474,7 +1474,7 @@ static void mvneta_defaults_set(struct mvneta_port *pp) */ if (txq_number == 1) txq_map = (cpu == pp->rxq_def) ? - MVNETA_CPU_TXQ_ACCESS(1) : 0; + MVNETA_CPU_TXQ_ACCESS(0) : 0; } else { txq_map = MVNETA_CPU_TXQ_ACCESS_ALL_MASK; @@ -4185,7 +4185,7 @@ static void mvneta_percpu_elect(struct mvneta_port *pp) */ if (txq_number == 1) txq_map = (cpu == elected_cpu) ? - MVNETA_CPU_TXQ_ACCESS(1) : 0; + MVNETA_CPU_TXQ_ACCESS(0) : 0; else txq_map = mvreg_read(pp, MVNETA_CPU_MAP(cpu)) & MVNETA_CPU_TXQ_ACCESS_ALL_MASK; @@ -5242,7 +5242,7 @@ static int mvneta_probe(struct platform_device *pdev) goto err_free_ports; } - err = of_get_mac_address(dn, dev->dev_addr); + err = of_get_ethdev_address(dn, dev); if (!err) { mac_from = "device tree"; } else { diff --git a/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c b/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c index 524913c28f3b..ddd4ed34b0f2 100644 --- a/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c +++ b/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c @@ -6087,7 +6087,7 @@ static void mvpp2_port_copy_mac_addr(struct net_device *dev, struct mvpp2 *priv, if (fwnode_get_mac_address(fwnode, fw_mac_addr, ETH_ALEN)) { *mac_from = "firmware node"; - ether_addr_copy(dev->dev_addr, fw_mac_addr); + eth_hw_addr_set(dev, fw_mac_addr); return; } @@ -6095,7 +6095,7 @@ static void mvpp2_port_copy_mac_addr(struct net_device *dev, struct mvpp2 *priv, mvpp21_get_mac_address(port, hw_mac_addr); if (is_valid_ether_addr(hw_mac_addr)) { *mac_from = "hardware"; - ether_addr_copy(dev->dev_addr, hw_mac_addr); + eth_hw_addr_set(dev, hw_mac_addr); return; } } diff --git a/drivers/net/ethernet/marvell/mvpp2/mvpp2_prs.c b/drivers/net/ethernet/marvell/mvpp2/mvpp2_prs.c index a8188b972ccb..9af22f497a40 100644 --- a/drivers/net/ethernet/marvell/mvpp2/mvpp2_prs.c +++ b/drivers/net/ethernet/marvell/mvpp2/mvpp2_prs.c @@ -2333,7 +2333,7 @@ int mvpp2_prs_update_mac_da(struct net_device *dev, const u8 *da) return err; /* Set addr in the device */ - ether_addr_copy(dev->dev_addr, da); + eth_hw_addr_set(dev, da); return 0; } diff --git a/drivers/net/ethernet/marvell/octeontx2/af/cgx.c b/drivers/net/ethernet/marvell/octeontx2/af/cgx.c index fd0a31bf94fe..8ac95cb7bbb7 100644 --- a/drivers/net/ethernet/marvell/octeontx2/af/cgx.c +++ b/drivers/net/ethernet/marvell/octeontx2/af/cgx.c @@ -167,6 +167,9 @@ void cgx_lmac_write(int cgx_id, int lmac_id, u64 offset, u64 val) { struct cgx *cgx_dev = cgx_get_pdata(cgx_id); + /* Software must not access disabled LMAC registers */ + if (!is_lmac_valid(cgx_dev, lmac_id)) + return; cgx_write(cgx_dev, lmac_id, offset, val); } @@ -174,6 +177,10 @@ u64 cgx_lmac_read(int cgx_id, int lmac_id, u64 offset) { struct cgx *cgx_dev = cgx_get_pdata(cgx_id); + /* Software must not access disabled LMAC registers */ + if (!is_lmac_valid(cgx_dev, lmac_id)) + return 0; + return cgx_read(cgx_dev, lmac_id, offset); } diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu.h b/drivers/net/ethernet/marvell/octeontx2/af/rvu.h index fed49d6a178d..9d517e6dac2f 100644 --- a/drivers/net/ethernet/marvell/octeontx2/af/rvu.h +++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu.h @@ -23,6 +23,7 @@ #define PCI_DEVID_OCTEONTX2_LBK 0xA061 /* Subsystem Device ID */ +#define PCI_SUBSYS_DEVID_98XX 0xB100 #define PCI_SUBSYS_DEVID_96XX 0xB200 #define PCI_SUBSYS_DEVID_CN10K_A 0xB900 @@ -614,6 +615,16 @@ static inline u16 rvu_nix_chan_cpt(struct rvu *rvu, u8 chan) return rvu->hw->cpt_chan_base + chan; } +static inline bool is_rvu_supports_nix1(struct rvu *rvu) +{ + struct pci_dev *pdev = rvu->pdev; + + if (pdev->subsystem_device == PCI_SUBSYS_DEVID_98XX) + return true; + + return false; +} + /* Function Prototypes * RVU */ diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu_cgx.c b/drivers/net/ethernet/marvell/octeontx2/af/rvu_cgx.c index 28ff67819566..f4c7bb6bf053 100644 --- a/drivers/net/ethernet/marvell/octeontx2/af/rvu_cgx.c +++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu_cgx.c @@ -111,7 +111,7 @@ static void rvu_map_cgx_nix_block(struct rvu *rvu, int pf, p2x = cgx_lmac_get_p2x(cgx_id, lmac_id); /* Firmware sets P2X_SELECT as either NIX0 or NIX1 */ pfvf->nix_blkaddr = BLKADDR_NIX0; - if (p2x == CMR_P2X_SEL_NIX1) + if (is_rvu_supports_nix1(rvu) && p2x == CMR_P2X_SEL_NIX1) pfvf->nix_blkaddr = BLKADDR_NIX1; } @@ -724,7 +724,7 @@ static int rvu_cgx_ptp_rx_cfg(struct rvu *rvu, u16 pcifunc, bool enable) cgxd = rvu_cgx_pdata(cgx_id, rvu); mac_ops = get_mac_ops(cgxd); - mac_ops->mac_enadis_ptp_config(cgxd, lmac_id, true); + mac_ops->mac_enadis_ptp_config(cgxd, lmac_id, enable); /* If PTP is enabled then inform NPC that packets to be * parsed by this PF will have their data shifted by 8 bytes * and if PTP is disabled then no shift is required diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.c b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.c index 2e225309de9c..b743646993ca 100644 --- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.c +++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.c @@ -188,7 +188,7 @@ static int otx2_hw_get_mac_addr(struct otx2_nic *pfvf, return PTR_ERR(msghdr); } rsp = (struct nix_get_mac_addr_rsp *)msghdr; - ether_addr_copy(netdev->dev_addr, rsp->mac_addr); + eth_hw_addr_set(netdev, rsp->mac_addr); mutex_unlock(&pfvf->mbox.lock); return 0; diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_flows.c b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_flows.c index 63889449b8f6..483f660cebc4 100644 --- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_flows.c +++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_flows.c @@ -827,6 +827,14 @@ static int otx2_prepare_flow_request(struct ethtool_rx_flow_spec *fsp, return -EINVAL; vlan_etype = be16_to_cpu(fsp->h_ext.vlan_etype); + + /* Drop rule with vlan_etype == 802.1Q + * and vlan_id == 0 is not supported + */ + if (vlan_etype == ETH_P_8021Q && !fsp->m_ext.vlan_tci && + fsp->ring_cookie == RX_CLS_FLOW_DISC) + return -EINVAL; + /* Only ETH_P_8021Q and ETH_P_802AD types supported */ if (vlan_etype != ETH_P_8021Q && vlan_etype != ETH_P_8021AD) diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c index a987ae9d6a28..8fc4ecc4f714 100644 --- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c +++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c @@ -1430,8 +1430,9 @@ static int otx2_init_hw_resources(struct otx2_nic *pf) if (err) goto err_free_npa_lf; - /* Enable backpressure */ - otx2_nix_config_bp(pf, true); + /* Enable backpressure for CGX mapped PF/VFs */ + if (!is_otx2_lbkvf(pf->pdev)) + otx2_nix_config_bp(pf, true); /* Init Auras and pools used by NIX RQ, for free buffer ptrs */ err = otx2_rq_aura_pool_init(pf); diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_tc.c b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_tc.c index a42373e6f259..26231c59b024 100644 --- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_tc.c +++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_tc.c @@ -536,6 +536,21 @@ static int otx2_tc_prepare_flow(struct otx2_nic *nic, struct otx2_tc_flow *node, return -EOPNOTSUPP; } + if (!match.mask->vlan_id) { + struct flow_action_entry *act; + int i; + + flow_action_for_each(i, act, &rule->action) { + if (act->id == FLOW_ACTION_DROP) { + netdev_err(nic->netdev, + "vlan tpid 0x%x with vlan_id %d is not supported for DROP rule.\n", + ntohs(match.key->vlan_tpid), + match.key->vlan_id); + return -EOPNOTSUPP; + } + } + } + if (match.mask->vlan_id || match.mask->vlan_dei || match.mask->vlan_priority) { diff --git a/drivers/net/ethernet/marvell/prestera/prestera_main.c b/drivers/net/ethernet/marvell/prestera/prestera_main.c index 656c68cfd7ec..912759ea6ec5 100644 --- a/drivers/net/ethernet/marvell/prestera/prestera_main.c +++ b/drivers/net/ethernet/marvell/prestera/prestera_main.c @@ -141,7 +141,7 @@ static int prestera_port_set_mac_address(struct net_device *dev, void *p) if (err) return err; - ether_addr_copy(dev->dev_addr, addr->sa_data); + eth_hw_addr_set(dev, addr->sa_data); return 0; } diff --git a/drivers/net/ethernet/marvell/pxa168_eth.c b/drivers/net/ethernet/marvell/pxa168_eth.c index fab53c9b8380..8ebd13f089db 100644 --- a/drivers/net/ethernet/marvell/pxa168_eth.c +++ b/drivers/net/ethernet/marvell/pxa168_eth.c @@ -1434,7 +1434,7 @@ static int pxa168_eth_probe(struct platform_device *pdev) INIT_WORK(&pep->tx_timeout_task, pxa168_eth_tx_timeout_task); - err = of_get_mac_address(pdev->dev.of_node, dev->dev_addr); + err = of_get_ethdev_address(pdev->dev.of_node, dev); if (err) { /* try reading the mac address, if set by the bootloader */ pxa168_eth_get_mac_address(dev, dev->dev_addr); diff --git a/drivers/net/ethernet/marvell/sky2.c b/drivers/net/ethernet/marvell/sky2.c index e9fc74e54b22..ac0dbf1b9743 100644 --- a/drivers/net/ethernet/marvell/sky2.c +++ b/drivers/net/ethernet/marvell/sky2.c @@ -4802,7 +4802,7 @@ static struct net_device *sky2_init_netdev(struct sky2_hw *hw, unsigned port, * 1) from device tree data * 2) from internal registers set by bootloader */ - ret = of_get_mac_address(hw->pdev->dev.of_node, dev->dev_addr); + ret = of_get_ethdev_address(hw->pdev->dev.of_node, dev); if (ret) memcpy_fromio(dev->dev_addr, hw->regs + B2_MAC_1 + port * 8, ETH_ALEN); diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c b/drivers/net/ethernet/mediatek/mtk_eth_soc.c index bb1acdb0c62b..50ee9d3d4c84 100644 --- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c +++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c @@ -2612,23 +2612,6 @@ static int mtk_hw_deinit(struct mtk_eth *eth) return 0; } -static int __init mtk_init(struct net_device *dev) -{ - struct mtk_mac *mac = netdev_priv(dev); - struct mtk_eth *eth = mac->hw; - int ret; - - ret = of_get_mac_address(mac->of_node, dev->dev_addr); - if (ret) { - /* If the mac address is invalid, use random mac address */ - eth_hw_addr_random(dev); - dev_err(eth->dev, "generated random MAC address %pM\n", - dev->dev_addr); - } - - return 0; -} - static void mtk_uninit(struct net_device *dev) { struct mtk_mac *mac = netdev_priv(dev); @@ -2956,7 +2939,6 @@ static const struct ethtool_ops mtk_ethtool_ops = { }; static const struct net_device_ops mtk_netdev_ops = { - .ndo_init = mtk_init, .ndo_uninit = mtk_uninit, .ndo_open = mtk_open, .ndo_stop = mtk_stop, @@ -3010,6 +2992,17 @@ static int mtk_add_mac(struct mtk_eth *eth, struct device_node *np) mac->hw = eth; mac->of_node = np; + err = of_get_ethdev_address(mac->of_node, eth->netdev[id]); + if (err == -EPROBE_DEFER) + return err; + + if (err) { + /* If the mac address is invalid, use random mac address */ + eth_hw_addr_random(eth->netdev[id]); + dev_err(eth->dev, "generated random MAC address %pM\n", + eth->netdev[id]->dev_addr); + } + memset(mac->hwlro_ip, 0, sizeof(mac->hwlro_ip)); mac->hwlro_ip_cnt = 0; diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/ptp.c b/drivers/net/ethernet/mellanox/mlx5/core/en/ptp.c index ee95cc3a0378..ce941e6091c5 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en/ptp.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en/ptp.c @@ -676,8 +676,10 @@ int mlx5e_ptp_open(struct mlx5e_priv *priv, struct mlx5e_params *params, c = kvzalloc_node(sizeof(*c), GFP_KERNEL, dev_to_node(mlx5_core_dma_dev(mdev))); cparams = kvzalloc(sizeof(*cparams), GFP_KERNEL); - if (!c || !cparams) - return -ENOMEM; + if (!c || !cparams) { + err = -ENOMEM; + goto err_free; + } c->priv = priv; c->mdev = priv->mdev; diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/fs_tcp.c b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/fs_tcp.c index 4c4ee524176c..153c16e3ff3b 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/fs_tcp.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/fs_tcp.c @@ -194,6 +194,7 @@ static int accel_fs_tcp_create_groups(struct mlx5e_flow_table *ft, in = kvzalloc(inlen, GFP_KERNEL); if (!in || !ft->g) { kfree(ft->g); + ft->g = NULL; kvfree(in); return -ENOMEM; } diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c index 82849bed27f4..fdc4a5a80da4 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c @@ -3224,7 +3224,7 @@ static int mlx5e_set_mac(struct net_device *netdev, void *addr) return -EADDRNOTAVAIL; netif_addr_lock_bh(netdev); - ether_addr_copy(netdev->dev_addr, saddr->sa_data); + eth_hw_addr_set(netdev, saddr->sa_data); netif_addr_unlock_bh(netdev); mlx5e_nic_set_rx_mode(priv); diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c index 5cef556223e2..d123d9b4adf5 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c @@ -1282,7 +1282,8 @@ static void remove_unready_flow(struct mlx5e_tc_flow *flow) uplink_priv = &rpriv->uplink_priv; mutex_lock(&uplink_priv->unready_flows_lock); - unready_flow_del(flow); + if (flow_flag_test(flow, NOT_READY)) + unready_flow_del(flow); mutex_unlock(&uplink_priv->unready_flows_lock); } @@ -1525,8 +1526,7 @@ static void mlx5e_tc_del_fdb_flow(struct mlx5e_priv *priv, esw_attr = attr->esw_attr; mlx5e_put_flow_tunnel_id(flow); - if (flow_flag_test(flow, NOT_READY)) - remove_unready_flow(flow); + remove_unready_flow(flow); if (mlx5e_is_offloaded_flow(flow)) { if (flow_flag_test(flow, SLOW)) diff --git a/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_main.c b/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_main.c index 6704f5c1aa32..b990782c1eb1 100644 --- a/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_main.c +++ b/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_main.c @@ -75,7 +75,7 @@ static void mlxbf_gige_initial_mac(struct mlxbf_gige *priv) u64_to_ether_addr(local_mac, mac); if (is_valid_ether_addr(mac)) { - ether_addr_copy(priv->netdev->dev_addr, mac); + eth_hw_addr_set(priv->netdev, mac); } else { /* Provide a random MAC if for some reason the device has * not been configured with a valid MAC address already. diff --git a/drivers/net/ethernet/micrel/ks8851_common.c b/drivers/net/ethernet/micrel/ks8851_common.c index a6db1a8156e1..2c80dba2606c 100644 --- a/drivers/net/ethernet/micrel/ks8851_common.c +++ b/drivers/net/ethernet/micrel/ks8851_common.c @@ -195,7 +195,7 @@ static void ks8851_init_mac(struct ks8851_net *ks, struct device_node *np) struct net_device *dev = ks->netdev; int ret; - ret = of_get_mac_address(np, dev->dev_addr); + ret = of_get_ethdev_address(np, dev); if (!ret) { ks8851_write_mac_addr(dev); return; diff --git a/drivers/net/ethernet/microchip/enc28j60.c b/drivers/net/ethernet/microchip/enc28j60.c index 09cdc2f2e7ff..bf77e8adffbf 100644 --- a/drivers/net/ethernet/microchip/enc28j60.c +++ b/drivers/net/ethernet/microchip/enc28j60.c @@ -517,7 +517,7 @@ static int enc28j60_set_mac_address(struct net_device *dev, void *addr) if (!is_valid_ether_addr(address->sa_data)) return -EADDRNOTAVAIL; - ether_addr_copy(dev->dev_addr, address->sa_data); + eth_hw_addr_set(dev, address->sa_data); return enc28j60_set_hw_macaddr(dev); } @@ -1573,7 +1573,7 @@ static int enc28j60_probe(struct spi_device *spi) } if (device_get_mac_address(&spi->dev, macaddr, sizeof(macaddr))) - ether_addr_copy(dev->dev_addr, macaddr); + eth_hw_addr_set(dev, macaddr); else eth_hw_addr_random(dev); enc28j60_set_hw_macaddr(dev); diff --git a/drivers/net/ethernet/microchip/lan743x_main.c b/drivers/net/ethernet/microchip/lan743x_main.c index d64ce65a3c17..a3392c74372a 100644 --- a/drivers/net/ethernet/microchip/lan743x_main.c +++ b/drivers/net/ethernet/microchip/lan743x_main.c @@ -83,6 +83,18 @@ static int lan743x_csr_light_reset(struct lan743x_adapter *adapter) !(data & HW_CFG_LRST_), 100000, 10000000); } +static int lan743x_csr_wait_for_bit_atomic(struct lan743x_adapter *adapter, + int offset, u32 bit_mask, + int target_value, int udelay_min, + int udelay_max, int count) +{ + u32 data; + + return readx_poll_timeout_atomic(LAN743X_CSR_READ_OP, offset, data, + target_value == !!(data & bit_mask), + udelay_max, udelay_min * count); +} + static int lan743x_csr_wait_for_bit(struct lan743x_adapter *adapter, int offset, u32 bit_mask, int target_value, int usleep_min, @@ -671,8 +683,8 @@ static int lan743x_dp_write(struct lan743x_adapter *adapter, u32 dp_sel; int i; - if (lan743x_csr_wait_for_bit(adapter, DP_SEL, DP_SEL_DPRDY_, - 1, 40, 100, 100)) + if (lan743x_csr_wait_for_bit_atomic(adapter, DP_SEL, DP_SEL_DPRDY_, + 1, 40, 100, 100)) return -EIO; dp_sel = lan743x_csr_read(adapter, DP_SEL); dp_sel &= ~DP_SEL_MASK_; @@ -683,8 +695,9 @@ static int lan743x_dp_write(struct lan743x_adapter *adapter, lan743x_csr_write(adapter, DP_ADDR, addr + i); lan743x_csr_write(adapter, DP_DATA_0, buf[i]); lan743x_csr_write(adapter, DP_CMD, DP_CMD_WRITE_); - if (lan743x_csr_wait_for_bit(adapter, DP_SEL, DP_SEL_DPRDY_, - 1, 40, 100, 100)) + if (lan743x_csr_wait_for_bit_atomic(adapter, DP_SEL, + DP_SEL_DPRDY_, + 1, 40, 100, 100)) return -EIO; } @@ -816,7 +829,7 @@ static int lan743x_mac_init(struct lan743x_adapter *adapter) eth_random_addr(adapter->mac_address); } lan743x_mac_set_address(adapter, adapter->mac_address); - ether_addr_copy(netdev->dev_addr, adapter->mac_address); + eth_hw_addr_set(netdev, adapter->mac_address); return 0; } @@ -2664,7 +2677,7 @@ static int lan743x_netdev_set_mac_address(struct net_device *netdev, ret = eth_prepare_mac_addr_change(netdev, sock_addr); if (ret) return ret; - ether_addr_copy(netdev->dev_addr, sock_addr->sa_data); + eth_hw_addr_set(netdev, sock_addr->sa_data); lan743x_mac_set_address(adapter, sock_addr->sa_data); lan743x_rfe_update_mac_address(adapter); return 0; diff --git a/drivers/net/ethernet/microchip/sparx5/sparx5_netdev.c b/drivers/net/ethernet/microchip/sparx5/sparx5_netdev.c index 5c7b21ce64ed..a84038db8e1a 100644 --- a/drivers/net/ethernet/microchip/sparx5/sparx5_netdev.c +++ b/drivers/net/ethernet/microchip/sparx5/sparx5_netdev.c @@ -172,7 +172,7 @@ static int sparx5_set_mac_address(struct net_device *dev, void *p) sparx5_mact_learn(sparx5, PGID_CPU, addr->sa_data, port->pvid); /* Record the address */ - ether_addr_copy(dev->dev_addr, addr->sa_data); + eth_hw_addr_set(dev, addr->sa_data); return 0; } diff --git a/drivers/net/ethernet/microsoft/mana/mana_en.c b/drivers/net/ethernet/microsoft/mana/mana_en.c index 4b8c23993217..6224b7c21e0a 100644 --- a/drivers/net/ethernet/microsoft/mana/mana_en.c +++ b/drivers/net/ethernet/microsoft/mana/mana_en.c @@ -1619,7 +1619,7 @@ static int mana_init_port(struct net_device *ndev) if (apc->num_queues > apc->max_queues) apc->num_queues = apc->max_queues; - ether_addr_copy(ndev->dev_addr, apc->mac_addr); + eth_hw_addr_set(ndev, apc->mac_addr); return 0; diff --git a/drivers/net/ethernet/mscc/ocelot_net.c b/drivers/net/ethernet/mscc/ocelot_net.c index c08c56e07b1d..da8a4e01d4be 100644 --- a/drivers/net/ethernet/mscc/ocelot_net.c +++ b/drivers/net/ethernet/mscc/ocelot_net.c @@ -606,7 +606,7 @@ static int ocelot_port_set_mac_address(struct net_device *dev, void *p) /* Then forget the previous one. */ ocelot_mact_forget(ocelot, dev->dev_addr, ocelot_port->pvid_vlan.vid); - ether_addr_copy(dev->dev_addr, addr->sa_data); + eth_hw_addr_set(dev, addr->sa_data); return 0; } diff --git a/drivers/net/ethernet/netronome/nfp/abm/main.c b/drivers/net/ethernet/netronome/nfp/abm/main.c index 605a1617b195..5d3df28c648f 100644 --- a/drivers/net/ethernet/netronome/nfp/abm/main.c +++ b/drivers/net/ethernet/netronome/nfp/abm/main.c @@ -305,7 +305,7 @@ nfp_abm_vnic_set_mac(struct nfp_pf *pf, struct nfp_abm *abm, struct nfp_net *nn, return; } - ether_addr_copy(nn->dp.netdev->dev_addr, mac_addr); + eth_hw_addr_set(nn->dp.netdev, mac_addr); ether_addr_copy(nn->dp.netdev->perm_addr, mac_addr); } diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net_main.c b/drivers/net/ethernet/netronome/nfp/nfp_net_main.c index d10a93801344..74c4bf4d397d 100644 --- a/drivers/net/ethernet/netronome/nfp/nfp_net_main.c +++ b/drivers/net/ethernet/netronome/nfp/nfp_net_main.c @@ -55,7 +55,7 @@ nfp_net_get_mac_addr(struct nfp_pf *pf, struct net_device *netdev, return; } - ether_addr_copy(netdev->dev_addr, eth_port->mac_addr); + eth_hw_addr_set(netdev, eth_port->mac_addr); ether_addr_copy(netdev->perm_addr, eth_port->mac_addr); } diff --git a/drivers/net/ethernet/netronome/nfp/nfp_netvf_main.c b/drivers/net/ethernet/netronome/nfp/nfp_netvf_main.c index c0e2f4394aef..87f2268b16d6 100644 --- a/drivers/net/ethernet/netronome/nfp/nfp_netvf_main.c +++ b/drivers/net/ethernet/netronome/nfp/nfp_netvf_main.c @@ -58,7 +58,7 @@ static void nfp_netvf_get_mac_addr(struct nfp_net *nn) return; } - ether_addr_copy(nn->dp.netdev->dev_addr, mac_addr); + eth_hw_addr_set(nn->dp.netdev, mac_addr); ether_addr_copy(nn->dp.netdev->perm_addr, mac_addr); } diff --git a/drivers/net/ethernet/ni/nixge.c b/drivers/net/ethernet/ni/nixge.c index 5d0cecf80b38..cb63c037753d 100644 --- a/drivers/net/ethernet/ni/nixge.c +++ b/drivers/net/ethernet/ni/nixge.c @@ -1211,7 +1211,7 @@ static void *nixge_get_nvmem_address(struct device *dev) cell = nvmem_cell_get(dev, "address"); if (IS_ERR(cell)) - return NULL; + return cell; mac = nvmem_cell_read(cell, &cell_size); nvmem_cell_put(cell); @@ -1284,8 +1284,8 @@ static int nixge_probe(struct platform_device *pdev) ndev->max_mtu = NIXGE_JUMBO_MTU; mac_addr = nixge_get_nvmem_address(&pdev->dev); - if (mac_addr && is_valid_ether_addr(mac_addr)) { - ether_addr_copy(ndev->dev_addr, mac_addr); + if (!IS_ERR(mac_addr) && is_valid_ether_addr(mac_addr)) { + eth_hw_addr_set(ndev, mac_addr); kfree(mac_addr); } else { eth_hw_addr_random(ndev); diff --git a/drivers/net/ethernet/nxp/lpc_eth.c b/drivers/net/ethernet/nxp/lpc_eth.c index 919140522885..b42b65fb034e 100644 --- a/drivers/net/ethernet/nxp/lpc_eth.c +++ b/drivers/net/ethernet/nxp/lpc_eth.c @@ -1349,7 +1349,7 @@ static int lpc_eth_drv_probe(struct platform_device *pdev) __lpc_get_mac(pldat, ndev->dev_addr); if (!is_valid_ether_addr(ndev->dev_addr)) { - of_get_mac_address(np, ndev->dev_addr); + of_get_ethdev_address(np, ndev); } if (!is_valid_ether_addr(ndev->dev_addr)) eth_hw_addr_random(ndev); diff --git a/drivers/net/ethernet/pensando/ionic/ionic_lif.c b/drivers/net/ethernet/pensando/ionic/ionic_lif.c index 6fbd2a51d66c..2cc126d37835 100644 --- a/drivers/net/ethernet/pensando/ionic/ionic_lif.c +++ b/drivers/net/ethernet/pensando/ionic/ionic_lif.c @@ -451,11 +451,6 @@ static void ionic_qcqs_free(struct ionic_lif *lif) static void ionic_link_qcq_interrupts(struct ionic_qcq *src_qcq, struct ionic_qcq *n_qcq) { - if (WARN_ON(n_qcq->flags & IONIC_QCQ_F_INTR)) { - ionic_intr_free(n_qcq->cq.lif->ionic, n_qcq->intr.index); - n_qcq->flags &= ~IONIC_QCQ_F_INTR; - } - n_qcq->intr.vector = src_qcq->intr.vector; n_qcq->intr.index = src_qcq->intr.index; } diff --git a/drivers/net/ethernet/qlogic/qede/qede_filter.c b/drivers/net/ethernet/qlogic/qede/qede_filter.c index f99b085b56a5..03c51dd37e1f 100644 --- a/drivers/net/ethernet/qlogic/qede/qede_filter.c +++ b/drivers/net/ethernet/qlogic/qede/qede_filter.c @@ -557,7 +557,7 @@ void qede_force_mac(void *dev, u8 *mac, bool forced) return; } - ether_addr_copy(edev->ndev->dev_addr, mac); + eth_hw_addr_set(edev->ndev, mac); __qede_unlock(edev); } @@ -1101,7 +1101,7 @@ int qede_set_mac_addr(struct net_device *ndev, void *p) goto out; } - ether_addr_copy(ndev->dev_addr, addr->sa_data); + eth_hw_addr_set(ndev, addr->sa_data); DP_INFO(edev, "Setting device MAC to %pM\n", addr->sa_data); if (edev->state != QEDE_STATE_OPEN) { diff --git a/drivers/net/ethernet/qlogic/qede/qede_main.c b/drivers/net/ethernet/qlogic/qede/qede_main.c index 41f0a3433c3a..6c22bfc16ee6 100644 --- a/drivers/net/ethernet/qlogic/qede/qede_main.c +++ b/drivers/net/ethernet/qlogic/qede/qede_main.c @@ -843,7 +843,7 @@ static void qede_init_ndev(struct qede_dev *edev) ndev->max_mtu = QEDE_MAX_JUMBO_PACKET_SIZE; /* Set network device HW mac */ - ether_addr_copy(edev->ndev->dev_addr, edev->dev_info.common.hw_mac); + eth_hw_addr_set(edev->ndev, edev->dev_info.common.hw_mac); ndev->mtu = edev->dev_info.common.mtu; } diff --git a/drivers/net/ethernet/qualcomm/emac/emac.c b/drivers/net/ethernet/qualcomm/emac/emac.c index bb7f3286824f..94090856cf3a 100644 --- a/drivers/net/ethernet/qualcomm/emac/emac.c +++ b/drivers/net/ethernet/qualcomm/emac/emac.c @@ -550,7 +550,7 @@ static int emac_probe_resources(struct platform_device *pdev, /* get mac address */ if (device_get_mac_address(&pdev->dev, maddr, ETH_ALEN)) - ether_addr_copy(netdev->dev_addr, maddr); + eth_hw_addr_set(netdev, maddr); else eth_hw_addr_random(netdev); diff --git a/drivers/net/ethernet/qualcomm/qca_spi.c b/drivers/net/ethernet/qualcomm/qca_spi.c index 2205bb437e68..a047bab1d7c7 100644 --- a/drivers/net/ethernet/qualcomm/qca_spi.c +++ b/drivers/net/ethernet/qualcomm/qca_spi.c @@ -967,7 +967,7 @@ qca_spi_probe(struct spi_device *spi) spi_set_drvdata(spi, qcaspi_devs); - ret = of_get_mac_address(spi->dev.of_node, qca->net_dev->dev_addr); + ret = of_get_ethdev_address(spi->dev.of_node, qca->net_dev); if (ret) { eth_hw_addr_random(qca->net_dev); dev_info(&spi->dev, "Using random MAC address: %pM\n", diff --git a/drivers/net/ethernet/qualcomm/qca_uart.c b/drivers/net/ethernet/qualcomm/qca_uart.c index ce3f7ce31adc..27c4f43176aa 100644 --- a/drivers/net/ethernet/qualcomm/qca_uart.c +++ b/drivers/net/ethernet/qualcomm/qca_uart.c @@ -347,7 +347,7 @@ static int qca_uart_probe(struct serdev_device *serdev) of_property_read_u32(serdev->dev.of_node, "current-speed", &speed); - ret = of_get_mac_address(serdev->dev.of_node, qca->net_dev->dev_addr); + ret = of_get_ethdev_address(serdev->dev.of_node, qca->net_dev); if (ret) { eth_hw_addr_random(qca->net_dev); dev_info(&serdev->dev, "Using random MAC address: %pM\n", diff --git a/drivers/net/ethernet/renesas/ravb_main.c b/drivers/net/ethernet/renesas/ravb_main.c index 12548eeef4f8..19733c9a7c25 100644 --- a/drivers/net/ethernet/renesas/ravb_main.c +++ b/drivers/net/ethernet/renesas/ravb_main.c @@ -114,7 +114,7 @@ static void ravb_read_mac_address(struct device_node *np, { int ret; - ret = of_get_mac_address(np, ndev->dev_addr); + ret = of_get_ethdev_address(np, ndev); if (ret) { u32 mahr = ravb_read(ndev, MAHR); u32 malr = ravb_read(ndev, MALR); @@ -1774,6 +1774,8 @@ static int ravb_close(struct net_device *ndev) of_phy_deregister_fixed_link(np); } + cancel_work_sync(&priv->work); + if (info->multi_irqs) { free_irq(priv->tx_irqs[RAVB_NC], ndev); free_irq(priv->rx_irqs[RAVB_NC], ndev); @@ -2382,14 +2384,14 @@ static int ravb_remove(struct platform_device *pdev) clk_disable_unprepare(priv->refclk); - dma_free_coherent(ndev->dev.parent, priv->desc_bat_size, priv->desc_bat, - priv->desc_bat_dma); /* Set reset mode */ ravb_write(ndev, CCC_OPC_RESET, CCC); unregister_netdev(ndev); netif_napi_del(&priv->napi[RAVB_NC]); netif_napi_del(&priv->napi[RAVB_BE]); ravb_mdio_release(priv); + dma_free_coherent(ndev->dev.parent, priv->desc_bat_size, priv->desc_bat, + priv->desc_bat_dma); pm_runtime_put_sync(&pdev->dev); pm_runtime_disable(&pdev->dev); reset_control_assert(priv->rstc); diff --git a/drivers/net/ethernet/samsung/sxgbe/sxgbe_platform.c b/drivers/net/ethernet/samsung/sxgbe/sxgbe_platform.c index 4639ed9438a3..926532466691 100644 --- a/drivers/net/ethernet/samsung/sxgbe/sxgbe_platform.c +++ b/drivers/net/ethernet/samsung/sxgbe/sxgbe_platform.c @@ -118,7 +118,7 @@ static int sxgbe_platform_probe(struct platform_device *pdev) } /* Get MAC address if available (DT) */ - of_get_mac_address(node, priv->dev->dev_addr); + of_get_ethdev_address(node, priv->dev); /* Get the TX/RX IRQ numbers */ for (i = 0, chan = 1; i < SXGBE_TX_QUEUES; i++) { diff --git a/drivers/net/ethernet/sfc/ef10.c b/drivers/net/ethernet/sfc/ef10.c index 302b97c2e617..b20dbda37c7e 100644 --- a/drivers/net/ethernet/sfc/ef10.c +++ b/drivers/net/ethernet/sfc/ef10.c @@ -1297,8 +1297,10 @@ static void efx_ef10_fini_nic(struct efx_nic *efx) { struct efx_ef10_nic_data *nic_data = efx->nic_data; + spin_lock_bh(&efx->stats_lock); kfree(nic_data->mc_stats); nic_data->mc_stats = NULL; + spin_unlock_bh(&efx->stats_lock); } static int efx_ef10_init_nic(struct efx_nic *efx) @@ -1852,9 +1854,14 @@ static size_t efx_ef10_update_stats_pf(struct efx_nic *efx, u64 *full_stats, efx_ef10_get_stat_mask(efx, mask); - efx_nic_copy_stats(efx, nic_data->mc_stats); - efx_nic_update_stats(efx_ef10_stat_desc, EF10_STAT_COUNT, - mask, stats, nic_data->mc_stats, false); + /* If NIC was fini'd (probably resetting), then we can't read + * updated stats right now. + */ + if (nic_data->mc_stats) { + efx_nic_copy_stats(efx, nic_data->mc_stats); + efx_nic_update_stats(efx_ef10_stat_desc, EF10_STAT_COUNT, + mask, stats, nic_data->mc_stats, false); + } /* Update derived statistics */ efx_nic_fix_nodesc_drop_stat(efx, diff --git a/drivers/net/ethernet/sfc/ef10_sriov.c b/drivers/net/ethernet/sfc/ef10_sriov.c index f488461a23d1..eeaecea77cb8 100644 --- a/drivers/net/ethernet/sfc/ef10_sriov.c +++ b/drivers/net/ethernet/sfc/ef10_sriov.c @@ -527,7 +527,7 @@ int efx_ef10_sriov_set_vf_mac(struct efx_nic *efx, int vf_i, u8 *mac) goto fail; if (vf->efx) - ether_addr_copy(vf->efx->net_dev->dev_addr, mac); + eth_hw_addr_set(vf->efx->net_dev, mac); } ether_addr_copy(vf->mac, mac); diff --git a/drivers/net/ethernet/sfc/efx.c b/drivers/net/ethernet/sfc/efx.c index 41eb6f9f5596..bc1f4350360b 100644 --- a/drivers/net/ethernet/sfc/efx.c +++ b/drivers/net/ethernet/sfc/efx.c @@ -128,7 +128,7 @@ static int efx_probe_port(struct efx_nic *efx) return rc; /* Initialise MAC address to permanent address */ - ether_addr_copy(efx->net_dev->dev_addr, efx->net_dev->perm_addr); + eth_hw_addr_set(efx->net_dev, efx->net_dev->perm_addr); return 0; } diff --git a/drivers/net/ethernet/sfc/efx_common.c b/drivers/net/ethernet/sfc/efx_common.c index 6038b7e3e823..7249ea594b31 100644 --- a/drivers/net/ethernet/sfc/efx_common.c +++ b/drivers/net/ethernet/sfc/efx_common.c @@ -181,11 +181,11 @@ int efx_set_mac_address(struct net_device *net_dev, void *data) /* save old address */ ether_addr_copy(old_addr, net_dev->dev_addr); - ether_addr_copy(net_dev->dev_addr, new_addr); + eth_hw_addr_set(net_dev, new_addr); if (efx->type->set_mac_address) { rc = efx->type->set_mac_address(efx); if (rc) { - ether_addr_copy(net_dev->dev_addr, old_addr); + eth_hw_addr_set(net_dev, old_addr); return rc; } } diff --git a/drivers/net/ethernet/sfc/falcon/efx.c b/drivers/net/ethernet/sfc/falcon/efx.c index 423bdf81200f..c68837a951f4 100644 --- a/drivers/net/ethernet/sfc/falcon/efx.c +++ b/drivers/net/ethernet/sfc/falcon/efx.c @@ -1044,7 +1044,7 @@ static int ef4_probe_port(struct ef4_nic *efx) return rc; /* Initialise MAC address to permanent address */ - ether_addr_copy(efx->net_dev->dev_addr, efx->net_dev->perm_addr); + eth_hw_addr_set(efx->net_dev, efx->net_dev->perm_addr); return 0; } @@ -2162,11 +2162,11 @@ static int ef4_set_mac_address(struct net_device *net_dev, void *data) /* save old address */ ether_addr_copy(old_addr, net_dev->dev_addr); - ether_addr_copy(net_dev->dev_addr, new_addr); + eth_hw_addr_set(net_dev, new_addr); if (efx->type->set_mac_address) { rc = efx->type->set_mac_address(efx); if (rc) { - ether_addr_copy(net_dev->dev_addr, old_addr); + eth_hw_addr_set(net_dev, old_addr); return rc; } } diff --git a/drivers/net/ethernet/socionext/netsec.c b/drivers/net/ethernet/socionext/netsec.c index f0451911ab8f..6b8013fb17c3 100644 --- a/drivers/net/ethernet/socionext/netsec.c +++ b/drivers/net/ethernet/socionext/netsec.c @@ -2041,7 +2041,7 @@ static int netsec_probe(struct platform_device *pdev) mac = device_get_mac_address(&pdev->dev, macbuf, sizeof(macbuf)); if (mac) - ether_addr_copy(ndev->dev_addr, mac); + eth_hw_addr_set(ndev, mac); if (priv->eeprom_base && (!mac || !is_valid_ether_addr(ndev->dev_addr))) { diff --git a/drivers/net/ethernet/socionext/sni_ave.c b/drivers/net/ethernet/socionext/sni_ave.c index 57dc9680ad50..8ff56e2c8774 100644 --- a/drivers/net/ethernet/socionext/sni_ave.c +++ b/drivers/net/ethernet/socionext/sni_ave.c @@ -1601,7 +1601,7 @@ static int ave_probe(struct platform_device *pdev) ndev->max_mtu = AVE_MAX_ETHFRAME - (ETH_HLEN + ETH_FCS_LEN); - ret = of_get_mac_address(np, ndev->dev_addr); + ret = of_get_ethdev_address(np, ndev); if (ret) { /* if the mac address is invalid, use random mac address */ eth_hw_addr_random(ndev); diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c index ab4932e81492..5159720ad773 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c @@ -7610,12 +7610,6 @@ int stmmac_dvr_remove(struct device *dev) netif_carrier_off(ndev); unregister_netdev(ndev); - /* Serdes power down needs to happen after VLAN filter - * is deleted that is triggered by unregister_netdev(). - */ - if (priv->plat->serdes_powerdown) - priv->plat->serdes_powerdown(ndev, priv->plat->bsp_priv); - #ifdef CONFIG_DEBUG_FS stmmac_exit_fs(ndev); #endif diff --git a/drivers/net/ethernet/ti/am65-cpsw-nuss.c b/drivers/net/ethernet/ti/am65-cpsw-nuss.c index 692c291d9a01..daf0779261f3 100644 --- a/drivers/net/ethernet/ti/am65-cpsw-nuss.c +++ b/drivers/net/ethernet/ti/am65-cpsw-nuss.c @@ -1981,7 +1981,7 @@ am65_cpsw_nuss_init_port_ndev(struct am65_cpsw_common *common, u32 port_idx) ndev_priv->msg_enable = AM65_CPSW_DEBUG; SET_NETDEV_DEV(port->ndev, dev); - ether_addr_copy(port->ndev->dev_addr, port->slave.mac_addr); + eth_hw_addr_set(port->ndev, port->slave.mac_addr); port->ndev->min_mtu = AM65_CPSW_MIN_PACKET_SIZE; port->ndev->max_mtu = AM65_CPSW_MAX_PACKET_SIZE; diff --git a/drivers/net/ethernet/ti/cpsw_ale.c b/drivers/net/ethernet/ti/cpsw_ale.c index 1ef0aaef5c61..8c59e34d8bca 100644 --- a/drivers/net/ethernet/ti/cpsw_ale.c +++ b/drivers/net/ethernet/ti/cpsw_ale.c @@ -104,23 +104,37 @@ struct cpsw_ale_dev_id { static inline int cpsw_ale_get_field(u32 *ale_entry, u32 start, u32 bits) { - int idx; + int idx, idx2; + u32 hi_val = 0; idx = start / 32; + idx2 = (start + bits - 1) / 32; + /* Check if bits to be fetched exceed a word */ + if (idx != idx2) { + idx2 = 2 - idx2; /* flip */ + hi_val = ale_entry[idx2] << ((idx2 * 32) - start); + } start -= idx * 32; idx = 2 - idx; /* flip */ - return (ale_entry[idx] >> start) & BITMASK(bits); + return (hi_val + (ale_entry[idx] >> start)) & BITMASK(bits); } static inline void cpsw_ale_set_field(u32 *ale_entry, u32 start, u32 bits, u32 value) { - int idx; + int idx, idx2; value &= BITMASK(bits); - idx = start / 32; + idx = start / 32; + idx2 = (start + bits - 1) / 32; + /* Check if bits to be set exceed a word */ + if (idx != idx2) { + idx2 = 2 - idx2; /* flip */ + ale_entry[idx2] &= ~(BITMASK(bits + start - (idx2 * 32))); + ale_entry[idx2] |= (value >> ((idx2 * 32) - start)); + } start -= idx * 32; - idx = 2 - idx; /* flip */ + idx = 2 - idx; /* flip */ ale_entry[idx] &= ~(BITMASK(bits) << start); ale_entry[idx] |= (value << start); } diff --git a/drivers/net/ethernet/ti/cpsw_new.c b/drivers/net/ethernet/ti/cpsw_new.c index 277c91d13570..0d921f6542d6 100644 --- a/drivers/net/ethernet/ti/cpsw_new.c +++ b/drivers/net/ethernet/ti/cpsw_new.c @@ -1000,7 +1000,7 @@ static int cpsw_ndo_set_mac_address(struct net_device *ndev, void *p) flags, vid); ether_addr_copy(priv->mac_addr, addr->sa_data); - ether_addr_copy(ndev->dev_addr, priv->mac_addr); + eth_hw_addr_set(ndev, priv->mac_addr); cpsw_set_slave_mac(&cpsw->slaves[slave_no], priv); pm_runtime_put(cpsw->dev); @@ -1404,7 +1404,7 @@ static int cpsw_create_ports(struct cpsw_common *cpsw) dev_info(cpsw->dev, "Random MACID = %pM\n", priv->mac_addr); } - ether_addr_copy(ndev->dev_addr, slave_data->mac_addr); + eth_hw_addr_set(ndev, slave_data->mac_addr); ether_addr_copy(priv->mac_addr, slave_data->mac_addr); cpsw->slaves[i].ndev = ndev; diff --git a/drivers/net/ethernet/ti/davinci_emac.c b/drivers/net/ethernet/ti/davinci_emac.c index d243ca5dfde0..fbd6bd80f51f 100644 --- a/drivers/net/ethernet/ti/davinci_emac.c +++ b/drivers/net/ethernet/ti/davinci_emac.c @@ -1911,7 +1911,7 @@ static int davinci_emac_probe(struct platform_device *pdev) rc = davinci_emac_try_get_mac(pdev, res_ctrl ? 0 : 1, priv->mac_addr); if (!rc) - ether_addr_copy(ndev->dev_addr, priv->mac_addr); + eth_hw_addr_set(ndev, priv->mac_addr); if (!is_valid_ether_addr(priv->mac_addr)) { /* Use random MAC if still none obtained. */ diff --git a/drivers/net/ethernet/ti/netcp_core.c b/drivers/net/ethernet/ti/netcp_core.c index 07bdeece1723..a6450055908d 100644 --- a/drivers/net/ethernet/ti/netcp_core.c +++ b/drivers/net/ethernet/ti/netcp_core.c @@ -2028,14 +2028,14 @@ static int netcp_create_interface(struct netcp_device *netcp_device, emac_arch_get_mac_addr(efuse_mac_addr, efuse, efuse_mac); if (is_valid_ether_addr(efuse_mac_addr)) - ether_addr_copy(ndev->dev_addr, efuse_mac_addr); + eth_hw_addr_set(ndev, efuse_mac_addr); else eth_random_addr(ndev->dev_addr); devm_iounmap(dev, efuse); devm_release_mem_region(dev, res.start, size); } else { - ret = of_get_mac_address(node_interface, ndev->dev_addr); + ret = of_get_ethdev_address(node_interface, ndev); if (ret) eth_random_addr(ndev->dev_addr); } diff --git a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c index fbbbcfe0e891..e7f6c29b8dd8 100644 --- a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c +++ b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c @@ -2075,6 +2075,11 @@ static int axienet_probe(struct platform_device *pdev) goto cleanup_clk; } + /* Reset core now that clocks are enabled, prior to accessing MDIO */ + ret = __axienet_device_reset(lp); + if (ret) + goto cleanup_clk; + /* Autodetect the need for 64-bit DMA pointers. * When the IP is configured for a bus width bigger than 32 bits, * writing the MSB registers is mandatory, even if they are all 0. @@ -2122,11 +2127,6 @@ static int axienet_probe(struct platform_device *pdev) lp->coalesce_count_rx = XAXIDMA_DFT_RX_THRESHOLD; lp->coalesce_count_tx = XAXIDMA_DFT_TX_THRESHOLD; - /* Reset core now that clocks are enabled, prior to accessing MDIO */ - ret = __axienet_device_reset(lp); - if (ret) - goto cleanup_clk; - ret = axienet_mdio_setup(lp); if (ret) dev_warn(&pdev->dev, diff --git a/drivers/net/ethernet/xilinx/xilinx_emaclite.c b/drivers/net/ethernet/xilinx/xilinx_emaclite.c index b1971c4d5313..093c75da38c4 100644 --- a/drivers/net/ethernet/xilinx/xilinx_emaclite.c +++ b/drivers/net/ethernet/xilinx/xilinx_emaclite.c @@ -1151,7 +1151,7 @@ static int xemaclite_of_probe(struct platform_device *ofdev) lp->tx_ping_pong = get_bool(ofdev, "xlnx,tx-ping-pong"); lp->rx_ping_pong = get_bool(ofdev, "xlnx,rx-ping-pong"); - rc = of_get_mac_address(ofdev->dev.of_node, ndev->dev_addr); + rc = of_get_ethdev_address(ofdev->dev.of_node, ndev); if (rc) { dev_warn(dev, "No MAC address found, using random\n"); eth_hw_addr_random(ndev); diff --git a/drivers/net/gtp.c b/drivers/net/gtp.c index 30e0a10595a1..a3878aef0ea4 100644 --- a/drivers/net/gtp.c +++ b/drivers/net/gtp.c @@ -298,7 +298,9 @@ static void __gtp_encap_destroy(struct sock *sk) gtp->sk1u = NULL; udp_sk(sk)->encap_type = 0; rcu_assign_sk_user_data(sk, NULL); + release_sock(sk); sock_put(sk); + return; } release_sock(sk); } diff --git a/drivers/net/ipvlan/ipvlan_core.c b/drivers/net/ipvlan/ipvlan_core.c index 1f5125698e83..e10cb98b0f4f 100644 --- a/drivers/net/ipvlan/ipvlan_core.c +++ b/drivers/net/ipvlan/ipvlan_core.c @@ -586,7 +586,8 @@ static int ipvlan_xmit_mode_l3(struct sk_buff *skb, struct net_device *dev) consume_skb(skb); return NET_XMIT_DROP; } - return ipvlan_rcv_frame(addr, &skb, true); + ipvlan_rcv_frame(addr, &skb, true); + return NET_XMIT_SUCCESS; } } out: @@ -612,7 +613,8 @@ static int ipvlan_xmit_mode_l2(struct sk_buff *skb, struct net_device *dev) consume_skb(skb); return NET_XMIT_DROP; } - return ipvlan_rcv_frame(addr, &skb, true); + ipvlan_rcv_frame(addr, &skb, true); + return NET_XMIT_SUCCESS; } } skb = skb_share_check(skb, GFP_ATOMIC); @@ -624,7 +626,8 @@ static int ipvlan_xmit_mode_l2(struct sk_buff *skb, struct net_device *dev) * the skb for the main-dev. At the RX side we just return * RX_PASS for it to be processed further on the stack. */ - return dev_forward_skb(ipvlan->phy_dev, skb); + dev_forward_skb(ipvlan->phy_dev, skb); + return NET_XMIT_SUCCESS; } else if (is_multicast_ether_addr(eth->h_dest)) { skb_reset_mac_header(skb); diff --git a/drivers/net/netdevsim/dev.c b/drivers/net/netdevsim/dev.c index 94490dfae656..a7279356299a 100644 --- a/drivers/net/netdevsim/dev.c +++ b/drivers/net/netdevsim/dev.c @@ -168,13 +168,10 @@ static ssize_t nsim_dev_trap_fa_cookie_write(struct file *file, cookie_len = (count - 1) / 2; if ((count - 1) % 2) return -EINVAL; - buf = kmalloc(count, GFP_KERNEL | __GFP_NOWARN); - if (!buf) - return -ENOMEM; - ret = simple_write_to_buffer(buf, count, ppos, data, count); - if (ret < 0) - goto free_buf; + buf = memdup_user(data, count); + if (IS_ERR(buf)) + return PTR_ERR(buf); fa_cookie = kmalloc(sizeof(*fa_cookie) + cookie_len, GFP_KERNEL | __GFP_NOWARN); diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c index e4752050a40e..d742fa342221 100644 --- a/drivers/net/phy/phy_device.c +++ b/drivers/net/phy/phy_device.c @@ -3230,23 +3230,30 @@ static int __init phy_init(void) { int rc; + ethtool_set_ethtool_phy_ops(&phy_ethtool_phy_ops); + rc = mdio_bus_init(); if (rc) - return rc; + goto err_ethtool_phy_ops; - ethtool_set_ethtool_phy_ops(&phy_ethtool_phy_ops); features_init(); rc = phy_driver_register(&genphy_c45_driver, THIS_MODULE); if (rc) - goto err_c45; + goto err_mdio_bus; rc = phy_driver_register(&genphy_driver, THIS_MODULE); - if (rc) { - phy_driver_unregister(&genphy_c45_driver); + if (rc) + goto err_c45; + + return 0; + err_c45: - mdio_bus_exit(); - } + phy_driver_unregister(&genphy_c45_driver); +err_mdio_bus: + mdio_bus_exit(); +err_ethtool_phy_ops: + ethtool_set_ethtool_phy_ops(NULL); return rc; } diff --git a/drivers/net/ppp/pptp.c b/drivers/net/ppp/pptp.c index 0fe78826c8fa..32183f24e63f 100644 --- a/drivers/net/ppp/pptp.c +++ b/drivers/net/ppp/pptp.c @@ -24,6 +24,7 @@ #include #include #include +#include #include #include @@ -128,6 +129,23 @@ static void del_chan(struct pppox_sock *sock) spin_unlock(&chan_lock); } +static struct rtable *pptp_route_output(struct pppox_sock *po, + struct flowi4 *fl4) +{ + struct sock *sk = &po->sk; + struct net *net; + + net = sock_net(sk); + flowi4_init_output(fl4, sk->sk_bound_dev_if, sk->sk_mark, 0, + RT_SCOPE_UNIVERSE, IPPROTO_GRE, 0, + po->proto.pptp.dst_addr.sin_addr.s_addr, + po->proto.pptp.src_addr.sin_addr.s_addr, + 0, 0, sock_net_uid(net, sk)); + security_sk_classify_flow(sk, flowi4_to_flowi_common(fl4)); + + return ip_route_output_flow(net, fl4, sk); +} + static int pptp_xmit(struct ppp_channel *chan, struct sk_buff *skb) { struct sock *sk = (struct sock *) chan->private; @@ -151,11 +169,7 @@ static int pptp_xmit(struct ppp_channel *chan, struct sk_buff *skb) if (sk_pppox(po)->sk_state & PPPOX_DEAD) goto tx_error; - rt = ip_route_output_ports(net, &fl4, NULL, - opt->dst_addr.sin_addr.s_addr, - opt->src_addr.sin_addr.s_addr, - 0, 0, IPPROTO_GRE, - RT_TOS(0), sk->sk_bound_dev_if); + rt = pptp_route_output(po, &fl4); if (IS_ERR(rt)) goto tx_error; @@ -438,12 +452,7 @@ static int pptp_connect(struct socket *sock, struct sockaddr *uservaddr, po->chan.private = sk; po->chan.ops = &pptp_chan_ops; - rt = ip_route_output_ports(sock_net(sk), &fl4, sk, - opt->dst_addr.sin_addr.s_addr, - opt->src_addr.sin_addr.s_addr, - 0, 0, - IPPROTO_GRE, RT_CONN_FLAGS(sk), - sk->sk_bound_dev_if); + rt = pptp_route_output(po, &fl4); if (IS_ERR(rt)) { error = -EHOSTUNREACH; goto end; diff --git a/drivers/net/tap.c b/drivers/net/tap.c index 663ce0e09c2d..bdb05d246b86 100644 --- a/drivers/net/tap.c +++ b/drivers/net/tap.c @@ -523,7 +523,7 @@ static int tap_open(struct inode *inode, struct file *file) q->sock.state = SS_CONNECTED; q->sock.file = file; q->sock.ops = &tap_socket_ops; - sock_init_data_uid(&q->sock, &q->sk, inode->i_uid); + sock_init_data_uid(&q->sock, &q->sk, current_fsuid()); q->sk.sk_write_space = tap_sock_write_space; q->sk.sk_destruct = tap_sock_destruct; q->flags = IFF_VNET_HDR | IFF_NO_PI | IFF_TAP; diff --git a/drivers/net/tun.c b/drivers/net/tun.c index 30eea8270c9b..924bdae314c8 100644 --- a/drivers/net/tun.c +++ b/drivers/net/tun.c @@ -3411,7 +3411,7 @@ static int tun_chr_open(struct inode *inode, struct file * file) tfile->socket.file = file; tfile->socket.ops = &tun_socket_ops; - sock_init_data_uid(&tfile->socket, &tfile->sk, inode->i_uid); + sock_init_data_uid(&tfile->socket, &tfile->sk, current_fsuid()); tfile->sk.sk_write_space = tun_sock_write_space; tfile->sk.sk_sndbuf = INT_MAX; diff --git a/drivers/net/usb/Makefile b/drivers/net/usb/Makefile index 4964f7b326fb..c625c2de98de 100644 --- a/drivers/net/usb/Makefile +++ b/drivers/net/usb/Makefile @@ -12,7 +12,8 @@ obj-$(CONFIG_USB_HSO) += hso.o obj-$(CONFIG_USB_LAN78XX) += lan78xx.o obj-$(CONFIG_USB_NET_AX8817X) += asix.o asix-y := asix_devices.o asix_common.o ax88172a.o -obj-$(CONFIG_USB_NET_AX88179_178A) += ax88179_178a.o +obj-$(CONFIG_USB_NET_AX88179_178A) += ax_usb_nic.o +ax_usb_nic-y := ax_main.o ax88179_178a.o ax88179a_772d.o obj-$(CONFIG_USB_NET_CDCETHER) += cdc_ether.o obj-$(CONFIG_USB_NET_CDC_EEM) += cdc_eem.o obj-$(CONFIG_USB_NET_DM9601) += dm9601.o diff --git a/drivers/net/usb/ax88179_178a.c b/drivers/net/usb/ax88179_178a.c index 0a2c3860179e..e1927cf6476e 100644 --- a/drivers/net/usb/ax88179_178a.c +++ b/drivers/net/usb/ax88179_178a.c @@ -1,1098 +1,378 @@ -// SPDX-License-Identifier: GPL-2.0-or-later -/* - * ASIX AX88179/178A USB 3.0/2.0 to Gigabit Ethernet Devices +// SPDX-License-Identifier: GPL-2.0 +/******************************************************************************* + * Copyright (c) 2022 ASIX Electronic Corporation All rights reserved. * - * Copyright (C) 2011-2013 ASIX - */ + * This program is free software: you can redistribute it and/or modify it under + * the terms of the GNU General Public License as published by the Free Software + * Foundation, either version 2 of the License, or (at your option) any later + * version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details + * + * You should have received a copy of the GNU General Public License along with + * this program. If not, see . + ******************************************************************************/ +#include "ax_main.h" +#include "ax88179_178a.h" -#include -#include -#include -#include -#include -#include -#include -#include - -#define AX88179_PHY_ID 0x03 -#define AX_EEPROM_LEN 0x100 -#define AX88179_EEPROM_MAGIC 0x17900b95 -#define AX_MCAST_FLTSIZE 8 -#define AX_MAX_MCAST 64 -#define AX_INT_PPLS_LINK ((u32)BIT(16)) -#define AX_RXHDR_L4_TYPE_MASK 0x1c -#define AX_RXHDR_L4_TYPE_UDP 4 -#define AX_RXHDR_L4_TYPE_TCP 16 -#define AX_RXHDR_L3CSUM_ERR 2 -#define AX_RXHDR_L4CSUM_ERR 1 -#define AX_RXHDR_CRC_ERR ((u32)BIT(29)) -#define AX_RXHDR_DROP_ERR ((u32)BIT(31)) -#define AX_ACCESS_MAC 0x01 -#define AX_ACCESS_PHY 0x02 -#define AX_ACCESS_EEPROM 0x04 -#define AX_ACCESS_EFUS 0x05 -#define AX_RELOAD_EEPROM_EFUSE 0x06 -#define AX_PAUSE_WATERLVL_HIGH 0x54 -#define AX_PAUSE_WATERLVL_LOW 0x55 - -#define PHYSICAL_LINK_STATUS 0x02 - #define AX_USB_SS 0x04 - #define AX_USB_HS 0x02 - -#define GENERAL_STATUS 0x03 -/* Check AX88179 version. UA1:Bit2 = 0, UA2:Bit2 = 1 */ - #define AX_SECLD 0x04 - -#define AX_SROM_ADDR 0x07 -#define AX_SROM_CMD 0x0a - #define EEP_RD 0x04 - #define EEP_BUSY 0x10 - -#define AX_SROM_DATA_LOW 0x08 -#define AX_SROM_DATA_HIGH 0x09 - -#define AX_RX_CTL 0x0b - #define AX_RX_CTL_DROPCRCERR 0x0100 - #define AX_RX_CTL_IPE 0x0200 - #define AX_RX_CTL_START 0x0080 - #define AX_RX_CTL_AP 0x0020 - #define AX_RX_CTL_AM 0x0010 - #define AX_RX_CTL_AB 0x0008 - #define AX_RX_CTL_AMALL 0x0002 - #define AX_RX_CTL_PRO 0x0001 - #define AX_RX_CTL_STOP 0x0000 - -#define AX_NODE_ID 0x10 -#define AX_MULFLTARY 0x16 - -#define AX_MEDIUM_STATUS_MODE 0x22 - #define AX_MEDIUM_GIGAMODE 0x01 - #define AX_MEDIUM_FULL_DUPLEX 0x02 - #define AX_MEDIUM_EN_125MHZ 0x08 - #define AX_MEDIUM_RXFLOW_CTRLEN 0x10 - #define AX_MEDIUM_TXFLOW_CTRLEN 0x20 - #define AX_MEDIUM_RECEIVE_EN 0x100 - #define AX_MEDIUM_PS 0x200 - #define AX_MEDIUM_JUMBO_EN 0x8040 - -#define AX_MONITOR_MOD 0x24 - #define AX_MONITOR_MODE_RWLC 0x02 - #define AX_MONITOR_MODE_RWMP 0x04 - #define AX_MONITOR_MODE_PMEPOL 0x20 - #define AX_MONITOR_MODE_PMETYPE 0x40 - -#define AX_GPIO_CTRL 0x25 - #define AX_GPIO_CTRL_GPIO3EN 0x80 - #define AX_GPIO_CTRL_GPIO2EN 0x40 - #define AX_GPIO_CTRL_GPIO1EN 0x20 - -#define AX_PHYPWR_RSTCTL 0x26 - #define AX_PHYPWR_RSTCTL_BZ 0x0010 - #define AX_PHYPWR_RSTCTL_IPRL 0x0020 - #define AX_PHYPWR_RSTCTL_AT 0x1000 - -#define AX_RX_BULKIN_QCTRL 0x2e -#define AX_CLK_SELECT 0x33 - #define AX_CLK_SELECT_BCS 0x01 - #define AX_CLK_SELECT_ACS 0x02 - #define AX_CLK_SELECT_ULR 0x08 - -#define AX_RXCOE_CTL 0x34 - #define AX_RXCOE_IP 0x01 - #define AX_RXCOE_TCP 0x02 - #define AX_RXCOE_UDP 0x04 - #define AX_RXCOE_TCPV6 0x20 - #define AX_RXCOE_UDPV6 0x40 - -#define AX_TXCOE_CTL 0x35 - #define AX_TXCOE_IP 0x01 - #define AX_TXCOE_TCP 0x02 - #define AX_TXCOE_UDP 0x04 - #define AX_TXCOE_TCPV6 0x20 - #define AX_TXCOE_UDPV6 0x40 - -#define AX_LEDCTRL 0x73 - -#define GMII_PHY_PHYSR 0x11 - #define GMII_PHY_PHYSR_SMASK 0xc000 - #define GMII_PHY_PHYSR_GIGA 0x8000 - #define GMII_PHY_PHYSR_100 0x4000 - #define GMII_PHY_PHYSR_FULL 0x2000 - #define GMII_PHY_PHYSR_LINK 0x400 - -#define GMII_LED_ACT 0x1a - #define GMII_LED_ACTIVE_MASK 0xff8f - #define GMII_LED0_ACTIVE BIT(4) - #define GMII_LED1_ACTIVE BIT(5) - #define GMII_LED2_ACTIVE BIT(6) - -#define GMII_LED_LINK 0x1c - #define GMII_LED_LINK_MASK 0xf888 - #define GMII_LED0_LINK_10 BIT(0) - #define GMII_LED0_LINK_100 BIT(1) - #define GMII_LED0_LINK_1000 BIT(2) - #define GMII_LED1_LINK_10 BIT(4) - #define GMII_LED1_LINK_100 BIT(5) - #define GMII_LED1_LINK_1000 BIT(6) - #define GMII_LED2_LINK_10 BIT(8) - #define GMII_LED2_LINK_100 BIT(9) - #define GMII_LED2_LINK_1000 BIT(10) - #define LED0_ACTIVE BIT(0) - #define LED0_LINK_10 BIT(1) - #define LED0_LINK_100 BIT(2) - #define LED0_LINK_1000 BIT(3) - #define LED0_FD BIT(4) - #define LED0_USB3_MASK 0x001f - #define LED1_ACTIVE BIT(5) - #define LED1_LINK_10 BIT(6) - #define LED1_LINK_100 BIT(7) - #define LED1_LINK_1000 BIT(8) - #define LED1_FD BIT(9) - #define LED1_USB3_MASK 0x03e0 - #define LED2_ACTIVE BIT(10) - #define LED2_LINK_1000 BIT(13) - #define LED2_LINK_100 BIT(12) - #define LED2_LINK_10 BIT(11) - #define LED2_FD BIT(14) - #define LED_VALID BIT(15) - #define LED2_USB3_MASK 0x7c00 - -#define GMII_PHYPAGE 0x1e -#define GMII_PHY_PAGE_SELECT 0x1f - #define GMII_PHY_PGSEL_EXT 0x0007 - #define GMII_PHY_PGSEL_PAGE0 0x0000 - #define GMII_PHY_PGSEL_PAGE3 0x0003 - #define GMII_PHY_PGSEL_PAGE5 0x0005 - -struct ax88179_data { - u8 eee_enabled; - u8 eee_active; - u16 rxctl; - u16 reserved; -}; - -struct ax88179_int_data { - __le32 intdata1; - __le32 intdata2; -}; - -static const struct { - unsigned char ctrl, timer_l, timer_h, size, ifg; -} AX88179_BULKIN_SIZE[] = { - {7, 0x4f, 0, 0x12, 0xff}, +struct _ax_buikin_setting AX88179_BULKIN_SIZE[] = { + {7, 0x70, 0, 0x0C, 0x0f}, + {7, 0x70, 0, 0x0C, 0x0f}, {7, 0x20, 3, 0x16, 0xff}, {7, 0xae, 7, 0x18, 0xff}, - {7, 0xcc, 0x4c, 0x18, 8}, }; -static int __ax88179_read_cmd(struct usbnet *dev, u8 cmd, u16 value, u16 index, - u16 size, void *data, int in_pm) +const struct ethtool_ops ax88179_ethtool_ops = { + .get_drvinfo = ax_get_drvinfo, + .get_link_ksettings = ax_get_link_ksettings, + .set_link_ksettings = ax_set_link_ksettings, + .get_link = ethtool_op_get_link, + .get_msglevel = ax_get_msglevel, + .set_msglevel = ax_set_msglevel, + .get_wol = ax_get_wol, + .set_wol = ax_set_wol, + .get_ts_info = ethtool_op_get_ts_info, + .get_strings = ax_get_strings, + .get_sset_count = ax_get_sset_count, + .get_ethtool_stats = ax_get_ethtool_stats, + .get_regs_len = ax_get_regs_len, + .get_regs = ax_get_regs, +}; + +int ax88179_signature(struct ax_device *axdev, struct _ax_ioctl_command *info) { - int ret; - int (*fn)(struct usbnet *, u8, u8, u16, u16, void *, u16); - - BUG_ON(!dev); - - if (!in_pm) - fn = usbnet_read_cmd; - else - fn = usbnet_read_cmd_nopm; - - ret = fn(dev, cmd, USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, - value, index, data, size); - - if (unlikely(ret < 0)) - netdev_warn(dev->net, "Failed to read reg index 0x%04x: %d\n", - index, ret); - - return ret; -} - -static int __ax88179_write_cmd(struct usbnet *dev, u8 cmd, u16 value, u16 index, - u16 size, void *data, int in_pm) -{ - int ret; - int (*fn)(struct usbnet *, u8, u8, u16, u16, const void *, u16); - - BUG_ON(!dev); - - if (!in_pm) - fn = usbnet_write_cmd; - else - fn = usbnet_write_cmd_nopm; - - ret = fn(dev, cmd, USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, - value, index, data, size); - - if (unlikely(ret < 0)) - netdev_warn(dev->net, "Failed to write reg index 0x%04x: %d\n", - index, ret); - - return ret; -} - -static void ax88179_write_cmd_async(struct usbnet *dev, u8 cmd, u16 value, - u16 index, u16 size, void *data) -{ - u16 buf; - - if (2 == size) { - buf = *((u16 *)data); - cpu_to_le16s(&buf); - usbnet_write_cmd_async(dev, cmd, USB_DIR_OUT | USB_TYPE_VENDOR | - USB_RECIP_DEVICE, value, index, &buf, - size); - } else { - usbnet_write_cmd_async(dev, cmd, USB_DIR_OUT | USB_TYPE_VENDOR | - USB_RECIP_DEVICE, value, index, data, - size); - } -} - -static int ax88179_read_cmd_nopm(struct usbnet *dev, u8 cmd, u16 value, - u16 index, u16 size, void *data) -{ - int ret; - - if (2 == size) { - u16 buf; - ret = __ax88179_read_cmd(dev, cmd, value, index, size, &buf, 1); - le16_to_cpus(&buf); - *((u16 *)data) = buf; - } else if (4 == size) { - u32 buf; - ret = __ax88179_read_cmd(dev, cmd, value, index, size, &buf, 1); - le32_to_cpus(&buf); - *((u32 *)data) = buf; - } else { - ret = __ax88179_read_cmd(dev, cmd, value, index, size, data, 1); - } - - return ret; -} - -static int ax88179_write_cmd_nopm(struct usbnet *dev, u8 cmd, u16 value, - u16 index, u16 size, void *data) -{ - int ret; - - if (2 == size) { - u16 buf; - buf = *((u16 *)data); - cpu_to_le16s(&buf); - ret = __ax88179_write_cmd(dev, cmd, value, index, - size, &buf, 1); - } else { - ret = __ax88179_write_cmd(dev, cmd, value, index, - size, data, 1); - } - - return ret; -} - -static int ax88179_read_cmd(struct usbnet *dev, u8 cmd, u16 value, u16 index, - u16 size, void *data) -{ - int ret; - - if (2 == size) { - u16 buf = 0; - ret = __ax88179_read_cmd(dev, cmd, value, index, size, &buf, 0); - le16_to_cpus(&buf); - *((u16 *)data) = buf; - } else if (4 == size) { - u32 buf = 0; - ret = __ax88179_read_cmd(dev, cmd, value, index, size, &buf, 0); - le32_to_cpus(&buf); - *((u32 *)data) = buf; - } else { - ret = __ax88179_read_cmd(dev, cmd, value, index, size, data, 0); - } - - return ret; -} - -static int ax88179_write_cmd(struct usbnet *dev, u8 cmd, u16 value, u16 index, - u16 size, void *data) -{ - int ret; - - if (2 == size) { - u16 buf; - buf = *((u16 *)data); - cpu_to_le16s(&buf); - ret = __ax88179_write_cmd(dev, cmd, value, index, - size, &buf, 0); - } else { - ret = __ax88179_write_cmd(dev, cmd, value, index, - size, data, 0); - } - - return ret; -} - -static void ax88179_status(struct usbnet *dev, struct urb *urb) -{ - struct ax88179_int_data *event; - u32 link; - - if (urb->actual_length < 8) - return; - - event = urb->transfer_buffer; - le32_to_cpus((void *)&event->intdata1); - - link = (((__force u32)event->intdata1) & AX_INT_PPLS_LINK) >> 16; - - if (netif_carrier_ok(dev->net) != link) { - usbnet_link_change(dev, link, 1); - netdev_info(dev->net, "ax88179 - Link status is: %d\n", link); - } -} - -static int ax88179_mdio_read(struct net_device *netdev, int phy_id, int loc) -{ - struct usbnet *dev = netdev_priv(netdev); - u16 res; - - ax88179_read_cmd(dev, AX_ACCESS_PHY, phy_id, (__u16)loc, 2, &res); - return res; -} - -static void ax88179_mdio_write(struct net_device *netdev, int phy_id, int loc, - int val) -{ - struct usbnet *dev = netdev_priv(netdev); - u16 res = (u16) val; - - ax88179_write_cmd(dev, AX_ACCESS_PHY, phy_id, (__u16)loc, 2, &res); -} - -static inline int ax88179_phy_mmd_indirect(struct usbnet *dev, u16 prtad, - u16 devad) -{ - u16 tmp16; - int ret; - - tmp16 = devad; - ret = ax88179_write_cmd(dev, AX_ACCESS_PHY, AX88179_PHY_ID, - MII_MMD_CTRL, 2, &tmp16); - - tmp16 = prtad; - ret = ax88179_write_cmd(dev, AX_ACCESS_PHY, AX88179_PHY_ID, - MII_MMD_DATA, 2, &tmp16); - - tmp16 = devad | MII_MMD_CTRL_NOINCR; - ret = ax88179_write_cmd(dev, AX_ACCESS_PHY, AX88179_PHY_ID, - MII_MMD_CTRL, 2, &tmp16); - - return ret; -} - -static int -ax88179_phy_read_mmd_indirect(struct usbnet *dev, u16 prtad, u16 devad) -{ - int ret; - u16 tmp16; - - ax88179_phy_mmd_indirect(dev, prtad, devad); - - ret = ax88179_read_cmd(dev, AX_ACCESS_PHY, AX88179_PHY_ID, - MII_MMD_DATA, 2, &tmp16); - if (ret < 0) - return ret; - - return tmp16; -} - -static int -ax88179_phy_write_mmd_indirect(struct usbnet *dev, u16 prtad, u16 devad, - u16 data) -{ - int ret; - - ax88179_phy_mmd_indirect(dev, prtad, devad); - - ret = ax88179_write_cmd(dev, AX_ACCESS_PHY, AX88179_PHY_ID, - MII_MMD_DATA, 2, &data); - - if (ret < 0) - return ret; - + strscpy(info->sig, AX88179_SIGNATURE, sizeof(info->sig)); return 0; } -static int ax88179_suspend(struct usb_interface *intf, pm_message_t message) +int ax88179_read_eeprom(struct ax_device *axdev, struct _ax_ioctl_command *info) { - struct usbnet *dev = usb_get_intfdata(intf); - u16 tmp16; - u8 tmp8; + u8 i; + u16 tmp; + u8 value; + unsigned short *buf; - usbnet_suspend(intf, message); - - /* Disable RX path */ - ax88179_read_cmd_nopm(dev, AX_ACCESS_MAC, AX_MEDIUM_STATUS_MODE, - 2, 2, &tmp16); - tmp16 &= ~AX_MEDIUM_RECEIVE_EN; - ax88179_write_cmd_nopm(dev, AX_ACCESS_MAC, AX_MEDIUM_STATUS_MODE, - 2, 2, &tmp16); - - /* Force bulk-in zero length */ - ax88179_read_cmd_nopm(dev, AX_ACCESS_MAC, AX_PHYPWR_RSTCTL, - 2, 2, &tmp16); - - tmp16 |= AX_PHYPWR_RSTCTL_BZ | AX_PHYPWR_RSTCTL_IPRL; - ax88179_write_cmd_nopm(dev, AX_ACCESS_MAC, AX_PHYPWR_RSTCTL, - 2, 2, &tmp16); - - /* change clock */ - tmp8 = 0; - ax88179_write_cmd_nopm(dev, AX_ACCESS_MAC, AX_CLK_SELECT, 1, 1, &tmp8); - - /* Configure RX control register => stop operation */ - tmp16 = AX_RX_CTL_STOP; - ax88179_write_cmd_nopm(dev, AX_ACCESS_MAC, AX_RX_CTL, 2, 2, &tmp16); - - return 0; -} - -/* This function is used to enable the autodetach function. */ -/* This function is determined by offset 0x43 of EEPROM */ -static int ax88179_auto_detach(struct usbnet *dev, int in_pm) -{ - u16 tmp16; - u8 tmp8; - int (*fnr)(struct usbnet *, u8, u16, u16, u16, void *); - int (*fnw)(struct usbnet *, u8, u16, u16, u16, void *); - - if (!in_pm) { - fnr = ax88179_read_cmd; - fnw = ax88179_write_cmd; - } else { - fnr = ax88179_read_cmd_nopm; - fnw = ax88179_write_cmd_nopm; - } - - if (fnr(dev, AX_ACCESS_EEPROM, 0x43, 1, 2, &tmp16) < 0) - return 0; - - if ((tmp16 == 0xFFFF) || (!(tmp16 & 0x0100))) - return 0; - - /* Enable Auto Detach bit */ - tmp8 = 0; - fnr(dev, AX_ACCESS_MAC, AX_CLK_SELECT, 1, 1, &tmp8); - tmp8 |= AX_CLK_SELECT_ULR; - fnw(dev, AX_ACCESS_MAC, AX_CLK_SELECT, 1, 1, &tmp8); - - fnr(dev, AX_ACCESS_MAC, AX_PHYPWR_RSTCTL, 2, 2, &tmp16); - tmp16 |= AX_PHYPWR_RSTCTL_AT; - fnw(dev, AX_ACCESS_MAC, AX_PHYPWR_RSTCTL, 2, 2, &tmp16); - - return 0; -} - -static int ax88179_resume(struct usb_interface *intf) -{ - struct usbnet *dev = usb_get_intfdata(intf); - u16 tmp16; - u8 tmp8; - - usbnet_link_change(dev, 0, 0); - - /* Power up ethernet PHY */ - tmp16 = 0; - ax88179_write_cmd_nopm(dev, AX_ACCESS_MAC, AX_PHYPWR_RSTCTL, - 2, 2, &tmp16); - udelay(1000); - - tmp16 = AX_PHYPWR_RSTCTL_IPRL; - ax88179_write_cmd_nopm(dev, AX_ACCESS_MAC, AX_PHYPWR_RSTCTL, - 2, 2, &tmp16); - msleep(200); - - /* Ethernet PHY Auto Detach*/ - ax88179_auto_detach(dev, 1); - - /* Enable clock */ - ax88179_read_cmd_nopm(dev, AX_ACCESS_MAC, AX_CLK_SELECT, 1, 1, &tmp8); - tmp8 |= AX_CLK_SELECT_ACS | AX_CLK_SELECT_BCS; - ax88179_write_cmd_nopm(dev, AX_ACCESS_MAC, AX_CLK_SELECT, 1, 1, &tmp8); - msleep(100); - - /* Configure RX control register => start operation */ - tmp16 = AX_RX_CTL_DROPCRCERR | AX_RX_CTL_IPE | AX_RX_CTL_START | - AX_RX_CTL_AP | AX_RX_CTL_AMALL | AX_RX_CTL_AB; - ax88179_write_cmd_nopm(dev, AX_ACCESS_MAC, AX_RX_CTL, 2, 2, &tmp16); - - return usbnet_resume(intf); -} - -static void -ax88179_get_wol(struct net_device *net, struct ethtool_wolinfo *wolinfo) -{ - struct usbnet *dev = netdev_priv(net); - u8 opt; - - if (ax88179_read_cmd(dev, AX_ACCESS_MAC, AX_MONITOR_MOD, - 1, 1, &opt) < 0) { - wolinfo->supported = 0; - wolinfo->wolopts = 0; - return; - } - - wolinfo->supported = WAKE_PHY | WAKE_MAGIC; - wolinfo->wolopts = 0; - if (opt & AX_MONITOR_MODE_RWLC) - wolinfo->wolopts |= WAKE_PHY; - if (opt & AX_MONITOR_MODE_RWMP) - wolinfo->wolopts |= WAKE_MAGIC; -} - -static int -ax88179_set_wol(struct net_device *net, struct ethtool_wolinfo *wolinfo) -{ - struct usbnet *dev = netdev_priv(net); - u8 opt = 0; - - if (wolinfo->wolopts & ~(WAKE_PHY | WAKE_MAGIC)) - return -EINVAL; - - if (wolinfo->wolopts & WAKE_PHY) - opt |= AX_MONITOR_MODE_RWLC; - if (wolinfo->wolopts & WAKE_MAGIC) - opt |= AX_MONITOR_MODE_RWMP; - - if (ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_MONITOR_MOD, - 1, 1, &opt) < 0) - return -EINVAL; - - return 0; -} - -static int ax88179_get_eeprom_len(struct net_device *net) -{ - return AX_EEPROM_LEN; -} - -static int -ax88179_get_eeprom(struct net_device *net, struct ethtool_eeprom *eeprom, - u8 *data) -{ - struct usbnet *dev = netdev_priv(net); - u16 *eeprom_buff; - int first_word, last_word; - int i, ret; - - if (eeprom->len == 0) - return -EINVAL; - - eeprom->magic = AX88179_EEPROM_MAGIC; - - first_word = eeprom->offset >> 1; - last_word = (eeprom->offset + eeprom->len - 1) >> 1; - eeprom_buff = kmalloc_array(last_word - first_word + 1, sizeof(u16), + if (info->buf) { + buf = kmalloc_array(info->size, sizeof(unsigned short), GFP_KERNEL); - if (!eeprom_buff) - return -ENOMEM; + if (!buf) + return -ENOMEM; + } else { + netdev_info(axdev->netdev, "The EEPROM buffer cannot be NULL. \r\n"); + return -EINVAL; + } - /* ax88179/178A returns 2 bytes from eeprom on read */ - for (i = first_word; i <= last_word; i++) { - ret = __ax88179_read_cmd(dev, AX_ACCESS_EEPROM, i, 1, 2, - &eeprom_buff[i - first_word], - 0); - if (ret < 0) { - kfree(eeprom_buff); - return -EIO; + if (info->type == 0) { + for (i = 0; i < info->size; i++) { + if (ax_write_cmd(axdev, AX_ACCESS_MAC, AX_SROM_ADDR, 1, 1, &i) < 0) { + kfree(buf); + return -EINVAL; + } + + value = EEP_RD; + if (ax_write_cmd(axdev, AX_ACCESS_MAC, AX_SROM_CMD, 1, 1, &value) < 0) { + kfree(buf); + return -EINVAL; + } + + do { + ax_read_cmd(axdev, AX_ACCESS_MAC, AX_SROM_CMD, 1, 1, &value, 0); + } while (value & EEP_BUSY); + + if (ax_read_cmd(axdev, AX_ACCESS_MAC, AX_SROM_DATA_LOW, + 2, 2, &tmp, 1) < 0) { + kfree(buf); + return -EINVAL; + } + + *(buf + i) = be16_to_cpu(tmp); + + if (i == (info->size - 1)) + break; + } + } else { + for (i = 0; i < info->size; i++) { + if (ax_read_cmd(axdev, AX_ACCESS_EFUSE, i, 1, 2, &tmp, 1) < 0) { + kfree(buf); + return -EINVAL; + } + *(buf + i) = be16_to_cpu(tmp); + if (i == (info->size - 1)) + break; } } - memcpy(data, (u8 *)eeprom_buff + (eeprom->offset & 1), eeprom->len); - kfree(eeprom_buff); + if (copy_to_user(info->buf, buf, sizeof(unsigned short) * info->size)) { + kfree(buf); + return -EFAULT; + } + + kfree(buf); + return 0; } -static int -ax88179_set_eeprom(struct net_device *net, struct ethtool_eeprom *eeprom, - u8 *data) +int ax88179_write_eeprom(struct ax_device *axdev, + struct _ax_ioctl_command *info) { - struct usbnet *dev = netdev_priv(net); - u16 *eeprom_buff; - int first_word; - int last_word; - int ret; int i; + u16 data, csum = 0; + unsigned short *buf; - netdev_dbg(net, "write EEPROM len %d, offset %d, magic 0x%x\n", - eeprom->len, eeprom->offset, eeprom->magic); - - if (eeprom->len == 0) - return -EINVAL; - - if (eeprom->magic != AX88179_EEPROM_MAGIC) - return -EINVAL; - - first_word = eeprom->offset >> 1; - last_word = (eeprom->offset + eeprom->len - 1) >> 1; - - eeprom_buff = kmalloc_array(last_word - first_word + 1, sizeof(u16), + if (info->buf) { + buf = kmalloc_array(info->size, sizeof(unsigned short), GFP_KERNEL); - if (!eeprom_buff) - return -ENOMEM; + if (!buf) + return -ENOMEM; - /* align data to 16 bit boundaries, read the missing data from - the EEPROM */ - if (eeprom->offset & 1) { - ret = ax88179_read_cmd(dev, AX_ACCESS_EEPROM, first_word, 1, 2, - &eeprom_buff[0]); - if (ret < 0) { - netdev_err(net, "Failed to read EEPROM at offset 0x%02x.\n", first_word); - goto free; + if (copy_from_user(buf, info->buf, + sizeof(unsigned short) * info->size)) { + kfree(buf); + return -EFAULT; } - } - - if ((eeprom->offset + eeprom->len) & 1) { - ret = ax88179_read_cmd(dev, AX_ACCESS_EEPROM, last_word, 1, 2, - &eeprom_buff[last_word - first_word]); - if (ret < 0) { - netdev_err(net, "Failed to read EEPROM at offset 0x%02x.\n", last_word); - goto free; - } - } - - memcpy((u8 *)eeprom_buff + (eeprom->offset & 1), data, eeprom->len); - - for (i = first_word; i <= last_word; i++) { - netdev_dbg(net, "write to EEPROM at offset 0x%02x, data 0x%04x\n", - i, eeprom_buff[i - first_word]); - ret = ax88179_write_cmd(dev, AX_ACCESS_EEPROM, i, 1, 2, - &eeprom_buff[i - first_word]); - if (ret < 0) { - netdev_err(net, "Failed to write EEPROM at offset 0x%02x.\n", i); - goto free; - } - msleep(20); - } - - /* reload EEPROM data */ - ret = ax88179_write_cmd(dev, AX_RELOAD_EEPROM_EFUSE, 0x0000, 0, 0, NULL); - if (ret < 0) { - netdev_err(net, "Failed to reload EEPROM data\n"); - goto free; - } - - ret = 0; -free: - kfree(eeprom_buff); - return ret; -} - -static int ax88179_get_link_ksettings(struct net_device *net, - struct ethtool_link_ksettings *cmd) -{ - struct usbnet *dev = netdev_priv(net); - - mii_ethtool_get_link_ksettings(&dev->mii, cmd); - - return 0; -} - -static int ax88179_set_link_ksettings(struct net_device *net, - const struct ethtool_link_ksettings *cmd) -{ - struct usbnet *dev = netdev_priv(net); - return mii_ethtool_set_link_ksettings(&dev->mii, cmd); -} - -static int -ax88179_ethtool_get_eee(struct usbnet *dev, struct ethtool_eee *data) -{ - int val; - - /* Get Supported EEE */ - val = ax88179_phy_read_mmd_indirect(dev, MDIO_PCS_EEE_ABLE, - MDIO_MMD_PCS); - if (val < 0) - return val; - data->supported = mmd_eee_cap_to_ethtool_sup_t(val); - - /* Get advertisement EEE */ - val = ax88179_phy_read_mmd_indirect(dev, MDIO_AN_EEE_ADV, - MDIO_MMD_AN); - if (val < 0) - return val; - data->advertised = mmd_eee_adv_to_ethtool_adv_t(val); - - /* Get LP advertisement EEE */ - val = ax88179_phy_read_mmd_indirect(dev, MDIO_AN_EEE_LPABLE, - MDIO_MMD_AN); - if (val < 0) - return val; - data->lp_advertised = mmd_eee_adv_to_ethtool_adv_t(val); - - return 0; -} - -static int -ax88179_ethtool_set_eee(struct usbnet *dev, struct ethtool_eee *data) -{ - u16 tmp16 = ethtool_adv_to_mmd_eee_adv_t(data->advertised); - - return ax88179_phy_write_mmd_indirect(dev, MDIO_AN_EEE_ADV, - MDIO_MMD_AN, tmp16); -} - -static int ax88179_chk_eee(struct usbnet *dev) -{ - struct ethtool_cmd ecmd = { .cmd = ETHTOOL_GSET }; - struct ax88179_data *priv = (struct ax88179_data *)dev->data; - - mii_ethtool_gset(&dev->mii, &ecmd); - - if (ecmd.duplex & DUPLEX_FULL) { - int eee_lp, eee_cap, eee_adv; - u32 lp, cap, adv, supported = 0; - - eee_cap = ax88179_phy_read_mmd_indirect(dev, - MDIO_PCS_EEE_ABLE, - MDIO_MMD_PCS); - if (eee_cap < 0) { - priv->eee_active = 0; - return false; - } - - cap = mmd_eee_cap_to_ethtool_sup_t(eee_cap); - if (!cap) { - priv->eee_active = 0; - return false; - } - - eee_lp = ax88179_phy_read_mmd_indirect(dev, - MDIO_AN_EEE_LPABLE, - MDIO_MMD_AN); - if (eee_lp < 0) { - priv->eee_active = 0; - return false; - } - - eee_adv = ax88179_phy_read_mmd_indirect(dev, - MDIO_AN_EEE_ADV, - MDIO_MMD_AN); - - if (eee_adv < 0) { - priv->eee_active = 0; - return false; - } - - adv = mmd_eee_adv_to_ethtool_adv_t(eee_adv); - lp = mmd_eee_adv_to_ethtool_adv_t(eee_lp); - supported = (ecmd.speed == SPEED_1000) ? - SUPPORTED_1000baseT_Full : - SUPPORTED_100baseT_Full; - - if (!(lp & adv & supported)) { - priv->eee_active = 0; - return false; - } - - priv->eee_active = 1; - return true; - } - - priv->eee_active = 0; - return false; -} - -static void ax88179_disable_eee(struct usbnet *dev) -{ - u16 tmp16; - - tmp16 = GMII_PHY_PGSEL_PAGE3; - ax88179_write_cmd(dev, AX_ACCESS_PHY, AX88179_PHY_ID, - GMII_PHY_PAGE_SELECT, 2, &tmp16); - - tmp16 = 0x3246; - ax88179_write_cmd(dev, AX_ACCESS_PHY, AX88179_PHY_ID, - MII_PHYADDR, 2, &tmp16); - - tmp16 = GMII_PHY_PGSEL_PAGE0; - ax88179_write_cmd(dev, AX_ACCESS_PHY, AX88179_PHY_ID, - GMII_PHY_PAGE_SELECT, 2, &tmp16); -} - -static void ax88179_enable_eee(struct usbnet *dev) -{ - u16 tmp16; - - tmp16 = GMII_PHY_PGSEL_PAGE3; - ax88179_write_cmd(dev, AX_ACCESS_PHY, AX88179_PHY_ID, - GMII_PHY_PAGE_SELECT, 2, &tmp16); - - tmp16 = 0x3247; - ax88179_write_cmd(dev, AX_ACCESS_PHY, AX88179_PHY_ID, - MII_PHYADDR, 2, &tmp16); - - tmp16 = GMII_PHY_PGSEL_PAGE5; - ax88179_write_cmd(dev, AX_ACCESS_PHY, AX88179_PHY_ID, - GMII_PHY_PAGE_SELECT, 2, &tmp16); - - tmp16 = 0x0680; - ax88179_write_cmd(dev, AX_ACCESS_PHY, AX88179_PHY_ID, - MII_BMSR, 2, &tmp16); - - tmp16 = GMII_PHY_PGSEL_PAGE0; - ax88179_write_cmd(dev, AX_ACCESS_PHY, AX88179_PHY_ID, - GMII_PHY_PAGE_SELECT, 2, &tmp16); -} - -static int ax88179_get_eee(struct net_device *net, struct ethtool_eee *edata) -{ - struct usbnet *dev = netdev_priv(net); - struct ax88179_data *priv = (struct ax88179_data *)dev->data; - - edata->eee_enabled = priv->eee_enabled; - edata->eee_active = priv->eee_active; - - return ax88179_ethtool_get_eee(dev, edata); -} - -static int ax88179_set_eee(struct net_device *net, struct ethtool_eee *edata) -{ - struct usbnet *dev = netdev_priv(net); - struct ax88179_data *priv = (struct ax88179_data *)dev->data; - int ret; - - priv->eee_enabled = edata->eee_enabled; - if (!priv->eee_enabled) { - ax88179_disable_eee(dev); } else { - priv->eee_enabled = ax88179_chk_eee(dev); - if (!priv->eee_enabled) - return -EOPNOTSUPP; - - ax88179_enable_eee(dev); + netdev_err(axdev->netdev, "The EEPROM buffer cannot be NULL. \r\n"); + return -EINVAL; } - ret = ax88179_ethtool_set_eee(dev, edata); - if (ret) - return ret; + if (info->type == 0) { + if ((*(buf) >> 8) & 0x01) { + netdev_info(axdev->netdev, "Cannot be set to muliticast MAC address, "); + netdev_info(axdev->netdev, "bit0 of Node ID-0 cannot be set to 1. \r\n"); + kfree(buf); + return -EINVAL; + } - mii_nway_restart(&dev->mii); + csum = (*(buf + 3) & 0xff) + ((*(buf + 3) >> 8) & 0xff) + + (*(buf + 4) & 0xff) + ((*(buf + 4) >> 8) & 0xff); + csum = 0xff - ((csum >> 8) + (csum & 0xff)); + data = ((*(buf + 5)) & 0xff) | (csum << 8); + *(buf + 5) = data; - usbnet_link_change(dev, 0, 0); + for (i = 0; i < info->size; i++) { + data = cpu_to_be16(*(buf + i)); + if (ax_write_cmd(axdev, AX_ACCESS_EEPROM, + i, 1, 2, &data) < 0) { + kfree(buf); + return -EINVAL; + } - return ret; + msleep(info->delay); + } + } else if (info->type == 1) { + if ((*(buf) >> 8) & 0x01) { + netdev_info(axdev->netdev, "Cannot be set to muliticast MAC address, "); + netdev_info(axdev->netdev, "bit0 of Node ID-0 cannot be set to 1. \r\n"); + kfree(buf); + return -EINVAL; + } + + for (i = 0; i < info->size; i++) + csum += (*(buf + i) & 0xff) + ((*(buf + i) >> 8) & 0xff); + + csum -= ((*(buf + 0x19) >> 8) & 0xff); + while (csum > 255) + csum = (csum & 0x00FF) + ((csum >> 8) & 0x00FF); + csum = 0xFF - csum; + + data = ((*(buf + 0x19)) & 0xff) | (csum << 8); + *(buf + 0x19) = data; + + if (ax_write_cmd(axdev, AX_WRITE_EFUSE_EN, 0, 0, 0, NULL) < 0) { + kfree(buf); + return -EINVAL; + } + + msleep(info->delay); + + for (i = 0; i < info->size; i++) { + data = cpu_to_be16(*(buf + i)); + if (ax_write_cmd(axdev, AX_ACCESS_EFUSE, i, 1, 2, &data) < 0) { + kfree(buf); + return -EINVAL; + } + + msleep(info->delay); + } + + if (ax_write_cmd(axdev, AX_WRITE_EFUSE_DIS, 0, 0, 0, NULL) < 0) { + kfree(buf); + return -EINVAL; + } + + msleep(info->delay); + } else if (info->type == 2) { + if (ax_read_cmd(axdev, AX_ACCESS_EFUSE, 0, 1, 2, &data, 1) < 0) { + kfree(buf); + return -EINVAL; + } + + if (data == 0xFFFF) + info->type = 0; + else + info->type = 1; + } else { + kfree(buf); + return -EINVAL; + } + + kfree(buf); + return 0; } -static int ax88179_ioctl(struct net_device *net, struct ifreq *rq, int cmd) -{ - struct usbnet *dev = netdev_priv(net); - return generic_mii_ioctl(&dev->mii, if_mii(rq), cmd, NULL); -} - -static const struct ethtool_ops ax88179_ethtool_ops = { - .get_link = ethtool_op_get_link, - .get_msglevel = usbnet_get_msglevel, - .set_msglevel = usbnet_set_msglevel, - .get_wol = ax88179_get_wol, - .set_wol = ax88179_set_wol, - .get_eeprom_len = ax88179_get_eeprom_len, - .get_eeprom = ax88179_get_eeprom, - .set_eeprom = ax88179_set_eeprom, - .get_eee = ax88179_get_eee, - .set_eee = ax88179_set_eee, - .nway_reset = usbnet_nway_reset, - .get_link_ksettings = ax88179_get_link_ksettings, - .set_link_ksettings = ax88179_set_link_ksettings, - .get_ts_info = ethtool_op_get_ts_info, +IOCTRL_TABLE ax88179_tbl[] = { + ax88179_signature, + NULL,//ax_usb_command, + ax88179_read_eeprom, + ax88179_write_eeprom, }; -static void ax88179_set_multicast(struct net_device *net) +int ax88179_siocdevprivate(struct net_device *netdev, struct ifreq *rq, + void __user *udata, int cmd) { - struct usbnet *dev = netdev_priv(net); - struct ax88179_data *data = (struct ax88179_data *)dev->data; - u8 *m_filter = ((u8 *)dev->data) + 12; + struct ax_device *axdev = netdev_priv(netdev); + struct _ax_ioctl_command info; + struct _ax_ioctl_command *uptr = (struct _ax_ioctl_command *)rq->ifr_data; + int ret = 0; - data->rxctl = (AX_RX_CTL_START | AX_RX_CTL_AB | AX_RX_CTL_IPE); + switch (cmd) { + case AX_PRIVATE: + if (copy_from_user(&info, uptr, + sizeof(struct _ax_ioctl_command))) + return -EFAULT; + + if ((*ax88179_tbl[info.ioctl_cmd])(axdev, &info) < 0) { + netdev_info(netdev, "ax88179_tbl, return -EFAULT"); + return -EFAULT; + } + + if (copy_to_user(uptr, &info, sizeof(struct _ax_ioctl_command))) + return -EFAULT; + + break; + default: + ret = -EOPNOTSUPP; + } + + return ret; +} + +int ax88179_ioctl(struct net_device *netdev, struct ifreq *rq, int cmd) +{ + struct ax_device *axdev = netdev_priv(netdev); + + return generic_mii_ioctl(&axdev->mii, if_mii(rq), cmd, NULL); +} + +void ax88179_set_multicast(struct net_device *net) +{ + struct ax_device *axdev = netdev_priv(net); + u8 *m_filter = axdev->m_filter; + int mc_count = 0; + + if (!test_bit(AX_ENABLE, &axdev->flags)) + return; + + mc_count = netdev_mc_count(net); + + axdev->rxctl = (AX_RX_CTL_START | AX_RX_CTL_AB); if (net->flags & IFF_PROMISC) { - data->rxctl |= AX_RX_CTL_PRO; - } else if (net->flags & IFF_ALLMULTI || - netdev_mc_count(net) > AX_MAX_MCAST) { - data->rxctl |= AX_RX_CTL_AMALL; - } else if (netdev_mc_empty(net)) { - /* just broadcast and directed */ + axdev->rxctl |= AX_RX_CTL_PRO; + } else if (net->flags & IFF_ALLMULTI || mc_count > AX_MAX_MCAST) { + axdev->rxctl |= AX_RX_CTL_AMALL; + } else if (mc_count == 0) { } else { - /* We use the 20 byte dev->data for our 8 byte filter buffer - * to avoid allocating memory that is tricky to free later - */ u32 crc_bits; - struct netdev_hw_addr *ha; - - memset(m_filter, 0, AX_MCAST_FLTSIZE); + struct netdev_hw_addr *ha = NULL; + memset(m_filter, 0, AX_MCAST_FILTER_SIZE); netdev_for_each_mc_addr(ha, net) { crc_bits = ether_crc(ETH_ALEN, ha->addr) >> 26; - *(m_filter + (crc_bits >> 3)) |= (1 << (crc_bits & 7)); + *(m_filter + (crc_bits >> 3)) |= + 1 << (crc_bits & 7); } - - ax88179_write_cmd_async(dev, AX_ACCESS_MAC, AX_MULFLTARY, - AX_MCAST_FLTSIZE, AX_MCAST_FLTSIZE, - m_filter); - - data->rxctl |= AX_RX_CTL_AM; + ax_write_cmd_async(axdev, AX_ACCESS_MAC, AX_MULTI_FILTER_ARRY, + AX_MCAST_FILTER_SIZE, AX_MCAST_FILTER_SIZE, m_filter); + axdev->rxctl |= AX_RX_CTL_AM; } - - ax88179_write_cmd_async(dev, AX_ACCESS_MAC, AX_RX_CTL, - 2, 2, &data->rxctl); + ax_write_cmd_async(axdev, AX_ACCESS_MAC, AX_RX_CTL, 2, 2, &axdev->rxctl); } -static int -ax88179_set_features(struct net_device *net, netdev_features_t features) +int ax88179_set_mac_addr(struct net_device *netdev, void *p) { - u8 tmp; - struct usbnet *dev = netdev_priv(net); - netdev_features_t changed = net->features ^ features; - - if (changed & NETIF_F_IP_CSUM) { - ax88179_read_cmd(dev, AX_ACCESS_MAC, AX_TXCOE_CTL, 1, 1, &tmp); - tmp ^= AX_TXCOE_TCP | AX_TXCOE_UDP; - ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_TXCOE_CTL, 1, 1, &tmp); - } - - if (changed & NETIF_F_IPV6_CSUM) { - ax88179_read_cmd(dev, AX_ACCESS_MAC, AX_TXCOE_CTL, 1, 1, &tmp); - tmp ^= AX_TXCOE_TCPV6 | AX_TXCOE_UDPV6; - ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_TXCOE_CTL, 1, 1, &tmp); - } - - if (changed & NETIF_F_RXCSUM) { - ax88179_read_cmd(dev, AX_ACCESS_MAC, AX_RXCOE_CTL, 1, 1, &tmp); - tmp ^= AX_RXCOE_IP | AX_RXCOE_TCP | AX_RXCOE_UDP | - AX_RXCOE_TCPV6 | AX_RXCOE_UDPV6; - ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_RXCOE_CTL, 1, 1, &tmp); - } - - return 0; -} - -static int ax88179_change_mtu(struct net_device *net, int new_mtu) -{ - struct usbnet *dev = netdev_priv(net); - u16 tmp16; - - net->mtu = new_mtu; - dev->hard_mtu = net->mtu + net->hard_header_len; - - if (net->mtu > 1500) { - ax88179_read_cmd(dev, AX_ACCESS_MAC, AX_MEDIUM_STATUS_MODE, - 2, 2, &tmp16); - tmp16 |= AX_MEDIUM_JUMBO_EN; - ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_MEDIUM_STATUS_MODE, - 2, 2, &tmp16); - } else { - ax88179_read_cmd(dev, AX_ACCESS_MAC, AX_MEDIUM_STATUS_MODE, - 2, 2, &tmp16); - tmp16 &= ~AX_MEDIUM_JUMBO_EN; - ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_MEDIUM_STATUS_MODE, - 2, 2, &tmp16); - } - - /* max qlen depend on hard_mtu and rx_urb_size */ - usbnet_update_max_qlen(dev); - - return 0; -} - -static int ax88179_set_mac_addr(struct net_device *net, void *p) -{ - struct usbnet *dev = netdev_priv(net); + struct ax_device *axdev = netdev_priv(netdev); struct sockaddr *addr = p; int ret; - if (netif_running(net)) - return -EBUSY; if (!is_valid_ether_addr(addr->sa_data)) return -EADDRNOTAVAIL; - memcpy(net->dev_addr, addr->sa_data, ETH_ALEN); + if (netif_running(netdev)) + return -EBUSY; - /* Set the MAC address */ - ret = ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_NODE_ID, ETH_ALEN, - ETH_ALEN, net->dev_addr); + memcpy(netdev->dev_addr, addr->sa_data, ETH_ALEN); + + ret = ax_write_cmd(axdev, AX_ACCESS_MAC, AX_NODE_ID, ETH_ALEN, + ETH_ALEN, netdev->dev_addr); if (ret < 0) return ret; return 0; } -static const struct net_device_ops ax88179_netdev_ops = { - .ndo_open = usbnet_open, - .ndo_stop = usbnet_stop, - .ndo_start_xmit = usbnet_start_xmit, - .ndo_tx_timeout = usbnet_tx_timeout, - .ndo_get_stats64 = dev_get_tstats64, - .ndo_change_mtu = ax88179_change_mtu, - .ndo_set_mac_address = ax88179_set_mac_addr, - .ndo_validate_addr = eth_validate_addr, - .ndo_eth_ioctl = ax88179_ioctl, - .ndo_set_rx_mode = ax88179_set_multicast, - .ndo_set_features = ax88179_set_features, -}; - -static int ax88179_check_eeprom(struct usbnet *dev) +static int ax88179_check_eeprom(struct ax_device *axdev) { - u8 i, buf, eeprom[20]; - u16 csum, delay = HZ / 10; - unsigned long jtimeout; + u8 i = 0; + u8 buf[2]; + u8 eeprom[20]; + u16 csum = 0, delay = HZ / 10; - /* Read EEPROM content */ - for (i = 0; i < 6; i++) { - buf = i; - if (ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_SROM_ADDR, - 1, 1, &buf) < 0) + for (i = 0 ; i < 6; i++) { + buf[0] = i; + if (ax_write_cmd(axdev, AX_ACCESS_MAC, AX_SROM_ADDR, 1, 1, buf) < 0) return -EINVAL; - buf = EEP_RD; - if (ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_SROM_CMD, - 1, 1, &buf) < 0) + buf[0] = EEP_RD; + if (ax_write_cmd(axdev, AX_ACCESS_MAC, AX_SROM_CMD, 1, 1, buf) < 0) return -EINVAL; - jtimeout = jiffies + delay; do { - ax88179_read_cmd(dev, AX_ACCESS_MAC, AX_SROM_CMD, - 1, 1, &buf); + ax_read_cmd(axdev, AX_ACCESS_MAC, AX_SROM_CMD, 1, 1, buf, 0); - if (time_after(jiffies, jtimeout)) + if (time_after(jiffies, (jiffies + delay))) return -EINVAL; + } while (buf[0] & EEP_BUSY); - } while (buf & EEP_BUSY); + ax_read_cmd(axdev, AX_ACCESS_MAC, AX_SROM_DATA_LOW, 2, 2, &eeprom[i * 2], 0); - __ax88179_read_cmd(dev, AX_ACCESS_MAC, AX_SROM_DATA_LOW, - 2, 2, &eeprom[i * 2], 0); - - if ((i == 0) && (eeprom[0] == 0xFF)) + if (i == 0 && eeprom[0] == 0xFF) return -EINVAL; } csum = eeprom[6] + eeprom[7] + eeprom[8] + eeprom[9]; csum = (csum >> 8) + (csum & 0xff); - if ((csum + eeprom[10]) != 0xff) + + if ((csum + eeprom[10]) == 0xff) + return 0; + else return -EINVAL; return 0; } -static int ax88179_check_efuse(struct usbnet *dev, u16 *ledmode) +static int ax88179_check_efuse(struct ax_device *axdev, void *ledmode) { - u8 i; - u8 efuse[64]; + u8 i = 0; u16 csum = 0; + u8 efuse[64]; - if (ax88179_read_cmd(dev, AX_ACCESS_EFUS, 0, 64, 64, efuse) < 0) + if (ax_read_cmd(axdev, AX_ACCESS_EFUSE, 0, 64, 64, efuse, 0) < 0) return -EINVAL; - if (*efuse == 0xFF) + if (efuse[0] == 0xFF) return -EINVAL; for (i = 0; i < 64; i++) @@ -1101,24 +381,35 @@ static int ax88179_check_efuse(struct usbnet *dev, u16 *ledmode) while (csum > 255) csum = (csum & 0x00FF) + ((csum >> 8) & 0x00FF); - if (csum != 0xFF) + if (csum == 0xFF) { + memcpy((u8 *)ledmode, &efuse[51], 2); + return 0; + } else { return -EINVAL; - - *ledmode = (efuse[51] << 8) | efuse[52]; + } return 0; } -static int ax88179_convert_old_led(struct usbnet *dev, u16 *ledvalue) +static int ax88179_convert_old_led(struct ax_device *axdev, u8 efuse, void *ledvalue) { - u16 led; + u8 ledmode = 0; + u16 reg16; + u16 led = 0; - /* Loaded the old eFuse LED Mode */ - if (ax88179_read_cmd(dev, AX_ACCESS_EEPROM, 0x3C, 1, 2, &led) < 0) - return -EINVAL; + /* loaded the old eFuse LED Mode */ + if (efuse) { + if (ax_read_cmd(axdev, AX_ACCESS_EFUSE, 0x18, 1, 2, ®16, 1) < 0) + return -EINVAL; + ledmode = (u8)(reg16 & 0xFF); + } else { /* loaded the old EEprom LED Mode */ + if (ax_read_cmd(axdev, AX_ACCESS_EEPROM, 0x3C, 1, 2, ®16, 1) < 0) + return -EINVAL; + ledmode = (u8)(reg16 >> 8); + } + netdev_dbg(axdev->netdev, "Old LED Mode = %02X\n", ledmode); - led >>= 8; - switch (led) { + switch (ledmode) { case 0xFF: led = LED0_ACTIVE | LED1_LINK_10 | LED1_LINK_100 | LED1_LINK_1000 | LED2_ACTIVE | LED2_LINK_10 | @@ -1142,841 +433,622 @@ static int ax88179_convert_old_led(struct usbnet *dev, u16 *ledvalue) break; } - *ledvalue = led; + memcpy((u8 *)ledvalue, &led, 2); return 0; } -static int ax88179_led_setting(struct usbnet *dev) +static void ax88179_gether_setting(struct ax_device *axdev) { - u8 ledfd, value = 0; - u16 tmp, ledact, ledlink, ledvalue = 0, delay = HZ / 10; - unsigned long jtimeout; + u16 reg16; - /* Check AX88179 version. UA1 or UA2*/ - ax88179_read_cmd(dev, AX_ACCESS_MAC, GENERAL_STATUS, 1, 1, &value); + reg16 = 0x03; + ax_write_cmd(axdev, AX_ACCESS_PHY, AX88179_PHY_ID, + 31, 2, ®16); + reg16 = 0x3246; + ax_write_cmd(axdev, AX_ACCESS_PHY, AX88179_PHY_ID, + 25, 2, ®16); + reg16 = 0; + ax_write_cmd(axdev, AX_ACCESS_PHY, AX88179_PHY_ID, + 31, 2, ®16); +} - if (!(value & AX_SECLD)) { /* UA1 */ +static int ax88179_LED_setting(struct ax_device *axdev) +{ + u16 ledvalue = 0, delay = HZ / 10; + u16 ledact, ledlink; + u16 reg16; + u8 value; + + ax_read_cmd(axdev, AX_ACCESS_MAC, GENERAL_STATUS, 1, 1, &value, 0); + + if (!(value & AX_SECLD)) { value = AX_GPIO_CTRL_GPIO3EN | AX_GPIO_CTRL_GPIO2EN | AX_GPIO_CTRL_GPIO1EN; - if (ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_GPIO_CTRL, - 1, 1, &value) < 0) + if (ax_write_cmd(axdev, AX_ACCESS_MAC, AX_GPIO_CTRL, + 1, 1, &value) < 0) return -EINVAL; } - /* Check EEPROM */ - if (!ax88179_check_eeprom(dev)) { + if (!ax88179_check_eeprom(axdev)) { value = 0x42; - if (ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_SROM_ADDR, - 1, 1, &value) < 0) + if (ax_write_cmd(axdev, AX_ACCESS_MAC, AX_SROM_ADDR, 1, 1, &value) < 0) return -EINVAL; value = EEP_RD; - if (ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_SROM_CMD, - 1, 1, &value) < 0) + if (ax_write_cmd(axdev, AX_ACCESS_MAC, AX_SROM_CMD, 1, 1, &value) < 0) return -EINVAL; - jtimeout = jiffies + delay; do { - ax88179_read_cmd(dev, AX_ACCESS_MAC, AX_SROM_CMD, - 1, 1, &value); + ax_read_cmd(axdev, AX_ACCESS_MAC, AX_SROM_CMD, 1, 1, &value, 0); - if (time_after(jiffies, jtimeout)) + ax_read_cmd(axdev, AX_ACCESS_MAC, AX_SROM_CMD, 1, 1, &value, 0); + + if (time_after(jiffies, (jiffies + delay))) return -EINVAL; - } while (value & EEP_BUSY); - ax88179_read_cmd(dev, AX_ACCESS_MAC, AX_SROM_DATA_HIGH, - 1, 1, &value); + ax_read_cmd(axdev, AX_ACCESS_MAC, AX_SROM_DATA_HIGH, 1, 1, &value, 0); ledvalue = (value << 8); - - ax88179_read_cmd(dev, AX_ACCESS_MAC, AX_SROM_DATA_LOW, - 1, 1, &value); + ax_read_cmd(axdev, AX_ACCESS_MAC, AX_SROM_DATA_LOW, 1, 1, &value, 0); ledvalue |= value; - /* load internal ROM for defaule setting */ - if ((ledvalue == 0xFFFF) || ((ledvalue & LED_VALID) == 0)) - ax88179_convert_old_led(dev, &ledvalue); + if (ledvalue == 0xFFFF || ((ledvalue & LED_VALID) == 0)) + ax88179_convert_old_led(axdev, 0, &ledvalue); - } else if (!ax88179_check_efuse(dev, &ledvalue)) { - if ((ledvalue == 0xFFFF) || ((ledvalue & LED_VALID) == 0)) - ax88179_convert_old_led(dev, &ledvalue); + } else if (!ax88179_check_efuse(axdev, &ledvalue)) { + if (ledvalue == 0xFFFF || ((ledvalue & LED_VALID) == 0)) + ax88179_convert_old_led(axdev, 0, &ledvalue); } else { - ax88179_convert_old_led(dev, &ledvalue); + ax88179_convert_old_led(axdev, 0, &ledvalue); } - tmp = GMII_PHY_PGSEL_EXT; - ax88179_write_cmd(dev, AX_ACCESS_PHY, AX88179_PHY_ID, - GMII_PHY_PAGE_SELECT, 2, &tmp); + reg16 = GMII_PHY_PAGE_SELECT_EXT; + ax_write_cmd(axdev, AX_ACCESS_PHY, AX88179_PHY_ID, GMII_PHY_PAGE_SELECT, 2, ®16); - tmp = 0x2c; - ax88179_write_cmd(dev, AX_ACCESS_PHY, AX88179_PHY_ID, - GMII_PHYPAGE, 2, &tmp); + reg16 = 0x2c; + ax_write_cmd(axdev, AX_ACCESS_PHY, AX88179_PHY_ID, GMII_PHYPAGE, 2, ®16); - ax88179_read_cmd(dev, AX_ACCESS_PHY, AX88179_PHY_ID, - GMII_LED_ACT, 2, &ledact); + ax_read_cmd(axdev, AX_ACCESS_PHY, AX88179_PHY_ID, GMII_LED_ACTIVE, 2, &ledact, 1); - ax88179_read_cmd(dev, AX_ACCESS_PHY, AX88179_PHY_ID, - GMII_LED_LINK, 2, &ledlink); + ax_read_cmd(axdev, AX_ACCESS_PHY, AX88179_PHY_ID, GMII_LED_LINK, 2, &ledlink, 1); ledact &= GMII_LED_ACTIVE_MASK; ledlink &= GMII_LED_LINK_MASK; if (ledvalue & LED0_ACTIVE) ledact |= GMII_LED0_ACTIVE; - if (ledvalue & LED1_ACTIVE) ledact |= GMII_LED1_ACTIVE; - if (ledvalue & LED2_ACTIVE) ledact |= GMII_LED2_ACTIVE; if (ledvalue & LED0_LINK_10) ledlink |= GMII_LED0_LINK_10; - if (ledvalue & LED1_LINK_10) ledlink |= GMII_LED1_LINK_10; - if (ledvalue & LED2_LINK_10) ledlink |= GMII_LED2_LINK_10; if (ledvalue & LED0_LINK_100) ledlink |= GMII_LED0_LINK_100; - if (ledvalue & LED1_LINK_100) ledlink |= GMII_LED1_LINK_100; - if (ledvalue & LED2_LINK_100) ledlink |= GMII_LED2_LINK_100; if (ledvalue & LED0_LINK_1000) ledlink |= GMII_LED0_LINK_1000; - if (ledvalue & LED1_LINK_1000) ledlink |= GMII_LED1_LINK_1000; - if (ledvalue & LED2_LINK_1000) ledlink |= GMII_LED2_LINK_1000; - tmp = ledact; - ax88179_write_cmd(dev, AX_ACCESS_PHY, AX88179_PHY_ID, - GMII_LED_ACT, 2, &tmp); + ax_write_cmd(axdev, AX_ACCESS_PHY, AX88179_PHY_ID, GMII_LED_ACTIVE, 2, &ledact); - tmp = ledlink; - ax88179_write_cmd(dev, AX_ACCESS_PHY, AX88179_PHY_ID, - GMII_LED_LINK, 2, &tmp); + ax_write_cmd(axdev, AX_ACCESS_PHY, AX88179_PHY_ID, GMII_LED_LINK, 2, &ledlink); - tmp = GMII_PHY_PGSEL_PAGE0; - ax88179_write_cmd(dev, AX_ACCESS_PHY, AX88179_PHY_ID, - GMII_PHY_PAGE_SELECT, 2, &tmp); + reg16 = GMII_PHY_PAGE_SELECT_PAGE0; + ax_write_cmd(axdev, AX_ACCESS_PHY, AX88179_PHY_ID, GMII_PHY_PAGE_SELECT, 2, ®16); /* LED full duplex setting */ - ledfd = 0; + reg16 = 0; if (ledvalue & LED0_FD) - ledfd |= 0x01; + reg16 |= 0x01; else if ((ledvalue & LED0_USB3_MASK) == 0) - ledfd |= 0x02; + reg16 |= 0x02; if (ledvalue & LED1_FD) - ledfd |= 0x04; + reg16 |= 0x04; else if ((ledvalue & LED1_USB3_MASK) == 0) - ledfd |= 0x08; + reg16 |= 0x08; - if (ledvalue & LED2_FD) - ledfd |= 0x10; - else if ((ledvalue & LED2_USB3_MASK) == 0) - ledfd |= 0x20; + if (ledvalue & LED2_FD) /* LED2_FD */ + reg16 |= 0x10; + else if ((ledvalue & LED2_USB3_MASK) == 0) /* LED2_USB3 */ + reg16 |= 0x20; - ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_LEDCTRL, 1, 1, &ledfd); + ax_write_cmd(axdev, AX_ACCESS_MAC, 0x73, 1, 1, ®16); return 0; } -static void ax88179_get_mac_addr(struct usbnet *dev) +static void ax88179_EEE_setting(struct ax_device *axdev) { - u8 mac[ETH_ALEN]; - - memset(mac, 0, sizeof(mac)); - - /* Maybe the boot loader passed the MAC address via device tree */ - if (!eth_platform_get_mac_address(&dev->udev->dev, mac)) { - netif_dbg(dev, ifup, dev->net, - "MAC address read from device tree"); - } else { - ax88179_read_cmd(dev, AX_ACCESS_MAC, AX_NODE_ID, ETH_ALEN, - ETH_ALEN, mac); - netif_dbg(dev, ifup, dev->net, - "MAC address read from ASIX chip"); - } - - if (is_valid_ether_addr(mac)) { - memcpy(dev->net->dev_addr, mac, ETH_ALEN); - } else { - netdev_info(dev->net, "invalid MAC address, using random\n"); - eth_hw_addr_random(dev->net); - } - - ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_NODE_ID, ETH_ALEN, ETH_ALEN, - dev->net->dev_addr); + u16 reg16; + /* Disable */ + reg16 = 0x07; + ax_write_cmd(axdev, AX_ACCESS_PHY, AX88179_PHY_ID, GMII_PHY_MACR, 2, ®16); + reg16 = 0x3c; + ax_write_cmd(axdev, AX_ACCESS_PHY, AX88179_PHY_ID, GMII_PHY_MAADR, 2, ®16); + reg16 = 0x4007; + ax_write_cmd(axdev, AX_ACCESS_PHY, AX88179_PHY_ID, GMII_PHY_MACR, 2, ®16); + reg16 = 0x00; + ax_write_cmd(axdev, AX_ACCESS_PHY, AX88179_PHY_ID, GMII_PHY_MAADR, 2, ®16); } -static int ax88179_bind(struct usbnet *dev, struct usb_interface *intf) +static int ax88179_auto_detach(struct ax_device *axdev, int in_pm) { - u8 buf[5]; - u16 *tmp16; - u8 *tmp; - struct ax88179_data *ax179_data = (struct ax88179_data *)dev->data; - struct ethtool_eee eee_data; + u16 reg16; + usb_read_function fnr; + usb_write_function fnw; - usbnet_get_endpoints(dev, intf); + if (!in_pm) { + fnr = ax_read_cmd; + fnw = ax_write_cmd; + } else { + fnr = ax_read_cmd_nopm; + fnw = ax_write_cmd_nopm; + } - tmp16 = (u16 *)buf; - tmp = (u8 *)buf; + if (fnr(axdev, AX_ACCESS_EEPROM, 0x43, 1, 2, ®16, 1) < 0) + return 0; - memset(ax179_data, 0, sizeof(*ax179_data)); + if (reg16 == 0xFFFF || !(reg16 & 0x0100)) + return 0; - /* Power up ethernet PHY */ - *tmp16 = 0; - ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_PHYPWR_RSTCTL, 2, 2, tmp16); - *tmp16 = AX_PHYPWR_RSTCTL_IPRL; - ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_PHYPWR_RSTCTL, 2, 2, tmp16); + reg16 = 0; + fnr(axdev, AX_ACCESS_MAC, AX_CLK_SELECT, 1, 1, ®16, 0); + reg16 |= AX_CLK_SELECT_ULR; + fnw(axdev, AX_ACCESS_MAC, AX_CLK_SELECT, 1, 1, ®16); + + fnr(axdev, AX_ACCESS_MAC, AX_PHYPWR_RSTCTL, 2, 2, ®16, 1); + reg16 |= AX_PHYPWR_RSTCTL_AUTODETACH; + fnw(axdev, AX_ACCESS_MAC, AX_PHYPWR_RSTCTL, 2, 2, ®16); + + return 0; +} + +static int ax88179_hw_init(struct ax_device *axdev) +{ + u32 reg32; + u16 reg16; + u8 reg8; + u8 buf[6] = {0}; + + reg32 = 0; + ax_write_cmd(axdev, 0x81, 0x310, 0, 4, ®32); + + reg16 = 0; + ax_write_cmd(axdev, AX_ACCESS_MAC, AX_PHYPWR_RSTCTL, 2, 2, ®16); + reg16 = AX_PHYPWR_RSTCTL_IPRL; + ax_write_cmd(axdev, AX_ACCESS_MAC, AX_PHYPWR_RSTCTL, 2, 2, ®16); msleep(200); - *tmp = AX_CLK_SELECT_ACS | AX_CLK_SELECT_BCS; - ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_CLK_SELECT, 1, 1, tmp); + reg8 = AX_CLK_SELECT_ACS | AX_CLK_SELECT_BCS; + ax_write_cmd(axdev, AX_ACCESS_MAC, AX_CLK_SELECT, 1, 1, ®8); msleep(100); - /* Read MAC address from DTB or asix chip */ - ax88179_get_mac_addr(dev); - memcpy(dev->net->perm_addr, dev->net->dev_addr, ETH_ALEN); + ax88179_auto_detach(axdev, 0); - /* RX bulk configuration */ - memcpy(tmp, &AX88179_BULKIN_SIZE[0], 5); - ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_RX_BULKIN_QCTRL, 5, 5, tmp); + memcpy(buf, &AX88179_BULKIN_SIZE[0], 5); + ax_write_cmd(axdev, AX_ACCESS_MAC, AX_RX_BULKIN_QCTRL, 5, 5, buf); - dev->rx_urb_size = 1024 * 20; + reg8 = 0x34; + ax_write_cmd(axdev, AX_ACCESS_MAC, AX_PAUSE_WATERLVL_LOW, 1, 1, ®8); - *tmp = 0x34; - ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_PAUSE_WATERLVL_LOW, 1, 1, tmp); + reg8 = 0x52; + ax_write_cmd(axdev, AX_ACCESS_MAC, AX_PAUSE_WATERLVL_HIGH, 1, 1, ®8); - *tmp = 0x52; - ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_PAUSE_WATERLVL_HIGH, - 1, 1, tmp); + ax_write_cmd(axdev, 0x91, 0, 0, 0, NULL); - dev->net->netdev_ops = &ax88179_netdev_ops; - dev->net->ethtool_ops = &ax88179_ethtool_ops; - dev->net->needed_headroom = 8; - dev->net->max_mtu = 4088; - - /* Initialize MII structure */ - dev->mii.dev = dev->net; - dev->mii.mdio_read = ax88179_mdio_read; - dev->mii.mdio_write = ax88179_mdio_write; - dev->mii.phy_id_mask = 0xff; - dev->mii.reg_num_mask = 0xff; - dev->mii.phy_id = 0x03; - dev->mii.supports_gmii = 1; - - dev->net->features |= NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM | - NETIF_F_RXCSUM; - - dev->net->hw_features |= NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM | - NETIF_F_RXCSUM; - - /* Enable checksum offload */ - *tmp = AX_RXCOE_IP | AX_RXCOE_TCP | AX_RXCOE_UDP | + reg8 = AX_RXCOE_IP | AX_RXCOE_TCP | AX_RXCOE_UDP | AX_RXCOE_TCPV6 | AX_RXCOE_UDPV6; - ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_RXCOE_CTL, 1, 1, tmp); + ax_write_cmd(axdev, AX_ACCESS_MAC, AX_RXCOE_CTL, 1, 1, ®8); - *tmp = AX_TXCOE_IP | AX_TXCOE_TCP | AX_TXCOE_UDP | + reg8 = AX_TXCOE_IP | AX_TXCOE_TCP | AX_TXCOE_UDP | AX_TXCOE_TCPV6 | AX_TXCOE_UDPV6; - ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_TXCOE_CTL, 1, 1, tmp); + ax_write_cmd(axdev, AX_ACCESS_MAC, AX_TXCOE_CTL, 1, 1, ®8); - /* Configure RX control register => start operation */ - *tmp16 = AX_RX_CTL_DROPCRCERR | AX_RX_CTL_IPE | AX_RX_CTL_START | - AX_RX_CTL_AP | AX_RX_CTL_AMALL | AX_RX_CTL_AB; - ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_RX_CTL, 2, 2, tmp16); + reg8 = AX_MONITOR_MODE_PMETYPE | AX_MONITOR_MODE_PMEPOL | + AX_MONITOR_MODE_RWLC | AX_MONITOR_MODE_RWMP; + ax_write_cmd(axdev, AX_ACCESS_MAC, AX_MONITOR_MODE, 1, 1, ®8); - *tmp = AX_MONITOR_MODE_PMETYPE | AX_MONITOR_MODE_PMEPOL | - AX_MONITOR_MODE_RWMP; - ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_MONITOR_MOD, 1, 1, tmp); + ax88179_LED_setting(axdev); - /* Configure default medium type => giga */ - *tmp16 = AX_MEDIUM_RECEIVE_EN | AX_MEDIUM_TXFLOW_CTRLEN | - AX_MEDIUM_RXFLOW_CTRLEN | AX_MEDIUM_FULL_DUPLEX | - AX_MEDIUM_GIGAMODE; - ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_MEDIUM_STATUS_MODE, - 2, 2, tmp16); + ax88179_EEE_setting(axdev); - ax88179_led_setting(dev); + ax88179_gether_setting(axdev); - ax179_data->eee_enabled = 0; - ax179_data->eee_active = 0; + ax_set_tx_qlen(axdev); - ax88179_disable_eee(dev); - - ax88179_ethtool_get_eee(dev, &eee_data); - eee_data.advertised = 0; - ax88179_ethtool_set_eee(dev, &eee_data); - - /* Restart autoneg */ - mii_nway_restart(&dev->mii); - - usbnet_link_change(dev, 0, 0); + mii_nway_restart(&axdev->mii); return 0; } -static void ax88179_unbind(struct usbnet *dev, struct usb_interface *intf) +static int ax88179_bind(struct ax_device *axdev) { - u16 tmp16; + struct net_device *netdev = axdev->netdev; - /* Configure RX control register => stop operation */ - tmp16 = AX_RX_CTL_STOP; - ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_RX_CTL, 2, 2, &tmp16); + ax_print_version(axdev, AX_DRIVER_STRING_179_178A); - tmp16 = 0; - ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_CLK_SELECT, 1, 1, &tmp16); + netdev->features |= NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM | + NETIF_F_SG | NETIF_F_TSO | NETIF_F_FRAGLIST; + netdev->hw_features |= NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM | + NETIF_F_SG | NETIF_F_TSO | NETIF_F_FRAGLIST; - /* Power down ethernet PHY */ - tmp16 = 0; - ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_PHYPWR_RSTCTL, 2, 2, &tmp16); + axdev->tx_casecade_size = TX_CASECADES_SIZE; + axdev->gso_max_size = AX_GSO_DEFAULT_SIZE; + axdev->mii.supports_gmii = 1; + axdev->mii.dev = netdev; + axdev->mii.mdio_read = ax_mdio_read; + axdev->mii.mdio_write = ax_mdio_write; + axdev->mii.phy_id_mask = 0xff; + axdev->mii.reg_num_mask = 0xff; + axdev->mii.phy_id = AX88179_PHY_ID; + axdev->mii.force_media = 0; + axdev->mii.advertising = ADVERTISE_10HALF | ADVERTISE_10FULL | + ADVERTISE_100HALF | ADVERTISE_100FULL; + netif_set_gso_max_size(netdev, axdev->gso_max_size); + + axdev->bin_setting.custom = 1; + axdev->tx_align_len = 4; + + netdev->ethtool_ops = &ax88179_ethtool_ops; + axdev->netdev->netdev_ops = &ax88179_netdev_ops; + + return 0; } -static void -ax88179_rx_checksum(struct sk_buff *skb, u32 *pkt_hdr) +static void ax88179_unbind(struct ax_device *axdev) +{ +} + +static int ax88179_stop(struct ax_device *axdev) +{ + u16 reg16; + + reg16 = AX_RX_CTL_STOP; + ax_write_cmd(axdev, AX_ACCESS_MAC, AX_MEDIUM_STATUS_MODE, 2, 2, ®16); + + reg16 = 0; + ax_write_cmd(axdev, AX_ACCESS_MAC, AX_CLK_SELECT, 1, 1, ®16); + + reg16 = AX_PHYPWR_RSTCTL_BZ; + ax_write_cmd(axdev, AX_ACCESS_MAC, AX_PHYPWR_RSTCTL, 2, 2, ®16); + msleep(200); + + return 0; +} + +static int ax88179_link_reset(struct ax_device *axdev) +{ + u8 reg8[5], link_sts; + u16 mode, reg16, delay; + u32 reg32; + + mode = AX_MEDIUM_TXFLOW_CTRLEN | AX_MEDIUM_RXFLOW_CTRLEN; + + ax_read_cmd_nopm(axdev, AX_ACCESS_MAC, PHYSICAL_LINK_STATUS, + 1, 1, &link_sts, 0); + ax_read_cmd_nopm(axdev, AX_ACCESS_PHY, AX88179_PHY_ID, + GMII_PHY_PHYSR, 2, ®16, 1); + + if (!(reg16 & GMII_PHY_PHYSR_LINK)) { + return -1; + } else if (GMII_PHY_PHYSR_GIGA == (reg16 & GMII_PHY_PHYSR_SMASK)) { + mode |= AX_MEDIUM_GIGAMODE; + if (axdev->netdev->mtu > 1500) + mode |= AX_MEDIUM_JUMBO_EN; + + if (link_sts & AX_USB_SS) + memcpy(reg8, &AX88179_BULKIN_SIZE[0], 5); + else if (link_sts & AX_USB_HS) + memcpy(reg8, &AX88179_BULKIN_SIZE[1], 5); + else + memcpy(reg8, &AX88179_BULKIN_SIZE[3], 5); + } else if (GMII_PHY_PHYSR_100 == (reg16 & GMII_PHY_PHYSR_SMASK)) { + mode |= AX_MEDIUM_PS; + if (link_sts & (AX_USB_SS | AX_USB_HS)) + memcpy(reg8, &AX88179_BULKIN_SIZE[2], 5); + else + memcpy(reg8, &AX88179_BULKIN_SIZE[3], 5); + } else { + memcpy(reg8, &AX88179_BULKIN_SIZE[3], 5); + } + + ax_write_cmd_nopm(axdev, AX_ACCESS_MAC, AX_RX_BULKIN_QCTRL, 5, 5, reg8); + + if (reg16 & GMII_PHY_PHYSR_FULL) + mode |= AX_MEDIUM_FULL_DUPLEX; + + ax_read_cmd_nopm(axdev, 0x81, 0x8c, 0, 4, ®32, 1); + delay = HZ / 2; + if (reg32 & 0x40000000) { + unsigned long jtimeout; + u16 temp16 = 0; + + ax_write_cmd_nopm(axdev, AX_ACCESS_MAC, AX_RX_CTL, + 2, 2, &temp16); + ax_write_cmd_nopm(axdev, AX_ACCESS_MAC, AX_MEDIUM_STATUS_MODE, + 2, 2, &mode); + + jtimeout = jiffies + delay; + while (time_before(jiffies, jtimeout)) { + ax_read_cmd_nopm(axdev, 0x81, 0x8c, 0, 4, ®32, 1); + + if (!(reg32 & 0x40000000)) + break; + + reg32 = 0x80000000; + ax_write_cmd(axdev, 0x81, 0x8c, 0, 4, ®32); + } + + temp16 = AX_RX_CTL_DROPCRCERR | AX_RX_CTL_START | + AX_RX_CTL_AP | AX_RX_CTL_AMALL | AX_RX_CTL_AB; + ax_write_cmd_nopm(axdev, AX_ACCESS_MAC, AX_RX_CTL, + 2, 2, &temp16); + } + + axdev->rxctl |= AX_RX_CTL_DROPCRCERR | AX_RX_CTL_START | AX_RX_CTL_AB; + ax_write_cmd_nopm(axdev, AX_ACCESS_MAC, AX_RX_CTL, + 2, 2, &axdev->rxctl); + + mode |= AX_MEDIUM_RECEIVE_EN; + ax_write_cmd_nopm(axdev, AX_ACCESS_MAC, AX_MEDIUM_STATUS_MODE, + 2, 2, &mode); + + return 0; +} + +static int ax88179_tx_fixup(struct ax_device *axdev, struct tx_desc *desc) +{ + struct sk_buff_head skb_head, *tx_queue = &axdev->tx_queue[0]; + struct net_device_stats *stats = &axdev->netdev->stats; + int remain, ret; + u8 *tx_data; + + __skb_queue_head_init(&skb_head); + spin_lock(&tx_queue->lock); + skb_queue_splice_init(tx_queue, &skb_head); + spin_unlock(&tx_queue->lock); + + tx_data = desc->head; + desc->skb_num = 0; + desc->skb_len = 0; + remain = axdev->tx_casecade_size; + + while (remain >= ETH_ZLEN + 8) { + struct sk_buff *skb; + u32 *tx_hdr1, *tx_hdr2; + + skb = __skb_dequeue(&skb_head); + if (!skb) + break; + + if ((skb->len + AX_TX_HEADER_LEN) > remain && + (skb_shinfo(skb)->gso_size == 0)) { + __skb_queue_head(&skb_head, skb); + break; + } + + memset(tx_data, 0, AX_TX_HEADER_LEN); + tx_hdr1 = (u32 *)tx_data; + tx_hdr2 = tx_hdr1 + 1; + *tx_hdr1 = skb->len; + *tx_hdr2 = skb_shinfo(skb)->gso_size; + cpu_to_le32s(tx_hdr1); + cpu_to_le32s(tx_hdr2); + tx_data += 8; + + if (skb_copy_bits(skb, 0, tx_data, skb->len) < 0) { + stats->tx_dropped++; + dev_kfree_skb_any(skb); + continue; + } + + tx_data += skb->len; + desc->skb_len += skb->len; + desc->skb_num += skb_shinfo(skb)->gso_segs ?: 1; + dev_kfree_skb_any(skb); + + tx_data = __tx_buf_align(tx_data, axdev->tx_align_len); + if (*tx_hdr2 > 0) + break; + remain = axdev->tx_casecade_size - + (int)((void *)tx_data - desc->head); + } + + if (!skb_queue_empty(&skb_head)) { + spin_lock(&tx_queue->lock); + skb_queue_splice(&skb_head, tx_queue); + spin_unlock(&tx_queue->lock); + } + + netif_tx_lock(axdev->netdev); + + if (netif_queue_stopped(axdev->netdev) && + skb_queue_len(tx_queue) < axdev->tx_qlen) { + netif_wake_queue(axdev->netdev); + } + + netif_tx_unlock(axdev->netdev); + + ret = usb_autopm_get_interface_async(axdev->intf); + if (ret < 0) + goto out_tx_fill; + + usb_fill_bulk_urb(desc->urb, axdev->udev, + usb_sndbulkpipe(axdev->udev, 3), + desc->head, (int)(tx_data - (u8 *)desc->head), + (usb_complete_t)ax_write_bulk_callback, desc); + + ret = usb_submit_urb(desc->urb, GFP_ATOMIC); + if (ret < 0) + usb_autopm_put_interface_async(axdev->intf); + +out_tx_fill: + return ret; +} + +static void ax88179_rx_checksum(struct sk_buff *skb, u32 *pkt_hdr) { skb->ip_summed = CHECKSUM_NONE; - /* checksum error bit is set */ if ((*pkt_hdr & AX_RXHDR_L3CSUM_ERR) || (*pkt_hdr & AX_RXHDR_L4CSUM_ERR)) return; - /* It must be a TCP or UDP packet with a valid checksum */ if (((*pkt_hdr & AX_RXHDR_L4_TYPE_MASK) == AX_RXHDR_L4_TYPE_TCP) || ((*pkt_hdr & AX_RXHDR_L4_TYPE_MASK) == AX_RXHDR_L4_TYPE_UDP)) skb->ip_summed = CHECKSUM_UNNECESSARY; } -static int ax88179_rx_fixup(struct usbnet *dev, struct sk_buff *skb) +static void ax88179_rx_fixup +(struct ax_device *axdev, struct rx_desc *desc, int *work_done, int budget) { - struct sk_buff *ax_skb; - int pkt_cnt; - u32 rx_hdr; - u16 hdr_off; - u32 *pkt_hdr; + u8 *rx_data; + u32 const actual_length = desc->urb->actual_length; + u32 rx_hdr = 0, pkt_hdr = 0, pkt_hdr_curr = 0, hdr_off = 0; + u32 aa = 0; + int pkt_cnt = 0; + struct net_device *netdev = axdev->netdev; + struct net_device_stats *stats = ax_get_stats(netdev); - /* At the end of the SKB, there's a header telling us how many packets - * are bundled into this buffer and where we can find an array of - * per-packet metadata (which contains elements encoded into u16). - */ + memcpy(&rx_hdr, (((u8 *)desc->head) + actual_length - 4), + sizeof(rx_hdr)); + le32_to_cpus(&rx_hdr); - /* SKB contents for current firmware: - * - * ... - * - * - * ... - * - * - * - * where: - * contains pkt_len bytes: - * 2 bytes of IP alignment pseudo header - * packet received - * contains 4 bytes: - * pkt_len and fields AX_RXHDR_* - * 0-7 bytes to terminate at - * 8 bytes boundary (64-bit). - * 4 bytes to make rx_hdr terminate at - * 8 bytes boundary (64-bit) - * contains 4 bytes: - * pkt_len=0 and AX_RXHDR_DROP_ERR - * contains 4 bytes: - * pkt_cnt and hdr_off (offset of - * ) - * - * pkt_cnt is number of entrys in the per-packet metadata. - * In current firmware there is 2 entrys per packet. - * The first points to the packet and the - * second is a dummy header. - * This was done probably to align fields in 64-bit and - * maintain compatibility with old firmware. - * This code assumes that and are - * optional. - */ + pkt_cnt = rx_hdr & 0xFF; + hdr_off = rx_hdr >> 16; + pkt_hdr_curr = hdr_off; - if (skb->len < 4) - return 0; - skb_trim(skb, skb->len - 4); - rx_hdr = get_unaligned_le32(skb_tail_pointer(skb)); - pkt_cnt = (u16)rx_hdr; - hdr_off = (u16)(rx_hdr >> 16); - - if (pkt_cnt == 0) - return 0; - - /* Make sure that the bounds of the metadata array are inside the SKB - * (and in front of the counter at the end). - */ - if (pkt_cnt * 4 + hdr_off > skb->len) - return 0; - pkt_hdr = (u32 *)(skb->data + hdr_off); - - /* Packets must not overlap the metadata array */ - skb_trim(skb, hdr_off); - - for (; pkt_cnt > 0; pkt_cnt--, pkt_hdr++) { - u16 pkt_len_plus_padd; - u16 pkt_len; - - le32_to_cpus(pkt_hdr); - pkt_len = (*pkt_hdr >> 16) & 0x1fff; - pkt_len_plus_padd = (pkt_len + 7) & 0xfff8; - - /* Skip dummy header used for alignment - */ - if (pkt_len == 0) - continue; - - if (pkt_len_plus_padd > skb->len) - return 0; - - /* Check CRC or runt packet */ - if ((*pkt_hdr & (AX_RXHDR_CRC_ERR | AX_RXHDR_DROP_ERR)) || - pkt_len < 2 + ETH_HLEN) { - dev->net->stats.rx_errors++; - skb_pull(skb, pkt_len_plus_padd); - continue; - } - - /* last packet */ - if (pkt_len_plus_padd == skb->len) { - skb_trim(skb, pkt_len); - - /* Skip IP alignment pseudo header */ - skb_pull(skb, 2); - - skb->truesize = SKB_TRUESIZE(pkt_len_plus_padd); - ax88179_rx_checksum(skb, pkt_hdr); - return 1; - } - - ax_skb = skb_clone(skb, GFP_ATOMIC); - if (!ax_skb) - return 0; - skb_trim(ax_skb, pkt_len); - - /* Skip IP alignment pseudo header */ - skb_pull(ax_skb, 2); - - skb->truesize = pkt_len_plus_padd + - SKB_DATA_ALIGN(sizeof(struct sk_buff)); - ax88179_rx_checksum(ax_skb, pkt_hdr); - usbnet_skb_return(dev, ax_skb); - - skb_pull(skb, pkt_len_plus_padd); + aa = (actual_length - (((pkt_cnt + 2) & 0xFE) * 4)); + if (aa != hdr_off || + hdr_off >= desc->urb->actual_length || + pkt_cnt == 0) { + desc->urb->actual_length = 0; + stats->rx_length_errors++; + return; } + rx_data = desc->head; + while (pkt_cnt--) { + u32 pkt_len; + struct sk_buff *skb; + + memcpy(&pkt_hdr, (((u8 *)desc->head) + pkt_hdr_curr), + sizeof(pkt_hdr)); + pkt_hdr_curr += 4; + + le32_to_cpus(&pkt_hdr); + pkt_len = (pkt_hdr >> 16) & 0x1FFF; + + if (pkt_hdr & AX_RXHDR_CRC_ERR) { + stats->rx_crc_errors++; + goto find_next_rx; + } + if (pkt_hdr & AX_RXHDR_DROP_ERR) { + stats->rx_dropped++; + goto find_next_rx; + } + + skb = napi_alloc_skb(napi, pkt_len); + if (!skb) { + stats->rx_dropped++; + goto find_next_rx; + } + + memcpy(skb->data, rx_data, pkt_len); + skb_put(skb, pkt_len); + + ax88179_rx_checksum(skb, &pkt_hdr); + + skb->protocol = eth_type_trans(skb, netdev); + + if (*work_done < budget) { + napi_gro_receive(&axdev->napi, skb); + *work_done += 1; + stats->rx_packets++; + stats->rx_bytes += pkt_len; + } else { + __skb_queue_tail(&axdev->rx_queue, skb); + } +find_next_rx: + rx_data += (pkt_len + 7) & 0xFFF8; + } +} + +static int ax88179_system_suspend(struct ax_device *axdev) +{ + u16 reg16; + + ax_read_cmd_nopm(axdev, AX_ACCESS_MAC, AX_MEDIUM_STATUS_MODE, + 2, 2, ®16, 1); + reg16 &= ~AX_MEDIUM_RECEIVE_EN; + ax_write_cmd_nopm(axdev, AX_ACCESS_MAC, AX_MEDIUM_STATUS_MODE, + 2, 2, ®16); + + ax_read_cmd_nopm(axdev, AX_ACCESS_MAC, AX_PHYPWR_RSTCTL, + 2, 2, ®16, 1); + reg16 |= AX_PHYPWR_RSTCTL_IPRL; + ax_write_cmd_nopm(axdev, AX_ACCESS_MAC, AX_PHYPWR_RSTCTL, + 2, 2, ®16); + + reg16 = AX_RX_CTL_STOP; + ax_write_cmd_nopm(axdev, AX_ACCESS_MAC, AX_RX_CTL, 2, 2, ®16); + return 0; } -static struct sk_buff * -ax88179_tx_fixup(struct usbnet *dev, struct sk_buff *skb, gfp_t flags) +static int ax88179_system_resume(struct ax_device *axdev) { - u32 tx_hdr1, tx_hdr2; - int frame_size = dev->maxpacket; - int mss = skb_shinfo(skb)->gso_size; - int headroom; - void *ptr; + u16 reg16; + u8 reg8; - tx_hdr1 = skb->len; - tx_hdr2 = mss; - if (((skb->len + 8) % frame_size) == 0) - tx_hdr2 |= 0x80008000; /* Enable padding */ + reg16 = 0; + ax_write_cmd_nopm(axdev, AX_ACCESS_MAC, AX_PHYPWR_RSTCTL, 2, 2, ®16); + usleep_range(1000, 2000); - headroom = skb_headroom(skb) - 8; - - if ((skb_header_cloned(skb) || headroom < 0) && - pskb_expand_head(skb, headroom < 0 ? 8 : 0, 0, GFP_ATOMIC)) { - dev_kfree_skb_any(skb); - return NULL; - } - - ptr = skb_push(skb, 8); - put_unaligned_le32(tx_hdr1, ptr); - put_unaligned_le32(tx_hdr2, ptr + 4); - - return skb; -} - -static int ax88179_link_reset(struct usbnet *dev) -{ - struct ax88179_data *ax179_data = (struct ax88179_data *)dev->data; - u8 tmp[5], link_sts; - u16 mode, tmp16, delay = HZ / 10; - u32 tmp32 = 0x40000000; - unsigned long jtimeout; - - jtimeout = jiffies + delay; - while (tmp32 & 0x40000000) { - mode = 0; - ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_RX_CTL, 2, 2, &mode); - ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_RX_CTL, 2, 2, - &ax179_data->rxctl); - - /*link up, check the usb device control TX FIFO full or empty*/ - ax88179_read_cmd(dev, 0x81, 0x8c, 0, 4, &tmp32); - - if (time_after(jiffies, jtimeout)) - return 0; - } - - mode = AX_MEDIUM_RECEIVE_EN | AX_MEDIUM_TXFLOW_CTRLEN | - AX_MEDIUM_RXFLOW_CTRLEN; - - ax88179_read_cmd(dev, AX_ACCESS_MAC, PHYSICAL_LINK_STATUS, - 1, 1, &link_sts); - - ax88179_read_cmd(dev, AX_ACCESS_PHY, AX88179_PHY_ID, - GMII_PHY_PHYSR, 2, &tmp16); - - if (!(tmp16 & GMII_PHY_PHYSR_LINK)) { - return 0; - } else if (GMII_PHY_PHYSR_GIGA == (tmp16 & GMII_PHY_PHYSR_SMASK)) { - mode |= AX_MEDIUM_GIGAMODE | AX_MEDIUM_EN_125MHZ; - if (dev->net->mtu > 1500) - mode |= AX_MEDIUM_JUMBO_EN; - - if (link_sts & AX_USB_SS) - memcpy(tmp, &AX88179_BULKIN_SIZE[0], 5); - else if (link_sts & AX_USB_HS) - memcpy(tmp, &AX88179_BULKIN_SIZE[1], 5); - else - memcpy(tmp, &AX88179_BULKIN_SIZE[3], 5); - } else if (GMII_PHY_PHYSR_100 == (tmp16 & GMII_PHY_PHYSR_SMASK)) { - mode |= AX_MEDIUM_PS; - - if (link_sts & (AX_USB_SS | AX_USB_HS)) - memcpy(tmp, &AX88179_BULKIN_SIZE[2], 5); - else - memcpy(tmp, &AX88179_BULKIN_SIZE[3], 5); - } else { - memcpy(tmp, &AX88179_BULKIN_SIZE[3], 5); - } - - /* RX bulk configuration */ - ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_RX_BULKIN_QCTRL, 5, 5, tmp); - - dev->rx_urb_size = (1024 * (tmp[3] + 2)); - - if (tmp16 & GMII_PHY_PHYSR_FULL) - mode |= AX_MEDIUM_FULL_DUPLEX; - ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_MEDIUM_STATUS_MODE, - 2, 2, &mode); - - ax179_data->eee_enabled = ax88179_chk_eee(dev); - - netif_carrier_on(dev->net); - - return 0; -} - -static int ax88179_reset(struct usbnet *dev) -{ - u8 buf[5]; - u16 *tmp16; - u8 *tmp; - struct ax88179_data *ax179_data = (struct ax88179_data *)dev->data; - struct ethtool_eee eee_data; - - tmp16 = (u16 *)buf; - tmp = (u8 *)buf; - - /* Power up ethernet PHY */ - *tmp16 = 0; - ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_PHYPWR_RSTCTL, 2, 2, tmp16); - - *tmp16 = AX_PHYPWR_RSTCTL_IPRL; - ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_PHYPWR_RSTCTL, 2, 2, tmp16); + reg16 = AX_PHYPWR_RSTCTL_IPRL; + ax_write_cmd_nopm(axdev, AX_ACCESS_MAC, AX_PHYPWR_RSTCTL, 2, 2, ®16); msleep(200); - *tmp = AX_CLK_SELECT_ACS | AX_CLK_SELECT_BCS; - ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_CLK_SELECT, 1, 1, tmp); + ax88179_auto_detach(axdev, 1); + + ax_read_cmd_nopm(axdev, AX_ACCESS_MAC, AX_CLK_SELECT, 1, 1, ®8, 0); + reg8 |= AX_CLK_SELECT_ACS | AX_CLK_SELECT_BCS; + ax_write_cmd_nopm(axdev, AX_ACCESS_MAC, AX_CLK_SELECT, 1, 1, ®8); msleep(100); - /* Ethernet PHY Auto Detach*/ - ax88179_auto_detach(dev, 0); - - /* Read MAC address from DTB or asix chip */ - ax88179_get_mac_addr(dev); - - /* RX bulk configuration */ - memcpy(tmp, &AX88179_BULKIN_SIZE[0], 5); - ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_RX_BULKIN_QCTRL, 5, 5, tmp); - - dev->rx_urb_size = 1024 * 20; - - *tmp = 0x34; - ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_PAUSE_WATERLVL_LOW, 1, 1, tmp); - - *tmp = 0x52; - ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_PAUSE_WATERLVL_HIGH, - 1, 1, tmp); - - dev->net->features |= NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM | - NETIF_F_RXCSUM; - - dev->net->hw_features |= NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM | - NETIF_F_RXCSUM; - - /* Enable checksum offload */ - *tmp = AX_RXCOE_IP | AX_RXCOE_TCP | AX_RXCOE_UDP | - AX_RXCOE_TCPV6 | AX_RXCOE_UDPV6; - ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_RXCOE_CTL, 1, 1, tmp); - - *tmp = AX_TXCOE_IP | AX_TXCOE_TCP | AX_TXCOE_UDP | - AX_TXCOE_TCPV6 | AX_TXCOE_UDPV6; - ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_TXCOE_CTL, 1, 1, tmp); - - /* Configure RX control register => start operation */ - *tmp16 = AX_RX_CTL_DROPCRCERR | AX_RX_CTL_IPE | AX_RX_CTL_START | - AX_RX_CTL_AP | AX_RX_CTL_AMALL | AX_RX_CTL_AB; - ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_RX_CTL, 2, 2, tmp16); - - *tmp = AX_MONITOR_MODE_PMETYPE | AX_MONITOR_MODE_PMEPOL | - AX_MONITOR_MODE_RWMP; - ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_MONITOR_MOD, 1, 1, tmp); - - /* Configure default medium type => giga */ - *tmp16 = AX_MEDIUM_RECEIVE_EN | AX_MEDIUM_TXFLOW_CTRLEN | - AX_MEDIUM_RXFLOW_CTRLEN | AX_MEDIUM_FULL_DUPLEX | - AX_MEDIUM_GIGAMODE; - ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_MEDIUM_STATUS_MODE, - 2, 2, tmp16); - - ax88179_led_setting(dev); - - ax179_data->eee_enabled = 0; - ax179_data->eee_active = 0; - - ax88179_disable_eee(dev); - - ax88179_ethtool_get_eee(dev, &eee_data); - eee_data.advertised = 0; - ax88179_ethtool_set_eee(dev, &eee_data); - - /* Restart autoneg */ - mii_nway_restart(&dev->mii); - - usbnet_link_change(dev, 0, 0); + reg16 = AX_RX_CTL_START | AX_RX_CTL_AP | + AX_RX_CTL_AMALL | AX_RX_CTL_AB; + ax_write_cmd_nopm(axdev, AX_ACCESS_MAC, AX_RX_CTL, 2, 2, ®16); return 0; } -static int ax88179_stop(struct usbnet *dev) -{ - u16 tmp16; - - ax88179_read_cmd(dev, AX_ACCESS_MAC, AX_MEDIUM_STATUS_MODE, - 2, 2, &tmp16); - tmp16 &= ~AX_MEDIUM_RECEIVE_EN; - ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_MEDIUM_STATUS_MODE, - 2, 2, &tmp16); - - return 0; -} - -static const struct driver_info ax88179_info = { - .description = "ASIX AX88179 USB 3.0 Gigabit Ethernet", +const struct driver_info ax88179_info = { .bind = ax88179_bind, .unbind = ax88179_unbind, - .status = ax88179_status, - .link_reset = ax88179_link_reset, - .reset = ax88179_reset, + .hw_init = ax88179_hw_init, .stop = ax88179_stop, - .flags = FLAG_ETHER | FLAG_FRAMING_AX, - .rx_fixup = ax88179_rx_fixup, - .tx_fixup = ax88179_tx_fixup, -}; - -static const struct driver_info ax88178a_info = { - .description = "ASIX AX88178A USB 2.0 Gigabit Ethernet", - .bind = ax88179_bind, - .unbind = ax88179_unbind, - .status = ax88179_status, .link_reset = ax88179_link_reset, - .reset = ax88179_reset, - .stop = ax88179_stop, - .flags = FLAG_ETHER | FLAG_FRAMING_AX, .rx_fixup = ax88179_rx_fixup, .tx_fixup = ax88179_tx_fixup, + .system_suspend = ax88179_system_suspend, + .system_resume = ax88179_system_resume, + .napi_weight = AX88179_NAPI_WEIGHT, + .buf_rx_size = AX88179_BUF_RX_SIZE, }; - -static const struct driver_info cypress_GX3_info = { - .description = "Cypress GX3 SuperSpeed to Gigabit Ethernet Controller", - .bind = ax88179_bind, - .unbind = ax88179_unbind, - .status = ax88179_status, - .link_reset = ax88179_link_reset, - .reset = ax88179_reset, - .stop = ax88179_stop, - .flags = FLAG_ETHER | FLAG_FRAMING_AX, - .rx_fixup = ax88179_rx_fixup, - .tx_fixup = ax88179_tx_fixup, -}; - -static const struct driver_info dlink_dub1312_info = { - .description = "D-Link DUB-1312 USB 3.0 to Gigabit Ethernet Adapter", - .bind = ax88179_bind, - .unbind = ax88179_unbind, - .status = ax88179_status, - .link_reset = ax88179_link_reset, - .reset = ax88179_reset, - .stop = ax88179_stop, - .flags = FLAG_ETHER | FLAG_FRAMING_AX, - .rx_fixup = ax88179_rx_fixup, - .tx_fixup = ax88179_tx_fixup, -}; - -static const struct driver_info sitecom_info = { - .description = "Sitecom USB 3.0 to Gigabit Adapter", - .bind = ax88179_bind, - .unbind = ax88179_unbind, - .status = ax88179_status, - .link_reset = ax88179_link_reset, - .reset = ax88179_reset, - .stop = ax88179_stop, - .flags = FLAG_ETHER | FLAG_FRAMING_AX, - .rx_fixup = ax88179_rx_fixup, - .tx_fixup = ax88179_tx_fixup, -}; - -static const struct driver_info samsung_info = { - .description = "Samsung USB Ethernet Adapter", - .bind = ax88179_bind, - .unbind = ax88179_unbind, - .status = ax88179_status, - .link_reset = ax88179_link_reset, - .reset = ax88179_reset, - .stop = ax88179_stop, - .flags = FLAG_ETHER | FLAG_FRAMING_AX, - .rx_fixup = ax88179_rx_fixup, - .tx_fixup = ax88179_tx_fixup, -}; - -static const struct driver_info lenovo_info = { - .description = "Lenovo OneLinkDock Gigabit LAN", - .bind = ax88179_bind, - .unbind = ax88179_unbind, - .status = ax88179_status, - .link_reset = ax88179_link_reset, - .reset = ax88179_reset, - .stop = ax88179_stop, - .flags = FLAG_ETHER | FLAG_FRAMING_AX, - .rx_fixup = ax88179_rx_fixup, - .tx_fixup = ax88179_tx_fixup, -}; - -static const struct driver_info belkin_info = { - .description = "Belkin USB Ethernet Adapter", - .bind = ax88179_bind, - .unbind = ax88179_unbind, - .status = ax88179_status, - .link_reset = ax88179_link_reset, - .reset = ax88179_reset, - .stop = ax88179_stop, - .flags = FLAG_ETHER | FLAG_FRAMING_AX, - .rx_fixup = ax88179_rx_fixup, - .tx_fixup = ax88179_tx_fixup, -}; - -static const struct driver_info toshiba_info = { - .description = "Toshiba USB Ethernet Adapter", - .bind = ax88179_bind, - .unbind = ax88179_unbind, - .status = ax88179_status, - .link_reset = ax88179_link_reset, - .reset = ax88179_reset, - .stop = ax88179_stop, - .flags = FLAG_ETHER | FLAG_FRAMING_AX, - .rx_fixup = ax88179_rx_fixup, - .tx_fixup = ax88179_tx_fixup, -}; - -static const struct driver_info mct_info = { - .description = "MCT USB 3.0 Gigabit Ethernet Adapter", - .bind = ax88179_bind, - .unbind = ax88179_unbind, - .status = ax88179_status, - .link_reset = ax88179_link_reset, - .reset = ax88179_reset, - .stop = ax88179_stop, - .flags = FLAG_ETHER | FLAG_FRAMING_AX, - .rx_fixup = ax88179_rx_fixup, - .tx_fixup = ax88179_tx_fixup, -}; - -static const struct usb_device_id products[] = { -{ - /* ASIX AX88179 10/100/1000 */ - USB_DEVICE(0x0b95, 0x1790), - .driver_info = (unsigned long)&ax88179_info, -}, { - /* ASIX AX88178A 10/100/1000 */ - USB_DEVICE(0x0b95, 0x178a), - .driver_info = (unsigned long)&ax88178a_info, -}, { - /* Cypress GX3 SuperSpeed to Gigabit Ethernet Bridge Controller */ - USB_DEVICE(0x04b4, 0x3610), - .driver_info = (unsigned long)&cypress_GX3_info, -}, { - /* D-Link DUB-1312 USB 3.0 to Gigabit Ethernet Adapter */ - USB_DEVICE(0x2001, 0x4a00), - .driver_info = (unsigned long)&dlink_dub1312_info, -}, { - /* Sitecom USB 3.0 to Gigabit Adapter */ - USB_DEVICE(0x0df6, 0x0072), - .driver_info = (unsigned long)&sitecom_info, -}, { - /* Samsung USB Ethernet Adapter */ - USB_DEVICE(0x04e8, 0xa100), - .driver_info = (unsigned long)&samsung_info, -}, { - /* Lenovo OneLinkDock Gigabit LAN */ - USB_DEVICE(0x17ef, 0x304b), - .driver_info = (unsigned long)&lenovo_info, -}, { - /* Belkin B2B128 USB 3.0 Hub + Gigabit Ethernet Adapter */ - USB_DEVICE(0x050d, 0x0128), - .driver_info = (unsigned long)&belkin_info, -}, { - /* Toshiba USB 3.0 GBit Ethernet Adapter */ - USB_DEVICE(0x0930, 0x0a13), - .driver_info = (unsigned long)&toshiba_info, -}, { - /* Magic Control Technology U3-A9003 USB 3.0 Gigabit Ethernet Adapter */ - USB_DEVICE(0x0711, 0x0179), - .driver_info = (unsigned long)&mct_info, -}, - { }, -}; -MODULE_DEVICE_TABLE(usb, products); - -static struct usb_driver ax88179_178a_driver = { - .name = "ax88179_178a", - .id_table = products, - .probe = usbnet_probe, - .suspend = ax88179_suspend, - .resume = ax88179_resume, - .reset_resume = ax88179_resume, - .disconnect = usbnet_disconnect, - .supports_autosuspend = 1, - .disable_hub_initiated_lpm = 1, -}; - -module_usb_driver(ax88179_178a_driver); - -MODULE_DESCRIPTION("ASIX AX88179/178A based USB 3.0/2.0 Gigabit Ethernet Devices"); -MODULE_LICENSE("GPL"); diff --git a/drivers/net/usb/ax88179_178a.h b/drivers/net/usb/ax88179_178a.h new file mode 100644 index 000000000000..7a83c4f84b69 --- /dev/null +++ b/drivers/net/usb/ax88179_178a.h @@ -0,0 +1,31 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/******************************************************************************* + * Copyright (c) 2022 ASIX Electronic Corporation All rights reserved. + * + * This program is free software: you can redistribute it and/or modify it under + * the terms of the GNU General Public License as published by the Free Software + * Foundation, either version 2 of the License, or (at your option) any later + * version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details + * + * You should have received a copy of the GNU General Public License along with + * this program. If not, see . + ******************************************************************************/ +#ifndef __ASIX_AX88179_178A_H +#define __ASIX_AX88179_178A_H + +#define AX88179_NAPI_WEIGHT 64 +#define AX88179_BUF_RX_SIZE (48 * 1024) +#define AX88179_PHY_ID 0x03 + +extern const struct net_device_ops ax88179_netdev_ops; +int ax88179_siocdevprivate(struct net_device *netdev, struct ifreq *rq, + void __user *udata, int cmd); +int ax88179_ioctl(struct net_device *net, struct ifreq *rq, int cmd); +int ax88179_set_mac_addr(struct net_device *net, void *p); +void ax88179_set_multicast(struct net_device *net); +extern const struct driver_info ax88179_info; +#endif diff --git a/drivers/net/usb/ax88179a_772d.c b/drivers/net/usb/ax88179a_772d.c new file mode 100644 index 000000000000..c53a0b3a534b --- /dev/null +++ b/drivers/net/usb/ax88179a_772d.c @@ -0,0 +1,1231 @@ +// SPDX-License-Identifier: GPL-2.0 +/******************************************************************************* + * Copyright (c) 2022 ASIX Electronic Corporation All rights reserved. + * + * This program is free software: you can redistribute it and/or modify it under + * the terms of the GNU General Public License as published by the Free Software + * Foundation, either version 2 of the License, or (at your option) any later + * version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details + * + * You should have received a copy of the GNU General Public License along with + * this program. If not, see . + ******************************************************************************/ +#include "ax_main.h" +#include "ax88179a_772d.h" + +struct _ax_buikin_setting AX88179A_BULKIN_SIZE[] = { + {5, 0x7B, 0x00, 0x18, 0x0F}, //1G, SS + {5, 0xC0, 0x02, 0x06, 0x0F}, //1G, HS + {7, 0xF0, 0x00, 0x0C, 0x0F}, //100M, Full, SS + {6, 0x00, 0x00, 0x06, 0x0F}, //100M, Half, SS + {5, 0xC0, 0x04, 0x06, 0x0F}, //100M, Full, HS + {7, 0xC0, 0x04, 0x06, 0x0F}, //100M, Half, HS + {7, 0x00, 0, 0x03, 0x3F}, //FS +}; + +static int ax88179a_chk_eee(struct ax_device *axdev) +{ + struct ethtool_cmd ecmd = { .cmd = ETHTOOL_GSET }; + + mii_ethtool_gset(&axdev->mii, &ecmd); + + if (ecmd.speed == SPEED_1000) { + int eee_lp, eee_cap, eee_adv; + u32 lp, cap, adv; + + eee_cap = ax_mmd_read(axdev->netdev, + MDIO_MMD_PCS, MDIO_PCS_EEE_ABLE); + if (eee_cap < 0) + goto exit; + eee_cap &= ~MDIO_EEE_100TX; + + cap = mmd_eee_cap_to_ethtool_sup_t(eee_cap); + if (!cap) + goto exit; + + eee_lp = ax_mmd_read(axdev->netdev, + MDIO_MMD_AN, MDIO_AN_EEE_LPABLE); + if (eee_lp < 0) + goto exit; + + eee_adv = ax_mmd_read(axdev->netdev, + MDIO_MMD_AN, MDIO_AN_EEE_ADV); + if (eee_adv < 0) + goto exit; + + adv = mmd_eee_adv_to_ethtool_adv_t(eee_adv); + lp = mmd_eee_adv_to_ethtool_adv_t(eee_lp); + if (!(lp & adv & SUPPORTED_1000baseT_Full)) + goto exit; + + axdev->eee_active = 1; + return true; + } +exit: + axdev->eee_active = 0; + return false; +} + +static int ax88179a_ethtool_get_eee(struct ax_device *axdev, + struct ethtool_eee *data) +{ + int val; + + val = ax_mmd_read(axdev->netdev, MDIO_MMD_PCS, MDIO_PCS_EEE_ABLE); + if (val < 0) + return val; + val &= ~MDIO_EEE_100TX; + data->supported = mmd_eee_cap_to_ethtool_sup_t(val); + + val = ax_mmd_read(axdev->netdev, MDIO_MMD_AN, MDIO_AN_EEE_ADV); + if (val < 0) + return val; + data->advertised = mmd_eee_adv_to_ethtool_adv_t(val); + + val = ax_mmd_read(axdev->netdev, MDIO_MMD_AN, MDIO_AN_EEE_LPABLE); + if (val < 0) + return val; + data->lp_advertised = mmd_eee_adv_to_ethtool_adv_t(val); + + return 0; +} + +static int ax88179a_get_eee(struct net_device *net, struct ethtool_eee *edata) +{ + struct ax_device *axdev = netdev_priv(net); + + edata->eee_enabled = axdev->eee_enabled; + edata->eee_active = axdev->eee_active; + + return ax88179a_ethtool_get_eee(axdev, edata); +} + +static void ax88179a_eee_setting(struct ax_device *axdev, bool enable) +{ + ax_write_cmd(axdev, AX88179_GPHY_CTRL, AX_GPHY_EEE_CTRL, + enable, 0, NULL); +} + +static int ax88179a_set_eee(struct net_device *net, struct ethtool_eee *edata) +{ + struct ax_device *axdev = netdev_priv(net); + + if (edata->advertised & MDIO_EEE_100TX) + return -EOPNOTSUPP; + + axdev->eee_enabled = edata->eee_enabled; + ax88179a_eee_setting(axdev, axdev->eee_enabled); + if (axdev->eee_enabled) { + axdev->eee_enabled = ax88179a_chk_eee(axdev); + if (!axdev->eee_enabled) { + ax88179a_eee_setting(axdev, false); + return -EOPNOTSUPP; + } + } + + mii_nway_restart(&axdev->mii); + + return 0; +} + +static int ax88179a_get_coalesce(struct net_device *netdev, + struct ethtool_coalesce *coalesce, + struct kernel_ethtool_coalesce *kernel_coal, + struct netlink_ext_ack *extack) +{ + struct ax_device *axdev = netdev_priv(netdev); + + coalesce->rx_coalesce_usecs = axdev->coalesce; + + return 0; +} + +static u16 ax88179a_usec_to_bin_timer(struct ax_device *axdev) +{ + u16 speed_multiple; + + switch (axdev->link_info.eth_speed) { + case ETHER_LINK_10: + speed_multiple = 100; + break; + case ETHER_LINK_100: + speed_multiple = 10; + break; + case ETHER_LINK_1000: + default: + speed_multiple = 1; + break; + } + + return (axdev->coalesce * US_TO_NS * speed_multiple) / + AX88179A_BIN_TIMER_UINT; +} + +static u32 ax88179a_bin_timer_to_usec(struct ax_device *axdev, u16 timer) +{ + u16 speed_multiple; + + switch (axdev->link_info.eth_speed) { + case ETHER_LINK_10: + speed_multiple = 100; + break; + case ETHER_LINK_100: + speed_multiple = 10; + break; + case ETHER_LINK_1000: + default: + speed_multiple = 1; + break; + } + + return (AX88179A_BIN_TIMER_UINT * timer) / (US_TO_NS * speed_multiple); +} + +static int ax88179a_set_coalesce(struct net_device *netdev, + struct ethtool_coalesce *coalesce, + struct kernel_ethtool_coalesce *kernel_coal, + struct netlink_ext_ack *extack) +{ + struct ax_device *axdev = netdev_priv(netdev); + u16 timer; + int ret = 0; + + ret = usb_autopm_get_interface(axdev->intf); + if (ret < 0) + return ret; + + axdev->coalesce = coalesce->rx_coalesce_usecs; + + timer = ax88179a_usec_to_bin_timer(axdev); + if (timer > 0) { + timer &= 0x7FFF; + ax_write_cmd(axdev, AX_ACCESS_MAC, AX_RX_BULKIN_QTIMR_LOW, 2, 2, &timer); + } + + usb_autopm_put_interface(axdev->intf); + + return ret; +} + +const struct ethtool_ops ax88179a_ethtool_ops = { + .supported_coalesce_params = ETHTOOL_COALESCE_RX_USECS, + .get_drvinfo = ax_get_drvinfo, + .get_link_ksettings = ax_get_link_ksettings, + .set_link_ksettings = ax_set_link_ksettings, + .get_link = ethtool_op_get_link, + .get_msglevel = ax_get_msglevel, + .set_msglevel = ax_set_msglevel, + .get_wol = ax_get_wol, + .set_wol = ax_set_wol, + .get_eee = ax88179a_get_eee, + .set_eee = ax88179a_set_eee, + .get_coalesce = ax88179a_get_coalesce, + .set_coalesce = ax88179a_set_coalesce, + .get_strings = ax_get_strings, + .get_sset_count = ax_get_sset_count, + .get_ethtool_stats = ax_get_ethtool_stats, + .get_pauseparam = ax_get_pauseparam, + .set_pauseparam = ax_set_pauseparam, + .get_regs_len = ax_get_regs_len, + .get_regs = ax_get_regs, + .get_ts_info = ethtool_op_get_ts_info, +}; + +void ax88179a_get_fw_version(struct ax_device *axdev) +{ + int i; + + for (i = 0; i < 3; i++) { + if (ax_read_cmd(axdev, AX88179A_ACCESS_BL, (0xFD + i), + 1, 1, &axdev->fw_version[i], 1) < 0) + axdev->fw_version[i] = ~0; + } + + if (ax_read_cmd(axdev, AX88179A_ACCESS_BL, AX88179A_SW_REVERSION, + 1, 1, &axdev->fw_version[3], 0) < 0) + axdev->fw_version[3] = ~0; + else + axdev->fw_version[3] &= 0xF; +} + +int ax88179a_signature(struct ax_device *axdev, struct _ax_ioctl_command *info) +{ + strscpy(info->sig, AX88179A_SIGNATURE, sizeof(info->sig)); + return 0; +} + +int ax88179a_read_version(struct ax_device *axdev, + struct _ax_ioctl_command *info) +{ + unsigned char temp[16] = {0}; + + snprintf(temp, sizeof(temp), "v%d.%d.%d.%d", axdev->fw_version[0], + axdev->fw_version[1], axdev->fw_version[2], axdev->fw_version[3]); + memcpy(&info->version.version, temp, 16); + + return 0; +} + +int ax88179a_write_flash(struct ax_device *axdev, + struct _ax_ioctl_command *info) +{ + int i, ret; + u8 *buf = NULL; + u8 *block; + + buf = kzalloc(256, GFP_KERNEL); + if (!buf) + return -ENOMEM; + block = buf; + + ret = ax_write_cmd(axdev, AX88179A_FLASH_WEN, 0, 0, 0, NULL); + if (ret < 0) { + netdev_err(axdev->netdev, "Flash write enable failed"); + info->flash.status = -ERR_FALSH_WRITE_EN; + goto out; + } + + for (i = info->flash.offset; + i < (info->flash.length + info->flash.offset); + i += 256) { + if (copy_from_user(block, + (void __user *)&info->flash.buf[i], 256)) { + ret = -EFAULT; + goto out; + } + + ret = ax_write_cmd(axdev, AX88179A_FLASH_WRITE, + (u16)((i >> 16) & 0xFFFF), + (u16)(i & 0xFFFF), 256, block); + if (ret < 0) { + info->flash.status = -ERR_FALSH_WRITE; + goto out; + } + } + + ret = ax_write_cmd(axdev, AX88179A_FLASH_WDIS, 0, 0, 0, NULL); + if (ret < 0) { + netdev_err(axdev->netdev, "Flash write disable failed"); + info->flash.status = -ERR_FALSH_WRITE_DIS; + return ret; + } +out: + kfree(buf); + + return ret; +} + +int ax88179a_read_flash(struct ax_device *axdev, struct _ax_ioctl_command *info) +{ + int i, ret = 0; + void *buf = NULL; + u8 *block; + + buf = kzalloc(256, GFP_KERNEL); + if (!buf) + return -ENOMEM; + block = buf; + + for (i = info->flash.offset; + i < (info->flash.length + info->flash.offset); + i += 256) { + ret = ax_read_cmd(axdev, AX88179A_FLASH_READ, + (u16)((i >> 16) & 0xFFFF), + (u16)(i & 0xFFFF), 256, block, 0); + if (ret < 0) { + info->flash.status = -ERR_FALSH_READ; + break; + } + + if (copy_to_user((void __user *)&info->flash.buf[i], + block, 256)) { + ret = -EFAULT; + break; + } + } + + kfree(buf); + + return ret; +} + +int ax88179a_program_efuse(struct ax_device *axdev, + struct _ax_ioctl_command *info) +{ + int ret = 0; + u16 offset = (u16)(info->flash.offset * 16); + u8 buf[20] = {0}; + + ret = copy_from_user(buf, (void __user *)info->flash.buf, 20); + if (ret) + return ret; + + ret = ax_write_cmd(axdev, AX_ACCESS_EFUSE, offset, 0, 20, buf); + if (ret < 0) { + info->flash.status = -ERR_EFUSE_WRITE; + return ret; + } + + return ret; +} + +int ax88179a_dump_efuse(struct ax_device *axdev, struct _ax_ioctl_command *info) +{ + int ret = 0; + u16 offset = (u16)(info->flash.offset * 16); + u8 buf[20] = {0}; + + ret = ax_read_cmd(axdev, AX_ACCESS_EFUSE, offset, 0, 20, buf, 0); + if (ret < 0) { + info->flash.status = -ERR_EFUSE_READ; + return ret; + } + + ret = copy_to_user((void __user *)info->flash.buf, buf, 20); + + return ret; +} + +int ax88179a_boot_to_rom(struct ax_device *axdev, + struct _ax_ioctl_command *info) +{ + usb_control_msg(axdev->udev, usb_sndctrlpipe(axdev->udev, 0), + AX88179A_BOOT_TO_ROM, + USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, + 0x5A5A, 0xA5A5, NULL, 0, 1); + + return 0; +} + +int ax88179a_erase_flash(struct ax_device *axdev, + struct _ax_ioctl_command *info) +{ + int ret = 0; + + ret = ax_write_cmd(axdev, AX88179A_FLASH_WEN, 0, 0, 0, NULL); + if (ret < 0) { + netdev_err(axdev->netdev, "Flash write enable failed"); + info->flash.status = -ERR_FALSH_WRITE_EN; + return ret; + } + + ret = usb_control_msg(axdev->udev, usb_sndctrlpipe(axdev->udev, 0), + AX88179A_FLASH_EARSE_ALL, + USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, + 0, 0, NULL, 0, 300000); + if (ret < 0) { + netdev_err(axdev->netdev, "Flash erase all failed"); + info->flash.status = -ERR_FALSH_ERASE_ALL; + return ret; + } + + ret = ax_write_cmd(axdev, AX88179A_FLASH_WDIS, 0, 0, 0, NULL); + if (ret < 0) { + netdev_err(axdev->netdev, "Flash write disable failed"); + info->flash.status = -ERR_FALSH_WRITE_DIS; + return ret; + } + + return 0; +} + +int ax88179a_sw_reset(struct ax_device *axdev, struct _ax_ioctl_command *info) +{ + void *buf = NULL; + + buf = kzalloc(sizeof(u32), GFP_KERNEL); + if (!buf) + return -ENOMEM; + + *((u32 *)buf) = 1; + + usb_control_msg(axdev->udev, usb_sndctrlpipe(axdev->udev, 0), 0x10, + USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, + 0x18E8, 0x000F, buf, 4, 10); + + kfree(buf); + + return 0; +} + +IOCTRL_TABLE ax88179a_tbl[] = { + ax88179a_signature, + ax_usb_command, + ax88179a_read_version, + ax88179a_write_flash, + ax88179a_boot_to_rom, + ax88179a_erase_flash, + ax88179a_sw_reset, + ax88179a_read_flash, + ax88179a_program_efuse, + ax88179a_dump_efuse, +}; + +int ax88179a_siocdevprivate(struct net_device *netdev, struct ifreq *rq, + void __user *udata, int cmd) +{ + struct ax_device *axdev = netdev_priv(netdev); + struct _ax_ioctl_command info; + void __user *uptr = (void __user *)rq->ifr_data; + int ret = 0; + + switch (cmd) { + case AX_PRIVATE: + if (copy_from_user(&info, uptr, + sizeof(struct _ax_ioctl_command))) { + netdev_err(netdev, "copy_from_user, return -EFAULT"); + return -EFAULT; + } + + ret = (*ax88179a_tbl[info.ioctl_cmd])(axdev, &info); + if (ret < 0) { + netdev_err(netdev, "ax88179a_tbl, return %d", ret); + return ret; + } + + if (copy_to_user(uptr, &info, + sizeof(struct _ax_ioctl_command))) { + netdev_err(netdev, "copy_to_user, return -EFAULT"); + return -EFAULT; + } + + break; + default: + ret = -EOPNOTSUPP; + } + + return ret; +} + +int ax88179a_ioctl(struct net_device *netdev, struct ifreq *rq, int cmd) +{ + struct ax_device *axdev = netdev_priv(netdev); + + switch (cmd) { + } + return generic_mii_ioctl(&axdev->mii, if_mii(rq), cmd, NULL); +} + +static int ax88179a_autodetach(struct ax_device *axdev) +{ + u16 value = ((axdev->autodetach) ? 1 : 0) | AX88179A_AUTODETACH_DELAY; + + return ax_write_cmd(axdev, AX88179A_AUTODETACH, value, 0, 0, NULL); +} + +static bool ax88179a_check_phy_power(struct ax_device *axdev) +{ + u8 reg8 = 0; + int ret = 0; + + ret = ax_read_cmd_nopm(axdev, AX88179A_PHY_POWER, 0, 0, 1, ®8, 1); + if (ret < 0) + return false; + + return (reg8 & AX_PHY_POWER); +} + +static int ax88179a_set_phy_power(struct ax_device *axdev, bool on) +{ + u8 reg8; + int ret; + + reg8 = (on) ? AX_PHY_POWER : 0; + ret = ax_write_cmd_nopm(axdev, AX88179A_PHY_POWER, 0, 0, 1, ®8); + if (ret < 0) + return ret; + msleep(250); + + return 0; +} + +static int ax88179a_bind(struct ax_device *axdev) +{ + struct net_device *netdev = axdev->netdev; + u16 wvalue = 0; + int ret; + + ax88179a_get_fw_version(axdev); + ax_print_version(axdev, AX_DRIVER_STRING_179A_772D); + + ret = ax_write_cmd(axdev, AX_FW_MODE, AX_FW_MODE_179A, wvalue, 0, NULL); + if (ret < 0) + return ret; + + ret = ax_write_cmd(axdev, AX_RELOAD_FLASH_EFUSE, 0, 0, 0, NULL); + if (ret < 0) + return ret; + + netdev->features |= NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM | + NETIF_F_SG | NETIF_F_TSO | NETIF_F_FRAGLIST | + NETIF_F_HW_VLAN_CTAG_RX | + NETIF_F_HW_VLAN_CTAG_TX; + netdev->hw_features |= NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM | + NETIF_F_SG | NETIF_F_TSO | NETIF_F_FRAGLIST | + NETIF_F_HW_VLAN_CTAG_RX | + NETIF_F_HW_VLAN_CTAG_TX | NETIF_F_RXALL; + netdev->vlan_features = NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_TSO | + NETIF_F_HIGHDMA | NETIF_F_FRAGLIST | + NETIF_F_IPV6_CSUM; + + axdev->tx_casecade_size = TX_CASECADES_SIZE; + axdev->gso_max_size = AX_GSO_DEFAULT_SIZE; + axdev->mii.supports_gmii = true; + axdev->mii.dev = netdev; + axdev->mii.mdio_read = ax_mdio_read; + axdev->mii.mdio_write = ax_mdio_write; + axdev->mii.phy_id_mask = 0x3F; + axdev->mii.reg_num_mask = 0x1F; + axdev->mii.phy_id = AX88179A_PHY_ID; + + netif_set_gso_max_size(netdev, axdev->gso_max_size); + + axdev->bin_setting.custom = false; + axdev->tx_align_len = 8; + axdev->coalesce = 0; + + netdev->ethtool_ops = &ax88179a_ethtool_ops; + axdev->netdev->netdev_ops = &ax88179a_netdev_ops; + + return ret; +} + +static void ax88179a_unbind(struct ax_device *axdev) +{ +} + +static int ax88179a_stop(struct ax_device *axdev) +{ + u16 reg16; + + reg16 = AX_RX_CTL_STOP; + ax_write_cmd(axdev, AX_ACCESS_MAC, AX_MEDIUM_STATUS_MODE, 2, 2, ®16); + ax88179a_set_phy_power(axdev, false); + + return 0; +} + +void ax88179a_set_multicast(struct net_device *netdev) +{ + struct ax_device *axdev = netdev_priv(netdev); + u8 *m_filter = axdev->m_filter; + int mc_count = 0; + + if (!test_bit(AX_ENABLE, &axdev->flags)) + return; + + mc_count = netdev_mc_count(netdev); + + axdev->rxctl = (AX_RX_CTL_START | AX_RX_CTL_AB); + + if (netdev->flags & IFF_PROMISC) { + axdev->rxctl |= AX_RX_CTL_PRO; + } else if (netdev->flags & IFF_ALLMULTI || mc_count > AX_MAX_MCAST) { + axdev->rxctl |= AX_RX_CTL_AMALL; + } else if (netdev_mc_empty(netdev)) { + } else { + u32 crc_bits; + struct netdev_hw_addr *ha = NULL; + + memset(m_filter, 0, AX_MCAST_FILTER_SIZE); + netdev_for_each_mc_addr(ha, netdev) { + crc_bits = ether_crc(ETH_ALEN, ha->addr) >> 26; + *(m_filter + (crc_bits >> 3)) |= 1 << (crc_bits & 7); + } + ax_write_cmd_async(axdev, AX_ACCESS_MAC, AX_MULTI_FILTER_ARRY, + AX_MCAST_FILTER_SIZE, AX_MCAST_FILTER_SIZE, m_filter); + + axdev->rxctl |= AX_RX_CTL_AM; + } + + ax_write_cmd_async(axdev, AX_ACCESS_MAC, AX_RX_CTL, 2, 2, &axdev->rxctl); +} + +static int ax88179a_hw_init(struct ax_device *axdev) +{ + u16 reg16; + u8 reg8; + int ret; + + ret = ax88179a_set_phy_power(axdev, true); + if (ret < 0) + return ret; + msleep(250); + + ret = ax88179a_autodetach(axdev); + if (ret < 0) + return ret; + + reg8 = AX_TXCOE_IP | AX_TXCOE_TCP | AX_TXCOE_UDP | + AX_TXCOE_TCPV6 | AX_TXCOE_UDPV6; + ret = ax_write_cmd(axdev, AX_ACCESS_MAC, AX_TXCOE_CTL, 1, 1, ®8); + if (ret < 0) + return ret; + + reg8 = AX_RXCOE_IP | AX_RXCOE_TCP | AX_RXCOE_UDP | + AX_RXCOE_TCPV6 | AX_RXCOE_UDPV6; + ret = ax_write_cmd(axdev, AX_ACCESS_MAC, AX_RXCOE_CTL, 1, 1, ®8); + if (ret < 0) + return ret; + + reg8 = AX_MAC_EFF_EN; + ret = ax_write_cmd(axdev, AX_ACCESS_MAC, AX88179A_MAC_BULK_OUT_CTRL, + 1, 1, ®8); + if (ret < 0) + return ret; + + reg16 = 0; + ret = ax_write_cmd_async(axdev, AX_ACCESS_MAC, AX_RX_CTL, 2, 2, ®16); + if (ret < 0) + return ret; + + reg8 = 0x04; + ret = ax_write_cmd(axdev, AX_ACCESS_MAC, AX_PAUSE_WATERLVL_LOW, 1, 1, ®8); + if (ret < 0) + return ret; + + reg8 = 0x10; + ret = ax_write_cmd(axdev, AX_ACCESS_MAC, AX_PAUSE_WATERLVL_HIGH, 1, 1, ®8); + if (ret < 0) + return ret; + + reg8 = 0; + if (axdev->netdev->features & NETIF_F_HW_VLAN_CTAG_FILTER) + reg8 |= AX_VLAN_CONTROL_VFE; + if (axdev->netdev->features & NETIF_F_HW_VLAN_CTAG_RX) + reg8 |= AX_VLAN_CONTROL_VSO; + ret = ax_write_cmd(axdev, AX_ACCESS_MAC, AX88179A_VLAN_ID_CONTROL, 1, 1, ®8); + if (ret < 0) + return ret; + + reg8 = 0xff; + ret = ax_write_cmd(axdev, AX_ACCESS_MAC, AX88179A_MAC_BM_INT_MASK, 1, 1, ®8); + if (ret < 0) + return ret; + + reg8 = 0; + ret = ax_write_cmd(axdev, AX_ACCESS_MAC, AX88179A_MAC_BM_RX_DMA_CTL, 1, 1, ®8); + if (ret < 0) + return ret; + + ret = ax_write_cmd(axdev, AX_ACCESS_MAC, AX88179A_MAC_BM_TX_DMA_CTL, 1, 1, ®8); + if (ret < 0) + return ret; + + ret = ax_write_cmd(axdev, AX_ACCESS_MAC, AX88179A_MAC_ARC_CTRL, 1, 1, ®8); + if (ret < 0) + return ret; + + ret = ax_write_cmd(axdev, AX_ACCESS_MAC, AX88179A_MAC_SWP_CTRL, 1, 1, ®8); + if (ret < 0) + return ret; + + reg8 = AX_TXHDR_CKSUM_EN; + ret = ax_write_cmd_nopm(axdev, AX_ACCESS_MAC, AX88179A_MAC_TX_HDR_CKSUM, 1, 1, ®8); + if (ret < 0) + return ret; + + reg16 = AX_RX_CTL_START | AX_RX_CTL_AP | AX_RX_CTL_AMALL | + AX_RX_CTL_AB | AX_RX_CTL_DROPCRCERR; + ret = ax_write_cmd(axdev, AX_ACCESS_MAC, AX_RX_CTL, 1, 1, ®16); + if (ret < 0) + return ret; + + reg8 = 0; + ret = ax_write_cmd(axdev, AX_ACCESS_MAC, AX88179A_MAC_PATH, 1, 1, ®8); + if (ret < 0) + return ret; + + ret = ax_read_cmd(axdev, AX_ACCESS_MAC, AX_MONITOR_MODE, 1, 1, ®8, 1); + if (ret < 0) + return ret; + reg8 &= 0xE0; + ret = ax_write_cmd(axdev, AX_ACCESS_MAC, AX_MONITOR_MODE, 1, 1, ®8); + if (ret < 0) + return ret; + + ret = ax_read_cmd(axdev, AX_ACCESS_MAC, AX_MEDIUM_STATUS_MODE, 2, 2, ®16, 2); + if (ret < 0) + return ret; + + reg16 &= ~AX_MEDIUM_GIGAMODE; + ret = ax_write_cmd(axdev, AX_ACCESS_MAC, AX_MEDIUM_STATUS_MODE, 2, 2, ®16); + if (ret < 0) + return ret; + + reg16 |= AX_MEDIUM_GIGAMODE; + ret = ax_write_cmd(axdev, AX_ACCESS_MAC, AX_MEDIUM_STATUS_MODE, 2, 2, ®16); + if (ret < 0) + return ret; + + reg8 = 0; + ret = ax_write_cmd(axdev, AX_ACCESS_MAC, AX88179A_BFM_DATA, 1, 1, ®8); + if (ret < 0) + return ret; + + ret = ax_write_cmd(axdev, AX_ACCESS_MAC, AX88179A_CDC_ECM_CTRL, 1, 1, ®8); + if (ret < 0) + return ret; + + ax_set_tx_qlen(axdev); + + return ret; +} + +static int ax88179a_get_ether_link(struct ax_device *axdev) +{ + struct ax_link_info *link_info = &axdev->link_info; + struct ethtool_link_ksettings cmd; + + mii_ethtool_get_link_ksettings(&axdev->mii, &cmd); + switch (cmd.base.speed) { + case SPEED_1000: + link_info->eth_speed = ETHER_LINK_1000; + break; + case SPEED_100: + link_info->eth_speed = ETHER_LINK_100; + break; + case SPEED_10: + default: + link_info->eth_speed = ETHER_LINK_10; + break; + } + + link_info->full_duplex = cmd.base.duplex; + return 0; +} + +static int ax88179a_set_bulkin_setting(struct ax_device *axdev) +{ + struct ax_link_info *link_info = &axdev->link_info; + u8 link_sts; + int index = 0, ret; + + ret = ax_read_cmd_nopm(axdev, AX_ACCESS_MAC, PHYSICAL_LINK_STATUS, 1, 1, &link_sts, 0); + if (ret < 0) + return ret; + + switch (link_info->eth_speed) { + case ETHER_LINK_1000: + if (link_sts & AX_USB_SS) + index = 0; + else if (link_sts & AX_USB_HS) + index = 1; + break; + case ETHER_LINK_100: + if (link_sts & AX_USB_SS) + index = 2; + else if (link_sts & AX_USB_HS) + index = 4; + + if (!link_info->full_duplex) + index++; + break; + case ETHER_LINK_10: + index = 6; + break; + case ETHER_LINK_NONE: + default: + index = 0; + break; + } + + if (axdev->coalesce == 0) { + u16 timer = *((u16 *)&AX88179A_BULKIN_SIZE[index].timer_l); + + axdev->coalesce = ax88179a_bin_timer_to_usec(axdev, timer); + } else { + u16 timer = ax88179a_usec_to_bin_timer(axdev); + + memcpy(&AX88179A_BULKIN_SIZE[index].timer_l, &timer, 2); + } + + ret = ax_write_cmd_nopm(axdev, AX_ACCESS_MAC, AX_RX_BULKIN_QCTRL, + 5, 5, &AX88179A_BULKIN_SIZE[index]); + if (ret < 0) + return ret; + + return 0; +} + +static int ax88179a_link_setting(struct ax_device *axdev) +{ + struct ax_link_info *link_info = &axdev->link_info; + struct ethtool_pauseparam pause; + u16 medium_mode, reg16; + u8 reg8[3]; + int ret; + + reg16 = AX_RX_CTL_STOP; + ret = ax_write_cmd_nopm(axdev, AX_ACCESS_MAC, AX_RX_CTL, 2, 2, ®16); + if (ret < 0) + return ret; + + reg8[0] = 0; + ret = ax_write_cmd_nopm(axdev, AX_ACCESS_MAC, AX88179A_MAC_PATH, 1, 1, reg8); + if (ret < 0) + return ret; + + reg8[0] = 0xA5; + ret = ax_write_cmd_nopm(axdev, AX_ACCESS_MAC, AX88179A_MAC_CDC_DELAY_TX, 1, 1, reg8); + if (ret < 0) + return ret; + + reg8[0] = 0x10; + reg8[1] = 0x04; + ret = ax_write_cmd_nopm(axdev, AX_ACCESS_MAC, AX_PAUSE_WATERLVL_HIGH, 2, 2, reg8); + if (ret < 0) + return ret; + + memset(&pause, 0, sizeof(pause)); + ax_get_pauseparam(axdev->netdev, &pause); + medium_mode = AX_MEDIUM_RECEIVE_EN; + if (pause.rx_pause) + medium_mode |= AX_MEDIUM_RXFLOW_CTRLEN; + + if (pause.tx_pause) { + medium_mode |= AX_MEDIUM_TXFLOW_CTRLEN; + reg8[0] = 0x28 | AX_NEW_PAUSE_EN; + } else { + reg8[0] = 0; + } + ret = ax_write_cmd(axdev, AX_ACCESS_MAC, AX88179A_NEW_PAUSE_CTRL, + 1, 1, reg8); + if (ret < 0) + return ret; + + switch (link_info->eth_speed) { + case ETHER_LINK_1000: + case ETHER_LINK_100: + reg8[0] = 0x78; + reg8[1] = (AX_LSOFC_WCNT_7_ACCESS << 5) | AX_GMII_CRC_APPEND; + reg8[2] = 0; + ret = ax_write_cmd_nopm(axdev, AX_ACCESS_MAC, + AX88178A_MAC_RX_STATUS_CDC, 3, 3, reg8); + if (ret < 0) + return ret; + + reg8[0] = 0x40; + ret = ax_write_cmd_nopm(axdev, AX_ACCESS_MAC, + AX88179A_MAC_RX_DATA_CDC_CNT, + 1, 1, reg8); + if (ret < 0) + return ret; + if (link_info->eth_speed == ETHER_LINK_1000) + medium_mode |= AX_MEDIUM_GIGAMODE; + break; + case ETHER_LINK_10: + reg8[0] = 0xFA; + reg8[1] = (AX_LSOFC_WCNT_7_ACCESS << 5) | AX_GMII_CRC_APPEND; + reg8[2] = 0xFF; + ret = ax_write_cmd_nopm(axdev, AX_ACCESS_MAC, + AX88178A_MAC_RX_STATUS_CDC, 3, 3, reg8); + if (ret < 0) + return ret; + + reg8[0] = 0xFA; + ret = ax_write_cmd_nopm(axdev, AX_ACCESS_MAC, + AX88179A_MAC_RX_DATA_CDC_CNT, + 1, 1, reg8); + if (ret < 0) + return ret; + break; + default: + break; + } + + reg8[0] = 0; + ret = ax_write_cmd_nopm(axdev, AX_ACCESS_MAC, AX88179A_BFM_DATA, + 1, 1, reg8); + if (ret < 0) + return ret; + + ret = ax88179a_set_bulkin_setting(axdev); + if (ret < 0) + return ret; + + if (link_info->full_duplex) + medium_mode |= AX_MEDIUM_FULL_DUPLEX; + ret = ax_write_cmd_nopm(axdev, AX_ACCESS_MAC, AX_MEDIUM_STATUS_MODE, + 2, 2, &medium_mode); + if (ret < 0) + return ret; + + axdev->rxctl |= AX_RX_CTL_START | AX_RX_CTL_AB; + ret = ax_write_cmd_nopm(axdev, AX_ACCESS_MAC, AX_RX_CTL, + 2, 2, &axdev->rxctl); + if (ret < 0) + return ret; + + reg8[0] = AX_MAC_RX_PATH_READY | AX_MAC_TX_PATH_READY; + ret = ax_write_cmd_nopm(axdev, AX_ACCESS_MAC, AX88179A_MAC_PATH, + 1, 1, reg8); + if (ret < 0) + return ret; + + return 0; +} + +static int ax88179a_link_reset(struct ax_device *axdev) +{ + int ret; + + ret = ax88179a_get_ether_link(axdev); + if (ret < 0) + return ret; + + ret = ax88179a_link_setting(axdev); + if (ret < 0) + return ret; + + axdev->eee_enabled = ax88179a_chk_eee(axdev); + ax88179a_eee_setting(axdev, axdev->eee_enabled); + + return 0; +} + +inline void ax88179a_rx_checksum(struct sk_buff *skb, void *pkt_hdr) +{ + struct _179a_rx_pkt_header *hdr = (struct _179a_rx_pkt_header *)pkt_hdr; + + skb->ip_summed = CHECKSUM_NONE; + + if (hdr->L4_err || hdr->L3_err) + return; + + if (hdr->L4_pkt_type == AX_RXHDR_L4_TYPE_TCP || hdr->L4_pkt_type == AX_RXHDR_L4_TYPE_UDP) + skb->ip_summed = CHECKSUM_UNNECESSARY; +} + +static void ax88179a_rx_fixup(struct ax_device *axdev, struct rx_desc *desc, + int *work_done, int budget) +{ + struct napi_struct *napi = &axdev->napi; + struct net_device *netdev = axdev->netdev; + struct net_device_stats *stats = ax_get_stats(netdev); + struct _179a_rx_pkt_header *pkt_hdr; + struct _179a_rx_header *rx_header; + const u32 actual_length = desc->urb->actual_length; + u8 *rx_data; + u32 aa = 0, rx_hdroffset = 0; + u16 pkt_count = 0; + + rx_header = (struct _179a_rx_header *) + (((u8 *)desc->head) + actual_length - AX88179A_RX_HEADER_SIZE); + le64_to_cpus(rx_header); + + rx_hdroffset = rx_header->hdr_off; + pkt_count = rx_header->pkt_cnt; + aa = (actual_length - ((pkt_count + 1) * 8)); + if ((aa != rx_hdroffset && ((aa - rx_hdroffset) % 16) != 0) || + rx_hdroffset >= desc->urb->actual_length || + pkt_count == 0) { + desc->urb->actual_length = 0; + stats->rx_length_errors++; + return; + } + + pkt_hdr = (struct _179a_rx_pkt_header *) + (((u8 *)desc->head) + rx_header->hdr_off); + + rx_data = desc->head; + while (pkt_count--) { + struct sk_buff *skb; + u32 pkt_len = 0; + + le64_to_cpus(pkt_hdr); + + if (!pkt_hdr->rx_ok) { + stats->rx_crc_errors++; + if (!(netdev->features & NETIF_F_RXALL)) + goto find_next_rx; + } + + if (pkt_hdr->drop) { + stats->rx_dropped++; + if (!(netdev->features & NETIF_F_RXALL)) + goto find_next_rx; + } + + pkt_len = (u32)(pkt_hdr->length & 0x7FFF); + + skb = napi_alloc_skb(napi, pkt_len); + if (!skb) { + stats->rx_dropped++; + goto find_next_rx; + } + + skb_put(skb, pkt_len); + memcpy(skb->data, rx_data, pkt_len); + ax88179a_rx_checksum(skb, pkt_hdr); + + skb->truesize = skb->len + sizeof(struct sk_buff); + + if (pkt_hdr->vlan_ind) + __vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q), + pkt_hdr->vlan_tag & VLAN_VID_MASK); + + skb->protocol = eth_type_trans(skb, netdev); + if (*work_done < budget) { + napi_gro_receive(napi, skb); + *work_done += 1; + stats->rx_packets++; + stats->rx_bytes += pkt_len; + } else { + __skb_queue_tail(&axdev->rx_queue, skb); + } +find_next_rx: + rx_data += (pkt_len + 7) & 0x7FFF8; + pkt_hdr++; + } +} + +static int ax88179a_tx_fixup(struct ax_device *axdev, struct tx_desc *desc) +{ + struct sk_buff_head skb_head, *tx_queue; + struct net_device_stats *stats = &axdev->netdev->stats; + int remain, ret; + int endpoint = 3; + u8 *tx_data; + + tx_queue = axdev->tx_queue; + + __skb_queue_head_init(&skb_head); + spin_lock(&tx_queue->lock); + skb_queue_splice_init(tx_queue, &skb_head); + spin_unlock(&tx_queue->lock); + + tx_data = desc->head; + desc->skb_num = 0; + desc->skb_len = 0; + remain = axdev->tx_casecade_size; + + while (remain >= (ETH_ZLEN + AX88179A_TX_HEADER_SIZE)) { + struct sk_buff *skb; + struct _179a_tx_pkt_header *tx_hdr; + u16 tci = 0; + + skb = __skb_dequeue(&skb_head); + if (!skb) + break; + + if ((skb->len + AX88179A_TX_HEADER_SIZE) > remain && + (skb_shinfo(skb)->gso_size == 0)) { + __skb_queue_head(&skb_head, skb); + break; + } + + tx_hdr = (struct _179a_tx_pkt_header *)tx_data; + memset(tx_hdr, 0, AX88179A_TX_HEADER_SIZE); + tx_hdr->length = (skb->len & 0x1FFFFF); + tx_hdr->checksum = AX88179A_TX_HERDER_CHKSUM(tx_hdr->length); + tx_hdr->max_seg_size = skb_shinfo(skb)->gso_size; + if ((axdev->netdev->features & NETIF_F_HW_VLAN_CTAG_TX) && + (vlan_get_tag(skb, &tci) >= 0)) { + tx_hdr->vlan_tag = 1; + tx_hdr->vlan_info = tci; + } + + cpu_to_le64s(tx_hdr); + tx_data += AX88179A_TX_HEADER_SIZE; + + if (skb_copy_bits(skb, 0, tx_data, skb->len) < 0) { + stats->tx_dropped += skb_shinfo(skb)->gso_segs ?: 1; + dev_kfree_skb_any(skb); + continue; + } + + tx_data = __tx_buf_align((void *)(tx_data + skb->len), + axdev->tx_align_len); + desc->skb_len += skb->len; + desc->skb_num += skb_shinfo(skb)->gso_segs ?: 1; + dev_kfree_skb_any(skb); + + if (tx_hdr->max_seg_size) + break; + + remain = axdev->tx_casecade_size - + (int)((void *)tx_data - desc->head); + } + + if (!skb_queue_empty(&skb_head)) { + spin_lock(&tx_queue->lock); + skb_queue_splice(&skb_head, tx_queue); + spin_unlock(&tx_queue->lock); + } + + netif_tx_lock(axdev->netdev); + if (netif_queue_stopped(axdev->netdev) && + skb_queue_len(tx_queue) < axdev->tx_qlen) { + netif_wake_queue(axdev->netdev); + } + netif_tx_unlock(axdev->netdev); + + ret = usb_autopm_get_interface_async(axdev->intf); + if (ret < 0) + return ret; + + usb_fill_bulk_urb(desc->urb, axdev->udev, + usb_sndbulkpipe(axdev->udev, endpoint), + desc->head, (int)(tx_data - (u8 *)desc->head), + (usb_complete_t)ax_write_bulk_callback, desc); + + ret = usb_submit_urb(desc->urb, GFP_ATOMIC); + if (ret < 0) + usb_autopm_put_interface_async(axdev->intf); + + return 0; +} + +static int ax88179a_system_suspend(struct ax_device *axdev) +{ + return 0; +} + +static int ax88179a_system_resume(struct ax_device *axdev) +{ + int ret; + + if (!ax88179a_check_phy_power(axdev)) + ax88179a_set_phy_power(axdev, true); + + ret = ax_write_cmd_nopm(axdev, AX_FW_MODE, AX_FW_MODE_179A, 0, 0, NULL); + if (ret < 0) + return ret; + + axdev->driver_info->hw_init(axdev); + + return 0; +} + +const struct driver_info ax88179a_info = { + .bind = ax88179a_bind, + .unbind = ax88179a_unbind, + .hw_init = ax88179a_hw_init, + .stop = ax88179a_stop, + .link_reset = ax88179a_link_reset, + .rx_fixup = ax88179a_rx_fixup, + .tx_fixup = ax88179a_tx_fixup, + .system_suspend = ax88179a_system_suspend, + .system_resume = ax88179a_system_resume, + .napi_weight = AX88179A_NAPI_WEIGHT, + .buf_rx_size = AX88179A_BUF_RX_SIZE, +}; + +const struct driver_info ax88772d_info = { + .bind = ax88179a_bind, + .unbind = ax88179a_unbind, + .hw_init = ax88179a_hw_init, + .stop = ax88179a_stop, + .link_reset = ax88179a_link_reset, + .rx_fixup = ax88179a_rx_fixup, + .tx_fixup = ax88179a_tx_fixup, + .system_suspend = ax88179a_system_suspend, + .system_resume = ax88179a_system_resume, + .napi_weight = AX88179A_NAPI_WEIGHT, + .buf_rx_size = AX88179A_BUF_RX_SIZE, +}; diff --git a/drivers/net/usb/ax88179a_772d.h b/drivers/net/usb/ax88179a_772d.h new file mode 100644 index 000000000000..b13618b20bbf --- /dev/null +++ b/drivers/net/usb/ax88179a_772d.h @@ -0,0 +1,170 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/******************************************************************************* + * Copyright (c) 2022 ASIX Electronic Corporation All rights reserved. + * + * This program is free software: you can redistribute it and/or modify it under + * the terms of the GNU General Public License as published by the Free Software + * Foundation, either version 2 of the License, or (at your option) any later + * version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details + * + * You should have received a copy of the GNU General Public License along with + * this program. If not, see . + ******************************************************************************/ +#ifndef __ASIX_AX88179A_772D_H +#define __ASIX_AX88179A_772D_H + +#define AX88179A_BIN_TIMER_UINT 800 //ns + +#define AX88179A_NAPI_WEIGHT 64 +#define AX88179A_BUF_RX_SIZE (48 * 1024) +#define AX88179A_PHY_ID 0x03 +#define AX88179_GPHY_CTRL 0x0F + #define AX_GPHY_EEE_CTRL 0x01 +#define AX88179A_HIGH_QUEUE_POINT 0x60 +#define AX88179A_AUTODETACH_DELAY (5UL << 8) + +#define AX88179A_PBUS_REG 0x10 +#define AX88179A_ACCESS_BL 0x2A +#define AX88179A_PHY_CLAUSE45 0x27 +#define AX88179A_PHY_POWER 0x31 + #define AX_PHY_POWER 0x02 +#define AX88179A_BOOT_TO_ROM 0x9F +#define AX88179A_AUTODETACH 0xC0 + +#define AX88179A_BFM_DATA 0x0E + #define AX_TX_QUEUE_CFG 0x02 + #define AX_TX_QUEUE_SET 0x08 + #define AX_TX_Q1_AHB_FC_EN 0x10 + #define AX_TX_Q2_AHB_FC_EN 0x20 + #define AX_XGMII_EN 0x80 +#define AX88179A_ETH_TX_GAP 0x0D +#define AX88179A_FLASH_READ 0x21 +#define AX88179A_FLASH_WEN 0x22 +#define AX88179A_FLASH_WDIS 0x23 +#define AX88179A_FLASH_WRITE 0x24 +#define AX88179A_FLASH_EARSE_ALL 0x25 +#define AX88179A_VLAN_ID_CONTROL 0x2B + #define AX_VLAN_CONTROL_WE 0x0001 + #define AX_VLAN_CONTROL_RD 0x0002 + #define AX_VLAN_CONTROL_VSO 0x0010 + #define AX_VLAN_CONTROL_VFE 0x0020 +#define AX88179A_MAC_BM_INT_MASK 0x41 +#define AX88179A_MAC_BM_RX_DMA_CTL 0x43 +#define AX88179A_MAC_BM_TX_DMA_CTL 0x46 +#define AX88179A_CLK_EN_ARRAY_1 0x4B + #define AX_MAC_MII_TX_25M_EN 0x02 + #define AX_MAC_RX_25M_EN 0x08 +#define AX88179A_MAC_CLK_SELECT_1 0x4D + #define AX_MAC_PCSCLK_MII_TX 0x01 +#define AX88178A_MAC_RX_STATUS_CDC 0x6D +#define AX88179A_MAC_LSOFC_GMIIPF 0x6E + #define AX_GMII_CRC_APPEND 0x10 + #define AX_LSOFC_WCNT_1_ACCESS 0x00 + #define AX_LSOFC_WCNT_2_ACCESS 0x01 + #define AX_LSOFC_WCNT_5_ACCESS 0x02 + #define AX_LSOFC_WCNT_7_ACCESS 0x03 +#define AX88179A_MAC_RX_FILTER_CTRL 0x6F + #define AX_MAC_RX_FILTER_OFT_EN 0x80 +#define AX88179A_MAC_QUEUE_POINT 0x7F +#define AX88179A_MAC_ARC_CTRL 0x9E +#define AX88179A_CDC_ECM_CTRL 0xB0 +#define AX88179A_MAC_SWP_CTRL 0xB1 +#define AX88179A_MAC_TX_PAUSE_0 0xB2 +#define AX88179A_MAC_TX_PAUSE_1 0xB3 +#define AX88179A_MAC_TX_PAUSE_2 0xB4 +#define AX88179A_MAC_CDC_DELAY_TX 0xB5 +#define AX88179A_MAC_PATH 0xB7 + #define AX_MAC_RX_PATH_READY 0x01 + #define AX_MAC_TX_PATH_READY 0x02 +#define AX88179A_NEW_PAUSE_CTRL 0xB8 + #define AX_NEW_PAUSE_EN 0x01 +#define AX88179A_MAC_BULK_OUT_CTRL 0xB9 + #define AX_MAC_EFF_EN 0x02 +#define AX88179A_MAC_RX_DATA_CDC_CNT 0xC0 +#define AX88179A_MAC_BFM_CTRL 0xC1 + #define AX_MAC_STOP_EP5_ACCESS 0x01 + #define AX_MAC_STOP_EP3_ACCESS 0x02 + #define AX_MAC_LSO_ERR_EN 0x04 + #define AX_MAC_MIQFFCTRL_FORMAT 0x10 + #define AX_MAC_MIQFFCTRL_DROP_CRC 0x20 +#define AX88179A_MAC_LSO_ENHANCE_CTRL 0xC3 + #define AX_LSO_ENHANCE_EN 0x01 +#define AX88179A_MAC_TX_HDR_CKSUM 0xCC + #define AX_TXHDR_CKSUM_EN 0x01 + #define AX_TXRX_INDV_RESET_EN 0x02 +#define AX88179A_MAC_CPU_CTRL_MAC_1 0xCE + #define AX_RX_INDV_RESET 0x01 + #define AX_TX_INDV_RESET 0x02 +#define AX88179A_EP5_EHR 0xF9 + #define AX_EP5_DAT_ERROR_HANDLE 0x80 +#define AX88179A_HW_EC_VERSION 0xFB +#define AX88179A_SW_REVERSION 0xFC + #define AX88179A_FLASH_MODE 0x80 + +#define PHY_1000M_STS 0x11 + #define LINK_1000M_OK 0x1000 +#define PHY_100M_STS 0x10 + #define LINK_100M_OK 0x1000 +#define PHY_10M_STS 0x16 + #define LINK_10M_OK 0x40 + +struct _179a_rx_pkt_header { + u16 L4_err :1, + L3_err :1, + L4_pkt_type :3, + L3_pkt_type :2, + CE :1, + TCO_match :1, + node_ID_match :1, + vlan_ind :1, + rx_ok :1, + reserved2 :3, + BMC :1; + u16 length :15, + drop :1; + u16 vlan_tag; + u16 WUF_detect :1, + WUF_wake :1, + WUF_ind :6, + PTP_ind :1, + reserved :7; +}; + +struct _179a_rx_header { + u32 pkt_cnt :13, + hdr_off :19; + u32 rx_throughput; +}; + +#define AX88179A_RX_HEADER_SIZE sizeof(struct _179a_rx_header) + +struct _179a_tx_pkt_header { + u32 length :21, + checksum :7, + padding :1, + vlan_tag :1, + CPHI :1, + DICF :1; + u32 max_seg_size :15, + reserved :1, + vlan_info :16; +}; + +#define AX88179A_TX_HEADER_SIZE sizeof(struct _179a_tx_pkt_header) + +#define AX88179A_TX_HERDER_CHKSUM(len) ((tx_hdr->length + \ + (tx_hdr->length >> 8) + \ + ((tx_hdr->length >> 16) & 0x1F)) & 0x7F) + +extern const struct net_device_ops ax88179a_netdev_ops; +extern const struct driver_info ax88179a_info; +extern const struct driver_info ax88772d_info; +int ax88179a_siocdevprivate(struct net_device *netdev, struct ifreq *rq, + void __user *udata, int cmd); +int ax88179a_ioctl(struct net_device *net, struct ifreq *rq, int cmd); +void ax88179a_set_multicast(struct net_device *net); +#endif /* End of __ASIX_AX88179A_772D_H */ diff --git a/drivers/net/usb/ax_ioctl.h b/drivers/net/usb/ax_ioctl.h new file mode 100644 index 000000000000..2971c35d570a --- /dev/null +++ b/drivers/net/usb/ax_ioctl.h @@ -0,0 +1,117 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/******************************************************************************* + * Copyright (c) 2022 ASIX Electronic Corporation All rights reserved. + * + * This program is free software: you can redistribute it and/or modify it under + * the terms of the GNU General Public License as published by the Free Software + * Foundation, either version 2 of the License, or (at your option) any later + * version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details + * + * You should have received a copy of the GNU General Public License along with + * this program. If not, see . + ******************************************************************************/ +#ifndef __ASIX_IOCTL_H +#define __ASIX_IOCTL_H +// CHANGE NETWORK INTERFACE WAY +// DEFAULT_SCAN : scan "eth0" - "eth255" +// INTERFACE_SCAN : scan all available network interfaces +#define NET_INTERFACE DEFAULT_SCAN +#define DEFAULT_SCAN 0x00 +#define INTERFACE_SCAN 0x01 + +#define AX88179_SIGNATURE "AX88179_178A" +#define AX88179_DRV_NAME "AX88179_178A" +#define AX88179A_SIGNATURE "AX88179A_772D" +#define AX88179A_DRV_NAME "AX88179A_772D" + +#define AX_PRIVATE SIOCDEVPRIVATE + +#define AX_SIGNATURE 0 +#define AX_USB_COMMAND 1 +#define AX88179_READ_EEPROM 2 +#define AX88179_WRITE_EEPROM 3 +#define AX88179A_READ_VERSION 2 +#define AX88179A_WRITE_FLASH 3 +#define AX88179A_ROOT_2_ROM 4 +#define AX88179A_ERASE_FLASH 5 +#define AX88179A_SW_RESET 6 +#define AX88179A_READ_FLASH 7 +#define AX88179A_PROGRAM_EFUSE 8 +#define AX88179A_DUMP_EFUSE 9 + +#define ERR_FALSH_WRITE_EN 1 +#define ERR_FALSH_WRITE_DIS 2 +#define ERR_FALSH_ERASE_ALL 3 +#define ERR_FALSH_WRITE 4 +#define ERR_FALSH_READ 5 +#define ERR_EFUSE_READ 6 +#define ERR_EFUSE_WRITE 6 + +#define USB_READ_OPS 0 +#define USB_WRITE_OPS 1 + +#define SCAN_DEV_MAX_RETRY 10 + +struct _ax_usb_command { + unsigned char ops; + unsigned char cmd; + unsigned short value; + unsigned short index; + unsigned short size; + unsigned char *data; + unsigned long cmd_data; +}; + +struct _ax88179a_flash { + int status; + int length; + int offset; + unsigned char *buf; +}; + +struct _ax88179a_version { + unsigned char version[16]; +}; + +struct _ax_ioctl_command { + unsigned short ioctl_cmd; + unsigned char sig[16]; + unsigned char type; + unsigned short *buf; + unsigned short size; + unsigned char delay; + union { + struct _ax88179a_flash flash; + struct _ax88179a_version version; + struct _ax_usb_command usb_cmd; + }; +}; + +struct ax_device; +typedef int (*IOCTRL_TABLE)(struct ax_device *axdev, + struct _ax_ioctl_command *info); + +struct ax_command_info { + int inet_sock; + struct ifreq *ifr; + int argc; + char **argv; + unsigned short ioctl_cmd; + const char *help_ins; + const char *help_desc; +}; + +typedef void (*MENU_FUNC)(struct ax_command_info *info); + +struct _command_list { + char *cmd; + unsigned short ioctl_cmd; + MENU_FUNC opt_func; + const char *help_ins; + const char *help_desc; +}; +#endif /* __ASIX_IOCTL_H */ diff --git a/drivers/net/usb/ax_main.c b/drivers/net/usb/ax_main.c new file mode 100644 index 000000000000..fd8f360db4f9 --- /dev/null +++ b/drivers/net/usb/ax_main.c @@ -0,0 +1,2091 @@ +// SPDX-License-Identifier: GPL-2.0 +/******************************************************************************* + * Copyright (c) 2022 ASIX Electronic Corporation All rights reserved. + * + * This program is free software: you can redistribute it and/or modify it under + * the terms of the GNU General Public License as published by the Free Software + * Foundation, either version 2 of the License, or (at your option) any later + * version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details + * + * You should have received a copy of the GNU General Public License along with + * this program. If not, see . + ******************************************************************************/ +#include "ax_main.h" +#include "ax88179_178a.h" +#include "ax88179a_772d.h" + +#ifdef ENABLE_AUTODETACH_FUNC +static int autodetach = -1; +module_param(autodetach, int, 0); +MODULE_PARM_DESC(autodetach, "Autodetach configuration"); +#endif + +static int bctrl = -1; +module_param(bctrl, int, 0); +MODULE_PARM_DESC(bctrl, "RX Bulk Control"); + +static int blwt = -1; +module_param(blwt, int, 0); +MODULE_PARM_DESC(blwt, "RX Bulk Timer Low"); + +static int bhit = -1; +module_param(bhit, int, 0); +MODULE_PARM_DESC(bhit, "RX Bulk Timer High"); + +static int bsize = -1; +module_param(bsize, int, 0); +MODULE_PARM_DESC(bsize, "RX Bulk Queue Size"); + +static int bifg = -1; +module_param(bifg, int, 0); +MODULE_PARM_DESC(bifg, "RX Bulk Inter Frame Gap"); + +static int +ax_submit_rx(struct ax_device *netdev, struct rx_desc *desc, gfp_t mem_flags); + +void ax_print_version(struct ax_device *axdev, const char *str) +{ + dev_info(&axdev->intf->dev, "%s %s (%d.%d.%d.%d_%d.%d)", + str, DRIVER_VERSION, axdev->fw_version[0], + axdev->fw_version[1], axdev->fw_version[2], + axdev->fw_version[3], axdev->chip_version, + axdev->sub_version); +} + +void ax_get_drvinfo(struct net_device *net, struct ethtool_drvinfo *info) +{ + struct ax_device *axdev = netdev_priv(net); + + strscpy(info->driver, MODULENAME, sizeof(info->driver)); + strscpy(info->version, DRIVER_VERSION, sizeof(info->version)); + usb_make_path(axdev->udev, info->bus_info, sizeof(info->bus_info)); + + snprintf(info->fw_version, sizeof(info->fw_version), "v%d.%d.%d.%d", + axdev->fw_version[0], axdev->fw_version[1], + axdev->fw_version[2], axdev->fw_version[3]); +} + +int ax_get_link_ksettings(struct net_device *netdev, + struct ethtool_link_ksettings *cmd) +{ + struct ax_device *axdev = netdev_priv(netdev); + int ret; + + if (!axdev->mii.mdio_read) + return -EOPNOTSUPP; + + ret = usb_autopm_get_interface(axdev->intf); + if (ret < 0) + return ret; + + mutex_lock(&axdev->control); + + mii_ethtool_get_link_ksettings(&axdev->mii, cmd); + + mutex_unlock(&axdev->control); + + usb_autopm_put_interface(axdev->intf); + + return 0; +} + +int ax_set_link_ksettings(struct net_device *netdev, + const struct ethtool_link_ksettings *cmd) +{ + struct ax_device *axdev = netdev_priv(netdev); + int ret; + + ret = usb_autopm_get_interface(axdev->intf); + if (ret < 0) + return ret; + + mutex_lock(&axdev->control); + + mii_ethtool_set_link_ksettings(&axdev->mii, cmd); + + mutex_unlock(&axdev->control); + + usb_autopm_put_interface(axdev->intf); + + return 0; +} + +u32 ax_get_msglevel(struct net_device *netdev) +{ + struct ax_device *axdev = netdev_priv(netdev); + + return axdev->msg_enable; +} + +void ax_set_msglevel(struct net_device *netdev, u32 value) +{ + struct ax_device *axdev = netdev_priv(netdev); + + axdev->msg_enable = value; +} + +void ax_get_wol(struct net_device *netdev, struct ethtool_wolinfo *wolinfo) +{ + struct ax_device *axdev = netdev_priv(netdev); + u8 reg8; + int ret; + + ret = ax_read_cmd(axdev, AX_ACCESS_MAC, AX_MONITOR_MODE, + 1, 1, ®8, 0); + if (ret < 0) { + wolinfo->supported = 0; + wolinfo->wolopts = 0; + return; + } + + wolinfo->supported = WAKE_PHY | WAKE_MAGIC; + + if (reg8 & AX_MONITOR_MODE_RWLC) + wolinfo->wolopts |= WAKE_PHY; + if (reg8 & AX_MONITOR_MODE_RWMP) + wolinfo->wolopts |= WAKE_MAGIC; +} + +int ax_set_wol(struct net_device *netdev, struct ethtool_wolinfo *wolinfo) +{ + struct ax_device *axdev = netdev_priv(netdev); + u8 reg8 = 0; + int ret; + + if (wolinfo->wolopts & WAKE_PHY) + reg8 |= AX_MONITOR_MODE_RWLC; + else + reg8 &= ~AX_MONITOR_MODE_RWLC; + + if (wolinfo->wolopts & WAKE_MAGIC) + reg8 |= AX_MONITOR_MODE_RWMP; + else + reg8 &= ~AX_MONITOR_MODE_RWMP; + + ret = ax_write_cmd(axdev, AX_ACCESS_MAC, AX_MONITOR_MODE, 1, 1, ®8); + if (ret < 0) + return ret; + + return 0; +} + +static const char ax_gstrings[][ETH_GSTRING_LEN] = { + "tx_packets", + "rx_packets", + "tx_bytes", + "rx_bytes", + "tx_dropped", + "rx_length_errors", + "rx_crc_errors", + "rx_dropped", + "buikin_complete", + "bulkin_error", + "bulkout_complete", + "bulkout_error", + "bulkint_complete", + "bulkint_error", +}; + +int ax_get_sset_count(struct net_device *netdev, int sset) +{ + switch (sset) { + case ETH_SS_STATS: + return ARRAY_SIZE(ax_gstrings); + default: + return -EOPNOTSUPP; + } +} + +void ax_get_strings(struct net_device *netdev, u32 stringset, u8 *data) +{ + switch (stringset) { + case ETH_SS_STATS: + memcpy(data, ax_gstrings, sizeof(ax_gstrings)); + break; + } +} + +void ax_get_ethtool_stats(struct net_device *netdev, + struct ethtool_stats *stats, u64 *data) +{ + struct net_device_stats *net_stats = ax_get_stats(netdev); + struct ax_device *axdev = netdev_priv(netdev); + u64 *temp = data; + + *temp++ = le32_to_cpu(net_stats->tx_packets); + *temp++ = le32_to_cpu(net_stats->rx_packets); + *temp++ = le32_to_cpu(net_stats->tx_bytes); + *temp++ = le32_to_cpu(net_stats->rx_bytes); + *temp++ = le32_to_cpu(net_stats->tx_dropped); + *temp++ = le32_to_cpu(net_stats->rx_length_errors); + *temp++ = le32_to_cpu(net_stats->rx_crc_errors); + *temp++ = le32_to_cpu(net_stats->rx_dropped); + *temp++ = le64_to_cpu(axdev->bulkin_complete); + *temp++ = le64_to_cpu(axdev->bulkin_error); + *temp++ = le64_to_cpu(axdev->bulkout_complete); + *temp++ = le64_to_cpu(axdev->bulkout_error); + *temp++ = le64_to_cpu(axdev->bulkint_complete); + *temp++ = le64_to_cpu(axdev->bulkint_error); +} + +void ax_get_pauseparam(struct net_device *netdev, + struct ethtool_pauseparam *pause) +{ + struct ax_device *axdev = netdev_priv(netdev); + u16 bmcr, lcladv, rmtadv; + u8 cap; + + if (usb_autopm_get_interface(axdev->intf) < 0) + return; + + bmcr = ax_mdio_read(netdev, axdev->mii.phy_id, MII_BMCR); + lcladv = ax_mdio_read(netdev, axdev->mii.phy_id, MII_ADVERTISE); + rmtadv = ax_mdio_read(netdev, axdev->mii.phy_id, MII_LPA); + + usb_autopm_put_interface(axdev->intf); + + if (!(bmcr & BMCR_ANENABLE)) { + pause->autoneg = 0; + pause->rx_pause = 0; + pause->tx_pause = 0; + return; + } + + pause->autoneg = 1; + + cap = mii_resolve_flowctrl_fdx(lcladv, rmtadv); + + if (cap & FLOW_CTRL_RX) + pause->rx_pause = 1; + + if (cap & FLOW_CTRL_TX) + pause->tx_pause = 1; +} + +int ax_set_pauseparam(struct net_device *netdev, + struct ethtool_pauseparam *pause) +{ + struct ax_device *axdev = netdev_priv(netdev); + u16 old, new1, bmcr; + u8 cap = 0; + int ret; + + ret = usb_autopm_get_interface(axdev->intf); + if (ret < 0) + return ret; + + mutex_lock(&axdev->control); + + bmcr = ax_mdio_read(netdev, axdev->mii.phy_id, MII_BMCR); + if (pause->autoneg && !(bmcr & BMCR_ANENABLE)) { + ret = -EINVAL; + goto out; + } + + if (pause->rx_pause) + cap |= FLOW_CTRL_RX; + + if (pause->tx_pause) + cap |= FLOW_CTRL_TX; + + old = ax_mdio_read(netdev, axdev->mii.phy_id, MII_ADVERTISE); + new1 = (old & ~(ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM)) | + mii_advertise_flowctrl(cap); + if (old != new1) + ax_mdio_write(netdev, axdev->mii.phy_id, MII_ADVERTISE, new1); + + mii_nway_restart(&axdev->mii); +out: + mutex_unlock(&axdev->control); + usb_autopm_put_interface(axdev->intf); + + return ret; +} + +int ax_get_regs_len(struct net_device *netdev) +{ + return 256; +} + +void ax_get_regs(struct net_device *netdev, + struct ethtool_regs *regs, void *buf) +{ + u8 *data = (u8 *)buf; + int i; + struct ax_device *axdev = netdev_priv(netdev); + + for (i = 0; i < 256; i++) + ax_read_cmd(axdev, AX_ACCESS_MAC, i, 1, 1, &data[i], 0); +} + +static int __ax_usb_read_cmd(struct ax_device *axdev, u8 cmd, u8 reqtype, + u16 value, u16 index, void *data, u16 size) +{ + void *buf = NULL; + int err = -ENOMEM; + + if (size) { + buf = kzalloc(size, GFP_KERNEL); + if (!buf) + goto out; + } + + err = usb_control_msg(axdev->udev, usb_rcvctrlpipe(axdev->udev, 0), + cmd, reqtype, value, index, buf, size, + USB_CTRL_GET_TIMEOUT); + if (err > 0 && err <= size) { + if (data) + memcpy(data, buf, err); + else + netdev_dbg(axdev->netdev, + "Huh? Data requested but thrown away.\n"); + } + + kfree(buf); +out: + return err; +} + +static int __ax_usb_write_cmd(struct ax_device *axdev, u8 cmd, u8 reqtype, + u16 value, u16 index, const void *data, u16 size) +{ + void *buf = NULL; + int err = -ENOMEM; + + if (data) { + buf = kmemdup(data, size, GFP_KERNEL); + if (!buf) + goto out; + } else { + if (size) { + WARN_ON_ONCE(1); + err = -EINVAL; + goto out; + } + } + + err = usb_control_msg(axdev->udev, usb_sndctrlpipe(axdev->udev, 0), + cmd, reqtype, value, index, buf, size, + USB_CTRL_SET_TIMEOUT); + kfree(buf); + +out: + return err; +} + +static int __ax_read_cmd(struct ax_device *axdev, u8 cmd, u8 reqtype, + u16 value, u16 index, void *data, u16 size) +{ + int ret; + + if (usb_autopm_get_interface(axdev->intf) < 0) + return -ENODEV; + + ret = __ax_usb_read_cmd(axdev, cmd, reqtype, value, index, + data, size); + + usb_autopm_put_interface(axdev->intf); + + return ret; +} + +static int __ax_write_cmd(struct ax_device *axdev, u8 cmd, u8 reqtype, + u16 value, u16 index, const void *data, u16 size) +{ + int ret; + + if (usb_autopm_get_interface(axdev->intf) < 0) + return -ENODEV; + + ret = __ax_usb_write_cmd(axdev, cmd, reqtype, value, index, + data, size); + + usb_autopm_put_interface(axdev->intf); + + return ret; +} + +static int __ax_read_cmd_nopm(struct ax_device *axdev, u8 cmd, u8 reqtype, + u16 value, u16 index, void *data, u16 size) +{ + return __ax_usb_read_cmd(axdev, cmd, reqtype, value, index, + data, size); +} + +static int __ax_write_cmd_nopm(struct ax_device *axdev, u8 cmd, u8 reqtype, + u16 value, u16 index, const void *data, + u16 size) +{ + return __ax_usb_write_cmd(axdev, cmd, reqtype, value, index, + data, size); +} + +static int __asix_read_cmd(struct ax_device *axdev, u8 cmd, u16 value, + u16 index, u16 size, void *data, int in_pm) +{ + int ret; + _usb_read_function fn; + + if (!in_pm) + fn = __ax_read_cmd; + else + fn = __ax_read_cmd_nopm; + + ret = fn(axdev, cmd, USB_DIR_IN | USB_TYPE_VENDOR | + USB_RECIP_DEVICE, value, index, data, size); + + if (unlikely(ret < 0)) + dev_warn(&axdev->intf->dev, + "Failed to read reg %04X_%04X_%04X_%04X (err %d)", + cmd, value, index, size, ret); + + return ret; +} + +static int __asix_write_cmd(struct ax_device *axdev, u8 cmd, u16 value, + u16 index, u16 size, void *data, int in_pm) +{ + int ret; + _usb_write_function fn; + + if (!in_pm) + fn = __ax_write_cmd; + else + fn = __ax_write_cmd_nopm; + + ret = fn(axdev, cmd, USB_DIR_OUT | USB_TYPE_VENDOR | + USB_RECIP_DEVICE, value, index, data, size); + + if (unlikely(ret < 0)) + dev_warn(&axdev->intf->dev, "Failed to write reg %04X_%04X_%04X_%04X (err %d)", + cmd, value, index, size, ret); + + return ret; +} + +int ax_read_cmd_nopm(struct ax_device *dev, u8 cmd, u16 value, + u16 index, u16 size, void *data, int eflag) +{ + int ret; + + if (eflag && size == 2) { + u16 buf = 0; + + ret = __asix_read_cmd(dev, cmd, value, index, size, &buf, 1); + le16_to_cpus(&buf); + *((u16 *)data) = buf; + } else if (eflag && (size == 4)) { + u32 buf = 0; + + ret = __asix_read_cmd(dev, cmd, value, index, size, &buf, 1); + le32_to_cpus(&buf); + *((u32 *)data) = buf; + } else { + ret = __asix_read_cmd(dev, cmd, value, index, size, data, 1); + } + + return ret; +} + +int ax_write_cmd_nopm(struct ax_device *dev, u8 cmd, u16 value, + u16 index, u16 size, void *data) +{ + int ret; + + if (size == 2) { + u16 buf = 0; + + buf = *((u16 *)data); + cpu_to_le16s(&buf); + ret = __asix_write_cmd(dev, cmd, value, index, size, &buf, 1); + } else { + ret = __asix_write_cmd(dev, cmd, value, index, size, data, 1); + } + + return ret; +} + +int ax_read_cmd(struct ax_device *dev, u8 cmd, u16 value, u16 index, u16 size, + void *data, int eflag) +{ + int ret; + + if (eflag && size == 2) { + u16 buf = 0; + + ret = __asix_read_cmd(dev, cmd, value, index, size, &buf, 0); + le16_to_cpus(&buf); + *((u16 *)data) = buf; + } else if (eflag && (size == 4)) { + u32 buf = 0; + + ret = __asix_read_cmd(dev, cmd, value, index, size, &buf, 0); + le32_to_cpus(&buf); + *((u32 *)data) = buf; + } else { + ret = __asix_read_cmd(dev, cmd, value, index, size, data, 0); + } + + return ret; +} + +int ax_write_cmd(struct ax_device *dev, u8 cmd, u16 value, u16 index, u16 size, + void *data) +{ + int ret; + + if (size == 2) { + u16 buf = 0; + + buf = *((u16 *)data); + cpu_to_le16s(&buf); + ret = __asix_write_cmd(dev, cmd, value, index, size, &buf, 0); + } else { + ret = __asix_write_cmd(dev, cmd, value, index, size, data, 0); + } + + return ret; +} + +static void ax_async_write_callback(struct urb *urb) +{ + struct _async_cmd_handle *asyncdata = (typeof(asyncdata))urb->context; + + if (urb->status < 0) + dev_err(&asyncdata->axdev->intf->dev, + "%s() failed with %d", __func__, urb->status); + + kfree(asyncdata->req); + kfree(asyncdata); + usb_free_urb(urb); +} + +int ax_write_cmd_async(struct ax_device *axdev, u8 cmd, u16 value, u16 index, + u16 size, void *data) +{ + struct usb_ctrlrequest *req = NULL; + int status = 0; + struct urb *urb = NULL; + void *buf = NULL; + struct _async_cmd_handle *asyncdata = NULL; + + urb = usb_alloc_urb(0, GFP_ATOMIC); + if (!urb) { + netdev_err(axdev->netdev, + "Error allocating URB in %s!", __func__); + return -ENOMEM; + } + + req = kzalloc(sizeof(*req), GFP_ATOMIC); + if (!req) { + usb_free_urb(urb); + return -ENOMEM; + } + + asyncdata = kzalloc(sizeof(*asyncdata), GFP_ATOMIC); + if (!asyncdata) { + kfree(req); + usb_free_urb(urb); + return -ENOMEM; + } + + asyncdata->req = req; + asyncdata->axdev = axdev; + + if (size == 2) { + asyncdata->rxctl = *((u16 *)data); + cpu_to_le16s(&asyncdata->rxctl); + buf = &asyncdata->rxctl; + } else { + memcpy(asyncdata->m_filter, data, size); + buf = asyncdata->m_filter; + } + + req->bRequestType = USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE; + req->bRequest = cmd; + req->wValue = cpu_to_le16(value); + req->wIndex = cpu_to_le16(index); + req->wLength = cpu_to_le16(size); + + usb_fill_control_urb(urb, axdev->udev, usb_sndctrlpipe(axdev->udev, 0), + (void *)req, buf, size, ax_async_write_callback, + asyncdata); + + status = usb_submit_urb(urb, GFP_ATOMIC); + if (status < 0) { + netdev_err(axdev->netdev, + "Error submitting the control message: status=%d", + status); + kfree(req); + kfree(asyncdata); + usb_free_urb(urb); + } + + return status; +} + +int ax_mmd_read(struct net_device *netdev, int dev_addr, int reg) +{ + struct ax_device *axdev = netdev_priv(netdev); + u16 res = 0; + + ax_read_cmd(axdev, AX88179A_PHY_CLAUSE45, (__u16)dev_addr, + (__u16)reg, 2, &res, 1); + + return res; +} + +void ax_mmd_write(struct net_device *netdev, int dev_addr, int reg, int val) +{ + struct ax_device *axdev = netdev_priv(netdev); + u16 res = (u16)val; + + ax_write_cmd(axdev, AX88179A_PHY_CLAUSE45, (__u16)dev_addr, + (__u16)reg, 2, &res); +} + +int ax_mdio_read(struct net_device *netdev, int phy_id, int reg) +{ + struct ax_device *axdev = netdev_priv(netdev); + u16 res; + + ax_read_cmd(axdev, AX_ACCESS_PHY, phy_id, (__u16)reg, 2, &res, 1); + + return res; +} + +void ax_mdio_write(struct net_device *netdev, int phy_id, int reg, int val) +{ + struct ax_device *axdev = netdev_priv(netdev); + u16 res = (u16)val; + + ax_write_cmd(axdev, AX_ACCESS_PHY, phy_id, (__u16)reg, 2, &res); +} + +inline struct net_device_stats *ax_get_stats(struct net_device *netdev) +{ + return &netdev->stats; +} + +static void ax_set_unplug(struct ax_device *axdev) +{ + if (axdev->udev->state == USB_STATE_NOTATTACHED) + set_bit(AX_UNPLUG, &axdev->flags); +} + +static int ax_check_tx_queue_not_empty(struct ax_device *axdev) +{ + int i; + + for (i = (AX_TX_QUEUE_SIZE - 1); i >= 0; i--) + if (!skb_queue_empty(&axdev->tx_queue[i])) + return i; + + return -1; +} + +static bool ax_check_tx_queue_len(struct ax_device *axdev) +{ + int i; + + for (i = 0; i < AX_TX_QUEUE_SIZE; i++) + if (skb_queue_len(&axdev->tx_queue[i]) > axdev->tx_qlen) + return true; + + return false; +} + +static void ax_read_bulk_callback(struct urb *urb) +{ + struct net_device *netdev; + int status = urb->status; + struct rx_desc *desc; + struct ax_device *axdev; + + desc = urb->context; + if (!desc) + return; + + axdev = desc->context; + if (!axdev) + return; + + if (test_bit(AX_UNPLUG, &axdev->flags) || + !test_bit(AX_ENABLE, &axdev->flags)) + return; + + netdev = axdev->netdev; + + if (!netif_carrier_ok(netdev)) + return; + + usb_mark_last_busy(axdev->udev); + + if (status) + axdev->bulkin_error++; + else + axdev->bulkin_complete++; + + switch (status) { + case 0: + if (urb->actual_length < ETH_ZLEN) + break; + + spin_lock(&axdev->rx_lock); + list_add_tail(&desc->list, &axdev->rx_done); + spin_unlock(&axdev->rx_lock); + napi_schedule(&axdev->napi); + return; + case -ESHUTDOWN: + ax_set_unplug(axdev); + netif_device_detach(axdev->netdev); + return; + case -ENOENT: + return; + case -ETIME: + if (net_ratelimit()) + netif_err(axdev, rx_err, netdev, + "maybe reset is needed?\n"); + break; + default: + if (net_ratelimit()) + netif_err(axdev, rx_err, netdev, + "RX status %d\n", status); + break; + } + + ax_submit_rx(axdev, desc, GFP_ATOMIC); +} + +void ax_write_bulk_callback(struct urb *urb) +{ + struct net_device_stats *stats; + struct net_device *netdev; + struct tx_desc *desc; + struct ax_device *axdev; + int status = urb->status; + + desc = urb->context; + if (!desc) + return; + + axdev = desc->context; + if (!axdev) + return; + + netdev = axdev->netdev; + stats = ax_get_stats(netdev); + + if (status) + axdev->bulkout_error++; + else + axdev->bulkout_complete++; + + if (status) { + if (net_ratelimit()) + netif_warn(axdev, tx_err, netdev, + "TX status %d\n", status); + stats->tx_errors += desc->skb_num; + } else { + stats->tx_packets += desc->skb_num; + stats->tx_bytes += desc->skb_len; + } + + spin_lock(&axdev->tx_lock); + list_add_tail(&desc->list, &axdev->tx_free); + spin_unlock(&axdev->tx_lock); + + usb_autopm_put_interface_async(axdev->intf); + + if (!netif_carrier_ok(netdev)) + return; + if (!test_bit(AX_ENABLE, &axdev->flags)) + return; + if (test_bit(AX_UNPLUG, &axdev->flags)) + return; + + if (ax_check_tx_queue_not_empty(axdev) >= 0) + napi_schedule(&axdev->napi); +} + +static void ax_intr_callback(struct urb *urb) +{ + struct ax_device *axdev; + struct ax_device_int_data *event = NULL; + int status = urb->status; + int res; + + axdev = urb->context; + if (!axdev) + return; + + if (!test_bit(AX_ENABLE, &axdev->flags) || + test_bit(AX_UNPLUG, &axdev->flags)) + return; + + if (status) + axdev->bulkint_error++; + else + axdev->bulkint_complete++; + + switch (status) { + case 0: + break; + case -ECONNRESET: + case -ESHUTDOWN: + netif_device_detach(axdev->netdev); + netif_err(axdev, intr, axdev->netdev, + "Stop submitting intr, status %d\n", status); + return; + case -ENOENT: + netif_err(axdev, intr, axdev->netdev, + "Stop submitting intr, status %d\n", status); + return; + case -EPROTO: + netif_err(axdev, intr, axdev->netdev, + "Stop submitting intr, status %d\n", status); + return; + case -EOVERFLOW: + netif_err(axdev, intr, axdev->netdev, + "intr status -EOVERFLOW\n"); + goto resubmit; + default: + netif_err(axdev, intr, axdev->netdev, + "intr status %d\n", status); + goto resubmit; + } + + event = urb->transfer_buffer; + axdev->link = event->link & AX_INT_PPLS_LINK; + axdev->intr_link_info = event->link_info; + + if (axdev->link) { + if (!netif_carrier_ok(axdev->netdev)) { + set_bit(AX_LINK_CHG, &axdev->flags); + schedule_delayed_work(&axdev->schedule, 0); + } + } else { + if (netif_carrier_ok(axdev->netdev)) { + netif_stop_queue(axdev->netdev); + set_bit(AX_LINK_CHG, &axdev->flags); + schedule_delayed_work(&axdev->schedule, 0); + } + } + +resubmit: + res = usb_submit_urb(urb, GFP_ATOMIC); + if (res == -ENODEV) { + ax_set_unplug(axdev); + netif_device_detach(axdev->netdev); + } else if (res) { + netif_err(axdev, intr, axdev->netdev, + "can't resubmit intr, status %d\n", res); + } +} + +inline void *__rx_buf_align(void *data) +{ + return (void *)ALIGN((uintptr_t)data, RX_ALIGN); +} + +inline void *__tx_buf_align(void *data, u8 tx_align_len) +{ + return (void *)ALIGN((uintptr_t)data, tx_align_len); +} + +static void ax_free_buffer(struct ax_device *axdev) +{ + int i; + + for (i = 0; i < AX88179_MAX_RX; i++) { + usb_free_urb(axdev->rx_list[i].urb); + axdev->rx_list[i].urb = NULL; + + kfree(axdev->rx_list[i].buffer); + axdev->rx_list[i].buffer = NULL; + axdev->rx_list[i].head = NULL; + } + + for (i = 0; i < AX88179_MAX_TX; i++) { + usb_free_urb(axdev->tx_list[i].urb); + axdev->tx_list[i].urb = NULL; + + kfree(axdev->tx_list[i].buffer); + axdev->tx_list[i].buffer = NULL; + axdev->tx_list[i].head = NULL; + } + + usb_free_urb(axdev->intr_urb); + axdev->intr_urb = NULL; + + kfree(axdev->intr_buff); + axdev->intr_buff = NULL; +} + +static int ax_alloc_buffer(struct ax_device *axdev) +{ + struct net_device *netdev = axdev->netdev; + struct usb_interface *intf = axdev->intf; + struct usb_host_interface *alt = intf->cur_altsetting; + struct usb_host_endpoint *ep_intr = alt->endpoint; + struct urb *urb; + int node, i; + u8 *buf; + + node = netdev->dev.parent ? dev_to_node(netdev->dev.parent) : -1; + + spin_lock_init(&axdev->rx_lock); + spin_lock_init(&axdev->tx_lock); + INIT_LIST_HEAD(&axdev->tx_free); + INIT_LIST_HEAD(&axdev->rx_done); + for (i = 0; i < AX_TX_QUEUE_SIZE; i++) + skb_queue_head_init(&axdev->tx_queue[i]); + skb_queue_head_init(&axdev->rx_queue); + + for (i = 0; i < AX88179_MAX_RX; i++) { + buf = kmalloc_node(axdev->driver_info->buf_rx_size, GFP_KERNEL, node); + if (!buf) + goto err1; + + if (buf != __rx_buf_align(buf)) { + kfree(buf); + buf = kmalloc_node(axdev->driver_info->buf_rx_size + RX_ALIGN, + GFP_KERNEL, node); + if (!buf) + goto err1; + } + urb = usb_alloc_urb(0, GFP_KERNEL); + if (!urb) { + kfree(buf); + goto err1; + } + + INIT_LIST_HEAD(&axdev->rx_list[i].list); + axdev->rx_list[i].context = axdev; + axdev->rx_list[i].urb = urb; + axdev->rx_list[i].buffer = buf; + axdev->rx_list[i].head = __rx_buf_align(buf); + } + + for (i = 0; i < AX88179_MAX_TX; i++) { + buf = kmalloc_node(AX88179_BUF_TX_SIZE, GFP_KERNEL, node); + if (!buf) + goto err1; + + if (buf != __tx_buf_align(buf, axdev->tx_align_len)) { + kfree(buf); + buf = kmalloc_node(AX88179_BUF_TX_SIZE + axdev->tx_align_len, + GFP_KERNEL, node); + if (!buf) + goto err1; + } + + urb = usb_alloc_urb(0, GFP_KERNEL); + if (!urb) { + kfree(buf); + goto err1; + } + + INIT_LIST_HEAD(&axdev->tx_list[i].list); + axdev->tx_list[i].context = axdev; + axdev->tx_list[i].urb = urb; + axdev->tx_list[i].buffer = buf; + axdev->tx_list[i].head = __tx_buf_align(buf, + axdev->tx_align_len); + + list_add_tail(&axdev->tx_list[i].list, &axdev->tx_free); + } + + axdev->intr_urb = usb_alloc_urb(0, GFP_KERNEL); + if (!axdev->intr_urb) + goto err1; + + axdev->intr_buff = kzalloc(INTBUFSIZE, GFP_KERNEL); + if (!axdev->intr_buff) + goto err1; + + axdev->intr_interval = (int)ep_intr->desc.bInterval; + usb_fill_int_urb(axdev->intr_urb, axdev->udev, + usb_rcvintpipe(axdev->udev, 1), axdev->intr_buff, + INTBUFSIZE, ax_intr_callback, axdev, + axdev->intr_interval); + + return 0; +err1: + ax_free_buffer(axdev); + return -ENOMEM; +} + +static struct tx_desc *ax_get_tx_desc(struct ax_device *dev) +{ + struct tx_desc *desc = NULL; + unsigned long flags; + + if (list_empty(&dev->tx_free)) + return NULL; + + spin_lock_irqsave(&dev->tx_lock, flags); + if (!list_empty(&dev->tx_free)) { + struct list_head *cursor; + + cursor = dev->tx_free.next; + list_del_init(cursor); + desc = list_entry(cursor, struct tx_desc, list); + } + spin_unlock_irqrestore(&dev->tx_lock, flags); + + return desc; +} + +static void ax_tx_bottom(struct ax_device *axdev) +{ + const struct driver_info *info = axdev->driver_info; + int ret; + + do { + struct tx_desc *desc; + int index = -1; + + index = ax_check_tx_queue_not_empty(axdev); + if (index < 0) + break; + + desc = ax_get_tx_desc(axdev); + if (!desc) + break; + desc->q_index = 0; + ret = info->tx_fixup(axdev, desc); + if (ret) { + struct net_device *netdev = axdev->netdev; + + if (ret == -ENODEV) { + ax_set_unplug(axdev); + netif_device_detach(netdev); + } else { + struct net_device_stats *stats; + unsigned long flags; + + stats = ax_get_stats(netdev); + stats->tx_dropped += desc->skb_num; + + spin_lock_irqsave(&axdev->tx_lock, flags); + list_add_tail(&desc->list, &axdev->tx_free); + spin_unlock_irqrestore(&axdev->tx_lock, flags); + } + } + } while (ret == 0); +} + +static void ax_bottom_half(struct ax_device *axdev) +{ + if (test_bit(AX_UNPLUG, &axdev->flags) || + !test_bit(AX_ENABLE, &axdev->flags) || + !netif_carrier_ok(axdev->netdev)) + return; + + clear_bit(AX_SCHEDULE_NAPI, &axdev->flags); + + ax_tx_bottom(axdev); +} + +static int ax_rx_bottom(struct ax_device *axdev, int budget) +{ + unsigned long flags; + struct list_head *cursor, *next, rx_queue; + int ret = 0, work_done = 0; + struct napi_struct *napi = &axdev->napi; + struct net_device *netdev = axdev->netdev; + struct net_device_stats *stats = ax_get_stats(netdev); + + if (!skb_queue_empty(&axdev->rx_queue)) { + while (work_done < budget) { + struct sk_buff *skb = __skb_dequeue(&axdev->rx_queue); + unsigned int pkt_len; + + if (!skb) + break; + + pkt_len = skb->len; + napi_gro_receive(napi, skb); + work_done++; + stats->rx_packets++; + stats->rx_bytes += pkt_len; + } + } + + if (list_empty(&axdev->rx_done)) + return work_done; + + INIT_LIST_HEAD(&rx_queue); + spin_lock_irqsave(&axdev->rx_lock, flags); + list_splice_init(&axdev->rx_done, &rx_queue); + spin_unlock_irqrestore(&axdev->rx_lock, flags); + + list_for_each_safe(cursor, next, &rx_queue) { + struct rx_desc *desc; + + list_del_init(cursor); + + desc = list_entry(cursor, struct rx_desc, list); + + if (desc->urb->actual_length < ETH_ZLEN) + goto submit; + + if (unlikely(skb_queue_len(&axdev->rx_queue) >= 1000)) + goto submit; + + axdev->driver_info->rx_fixup(axdev, desc, &work_done, budget); +submit: + if (!ret) { + ret = ax_submit_rx(axdev, desc, GFP_ATOMIC); + } else { + desc->urb->actual_length = 0; + list_add_tail(&desc->list, next); + } + } + + if (!list_empty(&rx_queue)) { + spin_lock_irqsave(&axdev->rx_lock, flags); + list_splice_tail(&rx_queue, &axdev->rx_done); + spin_unlock_irqrestore(&axdev->rx_lock, flags); + } + + return work_done; +} + +static +int ax_submit_rx(struct ax_device *dev, struct rx_desc *desc, gfp_t mem_flags) +{ + int ret; + + if (test_bit(AX_UNPLUG, &dev->flags) || + !test_bit(AX_ENABLE, &dev->flags) || + !netif_carrier_ok(dev->netdev)) + return 0; + + usb_fill_bulk_urb(desc->urb, dev->udev, usb_rcvbulkpipe(dev->udev, 2), + desc->head, dev->driver_info->buf_rx_size, + (usb_complete_t)ax_read_bulk_callback, desc); + + ret = usb_submit_urb(desc->urb, mem_flags); + if (ret == -ENODEV) { + ax_set_unplug(dev); + netif_device_detach(dev->netdev); + } else if (ret) { + struct urb *urb = desc->urb; + unsigned long flags; + + urb->actual_length = 0; + spin_lock_irqsave(&dev->rx_lock, flags); + list_add_tail(&desc->list, &dev->rx_done); + spin_unlock_irqrestore(&dev->rx_lock, flags); + + netif_err(dev, rx_err, dev->netdev, + "Couldn't submit rx[%p], ret = %d\n", desc, ret); + + napi_schedule(&dev->napi); + } + + return ret; +} + +static inline int __ax_poll(struct ax_device *axdev, int budget) +{ + struct napi_struct *napi = &axdev->napi; + int work_done; + + work_done = ax_rx_bottom(axdev, budget); + ax_bottom_half(axdev); + + if (work_done < budget) { + if (!napi_complete_done(napi, work_done)) + return work_done; + if (!list_empty(&axdev->rx_done)) + napi_schedule(napi); + else if (ax_check_tx_queue_not_empty(axdev) >= 0 && + !list_empty(&axdev->tx_free)) + napi_schedule(napi); + } + + return work_done; +} + +static int ax_poll(struct napi_struct *napi, int budget) +{ + struct ax_device *axdev = container_of(napi, struct ax_device, napi); + + return __ax_poll(axdev, budget); +} + +static void ax_drop_queued_tx(struct ax_device *axdev) +{ + struct net_device_stats *stats = ax_get_stats(axdev->netdev); + struct sk_buff_head skb_head, *tx_queue = axdev->tx_queue; + struct sk_buff *skb; + int i; + + for (i = 0; i < AX_TX_QUEUE_SIZE; i++) { + if (skb_queue_empty(&tx_queue[i])) + continue; + + __skb_queue_head_init(&skb_head); + spin_lock_bh(&tx_queue[i].lock); + skb_queue_splice_init(&tx_queue[i], &skb_head); + spin_unlock_bh(&tx_queue[i].lock); + + while ((skb = __skb_dequeue(&skb_head))) { + dev_kfree_skb(skb); + stats->tx_dropped++; + } + } +} + +static void ax_tx_timeout(struct net_device *netdev, unsigned int txqueue) +{ + struct ax_device *axdev = netdev_priv(netdev); + + netif_warn(axdev, tx_err, netdev, "Tx timeout\n"); + + usb_queue_reset_device(axdev->intf); +} + +static netdev_tx_t ax_start_xmit(struct sk_buff *skb, struct net_device *netdev) +{ + struct ax_device *axdev = netdev_priv(netdev); + + skb_tx_timestamp(skb); + skb_queue_tail(&axdev->tx_queue[0], skb); + if (!list_empty(&axdev->tx_free)) { + if (test_bit(AX_SELECTIVE_SUSPEND, &axdev->flags)) { + set_bit(AX_SCHEDULE_NAPI, &axdev->flags); + schedule_delayed_work(&axdev->schedule, 0); + } else { + usb_mark_last_busy(axdev->udev); + napi_schedule(&axdev->napi); + } + } else if (ax_check_tx_queue_len(axdev)) { + netif_stop_queue(netdev); + } + + return NETDEV_TX_OK; +} + +void ax_set_tx_qlen(struct ax_device *dev) +{ + struct net_device *netdev = dev->netdev; + + dev->tx_qlen = AX88179_BUF_TX_SIZE / (netdev->mtu + ETH_FCS_LEN + 8); +} + +static int ax_start_rx(struct ax_device *axdev) +{ + int i, ret = 0; + + INIT_LIST_HEAD(&axdev->rx_done); + for (i = 0; i < AX88179_MAX_RX; i++) { + INIT_LIST_HEAD(&axdev->rx_list[i].list); + ret = ax_submit_rx(axdev, &axdev->rx_list[i], GFP_KERNEL); + if (ret) + break; + } + + if (ret && ++i < AX88179_MAX_RX) { + struct list_head rx_queue; + unsigned long flags; + + INIT_LIST_HEAD(&rx_queue); + + do { + struct rx_desc *desc = &axdev->rx_list[i++]; + struct urb *urb = desc->urb; + + urb->actual_length = 0; + list_add_tail(&desc->list, &rx_queue); + } while (i < AX88179_MAX_RX); + + spin_lock_irqsave(&axdev->rx_lock, flags); + list_splice_tail(&rx_queue, &axdev->rx_done); + spin_unlock_irqrestore(&axdev->rx_lock, flags); + } + + return ret; +} + +static int ax_stop_rx(struct ax_device *axdev) +{ + int i; + + for (i = 0; i < AX88179_MAX_RX; i++) + usb_kill_urb(axdev->rx_list[i].urb); + + while (!skb_queue_empty(&axdev->rx_queue)) + dev_kfree_skb(__skb_dequeue(&axdev->rx_queue)); + + return 0; +} + +static void ax_disable(struct ax_device *axdev) +{ + int i; + + if (test_bit(AX_UNPLUG, &axdev->flags)) { + ax_drop_queued_tx(axdev); + return; + } + + for (i = 0; i < AX88179_MAX_TX; i++) + usb_kill_urb(axdev->tx_list[i].urb); + + ax_stop_rx(axdev); +} + +static int ax88179_set_features(struct net_device *net, netdev_features_t features) +{ + struct ax_device *dev = netdev_priv(net); + u8 reg8; + netdev_features_t changed = net->features ^ features; + + if (changed & NETIF_F_IP_CSUM) { + ax_read_cmd(dev, AX_ACCESS_MAC, AX_TXCOE_CTL, 1, 1, ®8, 0); + reg8 ^= AX_TXCOE_TCP | AX_TXCOE_UDP; + ax_write_cmd(dev, AX_ACCESS_MAC, AX_TXCOE_CTL, 1, 1, ®8); + } + + if (changed & NETIF_F_IPV6_CSUM) { + ax_read_cmd(dev, AX_ACCESS_MAC, AX_TXCOE_CTL, 1, 1, ®8, 0); + reg8 ^= AX_TXCOE_TCPV6 | AX_TXCOE_UDPV6; + ax_write_cmd(dev, AX_ACCESS_MAC, AX_TXCOE_CTL, 1, 1, ®8); + } + + if (changed & NETIF_F_RXCSUM) { + ax_read_cmd(dev, AX_ACCESS_MAC, AX_RXCOE_CTL, 1, 1, ®8, 0); + reg8 ^= AX_RXCOE_IP | AX_RXCOE_TCP | AX_RXCOE_UDP | + AX_RXCOE_TCPV6 | AX_RXCOE_UDPV6; + ax_write_cmd(dev, AX_ACCESS_MAC, AX_RXCOE_CTL, 1, 1, ®8); + } + + return 0; +} + +static void ax_set_carrier(struct ax_device *axdev) +{ + struct net_device *netdev = axdev->netdev; + struct napi_struct *napi = &axdev->napi; + + if (axdev->link) { + if (!netif_carrier_ok(netdev)) { + if (axdev->driver_info->link_reset(axdev)) + return; + netif_stop_queue(netdev); + napi_disable(napi); + netif_carrier_on(netdev); + ax_start_rx(axdev); + napi_enable(napi); + netif_wake_queue(netdev); + } else if (netif_queue_stopped(netdev) && + ax_check_tx_queue_len(axdev)) { + netif_wake_queue(netdev); + } + } else { + if (netif_carrier_ok(netdev)) { + netif_carrier_off(netdev); + napi_disable(napi); + ax_disable(axdev); + napi_enable(napi); + } + } + if (!test_bit(AX_SELECTIVE_SUSPEND, &axdev->flags)) + mii_check_media(&axdev->mii, 1, 1); +} + +static inline void __ax_work_func(struct ax_device *axdev) +{ + if (test_bit(AX_UNPLUG, &axdev->flags) || !netif_running(axdev->netdev)) + return; + + if (usb_autopm_get_interface(axdev->intf) < 0) + return; + + if (!test_bit(AX_ENABLE, &axdev->flags)) + goto out; + + if (!mutex_trylock(&axdev->control)) { + schedule_delayed_work(&axdev->schedule, 0); + goto out; + } + + if (test_and_clear_bit(AX_LINK_CHG, &axdev->flags)) + ax_set_carrier(axdev); + + if (test_and_clear_bit(AX_SCHEDULE_NAPI, &axdev->flags) && + netif_carrier_ok(axdev->netdev)) + napi_schedule(&axdev->napi); + + mutex_unlock(&axdev->control); + +out: + usb_autopm_put_interface(axdev->intf); +} + +static void ax_work_func_t(struct work_struct *work) +{ + struct ax_device *axdev = container_of(work, + struct ax_device, schedule.work); + + __ax_work_func(axdev); +} + +int ax_usb_command(struct ax_device *axdev, struct _ax_ioctl_command *info) +{ + struct _ax_usb_command *usb_cmd = &info->usb_cmd; + void *buf; + int err, timeout; + u16 size = usb_cmd->size; + u8 reqtype; + + buf = kmemdup(&usb_cmd->cmd_data, size, GFP_KERNEL); + if (!buf) + return -ENOMEM; + + if (usb_cmd->ops == USB_READ_OPS) { + reqtype = USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE; + timeout = USB_CTRL_GET_TIMEOUT; + } else { + reqtype = USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE; + timeout = USB_CTRL_SET_TIMEOUT; + } + + err = usb_control_msg(axdev->udev, usb_rcvctrlpipe(axdev->udev, 0), + usb_cmd->cmd, reqtype, usb_cmd->value, + usb_cmd->index, buf, size, timeout); + if (err > 0 && err <= size) + memcpy(&usb_cmd->cmd_data, buf, size); + + kfree(buf); + + return 0; +} + +static int ax_open(struct net_device *netdev) +{ + struct ax_device *axdev = netdev_priv(netdev); + int res = 0; + + res = ax_alloc_buffer(axdev); + if (res) + return res; + + res = usb_autopm_get_interface(axdev->intf); + if (res < 0) + goto out_free; + + mutex_lock(&axdev->control); + + set_bit(AX_ENABLE, &axdev->flags); + + res = axdev->driver_info->hw_init(axdev); + if (res < 0) + goto out_unlock; + + res = usb_submit_urb(axdev->intr_urb, GFP_KERNEL); + if (res) { + if (res == -ENODEV) + netif_device_detach(netdev); + netif_warn(axdev, ifup, netdev, + "intr_urb submit failed: %d\n", res); + goto out_unlock; + } + + napi_enable(&axdev->napi); + netif_carrier_off(netdev); + netif_start_queue(netdev); + mutex_unlock(&axdev->control); + usb_autopm_put_interface(axdev->intf); + + return 0; + +out_unlock: + mutex_unlock(&axdev->control); + usb_autopm_put_interface(axdev->intf); +out_free: + ax_free_buffer(axdev); + return res; +} + +static int ax_close(struct net_device *netdev) +{ + struct ax_device *axdev = netdev_priv(netdev); + int ret = 0; + + if (axdev->driver_info->stop) + axdev->driver_info->stop(axdev); + + clear_bit(AX_ENABLE, &axdev->flags); + usb_kill_urb(axdev->intr_urb); + cancel_delayed_work_sync(&axdev->schedule); + napi_disable(&axdev->napi); + netif_stop_queue(axdev->netdev); + + ret = usb_autopm_get_interface(axdev->intf); + if (ret < 0 || test_bit(AX_UNPLUG, &axdev->flags)) { + ax_drop_queued_tx(axdev); + ax_stop_rx(axdev); + } else { + ax_disable(axdev); + } + + if (!ret) + usb_autopm_put_interface(axdev->intf); + + ax_free_buffer(axdev); + + return ret; +} + +static int ax88179_change_mtu(struct net_device *net, int new_mtu) +{ + struct ax_device *axdev = netdev_priv(net); + u16 reg16; + + if (new_mtu <= 0 || new_mtu > 4088) + return -EINVAL; + + net->mtu = new_mtu; + + if (net->mtu > 1500) { + ax_read_cmd(axdev, AX_ACCESS_MAC, AX_MEDIUM_STATUS_MODE, + 2, 2, ®16, 1); + reg16 |= AX_MEDIUM_JUMBO_EN; + ax_write_cmd(axdev, AX_ACCESS_MAC, AX_MEDIUM_STATUS_MODE, + 2, 2, ®16); + } else { + ax_read_cmd(axdev, AX_ACCESS_MAC, AX_MEDIUM_STATUS_MODE, + 2, 2, ®16, 1); + reg16 &= ~AX_MEDIUM_JUMBO_EN; + ax_write_cmd(axdev, AX_ACCESS_MAC, AX_MEDIUM_STATUS_MODE, + 2, 2, ®16); + } + + return 0; +} + +int ax_get_mac_pass(struct ax_device *axdev, u8 *mac) +{ +#ifdef ENABLE_MAC_PASS + efi_char16_t name[] = L"MacAddressPassTemp"; + efi_guid_t guid = EFI_GUID(0xe2a741d8, 0xedf5, 0x47a1, + 0x8f, 0x94, 0xb0, 0xee, + 0x36, 0x8a, 0x3d, 0xe0); + u32 attr; + unsigned long data_size = sizeof(struct mac_pass); + struct mac_pass macpass; + efi_status_t status; + + if (!efi_rt_services_supported(EFI_RT_SUPPORTED_GET_VARIABLE)) + return -1; + + status = efi.get_variable(name, &guid, &attr, &data_size, &macpass); + if (status != EFI_SUCCESS) { + netdev_err(axdev->netdev, "Getting variable failed.(%ld)", + status); + return status; + } + + if (macpass.control == MAC_PASS_ENABLE_0) + memcpy(mac, macpass.mac0, 6); + else if (macpass.control == MAC_PASS_ENABLE_1) + memcpy(mac, macpass.mac1, 6); + else + return -1; +#endif + return 0; +} + +int ax_check_ether_addr(struct ax_device *axdev) +{ + u8 *addr = (u8 *)axdev->netdev->dev_addr; + u8 default_mac[6] = {0, 0x0e, 0xc6, 0x81, 0x79, 0x01}; + u8 default_mac_178a[6] = {0, 0x0e, 0xc6, 0x81, 0x78, 0x01}; + + if ((addr[0] == 0 && addr[1] == 0 && addr[2] == 0) || + !is_valid_ether_addr(addr) || + !memcmp(axdev->netdev->dev_addr, default_mac, ETH_ALEN) || + !memcmp(axdev->netdev->dev_addr, default_mac_178a, ETH_ALEN)) { + eth_random_addr(addr); + addr[0] = 0; + addr[1] = 0x0E; + addr[2] = 0xC6; + + return -EADDRNOTAVAIL; + } + + return 0; +} + +static int ax_get_chip_version(struct ax_device *axdev) +{ + int ret = 0; + + axdev->chip_version = AX_VERSION_INVALID; + ret = ax_read_cmd(axdev, AX_ACCESS_MAC, AX_CHIP_STATUS, + 1, 1, &axdev->chip_version, 0); + if (ret < 0) + return ret; + axdev->chip_version = CHIP_CODE(axdev->chip_version); + + return 0; +} + +static void ax_get_chip_subversion(struct ax_device *axdev) +{ + if (axdev->chip_version < AX_VERSION_AX88179A_772D) { + axdev->sub_version = 0; + return; + } + + if (ax_read_cmd(axdev, AX88179A_ACCESS_BL, AX88179A_HW_EC_VERSION, + 1, 1, &axdev->sub_version, 0) < 0) + axdev->sub_version = 0; +} + +static int ax_get_chip_feature(struct ax_device *axdev) +{ + if (ax_get_chip_version(axdev)) + return -ENODEV; + + if (axdev->chip_version < AX_VERSION_AX88179) + return -ENODEV; + + ax_get_chip_subversion(axdev); + + return 0; +} + +static int ax_get_mac_address(struct ax_device *axdev) +{ + struct net_device *netdev = axdev->netdev; + + if (ax_read_cmd(axdev, AX_ACCESS_MAC, AX_NODE_ID, ETH_ALEN, + ETH_ALEN, netdev->dev_addr, 0) < 0) { + dev_err(&axdev->intf->dev, "Failed to read MAC address"); + return -ENODEV; + } + + if (ax_check_ether_addr(axdev)) + dev_warn(&axdev->intf->dev, "Found invalid MAC address value"); + + ax_get_mac_pass(axdev, netdev->dev_addr); + +#ifdef FROCE_MAC_ADDR + netdev->dev_addr[0] = 0; + netdev->dev_addr[1] = 0x0E; + netdev->dev_addr[2] = 0xC6; + netdev->dev_addr[3] = 0; + netdev->dev_addr[4] = 0; + netdev->dev_addr[5] = 1; + dev_warn(&axdev->intf->dev, "Forced MAC addr: 00:0E:C6:00:00:01"); +#endif + + memcpy(netdev->perm_addr, netdev->dev_addr, ETH_ALEN); + + if (ax_write_cmd(axdev, AX_ACCESS_MAC, AX_NODE_ID, ETH_ALEN, + ETH_ALEN, netdev->dev_addr) < 0) { + dev_err(&axdev->intf->dev, "Failed to write MAC address"); + return -ENODEV; + } + + return 0; +} + +static int ax_probe(struct usb_interface *intf, const struct usb_device_id *id) +{ + struct usb_device *udev = interface_to_usbdev(intf); + //struct usb_driver *driver = to_usb_driver(intf->dev.driver); + const struct driver_info *info; + struct net_device *netdev; + struct ax_device *axdev; + int ret; + + if (udev->actconfig->desc.bConfigurationValue != 1) { + usb_driver_set_configuration(udev, 1); + return -ENODEV; + } + + info = (const struct driver_info *)id->driver_info; + if (!info || !info->bind || !info->unbind) { + dev_err(&intf->dev, "Driver method not registered\n"); + return -ENODEV; + } + netdev = alloc_etherdev(sizeof(struct ax_device)); + if (!netdev) { + dev_err(&intf->dev, "Out of memory\n"); + return -ENOMEM; + } + + axdev = netdev_priv(netdev); + axdev->driver_info = info; + + netdev->watchdog_timeo = AX_TX_TIMEOUT; + + axdev->udev = udev; + axdev->netdev = netdev; + axdev->intf = intf; + intf->needs_remote_wakeup = true; +#ifdef ENABLE_AUTODETACH_FUNC + axdev->autodetach = (autodetach == -1) ? false : true; +#else + axdev->autodetach = false; +#endif + mutex_init(&axdev->control); + INIT_DELAYED_WORK(&axdev->schedule, ax_work_func_t); + + ret = ax_get_chip_feature(axdev); + if (ret) { + dev_err(&intf->dev, "Failed to get Device feature\n"); + goto out; + } + + ret = info->bind(axdev); + if (ret) { + dev_err(&intf->dev, "Device initialization failed\n"); + goto out; + } + + usb_set_intfdata(intf, axdev); + netif_napi_add(netdev, &axdev->napi, ax_poll, info->napi_weight); + + ret = ax_get_mac_address(axdev); + if (ret < 0) + goto out; + + SET_NETDEV_DEV(netdev, &intf->dev); + ret = register_netdev(netdev); + if (ret != 0) { + netif_err(axdev, probe, netdev, + "couldn't register the device\n"); + goto out1; + } + + /* usb_enable_autosuspend(udev); */ + return 0; +out1: + netif_napi_del(&axdev->napi); + usb_set_intfdata(intf, NULL); +out: + free_netdev(netdev); + return ret; +} + +static void ax_disconnect(struct usb_interface *intf) +{ + struct ax_device *axdev = usb_get_intfdata(intf); + + usb_set_intfdata(intf, NULL); + if (axdev) { + axdev->driver_info->unbind(axdev); + ax_set_unplug(axdev); + netif_napi_del(&axdev->napi); + unregister_netdev(axdev->netdev); + free_netdev(axdev->netdev); + } +} + +static int ax_pre_reset(struct usb_interface *intf) +{ + struct ax_device *axdev = usb_get_intfdata(intf); + struct net_device *netdev; + + if (!axdev) + return 0; + + netdev = axdev->netdev; + if (!netif_running(netdev)) + return 0; + + netif_stop_queue(netdev); + clear_bit(AX_ENABLE, &axdev->flags); + usb_kill_urb(axdev->intr_urb); + cancel_delayed_work_sync(&axdev->schedule); + napi_disable(&axdev->napi); + + return 0; +} + +static int ax_post_reset(struct usb_interface *intf) +{ + struct ax_device *axdev = usb_get_intfdata(intf); + struct net_device *netdev; + + if (!axdev) + return 0; + + netdev = axdev->netdev; + if (!netif_running(netdev)) + return 0; + + set_bit(AX_ENABLE, &axdev->flags); + if (netif_carrier_ok(netdev)) { + mutex_lock(&axdev->control); + ax_start_rx(axdev); + mutex_unlock(&axdev->control); + } + + napi_enable(&axdev->napi); + netif_wake_queue(netdev); + usb_submit_urb(axdev->intr_urb, GFP_KERNEL); + + if (!list_empty(&axdev->rx_done)) + napi_schedule(&axdev->napi); + + return 0; +} + +static int ax_system_resume(struct ax_device *axdev) +{ + struct net_device *netdev = axdev->netdev; + + netif_device_attach(netdev); + + if (netif_running(netdev) && (netdev->flags & IFF_UP)) { + netif_carrier_off(netdev); + + axdev->driver_info->system_resume(axdev); + set_bit(AX_ENABLE, &axdev->flags); + usb_submit_urb(axdev->intr_urb, GFP_NOIO); + } + + return 0; +} + +static int ax_runtime_resume(struct ax_device *axdev) +{ + struct net_device *netdev = axdev->netdev; + + if (netif_running(netdev) && (netdev->flags & IFF_UP)) { + struct napi_struct *napi = &axdev->napi; + + napi_disable(napi); + set_bit(AX_ENABLE, &axdev->flags); + + if (netif_carrier_ok(netdev)) { + if (axdev->link) { + axdev->driver_info->link_reset(axdev); + ax_start_rx(axdev); + } else { + netif_carrier_off(netdev); + ax_disable(axdev); + } + } + + napi_enable(napi); + clear_bit(AX_SELECTIVE_SUSPEND, &axdev->flags); + if (!list_empty(&axdev->rx_done)) { + local_bh_disable(); + napi_schedule(&axdev->napi); + local_bh_enable(); + } + ax_write_cmd_nopm(axdev, AX_PHY_POLLING, 1, 0, 0, NULL); + usb_submit_urb(axdev->intr_urb, GFP_NOIO); + } else { + clear_bit(AX_SELECTIVE_SUSPEND, &axdev->flags); + } + + return 0; +} + +static int ax_system_suspend(struct ax_device *axdev) +{ + struct net_device *netdev = axdev->netdev; + + netif_device_detach(netdev); + if (netif_running(netdev) && test_bit(AX_ENABLE, &axdev->flags)) { + struct napi_struct *napi = &axdev->napi; + + clear_bit(AX_ENABLE, &axdev->flags); + usb_kill_urb(axdev->intr_urb); + + ax_disable(axdev); + + axdev->driver_info->system_suspend(axdev); + + napi_disable(napi); + cancel_delayed_work_sync(&axdev->schedule); + napi_enable(napi); + } + + return 0; +} + +static int ax_runtime_suspend(struct ax_device *axdev) +{ + struct net_device *netdev = axdev->netdev; + int ret = 0; + + set_bit(AX_SELECTIVE_SUSPEND, &axdev->flags); + + if (netif_running(netdev) && test_bit(AX_ENABLE, &axdev->flags)) { + u16 reg16; + + if (netif_carrier_ok(netdev)) { + ax_read_cmd_nopm(axdev, AX_ACCESS_MAC, + AX_RX_FREE_BUF_LOW, 2, 2, ®16, 1); + if (reg16 != 0x067F) { + ret = -EBUSY; + goto out1; + } + } + + clear_bit(AX_ENABLE, &axdev->flags); + usb_kill_urb(axdev->intr_urb); + + if (netif_carrier_ok(netdev)) { + struct napi_struct *napi = &axdev->napi; + + napi_disable(napi); + ax_stop_rx(axdev); + napi_enable(napi); + } + + ax_read_cmd_nopm(axdev, AX_ACCESS_MAC, + AX_MEDIUM_STATUS_MODE, 2, 2, ®16, 1); + reg16 &= ~AX_MEDIUM_RECEIVE_EN; + ax_write_cmd_nopm(axdev, AX_ACCESS_MAC, + AX_MEDIUM_STATUS_MODE, 2, 2, ®16); + + reg16 = AX_RX_CTL_STOP; + ax_write_cmd_nopm(axdev, AX_ACCESS_MAC, AX_RX_CTL, + 2, 2, ®16); + } + +out1: + return ret; +} + +static int ax_suspend(struct usb_interface *intf, pm_message_t message) +{ + struct ax_device *axdev = usb_get_intfdata(intf); + int ret; + + mutex_lock(&axdev->control); + + if (PMSG_IS_AUTO(message)) + ret = ax_runtime_suspend(axdev); + else + ret = ax_system_suspend(axdev); + + mutex_unlock(&axdev->control); + + return ret; +} + +static int ax_resume(struct usb_interface *intf) +{ + struct ax_device *axdev = usb_get_intfdata(intf); + int ret; + + mutex_lock(&axdev->control); + + if (test_bit(AX_SELECTIVE_SUSPEND, &axdev->flags)) + ret = ax_runtime_resume(axdev); + else + ret = ax_system_resume(axdev); + + mutex_unlock(&axdev->control); + + return ret; +} + +static int ax_reset_resume(struct usb_interface *intf) +{ + struct ax_device *axdev = usb_get_intfdata(intf); + + clear_bit(AX_SELECTIVE_SUSPEND, &axdev->flags); + + return ax_resume(intf); +} + +const struct net_device_ops ax88179_netdev_ops = { + .ndo_open = ax_open, + .ndo_stop = ax_close, + .ndo_siocdevprivate = ax88179_siocdevprivate, + .ndo_eth_ioctl = ax88179_ioctl, + .ndo_do_ioctl = ax88179_ioctl, + .ndo_start_xmit = ax_start_xmit, + .ndo_tx_timeout = ax_tx_timeout, + .ndo_set_features = ax88179_set_features, + .ndo_set_rx_mode = ax88179_set_multicast, + .ndo_set_mac_address = ax88179_set_mac_addr, + .ndo_change_mtu = ax88179_change_mtu, + .ndo_validate_addr = eth_validate_addr, +}; + +const struct net_device_ops ax88179a_netdev_ops = { + .ndo_open = ax_open, + .ndo_stop = ax_close, + .ndo_siocdevprivate = ax88179a_siocdevprivate, + .ndo_eth_ioctl = ax88179a_ioctl, + .ndo_do_ioctl = ax88179a_ioctl, + .ndo_start_xmit = ax_start_xmit, + .ndo_tx_timeout = ax_tx_timeout, + .ndo_set_features = ax88179_set_features, + .ndo_set_rx_mode = ax88179a_set_multicast, + .ndo_set_mac_address = ax88179_set_mac_addr, + .ndo_change_mtu = ax88179_change_mtu, + .ndo_validate_addr = eth_validate_addr, +}; + +#define ASIX_USB_DEVICE(vend, prod, lo, hi, info) { \ + USB_DEVICE_VER(vend, prod, lo, hi), \ + .driver_info = (unsigned long)&(info) \ +} + +static const struct usb_device_id ax_usb_table[] = { + ASIX_USB_DEVICE(USB_VENDOR_ID_ASIX, AX_DEVICE_ID_179X, 0, + AX_BCDDEVICE_ID_179, ax88179_info), + ASIX_USB_DEVICE(USB_VENDOR_ID_ASIX, AX_DEVICE_ID_178A, 0, + AX_BCDDEVICE_ID_178A, ax88179_info), + ASIX_USB_DEVICE(USB_VENDOR_ID_SITECOM, 0x0072, 0, + AX_BCDDEVICE_ID_179, ax88179_info), + ASIX_USB_DEVICE(USB_VENDOR_ID_LENOVO, 0x304b, 0, + AX_BCDDEVICE_ID_179, ax88179_info), + ASIX_USB_DEVICE(USB_VENDOR_ID_TOSHIBA, 0x0a13, 0, + AX_BCDDEVICE_ID_179, ax88179_info), + ASIX_USB_DEVICE(USB_VENDOR_ID_SAMSUNG, 0xa100, 0, + AX_BCDDEVICE_ID_179, ax88179_info), + ASIX_USB_DEVICE(USB_VENDOR_ID_DLINK, 0x4a00, 0, + AX_BCDDEVICE_ID_179, ax88179_info), + ASIX_USB_DEVICE(USB_VENDOR_ID_MAGIC_CONTROL, 0x0179, 0, + AX_BCDDEVICE_ID_179, ax88179_info), + ASIX_USB_DEVICE(USB_VENDOR_ID_ASIX, AX_DEVICE_ID_179X, 0, + AX_BCDDEVICE_ID_772D, ax88179a_info), + ASIX_USB_DEVICE(USB_VENDOR_ID_ASIX, AX_DEVICE_ID_179X, 0, + AX_BCDDEVICE_ID_179A, ax88179a_info), + {/*END*/} +}; + +MODULE_DEVICE_TABLE(usb, ax_usb_table); + +static struct usb_driver ax_usb_driver = { + .name = MODULENAME, + .id_table = ax_usb_table, + .probe = ax_probe, + .disconnect = ax_disconnect, + .suspend = ax_suspend, + .resume = ax_resume, + .reset_resume = ax_reset_resume, + .pre_reset = ax_pre_reset, + .post_reset = ax_post_reset, + .supports_autosuspend = 1, + .disable_hub_initiated_lpm = 1, +}; + +module_usb_driver(ax_usb_driver); + +MODULE_AUTHOR(DRIVER_AUTHOR); +MODULE_DESCRIPTION(DRIVER_DESC); +MODULE_LICENSE("GPL"); +MODULE_VERSION(DRIVER_VERSION); diff --git a/drivers/net/usb/ax_main.h b/drivers/net/usb/ax_main.h new file mode 100644 index 000000000000..5c9c9e5d13c8 --- /dev/null +++ b/drivers/net/usb/ax_main.h @@ -0,0 +1,563 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/******************************************************************************* + * Copyright (c) 2022 ASIX Electronic Corporation All rights reserved. + * + * This program is free software: you can redistribute it and/or modify it under + * the terms of the GNU General Public License as published by the Free Software + * Foundation, either version 2 of the License, or (at your option) any later + * version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details + * + * You should have received a copy of the GNU General Public License along with + * this program. If not, see . + ******************************************************************************/ +#ifndef __ASIX_MAIN_H +#define __ASIX_MAIN_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "ax_ioctl.h" + +#define napi_alloc_skb(napi, length) netdev_alloc_skb_ip_align(netdev, length) +#define napi_complete_done(n, d) napi_complete(n) + +typedef int (*_usb_read_function)(struct ax_device *dev, u8 cmd, u8 reqtype, + u16 value, u16 index, void *data, u16 size); +typedef int (*_usb_write_function)(struct ax_device *dev, u8 cmd, u8 reqtype, + u16 value, u16 index, const void *data, + u16 size); +typedef int (*usb_read_function)(struct ax_device *axdev, u8 cmd, u16 value, + u16 index, u16 size, void *data, int eflag); +typedef int (*usb_write_function)(struct ax_device *axdev, u8 cmd, u16 value, + u16 index, u16 size, void *data); + +#define USB_VENDOR_ID_ASIX 0x0B95 +#define USB_VENDOR_ID_SITECOM 0x0DF6 +#define USB_VENDOR_ID_LENOVO 0x17EF +#define USB_VENDOR_ID_TOSHIBA 0x0930 +#define USB_VENDOR_ID_SAMSUNG 0x04E8 +#define USB_VENDOR_ID_DLINK 0x2001 +#define USB_VENDOR_ID_MAGIC_CONTROL 0x0711 + +#define AX_DEVICE_ID_179X 0x1790 +#define AX_BCDDEVICE_ID_179 0x0100 +#define AX_BCDDEVICE_ID_179A 0x0200 +#define AX_DEVICE_ID_178A 0x178A +#define AX_BCDDEVICE_ID_178A 0x0100 +#define AX_DEVICE_ID_772D AX_DEVICE_ID_179X +#define AX_BCDDEVICE_ID_772D 0x0300 + +#define AX_DRIVER_STRING_179_178A \ + "ASIX AX88179_178A USB Ethernet Controller" +#define AX_DRIVER_STRING_179A_772D \ + "ASIX AX88179A_772D USB Ethernet Controller" + +#define DRIVER_VERSION "1.0.0" +#define DRIVER_AUTHOR "ASIX" +#define DRIVER_DESC "ASIX USB Ethernet Controller" +#define MODULENAME "ax_usb_nic" + +#define AX88179_MAX_TX 4 +#define AX88179_MAX_RX 10 +#define AX88179_BUF_TX_SIZE (48 * 1024) +#define AX_GSO_DEFAULT_SIZE (15 * 1024) +#define INTBUFSIZE 8 +#define TX_ALIGN 4 +#define RX_ALIGN 8 +#define TX_CASECADES_SIZE AX_GSO_DEFAULT_SIZE + +#define AX_TX_HEADER_LEN 8 +#define AX_TX_TIMEOUT (5 * HZ) +#define AX_MCAST_FILTER_SIZE 8 +#define AX_MAX_MCAST 64 +#define AX_TX_QUEUE_SIZE 1 + +#define US_TO_NS 1000 + +#define AX_ACCESS_MAC 0x01 +#define AX_ACCESS_PHY 0x02 +#define AX_ACCESS_WAKEUP 0x03 +#define AX_ACCESS_EEPROM 0x04 +#define AX_ACCESS_EFUSE 0x05 +#define AX_RELOAD_EEPROM_EFUSE 0x06 +#define AX_RELOAD_FLASH_EFUSE 0x06 +#define AX_FW_MODE 0x08 + #define AX_FW_MODE_179A 0x0001 + #define AX_USB_EP5_EN 0x0001 +#define AX_WRITE_EFUSE_EN 0x09 +#define AX_WRITE_EFUSE_DIS 0x0A +#define AX_ACCESS_MFAB 0x10 +#define AX_PHY_POLLING 0x90 + +#define PHYSICAL_LINK_STATUS 0x02 + #define AX_USB_SS 0x04 + #define AX_USB_HS 0x02 + #define AX_USB_FS 0x01 +#define GENERAL_STATUS 0x03 + #define AX_SECLD 0x04 +#define AX_CHIP_STATUS 0x05 + #define AX_CHIP_CODE_MASK 0x70 + #define CHIP_CODE(x) (((x) & AX_CHIP_CODE_MASK) >> 4) +#define AX_SROM_ADDR 0x07 +#define AX_SROM_CMD 0x0a + #define EEP_RD 0x04 + #define EEP_WR 0x08 + #define EEP_BUSY 0x10 +#define AX_SROM_DATA_LOW 0x08 +#define AX_SROM_DATA_HIGH 0x09 +#define AX_RX_CTL 0x0b +#define AX_RX_CTL_HI 0x0c + #define AX_RX_CTL_DROPCRCERR_HI 0x01 + #define AX_RX_CTL_DROPCRCERR 0x0100 + #define AX_RX_CTL_IPE 0x0200 + #define AX_RX_CTL_TXPADCRC 0x0400 + #define AX_RX_CTL_START 0x0080 + #define AX_RX_CTL_AP 0x0020 + #define AX_RX_CTL_AM 0x0010 + #define AX_RX_CTL_AB 0x0008 + #define AX_RX_CTL_HA8B 0x0004 + #define AX_RX_CTL_AMALL 0x0002 + #define AX_RX_CTL_PRO 0x0001 + #define AX_RX_CTL_STOP 0x0000 +#define AX_NODE_ID 0x10 +#define AX_MULTI_FILTER_ARRY 0x16 +#define AX_MEDIUM_STATUS_MODE 0x22 + #define AX_MEDIUM_GIGAMODE 0x0001 + #define AX_MEDIUM_FULL_DUPLEX 0x0002 + #define AX_MEDIUM_RXFLOW_CTRLEN 0x0010 + #define AX_MEDIUM_TXFLOW_CTRLEN 0x0020 + #define AX_MEDIUM_RECEIVE_EN 0x0100 + #define AX_MEDIUM_PS 0x0200 + #define AX_MEDIUM_JUMBO_EN 0x8040 +#define AX_MONITOR_MODE 0x24 + #define AX_MONITOR_MODE_RWLC 0x02 + #define AX_MONITOR_MODE_RWMP 0x04 + #define AX_MONITOR_MODE_RWWF 0x08 + #define AX_MONITOR_MODE_RW_FLAG 0x10 + #define AX_MONITOR_MODE_PMEPOL 0x20 + #define AX_MONITOR_MODE_PMETYPE 0x40 +#define AX_GPIO_CTRL 0x25 + #define AX_GPIO_CTRL_GPIO3EN 0x80 + #define AX_GPIO_CTRL_GPIO2EN 0x40 + #define AX_GPIO_CTRL_GPIO1EN 0x20 +#define AX_PHYPWR_RSTCTL 0x26 + #define AX_PHYPWR_RSTCTL_BZ 0x0010 + #define AX_PHYPWR_RSTCTL_IPRL 0x0020 + #define AX_PHYPWR_RSTCTL_AUTODETACH 0x1000 +#define AX_RX_BULKIN_QCTRL 0x2e + #define AX_RX_BULKIN_QCTRL_TIME 0x01 + #define AX_RX_BULKIN_QCTRL_IFG 0x02 + #define AX_RX_BULKIN_QCTRL_SIZE 0x04 +#define AX_RX_BULKIN_QTIMR_LOW 0x2f +#define AX_RX_BULKIN_QTIMR_HIGH 0x30 +#define AX_RX_BULKIN_QSIZE 0x31 +#define AX_RX_BULKIN_QIFG 0x32 +#define AX_CLK_SELECT 0x33 + #define AX_CLK_SELECT_BCS 0x01 + #define AX_CLK_SELECT_ACS 0x02 + #define AX_CLK_SELECT_ACSREQ 0x10 + #define AX_CLK_SELECT_ULR 0x08 +#define AX_RXCOE_CTL 0x34 + #define AX_RXCOE_IP 0x01 + #define AX_RXCOE_TCP 0x02 + #define AX_RXCOE_UDP 0x04 + #define AX_RXCOE_ICMP 0x08 + #define AX_RXCOE_IGMP 0x10 + #define AX_RXCOE_TCPV6 0x20 + #define AX_RXCOE_UDPV6 0x40 + #define AX_RXCOE_ICMV6 0x80 + #define AX_RXCOE_DEF_CSUM (AX_RXCOE_IP | AX_RXCOE_TCP | \ + AX_RXCOE_UDP | AX_RXCOE_ICMV6 | \ + AX_RXCOE_TCPV6 | AX_RXCOE_UDPV6) + +#define AX_TXCOE_CTL 0x35 + #define AX_TXCOE_IP 0x01 + #define AX_TXCOE_TCP 0x02 + #define AX_TXCOE_UDP 0x04 + #define AX_TXCOE_ICMP 0x08 + #define AX_TXCOE_IGMP 0x10 + #define AX_TXCOE_TCPV6 0x20 + #define AX_TXCOE_UDPV6 0x40 + #define AX_TXCOE_ICMV6 0x80 + #define AX_TXCOE_DEF_CSUM (AX_TXCOE_TCP | AX_TXCOE_UDP | \ + AX_TXCOE_TCPV6 | AX_TXCOE_UDPV6) + +#define AX_PAUSE_WATERLVL_HIGH 0x54 +#define AX_PAUSE_WATERLVL_LOW 0x55 +#define AX_RX_FREE_BUF_LOW 0x57 + +#define GMII_PHY_CONTROL 0x00 + #define GMII_CONTROL_RESET 0x8000 + #define GMII_CONTROL_LOOPBACK 0x4000 + #define GMII_CONTROL_10MB 0x0000 + #define GMII_CONTROL_100MB 0x2000 + #define GMII_CONTROL_1000MB 0x0040 + #define GMII_CONTROL_SPEED_BITS 0x2040 + #define GMII_CONTROL_ENABLE_AUTO 0x1000 + #define GMII_CONTROL_POWER_DOWN 0x0800 + #define GMII_CONTROL_ISOLATE 0x0400 + #define GMII_CONTROL_START_AUTO 0x0200 + #define GMII_CONTROL_FULL_DUPLEX 0x0100 +#define GMII_PHY_STATUS 0x01 + #define GMII_STATUS_100MB_MASK 0xE000 + #define GMII_STATUS_10MB_MASK 0x1800 + #define GMII_STATUS_AUTO_DONE 0x0020 + #define GMII_STATUS_AUTO 0x0008 + #define GMII_STATUS_LINK_UP 0x0004 + #define GMII_STATUS_EXTENDED 0x0001 + #define GMII_STATUS_100T4 0x8000 + #define GMII_STATUS_100TXFD 0x4000 + #define GMII_STATUS_100TX 0x2000 + #define GMII_STATUS_10TFD 0x1000 + #define GMII_STATUS_10T 0x0800 +#define GMII_PHY_OUI 0x02 +#define GMII_PHY_MODEL 0x03 +#define GMII_PHY_ANAR 0x04 + #define GMII_ANAR_ASYM_PAUSE 0x0800 + #define GMII_ANAR_PAUSE 0x0400 + #define GMII_ANAR_100T4 0x0200 + #define GMII_ANAR_100TXFD 0x0100 + #define GMII_ANAR_100TX 0x0080 + #define GMII_ANAR_10TFD 0x0040 + #define GMII_ANAR_10T 0x0020 + #define GMII_SELECTOR_FIELD 0x001F + +#define GMII_PHY_ANLPAR 0x05 + #define GMII_ANLPAR_100T4 0x0200 + #define GMII_ANLPAR_100TXFD 0x0100 + #define GMII_ANLPAR_100TX 0x0080 + #define GMII_ANLPAR_10TFD 0x0040 + #define GMII_ANLPAR_10T 0x0020 + #define GMII_ANLPAR_PAUSE 0x0400 + #define GMII_ANLPAR_ASYM_PAUSE 0x0800 + #define GMII_ANLPAR_ACK 0x4000 + #define GMII_SELECTOR_8023 0x0001 +#define GMII_PHY_ANER 0x06 +#define GMII_PHY_1000BT_CONTROL 0x09 +#define GMII_PHY_1000BT_STATUS 0x0A +#define GMII_PHY_MACR 0x0D +#define GMII_PHY_MAADR 0x0E +#define GMII_PHY_PHYSR 0x11 + #define GMII_PHY_PHYSR_SMASK 0xc000 + #define GMII_PHY_PHYSR_GIGA 0x8000 + #define GMII_PHY_PHYSR_100 0x4000 + #define GMII_PHY_PHYSR_FULL 0x2000 + #define GMII_PHY_PHYSR_LINK 0x400 + +#define GMII_1000_AUX_CTRL_MASTER_SLAVE 0x1000 +#define GMII_1000_AUX_CTRL_FD_CAPABLE 0x0200 +#define GMII_1000_AUX_CTRL_HD_CAPABLE 0x0100 +#define GMII_1000_AUX_STATUS_FD_CAPABLE 0x0800 +#define GMII_1000_AUX_STATUS_HD_CAPABLE 0x0400 +#define GMII_AUX_CTRL_STATUS 0x1C +#define GMII_AUX_ANEG_CPLT 0x8000 +#define GMII_AUX_FDX 0x0020 +#define GMII_AUX_SPEED_1000 0x0010 +#define GMII_AUX_SPEED_100 0x0008 +#define GMII_LED_ACTIVE 0x1a + #define GMII_LED_ACTIVE_MASK 0xff8f + #define GMII_LED0_ACTIVE BIT(4) + #define GMII_LED1_ACTIVE BIT(5) + #define GMII_LED2_ACTIVE BIT(6) +#define GMII_LED_LINK 0x1c + #define GMII_LED_LINK_MASK 0xf888 + #define GMII_LED0_LINK_10 BIT(0) + #define GMII_LED0_LINK_100 BIT(1) + #define GMII_LED0_LINK_1000 BIT(2) + #define GMII_LED1_LINK_10 BIT(4) + #define GMII_LED1_LINK_100 BIT(5) + #define GMII_LED1_LINK_1000 BIT(6) + #define GMII_LED2_LINK_10 BIT(8) + #define GMII_LED2_LINK_100 BIT(9) + #define GMII_LED2_LINK_1000 BIT(10) + #define LED_VALID BIT(15) + #define LED0_ACTIVE BIT(0) + #define LED0_LINK_10 BIT(1) + #define LED0_LINK_100 BIT(2) + #define LED0_LINK_1000 BIT(3) + #define LED0_FD BIT(4) + #define LED0_USB3_MASK 0x001f + #define LED1_ACTIVE BIT(5) + #define LED1_LINK_10 BIT(6) + #define LED1_LINK_100 BIT(7) + #define LED1_LINK_1000 BIT(8) + #define LED1_FD BIT(9) + #define LED1_USB3_MASK 0x03e0 + #define LED2_ACTIVE BIT(10) + #define LED2_LINK_1000 BIT(13) + #define LED2_LINK_100 BIT(12) + #define LED2_LINK_10 BIT(11) + #define LED2_FD BIT(14) + #define LED2_USB3_MASK 0x7c00 +#define GMII_PHYPAGE 0x1e +#define GMII_PHY_PAGE_SELECT 0x1f + #define GMII_PHY_PAGE_SELECT_EXT 0x0007 + #define GMII_PHY_PAGE_SELECT_PAGE0 0X0000 + #define GMII_PHY_PAGE_SELECT_PAGE1 0X0001 + #define GMII_PHY_PAGE_SELECT_PAGE2 0X0002 + #define GMII_PHY_PAGE_SELECT_PAGE3 0X0003 + #define GMII_PHY_PAGE_SELECT_PAGE4 0X0004 + #define GMII_PHY_PAGE_SELECT_PAGE5 0X0005 + #define GMII_PHY_PAGE_SELECT_PAGE6 0X0006 + +enum ax_driver_flags { + AX_UNPLUG = 0, + AX_ENABLE, + AX_LINK_CHG, + AX_SELECTIVE_SUSPEND, + AX_SCHEDULE_NAPI, +}; + +enum ax_chip_version { + AX_VERSION_INVALID = 0, + AX_VERSION_AX88179 = 4, + AX_VERSION_AX88179A_772D = 6, +}; + +struct ax_device; + +struct rx_desc { + struct list_head list; + struct urb *urb; + struct ax_device *context; + void *buffer; + void *head; +}; + +enum __ax_tx_flags { + AX_TX_NONE = 0, + AX_TX_TIMESTAMPS = 1, +}; + +enum __mac_pass_ctrl { + MAC_PASS_DISABLED = 0, + MAC_PASS_ENABLE_0 = 1, + MAC_PASS_ENABLE_1 = 2, +}; + +struct mac_pass { + u8 control; + u8 mac0[8]; + u8 mac1[8]; +} __packed; + +struct tx_desc { + struct list_head list; + struct urb *urb; + struct ax_device *context; + void *buffer; + void *head; + u32 skb_num; + u32 skb_len; + unsigned long flags; + int q_index; +}; + +struct ax_bulkin_setting { + u8 custom; + u8 bulkin_setting[5]; +}; + +enum ax_ether_link_speed { + ETHER_LINK_NONE = 0, + ETHER_LINK_10 = 1, + ETHER_LINK_100 = 2, + ETHER_LINK_1000 = 3, + ETHER_LINK_2500 = 4, +}; + +struct ax_link_info { + u8 eth_speed : 3, + full_duplex : 1, + usb_speed : 4; +} __packed; + +struct ax_device { + unsigned long flags; + struct usb_device *udev; + struct usb_interface *intf; + struct net_device *netdev; + const struct driver_info *driver_info; + struct napi_struct napi; + struct urb *intr_urb; + struct tx_desc tx_list[32]; + struct rx_desc rx_list[32]; + struct list_head rx_done, tx_free; + struct sk_buff_head tx_queue[AX_TX_QUEUE_SIZE]; + struct sk_buff_head rx_queue; + spinlock_t rx_lock, tx_lock; + struct delayed_work schedule, hw_phy_work; + struct mii_if_info mii; + struct mutex control; /* protects device */ + + int intr_interval; + u32 saved_wolopts; + u32 msg_enable; + u32 tx_qlen; + u32 coalesce; + u16 speed; + u8 *intr_buff; + u8 tx_align_len; + u8 link; + u16 rxctl; + u8 m_filter[8]; + u32 tx_casecade_size; + u32 gso_max_size; + u8 fw_version[4]; + + struct ax_link_info link_info; + struct ax_link_info intr_link_info; + u8 eee_enabled; + u8 eee_active; + int autodetach; + + struct ax_bulkin_setting bin_setting; + bool tx_header_cksum; + unsigned char chip_version; + unsigned char sub_version; +#define AX_ETH_SPEED_MASK 0xF +#define AX_ETH_DUPLEX_FULL 0x10 + u8 int_link_info; + + u64 bulkin_complete; + u64 bulkin_error; + u64 bulkout_complete; + u64 bulkout_error; + u64 bulkint_complete; + u64 bulkint_error; +}; + +struct driver_info { + int (*bind)(struct ax_device *axdev); + void (*unbind)(struct ax_device *axdev); + int (*hw_init)(struct ax_device *axdev); + int (*stop)(struct ax_device *axdev); + void (*rx_fixup)(struct ax_device *axdev, struct rx_desc *desc, + int *work_done, int budget); + int (*tx_fixup)(struct ax_device *axdev, struct tx_desc *desc); + int (*link_reset)(struct ax_device *axdev); + int (*system_suspend)(struct ax_device *axdev); + int (*system_resume)(struct ax_device *axdev); + + unsigned long napi_weight; + size_t buf_rx_size; +}; + +struct _async_cmd_handle { + struct ax_device *axdev; + struct usb_ctrlrequest *req; + u8 m_filter[8]; + u16 rxctl; +} __packed; + +struct ax_device_int_data { + u8 res1; + struct ax_link_info link_info; +#define AX_INT_PPLS_LINK BIT(0) +#define AX_INT_SPLS_LINK BIT(1) +#define AX_INT_CABOFF_UNPLUG BIT(7) + u8 link; + __le16 res2; + u8 status; + __le16 res3; +} __packed; + +struct _ax_buikin_setting { + u8 ctrl; + u8 timer_l; + u8 timer_h; + u8 size; + u8 ifg; +} __packed; + +#define AX_RXHDR_L4_ERR BIT(8) +#define AX_RXHDR_L3_ERR BIT(9) + +#define AX_RXHDR_L4_TYPE_ICMP 2 +#define AX_RXHDR_L4_TYPE_IGMP 3 +#define AX_RXHDR_L4_TYPE_TCMPV6 5 + +#define AX_RXHDR_L3_TYPE_IP 1 +#define AX_RXHDR_L3_TYPE_IPV6 2 + +#define AX_RXHDR_L4_TYPE_MASK 0x1c +#define AX_RXHDR_L4_TYPE_UDP 4 +#define AX_RXHDR_L4_TYPE_TCP 16 +#define AX_RXHDR_L3CSUM_ERR 2 +#define AX_RXHDR_L4CSUM_ERR 1 +#define AX_RXHDR_CRC_ERR 0x20000000 +#define AX_RXHDR_MII_ERR 0x40000000 +#define AX_RXHDR_DROP_ERR 0x80000000 + +int ax_check_ether_addr(struct ax_device *axdev); +int ax_get_mac_pass(struct ax_device *axdev, u8 *mac); +void ax_set_tx_qlen(struct ax_device *dev); + +inline void *__rx_buf_align(void *data); +inline void *__tx_buf_align(void *data, u8 tx_align_len); +inline struct net_device_stats *ax_get_stats(struct net_device *dev); +void ax_write_bulk_callback(struct urb *urb); + +void ax_get_drvinfo(struct net_device *net, struct ethtool_drvinfo *info); +int ax_get_link_ksettings(struct net_device *netdev, + struct ethtool_link_ksettings *cmd); +int ax_set_link_ksettings(struct net_device *netdev, + const struct ethtool_link_ksettings *cmd); +u32 ax_get_msglevel(struct net_device *netdev); +void ax_set_msglevel(struct net_device *netdev, u32 value); +void ax_get_wol(struct net_device *net, struct ethtool_wolinfo *wolinfo); +int ax_set_wol(struct net_device *net, struct ethtool_wolinfo *wolinfo); +int ax_get_sset_count(struct net_device *dev, int sset); +void ax_get_ethtool_stats +(struct net_device *dev, struct ethtool_stats *stats, u64 *data); +void ax_get_strings(struct net_device *netdev, u32 stringset, u8 *data); +void ax_get_pauseparam +(struct net_device *netdev, struct ethtool_pauseparam *pause); +int ax_set_pauseparam +(struct net_device *netdev, struct ethtool_pauseparam *pause); +int ax_get_regs_len(struct net_device *netdev); +void ax_get_regs +(struct net_device *netdev, struct ethtool_regs *regs, void *buf); + +int ax_read_cmd +(struct ax_device *axdev, u8 cmd, u16 value, u16 index, u16 size, void *data, +int eflag); + +int ax_write_cmd +(struct ax_device *axdev, u8 cmd, u16 value, u16 index, u16 size, void *data); + +int ax_read_cmd_nopm +(struct ax_device *axdev, u8 cmd, u16 value, u16 index, u16 size, void *data, +int eflag); + +int ax_write_cmd_nopm +(struct ax_device *axdev, u8 cmd, u16 value, u16 index, u16 size, void *data); + +int ax_write_cmd_async +(struct ax_device *axdev, u8 cmd, u16 value, u16 index, u16 size, void *data); + +int ax_mmd_read(struct net_device *netdev, int dev_addr, int reg); +void ax_mmd_write(struct net_device *netdev, int dev_addr, int reg, int val); + +int ax_mdio_read(struct net_device *netdev, int phy_id, int reg); +void ax_mdio_write(struct net_device *netdev, int phy_id, int reg, int val); + +int ax_usb_command(struct ax_device *axdev, struct _ax_ioctl_command *info); +void ax_print_version(struct ax_device *axdev, const char *str); +#endif /* __ASIX_MAIN_H */ diff --git a/drivers/net/wireguard/netlink.c b/drivers/net/wireguard/netlink.c index 5c804bcabfe6..f5bc279c9a8c 100644 --- a/drivers/net/wireguard/netlink.c +++ b/drivers/net/wireguard/netlink.c @@ -546,6 +546,7 @@ static int wg_set_device(struct sk_buff *skb, struct genl_info *info) u8 *private_key = nla_data(info->attrs[WGDEVICE_A_PRIVATE_KEY]); u8 public_key[NOISE_PUBLIC_KEY_LEN]; struct wg_peer *peer, *temp; + bool send_staged_packets; if (!crypto_memneq(wg->static_identity.static_private, private_key, NOISE_PUBLIC_KEY_LEN)) @@ -564,14 +565,17 @@ static int wg_set_device(struct sk_buff *skb, struct genl_info *info) } down_write(&wg->static_identity.lock); - wg_noise_set_static_identity_private_key(&wg->static_identity, - private_key); - list_for_each_entry_safe(peer, temp, &wg->peer_list, - peer_list) { + send_staged_packets = !wg->static_identity.has_identity && netif_running(wg->dev); + wg_noise_set_static_identity_private_key(&wg->static_identity, private_key); + send_staged_packets = send_staged_packets && wg->static_identity.has_identity; + + wg_cookie_checker_precompute_device_keys(&wg->cookie_checker); + list_for_each_entry_safe(peer, temp, &wg->peer_list, peer_list) { wg_noise_precompute_static_static(peer); wg_noise_expire_current_peer_keypairs(peer); + if (send_staged_packets) + wg_packet_send_staged_packets(peer); } - wg_cookie_checker_precompute_device_keys(&wg->cookie_checker); up_write(&wg->static_identity.lock); } skip_set_private_key: diff --git a/drivers/net/wireguard/queueing.c b/drivers/net/wireguard/queueing.c index 8084e7408c0a..26d235d15235 100644 --- a/drivers/net/wireguard/queueing.c +++ b/drivers/net/wireguard/queueing.c @@ -28,6 +28,7 @@ int wg_packet_queue_init(struct crypt_queue *queue, work_func_t function, int ret; memset(queue, 0, sizeof(*queue)); + queue->last_cpu = -1; ret = ptr_ring_init(&queue->ring, len, GFP_KERNEL); if (ret) return ret; diff --git a/drivers/net/wireguard/queueing.h b/drivers/net/wireguard/queueing.h index 1a7aaa268041..3c9e815e4be8 100644 --- a/drivers/net/wireguard/queueing.h +++ b/drivers/net/wireguard/queueing.h @@ -130,20 +130,17 @@ static inline int wg_cpumask_choose_online(int *stored_cpu, unsigned int id) return cpu; } -/* This function is racy, in the sense that next is unlocked, so it could return - * the same CPU twice. A race-free version of this would be to instead store an - * atomic sequence number, do an increment-and-return, and then iterate through - * every possible CPU until we get to that index -- choose_cpu. However that's - * a bit slower, and it doesn't seem like this potential race actually - * introduces any performance loss, so we live with it. +/* This function is racy, in the sense that it's called while last_cpu is + * unlocked, so it could return the same CPU twice. Adding locking or using + * atomic sequence numbers is slower though, and the consequences of racing are + * harmless, so live with it. */ -static inline int wg_cpumask_next_online(int *next) +static inline int wg_cpumask_next_online(int *last_cpu) { - int cpu = *next; - - while (unlikely(!cpumask_test_cpu(cpu, cpu_online_mask))) - cpu = cpumask_next(cpu, cpu_online_mask) % nr_cpumask_bits; - *next = cpumask_next(cpu, cpu_online_mask) % nr_cpumask_bits; + int cpu = cpumask_next(*last_cpu, cpu_online_mask); + if (cpu >= nr_cpu_ids) + cpu = cpumask_first(cpu_online_mask); + *last_cpu = cpu; return cpu; } @@ -172,7 +169,7 @@ static inline void wg_prev_queue_drop_peeked(struct prev_queue *queue) static inline int wg_queue_enqueue_per_device_and_peer( struct crypt_queue *device_queue, struct prev_queue *peer_queue, - struct sk_buff *skb, struct workqueue_struct *wq, int *next_cpu) + struct sk_buff *skb, struct workqueue_struct *wq) { int cpu; @@ -186,7 +183,7 @@ static inline int wg_queue_enqueue_per_device_and_peer( /* Then we queue it up in the device queue, which consumes the * packet as soon as it can. */ - cpu = wg_cpumask_next_online(next_cpu); + cpu = wg_cpumask_next_online(&device_queue->last_cpu); if (unlikely(ptr_ring_produce_bh(&device_queue->ring, skb))) return -EPIPE; queue_work_on(cpu, wq, &per_cpu_ptr(device_queue->worker, cpu)->work); diff --git a/drivers/net/wireguard/receive.c b/drivers/net/wireguard/receive.c index 7b8df406c773..f500aaf67837 100644 --- a/drivers/net/wireguard/receive.c +++ b/drivers/net/wireguard/receive.c @@ -531,7 +531,7 @@ static void wg_packet_consume_data(struct wg_device *wg, struct sk_buff *skb) goto err; ret = wg_queue_enqueue_per_device_and_peer(&wg->decrypt_queue, &peer->rx_queue, skb, - wg->packet_crypt_wq, &wg->decrypt_queue.last_cpu); + wg->packet_crypt_wq); if (unlikely(ret == -EPIPE)) wg_queue_enqueue_per_peer_rx(skb, PACKET_STATE_DEAD); if (likely(!ret || ret == -EPIPE)) { diff --git a/drivers/net/wireguard/send.c b/drivers/net/wireguard/send.c index 5368f7c35b4b..95c853b59e1d 100644 --- a/drivers/net/wireguard/send.c +++ b/drivers/net/wireguard/send.c @@ -318,7 +318,7 @@ static void wg_packet_create_data(struct wg_peer *peer, struct sk_buff *first) goto err; ret = wg_queue_enqueue_per_device_and_peer(&wg->encrypt_queue, &peer->tx_queue, first, - wg->packet_crypt_wq, &wg->encrypt_queue.last_cpu); + wg->packet_crypt_wq); if (unlikely(ret == -EPIPE)) wg_queue_enqueue_per_peer_tx(first, PACKET_STATE_DEAD); err: diff --git a/drivers/net/wireless/ath/ath9k/ar9003_hw.c b/drivers/net/wireless/ath/ath9k/ar9003_hw.c index 42f00a2a8c80..cf5648188459 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_hw.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_hw.c @@ -1099,17 +1099,22 @@ static bool ath9k_hw_verify_hang(struct ath_hw *ah, unsigned int queue) { u32 dma_dbg_chain, dma_dbg_complete; u8 dcu_chain_state, dcu_complete_state; + unsigned int dbg_reg, reg_offset; int i; - for (i = 0; i < NUM_STATUS_READS; i++) { - if (queue < 6) - dma_dbg_chain = REG_READ(ah, AR_DMADBG_4); - else - dma_dbg_chain = REG_READ(ah, AR_DMADBG_5); + if (queue < 6) { + dbg_reg = AR_DMADBG_4; + reg_offset = queue * 5; + } else { + dbg_reg = AR_DMADBG_5; + reg_offset = (queue - 6) * 5; + } + for (i = 0; i < NUM_STATUS_READS; i++) { + dma_dbg_chain = REG_READ(ah, dbg_reg); dma_dbg_complete = REG_READ(ah, AR_DMADBG_6); - dcu_chain_state = (dma_dbg_chain >> (5 * queue)) & 0x1f; + dcu_chain_state = (dma_dbg_chain >> reg_offset) & 0x1f; dcu_complete_state = dma_dbg_complete & 0x3; if ((dcu_chain_state != 0x6) || (dcu_complete_state != 0x1)) @@ -1128,6 +1133,7 @@ static bool ar9003_hw_detect_mac_hang(struct ath_hw *ah) u8 dcu_chain_state, dcu_complete_state; bool dcu_wait_frdone = false; unsigned long chk_dcu = 0; + unsigned int reg_offset; unsigned int i = 0; dma_dbg_4 = REG_READ(ah, AR_DMADBG_4); @@ -1139,12 +1145,15 @@ static bool ar9003_hw_detect_mac_hang(struct ath_hw *ah) goto exit; for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) { - if (i < 6) + if (i < 6) { chk_dbg = dma_dbg_4; - else + reg_offset = i * 5; + } else { chk_dbg = dma_dbg_5; + reg_offset = (i - 6) * 5; + } - dcu_chain_state = (chk_dbg >> (5 * i)) & 0x1f; + dcu_chain_state = (chk_dbg >> reg_offset) & 0x1f; if (dcu_chain_state == 0x6) { dcu_wait_frdone = true; chk_dcu |= BIT(i); diff --git a/drivers/net/wireless/ath/ath9k/htc_hst.c b/drivers/net/wireless/ath/ath9k/htc_hst.c index fe62ff668f75..99667aba289d 100644 --- a/drivers/net/wireless/ath/ath9k/htc_hst.c +++ b/drivers/net/wireless/ath/ath9k/htc_hst.c @@ -114,7 +114,13 @@ static void htc_process_conn_rsp(struct htc_target *target, if (svc_rspmsg->status == HTC_SERVICE_SUCCESS) { epid = svc_rspmsg->endpoint_id; - if (epid < 0 || epid >= ENDPOINT_MAX) + + /* Check that the received epid for the endpoint to attach + * a new service is valid. ENDPOINT0 can't be used here as it + * is already reserved for HTC_CTRL_RSVD_SVC service and thus + * should not be modified. + */ + if (epid <= ENDPOINT0 || epid >= ENDPOINT_MAX) return; service_id = be16_to_cpu(svc_rspmsg->service_id); diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index e2791d45f5f5..9e6d088bd281 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c @@ -203,7 +203,7 @@ void ath_cancel_work(struct ath_softc *sc) void ath_restart_work(struct ath_softc *sc) { ieee80211_queue_delayed_work(sc->hw, &sc->hw_check_work, - ATH_HW_CHECK_POLL_INT); + msecs_to_jiffies(ATH_HW_CHECK_POLL_INT)); if (AR_SREV_9340(sc->sc_ah) || AR_SREV_9330(sc->sc_ah)) ieee80211_queue_delayed_work(sc->hw, &sc->hw_pll_work, @@ -850,7 +850,7 @@ static bool ath9k_txq_list_has_key(struct list_head *txq_list, u32 keyix) static bool ath9k_txq_has_key(struct ath_softc *sc, u32 keyix) { struct ath_hw *ah = sc->sc_ah; - int i; + int i, j; struct ath_txq *txq; bool key_in_use = false; @@ -868,8 +868,9 @@ static bool ath9k_txq_has_key(struct ath_softc *sc, u32 keyix) if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) { int idx = txq->txq_tailidx; - while (!key_in_use && - !list_empty(&txq->txq_fifo[idx])) { + for (j = 0; !key_in_use && + !list_empty(&txq->txq_fifo[idx]) && + j < ATH_TXFIFO_DEPTH; j++) { key_in_use = ath9k_txq_list_has_key( &txq->txq_fifo[idx], keyix); INCR(idx, ATH_TXFIFO_DEPTH); @@ -2238,7 +2239,7 @@ void __ath9k_flush(struct ieee80211_hw *hw, u32 queues, bool drop, } ieee80211_queue_delayed_work(hw, &sc->hw_check_work, - ATH_HW_CHECK_POLL_INT); + msecs_to_jiffies(ATH_HW_CHECK_POLL_INT)); } static bool ath9k_tx_frames_pending(struct ieee80211_hw *hw) diff --git a/drivers/net/wireless/ath/ath9k/wmi.c b/drivers/net/wireless/ath/ath9k/wmi.c index 19345b8f7bfd..d652c647d56b 100644 --- a/drivers/net/wireless/ath/ath9k/wmi.c +++ b/drivers/net/wireless/ath/ath9k/wmi.c @@ -221,6 +221,10 @@ static void ath9k_wmi_ctrl_rx(void *priv, struct sk_buff *skb, if (unlikely(wmi->stopped)) goto free_skb; + /* Validate the obtained SKB. */ + if (unlikely(skb->len < sizeof(struct wmi_cmd_hdr))) + goto free_skb; + hdr = (struct wmi_cmd_hdr *) skb->data; cmd_id = be16_to_cpu(hdr->command_id); diff --git a/drivers/net/wireless/atmel/atmel_cs.c b/drivers/net/wireless/atmel/atmel_cs.c index 453bb84cb338..58bba9875d36 100644 --- a/drivers/net/wireless/atmel/atmel_cs.c +++ b/drivers/net/wireless/atmel/atmel_cs.c @@ -72,6 +72,7 @@ struct local_info { static int atmel_probe(struct pcmcia_device *p_dev) { struct local_info *local; + int ret; dev_dbg(&p_dev->dev, "atmel_attach()\n"); @@ -82,8 +83,16 @@ static int atmel_probe(struct pcmcia_device *p_dev) p_dev->priv = local; - return atmel_config(p_dev); -} /* atmel_attach */ + ret = atmel_config(p_dev); + if (ret) + goto err_free_priv; + + return 0; + +err_free_priv: + kfree(p_dev->priv); + return ret; +} static void atmel_detach(struct pcmcia_device *link) { diff --git a/drivers/net/wireless/cisco/airo.c b/drivers/net/wireless/cisco/airo.c index fc19ecbc4c08..bcbf197fa937 100644 --- a/drivers/net/wireless/cisco/airo.c +++ b/drivers/net/wireless/cisco/airo.c @@ -6147,8 +6147,11 @@ static int airo_get_rate(struct net_device *dev, { struct airo_info *local = dev->ml_priv; StatusRid status_rid; /* Card status info */ + int ret; - readStatusRid(local, &status_rid, 1); + ret = readStatusRid(local, &status_rid, 1); + if (ret) + return -EBUSY; vwrq->value = le16_to_cpu(status_rid.currentXmitRate) * 500000; /* If more than one rate, set auto */ diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/ops.c b/drivers/net/wireless/intel/iwlwifi/mvm/ops.c index 3ee4b3ecd0c8..01f65c9789e7 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/ops.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/ops.c @@ -1309,8 +1309,11 @@ static void iwl_mvm_queue_state_change(struct iwl_op_mode *op_mode, else set_bit(IWL_MVM_TXQ_STATE_STOP_FULL, &mvmtxq->state); - if (start && mvmsta->sta_state != IEEE80211_STA_NOTEXIST) + if (start && mvmsta->sta_state != IEEE80211_STA_NOTEXIST) { + local_bh_disable(); iwl_mvm_mac_itxq_xmit(mvm->hw, txq); + local_bh_enable(); + } } out: diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c b/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c index 49c28c96fdf2..411254e9e603 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c @@ -302,7 +302,8 @@ static void iwl_mvm_get_signal_strength(struct iwl_mvm *mvm, static int iwl_mvm_rx_mgmt_prot(struct ieee80211_sta *sta, struct ieee80211_hdr *hdr, struct iwl_rx_mpdu_desc *desc, - u32 status) + u32 status, + struct ieee80211_rx_status *stats) { struct iwl_mvm_sta *mvmsta; struct iwl_mvm_vif *mvmvif; @@ -331,8 +332,10 @@ static int iwl_mvm_rx_mgmt_prot(struct ieee80211_sta *sta, /* good cases */ if (likely(status & IWL_RX_MPDU_STATUS_MIC_OK && - !(status & IWL_RX_MPDU_STATUS_REPLAY_ERROR))) + !(status & IWL_RX_MPDU_STATUS_REPLAY_ERROR))) { + stats->flag |= RX_FLAG_DECRYPTED; return 0; + } if (!sta) return -1; @@ -401,7 +404,7 @@ static int iwl_mvm_rx_crypto(struct iwl_mvm *mvm, struct ieee80211_sta *sta, if (unlikely(ieee80211_is_mgmt(hdr->frame_control) && !ieee80211_has_protected(hdr->frame_control))) - return iwl_mvm_rx_mgmt_prot(sta, hdr, desc, status); + return iwl_mvm_rx_mgmt_prot(sta, hdr, desc, status, stats); if (!ieee80211_has_protected(hdr->frame_control) || (status & IWL_RX_MPDU_STATUS_SEC_MASK) == diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/rx.c b/drivers/net/wireless/intel/iwlwifi/pcie/rx.c index fea89330f692..6c6512158813 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/rx.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/rx.c @@ -1601,18 +1601,22 @@ irqreturn_t iwl_pcie_irq_rx_msix_handler(int irq, void *dev_id) struct msix_entry *entry = dev_id; struct iwl_trans_pcie *trans_pcie = iwl_pcie_get_trans_pcie(entry); struct iwl_trans *trans = trans_pcie->trans; - struct iwl_rxq *rxq = &trans_pcie->rxq[entry->entry]; + struct iwl_rxq *rxq; trace_iwlwifi_dev_irq_msix(trans->dev, entry, false, 0, 0); if (WARN_ON(entry->entry >= trans->num_rx_queues)) return IRQ_NONE; - if (WARN_ONCE(!rxq, - "[%d] Got MSI-X interrupt before we have Rx queues", - entry->entry)) + if (!trans_pcie->rxq) { + if (net_ratelimit()) + IWL_ERR(trans, + "[%d] Got MSI-X interrupt before we have Rx queues\n", + entry->entry); return IRQ_NONE; + } + rxq = &trans_pcie->rxq[entry->entry]; lock_map_acquire(&trans->sync_cmd_lockdep_map); IWL_DEBUG_ISR(trans, "[%d] Got interrupt\n", entry->entry); diff --git a/drivers/net/wireless/intersil/orinoco/orinoco_cs.c b/drivers/net/wireless/intersil/orinoco/orinoco_cs.c index a956f965a1e5..03bfd2482656 100644 --- a/drivers/net/wireless/intersil/orinoco/orinoco_cs.c +++ b/drivers/net/wireless/intersil/orinoco/orinoco_cs.c @@ -96,6 +96,7 @@ orinoco_cs_probe(struct pcmcia_device *link) { struct orinoco_private *priv; struct orinoco_pccard *card; + int ret; priv = alloc_orinocodev(sizeof(*card), &link->dev, orinoco_cs_hard_reset, NULL); @@ -107,8 +108,16 @@ orinoco_cs_probe(struct pcmcia_device *link) card->p_dev = link; link->priv = priv; - return orinoco_cs_config(link); -} /* orinoco_cs_attach */ + ret = orinoco_cs_config(link); + if (ret) + goto err_free_orinocodev; + + return 0; + +err_free_orinocodev: + free_orinocodev(priv); + return ret; +} static void orinoco_cs_detach(struct pcmcia_device *link) { diff --git a/drivers/net/wireless/intersil/orinoco/spectrum_cs.c b/drivers/net/wireless/intersil/orinoco/spectrum_cs.c index 291ef97ed45e..841d623c621a 100644 --- a/drivers/net/wireless/intersil/orinoco/spectrum_cs.c +++ b/drivers/net/wireless/intersil/orinoco/spectrum_cs.c @@ -157,6 +157,7 @@ spectrum_cs_probe(struct pcmcia_device *link) { struct orinoco_private *priv; struct orinoco_pccard *card; + int ret; priv = alloc_orinocodev(sizeof(*card), &link->dev, spectrum_cs_hard_reset, @@ -169,8 +170,16 @@ spectrum_cs_probe(struct pcmcia_device *link) card->p_dev = link; link->priv = priv; - return spectrum_cs_config(link); -} /* spectrum_cs_attach */ + ret = spectrum_cs_config(link); + if (ret) + goto err_free_orinocodev; + + return 0; + +err_free_orinocodev: + free_orinocodev(priv); + return ret; +} static void spectrum_cs_detach(struct pcmcia_device *link) { diff --git a/drivers/net/wireless/marvell/mwifiex/scan.c b/drivers/net/wireless/marvell/mwifiex/scan.c index 0b877f3f6b97..5ec8a42e7150 100644 --- a/drivers/net/wireless/marvell/mwifiex/scan.c +++ b/drivers/net/wireless/marvell/mwifiex/scan.c @@ -2199,9 +2199,9 @@ int mwifiex_ret_802_11_scan(struct mwifiex_private *priv, if (nd_config) { adapter->nd_info = - kzalloc(sizeof(struct cfg80211_wowlan_nd_match) + - sizeof(struct cfg80211_wowlan_nd_match *) * - scan_rsp->number_of_sets, GFP_ATOMIC); + kzalloc(struct_size(adapter->nd_info, matches, + scan_rsp->number_of_sets), + GFP_ATOMIC); if (adapter->nd_info) adapter->nd_info->n_matches = scan_rsp->number_of_sets; diff --git a/drivers/net/wireless/microchip/wilc1000/hif.c b/drivers/net/wireless/microchip/wilc1000/hif.c index d211ae224f32..41e3f0e79cb8 100644 --- a/drivers/net/wireless/microchip/wilc1000/hif.c +++ b/drivers/net/wireless/microchip/wilc1000/hif.c @@ -470,6 +470,9 @@ void *wilc_parse_join_bss_param(struct cfg80211_bss *bss, int rsn_ie_len = sizeof(struct element) + rsn_ie[1]; int offset = 8; + param->mode_802_11i = 2; + param->rsn_found = true; + /* extract RSN capabilities */ if (offset < rsn_ie_len) { /* skip over pairwise suites */ @@ -479,11 +482,8 @@ void *wilc_parse_join_bss_param(struct cfg80211_bss *bss, /* skip over authentication suites */ offset += (rsn_ie[offset] * 4) + 2; - if (offset + 1 < rsn_ie_len) { - param->mode_802_11i = 2; - param->rsn_found = true; + if (offset + 1 < rsn_ie_len) memcpy(param->rsn_cap, &rsn_ie[offset], 2); - } } } } diff --git a/drivers/net/wireless/ray_cs.c b/drivers/net/wireless/ray_cs.c index f8409e93fe33..96330a6c066b 100644 --- a/drivers/net/wireless/ray_cs.c +++ b/drivers/net/wireless/ray_cs.c @@ -270,13 +270,14 @@ static int ray_probe(struct pcmcia_device *p_dev) { ray_dev_t *local; struct net_device *dev; + int ret; dev_dbg(&p_dev->dev, "ray_attach()\n"); /* Allocate space for private device-specific data */ dev = alloc_etherdev(sizeof(ray_dev_t)); if (!dev) - goto fail_alloc_dev; + return -ENOMEM; local = netdev_priv(dev); local->finder = p_dev; @@ -313,11 +314,16 @@ static int ray_probe(struct pcmcia_device *p_dev) timer_setup(&local->timer, NULL, 0); this_device = p_dev; - return ray_config(p_dev); + ret = ray_config(p_dev); + if (ret) + goto err_free_dev; -fail_alloc_dev: - return -ENOMEM; -} /* ray_attach */ + return 0; + +err_free_dev: + free_netdev(dev); + return ret; +} static void ray_detach(struct pcmcia_device *link) { @@ -1643,38 +1649,34 @@ static void authenticate_timeout(struct timer_list *t) /*===========================================================================*/ static int parse_addr(char *in_str, UCHAR *out) { + int i, k; int len; - int i, j, k; - int status; if (in_str == NULL) return 0; - if ((len = strlen(in_str)) < 2) + len = strnlen(in_str, ADDRLEN * 2 + 1) - 1; + if (len < 1) return 0; memset(out, 0, ADDRLEN); - status = 1; - j = len - 1; - if (j > 12) - j = 12; i = 5; - while (j > 0) { - if ((k = hex_to_bin(in_str[j--])) != -1) + while (len > 0) { + if ((k = hex_to_bin(in_str[len--])) != -1) out[i] = k; else return 0; - if (j == 0) + if (len == 0) break; - if ((k = hex_to_bin(in_str[j--])) != -1) + if ((k = hex_to_bin(in_str[len--])) != -1) out[i] += k << 4; else return 0; if (!i--) break; } - return status; + return 1; } /*===========================================================================*/ diff --git a/drivers/net/wireless/rsi/rsi_91x_sdio.c b/drivers/net/wireless/rsi/rsi_91x_sdio.c index 9f16128e4ffa..670de56c69a2 100644 --- a/drivers/net/wireless/rsi/rsi_91x_sdio.c +++ b/drivers/net/wireless/rsi/rsi_91x_sdio.c @@ -1463,10 +1463,8 @@ static void rsi_shutdown(struct device *dev) rsi_dbg(ERR_ZONE, "SDIO Bus shutdown =====>\n"); - if (hw) { - struct cfg80211_wowlan *wowlan = hw->wiphy->wowlan_config; - - if (rsi_config_wowlan(adapter, wowlan)) + if (hw && hw->wiphy && hw->wiphy->wowlan_config) { + if (rsi_config_wowlan(adapter, hw->wiphy->wowlan_config)) rsi_dbg(ERR_ZONE, "Failed to configure WoWLAN\n"); } @@ -1481,9 +1479,6 @@ static void rsi_shutdown(struct device *dev) if (sdev->write_fail) rsi_dbg(INFO_ZONE, "###### Device is not ready #######\n"); - if (rsi_set_sdio_pm_caps(adapter)) - rsi_dbg(INFO_ZONE, "Setting power management caps failed\n"); - rsi_dbg(INFO_ZONE, "***** RSI module shut down *****\n"); } diff --git a/drivers/net/wireless/wl3501_cs.c b/drivers/net/wireless/wl3501_cs.c index cb71b73853f4..4c408fd7c159 100644 --- a/drivers/net/wireless/wl3501_cs.c +++ b/drivers/net/wireless/wl3501_cs.c @@ -1862,6 +1862,7 @@ static int wl3501_probe(struct pcmcia_device *p_dev) { struct net_device *dev; struct wl3501_card *this; + int ret; /* The io structure describes IO port mapping */ p_dev->resource[0]->end = 16; @@ -1873,8 +1874,7 @@ static int wl3501_probe(struct pcmcia_device *p_dev) dev = alloc_etherdev(sizeof(struct wl3501_card)); if (!dev) - goto out_link; - + return -ENOMEM; dev->netdev_ops = &wl3501_netdev_ops; dev->watchdog_timeo = 5 * HZ; @@ -1887,9 +1887,15 @@ static int wl3501_probe(struct pcmcia_device *p_dev) netif_stop_queue(dev); p_dev->priv = dev; - return wl3501_config(p_dev); -out_link: - return -ENOMEM; + ret = wl3501_config(p_dev); + if (ret) + goto out_free_etherdev; + + return 0; + +out_free_etherdev: + free_netdev(dev); + return ret; } static int wl3501_config(struct pcmcia_device *link) @@ -1945,8 +1951,7 @@ static int wl3501_config(struct pcmcia_device *link) goto failed; } - for (i = 0; i < 6; i++) - dev->dev_addr[i] = ((char *)&this->mac_addr)[i]; + eth_hw_addr_set(dev, this->mac_addr); /* print probe information */ printk(KERN_INFO "%s: wl3501 @ 0x%3.3x, IRQ %d, " diff --git a/drivers/ntb/hw/amd/ntb_hw_amd.c b/drivers/ntb/hw/amd/ntb_hw_amd.c index 87847c380051..1c03a78c125b 100644 --- a/drivers/ntb/hw/amd/ntb_hw_amd.c +++ b/drivers/ntb/hw/amd/ntb_hw_amd.c @@ -1336,12 +1336,17 @@ static struct pci_driver amd_ntb_pci_driver = { static int __init amd_ntb_pci_driver_init(void) { + int ret; pr_info("%s %s\n", NTB_DESC, NTB_VER); if (debugfs_initialized()) debugfs_dir = debugfs_create_dir(KBUILD_MODNAME, NULL); - return pci_register_driver(&amd_ntb_pci_driver); + ret = pci_register_driver(&amd_ntb_pci_driver); + if (ret) + debugfs_remove_recursive(debugfs_dir); + + return ret; } module_init(amd_ntb_pci_driver_init); diff --git a/drivers/ntb/hw/idt/ntb_hw_idt.c b/drivers/ntb/hw/idt/ntb_hw_idt.c index 733557231ed0..72060acb9caf 100644 --- a/drivers/ntb/hw/idt/ntb_hw_idt.c +++ b/drivers/ntb/hw/idt/ntb_hw_idt.c @@ -2891,6 +2891,7 @@ static struct pci_driver idt_pci_driver = { static int __init idt_pci_driver_init(void) { + int ret; pr_info("%s %s\n", NTB_DESC, NTB_VER); /* Create the top DebugFS directory if the FS is initialized */ @@ -2898,7 +2899,11 @@ static int __init idt_pci_driver_init(void) dbgfs_topdir = debugfs_create_dir(KBUILD_MODNAME, NULL); /* Register the NTB hardware driver to handle the PCI device */ - return pci_register_driver(&idt_pci_driver); + ret = pci_register_driver(&idt_pci_driver); + if (ret) + debugfs_remove_recursive(dbgfs_topdir); + + return ret; } module_init(idt_pci_driver_init); diff --git a/drivers/ntb/hw/intel/ntb_hw_gen1.c b/drivers/ntb/hw/intel/ntb_hw_gen1.c index e5f14e20a9ff..41897167abc7 100644 --- a/drivers/ntb/hw/intel/ntb_hw_gen1.c +++ b/drivers/ntb/hw/intel/ntb_hw_gen1.c @@ -2060,12 +2060,17 @@ static struct pci_driver intel_ntb_pci_driver = { static int __init intel_ntb_pci_driver_init(void) { + int ret; pr_info("%s %s\n", NTB_DESC, NTB_VER); if (debugfs_initialized()) debugfs_dir = debugfs_create_dir(KBUILD_MODNAME, NULL); - return pci_register_driver(&intel_ntb_pci_driver); + ret = pci_register_driver(&intel_ntb_pci_driver); + if (ret) + debugfs_remove_recursive(debugfs_dir); + + return ret; } module_init(intel_ntb_pci_driver_init); diff --git a/drivers/ntb/ntb_transport.c b/drivers/ntb/ntb_transport.c index a9b97ebc71ac..2abd2235bbca 100644 --- a/drivers/ntb/ntb_transport.c +++ b/drivers/ntb/ntb_transport.c @@ -410,7 +410,7 @@ int ntb_transport_register_client_dev(char *device_name) rc = device_register(dev); if (rc) { - kfree(client_dev); + put_device(dev); goto err; } diff --git a/drivers/ntb/test/ntb_tool.c b/drivers/ntb/test/ntb_tool.c index 5ee0afa621a9..eeeb4b1c97d2 100644 --- a/drivers/ntb/test/ntb_tool.c +++ b/drivers/ntb/test/ntb_tool.c @@ -998,6 +998,8 @@ static int tool_init_mws(struct tool_ctx *tc) tc->peers[pidx].outmws = devm_kcalloc(&tc->ntb->dev, tc->peers[pidx].outmw_cnt, sizeof(*tc->peers[pidx].outmws), GFP_KERNEL); + if (tc->peers[pidx].outmws == NULL) + return -ENOMEM; for (widx = 0; widx < tc->peers[pidx].outmw_cnt; widx++) { tc->peers[pidx].outmws[widx].pidx = pidx; diff --git a/drivers/nubus/proc.c b/drivers/nubus/proc.c index 88e1f9a0faaf..78cf0e7b53d5 100644 --- a/drivers/nubus/proc.c +++ b/drivers/nubus/proc.c @@ -137,6 +137,18 @@ static int nubus_proc_rsrc_show(struct seq_file *m, void *v) return 0; } +static int nubus_rsrc_proc_open(struct inode *inode, struct file *file) +{ + return single_open(file, nubus_proc_rsrc_show, inode); +} + +static const struct proc_ops nubus_rsrc_proc_ops = { + .proc_open = nubus_rsrc_proc_open, + .proc_read = seq_read, + .proc_lseek = seq_lseek, + .proc_release = single_release, +}; + void nubus_proc_add_rsrc_mem(struct proc_dir_entry *procdir, const struct nubus_dirent *ent, unsigned int size) @@ -152,8 +164,8 @@ void nubus_proc_add_rsrc_mem(struct proc_dir_entry *procdir, pde_data = nubus_proc_alloc_pde_data(nubus_dirptr(ent), size); else pde_data = NULL; - proc_create_single_data(name, S_IFREG | 0444, procdir, - nubus_proc_rsrc_show, pde_data); + proc_create_data(name, S_IFREG | 0444, procdir, + &nubus_rsrc_proc_ops, pde_data); } void nubus_proc_add_rsrc(struct proc_dir_entry *procdir, @@ -166,9 +178,9 @@ void nubus_proc_add_rsrc(struct proc_dir_entry *procdir, return; snprintf(name, sizeof(name), "%x", ent->type); - proc_create_single_data(name, S_IFREG | 0444, procdir, - nubus_proc_rsrc_show, - nubus_proc_alloc_pde_data(data, 0)); + proc_create_data(name, S_IFREG | 0444, procdir, + &nubus_rsrc_proc_ops, + nubus_proc_alloc_pde_data(data, 0)); } /* diff --git a/drivers/nvme/host/pci.c b/drivers/nvme/host/pci.c index a646757f76b3..bb3813e8474f 100644 --- a/drivers/nvme/host/pci.c +++ b/drivers/nvme/host/pci.c @@ -224,7 +224,6 @@ struct nvme_queue { struct nvme_iod { struct nvme_request req; struct nvme_command cmd; - struct nvme_queue *nvmeq; bool use_sgl; int aborted; int npages; /* In the PRP list. 0 means small pool in use */ @@ -422,11 +421,6 @@ static int nvme_init_request(struct blk_mq_tag_set *set, struct request *req, { struct nvme_dev *dev = set->driver_data; struct nvme_iod *iod = blk_mq_rq_to_pdu(req); - int queue_idx = (set == &dev->tagset) ? hctx_idx + 1 : 0; - struct nvme_queue *nvmeq = &dev->queues[queue_idx]; - - BUG_ON(!nvmeq); - iod->nvmeq = nvmeq; nvme_req(req)->ctrl = &dev->ctrl; nvme_req(req)->cmd = &iod->cmd; @@ -529,7 +523,7 @@ static void **nvme_pci_iod_list(struct request *req) static inline bool nvme_pci_use_sgls(struct nvme_dev *dev, struct request *req) { - struct nvme_iod *iod = blk_mq_rq_to_pdu(req); + struct nvme_queue *nvmeq = req->mq_hctx->driver_data; int nseg = blk_rq_nr_phys_segments(req); unsigned int avg_seg_size; @@ -537,7 +531,7 @@ static inline bool nvme_pci_use_sgls(struct nvme_dev *dev, struct request *req) if (!nvme_ctrl_sgl_supported(&dev->ctrl)) return false; - if (!iod->nvmeq->qid) + if (!nvmeq->qid) return false; if (!sgl_threshold || avg_seg_size < sgl_threshold) return false; @@ -846,6 +840,7 @@ static blk_status_t nvme_map_data(struct nvme_dev *dev, struct request *req, int nr_mapped; if (blk_rq_nr_phys_segments(req) == 1) { + struct nvme_queue *nvmeq = req->mq_hctx->driver_data; struct bio_vec bv = req_bvec(req); if (!is_pci_p2pdma_page(bv.bv_page)) { @@ -853,7 +848,7 @@ static blk_status_t nvme_map_data(struct nvme_dev *dev, struct request *req, return nvme_setup_prp_simple(dev, req, &cmnd->rw, &bv); - if (iod->nvmeq->qid && sgl_threshold && + if (nvmeq->qid && sgl_threshold && nvme_ctrl_sgl_supported(&dev->ctrl)) return nvme_setup_sgl_simple(dev, req, &cmnd->rw, &bv); @@ -963,12 +958,16 @@ out_free_cmd: static void nvme_pci_complete_rq(struct request *req) { - struct nvme_iod *iod = blk_mq_rq_to_pdu(req); - struct nvme_dev *dev = iod->nvmeq->dev; + struct nvme_queue *nvmeq = req->mq_hctx->driver_data; + struct nvme_dev *dev = nvmeq->dev; + + if (blk_integrity_rq(req)) { + struct nvme_iod *iod = blk_mq_rq_to_pdu(req); - if (blk_integrity_rq(req)) dma_unmap_page(dev->dev, iod->meta_dma, - rq_integrity_vec(req)->bv_len, rq_data_dir(req)); + rq_integrity_vec(req)->bv_len, rq_dma_dir(req)); + } + if (blk_rq_nr_phys_segments(req)) nvme_unmap_data(dev, req); nvme_complete_rq(req); @@ -1194,8 +1193,7 @@ static int adapter_delete_sq(struct nvme_dev *dev, u16 sqid) static void abort_endio(struct request *req, blk_status_t error) { - struct nvme_iod *iod = blk_mq_rq_to_pdu(req); - struct nvme_queue *nvmeq = iod->nvmeq; + struct nvme_queue *nvmeq = req->mq_hctx->driver_data; dev_warn(nvmeq->dev->ctrl.device, "Abort status: 0x%x", nvme_req(req)->status); @@ -1249,7 +1247,7 @@ static void nvme_warn_reset(struct nvme_dev *dev, u32 csts) static enum blk_eh_timer_return nvme_timeout(struct request *req, bool reserved) { struct nvme_iod *iod = blk_mq_rq_to_pdu(req); - struct nvme_queue *nvmeq = iod->nvmeq; + struct nvme_queue *nvmeq = req->mq_hctx->driver_data; struct nvme_dev *dev = nvmeq->dev; struct request *abort_req; struct nvme_command cmd = { }; diff --git a/drivers/nvmem/rmem.c b/drivers/nvmem/rmem.c index 80cb187f1481..752d0bf4445e 100644 --- a/drivers/nvmem/rmem.c +++ b/drivers/nvmem/rmem.c @@ -71,6 +71,7 @@ static int rmem_probe(struct platform_device *pdev) config.dev = dev; config.priv = priv; config.name = "rmem"; + config.id = NVMEM_DEVID_AUTO; config.size = mem->size; config.reg_read = rmem_read; diff --git a/drivers/opp/core.c b/drivers/opp/core.c index b2da497dd378..4960d5f8c8bc 100644 --- a/drivers/opp/core.c +++ b/drivers/opp/core.c @@ -1249,7 +1249,10 @@ static struct opp_table *_allocate_opp_table(struct device *dev, int index) return opp_table; remove_opp_dev: + _of_clear_opp_table(opp_table); _remove_opp_dev(opp_dev, opp_table); + mutex_destroy(&opp_table->genpd_virt_dev_lock); + mutex_destroy(&opp_table->lock); err: kfree(opp_table); return ERR_PTR(ret); diff --git a/drivers/pci/controller/cadence/pcie-cadence-host.c b/drivers/pci/controller/cadence/pcie-cadence-host.c index fb96d37a135c..4d8d15ac51ef 100644 --- a/drivers/pci/controller/cadence/pcie-cadence-host.c +++ b/drivers/pci/controller/cadence/pcie-cadence-host.c @@ -12,6 +12,8 @@ #include "pcie-cadence.h" +#define LINK_RETRAIN_TIMEOUT HZ + static u64 bar_max_size[] = { [RP_BAR0] = _ULL(128 * SZ_2G), [RP_BAR1] = SZ_2G, @@ -77,6 +79,27 @@ static struct pci_ops cdns_pcie_host_ops = { .write = pci_generic_config_write, }; +static int cdns_pcie_host_training_complete(struct cdns_pcie *pcie) +{ + u32 pcie_cap_off = CDNS_PCIE_RP_CAP_OFFSET; + unsigned long end_jiffies; + u16 lnk_stat; + + /* Wait for link training to complete. Exit after timeout. */ + end_jiffies = jiffies + LINK_RETRAIN_TIMEOUT; + do { + lnk_stat = cdns_pcie_rp_readw(pcie, pcie_cap_off + PCI_EXP_LNKSTA); + if (!(lnk_stat & PCI_EXP_LNKSTA_LT)) + break; + usleep_range(0, 1000); + } while (time_before(jiffies, end_jiffies)); + + if (!(lnk_stat & PCI_EXP_LNKSTA_LT)) + return 0; + + return -ETIMEDOUT; +} + static int cdns_pcie_host_wait_for_link(struct cdns_pcie *pcie) { struct device *dev = pcie->dev; @@ -118,6 +141,10 @@ static int cdns_pcie_retrain(struct cdns_pcie *pcie) cdns_pcie_rp_writew(pcie, pcie_cap_off + PCI_EXP_LNKCTL, lnk_ctl); + ret = cdns_pcie_host_training_complete(pcie); + if (ret) + return ret; + ret = cdns_pcie_host_wait_for_link(pcie); } return ret; diff --git a/drivers/pci/controller/dwc/pcie-qcom.c b/drivers/pci/controller/dwc/pcie-qcom.c index 5960cbbea818..9402fe8dddab 100644 --- a/drivers/pci/controller/dwc/pcie-qcom.c +++ b/drivers/pci/controller/dwc/pcie-qcom.c @@ -1134,6 +1134,8 @@ static int qcom_pcie_post_init_2_3_3(struct qcom_pcie *pcie) writel(PCI_EXP_DEVCTL2_COMP_TMOUT_DIS, pci->dbi_base + offset + PCI_EXP_DEVCTL2); + dw_pcie_dbi_ro_wr_dis(pci); + return 0; } diff --git a/drivers/pci/controller/pci-ftpci100.c b/drivers/pci/controller/pci-ftpci100.c index 88980a44461d..ca8de44045bb 100644 --- a/drivers/pci/controller/pci-ftpci100.c +++ b/drivers/pci/controller/pci-ftpci100.c @@ -442,22 +442,12 @@ static int faraday_pci_probe(struct platform_device *pdev) p->dev = dev; /* Retrieve and enable optional clocks */ - clk = devm_clk_get(dev, "PCLK"); + clk = devm_clk_get_enabled(dev, "PCLK"); if (IS_ERR(clk)) return PTR_ERR(clk); - ret = clk_prepare_enable(clk); - if (ret) { - dev_err(dev, "could not prepare PCLK\n"); - return ret; - } - p->bus_clk = devm_clk_get(dev, "PCICLK"); + p->bus_clk = devm_clk_get_enabled(dev, "PCICLK"); if (IS_ERR(p->bus_clk)) return PTR_ERR(p->bus_clk); - ret = clk_prepare_enable(p->bus_clk); - if (ret) { - dev_err(dev, "could not prepare PCICLK\n"); - return ret; - } p->base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(p->base)) diff --git a/drivers/pci/controller/pci-msm.c b/drivers/pci/controller/pci-msm.c index 4ab9ab0c9302..aed84199f11b 100644 --- a/drivers/pci/controller/pci-msm.c +++ b/drivers/pci/controller/pci-msm.c @@ -6716,7 +6716,7 @@ static irqreturn_t handle_global_irq(int irq, void *data) int i; struct msm_pcie_dev_t *dev = data; struct pci_dev *rp = dev->dev; - int aer = rp->aer_cap; + int aer; unsigned long irqsave_flags; u32 status = 0, status2 = 0; irqreturn_t ret = IRQ_HANDLED; @@ -6763,6 +6763,13 @@ static irqreturn_t handle_global_irq(int irq, void *data) "PCIe: RC%d: AER event idx %d.\n", dev->rc_idx, i); + if (!rp) { + PCIE_DBG2(dev, "PCIe: RC%d pci_dev is not allocated.\n", + dev->rc_idx); + goto done; + } + + aer = rp->aer_cap; pci_read_config_dword(rp, aer + PCI_ERR_ROOT_STATUS, &e_src.status); if (!(e_src.status & diff --git a/drivers/pci/controller/pcie-rockchip-ep.c b/drivers/pci/controller/pcie-rockchip-ep.c index d1a200b93b2b..827d91e73efa 100644 --- a/drivers/pci/controller/pcie-rockchip-ep.c +++ b/drivers/pci/controller/pcie-rockchip-ep.c @@ -125,6 +125,7 @@ static void rockchip_pcie_prog_ep_ob_atu(struct rockchip_pcie *rockchip, u8 fn, static int rockchip_pcie_ep_write_header(struct pci_epc *epc, u8 fn, u8 vfn, struct pci_epf_header *hdr) { + u32 reg; struct rockchip_pcie_ep *ep = epc_get_drvdata(epc); struct rockchip_pcie *rockchip = &ep->rockchip; @@ -137,8 +138,9 @@ static int rockchip_pcie_ep_write_header(struct pci_epc *epc, u8 fn, u8 vfn, PCIE_CORE_CONFIG_VENDOR); } - rockchip_pcie_write(rockchip, hdr->deviceid << 16, - ROCKCHIP_PCIE_EP_FUNC_BASE(fn) + PCI_VENDOR_ID); + reg = rockchip_pcie_read(rockchip, PCIE_EP_CONFIG_DID_VID); + reg = (reg & 0xFFFF) | (hdr->deviceid << 16); + rockchip_pcie_write(rockchip, reg, PCIE_EP_CONFIG_DID_VID); rockchip_pcie_write(rockchip, hdr->revid | @@ -312,15 +314,15 @@ static int rockchip_pcie_ep_set_msi(struct pci_epc *epc, u8 fn, u8 vfn, { struct rockchip_pcie_ep *ep = epc_get_drvdata(epc); struct rockchip_pcie *rockchip = &ep->rockchip; - u16 flags; + u32 flags; flags = rockchip_pcie_read(rockchip, ROCKCHIP_PCIE_EP_FUNC_BASE(fn) + ROCKCHIP_PCIE_EP_MSI_CTRL_REG); flags &= ~ROCKCHIP_PCIE_EP_MSI_CTRL_MMC_MASK; flags |= - ((multi_msg_cap << 1) << ROCKCHIP_PCIE_EP_MSI_CTRL_MMC_OFFSET) | - PCI_MSI_FLAGS_64BIT; + (multi_msg_cap << ROCKCHIP_PCIE_EP_MSI_CTRL_MMC_OFFSET) | + (PCI_MSI_FLAGS_64BIT << ROCKCHIP_PCIE_EP_MSI_FLAGS_OFFSET); flags &= ~ROCKCHIP_PCIE_EP_MSI_CTRL_MASK_MSI_CAP; rockchip_pcie_write(rockchip, flags, ROCKCHIP_PCIE_EP_FUNC_BASE(fn) + @@ -332,7 +334,7 @@ static int rockchip_pcie_ep_get_msi(struct pci_epc *epc, u8 fn, u8 vfn) { struct rockchip_pcie_ep *ep = epc_get_drvdata(epc); struct rockchip_pcie *rockchip = &ep->rockchip; - u16 flags; + u32 flags; flags = rockchip_pcie_read(rockchip, ROCKCHIP_PCIE_EP_FUNC_BASE(fn) + @@ -345,48 +347,25 @@ static int rockchip_pcie_ep_get_msi(struct pci_epc *epc, u8 fn, u8 vfn) } static void rockchip_pcie_ep_assert_intx(struct rockchip_pcie_ep *ep, u8 fn, - u8 intx, bool is_asserted) + u8 intx, bool do_assert) { struct rockchip_pcie *rockchip = &ep->rockchip; - u32 r = ep->max_regions - 1; - u32 offset; - u32 status; - u8 msg_code; - - if (unlikely(ep->irq_pci_addr != ROCKCHIP_PCIE_EP_PCI_LEGACY_IRQ_ADDR || - ep->irq_pci_fn != fn)) { - rockchip_pcie_prog_ep_ob_atu(rockchip, fn, r, - AXI_WRAPPER_NOR_MSG, - ep->irq_phys_addr, 0, 0); - ep->irq_pci_addr = ROCKCHIP_PCIE_EP_PCI_LEGACY_IRQ_ADDR; - ep->irq_pci_fn = fn; - } intx &= 3; - if (is_asserted) { + + if (do_assert) { ep->irq_pending |= BIT(intx); - msg_code = ROCKCHIP_PCIE_MSG_CODE_ASSERT_INTA + intx; + rockchip_pcie_write(rockchip, + PCIE_CLIENT_INT_IN_ASSERT | + PCIE_CLIENT_INT_PEND_ST_PEND, + PCIE_CLIENT_LEGACY_INT_CTRL); } else { ep->irq_pending &= ~BIT(intx); - msg_code = ROCKCHIP_PCIE_MSG_CODE_DEASSERT_INTA + intx; + rockchip_pcie_write(rockchip, + PCIE_CLIENT_INT_IN_DEASSERT | + PCIE_CLIENT_INT_PEND_ST_NORMAL, + PCIE_CLIENT_LEGACY_INT_CTRL); } - - status = rockchip_pcie_read(rockchip, - ROCKCHIP_PCIE_EP_FUNC_BASE(fn) + - ROCKCHIP_PCIE_EP_CMD_STATUS); - status &= ROCKCHIP_PCIE_EP_CMD_STATUS_IS; - - if ((status != 0) ^ (ep->irq_pending != 0)) { - status ^= ROCKCHIP_PCIE_EP_CMD_STATUS_IS; - rockchip_pcie_write(rockchip, status, - ROCKCHIP_PCIE_EP_FUNC_BASE(fn) + - ROCKCHIP_PCIE_EP_CMD_STATUS); - } - - offset = - ROCKCHIP_PCIE_MSG_ROUTING(ROCKCHIP_PCIE_MSG_ROUTING_LOCAL_INTX) | - ROCKCHIP_PCIE_MSG_CODE(msg_code) | ROCKCHIP_PCIE_MSG_NO_DATA; - writel(0, ep->irq_cpu_addr + offset); } static int rockchip_pcie_ep_send_legacy_irq(struct rockchip_pcie_ep *ep, u8 fn, @@ -416,7 +395,7 @@ static int rockchip_pcie_ep_send_msi_irq(struct rockchip_pcie_ep *ep, u8 fn, u8 interrupt_num) { struct rockchip_pcie *rockchip = &ep->rockchip; - u16 flags, mme, data, data_mask; + u32 flags, mme, data, data_mask; u8 msi_count; u64 pci_addr, pci_addr_mask = 0xff; @@ -506,6 +485,7 @@ static const struct pci_epc_features rockchip_pcie_epc_features = { .linkup_notifier = false, .msi_capable = true, .msix_capable = false, + .align = 256, }; static const struct pci_epc_features* @@ -631,6 +611,9 @@ static int rockchip_pcie_ep_probe(struct platform_device *pdev) ep->irq_pci_addr = ROCKCHIP_PCIE_EP_DUMMY_IRQ_ADDR; + rockchip_pcie_write(rockchip, PCIE_CLIENT_CONF_ENABLE, + PCIE_CLIENT_CONFIG); + return 0; err_epc_mem_exit: pci_epc_mem_exit(epc); diff --git a/drivers/pci/controller/pcie-rockchip.c b/drivers/pci/controller/pcie-rockchip.c index 990a00e08bc5..1aa84035a8bc 100644 --- a/drivers/pci/controller/pcie-rockchip.c +++ b/drivers/pci/controller/pcie-rockchip.c @@ -14,6 +14,7 @@ #include #include #include +#include #include #include #include @@ -153,6 +154,12 @@ int rockchip_pcie_parse_dt(struct rockchip_pcie *rockchip) } EXPORT_SYMBOL_GPL(rockchip_pcie_parse_dt); +#define rockchip_pcie_read_addr(addr) rockchip_pcie_read(rockchip, addr) +/* 100 ms max wait time for PHY PLLs to lock */ +#define RK_PHY_PLL_LOCK_TIMEOUT_US 100000 +/* Sleep should be less than 20ms */ +#define RK_PHY_PLL_LOCK_SLEEP_US 1000 + int rockchip_pcie_init_port(struct rockchip_pcie *rockchip) { struct device *dev = rockchip->dev; @@ -254,6 +261,16 @@ int rockchip_pcie_init_port(struct rockchip_pcie *rockchip) } } + err = readx_poll_timeout(rockchip_pcie_read_addr, + PCIE_CLIENT_SIDE_BAND_STATUS, + regs, !(regs & PCIE_CLIENT_PHY_ST), + RK_PHY_PLL_LOCK_SLEEP_US, + RK_PHY_PLL_LOCK_TIMEOUT_US); + if (err) { + dev_err(dev, "PHY PLLs could not lock, %d\n", err); + goto err_power_off_phy; + } + /* * Please don't reorder the deassert sequence of the following * four reset pins. diff --git a/drivers/pci/controller/pcie-rockchip.h b/drivers/pci/controller/pcie-rockchip.h index 1650a5087450..cbd2fd25ba76 100644 --- a/drivers/pci/controller/pcie-rockchip.h +++ b/drivers/pci/controller/pcie-rockchip.h @@ -38,6 +38,13 @@ #define PCIE_CLIENT_MODE_EP HIWORD_UPDATE(0x0040, 0) #define PCIE_CLIENT_GEN_SEL_1 HIWORD_UPDATE(0x0080, 0) #define PCIE_CLIENT_GEN_SEL_2 HIWORD_UPDATE_BIT(0x0080) +#define PCIE_CLIENT_LEGACY_INT_CTRL (PCIE_CLIENT_BASE + 0x0c) +#define PCIE_CLIENT_INT_IN_ASSERT HIWORD_UPDATE_BIT(0x0002) +#define PCIE_CLIENT_INT_IN_DEASSERT HIWORD_UPDATE(0x0002, 0) +#define PCIE_CLIENT_INT_PEND_ST_PEND HIWORD_UPDATE_BIT(0x0001) +#define PCIE_CLIENT_INT_PEND_ST_NORMAL HIWORD_UPDATE(0x0001, 0) +#define PCIE_CLIENT_SIDE_BAND_STATUS (PCIE_CLIENT_BASE + 0x20) +#define PCIE_CLIENT_PHY_ST BIT(12) #define PCIE_CLIENT_DEBUG_OUT_0 (PCIE_CLIENT_BASE + 0x3c) #define PCIE_CLIENT_DEBUG_LTSSM_MASK GENMASK(5, 0) #define PCIE_CLIENT_DEBUG_LTSSM_L1 0x18 @@ -133,6 +140,8 @@ #define PCIE_RC_RP_ATS_BASE 0x400000 #define PCIE_RC_CONFIG_NORMAL_BASE 0x800000 #define PCIE_RC_CONFIG_BASE 0xa00000 +#define PCIE_EP_CONFIG_BASE 0xa00000 +#define PCIE_EP_CONFIG_DID_VID (PCIE_EP_CONFIG_BASE + 0x00) #define PCIE_RC_CONFIG_RID_CCR (PCIE_RC_CONFIG_BASE + 0x08) #define PCIE_RC_CONFIG_SCC_SHIFT 16 #define PCIE_RC_CONFIG_DCR (PCIE_RC_CONFIG_BASE + 0xc4) @@ -217,6 +226,7 @@ #define ROCKCHIP_PCIE_EP_CMD_STATUS 0x4 #define ROCKCHIP_PCIE_EP_CMD_STATUS_IS BIT(19) #define ROCKCHIP_PCIE_EP_MSI_CTRL_REG 0x90 +#define ROCKCHIP_PCIE_EP_MSI_FLAGS_OFFSET 16 #define ROCKCHIP_PCIE_EP_MSI_CTRL_MMC_OFFSET 17 #define ROCKCHIP_PCIE_EP_MSI_CTRL_MMC_MASK GENMASK(19, 17) #define ROCKCHIP_PCIE_EP_MSI_CTRL_MME_OFFSET 20 @@ -224,7 +234,6 @@ #define ROCKCHIP_PCIE_EP_MSI_CTRL_ME BIT(16) #define ROCKCHIP_PCIE_EP_MSI_CTRL_MASK_MSI_CAP BIT(24) #define ROCKCHIP_PCIE_EP_DUMMY_IRQ_ADDR 0x1 -#define ROCKCHIP_PCIE_EP_PCI_LEGACY_IRQ_ADDR 0x3 #define ROCKCHIP_PCIE_EP_FUNC_BASE(fn) (((fn) << 12) & GENMASK(19, 12)) #define ROCKCHIP_PCIE_AT_IB_EP_FUNC_BAR_ADDR0(fn, bar) \ (PCIE_RC_RP_ATS_BASE + 0x0840 + (fn) * 0x0040 + (bar) * 0x0008) diff --git a/drivers/pci/controller/vmd.c b/drivers/pci/controller/vmd.c index 8dce71142e10..f49001ba96c7 100644 --- a/drivers/pci/controller/vmd.c +++ b/drivers/pci/controller/vmd.c @@ -881,6 +881,13 @@ static void vmd_remove(struct pci_dev *dev) vmd_remove_irq_domain(vmd); } +static void vmd_shutdown(struct pci_dev *dev) +{ + struct vmd_dev *vmd = pci_get_drvdata(dev); + + vmd_remove_irq_domain(vmd); +} + #ifdef CONFIG_PM_SLEEP static int vmd_suspend(struct device *dev) { @@ -946,6 +953,7 @@ static struct pci_driver vmd_drv = { .id_table = vmd_ids, .probe = vmd_probe, .remove = vmd_remove, + .shutdown = vmd_shutdown, .driver = { .pm = &vmd_dev_pm_ops, }, diff --git a/drivers/pci/hotplug/pciehp_ctrl.c b/drivers/pci/hotplug/pciehp_ctrl.c index 529c34808440..32baba1b7f13 100644 --- a/drivers/pci/hotplug/pciehp_ctrl.c +++ b/drivers/pci/hotplug/pciehp_ctrl.c @@ -256,6 +256,14 @@ void pciehp_handle_presence_or_link_change(struct controller *ctrl, u32 events) present = pciehp_card_present(ctrl); link_active = pciehp_check_link_active(ctrl); if (present <= 0 && link_active <= 0) { + if (ctrl->state == BLINKINGON_STATE) { + ctrl->state = OFF_STATE; + cancel_delayed_work(&ctrl->button_work); + pciehp_set_indicators(ctrl, PCI_EXP_SLTCTL_PWR_IND_OFF, + INDICATOR_NOOP); + ctrl_info(ctrl, "Slot(%s): Card not present\n", + slot_name(ctrl)); + } mutex_unlock(&ctrl->state_lock); return; } diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index b942583d082c..0ff79bcd12a3 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -2886,13 +2886,13 @@ static const struct dmi_system_id bridge_d3_blacklist[] = { { /* * Downstream device is not accessible after putting a root port - * into D3cold and back into D0 on Elo i2. + * into D3cold and back into D0 on Elo Continental Z2 board */ - .ident = "Elo i2", + .ident = "Elo Continental Z2", .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "Elo Touch Solutions"), - DMI_MATCH(DMI_PRODUCT_NAME, "Elo i2"), - DMI_MATCH(DMI_PRODUCT_VERSION, "RevB"), + DMI_MATCH(DMI_BOARD_VENDOR, "Elo Touch Solutions"), + DMI_MATCH(DMI_BOARD_NAME, "Geminilake"), + DMI_MATCH(DMI_BOARD_VERSION, "Continental Z2"), }, }, #endif diff --git a/drivers/pci/pcie/aspm.c b/drivers/pci/pcie/aspm.c index b3ad316418f1..c58294f53fcd 100644 --- a/drivers/pci/pcie/aspm.c +++ b/drivers/pci/pcie/aspm.c @@ -993,21 +993,24 @@ void pcie_aspm_exit_link_state(struct pci_dev *pdev) down_read(&pci_bus_sem); mutex_lock(&aspm_lock); - /* - * All PCIe functions are in one slot, remove one function will remove - * the whole slot, so just wait until we are the last function left. - */ - if (!list_empty(&parent->subordinate->devices)) - goto out; link = parent->link_state; root = link->root; parent_link = link->parent; - /* All functions are removed, so just disable ASPM for the link */ + /* + * link->downstream is a pointer to the pci_dev of function 0. If + * we remove that function, the pci_dev is about to be deallocated, + * so we can't use link->downstream again. Free the link state to + * avoid this. + * + * If we're removing a non-0 function, it's possible we could + * retain the link state, but PCIe r6.0, sec 7.5.3.7, recommends + * programming the same ASPM Control value for all functions of + * multi-function devices, so disable ASPM for all of them. + */ pcie_config_aspm_link(link, 0); list_del(&link->sibling); - /* Clock PM is for endpoint device */ free_link_state(link); /* Recheck latencies and configure upstream links */ @@ -1015,7 +1018,7 @@ void pcie_aspm_exit_link_state(struct pci_dev *pdev) pcie_update_aspm_capable(root); pcie_config_aspm_path(parent_link); } -out: + mutex_unlock(&aspm_lock); up_read(&pci_bus_sem); } diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c index 643a3b292f0b..ec17d42c2a15 100644 --- a/drivers/pci/quirks.c +++ b/drivers/pci/quirks.c @@ -4149,6 +4149,8 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_MARVELL_EXT, 0x9220, /* https://bugzilla.kernel.org/show_bug.cgi?id=42679#c49 */ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_MARVELL_EXT, 0x9230, quirk_dma_func1_alias); +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_MARVELL_EXT, 0x9235, + quirk_dma_func1_alias); DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_TTI, 0x0642, quirk_dma_func1_alias); DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_TTI, 0x0645, diff --git a/drivers/perf/arm-cmn.c b/drivers/perf/arm-cmn.c index 9ddb5034d3ec..24852dbf69f1 100644 --- a/drivers/perf/arm-cmn.c +++ b/drivers/perf/arm-cmn.c @@ -1571,9 +1571,10 @@ static int arm_cmn_init_dtc(struct arm_cmn *cmn, struct arm_cmn_node *dn, int id if (dtc->irq < 0) return dtc->irq; - writel_relaxed(0, dtc->base + CMN_DT_PMCR); + writel_relaxed(CMN_DT_DTC_CTL_DT_EN, dtc->base + CMN_DT_DTC_CTL); + writel_relaxed(CMN_DT_PMCR_PMU_EN | CMN_DT_PMCR_OVFL_INTR_EN, dtc->base + CMN_DT_PMCR); + writeq_relaxed(0, dtc->base + CMN_DT_PMCCNTR); writel_relaxed(0x1ff, dtc->base + CMN_DT_PMOVSR_CLR); - writel_relaxed(CMN_DT_PMCR_OVFL_INTR_EN, dtc->base + CMN_DT_PMCR); return 0; } @@ -1629,7 +1630,7 @@ static int arm_cmn_init_dtcs(struct arm_cmn *cmn) dn->type = CMN_TYPE_RNI; } - writel_relaxed(CMN_DT_DTC_CTL_DT_EN, cmn->dtc[0].base + CMN_DT_DTC_CTL); + arm_cmn_set_state(cmn, CMN_STATE_DISABLED); return 0; } diff --git a/drivers/phy/qualcomm/Kconfig b/drivers/phy/qualcomm/Kconfig index e6f0386d7ec6..3027ad0d7540 100644 --- a/drivers/phy/qualcomm/Kconfig +++ b/drivers/phy/qualcomm/Kconfig @@ -78,6 +78,12 @@ config PHY_QCOM_UFS_V4 help Support for 7nm UFS QMP phy present on QCOM chipsets. +config PHY_QCOM_UFS_V3 + tristate "Qualcomm Technologies, Inc. UFS PHY V3 driver" + depends on PHY_QCOM_UFS + help + Support for 11nm UFS QMP phy present on QCOM chipsets. + config PHY_QCOM_UFS_QRBTC_SDM845 tristate "Qualcomm Technologies, Inc. UFS Presil Phy Driver" depends on PHY_QCOM_UFS && REGULATOR_STUB diff --git a/drivers/phy/qualcomm/Makefile b/drivers/phy/qualcomm/Makefile index 2bfe5e1cdf8e..0b4374960377 100644 --- a/drivers/phy/qualcomm/Makefile +++ b/drivers/phy/qualcomm/Makefile @@ -8,6 +8,7 @@ obj-$(CONFIG_PHY_QCOM_QMP) += phy-qcom-qmp.o obj-$(CONFIG_PHY_QCOM_QUSB2) += phy-qcom-qusb2.o obj-$(CONFIG_PHY_QCOM_UFS) += phy-qcom-ufs.o obj-$(CONFIG_PHY_QCOM_UFS_V4) += phy-qcom-ufs-qmp-v4-kalama.o phy-qcom-ufs-qmp-v4-waipio.o phy-qcom-ufs-qmp-v4.o phy-qcom-ufs-qmp-v4-khaje.o phy-qcom-ufs-qmp-v4-lahaina.o phy-qcom-ufs-qmp-v4-kona.o phy-qcom-ufs-qmp-v4-crow.o +obj-$(CONFIG_PHY_QCOM_UFS_V3) += phy-qcom-ufs-qmp-v3-660.o obj-$(CONFIG_PHY_QCOM_UFS_QRBTC_SDM845) += phy-qcom-ufs-qrbtc-sdm845.o obj-$(CONFIG_PHY_QCOM_USB_HS) += phy-qcom-usb-hs.o obj-$(CONFIG_PHY_QCOM_USB_HSIC) += phy-qcom-usb-hsic.o diff --git a/drivers/phy/qualcomm/phy-qcom-ufs-qmp-v3-660.c b/drivers/phy/qualcomm/phy-qcom-ufs-qmp-v3-660.c new file mode 100644 index 000000000000..2d0b11f84f4e --- /dev/null +++ b/drivers/phy/qualcomm/phy-qcom-ufs-qmp-v3-660.c @@ -0,0 +1,265 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2013-2018,2021, The Linux Foundation. All rights reserved. + * Copyright (c) 2023, Qualcomm Innovation Center, Inc. All rights reserved. + */ + +#include "phy-qcom-ufs-qmp-v3-660.h" + +#define UFS_PHY_NAME "ufs_phy_qmp_v3_660" + +static +int ufs_qcom_phy_qmp_v3_660_phy_calibrate(struct phy *generic_phy) +{ + struct ufs_qcom_phy *ufs_qcom_phy = get_ufs_qcom_phy(generic_phy); + bool is_g4, is_rate_B; + int err; + int tbl_size_A, tbl_size_B; + struct ufs_qcom_phy_calibration *tbl_A, *tbl_B; + u8 major = ufs_qcom_phy->host_ctrl_rev_major; + u16 minor = ufs_qcom_phy->host_ctrl_rev_minor; + u16 step = ufs_qcom_phy->host_ctrl_rev_step; + + /* For UFS PHY's submode, 1 = G4, 0 = non-G4 */ + is_g4 = !!ufs_qcom_phy->submode; + is_rate_B = (ufs_qcom_phy->mode == PHY_MODE_UFS_HS_B) ? true : false; + + tbl_size_B = ARRAY_SIZE(phy_cal_table_rate_B); + tbl_B = phy_cal_table_rate_B; + + if ((major == 0x3) && (minor == 0x001) && (step >= 0x001)) { + tbl_A = phy_cal_table_rate_A_3_1_1; + tbl_size_A = ARRAY_SIZE(phy_cal_table_rate_A_3_1_1); + } else { + dev_err(ufs_qcom_phy->dev, + "%s: Unknown UFS-PHY version (major 0x%x minor 0x%x step 0x%x), no calibration values\n", + __func__, major, minor, step); + err = -ENODEV; + goto out; + } + + err = ufs_qcom_phy_calibrate(ufs_qcom_phy, + tbl_A, tbl_size_A, + tbl_B, tbl_size_B, + is_rate_B); + + if (err) + dev_err(ufs_qcom_phy->dev, + "%s: ufs_qcom_phy_calibrate() failed %d\n", + __func__, err); + +out: + return err; +} + +static int ufs_qcom_phy_qmp_v3_660_init(struct phy *generic_phy) +{ + struct ufs_qcom_phy_qmp_v3_660 *phy = phy_get_drvdata(generic_phy); + struct ufs_qcom_phy *phy_common = &phy->common_cfg; + int err; + + err = ufs_qcom_phy_init_clks(phy_common); + if (err) { + dev_err(phy_common->dev, "%s: ufs_qcom_phy_init_clks() failed %d\n", + __func__, err); + goto out; + } + + err = ufs_qcom_phy_init_vregulators(phy_common); + if (err) { + dev_err(phy_common->dev, "%s: ufs_qcom_phy_init_vregulators() failed %d\n", + __func__, err); + goto out; + } + + /* Optional */ + ufs_qcom_phy_get_reset(phy_common); + +out: + return err; +} + +static int ufs_qcom_phy_qmp_v3_660_exit(struct phy *generic_phy) +{ + return 0; +} + +static +int ufs_qcom_phy_qmp_v3_660_set_mode(struct phy *generic_phy, + enum phy_mode mode, int submode) +{ + struct ufs_qcom_phy *phy_common = get_ufs_qcom_phy(generic_phy); + + phy_common->mode = PHY_MODE_INVALID; + + if (mode > 0) + phy_common->mode = mode; + + phy_common->submode = submode; + + return 0; +} + +static +void ufs_qcom_phy_qmp_v3_660_power_control(struct ufs_qcom_phy *phy, + bool power_ctrl) +{ + if (!power_ctrl) { + /* apply analog power collapse */ + writel_relaxed(0x0, phy->mmio + UFS_PHY_POWER_DOWN_CONTROL); + /* + * Make sure that PHY knows its analog rail is going to be + * powered OFF. + */ + mb(); + } else { + /* bring PHY out of analog power collapse */ + writel_relaxed(0x1, phy->mmio + UFS_PHY_POWER_DOWN_CONTROL); + + /* + * Before any transactions involving PHY, ensure PHY knows + * that it's analog rail is powered ON. + */ + mb(); + } +} + +static inline +void ufs_qcom_phy_qmp_v3_660_set_tx_lane_enable(struct ufs_qcom_phy *phy, + u32 val) +{ + /* + * v3 PHY does not have TX_LANE_ENABLE register. + * Implement this function so as not to propagate error to caller. + */ +} + +static +void ufs_qcom_phy_qmp_v3_660_ctrl_rx_linecfg(struct ufs_qcom_phy *phy, + bool ctrl) +{ + u32 temp; + + temp = readl_relaxed(phy->mmio + UFS_PHY_LINECFG_DISABLE); + + if (ctrl) /* enable RX LineCfg */ + temp &= ~UFS_PHY_RX_LINECFG_DISABLE_BIT; + else /* disable RX LineCfg */ + temp |= UFS_PHY_RX_LINECFG_DISABLE_BIT; + + writel_relaxed(temp, phy->mmio + UFS_PHY_LINECFG_DISABLE); + /* Make sure that RX LineCfg config applied before we return */ + mb(); +} + +static inline void ufs_qcom_phy_qmp_v3_660_start_serdes( + struct ufs_qcom_phy *phy) +{ + u32 tmp; + + tmp = readl_relaxed(phy->mmio + UFS_PHY_PHY_START); + tmp &= ~MASK_SERDES_START; + tmp |= (1 << OFFSET_SERDES_START); + writel_relaxed(tmp, phy->mmio + UFS_PHY_PHY_START); + /* Ensure register value is committed */ + mb(); +} + +static int ufs_qcom_phy_qmp_v3_660_is_pcs_ready( + struct ufs_qcom_phy *phy_common) +{ + int err = 0; + u32 val; + + err = readl_poll_timeout(phy_common->mmio + UFS_PHY_PCS_READY_STATUS, + val, (val & MASK_PCS_READY), 10, 1000000); + if (err) + dev_err(phy_common->dev, "%s: poll for pcs failed err = %d\n", + __func__, err); + return err; +} + +static void ufs_qcom_phy_qmp_v3_660_dbg_register_dump( + struct ufs_qcom_phy *phy) +{ + ufs_qcom_phy_dump_regs(phy, COM_BASE, COM_SIZE, + "PHY QSERDES COM Registers "); + ufs_qcom_phy_dump_regs(phy, PHY_BASE, PHY_SIZE, + "PHY Registers "); + ufs_qcom_phy_dump_regs(phy, RX_BASE, RX_SIZE, + "PHY RX0 Registers "); + ufs_qcom_phy_dump_regs(phy, TX_BASE, TX_SIZE, + "PHY TX0 Registers "); +} + +static const struct phy_ops ufs_qcom_phy_qmp_v3_660_phy_ops = { + .init = ufs_qcom_phy_qmp_v3_660_init, + .exit = ufs_qcom_phy_qmp_v3_660_exit, + .power_on = ufs_qcom_phy_power_on, + .power_off = ufs_qcom_phy_power_off, + .set_mode = ufs_qcom_phy_qmp_v3_660_set_mode, + .calibrate = ufs_qcom_phy_qmp_v3_660_phy_calibrate, + .owner = THIS_MODULE, +}; + +static struct ufs_qcom_phy_specific_ops phy_v3_660_ops = { + .start_serdes = ufs_qcom_phy_qmp_v3_660_start_serdes, + .is_physical_coding_sublayer_ready = + ufs_qcom_phy_qmp_v3_660_is_pcs_ready, + .set_tx_lane_enable = ufs_qcom_phy_qmp_v3_660_set_tx_lane_enable, + .ctrl_rx_linecfg = ufs_qcom_phy_qmp_v3_660_ctrl_rx_linecfg, + .power_control = ufs_qcom_phy_qmp_v3_660_power_control, + .dbg_register_dump = ufs_qcom_phy_qmp_v3_660_dbg_register_dump, +}; + +static int ufs_qcom_phy_qmp_v3_660_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct phy *generic_phy; + struct ufs_qcom_phy_qmp_v3_660 *phy; + int err = 0; + + phy = devm_kzalloc(dev, sizeof(*phy), GFP_KERNEL); + if (!phy) { + err = -ENOMEM; + goto out; + } + + generic_phy = ufs_qcom_phy_generic_probe(pdev, &phy->common_cfg, + &ufs_qcom_phy_qmp_v3_660_phy_ops, + &phy_v3_660_ops); + + if (!generic_phy) { + dev_err(dev, "%s: ufs_qcom_phy_generic_probe() failed\n", + __func__); + err = -EIO; + goto out; + } + + phy_set_drvdata(generic_phy, phy); + + strscpy(phy->common_cfg.name, UFS_PHY_NAME, + sizeof(phy->common_cfg.name)); + +out: + return err; +} + +static const struct of_device_id ufs_qcom_phy_qmp_v3_660_of_match[] = { + {.compatible = "qcom,ufs-phy-qmp-v3-660"}, + {}, +}; +MODULE_DEVICE_TABLE(of, ufs_qcom_phy_qmp_v3_660_of_match); + +static struct platform_driver ufs_qcom_phy_qmp_v3_660_driver = { + .probe = ufs_qcom_phy_qmp_v3_660_probe, + .driver = { + .of_match_table = ufs_qcom_phy_qmp_v3_660_of_match, + .name = "ufs_qcom_phy_qmp_v3_660", + }, +}; + +module_platform_driver(ufs_qcom_phy_qmp_v3_660_driver); + +MODULE_DESCRIPTION("Universal Flash Storage (UFS) QCOM PHY QMP v3 660"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/phy/qualcomm/phy-qcom-ufs-qmp-v3-660.h b/drivers/phy/qualcomm/phy-qcom-ufs-qmp-v3-660.h new file mode 100644 index 000000000000..2b9586d758e2 --- /dev/null +++ b/drivers/phy/qualcomm/phy-qcom-ufs-qmp-v3-660.h @@ -0,0 +1,277 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2013-2016,2019-2021, The Linux Foundation. All rights reserved. + * Copyright (c) 2023, Qualcomm Innovation Center, Inc. All rights reserved. + */ + +#ifndef UFS_QCOM_PHY_QMP_V3_660_H_ +#define UFS_QCOM_PHY_QMP_V3_660_H_ + +#include "phy-qcom-ufs-i.h" + +/* QCOM UFS PHY control registers */ +#define COM_BASE 0x000 +#define COM_OFF(x) (COM_BASE + x) +#define COM_SIZE 0x1C0 + +#define TX_BASE 0x400 +#define TX_OFF(x) (TX_BASE + x) +#define TX_SIZE 0x128 + +#define RX_BASE 0x600 +#define RX_OFF(x) (RX_BASE + x) +#define RX_SIZE 0x1FC + +#define PHY_BASE 0xC00 +#define PHY_OFF(x) (PHY_BASE + x) +#define PHY_SIZE 0x1B4 + +/* UFS PHY QSERDES COM registers */ +#define QSERDES_COM_ATB_SEL1 COM_OFF(0x00) +#define QSERDES_COM_ATB_SEL2 COM_OFF(0x04) +#define QSERDES_COM_FREQ_UPDATE COM_OFF(0x08) +#define QSERDES_COM_BG_TIMER COM_OFF(0x0C) +#define QSERDES_COM_SSC_EN_CENTER COM_OFF(0x10) +#define QSERDES_COM_SSC_ADJ_PER1 COM_OFF(0x14) +#define QSERDES_COM_SSC_ADJ_PER2 COM_OFF(0x18) +#define QSERDES_COM_SSC_PER1 COM_OFF(0x1C) +#define QSERDES_COM_SSC_PER2 COM_OFF(0x20) +#define QSERDES_COM_SSC_STEP_SIZE1 COM_OFF(0x24) +#define QSERDES_COM_SSC_STEP_SIZE2 COM_OFF(0x28) +#define QSERDES_COM_POST_DIV COM_OFF(0x2C) +#define QSERDES_COM_POST_DIV_MUX COM_OFF(0x30) +#define QSERDES_COM_BIAS_EN_CLKBUFLR_EN COM_OFF(0x34) +#define QSERDES_COM_CLK_ENABLE1 COM_OFF(0x38) +#define QSERDES_COM_SYS_CLK_CTRL COM_OFF(0x3C) +#define QSERDES_COM_SYSCLK_BUF_ENABLE COM_OFF(0x40) +#define QSERDES_COM_PLL_EN COM_OFF(0x44) +#define QSERDES_COM_PLL_IVCO COM_OFF(0x48) +#define QSERDES_COM_LOCK_CMP1_MODE0 COM_OFF(0X4C) +#define QSERDES_COM_LOCK_CMP2_MODE0 COM_OFF(0X50) +#define QSERDES_COM_LOCK_CMP3_MODE0 COM_OFF(0X54) +#define QSERDES_COM_LOCK_CMP1_MODE1 COM_OFF(0X58) +#define QSERDES_COM_LOCK_CMP2_MODE1 COM_OFF(0X5C) +#define QSERDES_COM_LOCK_CMP3_MODE1 COM_OFF(0X60) +#define QSERDES_COM_CMD_RSVD0 COM_OFF(0x64) +#define QSERDES_COM_EP_CLOCK_DETECT_CTRL COM_OFF(0x68) +#define QSERDES_COM_SYSCLK_DET_COMP_STATUS COM_OFF(0x6C) +#define QSERDES_COM_BG_TRIM COM_OFF(0x70) +#define QSERDES_COM_CLK_EP_DIV COM_OFF(0x74) +#define QSERDES_COM_CP_CTRL_MODE0 COM_OFF(0x78) +#define QSERDES_COM_CP_CTRL_MODE1 COM_OFF(0x7C) +#define QSERDES_COM_CMN_RSVD1 COM_OFF(0x80) +#define QSERDES_COM_PLL_RCTRL_MODE0 COM_OFF(0x84) +#define QSERDES_COM_PLL_RCTRL_MODE1 COM_OFF(0x88) +#define QSERDES_COM_CMN_RSVD2 COM_OFF(0x8C) +#define QSERDES_COM_PLL_CCTRL_MODE0 COM_OFF(0x90) +#define QSERDES_COM_PLL_CCTRL_MODE1 COM_OFF(0x94) +#define QSERDES_COM_CMN_RSVD3 COM_OFF(0x98) +#define QSERDES_COM_PLL_CNTRL COM_OFF(0x9C) +#define QSERDES_COM_PHASE_SEL_CTRL COM_OFF(0xA0) +#define QSERDES_COM_PHASE_SEL_DC COM_OFF(0xA4) +#define QSERDES_COM_BIAS_EN_CTRL_BY_PSM COM_OFF(0xA8) +#define QSERDES_COM_SYSCLK_EN_SEL COM_OFF(0xAC) +#define QSERDES_COM_CML_SYSCLK_SEL COM_OFF(0xB0) +#define QSERDES_COM_RESETSM_CNTRL COM_OFF(0xB4) +#define QSERDES_COM_RESETSM_CNTRL2 COM_OFF(0xB8) +#define QSERDES_COM_RESTRIM_CTRL COM_OFF(0xBC) +#define QSERDES_COM_RESTRIM_CTRL2 COM_OFF(0xC0) +#define QSERDES_COM_LOCK_CMP_EN COM_OFF(0xC8) +#define QSERDES_COM_LOCK_CMP_CFG COM_OFF(0xCC) +#define QSERDES_COM_DEC_START_MODE0 COM_OFF(0xD0) +#define QSERDES_COM_DEC_START_MODE1 COM_OFF(0xD4) +#define QSERDES_COM_VCOCAL_DEADMAN_CTRL COM_OFF(0xD8) +#define QSERDES_COM_DIV_FRAC_START1_MODE0 COM_OFF(0xDC) +#define QSERDES_COM_DIV_FRAC_START2_MODE0 COM_OFF(0xE0) +#define QSERDES_COM_DIV_FRAC_START3_MODE0 COM_OFF(0xE4) +#define QSERDES_COM_DIV_FRAC_START1_MODE1 COM_OFF(0xE8) +#define QSERDES_COM_DIV_FRAC_START2_MODE1 COM_OFF(0xEC) +#define QSERDES_COM_DIV_FRAC_START3_MODE1 COM_OFF(0xF0) +#define QSERDES_COM_VCO_TUNE_MINVAL1 COM_OFF(0xF4) +#define QSERDES_COM_VCO_TUNE_MINVAL2 COM_OFF(0xF8) +#define QSERDES_COM_CMN_RSVD4 COM_OFF(0xFC) +#define QSERDES_COM_INTEGLOOP_INITVAL COM_OFF(0x100) +#define QSERDES_COM_INTEGLOOP_EN COM_OFF(0x104) +#define QSERDES_COM_INTEGLOOP_GAIN0_MODE0 COM_OFF(0x108) +#define QSERDES_COM_INTEGLOOP_GAIN1_MODE0 COM_OFF(0x10C) +#define QSERDES_COM_INTEGLOOP_GAIN0_MODE1 COM_OFF(0x110) +#define QSERDES_COM_INTEGLOOP_GAIN1_MODE1 COM_OFF(0x114) +#define QSERDES_COM_VCO_TUNE_MAXVAL1 COM_OFF(0x118) +#define QSERDES_COM_VCO_TUNE_MAXVAL2 COM_OFF(0x11C) +#define QSERDES_COM_RES_TRIM_CONTROL2 COM_OFF(0x120) +#define QSERDES_COM_VCO_TUNE_CTRL COM_OFF(0x124) +#define QSERDES_COM_VCO_TUNE_MAP COM_OFF(0x128) +#define QSERDES_COM_VCO_TUNE1_MODE0 COM_OFF(0x12C) +#define QSERDES_COM_VCO_TUNE2_MODE0 COM_OFF(0x130) +#define QSERDES_COM_VCO_TUNE1_MODE1 COM_OFF(0x134) +#define QSERDES_COM_VCO_TUNE2_MODE1 COM_OFF(0x138) +#define QSERDES_COM_VCO_TUNE_INITVAL1 COM_OFF(0x13C) +#define QSERDES_COM_VCO_TUNE_INITVAL2 COM_OFF(0x140) +#define QSERDES_COM_VCO_TUNE_TIMER1 COM_OFF(0x144) +#define QSERDES_COM_VCO_TUNE_TIMER2 COM_OFF(0x148) +#define QSERDES_COM_SAR COM_OFF(0x14C) +#define QSERDES_COM_SAR_CLK COM_OFF(0x150) +#define QSERDES_COM_SAR_CODE_OUT_STATUS COM_OFF(0x154) +#define QSERDES_COM_SAR_CODE_READY_STATUS COM_OFF(0x158) +#define QSERDES_COM_CMN_STATUS COM_OFF(0x15C) +#define QSERDES_COM_RESET_SM_STATUS COM_OFF(0x160) +#define QSERDES_COM_RESTRIM_CODE_STATUS COM_OFF(0x164) +#define QSERDES_COM_PLLCAL_CODE1_STATUS COM_OFF(0x168) +#define QSERDES_COM_PLLCAL_CODE2_STATUS COM_OFF(0x16C) +#define QSERDES_COM_BG_CTRL COM_OFF(0x170) +#define QSERDES_COM_CLK_SELECT COM_OFF(0x174) +#define QSERDES_COM_HSCLK_SEL COM_OFF(0x178) +#define QSERDES_COM_INTEGLOOP_BINCODE_STATUS COM_OFF(0x17C) +#define QSERDES_COM_PLL_ANALOG COM_OFF(0x180) +#define QSERDES_COM_CORECLK_DIV COM_OFF(0x184) +#define QSERDES_COM_SW_RESET COM_OFF(0x188) +#define QSERDES_COM_CORE_CLK_EN COM_OFF(0x18C) +#define QSERDES_COM_C_READY_STATUS COM_OFF(0x190) +#define QSERDES_COM_CMN_CONFIG COM_OFF(0x194) +#define QSERDES_COM_CMN_RATE_OVERRIDE COM_OFF(0x198) +#define QSERDES_COM_SVS_MODE_CLK_SEL COM_OFF(0x19C) +#define QSERDES_COM_DEBUG_BUS0 COM_OFF(0x1A0) +#define QSERDES_COM_DEBUG_BUS1 COM_OFF(0x1A4) +#define QSERDES_COM_DEBUG_BUS2 COM_OFF(0x1A8) +#define QSERDES_COM_DEBUG_BUS3 COM_OFF(0x1AC) +#define QSERDES_COM_DEBUG_BUS_SEL COM_OFF(0x1B0) +#define QSERDES_COM_CMN_MISC1 COM_OFF(0x1B4) +#define QSERDES_COM_CORECLK_DIV_MODE1 COM_OFF(0x1BC) +#define QSERDES_COM_CMN_RSVD5 COM_OFF(0x1C0) + +/* UFS PHY registers */ +#define UFS_PHY_PHY_START PHY_OFF(0x00) +#define UFS_PHY_POWER_DOWN_CONTROL PHY_OFF(0x04) +#define UFS_PHY_TX_LARGE_AMP_DRV_LVL PHY_OFF(0x34) +#define UFS_PHY_TX_SMALL_AMP_DRV_LVL PHY_OFF(0x3C) +#define UFS_PHY_RX_MIN_STALL_NOCONFIG_TIME_CAP PHY_OFF(0xCC) +#define UFS_PHY_LINECFG_DISABLE PHY_OFF(0x138) +#define UFS_PHY_RX_SYM_RESYNC_CTRL PHY_OFF(0x13C) +#define UFS_PHY_RX_MIN_HIBERN8_TIME PHY_OFF(0x140) +#define UFS_PHY_RX_SIGDET_CTRL2 PHY_OFF(0x148) +#define UFS_PHY_RX_PWM_GEAR_BAND PHY_OFF(0x154) +#define UFS_PHY_PCS_READY_STATUS PHY_OFF(0x168) + +/* UFS PHY TX registers */ +#define QSERDES_TX_HIGHZ_TRANSCEIVER_BIAS_DRVR_EN TX_OFF(0x68) +#define QSERDES_TX_LANE_MODE TX_OFF(0x94) + +/* UFS PHY RX registers */ +#define QSERDES_RX_UCDR_SVS_SO_GAIN_HALF RX_OFF(0x30) +#define QSERDES_RX_UCDR_SVS_SO_GAIN_QUARTER RX_OFF(0x34) +#define QSERDES_RX_UCDR_SVS_SO_GAIN_EIGHTH RX_OFF(0x38) +#define QSERDES_RX_UCDR_SVS_SO_GAIN RX_OFF(0x3C) +#define QSERDES_RX_UCDR_FASTLOCK_FO_GAIN RX_OFF(0x40) +#define QSERDES_RX_UCDR_SO_SATURATION_ENABLE RX_OFF(0x48) +#define QSERDES_RX_RX_TERM_BW RX_OFF(0x90) +#define QSERDES_RX_RX_EQ_GAIN1_LSB RX_OFF(0xC4) +#define QSERDES_RX_RX_EQ_GAIN1_MSB RX_OFF(0xC8) +#define QSERDES_RX_RX_EQ_GAIN2_LSB RX_OFF(0xCC) +#define QSERDES_RX_RX_EQ_GAIN2_MSB RX_OFF(0xD0) +#define QSERDES_RX_RX_EQU_ADAPTOR_CNTRL2 RX_OFF(0xD8) +#define QSERDES_RX_SIGDET_CNTRL RX_OFF(0x114) +#define QSERDES_RX_SIGDET_LVL RX_OFF(0x118) +#define QSERDES_RX_SIGDET_DEGLITCH_CNTRL RX_OFF(0x11C) +#define QSERDES_RX_RX_INTERFACE_MODE RX_OFF(0x12C) + + +#define UFS_PHY_RX_LINECFG_DISABLE_BIT BIT(1) + +/* + * This structure represents the v3 660 specific phy. + * common_cfg MUST remain the first field in this structure + * in case extra fields are added. This way, when calling + * get_ufs_qcom_phy() of generic phy, we can extract the + * common phy structure (struct ufs_qcom_phy) out of it + * regardless of the relevant specific phy. + */ +struct ufs_qcom_phy_qmp_v3_660 { + struct ufs_qcom_phy common_cfg; +}; + +static struct ufs_qcom_phy_calibration phy_cal_table_rate_A_3_1_1[] = { + UFS_QCOM_PHY_CAL_ENTRY(UFS_PHY_POWER_DOWN_CONTROL, 0x01), + UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_CMN_CONFIG, 0x0e), + UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_SYSCLK_EN_SEL, 0x14), + UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_CLK_SELECT, 0x30), + UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_SYS_CLK_CTRL, 0x02), + UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_BIAS_EN_CLKBUFLR_EN, 0x08), + UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_BG_TIMER, 0x0a), + UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_HSCLK_SEL, 0x00), + UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_CORECLK_DIV, 0x0a), + UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_CORECLK_DIV_MODE1, 0x0a), + UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_LOCK_CMP_EN, 0x01), + UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_VCO_TUNE_CTRL, 0x00), + UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_RESETSM_CNTRL, 0x20), + UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_CORE_CLK_EN, 0x00), + UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_LOCK_CMP_CFG, 0x00), + UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_VCO_TUNE_TIMER1, 0xff), + UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_VCO_TUNE_TIMER2, 0x3f), + UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_VCO_TUNE_MAP, 0x04), + UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_SVS_MODE_CLK_SEL, 0x05), + UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_DEC_START_MODE0, 0x82), + UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_DIV_FRAC_START1_MODE0, 0x00), + UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_DIV_FRAC_START2_MODE0, 0x00), + UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_DIV_FRAC_START3_MODE0, 0x00), + UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_CP_CTRL_MODE0, 0x0b), + UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_PLL_RCTRL_MODE0, 0x16), + UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_PLL_CCTRL_MODE0, 0x28), + UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_INTEGLOOP_GAIN0_MODE0, 0x80), + UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_INTEGLOOP_GAIN1_MODE0, 0x00), + UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_VCO_TUNE1_MODE0, 0x28), + UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_VCO_TUNE2_MODE0, 0x02), + UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_LOCK_CMP1_MODE0, 0xff), + UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_LOCK_CMP2_MODE0, 0x0c), + UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_LOCK_CMP3_MODE0, 0x00), + UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_DEC_START_MODE1, 0x98), + UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_DIV_FRAC_START1_MODE1, 0x00), + UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_DIV_FRAC_START2_MODE1, 0x00), + UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_DIV_FRAC_START3_MODE1, 0x00), + UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_CP_CTRL_MODE1, 0x0b), + UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_PLL_RCTRL_MODE1, 0x16), + UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_PLL_CCTRL_MODE1, 0x28), + UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_INTEGLOOP_GAIN0_MODE1, 0x80), + UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_INTEGLOOP_GAIN1_MODE1, 0x00), + UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_VCO_TUNE1_MODE1, 0xd6), + UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_VCO_TUNE2_MODE1, 0x00), + UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_LOCK_CMP1_MODE1, 0x32), + UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_LOCK_CMP2_MODE1, 0x0f), + UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_LOCK_CMP3_MODE1, 0x00), + + UFS_QCOM_PHY_CAL_ENTRY(QSERDES_TX_HIGHZ_TRANSCEIVER_BIAS_DRVR_EN, 0x45), + UFS_QCOM_PHY_CAL_ENTRY(QSERDES_TX_LANE_MODE, 0x06), + + UFS_QCOM_PHY_CAL_ENTRY(QSERDES_RX_SIGDET_LVL, 0x24), + UFS_QCOM_PHY_CAL_ENTRY(QSERDES_RX_SIGDET_CNTRL, 0x0F), + UFS_QCOM_PHY_CAL_ENTRY(QSERDES_RX_RX_INTERFACE_MODE, 0x40), + UFS_QCOM_PHY_CAL_ENTRY(QSERDES_RX_SIGDET_DEGLITCH_CNTRL, 0x1E), + UFS_QCOM_PHY_CAL_ENTRY(QSERDES_RX_UCDR_FASTLOCK_FO_GAIN, 0x0B), + UFS_QCOM_PHY_CAL_ENTRY(QSERDES_RX_RX_TERM_BW, 0x5B), + UFS_QCOM_PHY_CAL_ENTRY(QSERDES_RX_RX_EQ_GAIN1_LSB, 0xFF), + UFS_QCOM_PHY_CAL_ENTRY(QSERDES_RX_RX_EQ_GAIN1_MSB, 0x3F), + UFS_QCOM_PHY_CAL_ENTRY(QSERDES_RX_RX_EQ_GAIN2_LSB, 0xFF), + UFS_QCOM_PHY_CAL_ENTRY(QSERDES_RX_RX_EQ_GAIN2_MSB, 0x3F), + UFS_QCOM_PHY_CAL_ENTRY(QSERDES_RX_RX_EQU_ADAPTOR_CNTRL2, 0x0D), + + UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_PLL_IVCO, 0x0F), + UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_BG_TRIM, 0x0F), + UFS_QCOM_PHY_CAL_ENTRY(UFS_PHY_RX_PWM_GEAR_BAND, 0x15), + UFS_QCOM_PHY_CAL_ENTRY(QSERDES_RX_UCDR_SVS_SO_GAIN_HALF, 0x04), + UFS_QCOM_PHY_CAL_ENTRY(QSERDES_RX_UCDR_SVS_SO_GAIN_QUARTER, 0x04), + UFS_QCOM_PHY_CAL_ENTRY(QSERDES_RX_UCDR_SVS_SO_GAIN, 0x04), + UFS_QCOM_PHY_CAL_ENTRY(QSERDES_RX_UCDR_SO_SATURATION_ENABLE, 0x4B), + UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_VCO_TUNE_INITVAL1, 0xFF), + UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_VCO_TUNE_INITVAL2, 0x00), + UFS_QCOM_PHY_CAL_ENTRY(UFS_PHY_RX_SIGDET_CTRL2, 0x6c), + UFS_QCOM_PHY_CAL_ENTRY(UFS_PHY_TX_LARGE_AMP_DRV_LVL, 0x0A), + UFS_QCOM_PHY_CAL_ENTRY(UFS_PHY_TX_SMALL_AMP_DRV_LVL, 0x02), + UFS_QCOM_PHY_CAL_ENTRY(UFS_PHY_RX_MIN_STALL_NOCONFIG_TIME_CAP, 0x28), + UFS_QCOM_PHY_CAL_ENTRY(UFS_PHY_RX_SYM_RESYNC_CTRL, 0x03), + UFS_QCOM_PHY_CAL_ENTRY(UFS_PHY_RX_MIN_HIBERN8_TIME, 0x9A), /* 8 us */ +}; + +static struct ufs_qcom_phy_calibration phy_cal_table_rate_B[] = { + UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_VCO_TUNE_MAP, 0x44), +}; + +#endif diff --git a/drivers/phy/tegra/xusb.c b/drivers/phy/tegra/xusb.c index 71271af39ad6..119e2c039225 100644 --- a/drivers/phy/tegra/xusb.c +++ b/drivers/phy/tegra/xusb.c @@ -562,6 +562,7 @@ static void tegra_xusb_port_unregister(struct tegra_xusb_port *port) usb_role_switch_unregister(port->usb_role_sw); cancel_work_sync(&port->usb_phy_work); usb_remove_phy(&port->usb_phy); + port->usb_phy.dev->driver = NULL; } if (port->ops->remove) @@ -668,6 +669,9 @@ static int tegra_xusb_setup_usb_role_switch(struct tegra_xusb_port *port) port->dev.driver = devm_kzalloc(&port->dev, sizeof(struct device_driver), GFP_KERNEL); + if (!port->dev.driver) + return -ENOMEM; + port->dev.driver->owner = THIS_MODULE; port->usb_role_sw = usb_role_switch_register(&port->dev, diff --git a/drivers/pinctrl/intel/pinctrl-cherryview.c b/drivers/pinctrl/intel/pinctrl-cherryview.c index 980099028cf8..34f0ec784dbe 100644 --- a/drivers/pinctrl/intel/pinctrl-cherryview.c +++ b/drivers/pinctrl/intel/pinctrl-cherryview.c @@ -945,11 +945,6 @@ static int chv_config_get(struct pinctrl_dev *pctldev, unsigned int pin, break; - case PIN_CONFIG_DRIVE_OPEN_DRAIN: - if (!(ctrl1 & CHV_PADCTRL1_ODEN)) - return -EINVAL; - break; - case PIN_CONFIG_BIAS_HIGH_IMPEDANCE: { u32 cfg; @@ -959,6 +954,16 @@ static int chv_config_get(struct pinctrl_dev *pctldev, unsigned int pin, return -EINVAL; break; + + case PIN_CONFIG_DRIVE_PUSH_PULL: + if (ctrl1 & CHV_PADCTRL1_ODEN) + return -EINVAL; + break; + + case PIN_CONFIG_DRIVE_OPEN_DRAIN: + if (!(ctrl1 & CHV_PADCTRL1_ODEN)) + return -EINVAL; + break; } default: diff --git a/drivers/pinctrl/pinctrl-amd.c b/drivers/pinctrl/pinctrl-amd.c index 52d1fe5ec3e7..384d93146e1f 100644 --- a/drivers/pinctrl/pinctrl-amd.c +++ b/drivers/pinctrl/pinctrl-amd.c @@ -126,6 +126,14 @@ static int amd_gpio_set_debounce(struct gpio_chip *gc, unsigned offset, struct amd_gpio *gpio_dev = gpiochip_get_data(gc); raw_spin_lock_irqsave(&gpio_dev->lock, flags); + + /* Use special handling for Pin0 debounce */ + if (offset == 0) { + pin_reg = readl(gpio_dev->base + WAKE_INT_MASTER_REG); + if (pin_reg & INTERNAL_GPIO0_DEBOUNCE) + debounce = 0; + } + pin_reg = readl(gpio_dev->base + offset * 4); if (debounce) { @@ -181,18 +189,6 @@ static int amd_gpio_set_debounce(struct gpio_chip *gc, unsigned offset, return ret; } -static int amd_gpio_set_config(struct gpio_chip *gc, unsigned offset, - unsigned long config) -{ - u32 debounce; - - if (pinconf_to_config_param(config) != PIN_CONFIG_INPUT_DEBOUNCE) - return -ENOTSUPP; - - debounce = pinconf_to_config_argument(config); - return amd_gpio_set_debounce(gc, offset, debounce); -} - #ifdef CONFIG_DEBUG_FS static void amd_gpio_dbg_show(struct seq_file *s, struct gpio_chip *gc) { @@ -223,6 +219,7 @@ static void amd_gpio_dbg_show(struct seq_file *s, struct gpio_chip *gc) char debounce_value[40]; char *debounce_enable; + seq_printf(s, "WAKE_INT_MASTER_REG: 0x%08x\n", readl(gpio_dev->base + WAKE_INT_MASTER_REG)); for (bank = 0; bank < gpio_dev->hwbank_num; bank++) { seq_printf(s, "GPIO bank%d\t", bank); @@ -646,21 +643,21 @@ static bool do_amd_gpio_irq_handler(int irq, void *dev_id) * We must read the pin register again, in case the * value was changed while executing * generic_handle_domain_irq() above. - * If we didn't find a mapping for the interrupt, - * disable it in order to avoid a system hang caused - * by an interrupt storm. + * If the line is not an irq, disable it in order to + * avoid a system hang caused by an interrupt storm. */ raw_spin_lock_irqsave(&gpio_dev->lock, flags); regval = readl(regs + i); - if (irq == 0) { - regval &= ~BIT(INTERRUPT_ENABLE_OFF); + if (!gpiochip_line_is_irq(gc, irqnr + i)) { + regval &= ~BIT(INTERRUPT_MASK_OFF); dev_dbg(&gpio_dev->pdev->dev, "Disabling spurious GPIO IRQ %d\n", irqnr + i); + } else { + ret = true; } writel(regval, regs + i); raw_spin_unlock_irqrestore(&gpio_dev->lock, flags); - ret = true; } } /* did not cause wake on resume context for shared IRQ */ @@ -766,7 +763,7 @@ static int amd_pinconf_get(struct pinctrl_dev *pctldev, } static int amd_pinconf_set(struct pinctrl_dev *pctldev, unsigned int pin, - unsigned long *configs, unsigned num_configs) + unsigned long *configs, unsigned int num_configs) { int i; u32 arg; @@ -856,6 +853,20 @@ static int amd_pinconf_group_set(struct pinctrl_dev *pctldev, return 0; } +static int amd_gpio_set_config(struct gpio_chip *gc, unsigned int pin, + unsigned long config) +{ + struct amd_gpio *gpio_dev = gpiochip_get_data(gc); + + if (pinconf_to_config_param(config) == PIN_CONFIG_INPUT_DEBOUNCE) { + u32 debounce = pinconf_to_config_argument(config); + + return amd_gpio_set_debounce(gc, pin, debounce); + } + + return amd_pinconf_set(gpio_dev->pctrl, pin, &config, 1); +} + static const struct pinconf_ops amd_pinconf_ops = { .pin_config_get = amd_pinconf_get, .pin_config_set = amd_pinconf_set, @@ -883,9 +894,9 @@ static void amd_gpio_irq_init(struct amd_gpio *gpio_dev) raw_spin_lock_irqsave(&gpio_dev->lock, flags); - pin_reg = readl(gpio_dev->base + i * 4); + pin_reg = readl(gpio_dev->base + pin * 4); pin_reg &= ~mask; - writel(pin_reg, gpio_dev->base + i * 4); + writel(pin_reg, gpio_dev->base + pin * 4); raw_spin_unlock_irqrestore(&gpio_dev->lock, flags); } diff --git a/drivers/pinctrl/pinctrl-amd.h b/drivers/pinctrl/pinctrl-amd.h index 1d4317073654..04ae23c46152 100644 --- a/drivers/pinctrl/pinctrl-amd.h +++ b/drivers/pinctrl/pinctrl-amd.h @@ -17,6 +17,7 @@ #define AMD_GPIO_PINS_BANK3 32 #define WAKE_INT_MASTER_REG 0xfc +#define INTERNAL_GPIO0_DEBOUNCE (1 << 15) #define EOI_MASK (1 << 29) #define WAKE_INT_STATUS_REG0 0x2f8 diff --git a/drivers/pinctrl/pinctrl-at91-pio4.c b/drivers/pinctrl/pinctrl-at91-pio4.c index e31f5d9febe9..62b9a94c10ba 100644 --- a/drivers/pinctrl/pinctrl-at91-pio4.c +++ b/drivers/pinctrl/pinctrl-at91-pio4.c @@ -1128,6 +1128,8 @@ static int atmel_pinctrl_probe(struct platform_device *pdev) /* Pin naming convention: P(bank_name)(bank_pin_number). */ pin_desc[i].name = devm_kasprintf(&pdev->dev, GFP_KERNEL, "P%c%d", bank + 'A', line); + if (!pin_desc[i].name) + return -ENOMEM; group->name = group_names[i] = pin_desc[i].name; group->pin = pin_desc[i].number; diff --git a/drivers/pinctrl/pinctrl-microchip-sgpio.c b/drivers/pinctrl/pinctrl-microchip-sgpio.c index dfa374195694..aceadc9ec024 100644 --- a/drivers/pinctrl/pinctrl-microchip-sgpio.c +++ b/drivers/pinctrl/pinctrl-microchip-sgpio.c @@ -729,6 +729,9 @@ static int microchip_sgpio_register_bank(struct device *dev, pctl_desc->name = devm_kasprintf(dev, GFP_KERNEL, "%s-%sput", dev_name(dev), bank->is_input ? "in" : "out"); + if (!pctl_desc->name) + return -ENOMEM; + pctl_desc->pctlops = &sgpio_pctl_ops; pctl_desc->pmxops = &sgpio_pmx_ops; pctl_desc->confops = &sgpio_confops; diff --git a/drivers/pinctrl/qcom/Kconfig b/drivers/pinctrl/qcom/Kconfig index 4e8e6f922484..d770b866583c 100644 --- a/drivers/pinctrl/qcom/Kconfig +++ b/drivers/pinctrl/qcom/Kconfig @@ -326,6 +326,17 @@ config PINCTRL_SDM660 Qualcomm Technologies Inc TLMM block found on the Qualcomm Technologies Inc SDM660 platform. +config PINCTRL_SDM670 + tristate "Qualcomm Technologies Inc SDM670 pin controller driver" + depends on GPIOLIB && OF + select PINCTRL_MSM + help + This is the pinctrl, pinmux, pinconf and gpiolib driver for the + Qualcomm Technologies Inc TLMM block found on the Qualcomm + Technologies Inc SDM670 platform. + Say Y here to compile statically, or M here to compile it as a module. + If unsure, say N. + config PINCTRL_SDM845 tristate "Qualcomm Technologies Inc SDM845 pin controller driver" depends on (OF || ACPI) diff --git a/drivers/pinctrl/qcom/Makefile b/drivers/pinctrl/qcom/Makefile index 6f0e654bf973..d7571d3c4bac 100644 --- a/drivers/pinctrl/qcom/Makefile +++ b/drivers/pinctrl/qcom/Makefile @@ -57,3 +57,4 @@ obj-$(CONFIG_PINCTRL_LEMANS) += pinctrl-lemans.o obj-$(CONFIG_PINCTRL_DIREWOLF) += pinctrl-direwolf.o obj-$(CONFIG_PINCTRL_MONACO_AUTO) += pinctrl-monaco_auto.o obj-$(CONFIG_PINCTRL_TRINKET) += pinctrl-trinket.o +obj-$(CONFIG_PINCTRL_SDM670) += pinctrl-sdm670.o diff --git a/drivers/pinctrl/qcom/pinctrl-direwolf.c b/drivers/pinctrl/qcom/pinctrl-direwolf.c index 32a9cd76405e..82c486089104 100644 --- a/drivers/pinctrl/qcom/pinctrl-direwolf.c +++ b/drivers/pinctrl/qcom/pinctrl-direwolf.c @@ -2295,7 +2295,7 @@ static struct msm_dir_conn direwolf_dir_conn[] = { {-1, 0}, {-1, 0}, {-1, 0}, {-1, 0} }; -static const struct msm_pinctrl_soc_data direwolf_pinctrl = { +static struct msm_pinctrl_soc_data direwolf_pinctrl = { .pins = direwolf_pins, .npins = ARRAY_SIZE(direwolf_pins), .functions = direwolf_functions, @@ -2306,6 +2306,42 @@ static const struct msm_pinctrl_soc_data direwolf_pinctrl = { .dir_conn = direwolf_dir_conn, }; +static int direwolf_pinctrl_gpio_irq_map_probe(struct platform_device *pdev) +{ + int ret, n, gpio_irq_map_count; + struct device_node *np = pdev->dev.of_node; + struct msm_gpio_wakeirq_map *gpio_irq_map; + + n = of_property_count_elems_of_size(np, "qcom,gpio-irq-map", + sizeof(u32)); + if (n <= 0 || n % 2) + return -EINVAL; + + gpio_irq_map_count = n / 2; + gpio_irq_map = devm_kcalloc(&pdev->dev, gpio_irq_map_count, + sizeof(*gpio_irq_map), GFP_KERNEL); + if (!gpio_irq_map) + return -ENOMEM; + + for (n = 0; n < gpio_irq_map_count; n++) { + ret = of_property_read_u32_index(np, "qcom,gpio-irq-map", + n * 2 + 0, + &gpio_irq_map[n].gpio); + if (ret) + return ret; + ret = of_property_read_u32_index(np, "qcom,gpio-irq-map", + n * 2 + 1, + &gpio_irq_map[n].wakeirq); + if (ret) + return ret; + } + + direwolf_pinctrl.wakeirq_map = gpio_irq_map; + direwolf_pinctrl.nwakeirq_map = gpio_irq_map_count; + + return 0; +} + static int direwolf_pinctrl_dirconn_list_probe(struct platform_device *pdev) { int ret, n, dirconn_list_count, m; @@ -2341,6 +2377,15 @@ static int direwolf_pinctrl_probe(struct platform_device *pdev) { int len, ret; + if (of_find_property(pdev->dev.of_node, "qcom,gpio-irq-map", &len)) { + ret = direwolf_pinctrl_gpio_irq_map_probe(pdev); + if (ret) { + dev_err(&pdev->dev, + "Unable to parse GPIO IRQ map\n"); + return ret; + } + } + if (of_find_property(pdev->dev.of_node, "qcom,dirconn-list", &len)) { ret = direwolf_pinctrl_dirconn_list_probe(pdev); if (ret) { diff --git a/drivers/pinctrl/qcom/pinctrl-msm.c b/drivers/pinctrl/qcom/pinctrl-msm.c index eb1cb1de1144..1ac89e0a102e 100644 --- a/drivers/pinctrl/qcom/pinctrl-msm.c +++ b/drivers/pinctrl/qcom/pinctrl-msm.c @@ -1800,9 +1800,11 @@ static int msm_pinctrl_hibernation_suspend(void) msm_readl_ctl(pctrl, pgroup); pctrl->gpio_regs[i].io_reg = msm_readl_io(pctrl, pgroup); - pctrl->gpio_regs[i].intr_cfg_reg = + if (pgroup->intr_cfg_reg) + pctrl->gpio_regs[i].intr_cfg_reg = msm_readl_intr_cfg(pctrl, pgroup); - pctrl->gpio_regs[i].intr_status_reg = + if (pgroup->intr_status_reg) + pctrl->gpio_regs[i].intr_status_reg = msm_readl_intr_status(pctrl, pgroup); } @@ -1845,9 +1847,11 @@ static void msm_pinctrl_hibernation_resume(void) pgroup = &soc->groups[i]; msm_writel_ctl(pctrl->gpio_regs[i].ctl_reg, pctrl, pgroup); msm_writel_io(pctrl->gpio_regs[i].io_reg, pctrl, pgroup); - msm_writel_intr_cfg(pctrl->gpio_regs[i].intr_cfg_reg, - pctrl, pgroup); - msm_writel_intr_status(pctrl->gpio_regs[i].intr_status_reg, + if (pgroup->intr_cfg_reg) + msm_writel_intr_cfg(pctrl->gpio_regs[i].intr_cfg_reg, + pctrl, pgroup); + if (pgroup->intr_status_reg) + msm_writel_intr_status(pctrl->gpio_regs[i].intr_status_reg, pctrl, pgroup); } diff --git a/drivers/pinctrl/qcom/pinctrl-sdm670.c b/drivers/pinctrl/qcom/pinctrl-sdm670.c new file mode 100644 index 000000000000..2116a2ce27c4 --- /dev/null +++ b/drivers/pinctrl/qcom/pinctrl-sdm670.c @@ -0,0 +1,1707 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. + * Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved. + */ +#include +#include +#include +#include + +#include "pinctrl-msm.h" + +#define FUNCTION(fname) \ + [msm_mux_##fname] = { \ + .name = #fname, \ + .groups = fname##_groups, \ + .ngroups = ARRAY_SIZE(fname##_groups), \ + } + +#define NORTH 0x00500000 +#define SOUTH 0x00900000 +#define WEST 0x00100000 + +#define DUMMY 0x0 +#define REG_SIZE 0x1000 +#define PINGROUP(id, base, f1, f2, f3, f4, f5, f6, f7, f8, f9) \ + { \ + .name = "gpio" #id, \ + .pins = gpio##id##_pins, \ + .npins = (unsigned int)ARRAY_SIZE(gpio##id##_pins), \ + .funcs = (int[]){ \ + msm_mux_gpio, /* gpio mode */ \ + msm_mux_##f1, \ + msm_mux_##f2, \ + msm_mux_##f3, \ + msm_mux_##f4, \ + msm_mux_##f5, \ + msm_mux_##f6, \ + msm_mux_##f7, \ + msm_mux_##f8, \ + msm_mux_##f9 \ + }, \ + .nfuncs = 10, \ + .ctl_reg = base + REG_SIZE * id, \ + .io_reg = base + 0x4 + REG_SIZE * id, \ + .intr_cfg_reg = base + 0x8 + REG_SIZE * id, \ + .intr_status_reg = base + 0xc + REG_SIZE * id, \ + .intr_target_reg = base + 0x8 + REG_SIZE * id, \ + .dir_conn_reg = (base == NORTH) ? base + 0xa3000 : \ + ((base == SOUTH) ? base + 0xa6000 : base + 0xa4000), \ + .mux_bit = 2, \ + .pull_bit = 0, \ + .drv_bit = 6, \ + .oe_bit = 9, \ + .in_bit = 0, \ + .out_bit = 1, \ + .intr_enable_bit = 0, \ + .intr_status_bit = 0, \ + .intr_target_bit = 5, \ + .intr_target_kpss_val = 3, \ + .intr_raw_status_bit = 4, \ + .intr_polarity_bit = 1, \ + .intr_detection_bit = 2, \ + .intr_detection_width = 2, \ + .dir_conn_en_bit = 8, \ + } + +#define SDC_QDSD_PINGROUP(pg_name, ctl, pull, drv) \ + { \ + .name = #pg_name, \ + .pins = pg_name##_pins, \ + .npins = (unsigned int)ARRAY_SIZE(pg_name##_pins), \ + .ctl_reg = ctl, \ + .io_reg = 0, \ + .intr_cfg_reg = 0, \ + .intr_status_reg = 0, \ + .intr_target_reg = 0, \ + .mux_bit = -1, \ + .pull_bit = pull, \ + .drv_bit = drv, \ + .oe_bit = -1, \ + .in_bit = -1, \ + .out_bit = -1, \ + .intr_enable_bit = -1, \ + .intr_status_bit = -1, \ + .intr_target_bit = -1, \ + .intr_raw_status_bit = -1, \ + .intr_polarity_bit = -1, \ + .intr_detection_bit = -1, \ + .intr_detection_width = -1, \ + } + +#define UFS_RESET(pg_name, offset) \ + { \ + .name = #pg_name, \ + .pins = pg_name##_pins, \ + .npins = (unsigned int)ARRAY_SIZE(pg_name##_pins), \ + .ctl_reg = offset, \ + .io_reg = offset + 0x4, \ + .intr_cfg_reg = 0, \ + .intr_status_reg = 0, \ + .intr_target_reg = 0, \ + .mux_bit = -1, \ + .pull_bit = 3, \ + .drv_bit = 0, \ + .oe_bit = -1, \ + .in_bit = -1, \ + .out_bit = 0, \ + .intr_enable_bit = -1, \ + .intr_status_bit = -1, \ + .intr_target_bit = -1, \ + .intr_raw_status_bit = -1, \ + .intr_polarity_bit = -1, \ + .intr_detection_bit = -1, \ + .intr_detection_width = -1, \ + } +static const struct pinctrl_pin_desc sdm670_pins[] = { + PINCTRL_PIN(0, "GPIO_0"), + PINCTRL_PIN(1, "GPIO_1"), + PINCTRL_PIN(2, "GPIO_2"), + PINCTRL_PIN(3, "GPIO_3"), + PINCTRL_PIN(4, "GPIO_4"), + PINCTRL_PIN(5, "GPIO_5"), + PINCTRL_PIN(6, "GPIO_6"), + PINCTRL_PIN(7, "GPIO_7"), + PINCTRL_PIN(8, "GPIO_8"), + PINCTRL_PIN(9, "GPIO_9"), + PINCTRL_PIN(10, "GPIO_10"), + PINCTRL_PIN(11, "GPIO_11"), + PINCTRL_PIN(12, "GPIO_12"), + PINCTRL_PIN(13, "GPIO_13"), + PINCTRL_PIN(14, "GPIO_14"), + PINCTRL_PIN(15, "GPIO_15"), + PINCTRL_PIN(16, "GPIO_16"), + PINCTRL_PIN(17, "GPIO_17"), + PINCTRL_PIN(18, "GPIO_18"), + PINCTRL_PIN(19, "GPIO_19"), + PINCTRL_PIN(20, "GPIO_20"), + PINCTRL_PIN(21, "GPIO_21"), + PINCTRL_PIN(22, "GPIO_22"), + PINCTRL_PIN(23, "GPIO_23"), + PINCTRL_PIN(24, "GPIO_24"), + PINCTRL_PIN(25, "GPIO_25"), + PINCTRL_PIN(26, "GPIO_26"), + PINCTRL_PIN(27, "GPIO_27"), + PINCTRL_PIN(28, "GPIO_28"), + PINCTRL_PIN(29, "GPIO_29"), + PINCTRL_PIN(30, "GPIO_30"), + PINCTRL_PIN(31, "GPIO_31"), + PINCTRL_PIN(32, "GPIO_32"), + PINCTRL_PIN(33, "GPIO_33"), + PINCTRL_PIN(34, "GPIO_34"), + PINCTRL_PIN(35, "GPIO_35"), + PINCTRL_PIN(36, "GPIO_36"), + PINCTRL_PIN(37, "GPIO_37"), + PINCTRL_PIN(38, "GPIO_38"), + PINCTRL_PIN(39, "GPIO_39"), + PINCTRL_PIN(40, "GPIO_40"), + PINCTRL_PIN(41, "GPIO_41"), + PINCTRL_PIN(42, "GPIO_42"), + PINCTRL_PIN(43, "GPIO_43"), + PINCTRL_PIN(44, "GPIO_44"), + PINCTRL_PIN(45, "GPIO_45"), + PINCTRL_PIN(46, "GPIO_46"), + PINCTRL_PIN(47, "GPIO_47"), + PINCTRL_PIN(48, "GPIO_48"), + PINCTRL_PIN(49, "GPIO_49"), + PINCTRL_PIN(50, "GPIO_50"), + PINCTRL_PIN(51, "GPIO_51"), + PINCTRL_PIN(52, "GPIO_52"), + PINCTRL_PIN(53, "GPIO_53"), + PINCTRL_PIN(54, "GPIO_54"), + PINCTRL_PIN(55, "GPIO_55"), + PINCTRL_PIN(56, "GPIO_56"), + PINCTRL_PIN(57, "GPIO_57"), + PINCTRL_PIN(65, "GPIO_65"), + PINCTRL_PIN(66, "GPIO_66"), + PINCTRL_PIN(67, "GPIO_67"), + PINCTRL_PIN(68, "GPIO_68"), + PINCTRL_PIN(75, "GPIO_75"), + PINCTRL_PIN(76, "GPIO_76"), + PINCTRL_PIN(77, "GPIO_77"), + PINCTRL_PIN(78, "GPIO_78"), + PINCTRL_PIN(79, "GPIO_79"), + PINCTRL_PIN(80, "GPIO_80"), + PINCTRL_PIN(81, "GPIO_81"), + PINCTRL_PIN(82, "GPIO_82"), + PINCTRL_PIN(83, "GPIO_83"), + PINCTRL_PIN(84, "GPIO_84"), + PINCTRL_PIN(85, "GPIO_85"), + PINCTRL_PIN(86, "GPIO_86"), + PINCTRL_PIN(87, "GPIO_87"), + PINCTRL_PIN(88, "GPIO_88"), + PINCTRL_PIN(89, "GPIO_89"), + PINCTRL_PIN(90, "GPIO_90"), + PINCTRL_PIN(91, "GPIO_91"), + PINCTRL_PIN(92, "GPIO_92"), + PINCTRL_PIN(93, "GPIO_93"), + PINCTRL_PIN(94, "GPIO_94"), + PINCTRL_PIN(95, "GPIO_95"), + PINCTRL_PIN(96, "GPIO_96"), + PINCTRL_PIN(97, "GPIO_97"), + PINCTRL_PIN(98, "GPIO_98"), + PINCTRL_PIN(99, "GPIO_99"), + PINCTRL_PIN(100, "GPIO_100"), + PINCTRL_PIN(101, "GPIO_101"), + PINCTRL_PIN(102, "GPIO_102"), + PINCTRL_PIN(103, "GPIO_103"), + PINCTRL_PIN(105, "GPIO_105"), + PINCTRL_PIN(106, "GPIO_106"), + PINCTRL_PIN(107, "GPIO_107"), + PINCTRL_PIN(108, "GPIO_108"), + PINCTRL_PIN(109, "GPIO_109"), + PINCTRL_PIN(110, "GPIO_110"), + PINCTRL_PIN(111, "GPIO_111"), + PINCTRL_PIN(112, "GPIO_112"), + PINCTRL_PIN(113, "GPIO_113"), + PINCTRL_PIN(114, "GPIO_114"), + PINCTRL_PIN(115, "GPIO_115"), + PINCTRL_PIN(116, "GPIO_116"), + PINCTRL_PIN(117, "GPIO_117"), + PINCTRL_PIN(118, "GPIO_118"), + PINCTRL_PIN(119, "GPIO_119"), + PINCTRL_PIN(120, "GPIO_120"), + PINCTRL_PIN(121, "GPIO_121"), + PINCTRL_PIN(122, "GPIO_122"), + PINCTRL_PIN(123, "GPIO_123"), + PINCTRL_PIN(124, "GPIO_124"), + PINCTRL_PIN(125, "GPIO_125"), + PINCTRL_PIN(126, "GPIO_126"), + PINCTRL_PIN(127, "GPIO_127"), + PINCTRL_PIN(128, "GPIO_128"), + PINCTRL_PIN(129, "GPIO_129"), + PINCTRL_PIN(130, "GPIO_130"), + PINCTRL_PIN(131, "GPIO_131"), + PINCTRL_PIN(132, "GPIO_132"), + PINCTRL_PIN(133, "GPIO_133"), + PINCTRL_PIN(134, "GPIO_134"), + PINCTRL_PIN(135, "GPIO_135"), + PINCTRL_PIN(136, "GPIO_136"), + PINCTRL_PIN(137, "GPIO_137"), + PINCTRL_PIN(138, "GPIO_138"), + PINCTRL_PIN(139, "GPIO_139"), + PINCTRL_PIN(140, "GPIO_140"), + PINCTRL_PIN(141, "GPIO_141"), + PINCTRL_PIN(142, "GPIO_142"), + PINCTRL_PIN(143, "GPIO_143"), + PINCTRL_PIN(144, "GPIO_144"), + PINCTRL_PIN(145, "GPIO_145"), + PINCTRL_PIN(146, "GPIO_146"), + PINCTRL_PIN(147, "GPIO_147"), + PINCTRL_PIN(148, "GPIO_148"), + PINCTRL_PIN(149, "GPIO_149"), + PINCTRL_PIN(150, "SDC1_RCLK"), + PINCTRL_PIN(151, "SDC1_CLK"), + PINCTRL_PIN(152, "SDC1_CMD"), + PINCTRL_PIN(153, "SDC1_DATA"), + PINCTRL_PIN(154, "SDC2_CLK"), + PINCTRL_PIN(155, "SDC2_CMD"), + PINCTRL_PIN(156, "SDC2_DATA"), + PINCTRL_PIN(157, "UFS_RESET"), +}; + +#define DECLARE_MSM_GPIO_PINS(pin) \ + static const unsigned int gpio##pin##_pins[] = { pin } +DECLARE_MSM_GPIO_PINS(0); +DECLARE_MSM_GPIO_PINS(1); +DECLARE_MSM_GPIO_PINS(2); +DECLARE_MSM_GPIO_PINS(3); +DECLARE_MSM_GPIO_PINS(4); +DECLARE_MSM_GPIO_PINS(5); +DECLARE_MSM_GPIO_PINS(6); +DECLARE_MSM_GPIO_PINS(7); +DECLARE_MSM_GPIO_PINS(8); +DECLARE_MSM_GPIO_PINS(9); +DECLARE_MSM_GPIO_PINS(10); +DECLARE_MSM_GPIO_PINS(11); +DECLARE_MSM_GPIO_PINS(12); +DECLARE_MSM_GPIO_PINS(13); +DECLARE_MSM_GPIO_PINS(14); +DECLARE_MSM_GPIO_PINS(15); +DECLARE_MSM_GPIO_PINS(16); +DECLARE_MSM_GPIO_PINS(17); +DECLARE_MSM_GPIO_PINS(18); +DECLARE_MSM_GPIO_PINS(19); +DECLARE_MSM_GPIO_PINS(20); +DECLARE_MSM_GPIO_PINS(21); +DECLARE_MSM_GPIO_PINS(22); +DECLARE_MSM_GPIO_PINS(23); +DECLARE_MSM_GPIO_PINS(24); +DECLARE_MSM_GPIO_PINS(25); +DECLARE_MSM_GPIO_PINS(26); +DECLARE_MSM_GPIO_PINS(27); +DECLARE_MSM_GPIO_PINS(28); +DECLARE_MSM_GPIO_PINS(29); +DECLARE_MSM_GPIO_PINS(30); +DECLARE_MSM_GPIO_PINS(31); +DECLARE_MSM_GPIO_PINS(32); +DECLARE_MSM_GPIO_PINS(33); +DECLARE_MSM_GPIO_PINS(34); +DECLARE_MSM_GPIO_PINS(35); +DECLARE_MSM_GPIO_PINS(36); +DECLARE_MSM_GPIO_PINS(37); +DECLARE_MSM_GPIO_PINS(38); +DECLARE_MSM_GPIO_PINS(39); +DECLARE_MSM_GPIO_PINS(40); +DECLARE_MSM_GPIO_PINS(41); +DECLARE_MSM_GPIO_PINS(42); +DECLARE_MSM_GPIO_PINS(43); +DECLARE_MSM_GPIO_PINS(44); +DECLARE_MSM_GPIO_PINS(45); +DECLARE_MSM_GPIO_PINS(46); +DECLARE_MSM_GPIO_PINS(47); +DECLARE_MSM_GPIO_PINS(48); +DECLARE_MSM_GPIO_PINS(49); +DECLARE_MSM_GPIO_PINS(50); +DECLARE_MSM_GPIO_PINS(51); +DECLARE_MSM_GPIO_PINS(52); +DECLARE_MSM_GPIO_PINS(53); +DECLARE_MSM_GPIO_PINS(54); +DECLARE_MSM_GPIO_PINS(55); +DECLARE_MSM_GPIO_PINS(56); +DECLARE_MSM_GPIO_PINS(57); +DECLARE_MSM_GPIO_PINS(58); +DECLARE_MSM_GPIO_PINS(59); +DECLARE_MSM_GPIO_PINS(60); +DECLARE_MSM_GPIO_PINS(61); +DECLARE_MSM_GPIO_PINS(62); +DECLARE_MSM_GPIO_PINS(63); +DECLARE_MSM_GPIO_PINS(64); +DECLARE_MSM_GPIO_PINS(65); +DECLARE_MSM_GPIO_PINS(66); +DECLARE_MSM_GPIO_PINS(67); +DECLARE_MSM_GPIO_PINS(68); +DECLARE_MSM_GPIO_PINS(69); +DECLARE_MSM_GPIO_PINS(70); +DECLARE_MSM_GPIO_PINS(71); +DECLARE_MSM_GPIO_PINS(72); +DECLARE_MSM_GPIO_PINS(73); +DECLARE_MSM_GPIO_PINS(74); +DECLARE_MSM_GPIO_PINS(75); +DECLARE_MSM_GPIO_PINS(76); +DECLARE_MSM_GPIO_PINS(77); +DECLARE_MSM_GPIO_PINS(78); +DECLARE_MSM_GPIO_PINS(79); +DECLARE_MSM_GPIO_PINS(80); +DECLARE_MSM_GPIO_PINS(81); +DECLARE_MSM_GPIO_PINS(82); +DECLARE_MSM_GPIO_PINS(83); +DECLARE_MSM_GPIO_PINS(84); +DECLARE_MSM_GPIO_PINS(85); +DECLARE_MSM_GPIO_PINS(86); +DECLARE_MSM_GPIO_PINS(87); +DECLARE_MSM_GPIO_PINS(88); +DECLARE_MSM_GPIO_PINS(89); +DECLARE_MSM_GPIO_PINS(90); +DECLARE_MSM_GPIO_PINS(91); +DECLARE_MSM_GPIO_PINS(92); +DECLARE_MSM_GPIO_PINS(93); +DECLARE_MSM_GPIO_PINS(94); +DECLARE_MSM_GPIO_PINS(95); +DECLARE_MSM_GPIO_PINS(96); +DECLARE_MSM_GPIO_PINS(97); +DECLARE_MSM_GPIO_PINS(98); +DECLARE_MSM_GPIO_PINS(99); +DECLARE_MSM_GPIO_PINS(100); +DECLARE_MSM_GPIO_PINS(101); +DECLARE_MSM_GPIO_PINS(102); +DECLARE_MSM_GPIO_PINS(103); +DECLARE_MSM_GPIO_PINS(104); +DECLARE_MSM_GPIO_PINS(105); +DECLARE_MSM_GPIO_PINS(106); +DECLARE_MSM_GPIO_PINS(107); +DECLARE_MSM_GPIO_PINS(108); +DECLARE_MSM_GPIO_PINS(109); +DECLARE_MSM_GPIO_PINS(110); +DECLARE_MSM_GPIO_PINS(111); +DECLARE_MSM_GPIO_PINS(112); +DECLARE_MSM_GPIO_PINS(113); +DECLARE_MSM_GPIO_PINS(114); +DECLARE_MSM_GPIO_PINS(115); +DECLARE_MSM_GPIO_PINS(116); +DECLARE_MSM_GPIO_PINS(117); +DECLARE_MSM_GPIO_PINS(118); +DECLARE_MSM_GPIO_PINS(119); +DECLARE_MSM_GPIO_PINS(120); +DECLARE_MSM_GPIO_PINS(121); +DECLARE_MSM_GPIO_PINS(122); +DECLARE_MSM_GPIO_PINS(123); +DECLARE_MSM_GPIO_PINS(124); +DECLARE_MSM_GPIO_PINS(125); +DECLARE_MSM_GPIO_PINS(126); +DECLARE_MSM_GPIO_PINS(127); +DECLARE_MSM_GPIO_PINS(128); +DECLARE_MSM_GPIO_PINS(129); +DECLARE_MSM_GPIO_PINS(130); +DECLARE_MSM_GPIO_PINS(131); +DECLARE_MSM_GPIO_PINS(132); +DECLARE_MSM_GPIO_PINS(133); +DECLARE_MSM_GPIO_PINS(134); +DECLARE_MSM_GPIO_PINS(135); +DECLARE_MSM_GPIO_PINS(136); +DECLARE_MSM_GPIO_PINS(137); +DECLARE_MSM_GPIO_PINS(138); +DECLARE_MSM_GPIO_PINS(139); +DECLARE_MSM_GPIO_PINS(140); +DECLARE_MSM_GPIO_PINS(141); +DECLARE_MSM_GPIO_PINS(142); +DECLARE_MSM_GPIO_PINS(143); +DECLARE_MSM_GPIO_PINS(144); +DECLARE_MSM_GPIO_PINS(145); +DECLARE_MSM_GPIO_PINS(146); +DECLARE_MSM_GPIO_PINS(147); +DECLARE_MSM_GPIO_PINS(148); +DECLARE_MSM_GPIO_PINS(149); + +static const unsigned int sdc1_rclk_pins[] = { 150 }; +static const unsigned int sdc1_clk_pins[] = { 151 }; +static const unsigned int sdc1_cmd_pins[] = { 152 }; +static const unsigned int sdc1_data_pins[] = { 153 }; +static const unsigned int sdc2_clk_pins[] = { 154 }; +static const unsigned int sdc2_cmd_pins[] = { 155 }; +static const unsigned int sdc2_data_pins[] = { 156 }; +static const unsigned int ufs_reset_pins[] = { 157 }; + +enum sdm670_functions { + msm_mux_qup0, + msm_mux_gpio, + msm_mux_qup9, + msm_mux_qdss_cti, + msm_mux_ddr_pxi0, + msm_mux_ddr_bist, + msm_mux_atest_tsens2, + msm_mux_vsense_trigger, + msm_mux_atest_usb1, + msm_mux_qup_l4, + msm_mux_GP_PDM1, + msm_mux_qup_l5, + msm_mux_mdp_vsync, + msm_mux_qup_l6, + msm_mux_wlan2_adc1, + msm_mux_atest_usb11, + msm_mux_ddr_pxi2, + msm_mux_edp_lcd, + msm_mux_dbg_out, + msm_mux_wlan2_adc0, + msm_mux_atest_usb10, + msm_mux_m_voc, + msm_mux_tsif1_sync, + msm_mux_ddr_pxi3, + msm_mux_cam_mclk, + msm_mux_pll_bypassnl, + msm_mux_qdss_gpio0, + msm_mux_pll_reset, + msm_mux_qdss_gpio1, + msm_mux_qdss_gpio2, + msm_mux_qdss_gpio3, + msm_mux_cci_i2c, + msm_mux_qup1, + msm_mux_qdss_gpio4, + msm_mux_qdss_gpio5, + msm_mux_qdss_gpio6, + msm_mux_qdss_gpio7, + msm_mux_cci_timer0, + msm_mux_gcc_gp2, + msm_mux_qdss_gpio8, + msm_mux_cci_timer1, + msm_mux_gcc_gp3, + msm_mux_qdss_gpio, + msm_mux_cci_timer2, + msm_mux_qdss_gpio9, + msm_mux_cci_timer3, + msm_mux_cci_async, + msm_mux_qdss_gpio10, + msm_mux_cci_timer4, + msm_mux_qdss_gpio11, + msm_mux_qdss_gpio12, + msm_mux_JITTER_BIST, + msm_mux_qup2, + msm_mux_qdss_gpio13, + msm_mux_PLL_BIST, + msm_mux_qdss_gpio14, + msm_mux_AGERA_PLL, + msm_mux_phase_flag1, + msm_mux_qdss_gpio15, + msm_mux_atest_tsens, + msm_mux_phase_flag2, + msm_mux_qup11, + msm_mux_qup14, + msm_mux_pci_e0, + msm_mux_QUP_L4, + msm_mux_QUP_L5, + msm_mux_QUP_L6, + msm_mux_usb_phy, + msm_mux_lpass_slimbus, + msm_mux_sd_write, + msm_mux_tsif1_error, + msm_mux_qup3, + msm_mux_qup6, + msm_mux_qup12, + msm_mux_phase_flag16, + msm_mux_qup10, + msm_mux_phase_flag11, + msm_mux_GP_PDM0, + msm_mux_phase_flag12, + msm_mux_wlan1_adc1, + msm_mux_atest_usb13, + msm_mux_ddr_pxi1, + msm_mux_phase_flag13, + msm_mux_wlan1_adc0, + msm_mux_atest_usb12, + msm_mux_phase_flag17, + msm_mux_qua_mi2s, + msm_mux_gcc_gp1, + msm_mux_phase_flag18, + msm_mux_pri_mi2s, + msm_mux_qup8, + msm_mux_wsa_clk, + msm_mux_pri_mi2s_ws, + msm_mux_wsa_data, + msm_mux_atest_usb2, + msm_mux_atest_usb23, + msm_mux_ter_mi2s, + msm_mux_phase_flag8, + msm_mux_atest_usb22, + msm_mux_phase_flag9, + msm_mux_atest_usb21, + msm_mux_phase_flag4, + msm_mux_atest_usb20, + msm_mux_sec_mi2s, + msm_mux_GP_PDM2, + msm_mux_qup15, + msm_mux_qup5, + msm_mux_copy_gp, + msm_mux_tsif1_clk, + msm_mux_qup4, + msm_mux_tgu_ch3, + msm_mux_phase_flag10, + msm_mux_tsif1_en, + msm_mux_mdp_vsync0, + msm_mux_mdp_vsync1, + msm_mux_mdp_vsync2, + msm_mux_mdp_vsync3, + msm_mux_tgu_ch0, + msm_mux_phase_flag0, + msm_mux_tsif1_data, + msm_mux_sdc4_cmd, + msm_mux_tgu_ch1, + msm_mux_tsif2_error, + msm_mux_sdc43, + msm_mux_vfr_1, + msm_mux_tgu_ch2, + msm_mux_tsif2_clk, + msm_mux_sdc4_clk, + msm_mux_qup7, + msm_mux_tsif2_en, + msm_mux_sdc42, + msm_mux_tsif2_data, + msm_mux_sdc41, + msm_mux_tsif2_sync, + msm_mux_sdc40, + msm_mux_phase_flag3, + msm_mux_ldo_en, + msm_mux_ldo_update, + msm_mux_phase_flag14, + msm_mux_prng_rosc, + msm_mux_phase_flag15, + msm_mux_phase_flag5, + msm_mux_pci_e1, + msm_mux_COPY_PHASE, + msm_mux_uim2_data, + msm_mux_qup13, + msm_mux_uim2_clk, + msm_mux_uim2_reset, + msm_mux_uim2_present, + msm_mux_uim1_data, + msm_mux_uim1_clk, + msm_mux_uim1_reset, + msm_mux_uim1_present, + msm_mux_uim_batt, + msm_mux_edp_hot, + msm_mux_NAV_PPS, + msm_mux_GPS_TX, + msm_mux_atest_char, + msm_mux_adsp_ext, + msm_mux_atest_char3, + msm_mux_atest_char2, + msm_mux_atest_char1, + msm_mux_atest_char0, + msm_mux_qlink_request, + msm_mux_qlink_enable, + msm_mux_pa_indicator, + msm_mux_phase_flag26, + msm_mux_phase_flag27, + msm_mux_phase_flag28, + msm_mux_phase_flag6, + msm_mux_phase_flag29, + msm_mux_phase_flag30, + msm_mux_phase_flag31, + msm_mux_mss_lte, + msm_mux_NA, +}; + +static const char * const qup0_groups[] = { + "gpio0", "gpio1", "gpio2", "gpio3", +}; +static const char * const gpio_groups[] = { + "gpio0", "gpio1", "gpio2", "gpio3", "gpio4", "gpio5", "gpio6", "gpio7", + "gpio8", "gpio9", "gpio10", "gpio11", "gpio12", "gpio13", "gpio14", + "gpio15", "gpio16", "gpio17", "gpio18", "gpio19", "gpio20", "gpio21", + "gpio22", "gpio23", "gpio24", "gpio25", "gpio26", "gpio27", "gpio28", + "gpio29", "gpio30", "gpio31", "gpio32", "gpio33", "gpio34", "gpio35", + "gpio36", "gpio37", "gpio38", "gpio39", "gpio40", "gpio41", "gpio42", + "gpio43", "gpio44", "gpio45", "gpio46", "gpio47", "gpio48", "gpio49", + "gpio50", "gpio51", "gpio52", "gpio53", "gpio54", "gpio55", "gpio56", + "gpio57", "gpio65", "gpio66", "gpio67", "gpio68", "gpio75", "gpio76", + "gpio77", "gpio78", "gpio79", "gpio80", "gpio81", "gpio82", "gpio83", + "gpio84", "gpio85", "gpio86", "gpio87", "gpio88", "gpio89", "gpio90", + "gpio91", "gpio92", "gpio93", "gpio94", "gpio95", "gpio96", "gpio97", + "gpio98", "gpio99", "gpio100", "gpio101", "gpio102", "gpio103", + "gpio105", "gpio106", "gpio107", "gpio108", "gpio109", "gpio110", + "gpio111", "gpio112", "gpio113", "gpio114", "gpio115", "gpio116", + "gpio117", "gpio118", "gpio119", "gpio120", "gpio121", "gpio122", + "gpio123", "gpio124", "gpio125", "gpio126", "gpio127", "gpio128", + "gpio129", "gpio130", "gpio131", "gpio132", "gpio133", "gpio134", + "gpio135", "gpio136", "gpio137", "gpio138", "gpio139", "gpio140", + "gpio141", "gpio142", "gpio143", "gpio144", "gpio145", "gpio146", + "gpio147", "gpio148", "gpio149", +}; +static const char * const qup9_groups[] = { + "gpio4", "gpio5", "gpio6", "gpio7", +}; +static const char * const qdss_cti_groups[] = { + "gpio4", "gpio5", "gpio51", "gpio52", "gpio90", "gpio91", +}; +static const char * const ddr_pxi0_groups[] = { + "gpio6", "gpio7", +}; +static const char * const ddr_bist_groups[] = { + "gpio7", "gpio8", "gpio9", "gpio10", +}; +static const char * const atest_tsens2_groups[] = { + "gpio7", +}; +static const char * const vsense_trigger_groups[] = { + "gpio7", +}; +static const char * const atest_usb1_groups[] = { + "gpio7", +}; +static const char * const qup_l4_groups[] = { + "gpio8", "gpio105", "gpio123", +}; +static const char * const GP_PDM1_groups[] = { + "gpio8", "gpio66", +}; +static const char * const qup_l5_groups[] = { + "gpio9", "gpio106", "gpio124", +}; +static const char * const mdp_vsync_groups[] = { + "gpio10", "gpio11", "gpio12", "gpio97", "gpio98", +}; +static const char * const qup_l6_groups[] = { + "gpio10", "gpio107", "gpio125", +}; +static const char * const wlan2_adc1_groups[] = { + "gpio10", +}; +static const char * const atest_usb11_groups[] = { + "gpio10", +}; +static const char * const ddr_pxi2_groups[] = { + "gpio10", "gpio11", +}; +static const char * const edp_lcd_groups[] = { + "gpio11", +}; +static const char * const dbg_out_groups[] = { + "gpio11", +}; +static const char * const wlan2_adc0_groups[] = { + "gpio11", +}; +static const char * const atest_usb10_groups[] = { + "gpio11", +}; +static const char * const m_voc_groups[] = { + "gpio12", +}; +static const char * const tsif1_sync_groups[] = { + "gpio12", +}; +static const char * const ddr_pxi3_groups[] = { + "gpio12", "gpio13", +}; +static const char * const cam_mclk_groups[] = { + "gpio13", "gpio14", "gpio15", "gpio16", +}; +static const char * const pll_bypassnl_groups[] = { + "gpio13", +}; +static const char * const qdss_gpio0_groups[] = { + "gpio13", "gpio117", +}; +static const char * const pll_reset_groups[] = { + "gpio14", +}; +static const char * const qdss_gpio1_groups[] = { + "gpio14", "gpio118", +}; +static const char * const qdss_gpio2_groups[] = { + "gpio15", "gpio119", +}; +static const char * const qdss_gpio3_groups[] = { + "gpio16", "gpio120", +}; +static const char * const cci_i2c_groups[] = { + "gpio17", "gpio18", "gpio19", "gpio20", +}; +static const char * const qup1_groups[] = { + "gpio17", "gpio18", "gpio19", "gpio20", +}; +static const char * const qdss_gpio4_groups[] = { + "gpio17", "gpio121", +}; +static const char * const qdss_gpio5_groups[] = { + "gpio18", "gpio122", +}; +static const char * const qdss_gpio6_groups[] = { + "gpio19", "gpio41", +}; +static const char * const qdss_gpio7_groups[] = { + "gpio20", "gpio42", +}; +static const char * const cci_timer0_groups[] = { + "gpio21", +}; +static const char * const gcc_gp2_groups[] = { + "gpio21", +}; +static const char * const qdss_gpio8_groups[] = { + "gpio21", "gpio75", +}; +static const char * const cci_timer1_groups[] = { + "gpio22", +}; +static const char * const gcc_gp3_groups[] = { + "gpio22", +}; +static const char * const qdss_gpio_groups[] = { + "gpio22", "gpio30", "gpio123", "gpio124", +}; +static const char * const cci_timer2_groups[] = { + "gpio23", +}; +static const char * const qdss_gpio9_groups[] = { + "gpio23", "gpio76", +}; +static const char * const cci_timer3_groups[] = { + "gpio24", +}; +static const char * const cci_async_groups[] = { + "gpio24", "gpio25", "gpio26", +}; +static const char * const qdss_gpio10_groups[] = { + "gpio24", "gpio77", +}; +static const char * const cci_timer4_groups[] = { + "gpio25", +}; +static const char * const qdss_gpio11_groups[] = { + "gpio25", "gpio79", +}; +static const char * const qdss_gpio12_groups[] = { + "gpio26", "gpio80", +}; +static const char * const JITTER_BIST_groups[] = { + "gpio26", "gpio35", +}; +static const char * const qup2_groups[] = { + "gpio27", "gpio28", "gpio29", "gpio30", +}; +static const char * const qdss_gpio13_groups[] = { + "gpio27", "gpio93", +}; +static const char * const PLL_BIST_groups[] = { + "gpio27", "gpio36", +}; +static const char * const qdss_gpio14_groups[] = { + "gpio28", "gpio43", +}; +static const char * const AGERA_PLL_groups[] = { + "gpio28", "gpio37", +}; +static const char * const phase_flag1_groups[] = { + "gpio29", +}; +static const char * const qdss_gpio15_groups[] = { + "gpio29", "gpio44", +}; +static const char * const atest_tsens_groups[] = { + "gpio29", +}; +static const char * const phase_flag2_groups[] = { + "gpio30", +}; +static const char * const qup11_groups[] = { + "gpio31", "gpio32", "gpio33", "gpio34", +}; +static const char * const qup14_groups[] = { + "gpio31", "gpio32", "gpio33", "gpio34", +}; +static const char * const pci_e0_groups[] = { + "gpio35", "gpio36", +}; +static const char * const QUP_L4_groups[] = { + "gpio35", "gpio75", +}; +static const char * const QUP_L5_groups[] = { + "gpio36", "gpio76", +}; +static const char * const QUP_L6_groups[] = { + "gpio37", "gpio77", +}; +static const char * const usb_phy_groups[] = { + "gpio38", +}; +static const char * const lpass_slimbus_groups[] = { + "gpio39", +}; +static const char * const sd_write_groups[] = { + "gpio40", +}; +static const char * const tsif1_error_groups[] = { + "gpio40", +}; +static const char * const qup3_groups[] = { + "gpio41", "gpio42", "gpio43", "gpio44", +}; +static const char * const qup6_groups[] = { + "gpio45", "gpio46", "gpio47", "gpio48", +}; +static const char * const qup12_groups[] = { + "gpio49", "gpio50", "gpio51", "gpio52", +}; +static const char * const phase_flag16_groups[] = { + "gpio52", +}; +static const char * const qup10_groups[] = { + "gpio53", "gpio54", "gpio55", "gpio56", +}; +static const char * const phase_flag11_groups[] = { + "gpio53", +}; +static const char * const GP_PDM0_groups[] = { + "gpio54", "gpio95", +}; +static const char * const phase_flag12_groups[] = { + "gpio54", +}; +static const char * const wlan1_adc1_groups[] = { + "gpio54", +}; +static const char * const atest_usb13_groups[] = { + "gpio54", +}; +static const char * const ddr_pxi1_groups[] = { + "gpio54", "gpio55", +}; +static const char * const phase_flag13_groups[] = { + "gpio55", +}; +static const char * const wlan1_adc0_groups[] = { + "gpio55", +}; +static const char * const atest_usb12_groups[] = { + "gpio55", +}; +static const char * const phase_flag17_groups[] = { + "gpio56", +}; +static const char * const qua_mi2s_groups[] = { + "gpio57", +}; +static const char * const gcc_gp1_groups[] = { + "gpio57", "gpio78", +}; +static const char * const phase_flag18_groups[] = { + "gpio57", +}; +static const char * const pri_mi2s_groups[] = { + "gpio65", "gpio67", "gpio68", +}; +static const char * const qup8_groups[] = { + "gpio65", "gpio66", "gpio67", "gpio68", +}; +static const char * const wsa_clk_groups[] = { + "gpio65", +}; +static const char * const pri_mi2s_ws_groups[] = { + "gpio66", +}; +static const char * const wsa_data_groups[] = { + "gpio66", +}; +static const char * const atest_usb2_groups[] = { + "gpio67", +}; +static const char * const atest_usb23_groups[] = { + "gpio68", +}; +static const char * const ter_mi2s_groups[] = { + "gpio75", "gpio76", "gpio77", "gpio78", +}; +static const char * const phase_flag8_groups[] = { + "gpio75", +}; +static const char * const atest_usb22_groups[] = { + "gpio75", +}; +static const char * const phase_flag9_groups[] = { + "gpio76", +}; +static const char * const atest_usb21_groups[] = { + "gpio76", +}; +static const char * const phase_flag4_groups[] = { + "gpio77", +}; +static const char * const atest_usb20_groups[] = { + "gpio77", +}; +static const char * const sec_mi2s_groups[] = { + "gpio79", "gpio80", "gpio81", "gpio82", "gpio83", +}; +static const char * const GP_PDM2_groups[] = { + "gpio79", +}; +static const char * const qup15_groups[] = { + "gpio81", "gpio82", "gpio83", "gpio84", +}; +static const char * const qup5_groups[] = { + "gpio85", "gpio86", "gpio87", "gpio88", +}; +static const char * const copy_gp_groups[] = { + "gpio86", +}; +static const char * const tsif1_clk_groups[] = { + "gpio89", +}; +static const char * const qup4_groups[] = { + "gpio89", "gpio90", "gpio91", "gpio92", +}; +static const char * const tgu_ch3_groups[] = { + "gpio89", +}; +static const char * const phase_flag10_groups[] = { + "gpio89", +}; +static const char * const tsif1_en_groups[] = { + "gpio90", +}; +static const char * const mdp_vsync0_groups[] = { + "gpio90", +}; +static const char * const mdp_vsync1_groups[] = { + "gpio90", +}; +static const char * const mdp_vsync2_groups[] = { + "gpio90", +}; +static const char * const mdp_vsync3_groups[] = { + "gpio90", +}; +static const char * const tgu_ch0_groups[] = { + "gpio90", +}; +static const char * const phase_flag0_groups[] = { + "gpio90", +}; +static const char * const tsif1_data_groups[] = { + "gpio91", +}; +static const char * const sdc4_cmd_groups[] = { + "gpio91", +}; +static const char * const tgu_ch1_groups[] = { + "gpio91", +}; +static const char * const tsif2_error_groups[] = { + "gpio92", +}; +static const char * const sdc43_groups[] = { + "gpio92", +}; +static const char * const vfr_1_groups[] = { + "gpio92", +}; +static const char * const tgu_ch2_groups[] = { + "gpio92", +}; +static const char * const tsif2_clk_groups[] = { + "gpio93", +}; +static const char * const sdc4_clk_groups[] = { + "gpio93", +}; +static const char * const qup7_groups[] = { + "gpio93", "gpio94", "gpio95", "gpio96", +}; +static const char * const tsif2_en_groups[] = { + "gpio94", +}; +static const char * const sdc42_groups[] = { + "gpio94", +}; +static const char * const tsif2_data_groups[] = { + "gpio95", +}; +static const char * const sdc41_groups[] = { + "gpio95", +}; +static const char * const tsif2_sync_groups[] = { + "gpio96", +}; +static const char * const sdc40_groups[] = { + "gpio96", +}; +static const char * const phase_flag3_groups[] = { + "gpio96", +}; +static const char * const ldo_en_groups[] = { + "gpio97", +}; +static const char * const ldo_update_groups[] = { + "gpio98", +}; +static const char * const phase_flag14_groups[] = { + "gpio99", +}; +static const char * const prng_rosc_groups[] = { + "gpio99", "gpio102", +}; +static const char * const phase_flag15_groups[] = { + "gpio100", +}; +static const char * const phase_flag5_groups[] = { + "gpio101", +}; +static const char * const pci_e1_groups[] = { + "gpio102", "gpio103", +}; +static const char * const COPY_PHASE_groups[] = { + "gpio103", +}; +static const char * const uim2_data_groups[] = { + "gpio105", +}; +static const char * const qup13_groups[] = { + "gpio105", "gpio106", "gpio107", "gpio108", +}; +static const char * const uim2_clk_groups[] = { + "gpio106", +}; +static const char * const uim2_reset_groups[] = { + "gpio107", +}; +static const char * const uim2_present_groups[] = { + "gpio108", +}; +static const char * const uim1_data_groups[] = { + "gpio109", +}; +static const char * const uim1_clk_groups[] = { + "gpio110", +}; +static const char * const uim1_reset_groups[] = { + "gpio111", +}; +static const char * const uim1_present_groups[] = { + "gpio112", +}; +static const char * const uim_batt_groups[] = { + "gpio113", +}; +static const char * const edp_hot_groups[] = { + "gpio113", +}; +static const char * const NAV_PPS_groups[] = { + "gpio114", "gpio114", "gpio115", "gpio115", "gpio128", "gpio128", + "gpio129", "gpio129", "gpio143", "gpio143", +}; +static const char * const GPS_TX_groups[] = { + "gpio114", "gpio115", "gpio128", "gpio129", "gpio143", "gpio145", +}; +static const char * const atest_char_groups[] = { + "gpio117", +}; +static const char * const adsp_ext_groups[] = { + "gpio118", +}; +static const char * const atest_char3_groups[] = { + "gpio118", +}; +static const char * const atest_char2_groups[] = { + "gpio119", +}; +static const char * const atest_char1_groups[] = { + "gpio120", +}; +static const char * const atest_char0_groups[] = { + "gpio121", +}; +static const char * const qlink_request_groups[] = { + "gpio130", +}; +static const char * const qlink_enable_groups[] = { + "gpio131", +}; +static const char * const pa_indicator_groups[] = { + "gpio135", +}; +static const char * const phase_flag26_groups[] = { + "gpio137", +}; +static const char * const phase_flag27_groups[] = { + "gpio138", +}; +static const char * const phase_flag28_groups[] = { + "gpio139", +}; +static const char * const phase_flag6_groups[] = { + "gpio140", +}; +static const char * const phase_flag29_groups[] = { + "gpio141", +}; +static const char * const phase_flag30_groups[] = { + "gpio142", +}; +static const char * const phase_flag31_groups[] = { + "gpio143", +}; +static const char * const mss_lte_groups[] = { + "gpio144", "gpio145", +}; + +static const struct msm_function sdm670_functions[] = { + FUNCTION(qup0), + FUNCTION(gpio), + FUNCTION(qup9), + FUNCTION(qdss_cti), + FUNCTION(ddr_pxi0), + FUNCTION(ddr_bist), + FUNCTION(atest_tsens2), + FUNCTION(vsense_trigger), + FUNCTION(atest_usb1), + FUNCTION(qup_l4), + FUNCTION(GP_PDM1), + FUNCTION(qup_l5), + FUNCTION(mdp_vsync), + FUNCTION(qup_l6), + FUNCTION(wlan2_adc1), + FUNCTION(atest_usb11), + FUNCTION(ddr_pxi2), + FUNCTION(edp_lcd), + FUNCTION(dbg_out), + FUNCTION(wlan2_adc0), + FUNCTION(atest_usb10), + FUNCTION(m_voc), + FUNCTION(tsif1_sync), + FUNCTION(ddr_pxi3), + FUNCTION(cam_mclk), + FUNCTION(pll_bypassnl), + FUNCTION(qdss_gpio0), + FUNCTION(pll_reset), + FUNCTION(qdss_gpio1), + FUNCTION(qdss_gpio2), + FUNCTION(qdss_gpio3), + FUNCTION(cci_i2c), + FUNCTION(qup1), + FUNCTION(qdss_gpio4), + FUNCTION(qdss_gpio5), + FUNCTION(qdss_gpio6), + FUNCTION(qdss_gpio7), + FUNCTION(cci_timer0), + FUNCTION(gcc_gp2), + FUNCTION(qdss_gpio8), + FUNCTION(cci_timer1), + FUNCTION(gcc_gp3), + FUNCTION(qdss_gpio), + FUNCTION(cci_timer2), + FUNCTION(qdss_gpio9), + FUNCTION(cci_timer3), + FUNCTION(cci_async), + FUNCTION(qdss_gpio10), + FUNCTION(cci_timer4), + FUNCTION(qdss_gpio11), + FUNCTION(qdss_gpio12), + FUNCTION(JITTER_BIST), + FUNCTION(qup2), + FUNCTION(qdss_gpio13), + FUNCTION(PLL_BIST), + FUNCTION(qdss_gpio14), + FUNCTION(AGERA_PLL), + FUNCTION(phase_flag1), + FUNCTION(qdss_gpio15), + FUNCTION(atest_tsens), + FUNCTION(phase_flag2), + FUNCTION(qup11), + FUNCTION(qup14), + FUNCTION(pci_e0), + FUNCTION(QUP_L4), + FUNCTION(QUP_L5), + FUNCTION(QUP_L6), + FUNCTION(usb_phy), + FUNCTION(lpass_slimbus), + FUNCTION(sd_write), + FUNCTION(tsif1_error), + FUNCTION(qup3), + FUNCTION(qup6), + FUNCTION(qup12), + FUNCTION(phase_flag16), + FUNCTION(qup10), + FUNCTION(phase_flag11), + FUNCTION(GP_PDM0), + FUNCTION(phase_flag12), + FUNCTION(wlan1_adc1), + FUNCTION(atest_usb13), + FUNCTION(ddr_pxi1), + FUNCTION(phase_flag13), + FUNCTION(wlan1_adc0), + FUNCTION(atest_usb12), + FUNCTION(phase_flag17), + FUNCTION(qua_mi2s), + FUNCTION(gcc_gp1), + FUNCTION(phase_flag18), + FUNCTION(pri_mi2s), + FUNCTION(qup8), + FUNCTION(wsa_clk), + FUNCTION(pri_mi2s_ws), + FUNCTION(wsa_data), + FUNCTION(atest_usb2), + FUNCTION(atest_usb23), + FUNCTION(ter_mi2s), + FUNCTION(phase_flag8), + FUNCTION(atest_usb22), + FUNCTION(phase_flag9), + FUNCTION(atest_usb21), + FUNCTION(phase_flag4), + FUNCTION(atest_usb20), + FUNCTION(sec_mi2s), + FUNCTION(GP_PDM2), + FUNCTION(qup15), + FUNCTION(qup5), + FUNCTION(copy_gp), + FUNCTION(tsif1_clk), + FUNCTION(qup4), + FUNCTION(tgu_ch3), + FUNCTION(phase_flag10), + FUNCTION(tsif1_en), + FUNCTION(mdp_vsync0), + FUNCTION(mdp_vsync1), + FUNCTION(mdp_vsync2), + FUNCTION(mdp_vsync3), + FUNCTION(tgu_ch0), + FUNCTION(phase_flag0), + FUNCTION(tsif1_data), + FUNCTION(sdc4_cmd), + FUNCTION(tgu_ch1), + FUNCTION(tsif2_error), + FUNCTION(sdc43), + FUNCTION(vfr_1), + FUNCTION(tgu_ch2), + FUNCTION(tsif2_clk), + FUNCTION(sdc4_clk), + FUNCTION(qup7), + FUNCTION(tsif2_en), + FUNCTION(sdc42), + FUNCTION(tsif2_data), + FUNCTION(sdc41), + FUNCTION(tsif2_sync), + FUNCTION(sdc40), + FUNCTION(phase_flag3), + FUNCTION(ldo_en), + FUNCTION(ldo_update), + FUNCTION(phase_flag14), + FUNCTION(prng_rosc), + FUNCTION(phase_flag15), + FUNCTION(phase_flag5), + FUNCTION(pci_e1), + FUNCTION(COPY_PHASE), + FUNCTION(uim2_data), + FUNCTION(qup13), + FUNCTION(uim2_clk), + FUNCTION(uim2_reset), + FUNCTION(uim2_present), + FUNCTION(uim1_data), + FUNCTION(uim1_clk), + FUNCTION(uim1_reset), + FUNCTION(uim1_present), + FUNCTION(uim_batt), + FUNCTION(edp_hot), + FUNCTION(NAV_PPS), + FUNCTION(GPS_TX), + FUNCTION(atest_char), + FUNCTION(adsp_ext), + FUNCTION(atest_char3), + FUNCTION(atest_char2), + FUNCTION(atest_char1), + FUNCTION(atest_char0), + FUNCTION(qlink_request), + FUNCTION(qlink_enable), + FUNCTION(pa_indicator), + FUNCTION(phase_flag26), + FUNCTION(phase_flag27), + FUNCTION(phase_flag28), + FUNCTION(phase_flag6), + FUNCTION(phase_flag29), + FUNCTION(phase_flag30), + FUNCTION(phase_flag31), + FUNCTION(mss_lte), +}; + +/* Every pin is maintained as a single group, and missing or non-existing pin + * would be maintained as dummy group to synchronize pin group index with + * pin descriptor registered with pinctrl core. + * Clients would not be able to request these dummy pin groups. + */ +static const struct msm_pingroup sdm670_groups[] = { + [0] = PINGROUP(0, SOUTH, qup0, NA, NA, NA, NA, NA, NA, NA, NA), + [1] = PINGROUP(1, SOUTH, qup0, NA, NA, NA, NA, NA, NA, NA, NA), + [2] = PINGROUP(2, SOUTH, qup0, NA, NA, NA, NA, NA, NA, NA, NA), + [3] = PINGROUP(3, SOUTH, qup0, NA, NA, NA, NA, NA, NA, NA, NA), + [4] = PINGROUP(4, NORTH, qup9, qdss_cti, NA, NA, NA, NA, NA, NA, NA), + [5] = PINGROUP(5, NORTH, qup9, qdss_cti, NA, NA, NA, NA, NA, NA, NA), + [6] = PINGROUP(6, NORTH, qup9, NA, ddr_pxi0, NA, NA, NA, NA, NA, NA), + [7] = PINGROUP(7, NORTH, qup9, ddr_bist, NA, atest_tsens2, + vsense_trigger, atest_usb1, ddr_pxi0, NA, NA), + [8] = PINGROUP(8, WEST, qup_l4, GP_PDM1, ddr_bist, NA, NA, NA, NA, NA, + NA), + [9] = PINGROUP(9, WEST, qup_l5, ddr_bist, NA, NA, NA, NA, NA, NA, NA), + [10] = PINGROUP(10, NORTH, mdp_vsync, qup_l6, ddr_bist, wlan2_adc1, + atest_usb11, ddr_pxi2, NA, NA, NA), + [11] = PINGROUP(11, NORTH, mdp_vsync, edp_lcd, dbg_out, wlan2_adc0, + atest_usb10, ddr_pxi2, NA, NA, NA), + [12] = PINGROUP(12, SOUTH, mdp_vsync, m_voc, tsif1_sync, ddr_pxi3, NA, + NA, NA, NA, NA), + [13] = PINGROUP(13, WEST, cam_mclk, pll_bypassnl, qdss_gpio0, ddr_pxi3, + NA, NA, NA, NA, NA), + [14] = PINGROUP(14, WEST, cam_mclk, pll_reset, qdss_gpio1, NA, NA, NA, + NA, NA, NA), + [15] = PINGROUP(15, WEST, cam_mclk, qdss_gpio2, NA, NA, NA, NA, NA, NA, + NA), + [16] = PINGROUP(16, WEST, cam_mclk, qdss_gpio3, NA, NA, NA, NA, NA, NA, + NA), + [17] = PINGROUP(17, WEST, cci_i2c, qup1, qdss_gpio4, NA, NA, NA, NA, + NA, NA), + [18] = PINGROUP(18, WEST, cci_i2c, qup1, NA, qdss_gpio5, NA, NA, NA, + NA, NA), + [19] = PINGROUP(19, WEST, cci_i2c, qup1, NA, qdss_gpio6, NA, NA, NA, + NA, NA), + [20] = PINGROUP(20, WEST, cci_i2c, qup1, NA, qdss_gpio7, NA, NA, NA, + NA, NA), + [21] = PINGROUP(21, WEST, cci_timer0, gcc_gp2, qdss_gpio8, NA, NA, NA, + NA, NA, NA), + [22] = PINGROUP(22, WEST, cci_timer1, gcc_gp3, qdss_gpio, NA, NA, NA, + NA, NA, NA), + [23] = PINGROUP(23, WEST, cci_timer2, qdss_gpio9, NA, NA, NA, NA, NA, + NA, NA), + [24] = PINGROUP(24, WEST, cci_timer3, cci_async, qdss_gpio10, NA, NA, + NA, NA, NA, NA), + [25] = PINGROUP(25, WEST, cci_timer4, cci_async, qdss_gpio11, NA, NA, + NA, NA, NA, NA), + [26] = PINGROUP(26, WEST, cci_async, qdss_gpio12, JITTER_BIST, NA, NA, + NA, NA, NA, NA), + [27] = PINGROUP(27, WEST, qup2, qdss_gpio13, PLL_BIST, NA, NA, NA, NA, + NA, NA), + [28] = PINGROUP(28, WEST, qup2, qdss_gpio14, AGERA_PLL, NA, NA, NA, NA, + NA, NA), + [29] = PINGROUP(29, WEST, qup2, NA, phase_flag1, qdss_gpio15, + atest_tsens, NA, NA, NA, NA), + [30] = PINGROUP(30, WEST, qup2, phase_flag2, qdss_gpio, NA, NA, NA, NA, + NA, NA), + [31] = PINGROUP(31, WEST, qup11, qup14, NA, NA, NA, NA, NA, NA, NA), + [32] = PINGROUP(32, WEST, qup11, qup14, NA, NA, NA, NA, NA, NA, NA), + [33] = PINGROUP(33, WEST, qup11, qup14, NA, NA, NA, NA, NA, NA, NA), + [34] = PINGROUP(34, WEST, qup11, qup14, NA, NA, NA, NA, NA, NA, NA), + [35] = PINGROUP(35, NORTH, pci_e0, QUP_L4, JITTER_BIST, NA, NA, NA, NA, + NA, NA), + [36] = PINGROUP(36, NORTH, pci_e0, QUP_L5, PLL_BIST, NA, NA, NA, NA, + NA, NA), + [37] = PINGROUP(37, NORTH, QUP_L6, AGERA_PLL, NA, NA, NA, NA, NA, NA, + NA), + [38] = PINGROUP(38, NORTH, usb_phy, NA, NA, NA, NA, NA, NA, NA, NA), + [39] = PINGROUP(39, NORTH, lpass_slimbus, NA, NA, NA, NA, NA, NA, NA, + NA), + [40] = PINGROUP(40, NORTH, sd_write, tsif1_error, NA, NA, NA, NA, NA, + NA, NA), + [41] = PINGROUP(41, SOUTH, qup3, NA, qdss_gpio6, NA, NA, NA, NA, NA, + NA), + [42] = PINGROUP(42, SOUTH, qup3, NA, qdss_gpio7, NA, NA, NA, NA, NA, + NA), + [43] = PINGROUP(43, SOUTH, qup3, NA, qdss_gpio14, NA, NA, NA, NA, NA, + NA), + [44] = PINGROUP(44, SOUTH, qup3, NA, qdss_gpio15, NA, NA, NA, NA, NA, + NA), + [45] = PINGROUP(45, SOUTH, qup6, NA, NA, NA, NA, NA, NA, NA, NA), + [46] = PINGROUP(46, SOUTH, qup6, NA, NA, NA, NA, NA, NA, NA, NA), + [47] = PINGROUP(47, SOUTH, qup6, NA, NA, NA, NA, NA, NA, NA, NA), + [48] = PINGROUP(48, SOUTH, qup6, NA, NA, NA, NA, NA, NA, NA, NA), + [49] = PINGROUP(49, NORTH, qup12, NA, NA, NA, NA, NA, NA, NA, NA), + [50] = PINGROUP(50, NORTH, qup12, NA, NA, NA, NA, NA, NA, NA, NA), + [51] = PINGROUP(51, NORTH, qup12, qdss_cti, NA, NA, NA, NA, NA, NA, NA), + [52] = PINGROUP(52, NORTH, qup12, phase_flag16, qdss_cti, NA, NA, NA, + NA, NA, NA), + [53] = PINGROUP(53, NORTH, qup10, phase_flag11, NA, NA, NA, NA, NA, NA, + NA), + [54] = PINGROUP(54, NORTH, qup10, GP_PDM0, phase_flag12, NA, + wlan1_adc1, atest_usb13, ddr_pxi1, NA, NA), + [55] = PINGROUP(55, NORTH, qup10, phase_flag13, NA, wlan1_adc0, + atest_usb12, ddr_pxi1, NA, NA, NA), + [56] = PINGROUP(56, NORTH, qup10, phase_flag17, NA, NA, NA, NA, NA, NA, + NA), + [57] = PINGROUP(57, NORTH, qua_mi2s, gcc_gp1, phase_flag18, NA, NA, NA, + NA, NA, NA), + [58] = PINGROUP(58, DUMMY, NA, NA, NA, NA, NA, NA, NA, NA, NA), + [59] = PINGROUP(59, DUMMY, NA, NA, NA, NA, NA, NA, NA, NA, NA), + [60] = PINGROUP(60, DUMMY, NA, NA, NA, NA, NA, NA, NA, NA, NA), + [61] = PINGROUP(61, DUMMY, NA, NA, NA, NA, NA, NA, NA, NA, NA), + [62] = PINGROUP(62, DUMMY, NA, NA, NA, NA, NA, NA, NA, NA, NA), + [63] = PINGROUP(63, DUMMY, NA, NA, NA, NA, NA, NA, NA, NA, NA), + [64] = PINGROUP(64, DUMMY, NA, NA, NA, NA, NA, NA, NA, NA, NA), + [65] = PINGROUP(65, NORTH, pri_mi2s, qup8, wsa_clk, NA, NA, NA, NA, NA, + NA), + [66] = PINGROUP(66, NORTH, pri_mi2s_ws, qup8, wsa_data, GP_PDM1, NA, + NA, NA, NA, NA), + [67] = PINGROUP(67, NORTH, pri_mi2s, qup8, NA, atest_usb2, NA, NA, NA, + NA, NA), + [68] = PINGROUP(68, NORTH, pri_mi2s, qup8, NA, atest_usb23, NA, NA, NA, + NA, NA), + [69] = PINGROUP(69, DUMMY, NA, NA, NA, NA, NA, NA, NA, NA, NA), + [70] = PINGROUP(70, DUMMY, NA, NA, NA, NA, NA, NA, NA, NA, NA), + [71] = PINGROUP(71, DUMMY, NA, NA, NA, NA, NA, NA, NA, NA, NA), + [72] = PINGROUP(72, DUMMY, NA, NA, NA, NA, NA, NA, NA, NA, NA), + [73] = PINGROUP(73, DUMMY, NA, NA, NA, NA, NA, NA, NA, NA, NA), + [74] = PINGROUP(74, DUMMY, NA, NA, NA, NA, NA, NA, NA, NA, NA), + [75] = PINGROUP(75, NORTH, ter_mi2s, phase_flag8, qdss_gpio8, + atest_usb22, QUP_L4, NA, NA, NA, NA), + [76] = PINGROUP(76, NORTH, ter_mi2s, phase_flag9, qdss_gpio9, + atest_usb21, QUP_L5, NA, NA, NA, NA), + [77] = PINGROUP(77, NORTH, ter_mi2s, phase_flag4, qdss_gpio10, + atest_usb20, QUP_L6, NA, NA, NA, NA), + [78] = PINGROUP(78, NORTH, ter_mi2s, gcc_gp1, NA, NA, NA, NA, NA, NA, + NA), + [79] = PINGROUP(79, NORTH, sec_mi2s, GP_PDM2, NA, qdss_gpio11, NA, NA, + NA, NA, NA), + [80] = PINGROUP(80, NORTH, sec_mi2s, NA, qdss_gpio12, NA, NA, NA, NA, + NA, NA), + [81] = PINGROUP(81, NORTH, sec_mi2s, qup15, NA, NA, NA, NA, NA, NA, NA), + [82] = PINGROUP(82, NORTH, sec_mi2s, qup15, NA, NA, NA, NA, NA, NA, NA), + [83] = PINGROUP(83, NORTH, sec_mi2s, qup15, NA, NA, NA, NA, NA, NA, NA), + [84] = PINGROUP(84, NORTH, qup15, NA, NA, NA, NA, NA, NA, NA, NA), + [85] = PINGROUP(85, SOUTH, qup5, NA, NA, NA, NA, NA, NA, NA, NA), + [86] = PINGROUP(86, SOUTH, qup5, copy_gp, NA, NA, NA, NA, NA, NA, NA), + [87] = PINGROUP(87, SOUTH, qup5, NA, NA, NA, NA, NA, NA, NA, NA), + [88] = PINGROUP(88, SOUTH, qup5, NA, NA, NA, NA, NA, NA, NA, NA), + [89] = PINGROUP(89, SOUTH, tsif1_clk, qup4, tgu_ch3, phase_flag10, NA, + NA, NA, NA, NA), + [90] = PINGROUP(90, SOUTH, tsif1_en, mdp_vsync0, qup4, mdp_vsync1, + mdp_vsync2, mdp_vsync3, tgu_ch0, phase_flag0, qdss_cti), + [91] = PINGROUP(91, SOUTH, tsif1_data, sdc4_cmd, qup4, tgu_ch1, NA, + qdss_cti, NA, NA, NA), + [92] = PINGROUP(92, SOUTH, tsif2_error, sdc43, qup4, vfr_1, tgu_ch2, + NA, NA, NA, NA), + [93] = PINGROUP(93, SOUTH, tsif2_clk, sdc4_clk, qup7, NA, qdss_gpio13, + NA, NA, NA, NA), + [94] = PINGROUP(94, SOUTH, tsif2_en, sdc42, qup7, NA, NA, NA, NA, NA, + NA), + [95] = PINGROUP(95, SOUTH, tsif2_data, sdc41, qup7, GP_PDM0, NA, NA, + NA, NA, NA), + [96] = PINGROUP(96, SOUTH, tsif2_sync, sdc40, qup7, phase_flag3, NA, + NA, NA, NA, NA), + [97] = PINGROUP(97, WEST, NA, NA, mdp_vsync, ldo_en, NA, NA, NA, NA, + NA), + [98] = PINGROUP(98, WEST, NA, mdp_vsync, ldo_update, NA, NA, NA, NA, + NA, NA), + [99] = PINGROUP(99, NORTH, phase_flag14, prng_rosc, NA, NA, NA, NA, NA, + NA, NA), + [100] = PINGROUP(100, WEST, phase_flag15, NA, NA, NA, NA, NA, NA, NA, + NA), + [101] = PINGROUP(101, WEST, NA, phase_flag5, NA, NA, NA, NA, NA, NA, + NA), + [102] = PINGROUP(102, WEST, pci_e1, prng_rosc, NA, NA, NA, NA, NA, NA, + NA), + [103] = PINGROUP(103, WEST, pci_e1, COPY_PHASE, NA, NA, NA, NA, NA, NA, + NA), + [104] = PINGROUP(104, DUMMY, NA, NA, NA, NA, NA, NA, NA, NA, NA), + [105] = PINGROUP(105, NORTH, uim2_data, qup13, qup_l4, NA, NA, NA, NA, + NA, NA), + [106] = PINGROUP(106, NORTH, uim2_clk, qup13, qup_l5, NA, NA, NA, NA, + NA, NA), + [107] = PINGROUP(107, NORTH, uim2_reset, qup13, qup_l6, NA, NA, NA, NA, + NA, NA), + [108] = PINGROUP(108, NORTH, uim2_present, qup13, NA, NA, NA, NA, NA, + NA, NA), + [109] = PINGROUP(109, NORTH, uim1_data, NA, NA, NA, NA, NA, NA, NA, NA), + [110] = PINGROUP(110, NORTH, uim1_clk, NA, NA, NA, NA, NA, NA, NA, NA), + [111] = PINGROUP(111, NORTH, uim1_reset, NA, NA, NA, NA, NA, NA, NA, + NA), + [112] = PINGROUP(112, NORTH, uim1_present, NA, NA, NA, NA, NA, NA, NA, + NA), + [113] = PINGROUP(113, NORTH, uim_batt, edp_hot, NA, NA, NA, NA, NA, NA, + NA), + [114] = PINGROUP(114, WEST, NA, NAV_PPS, NAV_PPS, GPS_TX, NA, NA, NA, + NA, NA), + [115] = PINGROUP(115, WEST, NA, NAV_PPS, NAV_PPS, GPS_TX, NA, NA, NA, + NA, NA), + [116] = PINGROUP(116, SOUTH, NA, NA, NA, NA, NA, NA, NA, NA, NA), + [117] = PINGROUP(117, NORTH, NA, qdss_gpio0, atest_char, NA, NA, NA, + NA, NA, NA), + [118] = PINGROUP(118, NORTH, adsp_ext, NA, qdss_gpio1, atest_char3, NA, + NA, NA, NA, NA), + [119] = PINGROUP(119, NORTH, NA, qdss_gpio2, atest_char2, NA, NA, NA, + NA, NA, NA), + [120] = PINGROUP(120, NORTH, NA, qdss_gpio3, atest_char1, NA, NA, NA, + NA, NA, NA), + [121] = PINGROUP(121, NORTH, NA, qdss_gpio4, atest_char0, NA, NA, NA, + NA, NA, NA), + [122] = PINGROUP(122, NORTH, NA, qdss_gpio5, NA, NA, NA, NA, NA, NA, + NA), + [123] = PINGROUP(123, NORTH, qup_l4, NA, qdss_gpio, NA, NA, NA, NA, NA, + NA), + [124] = PINGROUP(124, NORTH, qup_l5, NA, qdss_gpio, NA, NA, NA, NA, NA, + NA), + [125] = PINGROUP(125, NORTH, qup_l6, NA, NA, NA, NA, NA, NA, NA, NA), + [126] = PINGROUP(126, NORTH, NA, NA, NA, NA, NA, NA, NA, NA, NA), + [127] = PINGROUP(127, WEST, NA, NA, NA, NA, NA, NA, NA, NA, NA), + [128] = PINGROUP(128, WEST, NAV_PPS, NAV_PPS, GPS_TX, NA, NA, NA, NA, + NA, NA), + [129] = PINGROUP(129, WEST, NAV_PPS, NAV_PPS, GPS_TX, NA, NA, NA, NA, + NA, NA), + [130] = PINGROUP(130, WEST, qlink_request, NA, NA, NA, NA, NA, NA, NA, + NA), + [131] = PINGROUP(131, WEST, qlink_enable, NA, NA, NA, NA, NA, NA, NA, + NA), + [132] = PINGROUP(132, WEST, NA, NA, NA, NA, NA, NA, NA, NA, NA), + [133] = PINGROUP(133, NORTH, NA, NA, NA, NA, NA, NA, NA, NA, NA), + [134] = PINGROUP(134, NORTH, NA, NA, NA, NA, NA, NA, NA, NA, NA), + [135] = PINGROUP(135, WEST, NA, pa_indicator, NA, NA, NA, NA, NA, NA, + NA), + [136] = PINGROUP(136, WEST, NA, NA, NA, NA, NA, NA, NA, NA, NA), + [137] = PINGROUP(137, WEST, NA, NA, phase_flag26, NA, NA, NA, NA, NA, + NA), + [138] = PINGROUP(138, WEST, NA, NA, phase_flag27, NA, NA, NA, NA, NA, + NA), + [139] = PINGROUP(139, WEST, NA, phase_flag28, NA, NA, NA, NA, NA, NA, + NA), + [140] = PINGROUP(140, WEST, NA, NA, phase_flag6, NA, NA, NA, NA, NA, + NA), + [141] = PINGROUP(141, WEST, NA, phase_flag29, NA, NA, NA, NA, NA, NA, + NA), + [142] = PINGROUP(142, WEST, NA, phase_flag30, NA, NA, NA, NA, NA, NA, + NA), + [143] = PINGROUP(143, WEST, NA, NAV_PPS, NAV_PPS, GPS_TX, phase_flag31, + NA, NA, NA, NA), + [144] = PINGROUP(144, SOUTH, mss_lte, NA, NA, NA, NA, NA, NA, NA, NA), + [145] = PINGROUP(145, SOUTH, mss_lte, GPS_TX, NA, NA, NA, NA, NA, NA, + NA), + [146] = PINGROUP(146, WEST, NA, NA, NA, NA, NA, NA, NA, NA, NA), + [147] = PINGROUP(147, WEST, NA, NA, NA, NA, NA, NA, NA, NA, NA), + [148] = PINGROUP(148, WEST, NA, NA, NA, NA, NA, NA, NA, NA, NA), + [149] = PINGROUP(149, WEST, NA, NA, NA, NA, NA, NA, NA, NA, NA), + [150] = SDC_QDSD_PINGROUP(sdc1_rclk, 0x599000, 15, 0), + [151] = SDC_QDSD_PINGROUP(sdc1_clk, 0x599000, 13, 6), + [152] = SDC_QDSD_PINGROUP(sdc1_cmd, 0x599000, 11, 3), + [153] = SDC_QDSD_PINGROUP(sdc1_data, 0x599000, 9, 0), + [154] = SDC_QDSD_PINGROUP(sdc2_clk, 0x99a000, 14, 6), + [155] = SDC_QDSD_PINGROUP(sdc2_cmd, 0x99a000, 11, 3), + [156] = SDC_QDSD_PINGROUP(sdc2_data, 0x99a000, 9, 0), + [157] = UFS_RESET(ufs_reset, 0x99d000), +}; +static struct msm_dir_conn sdm670_dir_conn[] = { + {1, 510}, + {3, 511}, + {5, 512}, + {10, 513}, + {11, 514}, + {20, 515}, + {22, 516}, + {24, 517}, + {26, 518}, + {30, 519}, + {31, 632}, + {32, 521}, + {34, 522}, + {36, 523}, + {37, 524}, + {38, 525}, + {39, 526}, + {40, 527}, + {41, 630}, + {43, 529}, + {44, 530}, + {46, 531}, + {48, 532}, + {49, 633}, + {52, 534}, + {53, 535}, + {54, 536}, + {56, 537}, + {57, 538}, + {66, 546}, + {68, 547}, + {77, 550}, + {78, 551}, + {79, 552}, + {80, 553}, + {84, 554}, + {85, 555}, + {86, 556}, + {88, 557}, + {89, 631}, + {91, 559}, + {92, 560}, + {95, 561}, + {96, 562}, + {97, 563}, + {101, 564}, + {103, 565}, + {108, 567}, + {112, 568}, + {113, 569}, + {115, 570}, + {116, 571}, + {117, 572}, + {118, 573}, + {119, 609}, + {120, 610}, + {121, 611}, + {122, 612}, + {123, 613}, + {124, 614}, + {125, 615}, + {126, 616}, + {127, 617}, + {128, 618}, + {129, 619}, + {130, 620}, + {132, 621}, + {133, 622}, + {145, 623}, + {0, 216}, + {0, 215}, + {0, 214}, + {0, 213}, + {0, 212}, + {0, 211}, + {0, 210}, + {0, 209}, +}; + +static const struct msm_pinctrl_soc_data sdm670_pinctrl = { + .pins = sdm670_pins, + .npins = ARRAY_SIZE(sdm670_pins), + .functions = sdm670_functions, + .nfunctions = ARRAY_SIZE(sdm670_functions), + .groups = sdm670_groups, + .ngroups = ARRAY_SIZE(sdm670_groups), + .ngpios = 150, + .dir_conn = sdm670_dir_conn, +}; + +static int sdm670_pinctrl_probe(struct platform_device *pdev) +{ + return msm_pinctrl_probe(pdev, &sdm670_pinctrl); +} + +static const struct of_device_id sdm670_pinctrl_of_match[] = { + { .compatible = "qcom,sdm670-pinctrl", }, + { }, +}; + +static struct platform_driver sdm670_pinctrl_driver = { + .driver = { + .name = "sdm670-pinctrl", + .of_match_table = sdm670_pinctrl_of_match, + }, + .probe = sdm670_pinctrl_probe, + .remove = msm_pinctrl_remove, +}; + +static int __init sdm670_pinctrl_init(void) +{ + return platform_driver_register(&sdm670_pinctrl_driver); +} +arch_initcall(sdm670_pinctrl_init); + +static void __exit sdm670_pinctrl_exit(void) +{ + platform_driver_unregister(&sdm670_pinctrl_driver); +} +module_exit(sdm670_pinctrl_exit); + +MODULE_DESCRIPTION("QTI sdm670 pinctrl driver"); +MODULE_LICENSE("GPL v2"); +MODULE_DEVICE_TABLE(of, sdm670_pinctrl_of_match); diff --git a/drivers/pinctrl/qcom/pinctrl-spmi-gpio.c b/drivers/pinctrl/qcom/pinctrl-spmi-gpio.c index 1235a36b22d1..8b51e5ab9e90 100644 --- a/drivers/pinctrl/qcom/pinctrl-spmi-gpio.c +++ b/drivers/pinctrl/qcom/pinctrl-spmi-gpio.c @@ -16,6 +16,7 @@ #include #include #include +#include #include #include @@ -812,8 +813,17 @@ static int pmic_gpio_restore(struct device *dev) return ret; } +static int pmic_gpio_resume(struct device *dev) +{ + if (pm_suspend_via_firmware()) + return pmic_gpio_restore(dev); + + return 0; +} + static const struct dev_pm_ops pmic_gpio_pm_ops = { .restore = pmic_gpio_restore, + .resume = pmic_gpio_resume, }; #else static const struct dev_pm_ops pmic_gpio_pm_ops = {}; diff --git a/drivers/platform/msm/ep_pcie/ep_pcie_core.c b/drivers/platform/msm/ep_pcie/ep_pcie_core.c index f6be0184a74d..c4e419f743e2 100644 --- a/drivers/platform/msm/ep_pcie/ep_pcie_core.c +++ b/drivers/platform/msm/ep_pcie/ep_pcie_core.c @@ -302,7 +302,7 @@ static int ep_pcie_reset_init(struct ep_pcie_dev_t *dev) "PCIe V%d: successfully asserted reset for %s\n", dev->rev, reset_info->name); } - EP_PCIE_ERR(dev, "After Reset assert %s\n", + EP_PCIE_DBG(dev, "After Reset assert %s\n", reset_info->name); /* add a 1ms delay to ensure the reset is asserted */ usleep_range(1000, 1005); @@ -325,7 +325,7 @@ static int ep_pcie_reset_init(struct ep_pcie_dev_t *dev) "PCIe V%d: successfully deasserted reset for %s\n", dev->rev, reset_info->name); } - EP_PCIE_ERR(dev, "After Reset de-assert %s\n", + EP_PCIE_DBG(dev, "After Reset de-assert %s\n", reset_info->name); } return 0; @@ -2306,7 +2306,7 @@ int ep_pcie_core_enable_endpoint(enum ep_pcie_options opt) ep_pcie_clk_dump(dev); goto link_fail_pipe_clk_deinit; } else { - EP_PCIE_INFO(dev, "PCIe V%d: PCIe PHY is ready\n", dev->rev); + EP_PCIE_DBG(dev, "PCIe V%d: PCIe PHY is ready\n", dev->rev); } ep_pcie_core_init(dev, false); diff --git a/drivers/platform/msm/ep_pcie/ep_pcie_phy.c b/drivers/platform/msm/ep_pcie/ep_pcie_phy.c index 174fb921b02e..2fa1cc63154a 100644 --- a/drivers/platform/msm/ep_pcie/ep_pcie_phy.c +++ b/drivers/platform/msm/ep_pcie/ep_pcie_phy.c @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-2.0-only /* * Copyright (c) 2015-2018, 2019-2020, The Linux Foundation. All rights reserved. - * Copyright (c) 2022, Qualcomm Innovation Center, Inc. All rights reserved. + * Copyright (c) 2022-2023, Qualcomm Innovation Center, Inc. All rights reserved. */ /* @@ -43,6 +43,10 @@ void ep_pcie_phy_init(struct ep_pcie_dev_t *dev) "PCIe V%d: PHY V%d: Initializing 5nm QMP phy - 100MHz\n", dev->rev, dev->phy_rev); break; + case 8: + EP_PCIE_DBG(dev, + "PCIe V%d: PHY V%d: Initializing 4nm QMP phy - 100MHz\n", + dev->rev, dev->phy_rev); default: EP_PCIE_ERR(dev, "PCIe V%d: Unexpected phy version %d is caught\n", diff --git a/drivers/platform/x86/wmi.c b/drivers/platform/x86/wmi.c index c4f917d45b51..7ce0408d3bfd 100644 --- a/drivers/platform/x86/wmi.c +++ b/drivers/platform/x86/wmi.c @@ -39,7 +39,7 @@ MODULE_LICENSE("GPL"); static LIST_HEAD(wmi_block_list); struct guid_block { - char guid[16]; + guid_t guid; union { char object_id[2]; struct { @@ -124,7 +124,7 @@ static bool find_guid(const char *guid_string, struct wmi_block **out) list_for_each_entry(wblock, &wmi_block_list, list) { block = &wblock->gblock; - if (memcmp(block->guid, &guid_input, 16) == 0) { + if (guid_equal(&block->guid, &guid_input)) { if (out) *out = wblock; return true; @@ -133,11 +133,20 @@ static bool find_guid(const char *guid_string, struct wmi_block **out) return false; } +static bool guid_parse_and_compare(const char *string, const guid_t *guid) +{ + guid_t guid_input; + + if (guid_parse(string, &guid_input)) + return false; + + return guid_equal(&guid_input, guid); +} + static const void *find_guid_context(struct wmi_block *wblock, struct wmi_driver *wdriver) { const struct wmi_device_id *id; - guid_t guid_input; if (wblock == NULL || wdriver == NULL) return NULL; @@ -146,9 +155,7 @@ static const void *find_guid_context(struct wmi_block *wblock, id = wdriver->id_table; while (*id->guid_string) { - if (guid_parse(id->guid_string, &guid_input)) - continue; - if (!memcmp(wblock->gblock.guid, &guid_input, 16)) + if (guid_parse_and_compare(id->guid_string, &wblock->gblock.guid)) return id->context; id++; } @@ -460,7 +467,7 @@ EXPORT_SYMBOL_GPL(wmi_set_block); static void wmi_dump_wdg(const struct guid_block *g) { - pr_info("%pUL:\n", g->guid); + pr_info("%pUL:\n", &g->guid); if (g->flags & ACPI_WMI_EVENT) pr_info("\tnotify_id: 0x%02X\n", g->notify_id); else @@ -542,7 +549,7 @@ wmi_notify_handler handler, void *data) list_for_each_entry(block, &wmi_block_list, list) { acpi_status wmi_status; - if (memcmp(block->gblock.guid, &guid_input, 16) == 0) { + if (guid_equal(&block->gblock.guid, &guid_input)) { if (block->handler && block->handler != wmi_notify_debug) return AE_ALREADY_ACQUIRED; @@ -582,7 +589,7 @@ acpi_status wmi_remove_notify_handler(const char *guid) list_for_each_entry(block, &wmi_block_list, list) { acpi_status wmi_status; - if (memcmp(block->gblock.guid, &guid_input, 16) == 0) { + if (guid_equal(&block->gblock.guid, &guid_input)) { if (!block->handler || block->handler == wmi_notify_debug) return AE_NULL_ENTRY; @@ -618,7 +625,6 @@ acpi_status wmi_get_event_data(u32 event, struct acpi_buffer *out) { struct acpi_object_list input; union acpi_object params[1]; - struct guid_block *gblock; struct wmi_block *wblock; input.count = 1; @@ -627,7 +633,7 @@ acpi_status wmi_get_event_data(u32 event, struct acpi_buffer *out) params[0].integer.value = event; list_for_each_entry(wblock, &wmi_block_list, list) { - gblock = &wblock->gblock; + struct guid_block *gblock = &wblock->gblock; if ((gblock->flags & ACPI_WMI_EVENT) && (gblock->notify_id == event)) @@ -693,7 +699,7 @@ static ssize_t modalias_show(struct device *dev, struct device_attribute *attr, { struct wmi_block *wblock = dev_to_wblock(dev); - return sprintf(buf, "wmi:%pUL\n", wblock->gblock.guid); + return sprintf(buf, "wmi:%pUL\n", &wblock->gblock.guid); } static DEVICE_ATTR_RO(modalias); @@ -702,7 +708,7 @@ static ssize_t guid_show(struct device *dev, struct device_attribute *attr, { struct wmi_block *wblock = dev_to_wblock(dev); - return sprintf(buf, "%pUL\n", wblock->gblock.guid); + return sprintf(buf, "%pUL\n", &wblock->gblock.guid); } static DEVICE_ATTR_RO(guid); @@ -785,10 +791,10 @@ static int wmi_dev_uevent(struct device *dev, struct kobj_uevent_env *env) { struct wmi_block *wblock = dev_to_wblock(dev); - if (add_uevent_var(env, "MODALIAS=wmi:%pUL", wblock->gblock.guid)) + if (add_uevent_var(env, "MODALIAS=wmi:%pUL", &wblock->gblock.guid)) return -ENOMEM; - if (add_uevent_var(env, "WMI_GUID=%pUL", wblock->gblock.guid)) + if (add_uevent_var(env, "WMI_GUID=%pUL", &wblock->gblock.guid)) return -ENOMEM; return 0; @@ -811,11 +817,7 @@ static int wmi_dev_match(struct device *dev, struct device_driver *driver) return 0; while (*id->guid_string) { - guid_t driver_guid; - - if (WARN_ON(guid_parse(id->guid_string, &driver_guid))) - continue; - if (!memcmp(&driver_guid, wblock->gblock.guid, 16)) + if (guid_parse_and_compare(id->guid_string, &wblock->gblock.guid)) return 1; id++; @@ -1046,7 +1048,6 @@ static const struct device_type wmi_type_data = { }; static int wmi_create_device(struct device *wmi_bus_dev, - const struct guid_block *gblock, struct wmi_block *wblock, struct acpi_device *device) { @@ -1054,12 +1055,12 @@ static int wmi_create_device(struct device *wmi_bus_dev, char method[5]; int result; - if (gblock->flags & ACPI_WMI_EVENT) { + if (wblock->gblock.flags & ACPI_WMI_EVENT) { wblock->dev.dev.type = &wmi_type_event; goto out_init; } - if (gblock->flags & ACPI_WMI_METHOD) { + if (wblock->gblock.flags & ACPI_WMI_METHOD) { wblock->dev.dev.type = &wmi_type_method; mutex_init(&wblock->char_mutex); goto out_init; @@ -1109,7 +1110,7 @@ static int wmi_create_device(struct device *wmi_bus_dev, wblock->dev.dev.bus = &wmi_bus_type; wblock->dev.dev.parent = wmi_bus_dev; - dev_set_name(&wblock->dev.dev, "%pUL", gblock->guid); + dev_set_name(&wblock->dev.dev, "%pUL", &wblock->gblock.guid); device_initialize(&wblock->dev.dev); @@ -1129,12 +1130,12 @@ static void wmi_free_devices(struct acpi_device *device) } } -static bool guid_already_parsed(struct acpi_device *device, const u8 *guid) +static bool guid_already_parsed(struct acpi_device *device, const guid_t *guid) { struct wmi_block *wblock; list_for_each_entry(wblock, &wmi_block_list, list) { - if (memcmp(wblock->gblock.guid, guid, 16) == 0) { + if (guid_equal(&wblock->gblock.guid, guid)) { /* * Because we historically didn't track the relationship * between GUIDs and ACPI nodes, we don't know whether @@ -1189,7 +1190,7 @@ static int parse_wdg(struct device *wmi_bus_dev, struct acpi_device *device) * case yet, so for now, we'll just ignore the duplicate * for device creation. */ - if (guid_already_parsed(device, gblock[i].guid)) + if (guid_already_parsed(device, &gblock[i].guid)) continue; wblock = kzalloc(sizeof(struct wmi_block), GFP_KERNEL); @@ -1201,7 +1202,7 @@ static int parse_wdg(struct device *wmi_bus_dev, struct acpi_device *device) wblock->acpi_device = device; wblock->gblock = gblock[i]; - retval = wmi_create_device(wmi_bus_dev, &gblock[i], wblock, device); + retval = wmi_create_device(wmi_bus_dev, wblock, device); if (retval) { kfree(wblock); continue; @@ -1226,7 +1227,7 @@ static int parse_wdg(struct device *wmi_bus_dev, struct acpi_device *device) retval = device_add(&wblock->dev.dev); if (retval) { dev_err(wmi_bus_dev, "failed to register %pUL\n", - wblock->gblock.guid); + &wblock->gblock.guid); if (debug_event) wmi_method_enable(wblock, 0); list_del(&wblock->list); @@ -1283,12 +1284,11 @@ acpi_wmi_ec_space_handler(u32 function, acpi_physical_address address, static void acpi_wmi_notify_handler(acpi_handle handle, u32 event, void *context) { - struct guid_block *block; struct wmi_block *wblock; bool found_it = false; list_for_each_entry(wblock, &wmi_block_list, list) { - block = &wblock->gblock; + struct guid_block *block = &wblock->gblock; if (wblock->acpi_device->handle == handle && (block->flags & ACPI_WMI_EVENT) && @@ -1334,7 +1334,7 @@ static void acpi_wmi_notify_handler(acpi_handle handle, u32 event, } if (debug_event) - pr_info("DEBUG Event GUID: %pUL\n", wblock->gblock.guid); + pr_info("DEBUG Event GUID: %pUL\n", &wblock->gblock.guid); acpi_bus_generate_netlink_event( wblock->acpi_device->pnp.device_class, diff --git a/drivers/power/supply/qcom/smb23x-charger.c b/drivers/power/supply/qcom/smb23x-charger.c index e80b5fd17417..512f3342ed81 100644 --- a/drivers/power/supply/qcom/smb23x-charger.c +++ b/drivers/power/supply/qcom/smb23x-charger.c @@ -791,7 +791,7 @@ static int smb23x_set_appropriate_usb_current(struct smb23x_chip *chip) static int smb23x_hw_init(struct smb23x_chip *chip) { int rc, i = 0; - u8 tmp; + u8 tmp = 0; rc = smb23x_enable_volatile_writes(chip); if (rc < 0) { diff --git a/drivers/powercap/Kconfig b/drivers/powercap/Kconfig index 8242e8c5ed77..503797b2a1c6 100644 --- a/drivers/powercap/Kconfig +++ b/drivers/powercap/Kconfig @@ -18,10 +18,12 @@ if POWERCAP # Client driver configurations go here. config INTEL_RAPL_CORE tristate + depends on PCI + select IOSF_MBI config INTEL_RAPL tristate "Intel RAPL Support via MSR Interface" - depends on X86 && IOSF_MBI + depends on X86 && PCI select INTEL_RAPL_CORE help This enables support for the Intel Running Average Power Limit (RAPL) diff --git a/drivers/powercap/intel_rapl_msr.c b/drivers/powercap/intel_rapl_msr.c index 1be45f36ab6c..c19e69e77093 100644 --- a/drivers/powercap/intel_rapl_msr.c +++ b/drivers/powercap/intel_rapl_msr.c @@ -22,7 +22,6 @@ #include #include -#include #include #include diff --git a/drivers/pwm/pwm-ab8500.c b/drivers/pwm/pwm-ab8500.c index ad37bc46f272..5fa91f4cda7a 100644 --- a/drivers/pwm/pwm-ab8500.c +++ b/drivers/pwm/pwm-ab8500.c @@ -96,7 +96,7 @@ static int ab8500_pwm_probe(struct platform_device *pdev) int err; if (pdev->id < 1 || pdev->id > 31) - return dev_err_probe(&pdev->dev, EINVAL, "Invalid device id %d\n", pdev->id); + return dev_err_probe(&pdev->dev, -EINVAL, "Invalid device id %d\n", pdev->id); /* * Nothing to be done in probe, this is required to get the diff --git a/drivers/pwm/pwm-imx-tpm.c b/drivers/pwm/pwm-imx-tpm.c index e5e7b7c339a8..7a53bf51964f 100644 --- a/drivers/pwm/pwm-imx-tpm.c +++ b/drivers/pwm/pwm-imx-tpm.c @@ -397,6 +397,13 @@ static int __maybe_unused pwm_imx_tpm_suspend(struct device *dev) if (tpm->enable_count > 0) return -EBUSY; + /* + * Force 'real_period' to be zero to force period update code + * can be executed after system resume back, since suspend causes + * the period related registers to become their reset values. + */ + tpm->real_period = 0; + clk_disable_unprepare(tpm->clk); return 0; diff --git a/drivers/pwm/pwm-mtk-disp.c b/drivers/pwm/pwm-mtk-disp.c index 92ba02cfec92..a581d8adab59 100644 --- a/drivers/pwm/pwm-mtk-disp.c +++ b/drivers/pwm/pwm-mtk-disp.c @@ -79,14 +79,11 @@ static int mtk_disp_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm, if (state->polarity != PWM_POLARITY_NORMAL) return -EINVAL; - if (!state->enabled) { - mtk_disp_pwm_update_bits(mdp, DISP_PWM_EN, mdp->data->enable_mask, - 0x0); - - if (mdp->enabled) { - clk_disable_unprepare(mdp->clk_mm); - clk_disable_unprepare(mdp->clk_main); - } + if (!state->enabled && mdp->enabled) { + mtk_disp_pwm_update_bits(mdp, DISP_PWM_EN, + mdp->data->enable_mask, 0x0); + clk_disable_unprepare(mdp->clk_mm); + clk_disable_unprepare(mdp->clk_main); mdp->enabled = false; return 0; diff --git a/drivers/pwm/sysfs.c b/drivers/pwm/sysfs.c index 9903c3a7eced..b8417a8d2ef9 100644 --- a/drivers/pwm/sysfs.c +++ b/drivers/pwm/sysfs.c @@ -424,6 +424,13 @@ static int pwm_class_resume_npwm(struct device *parent, unsigned int npwm) if (!export) continue; + /* If pwmchip was not enabled before suspend, do nothing. */ + if (!export->suspend.enabled) { + /* release lock taken in pwm_class_get_state */ + mutex_unlock(&export->lock); + continue; + } + state.enabled = export->suspend.enabled; ret = pwm_class_apply_state(export, pwm, &state); if (ret < 0) @@ -448,7 +455,17 @@ static int __maybe_unused pwm_class_suspend(struct device *parent) if (!export) continue; + /* + * If pwmchip was not enabled before suspend, save + * state for resume time and do nothing else. + */ export->suspend = state; + if (!state.enabled) { + /* release lock taken in pwm_class_get_state */ + mutex_unlock(&export->lock); + continue; + } + state.enabled = false; ret = pwm_class_apply_state(export, pwm, &state); if (ret < 0) { diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c index 211ab227b000..ebde10e74434 100644 --- a/drivers/regulator/core.c +++ b/drivers/regulator/core.c @@ -1874,19 +1874,17 @@ static struct regulator *create_regulator(struct regulator_dev *rdev, if (err != -EEXIST) regulator->debugfs = debugfs_create_dir(supply_name, rdev->debugfs); - if (!regulator->debugfs) { + if (IS_ERR(regulator->debugfs)) rdev_dbg(rdev, "Failed to create debugfs directory\n"); - } else { - debugfs_create_u32("uA_load", 0444, regulator->debugfs, - ®ulator->uA_load); - debugfs_create_u32("min_uV", 0444, regulator->debugfs, - ®ulator->voltage[PM_SUSPEND_ON].min_uV); - debugfs_create_u32("max_uV", 0444, regulator->debugfs, - ®ulator->voltage[PM_SUSPEND_ON].max_uV); - debugfs_create_file("constraint_flags", 0444, - regulator->debugfs, regulator, - &constraint_flags_fops); - } + + debugfs_create_u32("uA_load", 0444, regulator->debugfs, + ®ulator->uA_load); + debugfs_create_u32("min_uV", 0444, regulator->debugfs, + ®ulator->voltage[PM_SUSPEND_ON].min_uV); + debugfs_create_u32("max_uV", 0444, regulator->debugfs, + ®ulator->voltage[PM_SUSPEND_ON].max_uV); + debugfs_create_file("constraint_flags", 0444, regulator->debugfs, + regulator, &constraint_flags_fops); /* * Check now if the regulator is an always on regulator - if @@ -5193,10 +5191,8 @@ static void rdev_init_debugfs(struct regulator_dev *rdev) } rdev->debugfs = debugfs_create_dir(rname, debugfs_root); - if (IS_ERR(rdev->debugfs)) { - rdev_warn(rdev, "Failed to create debugfs directory\n"); - return; - } + if (IS_ERR(rdev->debugfs)) + rdev_dbg(rdev, "Failed to create debugfs directory\n"); debugfs_create_u32("use_count", 0444, rdev->debugfs, &rdev->use_count); @@ -6104,7 +6100,7 @@ static int __init regulator_init(void) debugfs_root = debugfs_create_dir("regulator", NULL); if (IS_ERR(debugfs_root)) - pr_warn("regulator: Failed to create debugfs directory\n"); + pr_debug("regulator: Failed to create debugfs directory\n"); #ifdef CONFIG_DEBUG_FS debugfs_create_file("supply_map", 0444, debugfs_root, NULL, diff --git a/drivers/regulator/rpmh-regulator.c b/drivers/regulator/rpmh-regulator.c index 3a221d7a204f..e759035aa886 100644 --- a/drivers/regulator/rpmh-regulator.c +++ b/drivers/regulator/rpmh-regulator.c @@ -236,6 +236,7 @@ struct rpmh_aggr_vreg { bool always_wait_for_ack; bool next_wait_for_ack; bool sleep_request_sent; + bool enable_regulator_deepsleep; struct rpmh_vreg *vreg; int vreg_count; struct rpmh_regulator_mode *mode; @@ -923,6 +924,11 @@ static int rpmh_vreg_send_ds_requests(struct rpmh_aggr_vreg *aggr_vreg) { int rc; + if (!aggr_vreg->enable_regulator_deepsleep) { + pr_debug("clients are handling regulator votes during deepsleep\n"); + return 0; + } + mutex_lock(&aggr_vreg->lock); aggr_vreg->aggr_req_active.valid = 0; @@ -2050,6 +2056,9 @@ static int rpmh_regulator_probe(struct platform_device *pdev) return -EINVAL; } + if (of_find_node_by_name(node, "qcom,regulator_deepsleep")) + aggr_vreg->enable_regulator_deepsleep = true; + if (aggr_vreg->regulator_type == RPMH_REGULATOR_TYPE_ARC) { rc = rpmh_regulator_load_arc_level_mapping(aggr_vreg); if (rc) { diff --git a/drivers/remoteproc/qcom_q6v5_pas.c b/drivers/remoteproc/qcom_q6v5_pas.c index 5724cdc5da85..84bc8c4ac60f 100644 --- a/drivers/remoteproc/qcom_q6v5_pas.c +++ b/drivers/remoteproc/qcom_q6v5_pas.c @@ -1364,6 +1364,17 @@ static const struct adsp_data khaje_adsp_resource = { .ssctl_id = 0x14, }; +static const struct adsp_data qcs605_adsp_resource = { + .crash_reason_smem = 423, + .firmware_name = "adsp.mdt", + .pas_id = 1, + .minidump_id = 5, + .uses_elf64 = false, + .ssr_name = "lpass", + .sysmon_name = "adsp", + .ssctl_id = 0x14, +}; + static const struct adsp_data msm8998_adsp_resource = { .crash_reason_smem = 423, .firmware_name = "adsp.mdt", @@ -1498,6 +1509,17 @@ static const struct adsp_data khaje_cdsp_resource = { .ssctl_id = 0x17, }; +static const struct adsp_data qcs605_cdsp_resource = { + .crash_reason_smem = 601, + .firmware_name = "cdsp.mdt", + .pas_id = 18, + .minidump_id = 7, + .uses_elf64 = false, + .ssr_name = "cdsp", + .sysmon_name = "cdsp", + .ssctl_id = 0x17, +}; + static const struct adsp_data mpss_resource_init = { .crash_reason_smem = 421, .firmware_name = "modem.mdt", @@ -1599,6 +1621,18 @@ static const struct adsp_data khaje_mpss_resource = { .ssctl_id = 0x12, }; +static const struct adsp_data qcs605_mpss_resource = { + .crash_reason_smem = 421, + .firmware_name = "modem.mdt", + .pas_id = 4, + .free_after_auth_reset = true, + .minidump_id = 3, + .uses_elf64 = true, + .ssr_name = "mpss", + .sysmon_name = "modem", + .ssctl_id = 0x12, +}; + static const struct adsp_data slpi_resource_init = { .crash_reason_smem = 424, .firmware_name = "slpi.mdt", @@ -1830,6 +1864,7 @@ static const struct adsp_data lemans_adsp_resource = { .sysmon_name = "adsp", .qmp_name = "adsp", .ssctl_id = 0x14, + .minidump_id = 5, }; static const struct adsp_data lemans_cdsp_resource = { @@ -1843,6 +1878,7 @@ static const struct adsp_data lemans_cdsp_resource = { .sysmon_name = "cdsp", .qmp_name = "cdsp", .ssctl_id = 0x17, + .minidump_id = 19, }; static const struct adsp_data lemans_cdsp1_resource = { @@ -1856,6 +1892,7 @@ static const struct adsp_data lemans_cdsp1_resource = { .sysmon_name = "cdsp1", .qmp_name = "cdsp1", .ssctl_id = 0x20, + .minidump_id = 20, }; static const struct adsp_data lemans_gpdsp0_resource = { @@ -1869,6 +1906,7 @@ static const struct adsp_data lemans_gpdsp0_resource = { .sysmon_name = "gpdsp0", .qmp_name = "gpdsp0", .ssctl_id = 0x21, + .minidump_id = 21, }; static const struct adsp_data lemans_gpdsp1_resource = { @@ -1882,6 +1920,7 @@ static const struct adsp_data lemans_gpdsp1_resource = { .sysmon_name = "gpdsp1", .qmp_name = "gpdsp1", .ssctl_id = 0x22, + .minidump_id = 22, }; static const struct adsp_data kona_adsp_resource = { @@ -1962,7 +2001,7 @@ static const struct adsp_data qcs405_modem_resource = { .pas_id = 6, .has_aggre2_clk = false, .auto_boot = false, - .ssr_name = "wcnss", + .ssr_name = "mpss", .sysmon_name = "wlan", .qmp_name = "wlan", .ssctl_id = 0x12, @@ -2067,6 +2106,9 @@ static const struct of_device_id adsp_of_match[] = { { .compatible = "qcom,trinket-modem-pas", .data = &trinket_modem_resource}, { .compatible = "qcom,trinket-adsp-pas", .data = &trinket_adsp_resource}, { .compatible = "qcom,trinket-cdsp-pas", .data = &trinket_cdsp_resource}, + { .compatible = "qcom,qcs605-adsp-pas", .data = &qcs605_adsp_resource}, + { .compatible = "qcom,qcs605-cdsp-pas", .data = &qcs605_cdsp_resource}, + { .compatible = "qcom,qcs605-modem-pas", .data = &qcs605_mpss_resource}, { }, }; MODULE_DEVICE_TABLE(of, adsp_of_match); diff --git a/drivers/remoteproc/qcom_rproc_slate.c b/drivers/remoteproc/qcom_rproc_slate.c index 533bbe530299..5413d357e72a 100644 --- a/drivers/remoteproc/qcom_rproc_slate.c +++ b/drivers/remoteproc/qcom_rproc_slate.c @@ -571,6 +571,7 @@ int slate_flash_mode(struct qcom_slate *slate_data) static int slate_start(struct rproc *rproc) { struct qcom_slate *slate_data = (struct qcom_slate *)rproc->priv; + struct tzapp_slate_req slate_tz_req; int ret = 0; if (!slate_data) { @@ -584,6 +585,13 @@ static int slate_start(struct rproc *rproc) if (gpio_get_value(slate_data->gpios[0])) { pr_info("Slate is booted up!! Mode: FLASH\n"); slate_data->is_ready = true; + /* Update dump configuration when it boots from FLASH Mode. */ + slate_tz_req.tzapp_slate_cmd = SLATE_RPROC_UP_INFO; + ret = slate_tzapp_comm(slate_data, &slate_tz_req); + if (ret || slate_data->cmd_status) + dev_err(slate_data->dev, + "%s: failed to update dump info %d\n", + __func__, slate_data->cmd_status); return RESULT_SUCCESS; } else return RESULT_FAILURE; @@ -656,8 +664,7 @@ static void slate_coredump(struct rproc *rproc) } } - /* - * This check is added here to make slate dump collection + /* This check is added here to make slate dump collection * decision in RTOS/TWM mode exit. Only way for kernel to know slate state * info(crashed/running)in RTOS/TWM exit is by reading S2A irq line. * When S2A is pulled LOW, it is interpreted as slate crashed state and @@ -670,8 +677,13 @@ static void slate_coredump(struct rproc *rproc) */ if (is_twm_exit()) { + /* reset_cmd signals shutdown on slate, lets ack s2a irq for same + * otherwise it will haunt after slate boot up and crash system. + */ + enable_irq(slate_data->status_irq); + slate_data->is_ready = true; if (!gpio_get_value(slate_data->gpios[0])) { - pr_err("TWM Exit: Collect Dump, slate is CRASHED..!!\n"); + pr_info("TWM Exit: Collect Dump, slate is CRASHED..!!\n"); /* We are assuming that Slate TZapp has started * subsystem_ramdump service. * Introducing delay here for subsystem_ramdump @@ -679,11 +691,27 @@ static void slate_coredump(struct rproc *rproc) */ msleep(5000); } else { - pr_debug("TWM Exit: Skip dump collection, slate is RUNNING ..!!\n"); + pr_info("TWM Exit: Skip dump collection, slate is RUNNING ..!!\n"); /* Send RESET CMD to bring slate out of RTOS state */ + slate_data->cmd_status = 0; slate_tz_req.tzapp_slate_cmd = SLATE_RPROC_RESET; ret = slate_tzapp_comm(slate_data, &slate_tz_req); - return; + if (ret || slate_data->cmd_status) { + dev_err(slate_data->dev, + "%s: Failed to send reset signal to tzapp\n", + __func__); + goto rtos_out; + } + /* By this time if S2A is not pulled then wait for it to go LOW */ + if (gpio_get_value(slate_data->gpios[0])) { + ret = wait_for_err_ready(slate_data); + if (ret) { + dev_err(slate_data->dev, + "[%s:%d]: Timed out waiting for error ready: %s!\n", + current->comm, current->pid, slate_data->firmware_name); + } + } + goto rtos_out; } } rproc_coredump_cleanup(rproc); @@ -756,6 +784,11 @@ shm_free: dma_free: dma_free_attrs(slate_data->dev, size, region, start_addr, attr); + return; +rtos_out: + disable_irq(slate_data->status_irq); + slate_data->is_ready = false; + return; } /** @@ -774,7 +807,6 @@ static int slate_prepare(struct rproc *rproc) __func__); return -EINVAL; } - init_completion(&slate_data->err_ready); if (slate_data->app_status != RESULT_SUCCESS) { ret = load_slate_tzapp(slate_data); if (ret) { @@ -1197,6 +1229,7 @@ static int rproc_slate_driver_probe(struct platform_device *pdev) if (ret) goto destroy_wq; + init_completion(&slate->err_ready); pr_debug("Slate probe is completed\n"); return 0; diff --git a/drivers/remoteproc/qcom_spss.c b/drivers/remoteproc/qcom_spss.c index 645e0e8f6905..08d345c1992f 100644 --- a/drivers/remoteproc/qcom_spss.c +++ b/drivers/remoteproc/qcom_spss.c @@ -40,6 +40,10 @@ #define SP_SCSR_MB1_SP2CL_GP0_ADDR 0x1888020 #define SP_SCSR_MB3_SP2CL_GP0_ADDR 0x188C020 +#define MAX_ROT_DATA_SIZE_IN_BYTES 4096 + +static bool ssr_already_occurred_since_boot; + #define NUM_OF_DEBUG_REGISTERS_READ 0x3 struct spss_data { const char *firmware_name; @@ -298,13 +302,74 @@ static bool check_status(struct qcom_spss *spss, int *ret_error) return false; } +static int manage_unused_pil_region_memory(struct qcom_spss *spss) +{ + unsigned int src_vmid_list; + struct qcom_scm_vmperm newvm[2]; + u8 *spss_rot_data; + int res; + + spss_rot_data = kcalloc(MAX_ROT_DATA_SIZE_IN_BYTES, sizeof(*spss_rot_data), GFP_KERNEL); + if (!spss_rot_data) + return -ENOMEM; + + /* + * When assigning memory to different ownership, previous data is erased, + * ROT data needs to remain in SPSS region as written by SPSS before. + */ + memcpy(spss_rot_data, + (uint8_t *)(uintptr_t)(spss->mem_region+spss->mem_size-MAX_ROT_DATA_SIZE_IN_BYTES), + MAX_ROT_DATA_SIZE_IN_BYTES); + + src_vmid_list = BIT(QCOM_SCM_VMID_HLOS); + + newvm[0].vmid = QCOM_SCM_VMID_HLOS; + newvm[0].perm = QCOM_SCM_PERM_RW; + newvm[1].vmid = QCOM_SCM_VMID_CP_SPSS_SP; + newvm[1].perm = QCOM_SCM_PERM_RW; + + res = qcom_scm_assign_mem(spss->mem_phys + spss->mem_size - MAX_ROT_DATA_SIZE_IN_BYTES, + MAX_ROT_DATA_SIZE_IN_BYTES, &src_vmid_list, newvm, 2); + if (res) { + dev_err(spss->dev, "qcom_scm_assign_mem failed %d\n", res); + kfree(spss_rot_data); + return res; + } + + memcpy((uint8_t *)(uintptr_t)(spss->mem_region+spss->mem_size-MAX_ROT_DATA_SIZE_IN_BYTES), + spss_rot_data, MAX_ROT_DATA_SIZE_IN_BYTES); + + kfree(spss_rot_data); + return res; +} + static int spss_load(struct rproc *rproc, const struct firmware *fw) { struct qcom_spss *spss = (struct qcom_spss *)rproc->priv; + int res; - return qcom_mdt_load(spss->dev, fw, rproc->firmware, spss->pas_id, + res = qcom_mdt_load(spss->dev, fw, rproc->firmware, spss->pas_id, spss->mem_region, spss->mem_phys, spss->mem_size, &spss->mem_reloc); + + if (res) { + dev_err(spss->dev, "qcom_mdt_load of SPSS image failed, error value %d\n", res); + return res; + } + + /* + * During SSR only PIL memory is released. + * If an SSR already occurred, the memory beyond image_size + * remains assigned since PIL didn't own it. + */ + if (!ssr_already_occurred_since_boot) { + res = manage_unused_pil_region_memory(spss); + /* Set to true only if memory was successfully assigned*/ + if (!res) + ssr_already_occurred_since_boot = true; + } + + return res; } static int spss_stop(struct rproc *rproc) diff --git a/drivers/rpmsg/qcom_glink_native.c b/drivers/rpmsg/qcom_glink_native.c index 110ad760bc11..9064c136cbe9 100644 --- a/drivers/rpmsg/qcom_glink_native.c +++ b/drivers/rpmsg/qcom_glink_native.c @@ -756,6 +756,9 @@ static int qcom_glink_rx_done(struct rpmsg_endpoint *ept, void *data) list_for_each_entry_safe(intent, tmp, &channel->defer_intents, node) { if (intent->data == data) { list_del(&intent->node); + if (!intent->reuse) + idr_remove(&channel->liids, intent->id); + spin_unlock_irqrestore(&channel->intent_lock, flags); qcom_glink_send_rx_done(glink, channel, intent, true); diff --git a/drivers/rpmsg/qcom_glink_native.h b/drivers/rpmsg/qcom_glink_native.h index b2c9be7e4dcf..d26410ba79f5 100644 --- a/drivers/rpmsg/qcom_glink_native.h +++ b/drivers/rpmsg/qcom_glink_native.h @@ -11,7 +11,7 @@ #define GLINK_FEATURE_TRACER_PKT BIT(2) #define GLINK_FEATURE_ZERO_COPY BIT(3) #define GLINK_FEATURE_ZERO_COPY_POOLS BIT(4) - +#define GLINK_FEATURE_SHORT_CMD BIT(8) struct qcom_glink_pipe { size_t length; diff --git a/drivers/rpmsg/qcom_glink_slatecom.c b/drivers/rpmsg/qcom_glink_slatecom.c index b04dde6ec154..8b832e76b3df 100644 --- a/drivers/rpmsg/qcom_glink_slatecom.c +++ b/drivers/rpmsg/qcom_glink_slatecom.c @@ -29,7 +29,7 @@ #include "rpmsg_internal.h" #include "qcom_glink_native.h" -#define GLINK_LOG_PAGE_CNT 2 +#define GLINK_LOG_PAGE_CNT 32 #define GLINK_INFO(ctxt, x, ...) \ ipc_log_string(ctxt->ilc, "[%s]: "x, __func__, ##__VA_ARGS__) @@ -50,7 +50,7 @@ do { \ #define SLATECOM_ALIGNMENT 16 #define TX_BLOCKED_CMD_RESERVE 16 #define DEFAULT_FIFO_SIZE 1024 -#define SHORT_SIZE 16 +#define SHORT_SIZE 96 #define XPRT_ALIGNMENT 4 #define ACTIVE_TX BIT(0) @@ -488,23 +488,31 @@ static void glink_slatecom_tx_write(struct glink_slatecom *glink, void *data, size_t dlen) { int ret; + static uint32_t tx_short_cnt; /* packet tx_counter 12 to 15 bytes: field "param4" in "glink_slatecom_msg" * is available to use Hence, using this (Last 4 bytes) field for tx_counter. */ - *(uint32_t *)(data + 12) = ++(glink->tx_counter); + if (*(uint8_t *)(data) != SLATECOM_CMD_TX_SHORT_DATA) + *(uint32_t *)(data + 12) = ++(glink->tx_counter); + else + tx_short_cnt = tx_short_cnt + 1; if (dlen) { ret = glink_slatecom_tx_write_one(glink, data, dlen); if (ret < 0) { GLINK_ERR(glink, "Error %d writing tx data\n", ret); - glink->tx_counter = glink->tx_counter - 1; + if (*(uint8_t *)(data) != SLATECOM_CMD_TX_SHORT_DATA) + glink->tx_counter = glink->tx_counter - 1; + else + tx_short_cnt = tx_short_cnt - 1; return; } } - GLINK_INFO(glink, "Packet tx_counter = %d\n", glink->tx_counter); + GLINK_INFO(glink, "Packet tx_counter = %d, tx_short_cnt = %d\n", + glink->tx_counter, tx_short_cnt); } static void glink_slatecom_send_read_notify(struct glink_slatecom *glink) @@ -759,32 +767,51 @@ static int glink_slatecom_send_final(struct glink_slatecom_channel *channel, { int rc; struct glink_slatecom *glink = channel->glink; + u32 command_size = 0; + struct { struct glink_slatecom_msg msg; __le32 chunk_size; __le32 left_size; uint64_t addr; - } __packed req; + } __packed req_data; - memset(&req, 0, sizeof(req)); + struct { + struct glink_slatecom_msg msg; + u8 data[SHORT_SIZE]; + } __packed req_short; - CH_INFO(channel, "size:%d, wait:%d\n", len, wait); + memset(&req_data, 0, sizeof(req_data)); + memset(&req_short, 0, sizeof(req_short)); - if (len) { + CH_INFO(channel, "[lcid:id][%d:%d]size:%d, wait:%d\n", + cpu_to_le16(channel->lcid), cpu_to_le32(intent->id), len, wait); + + + if ((len <= SHORT_SIZE) && (glink->features & GLINK_FEATURE_SHORT_CMD)) { + req_short.msg.cmd = cpu_to_le16(SLATECOM_CMD_TX_SHORT_DATA); + req_short.msg.param1 = cpu_to_le16(channel->lcid); + req_short.msg.param2 = cpu_to_le32(intent->id); + req_short.msg.param3 = cpu_to_le32(len); + req_short.msg.param4 = cpu_to_be32(0); + memcpy(req_short.data, data, len); + command_size += (sizeof(req_short.msg) + ALIGN(len, XPRT_ALIGNMENT)) / WORD_SIZE; + } else { if (intent->offset) - req.msg.cmd = cpu_to_le16(SLATECOM_CMD_TX_DATA_CONT); + req_data.msg.cmd = cpu_to_le16(SLATECOM_CMD_TX_DATA_CONT); else - req.msg.cmd = cpu_to_le16(SLATECOM_CMD_TX_DATA); + req_data.msg.cmd = cpu_to_le16(SLATECOM_CMD_TX_DATA); - req.msg.param1 = cpu_to_le16(channel->lcid); - req.msg.param2 = cpu_to_le32(intent->id); - req.chunk_size = cpu_to_le32(len); - req.left_size = cpu_to_le32(0); - req.addr = 0; + req_data.msg.param1 = cpu_to_le16(channel->lcid); + req_data.msg.param2 = cpu_to_le32(intent->id); + req_data.chunk_size = cpu_to_le32(len); + req_data.left_size = cpu_to_le32(0); + req_data.addr = 0; + command_size += sizeof(req_data)/WORD_SIZE; } mutex_lock(&glink->tx_lock); - while (glink_slatecom_tx_avail(glink) < sizeof(req)/WORD_SIZE) { + while (glink_slatecom_tx_avail(glink) < command_size) { if (!wait) { mutex_unlock(&glink->tx_lock); CH_INFO(channel, "failed, please retry size:%d, wait:%d\n", len, wait); @@ -808,24 +835,29 @@ static int glink_slatecom_send_final(struct glink_slatecom_channel *channel, mutex_lock(&glink->tx_lock); - if (glink_slatecom_tx_avail(glink) >= sizeof(req)/WORD_SIZE) + if (glink_slatecom_tx_avail(glink) >= command_size) glink->sent_read_notify = false; } - do { - rc = slatecom_ahb_write_bytes(glink->slatecom_handle, - (uint32_t)(size_t)(intent->addr + intent->offset), - len, data); - if (rc < 0) { - GLINK_ERR(glink, "%s: Error %d writing data\n", + if (len > SHORT_SIZE) { + do { + rc = slatecom_ahb_write_bytes(glink->slatecom_handle, + (uint32_t)(size_t)(intent->addr + intent->offset), + len, data); + if (rc < 0) { + GLINK_ERR(glink, "%s: Error %d writing data\n", __func__, rc); - if (rc == -ECANCELED) - usleep_range(TX_WAIT_US, TX_WAIT_US + 1000); - } - } while (rc == -ECANCELED); + if (rc == -ECANCELED) + usleep_range(TX_WAIT_US, TX_WAIT_US + 1000); + } + } while (rc == -ECANCELED); - intent->offset += len; - glink_slatecom_tx_write(glink, &req, sizeof(req)); + intent->offset += len; + glink_slatecom_tx_write(glink, &req_data, sizeof(req_data)); + } else { + glink_slatecom_tx_write(glink, &req_short, + sizeof(req_short.msg) + ALIGN(len, XPRT_ALIGNMENT)); + } mutex_unlock(&glink->tx_lock); return 0; @@ -1816,21 +1848,31 @@ static int glink_slatecom_rx_short_data(struct glink_slatecom *glink, { struct glink_slatecom_rx_intent *intent; struct glink_slatecom_channel *channel; - size_t msglen = SHORT_SIZE; + size_t msglen = chunk_size; unsigned long flags; + static uint32_t rx_short_cnt; + + if (!(glink->features & GLINK_FEATURE_SHORT_CMD)) { + dev_err(glink->dev, "Short command feature not supported\n"); + return msglen; + } if (avail < msglen) { - dev_dbg(glink->dev, "Not enough data in fifo\n"); + dev_err(glink->dev, "Not enough data in fifo\n"); return avail; } mutex_lock(&glink->idr_lock); channel = idr_find(&glink->rcids, rcid); mutex_unlock(&glink->idr_lock); + + rx_short_cnt = rx_short_cnt + 1; + if (!channel) { dev_dbg(glink->dev, "Data on non-existing channel\n"); return msglen; } - CH_INFO(channel, "chunk_size:%d left_size:%d\n", chunk_size, left_size); + CH_INFO(channel, "[rcid:liid][%d:%d] rx_short_cnt:%d chunk_size:%d left_size:%d\n", + rcid, liid, rx_short_cnt, chunk_size, left_size); mutex_lock(&channel->intent_lock); intent = idr_find(&channel->liids, liid); @@ -1987,7 +2029,8 @@ static int glink_slatecom_process_cmd(struct glink_slatecom *glink, void *rx_dat while (offset < rx_size) { if (rx_size - offset < sizeof(struct glink_slatecom_msg)) { ret = -EBADMSG; - GLINK_ERR(glink, "%s: Error %d process cmd\n", __func__, ret); + GLINK_ERR(glink, "%s: Error %d process cmd for offset:%d rx_size:%d\n", + __func__, ret, offset, rx_size); return ret; } @@ -1999,10 +2042,12 @@ static int glink_slatecom_process_cmd(struct glink_slatecom *glink, void *rx_dat param2 = le32_to_cpu(msg->param2); param3 = le32_to_cpu(msg->param3); param4 = le32_to_cpu(msg->param4); - glink->rx_counter = glink->rx_counter + 1; - GLINK_INFO(glink, "Packet count local %d remote %d\n", - glink->rx_counter, param3); + if (cmd != SLATECOM_CMD_TX_SHORT_DATA) { + glink->rx_counter = glink->rx_counter + 1; + GLINK_INFO(glink, "Packet count local %d remote %d\n", + glink->rx_counter, param3); + } switch (cmd) { case SLATECOM_CMD_VERSION: @@ -2046,7 +2091,8 @@ static int glink_slatecom_process_cmd(struct glink_slatecom *glink, void *rx_dat param3, param4, rx_data + offset, rx_size - offset); - offset += ALIGN(ret, SLATECOM_ALIGNMENT); + /* 4 bytes alignment for short command */ + offset += ALIGN(ret, XPRT_ALIGNMENT); break; case SLATECOM_CMD_READ_NOTIF: break; @@ -2346,7 +2392,7 @@ int glink_slatecom_probe(struct platform_device *pdev) if (ret < 0) glink->name = dev->of_node->name; - glink->features = GLINK_FEATURE_INTENT_REUSE; + glink->features = GLINK_FEATURE_INTENT_REUSE | GLINK_FEATURE_SHORT_CMD; mutex_init(&glink->tx_lock); mutex_init(&glink->tx_avail_lock); diff --git a/drivers/rtc/rtc-st-lpc.c b/drivers/rtc/rtc-st-lpc.c index 0f8e4231098e..d04d46f9cc65 100644 --- a/drivers/rtc/rtc-st-lpc.c +++ b/drivers/rtc/rtc-st-lpc.c @@ -228,7 +228,7 @@ static int st_rtc_probe(struct platform_device *pdev) enable_irq_wake(rtc->irq); disable_irq(rtc->irq); - rtc->clk = clk_get(&pdev->dev, NULL); + rtc->clk = devm_clk_get(&pdev->dev, NULL); if (IS_ERR(rtc->clk)) { dev_err(&pdev->dev, "Unable to request clock\n"); return PTR_ERR(rtc->clk); diff --git a/drivers/s390/net/qeth_l3_sys.c b/drivers/s390/net/qeth_l3_sys.c index 1082380b21f8..dba9b307020c 100644 --- a/drivers/s390/net/qeth_l3_sys.c +++ b/drivers/s390/net/qeth_l3_sys.c @@ -652,7 +652,7 @@ static QETH_DEVICE_ATTR(vipa_add4, add4, 0644, static ssize_t qeth_l3_dev_vipa_del4_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { - return qeth_l3_vipa_store(dev, buf, true, count, QETH_PROT_IPV4); + return qeth_l3_vipa_store(dev, buf, false, count, QETH_PROT_IPV4); } static QETH_DEVICE_ATTR(vipa_del4, del4, 0200, NULL, diff --git a/drivers/scsi/3w-xxxx.c b/drivers/scsi/3w-xxxx.c index 4ee485ab2714..678c8ca4f699 100644 --- a/drivers/scsi/3w-xxxx.c +++ b/drivers/scsi/3w-xxxx.c @@ -2305,8 +2305,10 @@ static int tw_probe(struct pci_dev *pdev, const struct pci_device_id *dev_id) TW_DISABLE_INTERRUPTS(tw_dev); /* Initialize the card */ - if (tw_reset_sequence(tw_dev)) + if (tw_reset_sequence(tw_dev)) { + retval = -EINVAL; goto out_release_mem_region; + } /* Set host specific parameters */ host->max_id = TW_MAX_UNITS; diff --git a/drivers/scsi/qedf/qedf_main.c b/drivers/scsi/qedf/qedf_main.c index fa49a3e52a9b..cf10c1a60399 100644 --- a/drivers/scsi/qedf/qedf_main.c +++ b/drivers/scsi/qedf/qedf_main.c @@ -3046,9 +3046,8 @@ static int qedf_alloc_global_queues(struct qedf_ctx *qedf) * addresses of our queues */ if (!qedf->p_cpuq) { - status = -EINVAL; QEDF_ERR(&qedf->dbg_ctx, "p_cpuq is NULL.\n"); - goto mem_alloc_failure; + return -EINVAL; } qedf->global_queues = kzalloc((sizeof(struct global_queue *) diff --git a/drivers/scsi/qla2xxx/qla_attr.c b/drivers/scsi/qla2xxx/qla_attr.c index b6a427f0570e..de57d45ffc5c 100644 --- a/drivers/scsi/qla2xxx/qla_attr.c +++ b/drivers/scsi/qla2xxx/qla_attr.c @@ -2738,6 +2738,7 @@ static void qla2x00_terminate_rport_io(struct fc_rport *rport) { fc_port_t *fcport = *(fc_port_t **)rport->dd_data; + scsi_qla_host_t *vha; if (!fcport) return; @@ -2747,9 +2748,12 @@ qla2x00_terminate_rport_io(struct fc_rport *rport) if (test_bit(ABORT_ISP_ACTIVE, &fcport->vha->dpc_flags)) return; + vha = fcport->vha; if (unlikely(pci_channel_offline(fcport->vha->hw->pdev))) { qla2x00_abort_all_cmds(fcport->vha, DID_NO_CONNECT << 16); + qla2x00_eh_wait_for_pending_commands(fcport->vha, fcport->d_id.b24, + 0, WAIT_TARGET); return; } /* @@ -2774,6 +2778,15 @@ qla2x00_terminate_rport_io(struct fc_rport *rport) qla2x00_port_logout(fcport->vha, fcport); } } + + /* check for any straggling io left behind */ + if (qla2x00_eh_wait_for_pending_commands(fcport->vha, fcport->d_id.b24, 0, WAIT_TARGET)) { + ql_log(ql_log_warn, vha, 0x300b, + "IO not return. Resetting. \n"); + set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags); + qla2xxx_wake_dpc(vha); + qla2x00_wait_for_chip_reset(vha); + } } static int diff --git a/drivers/scsi/qla2xxx/qla_bsg.c b/drivers/scsi/qla2xxx/qla_bsg.c index c7c5c013a074..5db43b6b76c5 100644 --- a/drivers/scsi/qla2xxx/qla_bsg.c +++ b/drivers/scsi/qla2xxx/qla_bsg.c @@ -283,6 +283,10 @@ qla2x00_process_els(struct bsg_job *bsg_job) if (bsg_request->msgcode == FC_BSG_RPT_ELS) { rport = fc_bsg_to_rport(bsg_job); + if (!rport) { + rval = -ENOMEM; + goto done; + } fcport = *(fc_port_t **) rport->dd_data; host = rport_to_shost(rport); vha = shost_priv(host); @@ -2899,6 +2903,8 @@ qla24xx_bsg_request(struct bsg_job *bsg_job) if (bsg_request->msgcode == FC_BSG_RPT_ELS) { rport = fc_bsg_to_rport(bsg_job); + if (!rport) + return ret; host = rport_to_shost(rport); vha = shost_priv(host); } else { diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h index 5b499b0e2c86..e674d3fb5926 100644 --- a/drivers/scsi/qla2xxx/qla_def.h +++ b/drivers/scsi/qla2xxx/qla_def.h @@ -676,7 +676,6 @@ typedef struct srb { struct iocb_resource iores; struct kref cmd_kref; /* need to migrate ref_count over to this */ void *priv; - wait_queue_head_t nvme_ls_waitq; struct fc_port *fcport; struct scsi_qla_host *vha; unsigned int start_timer:1; diff --git a/drivers/scsi/qla2xxx/qla_edif.c b/drivers/scsi/qla2xxx/qla_edif.c index f81cf85dcdc7..40a03f9c2d21 100644 --- a/drivers/scsi/qla2xxx/qla_edif.c +++ b/drivers/scsi/qla2xxx/qla_edif.c @@ -2230,8 +2230,8 @@ qla24xx_issue_sa_replace_iocb(scsi_qla_host_t *vha, struct qla_work_evt *e) if (!sa_ctl) { ql_dbg(ql_dbg_edif, vha, 0x70e6, "sa_ctl allocation failed\n"); - rval = -ENOMEM; - goto done; + rval = -ENOMEM; + return rval; } fcport = sa_ctl->fcport; diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c index ded027fe2924..37cb469dc925 100644 --- a/drivers/scsi/qla2xxx/qla_init.c +++ b/drivers/scsi/qla2xxx/qla_init.c @@ -5359,7 +5359,7 @@ static void qla_get_login_template(scsi_qla_host_t *vha) __be32 *q; memset(ha->init_cb, 0, ha->init_cb_size); - sz = min_t(int, sizeof(struct fc_els_flogi), ha->init_cb_size); + sz = min_t(int, sizeof(struct fc_els_csp), ha->init_cb_size); rval = qla24xx_get_port_login_templ(vha, ha->init_cb_dma, ha->init_cb, sz); if (rval != QLA_SUCCESS) { diff --git a/drivers/scsi/qla2xxx/qla_inline.h b/drivers/scsi/qla2xxx/qla_inline.h index b0ee307b5d4b..a034699e58ae 100644 --- a/drivers/scsi/qla2xxx/qla_inline.h +++ b/drivers/scsi/qla2xxx/qla_inline.h @@ -109,11 +109,13 @@ qla2x00_set_fcport_disc_state(fc_port_t *fcport, int state) { int old_val; uint8_t shiftbits, mask; + uint8_t port_dstate_str_sz; /* This will have to change when the max no. of states > 16 */ shiftbits = 4; mask = (1 << shiftbits) - 1; + port_dstate_str_sz = sizeof(port_dstate_str) / sizeof(char *); fcport->disc_state = state; while (1) { old_val = atomic_read(&fcport->shadow_disc_state); @@ -121,7 +123,8 @@ qla2x00_set_fcport_disc_state(fc_port_t *fcport, int state) old_val, (old_val << shiftbits) | state)) { ql_dbg(ql_dbg_disc, fcport->vha, 0x2134, "FCPort %8phC disc_state transition: %s to %s - portid=%06x.\n", - fcport->port_name, port_dstate_str[old_val & mask], + fcport->port_name, (old_val & mask) < port_dstate_str_sz ? + port_dstate_str[old_val & mask] : "Unknown", port_dstate_str[state], fcport->d_id.b24); return; } diff --git a/drivers/scsi/qla2xxx/qla_iocb.c b/drivers/scsi/qla2xxx/qla_iocb.c index 4f48f098ea5a..7a4298388ef1 100644 --- a/drivers/scsi/qla2xxx/qla_iocb.c +++ b/drivers/scsi/qla2xxx/qla_iocb.c @@ -603,7 +603,8 @@ qla24xx_build_scsi_type_6_iocbs(srb_t *sp, struct cmd_type_6 *cmd_pkt, put_unaligned_le32(COMMAND_TYPE_6, &cmd_pkt->entry_type); /* No data transfer */ - if (!scsi_bufflen(cmd) || cmd->sc_data_direction == DMA_NONE) { + if (!scsi_bufflen(cmd) || cmd->sc_data_direction == DMA_NONE || + tot_dsds == 0) { cmd_pkt->byte_count = cpu_to_le32(0); return 0; } @@ -3898,7 +3899,7 @@ qla2x00_start_sp(srb_t *sp) pkt = __qla2x00_alloc_iocbs(sp->qpair, sp); if (!pkt) { - rval = EAGAIN; + rval = -EAGAIN; ql_log(ql_log_warn, vha, 0x700c, "qla2x00_alloc_iocbs failed.\n"); goto done; diff --git a/drivers/scsi/qla2xxx/qla_nvme.c b/drivers/scsi/qla2xxx/qla_nvme.c index 98edab687c13..53a54e8a4d97 100644 --- a/drivers/scsi/qla2xxx/qla_nvme.c +++ b/drivers/scsi/qla2xxx/qla_nvme.c @@ -355,7 +355,6 @@ static int qla_nvme_ls_req(struct nvme_fc_local_port *lport, if (rval != QLA_SUCCESS) { ql_log(ql_log_warn, vha, 0x700e, "qla2x00_start_sp failed = %d\n", rval); - wake_up(&sp->nvme_ls_waitq); sp->priv = NULL; priv->sp = NULL; qla2x00_rel_sp(sp); @@ -637,7 +636,6 @@ static int qla_nvme_post_cmd(struct nvme_fc_local_port *lport, if (!sp) return -EBUSY; - init_waitqueue_head(&sp->nvme_ls_waitq); kref_init(&sp->cmd_kref); spin_lock_init(&priv->cmd_lock); sp->priv = priv; @@ -656,7 +654,6 @@ static int qla_nvme_post_cmd(struct nvme_fc_local_port *lport, if (rval != QLA_SUCCESS) { ql_log(ql_log_warn, vha, 0x212d, "qla2x00_start_nvme_mq failed = %d\n", rval); - wake_up(&sp->nvme_ls_waitq); sp->priv = NULL; priv->sp = NULL; qla2xxx_rel_qpair_sp(sp->qpair, sp); diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c index 2efe31327ed1..30325fd4c120 100644 --- a/drivers/scsi/qla2xxx/qla_os.c +++ b/drivers/scsi/qla2xxx/qla_os.c @@ -5042,7 +5042,8 @@ struct scsi_qla_host *qla2x00_create_host(struct scsi_host_template *sht, } INIT_DELAYED_WORK(&vha->scan.scan_work, qla_scan_work_fn); - sprintf(vha->host_str, "%s_%lu", QLA2XXX_DRIVER_NAME, vha->host_no); + snprintf(vha->host_str, sizeof(vha->host_str), "%s_%lu", + QLA2XXX_DRIVER_NAME, vha->host_no); ql_dbg(ql_dbg_init, vha, 0x0041, "Allocated the host=%p hw=%p vha=%p dev_name=%s", vha->host, vha->hw, vha, diff --git a/drivers/scsi/ufs/ufshcd-crypto-qti.c b/drivers/scsi/ufs/ufshcd-crypto-qti.c index 81db691ef9cb..cd17134841f2 100644 --- a/drivers/scsi/ufs/ufshcd-crypto-qti.c +++ b/drivers/scsi/ufs/ufshcd-crypto-qti.c @@ -2,7 +2,7 @@ /* * UFS Crypto ops QTI implementation. * - * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. + * Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved. */ #include @@ -83,7 +83,7 @@ static int ufshcd_crypto_qti_keyslot_program(struct blk_keyslot_manager *ksm, get_mmio_data(&mmio_data, host); err = crypto_qti_keyslot_program(&mmio_data, key, slot, - data_unit_mask, cap_idx); + data_unit_mask, cap_idx, UFS_CE); if (err) pr_err("%s: failed with error %d\n", __func__, err); @@ -115,7 +115,7 @@ static int ufshcd_crypto_qti_keyslot_evict(struct blk_keyslot_manager *ksm, } get_mmio_data(&mmio_data, host); - err = crypto_qti_keyslot_evict(&mmio_data, slot); + err = crypto_qti_keyslot_evict(&mmio_data, slot, UFS_CE); if (err) pr_err("%s: failed with error %d\n", __func__, err); diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c index 264cde1003a1..d4199f3a7dea 100644 --- a/drivers/scsi/ufs/ufshcd.c +++ b/drivers/scsi/ufs/ufshcd.c @@ -7318,6 +7318,20 @@ static int ufshcd_eh_host_reset_handler(struct scsi_cmnd *cmd) hba = shost_priv(cmd->device->host); + /* + * If runtime pm send SSU and got timeout, scsi_error_handler + * stuck at this function to wait for flush_work(&hba->eh_work). + * And ufshcd_err_handler(eh_work) stuck at wait for runtime pm active. + * Do ufshcd_link_recovery instead schedule eh_work can prevent + * dead lock to happen. + */ + if (hba->pm_op_in_progress) { + if (ufshcd_link_recovery(hba)) + err = FAILED; + + return err; + } + spin_lock_irqsave(hba->host->host_lock, flags); hba->force_reset = true; ufshcd_schedule_eh_work(hba); diff --git a/drivers/slimbus/qcom-ngd-ctrl.c b/drivers/slimbus/qcom-ngd-ctrl.c index 6f42aa1c40e5..b249e0a17e48 100644 --- a/drivers/slimbus/qcom-ngd-ctrl.c +++ b/drivers/slimbus/qcom-ngd-ctrl.c @@ -998,17 +998,14 @@ static int qcom_slim_ngd_xfer_msg(struct slim_controller *sctrl, * acquired and is waiting for ctrl_lock. While in parallel for * slim_get_logical_addr request from codecs ctrl_lock is acquired * first followed by qcom_slim_ngd_xfer_msg. - * In qcom_slim_ngd_xfer_msg check if tx lock is already acquired - * as part of SSR/PDR notify and ngd is going down to avoid deadlock - * scenario if there is a get logical address request. + * mutex_trylock will not wait to aquire lock if it is already been + * acquired by SSR sequence hence it will unblock SSR to finish + * gracefully */ - if (mutex_is_locked(&ctrl->tx_lock) && - ctrl->state == QCOM_SLIM_NGD_CTRL_SSR_GOING_DOWN) { - SLIM_ERR(ctrl, "ngd going down due SSR/PDR, try again!\n"); + if (!mutex_trylock(&ctrl->tx_lock)) { + SLIM_ERR(ctrl, "ngd going down due SSR/PDR, try again! skipping check hw state\n"); return -EAGAIN; } - - mutex_lock(&ctrl->tx_lock); ret = check_hw_state(ctrl, txn); if (ret) { SLIM_WARN(ctrl, "ADSP slimbus not up MC:0x%x,mt:0x%x ret:%d\n", @@ -1096,7 +1093,10 @@ static int qcom_slim_ngd_xfer_msg(struct slim_controller *sctrl, memcpy(puc, txn->msg->wbuf, txn->msg->num_bytes); } - mutex_lock(&ctrl->tx_lock); + if (!mutex_trylock(&ctrl->tx_lock)) { + SLIM_ERR(ctrl, "ngd going down due SSR/PDR, try again! skipping tx msg post\n"); + return -EAGAIN; + } ret = qcom_slim_ngd_tx_msg_post(ctrl, pbuf, txn->rl); if (ret) { mutex_unlock(&ctrl->tx_lock); diff --git a/drivers/soc/amlogic/meson-secure-pwrc.c b/drivers/soc/amlogic/meson-secure-pwrc.c index 2eeea5e1b3b7..2f3ca5531fa9 100644 --- a/drivers/soc/amlogic/meson-secure-pwrc.c +++ b/drivers/soc/amlogic/meson-secure-pwrc.c @@ -104,7 +104,7 @@ static struct meson_secure_pwrc_domain_desc a1_pwrc_domains[] = { SEC_PD(ACODEC, 0), SEC_PD(AUDIO, 0), SEC_PD(OTP, 0), - SEC_PD(DMA, 0), + SEC_PD(DMA, GENPD_FLAG_ALWAYS_ON | GENPD_FLAG_IRQ_SAFE), SEC_PD(SD_EMMC, 0), SEC_PD(RAMA, 0), /* SRAMB is used as ATF runtime memory, and should be always on */ diff --git a/drivers/soc/fsl/qe/Kconfig b/drivers/soc/fsl/qe/Kconfig index 357c5800b112..7afa796dbbb8 100644 --- a/drivers/soc/fsl/qe/Kconfig +++ b/drivers/soc/fsl/qe/Kconfig @@ -39,6 +39,7 @@ config QE_TDM config QE_USB bool + depends on QUICC_ENGINE default y if USB_FSL_QE help QE USB Controller support diff --git a/drivers/soc/qcom/crypto-qti-common.c b/drivers/soc/qcom/crypto-qti-common.c index 11b63848b59c..db72a1606fba 100644 --- a/drivers/soc/qcom/crypto-qti-common.c +++ b/drivers/soc/qcom/crypto-qti-common.c @@ -32,8 +32,16 @@ #define CRYPTO_ICE_FDE_KEY_INDEX 31 #define CRYPTO_UD_VOLNAME "userdata" -#define CRYPTO_ICE_FDE_LEGACY_UFS "UFS ICE Full Disk Encryption " -#define CRYPTO_ICE_FDE_LEGACY_EMMC "SDCC ICE Full Disk Encryption " +#define CRYPTO_ICE_HASH_SIZE 32 +#define CRYPTO_ICE_KEY_ID_SIZE 32 + +#define CRYPTO_ICE_FDE_UFS_KEYID "UFS ICE Full Disk Encryption " +#define CRYPTO_ICE_FDE_EMMC_KEYID "SDCC ICE Full Disk Encryption " + +/* add the legacy key_id to support ICE OTA */ +#define CRYPTO_ICE_FDE_UFS_LEGACY_KEYID "UFS ICE Full Disk Encryption" +#define CRYPTO_ICE_FDE_EMMC_LEGACY_KEYID "SDCC ICE Full Disk Encryption" + #define CRYPTO_ICE_UFS_DEV_NAME "ufshcd-qcom" #define CRYPTO_ICE_EMMC_DEV_NAME "sdhci_msm" #define QSEECOM_KEY_ID_EXISTS -65 @@ -404,15 +412,15 @@ EXPORT_SYMBOL(crypto_qti_debug); int crypto_qti_keyslot_program(const struct ice_mmio_data *mmio_data, const struct blk_crypto_key *key, unsigned int slot, - u8 data_unit_mask, int capid) + u8 data_unit_mask, int capid, int storage_type) { int err = 0; err = crypto_qti_program_key(mmio_data, key, slot, - data_unit_mask, capid); + data_unit_mask, capid, storage_type); if (err) { pr_err("%s: program key failed with error %d\n", __func__, err); - err = crypto_qti_invalidate_key(mmio_data, slot); + err = crypto_qti_invalidate_key(mmio_data, slot, storage_type); if (err) { pr_err("%s: invalidate key failed with error %d\n", __func__, err); return err; @@ -424,11 +432,11 @@ int crypto_qti_keyslot_program(const struct ice_mmio_data *mmio_data, EXPORT_SYMBOL(crypto_qti_keyslot_program); int crypto_qti_keyslot_evict(const struct ice_mmio_data *mmio_data, - unsigned int slot) + unsigned int slot, int storage_type) { int err = 0; - err = crypto_qti_invalidate_key(mmio_data, slot); + err = crypto_qti_invalidate_key(mmio_data, slot, storage_type); if (err) { pr_err("%s: invalidate key failed with error %d\n", __func__, err); @@ -467,6 +475,42 @@ int crypto_qti_derive_raw_secret(const u8 *wrapped_key, EXPORT_SYMBOL(crypto_qti_derive_raw_secret); #if IS_ENABLED(CONFIG_QTI_CRYPTO_FDE) +static int get_key_id(char *key_id, uint32_t usage, bool hash_enable) +{ + /* only legacy hash will get the legacy key id, otherwise return new key id */ + if (hash_enable) { + switch (usage) { + case QSEECOM_KM_USAGE_UFS_ICE_DISK_ENCRYPTION: + memcpy((void *)key_id, (void *)CRYPTO_ICE_FDE_UFS_LEGACY_KEYID, + strlen(CRYPTO_ICE_FDE_UFS_LEGACY_KEYID)); + break; + case QSEECOM_KM_USAGE_SDCC_ICE_DISK_ENCRYPTION: + memcpy((void *)key_id, (void *)CRYPTO_ICE_FDE_EMMC_LEGACY_KEYID, + strlen(CRYPTO_ICE_FDE_EMMC_LEGACY_KEYID)); + break; + default: + pr_err("unsupported usage %d\n", usage); + return -EINVAL; + } + } else { + switch (usage) { + case QSEECOM_KM_USAGE_UFS_ICE_DISK_ENCRYPTION: + memcpy((void *)key_id, (void *)CRYPTO_ICE_FDE_UFS_KEYID, + strlen(CRYPTO_ICE_FDE_UFS_KEYID)); + break; + case QSEECOM_KM_USAGE_SDCC_ICE_DISK_ENCRYPTION: + memcpy((void *)key_id, (void *)CRYPTO_ICE_FDE_EMMC_KEYID, + strlen(CRYPTO_ICE_FDE_EMMC_KEYID)); + break; + default: + pr_err("unsupported usage %d\n", usage); + return -EINVAL; + } + } + + return 0; +} + static struct ice_part_cfg *crypto_qti_ice_get_part_cfg(struct ice_device *ice_dev, char const * const volname) { @@ -675,6 +719,11 @@ static ssize_t add_partition_store(struct device *dev, struct ice_device *ice_dev = dev_get_drvdata(dev); ssize_t ret = count; char label[PARTITION_META_INFO_VOLNAMELTH + 1] = {0}; + char key_id[CRYPTO_ICE_KEY_ID_SIZE] = {0}; + char *flag = "-hash"; + char *hash_index = NULL; + bool hash_enable = false; + size_t partition_count = count; int rc = 0; struct list_head *new_pos = NULL; struct ice_part_cfg *elem = NULL; @@ -682,26 +731,62 @@ static ssize_t add_partition_store(struct device *dev, bool new_key_generated = false; int key_res = 0; - if (count > PARTITION_META_INFO_VOLNAMELTH) { + /* The count of the buf include hash size and flag size */ + if (count > PARTITION_META_INFO_VOLNAMELTH + CRYPTO_ICE_HASH_SIZE + strlen(flag)) { dev_err(dev, "Invalid partition '%s' (%u)\n", buf, count); return -EINVAL; } + if (!buf) { + dev_err(dev, "Invalid buf\n"); + return -EINVAL; + } + if (!ice_dev) { dev_err(dev, "Invalid ICE device!\n"); return -ENODEV; } - /* Copy into a temporary buffer, stripping out newlines */ - count = strcspn(buf, "\n\r"); - memcpy(label, buf, count); - label[count] = '\0'; - - if (!count) { - dev_err(dev, "Invalid partition '%s' (%u)\n", buf, count); - return -EINVAL; + /* + * check if the userspace input the hash to generate ICE key + * -hash means input hash with legacy key id + */ + hash_index = strnstr(buf, flag, count); + if (hash_index) { + /* + * It must follow the right format to input partition name and hash, + * partition name can't be null. + */ + if (hash_index > buf + 1) { + hash_enable = true; + /* skip the blank and get the partition name count */ + partition_count = hash_index - buf - 1; + /* skip to the header pointer of hash */ + hash_index += strlen(flag) + 1; + /* exclude "\r" that in the end of input buf, and check hash size */ + if (strlen(hash_index) - 1 != CRYPTO_ICE_HASH_SIZE) { + dev_err(dev, "Invalid hash\n"); + return -EINVAL; + } + } else { + dev_err(dev, "Invalid partition\n"); + return -EINVAL; + } } + if (!hash_enable) { + /* Copy into a temporary buffer, stripping out newlines */ + partition_count = strcspn(buf, "\n\r"); + if (!partition_count) { + dev_err(dev, "Invalid partition '%s' (%u)\n", buf, partition_count); + return -EINVAL; + } + } + + /* copy the partition name */ + memcpy(label, buf, partition_count); + label[partition_count] = '\0'; + mutex_lock(&ice_dev->mutex); /* Check if the partition is already in the list */ list_for_each(new_pos, &ice_dev->part_cfg_list) @@ -737,25 +822,50 @@ static ssize_t add_partition_store(struct device *dev, */ if (strcmp(ice_dev->ice_instance_type, "ufs") == 0) { #if IS_ENABLED(CONFIG_QTI_CRYPTO_LEGACY_KEY_FDE) + /* In legacy mode, only one common key is needed */ if (list_empty(&ice_dev->part_cfg_list)) { - /* In legacy mode, only one common key is needed */ + /* get the key_id that depends on if inhash_enable or not */ + if (get_key_id(key_id, QSEECOM_KM_USAGE_UFS_ICE_DISK_ENCRYPTION, + hash_enable)) { + dev_err(dev, "Fail to get the ice key_id\n"); + ret = -EINVAL; + goto out; + } + key_res = qseecom_create_key_in_slot( QSEECOM_KM_USAGE_UFS_ICE_DISK_ENCRYPTION, - slot, CRYPTO_ICE_FDE_LEGACY_UFS, NULL); + slot, key_id, hash_index); } else { /* Key is already generated and set,contune */ key_res = QSEECOM_KEY_ID_EXISTS; } #else - key_res = qseecom_create_key_in_slot(QSEECOM_KM_USAGE_UFS_ICE_DISK_ENCRYPTION, + key_res = qseecom_create_key_in_slot( + QSEECOM_KM_USAGE_UFS_ICE_DISK_ENCRYPTION, slot, label, NULL); #endif } else if (strcmp(ice_dev->ice_instance_type, "sdcc") == 0) { #if IS_ENABLED(CONFIG_QTI_CRYPTO_LEGACY_KEY_FDE) - key_res = qseecom_create_key_in_slot(QSEECOM_KM_USAGE_SDCC_ICE_DISK_ENCRYPTION, - slot, CRYPTO_ICE_FDE_LEGACY_EMMC, NULL); + /* In legacy mode, only one common key is needed */ + if (list_empty(&ice_dev->part_cfg_list)) { + /* get the key_id that depends on if inhash_enable or not */ + if (get_key_id(key_id, QSEECOM_KM_USAGE_SDCC_ICE_DISK_ENCRYPTION, + hash_enable)) { + dev_err(dev, "Fail to get the ice key_id\n"); + ret = -EINVAL; + goto out; + } + + key_res = qseecom_create_key_in_slot( + QSEECOM_KM_USAGE_SDCC_ICE_DISK_ENCRYPTION, + slot, key_id, hash_index); + } else { + /* Key is already generated and set,contune */ + key_res = QSEECOM_KEY_ID_EXISTS; + } #else - key_res = qseecom_create_key_in_slot(QSEECOM_KM_USAGE_SDCC_ICE_DISK_ENCRYPTION, + key_res = qseecom_create_key_in_slot( + QSEECOM_KM_USAGE_SDCC_ICE_DISK_ENCRYPTION, slot, label, NULL); #endif } else { diff --git a/drivers/soc/qcom/crypto-qti-hwkm.c b/drivers/soc/qcom/crypto-qti-hwkm.c index b328af4e2010..1c42722f8088 100644 --- a/drivers/soc/qcom/crypto-qti-hwkm.c +++ b/drivers/soc/qcom/crypto-qti-hwkm.c @@ -280,7 +280,7 @@ static int crypto_qti_program_key_v1(const struct ice_mmio_data *mmio_data, int crypto_qti_program_key(const struct ice_mmio_data *mmio_data, const struct blk_crypto_key *key, unsigned int slot, - unsigned int data_unit_mask, int capid) + unsigned int data_unit_mask, int capid, int storage_type) { int err = 0; union crypto_cfg cfg; @@ -337,7 +337,7 @@ exit: EXPORT_SYMBOL(crypto_qti_program_key); int crypto_qti_invalidate_key(const struct ice_mmio_data *mmio_data, - unsigned int slot) + unsigned int slot, int storage_type) { int err = 0; diff --git a/drivers/soc/qcom/crypto-qti-platform.h b/drivers/soc/qcom/crypto-qti-platform.h index addc8f996e53..ed7aac7f5d2d 100644 --- a/drivers/soc/qcom/crypto-qti-platform.h +++ b/drivers/soc/qcom/crypto-qti-platform.h @@ -15,9 +15,9 @@ int crypto_qti_program_key(const struct ice_mmio_data *mmio_data, const struct blk_crypto_key *key, unsigned int slot, - unsigned int data_unit_mask, int capid); + unsigned int data_unit_mask, int capid, int storage_type); int crypto_qti_invalidate_key(const struct ice_mmio_data *mmio_data, - unsigned int slot); + unsigned int slot, int storage_type); int crypto_qti_derive_raw_secret_platform( const u8 *wrapped_key, unsigned int wrapped_key_size, u8 *secret, @@ -34,12 +34,12 @@ static inline int crypto_qti_program_key( const struct ice_mmio_data *mmio_data, const struct blk_crypto_key *key, unsigned int slot, - unsigned int data_unit_mask, int capid) + unsigned int data_unit_mask, int capid, int storage_type) { return -EOPNOTSUPP; } static inline int crypto_qti_invalidate_key( - const struct ice_mmio_data *mmio_data, unsigned int slot) + const struct ice_mmio_data *mmio_data, unsigned int slot, int storage_type) { return -EOPNOTSUPP; } diff --git a/drivers/soc/qcom/crypto-qti-tz.c b/drivers/soc/qcom/crypto-qti-tz.c index 5ae228b77265..ee1f6e591584 100644 --- a/drivers/soc/qcom/crypto-qti-tz.c +++ b/drivers/soc/qcom/crypto-qti-tz.c @@ -2,7 +2,7 @@ /* * Crypto TZ library for storage encryption. * - * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. + * Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved. */ #include @@ -10,35 +10,13 @@ #include #include #include -#include #include "crypto-qti-platform.h" #define ICE_CIPHER_MODE_XTS_256 3 -#define UFS_CE 10 -#define SDCC_CE 20 -#define UFS_CARD_CE 30 - -static bool is_boot_dev_type_emmc(void) -{ - struct device_node *np; - const char *bootparams; - - np = of_find_node_by_path("/chosen"); - of_property_read_string(np, "bootargs", &bootparams); - if (!bootparams) - pr_err("%s: failed to get bootargs property\n", __func__); - else if (strnstr(bootparams, "androidboot.bootdevice", - strlen(bootparams)) && - strnstr(bootparams, "sdhci", strlen(bootparams))) - return true; - - return false; - -} int crypto_qti_program_key(const struct ice_mmio_data *mmio_data, const struct blk_crypto_key *key, unsigned int slot, - unsigned int data_unit_mask, int capid) + unsigned int data_unit_mask, int capid, int storage_type) { int err = 0; struct qtee_shm shm; @@ -50,14 +28,10 @@ int crypto_qti_program_key(const struct ice_mmio_data *mmio_data, memcpy(shm.vaddr, key->raw, key->size); qtee_shmbridge_flush_shm_buf(&shm); - if (is_boot_dev_type_emmc()) - err = qcom_scm_config_set_ice_key(slot, shm.paddr, key->size, + err = qcom_scm_config_set_ice_key(slot, shm.paddr, key->size, ICE_CIPHER_MODE_XTS_256, - data_unit_mask, SDCC_CE); - else - err = qcom_scm_config_set_ice_key(slot, shm.paddr, key->size, - ICE_CIPHER_MODE_XTS_256, - data_unit_mask, UFS_CE); + data_unit_mask, storage_type); + if (err) pr_err("%s:SCM call Error: 0x%x slot %d\n", __func__, err, slot); @@ -70,14 +44,11 @@ int crypto_qti_program_key(const struct ice_mmio_data *mmio_data, EXPORT_SYMBOL(crypto_qti_program_key); int crypto_qti_invalidate_key(const struct ice_mmio_data *mmio_data, - unsigned int slot) + unsigned int slot, int storage_type) { int err = 0; - if (is_boot_dev_type_emmc()) - err = qcom_scm_clear_ice_key(slot, SDCC_CE); - else - err = qcom_scm_clear_ice_key(slot, UFS_CE); + err = qcom_scm_clear_ice_key(slot, storage_type); if (err) pr_err("%s:SCM call Error: 0x%x\n", __func__, err); diff --git a/drivers/soc/qcom/dcc_v2.c b/drivers/soc/qcom/dcc_v2.c index c62a64fa761a..c8a114d17998 100644 --- a/drivers/soc/qcom/dcc_v2.c +++ b/drivers/soc/qcom/dcc_v2.c @@ -676,7 +676,7 @@ static bool is_dcc_enabled(struct dcc_drvdata *drvdata) bool dcc_enable = false; int list; - for (list = 0; list < DCC_MAX_LINK_LIST; list++) { + for (list = 0; list < drvdata->nr_link_list; list++) { if (drvdata->enable[list]) { dcc_enable = true; break; diff --git a/drivers/soc/qcom/dcvs/c1dcvs_scmi.c b/drivers/soc/qcom/dcvs/c1dcvs_scmi.c index c7ae055b8260..cef2be4e7a7d 100644 --- a/drivers/soc/qcom/dcvs/c1dcvs_scmi.c +++ b/drivers/soc/qcom/dcvs/c1dcvs_scmi.c @@ -143,32 +143,25 @@ static ssize_t store_##name(struct kobject *kobj, \ size_t count) \ { \ int ret, i = 0; \ - char *s; \ - unsigned int msg[2] = {0}; \ - char *str; \ - \ - s = kstrdup(buf, GFP_KERNEL); \ - if (!s) \ - return -ENOMEM; \ - if (!ops) { \ - ret = -ENODEV; \ - goto out; \ - } \ + char *s = kstrdup(buf, GFP_KERNEL); \ + unsigned int msg[2] = {0}; \ + char *str, *s_orig = s; \ \ + if (!s) \ + return -ENOMEM; \ while (((str = strsep(&s, " ")) != NULL) && i < 2) { \ ret = kstrtouint(str, 10, &msg[i]); \ if (ret < 0) { \ pr_err("Invalid value :%d\n", ret); \ - ret = -EINVAL; \ - goto out; \ + goto out; \ } \ i++; \ } \ \ pr_info("Input threshold :%lu for cluster :%lu\n", msg[1], msg[0]);\ - ret = ops->set_##name(ph, msg); \ -out: \ - kfree(s); \ + ret = ops->set_##name(ph, msg); \ +out: \ + kfree(s_orig); \ return ((ret < 0) ? ret : count); \ } \ diff --git a/drivers/soc/qcom/dcvs/dcvs.c b/drivers/soc/qcom/dcvs/dcvs.c index fbe940a5b788..85a66bec2de7 100644 --- a/drivers/soc/qcom/dcvs/dcvs.c +++ b/drivers/soc/qcom/dcvs/dcvs.c @@ -29,6 +29,7 @@ static const char * const dcvs_hw_names[NUM_DCVS_HW_TYPES] = { [DCVS_LLCC] = "LLCC", [DCVS_L3] = "L3", [DCVS_DDRQOS] = "DDRQOS", + [DCVS_L3_1] = "L3_1", }; enum dcvs_type { @@ -699,7 +700,7 @@ static int qcom_dcvs_hw_probe(struct platform_device *pdev) return -ENODEV; } - if (hw_type == DCVS_L3) + if (hw_type == DCVS_L3 || hw_type == DCVS_L3_1) ret = populate_l3_table(dev, &hw->freq_table); else ret = populate_freq_table(dev, &hw->freq_table); @@ -769,7 +770,7 @@ static int qcom_dcvs_path_probe(struct platform_device *pdev) if (hw->type == DCVS_DDR || hw->type == DCVS_LLCC || hw->type == DCVS_DDRQOS) ret = setup_icc_sp_device(dev, hw, path); - else if (hw->type == DCVS_L3) + else if (hw->type == DCVS_L3 || hw->type == DCVS_L3_1) ret = setup_epss_l3_sp_device(dev, hw, path); if (ret < 0) { dev_err(dev, "Error setting up sp dev: %d\n", ret); @@ -788,7 +789,7 @@ static int qcom_dcvs_path_probe(struct platform_device *pdev) } break; case DCVS_PERCPU_PATH: - if (hw->type != DCVS_L3) { + if (hw->type != DCVS_L3 && hw->type != DCVS_L3_1) { dev_err(dev, "Unsupported HW for path: %d\n", ret); return -EINVAL; } diff --git a/drivers/soc/qcom/dcvs/dcvs_epss.c b/drivers/soc/qcom/dcvs/dcvs_epss.c index 461427e32e79..89da3ab7db20 100644 --- a/drivers/soc/qcom/dcvs/dcvs_epss.c +++ b/drivers/soc/qcom/dcvs/dcvs_epss.c @@ -1,6 +1,7 @@ // SPDX-License-Identifier: GPL-2.0-only /* * Copyright (c) 2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2023, Qualcomm Innovation Center, Inc. All rights reserved. */ #define pr_fmt(fmt) "qcom-dcvs-epss: " fmt @@ -121,7 +122,7 @@ static int commit_epss_l3(struct dcvs_path *path, struct dcvs_freq *freqs, if (freqs->ib <= hw->freq_table[idx]) break; - if (hw->type == DCVS_L3) { + if (hw->type == DCVS_L3 || hw->type == DCVS_L3_1) { if (shared) offset = d->l3_shared_offset; else { diff --git a/drivers/soc/qcom/hab/ghs_comm.c b/drivers/soc/qcom/hab/ghs_comm.c index a0b18d252f9f..71f19624ac2b 100644 --- a/drivers/soc/qcom/hab/ghs_comm.c +++ b/drivers/soc/qcom/hab/ghs_comm.c @@ -1,6 +1,7 @@ // SPDX-License-Identifier: GPL-2.0-only /* * Copyright (c) 2018-2021, The Linux Foundation. All rights reserved. + * Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved. */ #include "hab.h" #include "hab_ghs.h" @@ -28,7 +29,8 @@ int physical_channel_read(struct physical_channel *pchan, int physical_channel_send(struct physical_channel *pchan, struct hab_header *header, - void *payload) + void *payload, + unsigned int flags) { size_t sizebytes = HAB_HEADER_GET_SIZE(*header); struct ghs_vdev *dev = (struct ghs_vdev *)pchan->hyp_data; @@ -36,6 +38,9 @@ int physical_channel_send(struct physical_channel *pchan, uint8_t *msg; int irqs_disabled; + /* Only used in virtio arch */ + (void)flags; + if (!dev) { pr_err("no send pchan %s has been de-alloced msg for %zd bytes\n", pchan->name); diff --git a/drivers/soc/qcom/hab/hab.c b/drivers/soc/qcom/hab/hab.c index 6dafc2d62812..3cf6ebf05233 100644 --- a/drivers/soc/qcom/hab/hab.c +++ b/drivers/soc/qcom/hab/hab.c @@ -121,7 +121,7 @@ struct uhab_context *hab_ctx_alloc(int kernel) * ->habmem_export_destroy->habmem_exp_release, * where dma_buf_unmap_attachment() & dma_buf_detach() might sleep. */ -static void hab_ctx_free_fn(struct uhab_context *ctx) +void hab_ctx_free_fn(struct uhab_context *ctx) { struct hab_export_ack_recvd *exp_ack_recvd, *expack_tmp; struct hab_import_ack_recvd *imp_ack_recvd, *impack_tmp; @@ -137,7 +137,7 @@ static void hab_ctx_free_fn(struct uhab_context *ctx) int ret = 0; /* garbage-collect exp/imp buffers */ - write_lock_bh(&ctx->exp_lock); + write_lock(&ctx->exp_lock); list_for_each_entry_safe(exp, exp_tmp, &ctx->exp_whse, node) { list_del(&exp->node); exp_super = container_of(exp, struct export_desc_super, exp); @@ -152,12 +152,18 @@ static void hab_ctx_free_fn(struct uhab_context *ctx) pr_debug("potential leak exp %d vcid %X recovered\n", exp->export_id, exp->vcid_local); habmem_hyp_revoke(exp->payload, exp->payload_count); - write_unlock_bh(&ctx->exp_lock); + write_unlock(&ctx->exp_lock); + + pchan = exp->pchan; + hab_spin_lock(&pchan->expid_lock, irqs_disabled); + idr_remove(&pchan->expid_idr, exp->export_id); + hab_spin_unlock(&pchan->expid_lock, irqs_disabled); + habmem_remove_export(exp); - write_lock_bh(&ctx->exp_lock); + write_lock(&ctx->exp_lock); } } - write_unlock_bh(&ctx->exp_lock); + write_unlock(&ctx->exp_lock); spin_lock_bh(&ctx->imp_lock); list_for_each_entry_safe(exp, exp_tmp, &ctx->imp_whse, node) { @@ -175,7 +181,11 @@ static void hab_ctx_free_fn(struct uhab_context *ctx) HAB_HEADER_SET_SIZE(header, sizeof(uint32_t)); HAB_HEADER_SET_ID(header, HAB_VCID_UNIMPORT); HAB_HEADER_SET_SESSION_ID(header, HAB_SESSIONID_UNIMPORT); - physical_channel_send(exp->pchan, &header, &exp->export_id); + ret = physical_channel_send(exp->pchan, &header, &exp->export_id, + HABMM_SOCKET_SEND_FLAGS_NON_BLOCKING); + if (ret != 0) + pr_err("failed to send unimp msg %d, vcid %d, exp id %d\n", + ret, exp->vcid_local, exp->export_id); } else pr_err("exp id %d unmap fail on vcid %X\n", exp->export_id, exp->vcid_local); @@ -265,39 +275,9 @@ static void hab_ctx_free_fn(struct uhab_context *ctx) kfree(ctx); } -static void hab_ctx_free_work_fn(struct work_struct *work) -{ - struct uhab_context *ctx = - container_of(work, struct uhab_context, destroy_work); - - hab_ctx_free_fn(ctx); -} - - -/* - * ctx can only be freed after all the vchan releases the refcnt - * and hab_release() is called. - * - * this function might be called in atomic context in following situations - * (only applicable to Linux): - * 1. physical_channel_rx_dispatch()->hab_msg_recv()->hab_vchan_put() - * ->hab_ctx_put()->hab_ctx_free() in tasklet. - * 2. hab client holds spin_lock and calls hab_vchan_close()->hab_vchan_put() - * ->hab_vchan_free()->hab_ctx_free(). - */ void hab_ctx_free(struct kref *ref) { - struct uhab_context *ctx = - container_of(ref, struct uhab_context, refcount); - - if (likely(preemptible())) { - hab_ctx_free_fn(ctx); - } else { - pr_info("In non-preemptive context now, ctx owner %d\n", - ctx->owner); - INIT_WORK(&ctx->destroy_work, hab_ctx_free_work_fn); - schedule_work(&ctx->destroy_work); - } + hab_ctx_free_os(ref); } /* @@ -644,7 +624,7 @@ long hab_vchan_send(struct uhab_context *ctx, struct virtual_channel *vchan; int ret; struct hab_header header = HAB_HEADER_INITIALIZER; - int nonblocking_flag = flags & HABMM_SOCKET_SEND_FLAGS_NON_BLOCKING; + unsigned int nonblocking_flag = flags & HABMM_SOCKET_SEND_FLAGS_NON_BLOCKING; if (sizebytes > (size_t)HAB_HEADER_SIZE_MAX) { pr_err("Message too large, %lu bytes, max is %d\n", @@ -658,6 +638,16 @@ long hab_vchan_send(struct uhab_context *ctx, goto err; } + /** + * Without non-blocking configured, when the shared memory (vdev-shmem project) or + * vh_buf_header (virtio-hab project) used by HAB for front-end and back-end messaging + * is exhausted, the current path will be blocked. + * 1. The vdev-shmem project will be blocked in the hab_vchan_send function; + * 2. The virtio-hab project will be blocked in the hab_physical_send function; + */ + if (!nonblocking_flag) + might_sleep(); + /* log msg send timestamp: enter hab_vchan_send */ trace_hab_vchan_send_start(vchan); @@ -697,7 +687,7 @@ long hab_vchan_send(struct uhab_context *ctx, HAB_HEADER_SET_SESSION_ID(header, vchan->session_id); while (1) { - ret = physical_channel_send(vchan->pchan, &header, data); + ret = physical_channel_send(vchan->pchan, &header, data, nonblocking_flag); if (vchan->otherend_closed || nonblocking_flag || ret != -EAGAIN) @@ -711,7 +701,7 @@ long hab_vchan_send(struct uhab_context *ctx, * from the hab_vchan_send()'s perspective. */ if (!ret) - vchan->tx_cnt++; + atomic64_inc(&vchan->tx_cnt); err: /* log msg send timestamp: exit hab_vchan_send */ @@ -762,7 +752,7 @@ int hab_vchan_recv(struct uhab_context *ctx, * hab_vchan_recv()'s view w/ the ret as 0 and *message as * non-zero. */ - vchan->rx_cnt++; + atomic64_inc(&vchan->rx_cnt); } vchan->rx_inflight = 0; @@ -848,26 +838,36 @@ int hab_vchan_open(struct uhab_context *ctx, void hab_send_close_msg(struct virtual_channel *vchan) { struct hab_header header = HAB_HEADER_INITIALIZER; + int ret = 0; if (vchan && !vchan->otherend_closed) { HAB_HEADER_SET_SIZE(header, 0); HAB_HEADER_SET_TYPE(header, HAB_PAYLOAD_TYPE_CLOSE); HAB_HEADER_SET_ID(header, vchan->otherend_id); HAB_HEADER_SET_SESSION_ID(header, vchan->session_id); - physical_channel_send(vchan->pchan, &header, NULL); + ret = physical_channel_send(vchan->pchan, &header, NULL, + HABMM_SOCKET_SEND_FLAGS_NON_BLOCKING); + if (ret != 0) + pr_err("failed to send close msg %d, vcid %x\n", + ret, vchan->id); } } void hab_send_unimport_msg(struct virtual_channel *vchan, uint32_t exp_id) { struct hab_header header = HAB_HEADER_INITIALIZER; + int ret = 0; if (vchan) { HAB_HEADER_SET_SIZE(header, sizeof(uint32_t)); HAB_HEADER_SET_TYPE(header, HAB_PAYLOAD_TYPE_UNIMPORT); HAB_HEADER_SET_ID(header, vchan->otherend_id); HAB_HEADER_SET_SESSION_ID(header, vchan->session_id); - physical_channel_send(vchan->pchan, &header, &exp_id); + ret = physical_channel_send(vchan->pchan, &header, &exp_id, + HABMM_SOCKET_SEND_FLAGS_NON_BLOCKING); + if (ret != 0) + pr_err("failed to send unimp msg %d, vcid %x\n", + ret, vchan->id); } } diff --git a/drivers/soc/qcom/hab/hab.h b/drivers/soc/qcom/hab/hab.h index 8fa23ec9554d..a434281bf874 100644 --- a/drivers/soc/qcom/hab/hab.h +++ b/drivers/soc/qcom/hab/hab.h @@ -415,8 +415,8 @@ struct virtual_channel { int closed; int forked; /* if fork is detected and assume only once */ /* stats */ - uint64_t tx_cnt; /* total succeeded tx */ - uint64_t rx_cnt; /* total succeeded rx */ + atomic64_t tx_cnt; /* total succeeded tx */ + atomic64_t rx_cnt; /* total succeeded rx */ int rx_inflight; /* rx in progress/blocking */ }; @@ -486,6 +486,12 @@ enum exp_desc_state { EXP_DESC_IMPORTING, /* hab_mem_import is in progress */ EXP_DESC_IMPORTED, /* hab_mem_import is called and returns success */ }; + +enum export_state { + HAB_EXP_EXPORTING, + HAB_EXP_SUCCESS, +}; + struct export_desc_super { struct kref refcount; void *platform_data; @@ -493,6 +499,7 @@ struct export_desc_super { unsigned int payload_size; /* size of the compressed pfn structure */ enum exp_desc_state import_state; + enum export_state exp_state; uint32_t remote_imported; /* @@ -621,6 +628,9 @@ struct uhab_context *hab_ctx_alloc(int kernel); void hab_ctx_free(struct kref *ref); +void hab_ctx_free_fn(struct uhab_context *ctx); +void hab_ctx_free_os(struct kref *ref); + static inline void hab_ctx_get(struct uhab_context *ctx) { if (ctx) @@ -654,7 +664,8 @@ int physical_channel_read(struct physical_channel *pchan, int physical_channel_send(struct physical_channel *pchan, struct hab_header *header, - void *payload); + void *payload, + unsigned int flags); void physical_channel_rx_dispatch(unsigned long physical_channel); void physical_channel_rx_dispatch_common(unsigned long physical_channel); diff --git a/drivers/soc/qcom/hab/hab_comm.c b/drivers/soc/qcom/hab/hab_comm.c index 1312fc3b1151..2e9e923669f8 100644 --- a/drivers/soc/qcom/hab/hab_comm.c +++ b/drivers/soc/qcom/hab/hab_comm.c @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-2.0-only /* * Copyright (c) 2016-2019, The Linux Foundation. All rights reserved. - * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. + * Copyright (c) 2022-2023, Qualcomm Innovation Center, Inc. All rights reserved. */ #include "hab.h" @@ -88,13 +88,16 @@ int lb_kthread(void *d) int physical_channel_send(struct physical_channel *pchan, struct hab_header *header, - void *payload) + void *payload, unsigned int flags) { int size = HAB_HEADER_GET_SIZE(*header); /* payload size */ struct timespec64 ts = {0}; struct loopback_msg *msg = NULL; struct loopback_dev *dev = pchan->hyp_data; + /* Only used in virtio arch */ + (void)flags; + msg = kmalloc(size + sizeof(*msg), GFP_KERNEL); if (!msg) return -ENOMEM; diff --git a/drivers/soc/qcom/hab/hab_linux.c b/drivers/soc/qcom/hab/hab_linux.c index ef66a16c8a3e..d84dc214af09 100644 --- a/drivers/soc/qcom/hab/hab_linux.c +++ b/drivers/soc/qcom/hab/hab_linux.c @@ -11,6 +11,40 @@ unsigned int get_refcnt(struct kref ref) return kref_read(&ref); } +static void hab_ctx_free_work_fn(struct work_struct *work) +{ + struct uhab_context *ctx = + container_of(work, struct uhab_context, destroy_work); + + hab_ctx_free_fn(ctx); +} + +/* + * ctx can only be freed after all the vchan releases the refcnt + * and hab_release() is called. + * + * this function might be called in atomic context in following situations + * (only applicable to Linux): + * 1. physical_channel_rx_dispatch()->hab_msg_recv()->hab_vchan_put() + * ->hab_ctx_put()->hab_ctx_free() in tasklet. + * 2. hab client holds spin_lock and calls hab_vchan_close()->hab_vchan_put() + * ->hab_vchan_free()->hab_ctx_free(). + */ +void hab_ctx_free_os(struct kref *ref) +{ + struct uhab_context *ctx = + container_of(ref, struct uhab_context, refcount); + + if (likely(preemptible())) { + hab_ctx_free_fn(ctx); + } else { + pr_info("In non-preemptive context now, ctx owner %d\n", + ctx->owner); + INIT_WORK(&ctx->destroy_work, hab_ctx_free_work_fn); + schedule_work(&ctx->destroy_work); + } +} + static int hab_open(struct inode *inodep, struct file *filep) { int result = 0; @@ -312,10 +346,9 @@ static int hab_power_down_callback( case SYS_HALT: case SYS_POWER_OFF: pr_debug("reboot called %ld\n", action); - hab_hypervisor_unregister(); /* only for single VM guest */ break; } - pr_debug("reboot called %ld done\n", action); + pr_info("reboot called %ld done\n", action); return NOTIFY_DONE; } @@ -327,18 +360,28 @@ static void reclaim_cleanup(struct work_struct *reclaim_work) { struct export_desc *exp = NULL, *exp_tmp = NULL; struct export_desc_super *exp_super = NULL; + struct physical_channel *pchan = NULL; + LIST_HEAD(free_list); pr_debug("reclaim worker called\n"); spin_lock(&hab_driver.reclaim_lock); list_for_each_entry_safe(exp, exp_tmp, &hab_driver.reclaim_list, node) { exp_super = container_of(exp, struct export_desc_super, exp); - if (exp_super->remote_imported == 0) { - list_del(&exp->node); - pr_info("cleanup exp id %d\n", exp->export_id); - habmem_export_put(exp_super); - } + if (exp_super->remote_imported == 0) + list_move(&exp->node, &free_list); } spin_unlock(&hab_driver.reclaim_lock); + + list_for_each_entry_safe(exp, exp_tmp, &free_list, node) { + list_del(&exp->node); + exp_super = container_of(exp, struct export_desc_super, exp); + pchan = exp->pchan; + spin_lock_bh(&pchan->expid_lock); + idr_remove(&pchan->expid_idr, exp->export_id); + spin_unlock_bh(&pchan->expid_lock); + pr_info("cleanup exp id %u from %s\n", exp->export_id, pchan->name); + habmem_export_put(exp_super); + } } static int __init hab_init(void) diff --git a/drivers/soc/qcom/hab/hab_mem_linux.c b/drivers/soc/qcom/hab/hab_mem_linux.c index 355256a98be1..b9ad3d6dd946 100644 --- a/drivers/soc/qcom/hab/hab_mem_linux.c +++ b/drivers/soc/qcom/hab/hab_mem_linux.c @@ -11,8 +11,22 @@ #define VFIO_DEV_DT_NAME "vfio_" enum hab_page_list_type { + /* + * Use this type when dmabuf is created by habmm_import() + */ HAB_PAGE_LIST_IMPORT = 0x1, - HAB_PAGE_LIST_EXPORT + /* + * Use this type when dmabuf is created when hab_mem_export() is called + * with the "kernel" parameter is TRUE and w/o HABMM_EXPIMP_FLAGS_DMABUF + * and HABMM_EXPIMP_FLAGS_FD flag + */ + HAB_PAGE_LIST_EXPORT_KERNEL, + /* + * Use this type when dmabuf is created when hab_mem_export() is called + * with the "kernel" parameter is FALSE and w/o HABMM_EXP_MEM_TYPE_DMA + * and HABMM_EXPIMP_FLAGS_FD flag + */ + HAB_PAGE_LIST_EXPORT_USER }; struct pages_list { @@ -135,6 +149,7 @@ static void pages_list_remove(struct pages_list *pglist) static void pages_list_destroy(struct kref *refcount) { + int i = 0; struct pages_list *pglist = container_of(refcount, struct pages_list, refcount); @@ -146,6 +161,11 @@ static void pages_list_destroy(struct kref *refcount) /* the imported pages used, notify the remote */ if (pglist->type == HAB_PAGE_LIST_IMPORT) pages_list_remove(pglist); + else if (pglist->type == HAB_PAGE_LIST_EXPORT_USER) { + for (i = 0; i < pglist->npages; i++) + put_page(pglist->pages[i]); + } + vfree(pglist->pages); @@ -269,7 +289,7 @@ static struct dma_buf *habmem_get_dma_buf_from_uva(unsigned long address, pglist->pages = pages; pglist->npages = page_count; - pglist->type = HAB_PAGE_LIST_EXPORT; + pglist->type = HAB_PAGE_LIST_EXPORT_USER; kref_init(&pglist->refcount); @@ -575,7 +595,7 @@ int habmem_hyp_grant(struct virtual_channel *vchan, pglist->pages = pages; pglist->npages = page_count; - pglist->type = HAB_PAGE_LIST_EXPORT; + pglist->type = HAB_PAGE_LIST_EXPORT_KERNEL; pglist->pchan = vchan->pchan; pglist->vcid = vchan->id; diff --git a/drivers/soc/qcom/hab/hab_mimex.c b/drivers/soc/qcom/hab/hab_mimex.c index 2fb644e8e04a..0ac1d9fdacf2 100644 --- a/drivers/soc/qcom/hab/hab_mimex.c +++ b/drivers/soc/qcom/hab/hab_mimex.c @@ -187,9 +187,9 @@ void habmem_remove_export(struct export_desc *exp) } ctx = exp->ctx; - write_lock_bh(&ctx->exp_lock); + write_lock(&ctx->exp_lock); ctx->export_total--; - write_unlock_bh(&ctx->exp_lock); + write_unlock(&ctx->exp_lock); exp->ctx = NULL; habmem_export_put(exp_super); @@ -197,35 +197,17 @@ void habmem_remove_export(struct export_desc *exp) static void habmem_export_destroy(struct kref *refcount) { - struct physical_channel *pchan = NULL; struct export_desc_super *exp_super = container_of( refcount, struct export_desc_super, refcount); - struct export_desc *exp = NULL; if (!exp_super) { pr_err("invalid exp_super\n"); return; } - exp = &exp_super->exp; - if (!exp || !exp->pchan) { - if (exp) - pr_err("invalid info in exp %pK pchan %pK\n", - exp, exp->pchan); - else - pr_err("invalid exp\n"); - return; - } - - pchan = exp->pchan; - - spin_lock_bh(&pchan->expid_lock); - idr_remove(&pchan->expid_idr, exp->export_id); - spin_unlock_bh(&pchan->expid_lock); - habmem_exp_release(exp_super); vfree(exp_super); } @@ -241,8 +223,9 @@ static int habmem_export_vchan(struct uhab_context *ctx, uint32_t flags, uint32_t export_id) { - int ret; + int ret = 0; struct export_desc *exp = NULL; + struct export_desc_super *exp_super = NULL; uint32_t sizebytes = sizeof(*exp) + payload_size; struct hab_export_ack expected_ack = {0}; struct hab_header header = HAB_HEADER_INITIALIZER; @@ -253,7 +236,9 @@ static int habmem_export_vchan(struct uhab_context *ctx, return -EINVAL; } + spin_lock_bh(&vchan->pchan->expid_lock); exp = idr_find(&vchan->pchan->expid_idr, export_id); + spin_unlock_bh(&vchan->pchan->expid_lock); if (!exp) { pr_err("export vchan failed: exp_id %d, pchan %s\n", export_id, vchan->pchan->name); @@ -263,38 +248,89 @@ static int habmem_export_vchan(struct uhab_context *ctx, pr_debug("sizebytes including exp_desc: %u = %zu + %d\n", sizebytes, sizeof(*exp), payload_size); - HAB_HEADER_SET_SIZE(header, sizebytes); - HAB_HEADER_SET_TYPE(header, HAB_PAYLOAD_TYPE_EXPORT); - HAB_HEADER_SET_ID(header, vchan->otherend_id); - HAB_HEADER_SET_SESSION_ID(header, vchan->session_id); - ret = physical_channel_send(vchan->pchan, &header, exp); + /* exp_desc will not be sent to remote during export in new protocol */ + if (vchan->pchan->mem_proto == 0) { + HAB_HEADER_SET_SIZE(header, sizebytes); + HAB_HEADER_SET_TYPE(header, HAB_PAYLOAD_TYPE_EXPORT); + HAB_HEADER_SET_ID(header, vchan->otherend_id); + HAB_HEADER_SET_SESSION_ID(header, vchan->session_id); + ret = physical_channel_send(vchan->pchan, &header, exp, + HABMM_SOCKET_SEND_FLAGS_NON_BLOCKING); - if (ret != 0) { - pr_err("failed to export payload to the remote %d\n", ret); - return ret; + if (ret != 0) { + pr_err("failed to send imp msg %d, exp_id %d, vcid %x\n", + ret, export_id, vchan->id); + return ret; + } + + expected_ack.export_id = exp->export_id; + expected_ack.vcid_local = exp->vcid_local; + expected_ack.vcid_remote = exp->vcid_remote; + ret = hab_export_ack_wait(ctx, &expected_ack, vchan); + if (ret != 0) { + pr_err("failed to receive remote export ack %d on vc %x\n", + ret, vchan->id); + return ret; + } + + exp->pchan = vchan->pchan; + exp->vchan = vchan; + exp->ctx = ctx; } - expected_ack.export_id = exp->export_id; - expected_ack.vcid_local = exp->vcid_local; - expected_ack.vcid_remote = exp->vcid_remote; - ret = hab_export_ack_wait(ctx, &expected_ack, vchan); - if (ret != 0) { - pr_err("failed to receive remote export ack %d on vc %x\n", - ret, vchan->id); - return ret; - } - - exp->pchan = vchan->pchan; - exp->vchan = vchan; - exp->ctx = ctx; write_lock(&ctx->exp_lock); ctx->export_total++; list_add_tail(&exp->node, &ctx->exp_whse); write_unlock(&ctx->exp_lock); + exp_super = container_of(exp, struct export_desc_super, exp); + WRITE_ONCE(exp_super->exp_state, HAB_EXP_SUCCESS); + return ret; } +/* + * This function is a revoke function for habmm_hyp_grant_*(), + * only call this function when habmm_hyp_grant_*() returns + * success but exp hasn't been added to exp_whse. + * hab_hyp_grant_*() do 4 things: + * 1) add 1 to refcount of dma_buf. + * 2) alloc memory for struct export_desc_super. + * 3) alloc memory for struct exp_platform_data. + * 4) alloc idr. + * we revoke these 4 things in this function. we choose to call + * idr_remove before habmem_export_put() to unpublish this + * export desc as early as possible, however the racing between + * habmem_export_put() and other concurrent user is handled by + * state machine mechanism. + */ +static int habmem_hyp_grant_undo(struct uhab_context *ctx, + struct virtual_channel *vchan, + uint32_t export_id) +{ + struct export_desc *exp = NULL; + struct export_desc_super *exp_super = NULL; + int irqs_disabled = irqs_disabled(); + + exp = idr_find(&vchan->pchan->expid_idr, export_id); + if (!exp) { + pr_err("export vchan failed: exp_id %d, pchan %s\n", + export_id, vchan->pchan->name); + return -EINVAL; + } + + exp_super = container_of(exp, + struct export_desc_super, + exp); + + hab_spin_lock(&vchan->pchan->expid_lock, irqs_disabled); + idr_remove(&vchan->pchan->expid_idr, exp->export_id); + hab_spin_unlock(&vchan->pchan->expid_lock, irqs_disabled); + + exp->ctx = NULL; + return habmem_export_put(exp_super); +} + void habmem_export_get(struct export_desc_super *exp_super) { kref_get(&exp_super->refcount); @@ -315,8 +351,6 @@ int hab_mem_export(struct uhab_context *ctx, struct virtual_channel *vchan; int page_count; int compressed = 0; - struct export_desc *exp = NULL; - int irqs_disabled = irqs_disabled(); if (!ctx || !param || !param->sizebytes || ((param->sizebytes % PAGE_SIZE) != 0) @@ -357,31 +391,11 @@ int hab_mem_export(struct uhab_context *ctx, goto err; } - /* exp_desc will not be sent to remote during export in new protocol */ - if (vchan->pchan->mem_proto == 0) - ret = habmem_export_vchan(ctx, - vchan, - payload_size, - param->flags, - export_id); - else { - hab_spin_lock(&vchan->pchan->expid_lock, irqs_disabled); - exp = idr_find(&vchan->pchan->expid_idr, export_id); - hab_spin_unlock(&vchan->pchan->expid_lock, irqs_disabled); - if (!exp) { - pr_err("cannot find exp id %d on %s\n", export_id, vchan->pchan->name); - ret = -EINVAL; - goto err; - } - - write_lock_bh(&ctx->exp_lock); - ctx->export_total++; - list_add_tail(&exp->node, &ctx->exp_whse); - write_unlock_bh(&ctx->exp_lock); - } - + ret = habmem_export_vchan(ctx, vchan, payload_size, param->flags, export_id); if (!ret) param->exportid = export_id; + else + habmem_hyp_grant_undo(ctx, vchan, export_id); err: if (vchan) hab_vchan_put(vchan); @@ -392,8 +406,8 @@ int hab_mem_unexport(struct uhab_context *ctx, struct hab_unexport *param, int kernel) { - int ret = 0, found = 0; - struct export_desc *exp = NULL, *tmp = NULL; + int ret = 0; + struct export_desc *exp = NULL; struct export_desc_super *exp_super = NULL; struct virtual_channel *vchan; @@ -407,35 +421,37 @@ int hab_mem_unexport(struct uhab_context *ctx, goto err_novchan; } - write_lock_bh(&ctx->exp_lock); - list_for_each_entry_safe(exp, tmp, &ctx->exp_whse, node) { - if (param->exportid == exp->export_id && - vchan->pchan == exp->pchan) { - found = 1; - exp_super = container_of(exp, struct export_desc_super, exp); - if (exp_super->remote_imported == 0) - list_del(&exp->node); - else { - ret = -EBUSY; - write_unlock_bh(&ctx->exp_lock); - pr_err("remote has not unimported mem yet, vcid %x, exp_id %d, pchan %s\n", - vchan, - exp->export_id, - exp->pchan->name); - goto err_novchan; - } - break; - } - } - write_unlock_bh(&ctx->exp_lock); - - if (!found) { + spin_lock_bh(&vchan->pchan->expid_lock); + exp = idr_find(&vchan->pchan->expid_idr, param->exportid); + if (!exp) { + spin_unlock_bh(&vchan->pchan->expid_lock); + pr_err("unexp fail, cannot find exp id %d\n", param->exportid); ret = -EINVAL; goto err_novchan; } + exp_super = container_of(exp, struct export_desc_super, exp); + if (exp_super->exp_state == HAB_EXP_SUCCESS && + exp->ctx == ctx && + exp_super->remote_imported == 0) + idr_remove(&vchan->pchan->expid_idr, param->exportid); + else { + ret = exp_super->remote_imported == 0 ? -EINVAL : -EBUSY; + pr_err("unexp exp id %d fail, exp state %d, remote imp %d\n", + param->exportid, exp_super->exp_state, exp_super->remote_imported); + spin_unlock_bh(&vchan->pchan->expid_lock); + goto err_novchan; + } + spin_unlock_bh(&vchan->pchan->expid_lock); + + /* TODO: hab stat is not accurate after idr_remove and before list_del here */ + write_lock(&ctx->exp_lock); + list_del(&exp->node); + write_unlock(&ctx->exp_lock); + ret = habmem_hyp_revoke(exp->payload, exp->payload_count); if (ret) { + /* unrecoverable scenario*/ pr_err("Error found in revoke grant with ret %d\n", ret); goto err_novchan; } @@ -484,13 +500,14 @@ int hab_mem_import(struct uhab_context *ctx, HAB_HEADER_SET_TYPE(header, HAB_PAYLOAD_TYPE_IMPORT); HAB_HEADER_SET_ID(header, vchan->otherend_id); HAB_HEADER_SET_SESSION_ID(header, vchan->session_id); - ret = physical_channel_send(vchan->pchan, &header, &imp_data); + ret = physical_channel_send(vchan->pchan, &header, &imp_data, + HABMM_SOCKET_SEND_FLAGS_NON_BLOCKING); if (ret != 0) { - pr_err("failed to send import msg to the remote %d, exp_id %d, vcid %x\n", - ret, - param->exportid, - vchan->id); + pr_err("failed to send imp msg %d, exp_id %d, vcid %x\n", + ret, + param->exportid, + vchan->id); goto err_imp; } diff --git a/drivers/soc/qcom/hab/hab_msg.c b/drivers/soc/qcom/hab/hab_msg.c index 598da6313f33..41e3c372687e 100644 --- a/drivers/soc/qcom/hab/hab_msg.c +++ b/drivers/soc/qcom/hab/hab_msg.c @@ -267,7 +267,13 @@ static int hab_send_import_ack_fail(struct virtual_channel *vchan, HAB_HEADER_SET_TYPE(header, HAB_PAYLOAD_TYPE_IMPORT_ACK_FAIL); HAB_HEADER_SET_ID(header, vchan->otherend_id); HAB_HEADER_SET_SESSION_ID(header, vchan->session_id); - ret = physical_channel_send(vchan->pchan, &header, &export_id); + ret = physical_channel_send(vchan->pchan, &header, &export_id, + HABMM_SOCKET_SEND_FLAGS_NON_BLOCKING); + if (ret != 0) + pr_err("failed to send imp ack fail msg %d, exp_id %d, vcid %x\n", + ret, + export_id, + vchan->id); return ret; } @@ -293,7 +299,12 @@ static int hab_send_import_ack(struct virtual_channel *vchan, exp->pchan = NULL; exp->vchan = NULL; exp->ctx = NULL; - ret = physical_channel_send(vchan->pchan, &header, exp); + ret = physical_channel_send(vchan->pchan, &header, exp, + HABMM_SOCKET_SEND_FLAGS_NON_BLOCKING); + if (ret != 0) + pr_err("failed to send imp ack msg %d, vcid %x\n", + ret, vchan->id); + exp->pchan = vchan->pchan; exp->vchan = vchan; exp->ctx = vchan->ctx; @@ -349,6 +360,8 @@ static int hab_send_export_ack(struct virtual_channel *vchan, struct physical_channel *pchan, struct export_desc *exp) { + int ret = 0; + struct hab_export_ack exp_ack = { .export_id = exp->export_id, .vcid_local = exp->vcid_local, @@ -360,7 +373,13 @@ static int hab_send_export_ack(struct virtual_channel *vchan, HAB_HEADER_SET_TYPE(header, HAB_PAYLOAD_TYPE_EXPORT_ACK); HAB_HEADER_SET_ID(header, exp->vcid_local); HAB_HEADER_SET_SESSION_ID(header, vchan->session_id); - return physical_channel_send(pchan, &header, &exp_ack); + ret = physical_channel_send(pchan, &header, &exp_ack, + HABMM_SOCKET_SEND_FLAGS_NON_BLOCKING); + if (ret != 0) + pr_err("failed to send exp ack msg %d, vcid %x\n", + ret, vchan->id); + + return ret; } static int hab_receive_create_export_ack(struct physical_channel *pchan, @@ -686,12 +705,13 @@ int hab_msg_recv(struct physical_channel *pchan, uint32_t vchan_id = HAB_HEADER_GET_ID(*header); uint32_t session_id = HAB_HEADER_GET_SESSION_ID(*header); struct virtual_channel *vchan = NULL; - struct export_desc *exp, *exp_tmp; + struct export_desc *exp; struct export_desc_super *exp_desc_super = NULL; struct timespec64 ts = {0}; unsigned long long rx_mpm_tv; int found = 0; struct hab_import_data imp_data = {0}; + int irqs_disabled = irqs_disabled(); ret = hab_try_get_vchan(pchan, header, &vchan); if (ret != 0 || ((vchan == NULL) && (payload_type == HAB_PAYLOAD_TYPE_UNIMPORT))) @@ -801,38 +821,34 @@ int hab_msg_recv(struct physical_channel *pchan, case HAB_PAYLOAD_TYPE_IMPORT: if (physical_channel_read(pchan, &imp_data, sizeof(struct hab_import_data)) != - sizeof(struct hab_import_data)) + sizeof(struct hab_import_data)) { pr_err("corrupted import request, id %ld page %ld vcid %X on %s\n", - imp_data.exp_id, imp_data.page_cnt, vchan->id, pchan->name); - - write_lock_bh(&vchan->ctx->exp_lock); - //TODO: replace list walkthrough with idr_find() due to performance - list_for_each_entry_safe(exp, exp_tmp, &vchan->ctx->exp_whse, node) { - if ((imp_data.exp_id == exp->export_id) && (exp->pchan == vchan->pchan)) { - found = 1; - break; - } + imp_data.exp_id, imp_data.page_cnt, vchan->id, pchan->name); + break; } - if (found == 1) - if (imp_data.page_cnt != exp->payload_count) { - pr_err("request size mismatch, request %ld, actual %ld\n", - imp_data.page_cnt << PAGE_SHIFT, - exp->payload_count << PAGE_SHIFT); - found = 0; - } - if (found == 1) { + /* expid lock is hold to ensure the availability of exp node */ + hab_spin_lock(&pchan->expid_lock, irqs_disabled); + exp = idr_find(&pchan->expid_idr, imp_data.exp_id); + if ((exp != NULL) && (imp_data.page_cnt == exp->payload_count)) { + found = 1; exp_desc_super = container_of(exp, struct export_desc_super, exp); + } else + found = 0; + + if (found == 1 && (exp_desc_super->exp_state == HAB_EXP_SUCCESS)) { exp_desc_super->remote_imported = 1; + /* might sleep in Vhost & VirtIO HAB, need non-blocking send or RT Linux */ hab_send_import_ack(vchan, exp); pr_debug("remote imported exp id %d on vcid %x\n", exp->export_id, vchan->id); } else { - pr_err("cannot find requested exp id %ld on %s\n", - imp_data.exp_id, pchan->name); + pr_err("requested exp id %ld not found %d on %s\n", + imp_data.exp_id, found, pchan->name); + /* might sleep in Vhost & VirtIO HAB, need non-blocking send or RT Linux */ hab_send_import_ack_fail(vchan, imp_data.exp_id); } - write_unlock_bh(&vchan->ctx->exp_lock); + hab_spin_unlock(&pchan->expid_lock, irqs_disabled); break; case HAB_PAYLOAD_TYPE_IMPORT_ACK: diff --git a/drivers/soc/qcom/hab/hab_open.c b/drivers/soc/qcom/hab/hab_open.c index 3c530011f5e6..ab6d1cd7acc1 100644 --- a/drivers/soc/qcom/hab/hab_open.c +++ b/drivers/soc/qcom/hab/hab_open.c @@ -25,11 +25,18 @@ void hab_open_request_init(struct hab_open_request *request, int hab_open_request_send(struct hab_open_request *request) { struct hab_header header = HAB_HEADER_INITIALIZER; + int ret = 0; HAB_HEADER_SET_SIZE(header, sizeof(struct hab_open_send_data)); HAB_HEADER_SET_TYPE(header, request->type); - return physical_channel_send(request->pchan, &header, &request->xdata); + ret = physical_channel_send(request->pchan, &header, &request->xdata, + HABMM_SOCKET_SEND_FLAGS_NON_BLOCKING); + if (ret != 0) + pr_err("pchan %s failed to send open req msg %d\n", + request->pchan->name, ret); + + return ret; } /* @@ -256,11 +263,18 @@ int hab_open_receive_cancel(struct physical_channel *pchan, int hab_open_cancel_notify(struct hab_open_request *request) { struct hab_header header = HAB_HEADER_INITIALIZER; + int ret = 0; HAB_HEADER_SET_SIZE(header, sizeof(struct hab_open_send_data)); HAB_HEADER_SET_TYPE(header, HAB_PAYLOAD_TYPE_INIT_CANCEL); - return physical_channel_send(request->pchan, &header, &request->xdata); + ret = physical_channel_send(request->pchan, &header, &request->xdata, + HABMM_SOCKET_SEND_FLAGS_NON_BLOCKING); + if (ret != 0) + pr_err("pchan %s failed to send open cancel msg %d\n", + request->pchan->name, ret); + + return ret; } /* diff --git a/drivers/soc/qcom/hab/hab_stat.c b/drivers/soc/qcom/hab/hab_stat.c index c1d6a11cea90..57e2b69fc27a 100644 --- a/drivers/soc/qcom/hab/hab_stat.c +++ b/drivers/soc/qcom/hab/hab_stat.c @@ -62,11 +62,12 @@ int hab_stat_show_vchan(struct hab_driver *driver, read_lock(&pchan->vchans_lock); list_for_each_entry(vc, &pchan->vchannels, pnode) { ret = hab_stat_buffer_print(buf, size, - "%08X(%d:%d:%lu:%lu:%d) ", vc->id, + "%08X(%d:%d:%d:%ld:%ld:%d) ", vc->id, get_refcnt(vc->refcount), vc->otherend_closed, - (unsigned long)vc->tx_cnt, - (unsigned long)vc->rx_cnt, + vc->closed, + atomic64_read(&vc->tx_cnt), + atomic64_read(&vc->rx_cnt), vc->rx_inflight); } ret = hab_stat_buffer_print(buf, size, "\n"); @@ -123,14 +124,14 @@ static int print_ctx_total_expimp(struct uhab_context *ctx, int exim_size = 0; int ret = 0; - read_lock_bh(&ctx->exp_lock); + read_lock(&ctx->exp_lock); list_for_each_entry(exp, &ctx->exp_whse, node) { pfn_table = (struct compressed_pfns *)exp->payload; exim_size = get_pft_tbl_total_size(pfn_table); exp_total += exim_size; exp_cnt++; } - read_unlock_bh(&ctx->exp_lock); + read_unlock(&ctx->exp_lock); spin_lock_bh(&ctx->imp_lock); list_for_each_entry(exp, &ctx->imp_whse, node) { @@ -151,7 +152,7 @@ static int print_ctx_total_expimp(struct uhab_context *ctx, else return 0; - read_lock_bh(&ctx->exp_lock); + read_lock(&ctx->exp_lock); hab_stat_buffer_print(buf, size, "export[expid:vcid:size]: "); list_for_each_entry(exp, &ctx->exp_whse, node) { pfn_table = (struct compressed_pfns *)exp->payload; @@ -161,7 +162,7 @@ static int print_ctx_total_expimp(struct uhab_context *ctx, exp->vcid_local, exim_size); } hab_stat_buffer_print(buf, size, "\n"); - read_unlock_bh(&ctx->exp_lock); + read_unlock(&ctx->exp_lock); spin_lock_bh(&ctx->imp_lock); hab_stat_buffer_print(buf, size, "import[expid:vcid:size]: "); diff --git a/drivers/soc/qcom/hab/hab_vhost.c b/drivers/soc/qcom/hab/hab_vhost.c index febfc35dd2a2..5e2c9a611880 100644 --- a/drivers/soc/qcom/hab/hab_vhost.c +++ b/drivers/soc/qcom/hab/hab_vhost.c @@ -187,6 +187,12 @@ static void tx_worker(struct vhost_hab_pchannel *vh_pchan) pr_err("hab_msg_recv error %d\n", ret); total_len += out_len; + + if (vh_pchan->pchan->sequence_rx + 1 != header.sequence) + pr_err("%s: expected sequence_rx is %u, received is %u\n", + vh_pchan->pchan->name, + vh_pchan->pchan->sequence_rx, + header.sequence); vh_pchan->pchan->sequence_rx = header.sequence; } @@ -991,7 +997,8 @@ err_unlock: int physical_channel_send(struct physical_channel *pchan, struct hab_header *header, - void *payload) + void *payload, + unsigned int flags) { struct vhost_hab_pchannel *vh_pchan = pchan->hyp_data; struct vhost_virtqueue *vq; @@ -999,6 +1006,9 @@ int physical_channel_send(struct physical_channel *pchan, struct vhost_hab_send_node *send_node; size_t sizebytes = HAB_HEADER_GET_SIZE(*header); + /* Only used in virtio arch */ + (void)flags; + if (!vh_pchan) { pr_err("pchan is not ready yet\n"); return -ENODEV; diff --git a/drivers/soc/qcom/hab/hab_virtio.c b/drivers/soc/qcom/hab/hab_virtio.c index 99cd3906c943..47044f7796b3 100644 --- a/drivers/soc/qcom/hab/hab_virtio.c +++ b/drivers/soc/qcom/hab/hab_virtio.c @@ -237,8 +237,15 @@ static void virthab_recv_rxq(unsigned long p) /* parse and handle the input */ spin_unlock(&vpc->lock[HAB_PCHAN_RX_VQ]); rc = hab_msg_recv(pchan, (struct hab_header *)inbuf); - pchan->sequence_rx = ((struct hab_header *)inbuf)->sequence; + spin_lock(&vpc->lock[HAB_PCHAN_RX_VQ]); + if (pchan->sequence_rx + 1 != ((struct hab_header *)inbuf)->sequence) + pr_err("%s: expected sequence_rx is %u, received is %u\n", + pchan->name, + pchan->sequence_rx, + ((struct hab_header *)inbuf)->sequence); + pchan->sequence_rx = ((struct hab_header *)inbuf)->sequence; + if (rc && rc != -EINVAL) pr_err("%s hab_msg_recv wrong %d\n", pchan->name, rc); @@ -274,7 +281,7 @@ static void virthab_recv_rxq_task(struct virtqueue *vq) if (!vpc) return; - tasklet_schedule(&vpc->task); + tasklet_hi_schedule(&vpc->task); } static void init_pool_list(void *pool, int buf_size, int buf_num, @@ -913,18 +920,22 @@ void dump_hab_wq(struct physical_channel *pchan) {}; static struct vh_buf_header *get_vh_buf_header(spinlock_t *lock, unsigned long *irq_flags, struct list_head *list, - wait_queue_head_t *wq, int *cnt) + wait_queue_head_t *wq, int *cnt, + int nonblocking_flag) { struct vh_buf_header *hd = NULL; unsigned long flags = *irq_flags; + if (list_empty(list) && nonblocking_flag) + return ERR_PTR(-EAGAIN); + while (list_empty(list)) { spin_unlock_irqrestore(lock, flags); wait_event(*wq, !list_empty(list)); spin_lock_irqsave(lock, flags); } + hd = list_first_entry(list, struct vh_buf_header, node); - BUG_ON(!hd); list_del(&hd->node); *irq_flags = flags; @@ -933,8 +944,8 @@ static struct vh_buf_header *get_vh_buf_header(spinlock_t *lock, } int physical_channel_send(struct physical_channel *pchan, - struct hab_header *header, - void *payload) + struct hab_header *header, void *payload, + unsigned int flags) { size_t sizebytes = HAB_HEADER_GET_SIZE(*header); struct virtio_pchan_link *link = @@ -943,8 +954,9 @@ int physical_channel_send(struct physical_channel *pchan, struct scatterlist sgout[1]; char *outbuf = NULL; int rc; - unsigned long flags; + unsigned long lock_flags; struct vh_buf_header *hd = NULL; + int nonblocking_flag = flags & HABMM_SOCKET_SEND_FLAGS_NON_BLOCKING; if (link->vpc == NULL) { pr_err("%s: %s link->vpc not ready\n", __func__, pchan->name); @@ -958,23 +970,31 @@ int physical_channel_send(struct physical_channel *pchan, return -EINVAL; } - spin_lock_irqsave(&vpc->lock[HAB_PCHAN_TX_VQ], flags); + spin_lock_irqsave(&vpc->lock[HAB_PCHAN_TX_VQ], lock_flags); if (vpc->pchan_ready) { /* pick the available outbuf */ if (sizebytes <= OUT_SMALL_BUF_SIZE) { hd = get_vh_buf_header(&vpc->lock[HAB_PCHAN_TX_VQ], - &flags, &vpc->s_list, - &vpc->out_wq, &vpc->s_cnt); + &lock_flags, &vpc->s_list, + &vpc->out_wq, &vpc->s_cnt, + nonblocking_flag); } else if (sizebytes <= OUT_MEDIUM_BUF_NUM) { hd = get_vh_buf_header(&vpc->lock[HAB_PCHAN_TX_VQ], - &flags, &vpc->m_list, - &vpc->out_wq, &vpc->m_cnt); + &lock_flags, &vpc->m_list, + &vpc->out_wq, &vpc->m_cnt, + nonblocking_flag); } else { hd = get_vh_buf_header(&vpc->lock[HAB_PCHAN_TX_VQ], - &flags, &vpc->l_list, - &vpc->out_wq, &vpc->l_cnt); + &lock_flags, &vpc->l_list, + &vpc->out_wq, &vpc->l_cnt, + nonblocking_flag); + } + + if (IS_ERR(hd) && nonblocking_flag) { + spin_unlock_irqrestore(&vpc->lock[HAB_PCHAN_TX_VQ], lock_flags); + pr_info("get_vh_buf_header failed in non-blocking mode\n"); + return PTR_ERR(hd); } - BUG_ON(!hd); if (HAB_HEADER_GET_TYPE(*header) == HAB_PAYLOAD_TYPE_PROFILE) { struct habmm_xing_vm_stat *pstat = @@ -1010,7 +1030,7 @@ int physical_channel_send(struct physical_channel *pchan, pr_err("%s pchan not ready\n", pchan->name); rc = -ENODEV; } - spin_unlock_irqrestore(&vpc->lock[HAB_PCHAN_TX_VQ], flags); + spin_unlock_irqrestore(&vpc->lock[HAB_PCHAN_TX_VQ], lock_flags); return 0; } diff --git a/drivers/soc/qcom/hab/qvm_comm.c b/drivers/soc/qcom/hab/qvm_comm.c index b50a704f657e..4786e7f620b4 100644 --- a/drivers/soc/qcom/hab/qvm_comm.c +++ b/drivers/soc/qcom/hab/qvm_comm.c @@ -1,6 +1,7 @@ // SPDX-License-Identifier: GPL-2.0-only /* * Copyright (c) 2016-2021, The Linux Foundation. All rights reserved. + * Copyright (c) 2023, Qualcomm Innovation Center, Inc. All rights reserved. */ #include "hab.h" #include "hab_qvm.h" @@ -51,7 +52,8 @@ int physical_channel_read(struct physical_channel *pchan, int physical_channel_send(struct physical_channel *pchan, struct hab_header *header, - void *payload) + void *payload, + unsigned int flags) { size_t sizebytes = HAB_HEADER_GET_SIZE(*header); struct qvm_channel *dev = (struct qvm_channel *)pchan->hyp_data; @@ -59,6 +61,9 @@ int physical_channel_send(struct physical_channel *pchan, uint32_t buf_size = PIPE_SHMEM_SIZE; int irqs_disabled = irqs_disabled(); + /* Only used in virtio arch */ + (void)flags; + if (total_size > buf_size) return -EINVAL; /* too much data for ring */ @@ -189,6 +194,9 @@ void physical_channel_rx_dispatch(unsigned long data) } else if (ret != sizeof(header)) break; /* no data available */ + if (pchan->sequence_rx + 1 != header.sequence) + pr_err("%s: expected sequence_rx is %u, received is %u\n", + pchan->name, pchan->sequence_rx, header.sequence); pchan->sequence_rx = header.sequence; /* log msg recv timestamp: enter pchan dispatcher */ diff --git a/drivers/soc/qcom/hgsl/Makefile b/drivers/soc/qcom/hgsl/Makefile index f06db8686535..e0a5ddd04be8 100644 --- a/drivers/soc/qcom/hgsl/Makefile +++ b/drivers/soc/qcom/hgsl/Makefile @@ -5,6 +5,8 @@ qcom_hgsl-objs = hgsl.o \ hgsl_hyp.o \ hgsl_hyp_socket.o +qcom_hgsl-$(CONFIG_SYSFS) += hgsl_sysfs.o +qcom_hgsl-$(CONFIG_DEBUG_FS) += hgsl_debugfs.o qcom_hgsl-$(CONFIG_QCOM_HGSL_TCSR_SIGNAL) += hgsl_tcsr.o obj-$(CONFIG_QCOM_HGSL) += qcom_hgsl.o diff --git a/drivers/soc/qcom/hgsl/hgsl.c b/drivers/soc/qcom/hgsl/hgsl.c index 200d5c607139..0720195bb11d 100644 --- a/drivers/soc/qcom/hgsl/hgsl.c +++ b/drivers/soc/qcom/hgsl/hgsl.c @@ -24,7 +24,8 @@ #include "hgsl.h" #include "hgsl_tcsr.h" #include "hgsl_memory.h" -#include "hgsl_hyp.h" +#include "hgsl_sysfs.h" +#include "hgsl_debugfs.h" #define HGSL_DEVICE_NAME "hgsl" #define HGSL_DEV_NUM 1 @@ -41,6 +42,9 @@ #define CMDBATCH_EOF 0x00000100 #define ECP_MAX_NUM_IB1 (2000) +/* ibDescs stored in indirect buffer */ +#define CMDBATCH_INDIRECT 0x00000200 + /* Max retry count of waiting for free space of doorbell queue. */ #define HGSL_QFREE_MAX_RETRY_COUNT (500) #define GLB_DB_SRC_ISSUEIB_IRQ_ID_0 TCSR_SRC_IRQ_ID_0 @@ -89,6 +93,9 @@ enum HGSL_DBQ_METADATA_COMMAND_INFO { #define HGSL_DBQ_WRITE_INDEX_OFFSET_IN_DWORD (0x0) #define HGSL_DBQ_READ_INDEX_OFFSET_IN_DWORD (0x1) +#define HGSL_DBQ_IBDESC_SHORT_WAIT_MSEC (5) +#define HGSL_DBQ_IBDESC_LONG_WAIT_MSEC (30000) + enum HGSL_DBQ_METADATA_COOPERATIVE_RESET_INFO { HGSL_DBQ_HOST_TO_GVM_HARDRESET_REQ, HGSL_DBQ_GVM_TO_HOST_HARDRESET_DISPATCH_IN_BUSY, @@ -101,6 +108,18 @@ enum HGSL_DBQ_METADATA_CONTEXT_OFFSET_INFO { HGSL_DBQ_METADATA_CTXT_TOTAL_ENTITY_NUM, }; +enum HGSL_DBQ_IBDESC_REQUEST_TYPE { + HGSL_DBQ_IBDESC_REQUEST_ACQUIRE, + HGSL_DBQ_IBDESC_REQUEST_RELEASE, +}; + +enum HGSL_DBQ_IBDESC_WAIT_TYPE { + /* If caller can retry, use short wait */ + HGSL_DBQ_IBDESC_SHORT_WAIT, + /* If caller not capable of retrying, use long wait */ + HGSL_DBQ_IBDESC_LONG_WAIT, +}; + /* DBQ structure * IBs storage | reserved | w.idx/r.idx | ctxt.info | hard reset | batch ibs | * 0 1K 1.5K 2K 5.5K 6K | @@ -148,6 +167,13 @@ static struct hgsl_context *hgsl_get_context(struct qcom_hgsl *hgsl, uint32_t context_id); static void hgsl_put_context(struct hgsl_context *ctxt); +static bool dbq_check_ibdesc_state(struct qcom_hgsl *hgsl, struct hgsl_context *ctxt, + uint32_t request_type); + +static int dbq_wait_free_ibdesc(struct qcom_hgsl *hgsl, + struct hgsl_context *context, uint32_t request_type, + uint32_t wait_type); + static uint32_t hgsl_dbq_get_state_info(uint32_t *va_base, uint32_t command, uint32_t ctxt_id, uint32_t offset) { @@ -215,6 +241,8 @@ static void hgsl_dbq_set_state_info(uint32_t *va_base, uint32_t command, /* HFI command define. */ #define HTOF_MSG_ISSUE_CMD 130 +#define HFI_HEADER_CMD_SIZE_MAX (255) + #define MSG_ISSUE_INF_SZ() (sizeof(struct hgsl_db_cmds) >> 2) #define MSG_ISSUE_IBS_SZ(numIB) \ ((numIB) * (sizeof(struct hgsl_fw_ib_desc) >> 2)) @@ -1110,7 +1138,7 @@ static int hgsl_db_issue_cmd(struct hgsl_priv *priv, struct hgsl_fw_ib_desc ib_descs[], uint64_t user_profile_gpuaddr) { - int ret; + int ret = 0; uint32_t msg_dwords; uint32_t msg_buf_sz; struct hgsl_db_cmds *cmds; @@ -1119,6 +1147,8 @@ static int hgsl_db_issue_cmd(struct hgsl_priv *priv, struct db_msg_id db_msg_id; struct doorbell_queue *dbq = ctxt->dbq; struct qcom_hgsl *hgsl = priv->dev; + bool is_batch_ibdesc = false; + uint8_t *dst; ret = hgsl_dbcq_issue_cmd(priv, ctxt, num_ibs, gmu_cmd_flags, timestamp, ib_descs, user_profile_gpuaddr); @@ -1131,6 +1161,10 @@ static int hgsl_db_issue_cmd(struct hgsl_priv *priv, db_msg_id.msg_id = HTOF_MSG_ISSUE_CMD; db_msg_id.seq_no = atomic_inc_return(&dbq->seq_num); + if ((num_ibs > (UINT_MAX / (sizeof(struct hgsl_fw_ib_desc) >> 2))) || + (MSG_ISSUE_INF_SZ() > (UINT_MAX - MSG_ISSUE_IBS_SZ(num_ibs)))) + return -EINVAL; + msg_dwords = MSG_ISSUE_INF_SZ() + MSG_ISSUE_IBS_SZ(num_ibs); msg_buf_sz = ALIGN(msg_dwords, 4) << 2; @@ -1141,9 +1175,15 @@ static int hgsl_db_issue_cmd(struct hgsl_priv *priv, } if ((msg_buf_sz >= dbq->data.dwords) || (msg_buf_sz > (MSG_SZ_MASK >> MSG_SZ_SHIFT))) { - LOGE("msg size %d exceed queue size %d or max hfi cmd size %d", - msg_buf_sz, dbq->data.dwords, (MSG_SZ_MASK >> MSG_SZ_SHIFT)); - return -EINVAL; + if ((MSG_ISSUE_IBS_SZ(num_ibs) << 2) <= dbq->ibdesc_max_size) { + msg_dwords = MSG_ISSUE_INF_SZ(); + msg_buf_sz = ALIGN(msg_dwords, 4) << 2; + is_batch_ibdesc = true; + LOGI("Number of IBs exceed. Proceeding with CMDBATCH_IBDESC"); + } else { + dev_err(hgsl->dev, "number of IBs exceed\n"); + return -EINVAL; + } } ret = hgsl_db_next_timestamp(ctxt, timestamp); @@ -1162,7 +1202,29 @@ static int hgsl_db_issue_cmd(struct hgsl_priv *priv, cmds->cmd_flags = gmu_cmd_flags; cmds->timestamp = *timestamp; cmds->user_profile_gpuaddr = user_profile_gpuaddr; - memcpy(cmds->ib_descs, ib_descs, sizeof(ib_descs[0]) * num_ibs); + if (!is_batch_ibdesc) { + memcpy(cmds->ib_descs, ib_descs, sizeof(ib_descs[0]) * num_ibs); + } else { + mutex_lock(&dbq->lock); + /* wait for the buffer */ + ret = dbq_wait_free_ibdesc(hgsl, ctxt, + HGSL_DBQ_IBDESC_REQUEST_ACQUIRE, + HGSL_DBQ_IBDESC_SHORT_WAIT); + if (ret) { + mutex_unlock(&dbq->lock); + goto err; + } + dbq->ibdesc_priv.buf_inuse = true; + dbq->ibdesc_priv.context_id = ctxt->context_id; + dbq->ibdesc_priv.timestamp = *timestamp; + cmds->cmd_flags = gmu_cmd_flags | CMDBATCH_INDIRECT; + cmds->ib_desc_gmuaddr = dbq->gmuaddr + + (HGSL_DBQ_IBDESC_BASE_OFFSET_IN_DWORD << 2); + dst = (uint8_t *)dbq->vbase + + (HGSL_DBQ_IBDESC_BASE_OFFSET_IN_DWORD << 2); + memcpy(dst, ib_descs, sizeof(ib_descs[0]) * num_ibs); + mutex_unlock(&dbq->lock); + } req.msg_has_response = 0; req.msg_has_ret_packet = 0; @@ -1184,6 +1246,7 @@ static int hgsl_db_issue_cmd(struct hgsl_priv *priv, if (ret == 0) ctxt->queued_ts = *timestamp; +err: hgsl_free(cmds); return ret; } @@ -1335,6 +1398,8 @@ static int hgsl_dbq_init(struct qcom_hgsl *hgsl, dbq->state = DB_STATE_Q_FAULT; dbq->dma = dma_buf; dbq->dbq_idx = dbq_idx; + dbq->gmuaddr = hgsl->dbq_info[dbq_idx].gmuaddr; + dbq->ibdesc_max_size = hgsl->dbq_info[dbq_idx].ibdesc_max_size; atomic_set(&dbq->seq_num, 0); dma_buf_begin_cpu_access(dbq->dma, DMA_BIDIRECTIONAL); @@ -1640,6 +1705,77 @@ out: return ret; } +static bool dbq_check_ibdesc_state(struct qcom_hgsl *hgsl, + struct hgsl_context *ctxt, uint32_t request_type) +{ + struct doorbell_queue *dbq = ctxt->dbq; + bool wait_required = false; + + if (dbq == NULL || !dbq->ibdesc_priv.buf_inuse) + return wait_required; + + if (request_type == HGSL_DBQ_IBDESC_REQUEST_RELEASE) { + if (ctxt->context_id == dbq->ibdesc_priv.context_id) + wait_required = true; + } else if (request_type == HGSL_DBQ_IBDESC_REQUEST_ACQUIRE) + wait_required = true; + + return wait_required; +} + +static int dbq_wait_free_ibdesc(struct qcom_hgsl *hgsl, + struct hgsl_context *context, uint32_t request_type, + uint32_t wait_type) +{ + struct hgsl_context *ctxt = NULL; + struct doorbell_queue *dbq = context->dbq; + signed long start; + bool expired = false; + int timeout = 0; + int ret = 0; + + if (!dbq_check_ibdesc_state(hgsl, context, request_type)) + return 0; + + ctxt = hgsl_get_context(hgsl, dbq->ibdesc_priv.context_id); + if (!ctxt) { + LOGE("Invalid context id %d\n", dbq->ibdesc_priv.context_id); + return -EINVAL; + } + + if (wait_type == HGSL_DBQ_IBDESC_SHORT_WAIT) + timeout = msecs_to_jiffies(HGSL_DBQ_IBDESC_SHORT_WAIT_MSEC); + else if (wait_type == HGSL_DBQ_IBDESC_LONG_WAIT) + timeout = msecs_to_jiffies(HGSL_DBQ_IBDESC_LONG_WAIT_MSEC); + + start = jiffies; + do { + ret = hgsl_check_shadow_timestamp(ctxt, GSL_TIMESTAMP_RETIRED, + dbq->ibdesc_priv.timestamp, &expired); + if (ret || expired) + break; + mutex_unlock(&dbq->lock); + if (msleep_interruptible(1)) + ret = -EINTR; + mutex_lock(&dbq->lock); + if (ret == -EINTR) + break; + } while ((jiffies - start) < timeout); + + if (expired) + dbq->ibdesc_priv.buf_inuse = false; + else { + if (ret && ret != -EINTR && ret != -EAGAIN) + LOGE("Wait to free ibdesc failed %d", ret); + if (!ret) + ret = -EAGAIN; + } + + hgsl_put_context(ctxt); + + return ret; +} + static int hgsl_ctxt_create_dbq(struct hgsl_priv *priv, struct hgsl_hab_channel_t *hab_channel, struct hgsl_context *ctxt, uint32_t dbq_info, bool dbq_info_checked) @@ -1690,11 +1826,36 @@ static int hgsl_ctxt_create_dbq(struct hgsl_priv *priv, static int hgsl_ctxt_destroy(struct hgsl_priv *priv, struct hgsl_hab_channel_t *hab_channel, - uint32_t context_id, uint32_t *rval) + uint32_t context_id, uint32_t *rval, bool can_retry) { struct hgsl_context *ctxt = NULL; int ret; bool put_channel = false; + struct doorbell_queue *dbq = NULL; + + ctxt = hgsl_get_context(priv->dev, context_id); + if (!ctxt) { + LOGE("Invalid context id %d\n", context_id); + ret = -EINVAL; + goto out; + } + + dbq = ctxt->dbq; + if (dbq != NULL) { + mutex_lock(&dbq->lock); + /* if ibdesc is held by the context, release it here */ + ret = dbq_wait_free_ibdesc(priv->dev, ctxt, + HGSL_DBQ_IBDESC_REQUEST_RELEASE, + HGSL_DBQ_IBDESC_LONG_WAIT); + if (ret && !can_retry) + dbq->ibdesc_priv.buf_inuse = false; + mutex_unlock(&dbq->lock); + if (ret && can_retry) { + hgsl_put_context(ctxt); + goto out; + } + } + hgsl_put_context(ctxt); ctxt = hgsl_remove_context(priv, context_id); if (!ctxt) { @@ -1858,7 +2019,7 @@ out: LOGD("%d", params.ctxthandle); if (ret) { if (ctxt_created) - hgsl_ctxt_destroy(priv, hab_channel, params.ctxthandle, NULL); + hgsl_ctxt_destroy(priv, hab_channel, params.ctxthandle, NULL, false); else if (ctxt && (params.ctxthandle < HGSL_CONTEXT_NUM)) { if (!ctxt->is_fe_shadow) _cleanup_shadow(hab_channel, ctxt); @@ -1895,7 +2056,7 @@ static int hgsl_ioctl_ctxt_destroy(struct file *filep, unsigned long arg) goto out; } - ret = hgsl_ctxt_destroy(priv, hab_channel, params.ctxthandle, ¶ms.rval); + ret = hgsl_ctxt_destroy(priv, hab_channel, params.ctxthandle, ¶ms.rval, true); if (ret == 0) { if (copy_to_user(USRPTR(arg), ¶ms, sizeof(params))) @@ -3176,6 +3337,8 @@ static int hgsl_open(struct inode *inodep, struct file *filep) priv->dev = hgsl; filep->private_data = priv; + hgsl_sysfs_client_init(priv); + hgsl_debugfs_client_init(priv); out: if (ret != 0) kfree(priv); @@ -3242,6 +3405,8 @@ static int _hgsl_release(struct hgsl_priv *priv) struct qcom_hgsl *hgsl = priv->dev; uint32_t i; int ret; + hgsl_debugfs_client_release(priv); + hgsl_sysfs_client_release(priv); read_lock(&hgsl->ctxt_lock); for (i = 0; i < HGSL_CONTEXT_NUM; i++) { @@ -3249,7 +3414,7 @@ static int _hgsl_release(struct hgsl_priv *priv) (hgsl->contexts[i] != NULL) && (priv == hgsl->contexts[i]->priv)) { read_unlock(&hgsl->ctxt_lock); - hgsl_ctxt_destroy(priv, NULL, i, NULL); + hgsl_ctxt_destroy(priv, NULL, i, NULL, false); read_lock(&hgsl->ctxt_lock); } } @@ -3899,6 +4064,8 @@ static int qcom_hgsl_probe(struct platform_device *pdev) hgsl_dev->default_iocoherency = of_property_read_bool(pdev->dev.of_node, "default_iocoherency"); platform_set_drvdata(pdev, hgsl_dev); + hgsl_sysfs_init(pdev); + hgsl_debugfs_init(pdev); return 0; @@ -3912,6 +4079,8 @@ static int qcom_hgsl_remove(struct platform_device *pdev) struct qcom_hgsl *hgsl = platform_get_drvdata(pdev); struct hgsl_tcsr *tcsr_sender, *tcsr_receiver; int i; + hgsl_debugfs_release(pdev); + hgsl_sysfs_release(pdev); for (i = 0; i < HGSL_TCSR_NUM; i++) { tcsr_sender = hgsl->tcsr[i][HGSL_TCSR_ROLE_SENDER]; diff --git a/drivers/soc/qcom/hgsl/hgsl.h b/drivers/soc/qcom/hgsl/hgsl.h index c8e18b97c67c..e8bf09d17d17 100644 --- a/drivers/soc/qcom/hgsl/hgsl.h +++ b/drivers/soc/qcom/hgsl/hgsl.h @@ -56,14 +56,23 @@ struct db_buffer { void *vaddr; }; +struct dbq_ibdesc_priv { + bool buf_inuse; + uint32_t context_id; + uint32_t timestamp; +}; + struct doorbell_queue { struct dma_buf *dma; struct dma_buf_map map; void *vbase; + uint64_t gmuaddr; struct db_buffer data; uint32_t state; int tcsr_idx; uint32_t dbq_idx; + struct dbq_ibdesc_priv ibdesc_priv; + uint32_t ibdesc_max_size; struct mutex lock; atomic_t seq_num; }; @@ -125,6 +134,12 @@ struct qcom_hgsl { spinlock_t isync_timeline_lock; atomic64_t total_mem_size; bool default_iocoherency; + + /* Debug nodes */ + struct kobject sysfs; + struct kobject *clients_sysfs; + struct dentry *debugfs; + struct dentry *clients_debugfs; }; /** @@ -169,6 +184,14 @@ struct hgsl_priv { struct list_head mem_allocated; atomic64_t total_mem_size; + + /* sysfs stuff */ + struct kobject kobj; + struct kobject sysfs_client; + struct kobject sysfs_mem_size; + struct dentry *debugfs_client; + struct dentry *debugfs_mem; + struct dentry *debugfs_memtype; }; diff --git a/drivers/soc/qcom/hgsl/hgsl_debugfs.c b/drivers/soc/qcom/hgsl/hgsl_debugfs.c new file mode 100644 index 000000000000..7f4abc9e8ded --- /dev/null +++ b/drivers/soc/qcom/hgsl/hgsl_debugfs.c @@ -0,0 +1,143 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved. + * + */ + +#include +#include + +#include "hgsl.h" +#include "hgsl_debugfs.h" + +static int hgsl_client_mem_show(struct seq_file *s, void *unused) +{ + struct hgsl_priv *priv = s->private; + struct hgsl_mem_node *tmp = NULL; + + seq_printf(s, "%16s %16s %10s %10s\n", + "gpuaddr", "size", "flags", "type"); + + mutex_lock(&priv->lock); + list_for_each_entry(tmp, &priv->mem_allocated, node) { + seq_printf(s, "%p %16llx %10x %10d\n", + tmp->memdesc.gpuaddr, + tmp->memdesc.size, + tmp->flags, + tmp->memtype + ); + } + mutex_unlock(&priv->lock); + + return 0; +} +DEFINE_SHOW_ATTRIBUTE(hgsl_client_mem); + +static int hgsl_client_memtype_show(struct seq_file *s, void *unused) +{ + struct hgsl_priv *priv = s->private; + struct hgsl_mem_node *tmp = NULL; + int i; + int memtype; + + static struct { + char *name; + size_t size; + } gpu_mem_types[] = { + {"any", 0}, + {"framebuffer", 0}, + {"renderbbuffer", 0}, + {"arraybuffer", 0}, + {"elementarraybuffer", 0}, + {"vertexarraybuffer", 0}, + {"texture", 0}, + {"surface", 0}, + {"eglsurface", 0}, + {"gl", 0}, + {"cl", 0}, + {"cl_buffer_map", 0}, + {"cl_buffer_unmap", 0}, + {"cl_image_map", 0}, + {"cl_image_unmap", 0}, + {"cl_kernel_stack", 0}, + {"cmds", 0}, + {"2d", 0}, + {"egl_image", 0}, + {"egl_shadow", 0}, + {"multisample", 0}, + }; + + for (i = 0; i < ARRAY_SIZE(gpu_mem_types); i++) + gpu_mem_types[i].size = 0; + + mutex_lock(&priv->lock); + list_for_each_entry(tmp, &priv->mem_allocated, node) { + memtype = GET_MEMTYPE(tmp->flags); + if (memtype < ARRAY_SIZE(gpu_mem_types)) + gpu_mem_types[memtype].size += tmp->memdesc.size; + } + mutex_unlock(&priv->lock); + + seq_printf(s, "%16s %16s\n", "type", "size"); + for (i = 0; i < ARRAY_SIZE(gpu_mem_types); i++) { + if (gpu_mem_types[i].size != 0) + seq_printf(s, "%16s %16d\n", + gpu_mem_types[i].name, + gpu_mem_types[i].size); + } + + + return 0; +} +DEFINE_SHOW_ATTRIBUTE(hgsl_client_memtype); + +int hgsl_debugfs_client_init(struct hgsl_priv *priv) +{ + struct qcom_hgsl *hgsl = priv->dev; + unsigned char name[16]; + struct dentry *ret; + + snprintf(name, sizeof(name), "%d", priv->pid); + ret = debugfs_create_dir(name, + hgsl->clients_debugfs); + if (IS_ERR(ret)) { + pr_warn("Create debugfs proc node failed.\n"); + return PTR_ERR(ret); + } + + priv->debugfs_client = ret; + priv->debugfs_mem = debugfs_create_file("mem", 0444, + priv->debugfs_client, + priv, + &hgsl_client_mem_fops); + + priv->debugfs_memtype = debugfs_create_file("obj_types", 0444, + priv->debugfs_client, + priv, + &hgsl_client_memtype_fops); + + return 0; +} + +void hgsl_debugfs_client_release(struct hgsl_priv *priv) +{ + debugfs_remove_recursive(priv->debugfs_client); +} + +void hgsl_debugfs_init(struct platform_device *pdev) +{ + struct qcom_hgsl *hgsl_dev = platform_get_drvdata(pdev); + struct dentry *root; + + root = debugfs_create_dir("hgsl", NULL); + + hgsl_dev->debugfs = root; + hgsl_dev->clients_debugfs = debugfs_create_dir("clients", root); +} + +void hgsl_debugfs_release(struct platform_device *pdev) +{ + struct qcom_hgsl *hgsl = platform_get_drvdata(pdev); + + debugfs_remove_recursive(hgsl->debugfs); +} diff --git a/drivers/soc/qcom/hgsl/hgsl_debugfs.h b/drivers/soc/qcom/hgsl/hgsl_debugfs.h new file mode 100644 index 000000000000..4676c6de3ebb --- /dev/null +++ b/drivers/soc/qcom/hgsl/hgsl_debugfs.h @@ -0,0 +1,40 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved. + * + */ +#ifndef __HGSL_DEBUGFS_H +#define __HGSL_DEBUGFS_H + +#include +#include + +#ifdef CONFIG_DEBUG_FS +int hgsl_debugfs_client_init(struct hgsl_priv *priv); +void hgsl_debugfs_client_release(struct hgsl_priv *priv); + +void hgsl_debugfs_init(struct platform_device *pdev); +void hgsl_debugfs_release(struct platform_device *pdev); +#else +static int hgsl_debugfs_client_init(struct hgsl_priv *priv) +{ + return 0; +} + +void hgsl_debugfs_client_release(struct hgsl_priv *priv) +{ + +} + +void hgsl_debugfs_init(struct platform_device *pdev) +{ + +} +void hgsl_debugfs_release(struct platform_device *pdev) +{ + +} +#endif + +#endif /* __HGSL_DEBUGFS_H */ + diff --git a/drivers/soc/qcom/hgsl/hgsl_hyp.c b/drivers/soc/qcom/hgsl/hgsl_hyp.c index fbf660a11e56..6d375bdbabff 100644 --- a/drivers/soc/qcom/hgsl/hgsl_hyp.c +++ b/drivers/soc/qcom/hgsl/hgsl_hyp.c @@ -2202,6 +2202,19 @@ int hgsl_hyp_get_dbq_info(struct hgsl_hyp_priv_t *priv, uint32_t dbq_idx, LOGE("gsl_rpc_read_uint32_l failed, %d", ret); goto out; } + ret = gsl_rpc_read_uint64_l(recv_buf, &dbq_info->gmuaddr); + if (ret) + LOGW("gsl_rpc_read_uint64_l failed, %d", ret); + else { + ret = gsl_rpc_read_uint32_l(recv_buf, + &dbq_info->ibdesc_max_size); + if (ret) + LOGW("gsl_rpc_read_uint32_l failed, %d", ret); + } + if (ret) { + dbq_info->ibdesc_max_size = 0; + ret = 0; + } dbq_info->size = (dbq_info->size + (0x1000 - 1)) & (~(0x1000 - 1)); ret = habmm_import(hab_channel->socket, (void **)&dma_buf, dbq_info->size, diff --git a/drivers/soc/qcom/hgsl/hgsl_hyp.h b/drivers/soc/qcom/hgsl/hgsl_hyp.h index 090cea1a1941..ff38b1be4981 100644 --- a/drivers/soc/qcom/hgsl/hgsl_hyp.h +++ b/drivers/soc/qcom/hgsl/hgsl_hyp.h @@ -441,6 +441,8 @@ struct hgsl_dbq_info { int32_t queue_off_dwords; uint32_t db_signal; struct dma_buf *dma_buf; + uint64_t gmuaddr; + uint32_t ibdesc_max_size; struct hgsl_hab_channel_t *hab_channel; }; diff --git a/drivers/soc/qcom/hgsl/hgsl_memory.c b/drivers/soc/qcom/hgsl/hgsl_memory.c index 116acd556878..cec168ac7017 100644 --- a/drivers/soc/qcom/hgsl/hgsl_memory.c +++ b/drivers/soc/qcom/hgsl/hgsl_memory.c @@ -173,6 +173,10 @@ static void hgsl_free_pages(struct hgsl_mem_node *mem_node) struct page *p = mem_node->pages[i]; page_order = compound_order(p); + + mod_node_page_state(page_pgdat(p), NR_KERNEL_MISC_RECLAIMABLE, + -(1 << page_order)); + __free_pages(p, page_order); i += 1 << page_order; } @@ -509,6 +513,9 @@ static int hgsl_alloc_pages(struct device *dev, uint32_t requested_pcount, _dma_cache_op(dev, page, pcount, GSL_CACHEFLAGS_FLUSH); } + mod_node_page_state(page_pgdat(page), NR_KERNEL_MISC_RECLAIMABLE, + (1 << order)); + return pcount; } diff --git a/drivers/soc/qcom/hgsl/hgsl_memory.h b/drivers/soc/qcom/hgsl/hgsl_memory.h index af594ba407bb..a441daccbadb 100644 --- a/drivers/soc/qcom/hgsl/hgsl_memory.h +++ b/drivers/soc/qcom/hgsl/hgsl_memory.h @@ -13,6 +13,33 @@ #include "hgsl_types.h" #include "hgsl_utils.h" +#define GSL_MEMTYPE_MASK 0x0000FF00 +#define GSL_MEMTYPE_SHIFT 8 +#define GET_MEMTYPE(x) \ + ((x & GSL_MEMTYPE_MASK) >> GSL_MEMTYPE_SHIFT) +#define GSL_MEMTYPE_OBJECTANY 0x0 +#define GSL_MEMTYPE_FRAMEBUFFER 0x1 +#define GSL_MEMTYPE_RENDERBUFFER 0x2 +#define GSL_MEMTYPE_ARRAYBUFFER 0x3 +#define GSL_MEMTYPE_ELEMENTARRAYBUFFER 0x4 +#define GSL_MEMTYPE_VERTEXARRAYBUFFER 0x5 +#define GSL_MEMTYPE_TEXTURE 0x6 +#define GSL_MEMTYPE_SURFACE 0x7 +#define GSL_MEMTYPE_EGL_SURFACE 0x8 +#define GSL_MEMTYPE_GL 0x9 +#define GSL_MEMTYPE_CL 0xa +#define GSL_MEMTYPE_CL_BUFFER_MAP 0xb +#define GSL_MEMTYPE_CL_BUFFER_NOMAP 0xc +#define GSL_MEMTYPE_CL_IMAGE_MAP 0xd +#define GSL_MEMTYPE_CL_IMAGE_NOMAP 0xe +#define GSL_MEMTYPE_CL_KERNEL_STACK 0xf +#define GSL_MEMTYPE_COMMAND 0x10 +#define GSL_MEMTYPE_2D 0x11 +#define GSL_MEMTYPE_EGL_IMAGE 0x12 +#define GSL_MEMTYPE_EGL_SHADOW 0x13 +#define GSL_MEMTYPE_MULTISAMPLE 0x14 +#define GSL_MEMTYPE_VISIBLE_MAS 0x15 +#define GSL_MEMTYPE_KERNEL 0xff #define HGSL_MEM_META_MAX_SIZE 128 enum gsl_user_mem_type_t { GSL_USER_MEM_TYPE_PMEM = 0x00000000, diff --git a/drivers/soc/qcom/hgsl/hgsl_sync.c b/drivers/soc/qcom/hgsl/hgsl_sync.c index 2425eceb2abc..60b56d73049c 100644 --- a/drivers/soc/qcom/hgsl/hgsl_sync.c +++ b/drivers/soc/qcom/hgsl/hgsl_sync.c @@ -325,14 +325,16 @@ int hgsl_isync_timeline_create(struct hgsl_priv *priv, idr_preload(GFP_KERNEL); spin_lock(&hgsl->isync_timeline_lock); idr = idr_alloc(&hgsl->isync_timeline_idr, timeline, 1, 0, GFP_NOWAIT); - spin_unlock(&hgsl->isync_timeline_lock); - idr_preload_end(); - if (idr > 0) { timeline->id = idr; *timeline_id = idr; ret = 0; - } else + } + spin_unlock(&hgsl->isync_timeline_lock); + idr_preload_end(); + + /* allocate IDR failed */ + if (ret != 0) kfree(timeline); return ret; diff --git a/drivers/soc/qcom/hgsl/hgsl_sysfs.c b/drivers/soc/qcom/hgsl/hgsl_sysfs.c new file mode 100644 index 000000000000..176adc40bf17 --- /dev/null +++ b/drivers/soc/qcom/hgsl/hgsl_sysfs.c @@ -0,0 +1,149 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved. + */ + +#include +#include + +#include "hgsl.h" +#include "hgsl_sysfs.h" + +struct hgsl_sysfs_client_attr { + struct attribute attr; + ssize_t (*show)(struct kobject *kobj, + struct hgsl_sysfs_client_attr *attr, + char *buf); + ssize_t (*store)(struct kobject *kobj, + struct hgsl_sysfs_client_attr *attr, + const char *buf, + ssize_t count); +}; + +struct hgsl_sysfs_client_malloc_attr { + struct hgsl_sysfs_client_attr attr; + ssize_t (*show)(struct hgsl_priv *priv, char *buf); +}; + +static ssize_t hgsl_sysfs_client_malloc_show(struct hgsl_priv *priv, + char *buf) +{ + return scnprintf(buf, PAGE_SIZE, "%lld\n", + atomic64_read(&priv->total_mem_size)); +} + +static ssize_t hgsl_sysfs_client_show(struct kobject *kobj, + struct hgsl_sysfs_client_attr *_attr, char *buf) +{ + struct hgsl_sysfs_client_malloc_attr *client_attrib = + container_of(_attr, struct hgsl_sysfs_client_malloc_attr, attr); + struct hgsl_priv *priv = + container_of(kobj, struct hgsl_priv, sysfs_client); + + return client_attrib->show(priv, buf); +} + +static struct hgsl_sysfs_client_malloc_attr hgsl_sysfs_client_malloc_attr = { + .attr = __ATTR(mem_alloc, 0444, hgsl_sysfs_client_show, NULL), + .show = hgsl_sysfs_client_malloc_show, +}; + +static struct attribute *malloc_entry_attrs[] = { + &hgsl_sysfs_client_malloc_attr.attr.attr, + NULL, +}; +ATTRIBUTE_GROUPS(malloc_entry); + +static ssize_t hgsl_malloc_sysfs_show(struct kobject *kobj, + struct attribute *_attr, char *buf) +{ + struct hgsl_sysfs_client_attr *pattrib = + container_of(_attr, struct hgsl_sysfs_client_attr, attr); + + return pattrib->show(kobj, pattrib, buf); +} + +static const struct sysfs_ops hgsl_malloc_sysfs_ops = { + .show = hgsl_malloc_sysfs_show, +}; + +static struct kobj_type hgsl_sysfs_client_type = { + .sysfs_ops = &hgsl_malloc_sysfs_ops, + .default_groups = malloc_entry_groups, +}; + +int hgsl_sysfs_client_init(struct hgsl_priv *priv) +{ + int ret = 0; + struct qcom_hgsl *hgsl = priv->dev; + char name[9]; + + snprintf(name, sizeof(name), "%d", priv->pid); + + ret = kobject_init_and_add(&priv->sysfs_client, + &hgsl_sysfs_client_type, + hgsl->clients_sysfs, + name); + + if (unlikely(ret != 0)) { + kobject_put(&priv->sysfs_client); + pr_warn("Create sysfs proc node failed.\n"); + } + + return ret; +} + +void hgsl_sysfs_client_release(struct hgsl_priv *priv) +{ + kobject_put(&priv->sysfs_client); +} + +/* Global GPU memory usage */ +static ssize_t total_mem_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct qcom_hgsl *hgsl = dev_get_drvdata(dev); + + return scnprintf(buf, PAGE_SIZE, "%lld\n", hgsl->total_mem_size); +} + +static DEVICE_ATTR_RO(total_mem); + +static const struct attribute *_attrs[] = { + &dev_attr_total_mem.attr, + NULL, +}; + +int hgsl_sysfs_init(struct platform_device *pdev) +{ + struct qcom_hgsl *hgsl = platform_get_drvdata(pdev); + int ret; + + hgsl->clients_sysfs = kobject_create_and_add("clients", + &hgsl->class_dev->kobj); + + if (hgsl->clients_sysfs == NULL) { + ret = -EINVAL; + goto exit; + } + + ret = sysfs_create_files(&hgsl->class_dev->kobj, _attrs); + if (!ret) { + /* Notify userspace */ + kobject_uevent(&hgsl->dev->kobj, KOBJ_ADD); + } + +exit: + return ret; +} + + +void hgsl_sysfs_release(struct platform_device *pdev) +{ + struct qcom_hgsl *hgsl; + + hgsl = platform_get_drvdata(pdev); + sysfs_remove_files(&hgsl->dev->kobj, _attrs); + kobject_put(hgsl->clients_sysfs); +} + diff --git a/drivers/soc/qcom/hgsl/hgsl_sysfs.h b/drivers/soc/qcom/hgsl/hgsl_sysfs.h new file mode 100644 index 000000000000..4a6b9a18e46d --- /dev/null +++ b/drivers/soc/qcom/hgsl/hgsl_sysfs.h @@ -0,0 +1,36 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved. + * + */ +#ifndef __HGSL_SYSFS_H +#define __HGSL_SYSFS_H + +#include +#include + +#ifdef CONFIG_SYSFS +int hgsl_sysfs_client_init(struct hgsl_priv *priv); +void hgsl_sysfs_client_release(struct hgsl_priv *priv); +int hgsl_sysfs_init(struct platform_device *pdev); +void hgsl_sysfs_release(struct platform_device *pdev); +#else +int hgsl_sysfs_client_init(struct hgsl_priv *priv) +{ + return 0; +} + +void hgsl_sysfs_client_release(struct hgsl_priv *priv) +{ +} +int hgsl_sysfs_init(struct platform_device *pdev) +{ + return 0; +} +void hgsl_sysfs_release(struct platform_device *pdev) +{ +} +#endif /* CONFIG_SYSFS */ + +#endif /* __HGSL_SYSFS_H */ + diff --git a/drivers/soc/qcom/llcc-qcom.c b/drivers/soc/qcom/llcc-qcom.c index d5e4ec4c741c..b0c51f913c37 100644 --- a/drivers/soc/qcom/llcc-qcom.c +++ b/drivers/soc/qcom/llcc-qcom.c @@ -496,6 +496,20 @@ static struct llcc_slice_config lemans_data[] = { {LLCC_WRTCH, 31, 512, 1, 1, 0x00FF, 0x0, 0, 0, 0, 0, 1, 0, 0}, }; +static struct llcc_slice_config qcs605_data[] = { + {LLCC_CPUSS, 1, 512, 1, 0, 0xF, 0x0, 0, 0, 1, 1, 1}, + {LLCC_VIDSC0, 2, 256, 2, 1, 0x3, 0x0, 0, 0, 1, 1, 0}, + {LLCC_VIDSC1, 3, 256, 2, 1, 0x3, 0x0, 0, 0, 1, 1, 0}, + {LLCC_VOICE, 5, 512, 1, 0, 0xF, 0x0, 0, 0, 1, 1, 0}, + {LLCC_AUDIO, 6, 512, 1, 0, 0xF, 0x0, 0, 0, 1, 1, 0}, + {LLCC_MDM, 8, 512, 1, 0, 0xF, 0x0, 0, 0, 1, 1, 0}, + {LLCC_CMPT, 10, 512, 1, 0, 0xF, 0x0, 0, 0, 1, 1, 0}, + {LLCC_GPU, 12, 512, 1, 0, 0xF, 0x0, 0, 0, 1, 1, 0}, + {LLCC_MMUHWT, 13, 512, 1, 0, 0xF, 0x0, 0, 0, 1, 0, 1}, + {LLCC_AUDHW, 22, 512, 1, 1, 0xF, 0x0, 0, 0, 1, 1, 0}, +}; + + static const struct qcom_llcc_config diwali_cfg = { .sct_data = diwali_data, .size = ARRAY_SIZE(diwali_data), @@ -575,6 +589,11 @@ static const struct qcom_llcc_config lemans_cfg = { .size = ARRAY_SIZE(lemans_data), }; +static const struct qcom_llcc_config qcs605_cfg = { + .sct_data = qcs605_data, + .size = ARRAY_SIZE(qcs605_data), +}; + static struct llcc_drv_data *drv_data = (void *) -EPROBE_DEFER; /** @@ -1312,6 +1331,7 @@ static const struct of_device_id qcom_llcc_of_match[] = { { .compatible = "qcom,cinder-llcc", .data = &cinder_cfg }, { .compatible = "qcom,lemans-llcc", .data = &lemans_cfg }, { .compatible = "qcom,crow-llcc", .data = &crow_cfg }, + { .compatible = "qcom,qcs605-llcc", .data = &qcs605_cfg }, { } }; MODULE_DEVICE_TABLE(of, qcom_llcc_of_match); diff --git a/drivers/soc/qcom/qcom_aoss.c b/drivers/soc/qcom/qcom_aoss.c index 12a7f9ad1a7e..e1de2682e2af 100644 --- a/drivers/soc/qcom/qcom_aoss.c +++ b/drivers/soc/qcom/qcom_aoss.c @@ -1,5 +1,6 @@ // SPDX-License-Identifier: GPL-2.0 /* + * Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved. * Copyright (c) 2020-2021, The Linux Foundation. All rights reserved. * Copyright (c) 2019, Linaro Ltd */ @@ -17,6 +18,7 @@ #include #include #include +#include #define QMP_DESC_MAGIC 0x0 #define QMP_DESC_VERSION 0x4 @@ -79,6 +81,7 @@ struct qmp_rx_client { * @qdss_clk: QDSS clock hw struct * @pd_data: genpd data * @cooling_devs: thermal cooling devices + * @ds_entry: deepsleep entry path */ struct qmp { void __iomem *msgram; @@ -102,6 +105,7 @@ struct qmp { #if IS_ENABLED(CONFIG_DEBUG_FS) struct dentry *debugfs_file; #endif /* CONFIG_DEBUG_FS */ + bool ds_entry; }; struct qmp_pd { @@ -173,9 +177,11 @@ static int qmp_open(struct qmp *qmp) return -EINVAL; } - qmp->qmp_rx.rx_buf = devm_kzalloc(qmp->dev, qmp->qmp_rx.rx_size, GFP_KERNEL); - if (!qmp->qmp_rx.rx_buf) - return -ENOMEM; + if (!qmp->ds_entry) { + qmp->qmp_rx.rx_buf = devm_kzalloc(qmp->dev, qmp->qmp_rx.rx_size, GFP_KERNEL); + if (!qmp->qmp_rx.rx_buf) + return -ENOMEM; + } /* Ack remote core's link state */ val = readl(qmp->msgram + QMP_DESC_UCORE_LINK_STATE); @@ -213,6 +219,8 @@ static int qmp_open(struct qmp *qmp) goto timeout_close_channel; } + qmp->ds_entry = false; + return 0; timeout_close_channel: @@ -302,6 +310,9 @@ int qmp_send(struct qmp *qmp, const void *data, size_t len) if (WARN_ON(IS_ERR_OR_NULL(qmp) || !data)) return -EINVAL; + if (qmp->ds_entry) + return -ENXIO; + if (WARN_ON(len + sizeof(u32) > qmp->size)) return -EINVAL; @@ -786,9 +797,40 @@ static int aoss_qmp_mbox_restore(struct device *dev) return 0; } +static int aoss_qmp_mbox_suspend_noirq(struct device *dev) +{ + struct qmp *qmp = dev_get_drvdata(dev); + + if (pm_suspend_via_firmware()) { + qmp->ds_entry = true; + dev_info(dev, "AOSS: Deep sleep entry\n"); + } + + return 0; +} + +static int aoss_qmp_mbox_resume_early(struct device *dev) +{ + struct qmp *qmp = dev_get_drvdata(dev); + int ret = 0; + + if (pm_suspend_via_firmware()) { + ret = qmp_open(qmp); + + if (ret < 0) + dev_err(dev, "QMP restore failed, ret = %d\n", ret); + + dev_info(dev, "AOSS: Deep sleep exit\n"); + } + + return ret; +} + static const struct dev_pm_ops aoss_qmp_mbox_pm_ops = { .freeze_late = aoss_qmp_mbox_freeze, .restore_early = aoss_qmp_mbox_restore, + .suspend_noirq = aoss_qmp_mbox_suspend_noirq, + .resume_early = aoss_qmp_mbox_resume_early, }; static const struct of_device_id qmp_dt_match[] = { diff --git a/drivers/soc/qcom/qcom_ipcc.c b/drivers/soc/qcom/qcom_ipcc.c index b54a0a8dfb66..05ae5f8d7e9d 100644 --- a/drivers/soc/qcom/qcom_ipcc.c +++ b/drivers/soc/qcom/qcom_ipcc.c @@ -10,6 +10,9 @@ #include #include #include +#ifdef CONFIG_PM_SLEEP +#include +#endif /* IPCC Register offsets */ #define IPCC_REG_SEND_ID 0x0C @@ -58,6 +61,7 @@ struct ipcc_mbox_chan { u16 signal_id; struct mbox_chan *chan; struct ipcc_protocol_data *proto_data; + u16 is_signal_enabled; }; static inline u32 qcom_ipcc_get_packed_id(u16 client_id, u16 signal_id) @@ -102,6 +106,33 @@ static irqreturn_t qcom_ipcc_irq_fn(int irq, void *data) return IRQ_HANDLED; } +#ifdef CONFIG_PM_SLEEP +static void qcom_ipcc_update_irq_status(struct irq_domain *domain, + irq_hw_number_t hwirq, bool is_enabled) +{ + struct ipcc_mbox_chan *ipcc_mbox_chan; + int chan_id; + struct ipcc_protocol_data *proto_data = domain->host_data; + + for (chan_id = 0; chan_id < proto_data->mbox.num_chans; chan_id++) { + ipcc_mbox_chan = proto_data->chans[chan_id].con_priv; + if (!ipcc_mbox_chan) + break; + + if (ipcc_mbox_chan->client_id == qcom_ipcc_get_client_id(hwirq) && + ipcc_mbox_chan->signal_id == qcom_ipcc_get_signal_id(hwirq)) { + ipcc_mbox_chan->is_signal_enabled = is_enabled; + break; + } + } +} +#else +static void qcom_ipcc_update_irq_status(struct irq_domain *domain, + irq_hw_number_t hwirq, bool is_enabled) +{ +} +#endif + static void qcom_ipcc_mask_irq(struct irq_data *irqd) { struct ipcc_protocol_data *proto_data; @@ -115,6 +146,7 @@ static void qcom_ipcc_mask_irq(struct irq_data *irqd) "%s: Disabling interrupts for: client_id: %u; signal_id: %u\n", __func__, sender_client_id, sender_signal_id); + qcom_ipcc_update_irq_status(irqd->domain, hwirq, 0); writel(hwirq, proto_data->base + IPCC_REG_RECV_SIGNAL_DISABLE); } @@ -131,6 +163,7 @@ static void qcom_ipcc_unmask_irq(struct irq_data *irqd) "%s: Enabling interrupts for: client_id: %u; signal_id: %u\n", __func__, sender_client_id, sender_signal_id); + qcom_ipcc_update_irq_status(irqd->domain, hwirq, 1); writel(hwirq, proto_data->base + IPCC_REG_RECV_SIGNAL_ENABLE); } @@ -303,6 +336,75 @@ static int qcom_ipcc_setup_mbox(struct ipcc_protocol_data *proto_data, return mbox_controller_register(mbox); } +#ifdef CONFIG_PM_SLEEP +static void qcom_ipcc_restore_unmask_irq(struct device *dev) +{ + struct ipcc_mbox_chan *ipcc_mbox_chan; + int chan_id; + u32 packed_id; + struct ipcc_protocol_data *proto_data = dev_get_drvdata(dev); + + if (!proto_data || !proto_data->num_chans) + return; + + for (chan_id = 0; chan_id < proto_data->num_chans; chan_id++) { + ipcc_mbox_chan = proto_data->chans[chan_id].con_priv; + if (!ipcc_mbox_chan) + break; + + packed_id = qcom_ipcc_get_packed_id(ipcc_mbox_chan->client_id, + ipcc_mbox_chan->signal_id); + if (ipcc_mbox_chan->is_signal_enabled) { + dev_dbg(dev, + "%s: restore 0x%lx for client_id: %u signal_id: %u\n", + __func__, packed_id, ipcc_mbox_chan->client_id, + ipcc_mbox_chan->signal_id); + writel(packed_id, + proto_data->base + IPCC_REG_RECV_SIGNAL_ENABLE); + } + } +} + +static int qcom_ipcc_pm_suspend(struct device *dev) +{ + return 0; +} + +static int qcom_ipcc_pm_resume(struct device *dev) +{ + int virq; + struct irq_desc *desc; + const char *name = "null"; + u32 packed_id; + struct ipcc_protocol_data *proto_data = dev_get_drvdata(dev); + + if (pm_suspend_via_firmware()) { + qcom_ipcc_restore_unmask_irq(dev); + return 0; + } + + packed_id = readl(proto_data->base + IPCC_REG_RECV_ID); + if (packed_id == IPCC_NO_PENDING_IRQ) + return 0; + + virq = irq_find_mapping(proto_data->irq_domain, packed_id); + desc = irq_to_desc(virq); + if (desc == NULL) + name = "stray irq"; + else if (desc->action && desc->action->name) + name = desc->action->name; + + pr_warn("%s: %d triggered %s (client-id: %u; signal-id: %u\n", + __func__, virq, name, qcom_ipcc_get_client_id(packed_id), + qcom_ipcc_get_signal_id(packed_id)); + + return 0; +} +#else +#define qcom_ipcc_pm_suspend NULL +#define qcom_ipcc_pm_resume NULL +#endif + static int qcom_ipcc_probe(struct platform_device *pdev) { struct ipcc_protocol_data *proto_data; @@ -354,7 +456,8 @@ static int qcom_ipcc_probe(struct platform_device *pdev) } ret = devm_request_irq(&pdev->dev, proto_data->irq, qcom_ipcc_irq_fn, - IRQF_TRIGGER_HIGH | IRQF_NO_SUSPEND, name, proto_data); + IRQF_TRIGGER_HIGH | IRQF_NO_SUSPEND | + IRQF_NO_THREAD, name, proto_data); if (ret < 0) { dev_err(&pdev->dev, "Failed to register the irq: %d\n", ret); goto err_req_irq; @@ -390,12 +493,21 @@ static const struct of_device_id qcom_ipcc_of_match[] = { }; MODULE_DEVICE_TABLE(of, qcom_ipcc_of_match); +#ifdef CONFIG_PM_SLEEP +static const struct dev_pm_ops qcom_ipcc_dev_pm_ops = { + SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(qcom_ipcc_pm_suspend, qcom_ipcc_pm_resume) +}; +#endif + static struct platform_driver qcom_ipcc_driver = { .probe = qcom_ipcc_probe, .remove = qcom_ipcc_remove, .driver = { .name = "qcom_ipcc", .of_match_table = qcom_ipcc_of_match, +#ifdef CONFIG_PM_SLEEP + .pm = &qcom_ipcc_dev_pm_ops, +#endif }, }; diff --git a/drivers/soc/qcom/slatecom_interface.c b/drivers/soc/qcom/slatecom_interface.c index afe4b3ee44d3..bb324d73c2b8 100644 --- a/drivers/soc/qcom/slatecom_interface.c +++ b/drivers/soc/qcom/slatecom_interface.c @@ -10,6 +10,7 @@ #include #include #include +#include #include #include #include @@ -112,6 +113,12 @@ enum slatecom_state { SLATECOM_STATE_SLATE_SSR }; +struct rf_power_clk_data { + struct clk *clk; /* clock regulator handle */ + const char *name; /* clock name */ + bool is_enabled; /* is this clock enabled? */ +}; + struct slatedaemon_priv { void *pil_h; int app_status; @@ -133,6 +140,7 @@ struct slatedaemon_priv { struct workqueue_struct *slatecom_wq; struct wakeup_source slatecom_ws; struct qseecom_handle *qseecom_handle; + struct rf_power_clk_data *rf_clk_2; /* rf clock */ }; static void *slatecom_intf_drv; @@ -463,10 +471,99 @@ fail: return -EFAULT; } +static int dt_parse_clk_info(struct device *dev, + struct rf_power_clk_data **clk_data) +{ + int ret = -EINVAL; + struct rf_power_clk_data *clk = NULL; + struct device_node *np = dev->of_node; + + *clk_data = NULL; + if (of_parse_phandle(np, "clocks", 0)) { + clk = devm_kzalloc(dev, sizeof(*clk), GFP_KERNEL); + if (!clk) { + ret = -ENOMEM; + goto err; + } + + /* Allocated 20 bytes size buffer for clock name string */ + clk->name = devm_kzalloc(dev, 20, GFP_KERNEL); + + /* Parse clock name from node */ + ret = of_property_read_string_index(np, "clock-names", 0, + &(clk->name)); + if (ret < 0) { + pr_err("%s: reading \"clock-names\" failed\n", + __func__); + return ret; + } + + clk->clk = devm_clk_get(dev, clk->name); + if (IS_ERR(clk->clk)) { + ret = PTR_ERR(clk->clk); + pr_err("%s: failed to get %s, ret (%d)\n", + __func__, clk->name, ret); + clk->clk = NULL; + return ret; + } + *clk_data = clk; + } else { + pr_err("%s: clocks is not provided in device tree\n", __func__); + } + +err: + return ret; +} + +static int rf_clk_enable(struct rf_power_clk_data *clk) +{ + int rc = 0; + + pr_debug("%s: %s\n", __func__, clk->name); + + /* Get the clock handle for vreg */ + if (!clk->clk || clk->is_enabled) { + pr_err("%s: error - node: %p, clk->is_enabled:%d\n", + __func__, clk->clk, clk->is_enabled); + return -EINVAL; + } + + rc = clk_prepare_enable(clk->clk); + if (rc) { + pr_err("%s: failed to enable %s, rc(%d)\n", + __func__, clk->name, rc); + return rc; + } + + clk->is_enabled = true; + return rc; +} + +static int rf_clk_disable(struct rf_power_clk_data *clk) +{ + int rc = 0; + + pr_debug("%s: %s\n", __func__, clk->name); + + /* Get the clock handle for vreg */ + if (!clk->clk || !clk->is_enabled) { + pr_err("%s: error - node: %p, clk->is_enabled:%d\n", + __func__, clk->clk, clk->is_enabled); + return -EINVAL; + } + clk_disable_unprepare(clk->clk); + + clk->is_enabled = false; + return rc; +} + static int slatecom_fw_load(struct slatedaemon_priv *priv) { int ret = 0; + if (dev->rf_clk_2) + rf_clk_enable(dev->rf_clk_2); + if (!priv->pil_h) { pr_err("%s: Getting rproc handle\n", __func__); ret = slatecom_get_rproc_handle(priv); @@ -481,6 +578,7 @@ static int slatecom_fw_load(struct slatedaemon_priv *priv) goto fail; } slate_boot_status = 1; + dev->slate_unload = false; pr_info("%s: SLATE image is loaded\n", __func__); return 0; } @@ -842,6 +940,7 @@ static int send_boot_cmd_to_slate(struct slate_ui_data *ui_obj_msg) break; case TWM_EXIT: twm_exit = true; + dev->slate_unload = true; break; case AON_APP_RUNNING: slate_app_running = true; @@ -851,6 +950,7 @@ static int send_boot_cmd_to_slate(struct slate_ui_data *ui_obj_msg) ret = slatecom_fw_load(dev); else { pr_info("slate is already loaded\n"); + dev->slate_unload = false; ret = -EFAULT; } break; @@ -1097,7 +1197,8 @@ static int slate_daemon_probe(struct platform_device *pdev) slate_pdev = pdev; setup_pmic_gpio15(); ssr_register(); - + dt_parse_clk_info(&pdev->dev, + &dev->rf_clk_2); return 0; } @@ -1153,6 +1254,8 @@ static int ssr_slate_cb(struct notifier_block *this, send_uevent(&slatee); set_slate_bt_state(false); set_slate_dsp_state(false); + if (dev->rf_clk_2) + rf_clk_enable(dev->rf_clk_2); break; case QCOM_SSR_BEFORE_POWERUP: pr_debug("Slate before powerup\n"); @@ -1167,6 +1270,8 @@ static int ssr_slate_cb(struct notifier_block *this, if (dev->slatecom_current_state == SLATECOM_STATE_INIT || dev->slatecom_current_state == SLATECOM_STATE_SLATE_SSR) queue_work(dev->slatecom_wq, &dev->slatecom_up_work); + if (dev->rf_clk_2) + rf_clk_disable(dev->rf_clk_2); break; } return NOTIFY_DONE; diff --git a/drivers/soc/qcom/slatecom_spi.c b/drivers/soc/qcom/slatecom_spi.c index dd9a7f346cbd..67faac3ca9d2 100644 --- a/drivers/soc/qcom/slatecom_spi.c +++ b/drivers/soc/qcom/slatecom_spi.c @@ -229,11 +229,15 @@ int slatecom_set_spi_state(enum slatecom_spi_state state) { struct slate_spi_priv *slate_spi = container_of(slate_com_drv, struct slate_spi_priv, lhandle); - const struct device spi_dev = slate_spi->spi->master->dev; ktime_t time_start, delta; s64 time_elapsed; struct slate_context clnt_handle; int ret = 0; + struct device spi_dev; + + if (!slate_com_drv) + return -ENODEV; + spi_dev = slate_spi->spi->master->dev; if (req_irq_flag && state == SLATECOM_SPI_FREE) { ret = request_threaded_irq(slate_irq, NULL, slate_irq_tasklet_hndlr, @@ -297,6 +301,8 @@ void add_to_irq_list(struct cb_data *data) static uint8_t is_slatecom_ready(void) { + if (slate_com_drv == NULL) + pr_err("driver not probed yet\n"); return (slate_com_drv != NULL ? 1 : 0); } @@ -311,15 +317,15 @@ static void slate_spi_reinit_xfer(struct spi_transfer *xfer) static int read_slate_locl(enum slatecom_req_type req_type, uint32_t no_of_words, void *buf) { - struct slate_context clnt_handle; - struct slate_spi_priv *spi = - container_of(slate_com_drv, struct slate_spi_priv, lhandle); + struct slate_spi_priv *spi = NULL; int ret = 0; - if (!buf) - return -EINVAL; - + if (!slate_com_drv || !buf) { + pr_err("driver not probed yet or buf is empty\n"); + return -ENODEV; + } + spi = container_of(slate_com_drv, struct slate_spi_priv, lhandle); clnt_handle.slate_spi = spi; switch (req_type) { @@ -604,8 +610,11 @@ static void slate_irq_tasklet_hndlr_l(void) uint32_t irq_buf[5] = {0}; uint32_t cmnd_reg = 0; struct slate_context clnt_handle; - struct slate_spi_priv *spi = - container_of(slate_com_drv, struct slate_spi_priv, lhandle); + struct slate_spi_priv *spi = NULL; + + if (!slate_com_drv) + return; + spi = container_of(slate_com_drv, struct slate_spi_priv, lhandle); clnt_handle.slate_spi = spi; ret = slatecom_reg_read_internal(&clnt_handle, SLATE_STATUS_REG, 5, &irq_buf[0]); @@ -1053,7 +1062,12 @@ int slatecom_fifo_write(void *handle, uint32_t num_words, uint32_t size; int ret = 0; uint8_t cmnd = 0; - struct spi_device *spi = get_spi_device(); + struct spi_device *spi; + + if (!is_slatecom_ready()) + return -ENODEV; + + spi = get_spi_device(); if (!handle || !write_buf || num_words == 0 || num_words > SLATE_SPI_MAX_WORDS) { @@ -1061,9 +1075,6 @@ int slatecom_fifo_write(void *handle, uint32_t num_words, return -EINVAL; } - if (!is_slatecom_ready()) - return -ENODEV; - if (spi_state == SLATECOM_SPI_BUSY) { SLATECOM_ERR("Device busy\n"); return -EBUSY; @@ -1716,9 +1727,11 @@ static int slatecom_pm_resume(struct device *dev) { struct slate_context clnt_handle; int ret = 0; - struct slate_spi_priv *spi = - container_of(slate_com_drv, struct slate_spi_priv, lhandle); + struct slate_spi_priv *spi = NULL; + if (!slate_com_drv) + return -ENODEV; + spi = container_of(slate_com_drv, struct slate_spi_priv, lhandle); SLATECOM_ERR("entry\n"); free_irq(slate_irq, spi); ret = request_threaded_irq(slate_irq, NULL, slate_irq_tasklet_hndlr, @@ -1799,9 +1812,11 @@ static int slatecom_pm_runtime_resume(struct device *dev) { struct slate_context clnt_handle; int ret = 0; - struct slate_spi_priv *spi = - container_of(slate_com_drv, struct slate_spi_priv, lhandle); + struct slate_spi_priv *spi = NULL; + if (!slate_com_drv) + return -ENODEV; + spi = container_of(slate_com_drv, struct slate_spi_priv, lhandle); SLATECOM_INFO("entry\n"); clnt_handle.slate_spi = spi; @@ -1848,8 +1863,11 @@ static int slatecom_pm_restore(struct device *dev) { struct slate_context clnt_handle; int ret = 0; - struct slate_spi_priv *spi = - container_of(slate_com_drv, struct slate_spi_priv, lhandle); + struct slate_spi_priv *spi = NULL; + + if (!slate_com_drv) + return -ENODEV; + spi = container_of(slate_com_drv, struct slate_spi_priv, lhandle); if (atomic_read(&slate_is_spi_active)) { SLATECOM_INFO("Slatecom in restore state\n"); diff --git a/drivers/soundwire/qcom.c b/drivers/soundwire/qcom.c index a2e7a8110f84..3a3d0a6fe9e9 100644 --- a/drivers/soundwire/qcom.c +++ b/drivers/soundwire/qcom.c @@ -146,7 +146,8 @@ struct qcom_swrm_ctrl { u32 intr_mask; u8 rcmd_id; u8 wcmd_id; - struct qcom_swrm_port_config pconfig[QCOM_SDW_MAX_PORTS]; + /* Port numbers are 1 - 14 */ + struct qcom_swrm_port_config pconfig[QCOM_SDW_MAX_PORTS + 1]; struct sdw_stream_runtime *sruntime[SWRM_MAX_DAIS]; enum sdw_slave_status status[SDW_MAX_DEVICES + 1]; int (*reg_read)(struct qcom_swrm_ctrl *ctrl, int reg, u32 *val); diff --git a/drivers/spi/spi-bcm-qspi.c b/drivers/spi/spi-bcm-qspi.c index bd7c7fc73961..c79797c06cda 100644 --- a/drivers/spi/spi-bcm-qspi.c +++ b/drivers/spi/spi-bcm-qspi.c @@ -1370,13 +1370,9 @@ int bcm_qspi_probe(struct platform_device *pdev, res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "mspi"); - if (res) { - qspi->base[MSPI] = devm_ioremap_resource(dev, res); - if (IS_ERR(qspi->base[MSPI])) - return PTR_ERR(qspi->base[MSPI]); - } else { - return 0; - } + qspi->base[MSPI] = devm_ioremap_resource(dev, res); + if (IS_ERR(qspi->base[MSPI])) + return PTR_ERR(qspi->base[MSPI]); res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "bspi"); if (res) { diff --git a/drivers/spi/spi-bcm63xx.c b/drivers/spi/spi-bcm63xx.c index 80fa0ef8909c..147199002df1 100644 --- a/drivers/spi/spi-bcm63xx.c +++ b/drivers/spi/spi-bcm63xx.c @@ -126,7 +126,7 @@ enum bcm63xx_regs_spi { SPI_MSG_DATA_SIZE, }; -#define BCM63XX_SPI_MAX_PREPEND 15 +#define BCM63XX_SPI_MAX_PREPEND 7 #define BCM63XX_SPI_MAX_CS 8 #define BCM63XX_SPI_BUS_NUM 0 diff --git a/drivers/spi/spi-dw-core.c b/drivers/spi/spi-dw-core.c index 59e22c6b4b20..8fc598f09a72 100644 --- a/drivers/spi/spi-dw-core.c +++ b/drivers/spi/spi-dw-core.c @@ -416,7 +416,10 @@ static int dw_spi_transfer_one(struct spi_controller *master, int ret; dws->dma_mapped = 0; - dws->n_bytes = DIV_ROUND_UP(transfer->bits_per_word, BITS_PER_BYTE); + dws->n_bytes = + roundup_pow_of_two(DIV_ROUND_UP(transfer->bits_per_word, + BITS_PER_BYTE)); + dws->tx = (void *)transfer->tx_buf; dws->tx_len = transfer->len / dws->n_bytes; dws->rx = transfer->rx_buf; diff --git a/drivers/spi/spi-geni-qcom.c b/drivers/spi/spi-geni-qcom.c index 2f51421e2a71..4b92f119955c 100644 --- a/drivers/spi/spi-geni-qcom.c +++ b/drivers/spi/spi-geni-qcom.c @@ -32,7 +32,7 @@ #define CS_DEMUX_OUTPUT_SEL GENMASK(3, 0) #define SE_SPI_TRANS_CFG 0x25c -#define CS_TOGGLE BIT(0) +#define CS_TOGGLE BIT(1) #define SE_SPI_WORD_LEN 0x268 #define WORD_LEN_MSK GENMASK(9, 0) diff --git a/drivers/spi/spi-msm-geni.c b/drivers/spi/spi-msm-geni.c index 1ed1cee7116d..76b21d93a584 100644 --- a/drivers/spi/spi-msm-geni.c +++ b/drivers/spi/spi-msm-geni.c @@ -1897,6 +1897,7 @@ static int spi_geni_transfer_one(struct spi_master *spi, if (mas->is_dma_err) { mas->is_dma_err = false; + mas->cur_xfer = NULL; /* handle_fifo_timeout will do dma_unprep */ goto err_fifo_geni_transfer_one; } @@ -2133,8 +2134,10 @@ static void handle_dma_xfer(u32 dma_tx_status, u32 dma_rx_status, struct spi_gen if (dma_tx_status & DMA_TX_ERROR_STATUS) { geni_spi_dma_err(mas, dma_tx_status, 0); mas->is_dma_err = true; + mas->cmd_done = true; goto exit; } else if (dma_tx_status & TX_RESET_DONE) { + mas->cmd_done = true; GENI_SE_DBG(mas->ipc, false, mas->dev, "%s: Tx Reset done. DMA_TX_IRQ_STAT:0x%x\n", __func__, dma_tx_status); @@ -2154,13 +2157,16 @@ static void handle_dma_xfer(u32 dma_tx_status, u32 dma_rx_status, struct spi_gen if (dma_rx_status & DMA_RX_ERROR_STATUS) { geni_spi_dma_err(mas, dma_rx_status, 1); mas->is_dma_err = true; + mas->cmd_done = true; goto exit; } else if (dma_rx_status & RX_RESET_DONE) { + mas->cmd_done = true; GENI_SE_DBG(mas->ipc, false, mas->dev, "%s: Rx Reset done. DMA_RX_IRQ_STAT:0x%x\n", __func__, dma_rx_status); goto exit; } else if (dma_rx_status & RX_DMA_DONE) { + mas->cmd_done = true; GENI_SE_DBG(mas->ipc, false, mas->dev, "%s: RX DMA done.\n", __func__); if (dma_rx_len != dma_rx_len_in) { @@ -2176,8 +2182,9 @@ static void handle_dma_xfer(u32 dma_tx_status, u32 dma_rx_status, struct spi_gen } } } + if (!mas->tx_rem_bytes && !mas->rx_rem_bytes) - return; + mas->cmd_done = true; exit: return; } @@ -2231,13 +2238,14 @@ static irqreturn_t geni_spi_irq(int irq, void *data) SE_DMA_TX_IRQ_STAT); u32 dma_rx_status = geni_read_reg(mas->base, SE_DMA_RX_IRQ_STAT); - GENI_SE_DBG(mas->ipc, false, mas->dev, - "dma_txirq:0x%x dma_rxirq:0x%x\n", dma_tx_status, dma_rx_status); handle_dma_xfer(dma_tx_status, dma_rx_status, mas); - mas->cmd_done = true; if ((m_irq & M_CMD_CANCEL_EN) || (m_irq & M_CMD_ABORT_EN)) mas->cmd_done = true; + + GENI_SE_DBG(mas->ipc, false, mas->dev, + "dma_txirq:0x%x dma_rxirq:0x%x cmd_done=%d\n", + dma_tx_status, dma_rx_status, mas->cmd_done); } exit_geni_spi_irq: geni_write_reg(m_irq, mas->base, SE_GENI_M_IRQ_CLEAR); diff --git a/drivers/spmi/spmi-pmic-arb.c b/drivers/spmi/spmi-pmic-arb.c index ec2a592054e4..f23bbc9bbeb3 100644 --- a/drivers/spmi/spmi-pmic-arb.c +++ b/drivers/spmi/spmi-pmic-arb.c @@ -1634,7 +1634,7 @@ static int spmi_pmic_arb_probe(struct platform_device *pdev) } core = devm_ioremap(&ctrl->dev, res->start, resource_size(res)); - if (IS_ERR(core)) { + if (IS_ERR_OR_NULL(core)) { err = PTR_ERR(core); goto err_put_ctrl; } diff --git a/drivers/staging/clocking-wizard/clk-xlnx-clock-wizard.c b/drivers/staging/clocking-wizard/clk-xlnx-clock-wizard.c index 39367712ef54..8c1934df70de 100644 --- a/drivers/staging/clocking-wizard/clk-xlnx-clock-wizard.c +++ b/drivers/staging/clocking-wizard/clk-xlnx-clock-wizard.c @@ -347,7 +347,7 @@ static struct clk *clk_wzrd_register_divider(struct device *dev, hw = &div->hw; ret = devm_clk_hw_register(dev, hw); if (ret) - hw = ERR_PTR(ret); + return ERR_PTR(ret); return hw->clk; } diff --git a/drivers/staging/media/atomisp/pci/atomisp_gmin_platform.c b/drivers/staging/media/atomisp/pci/atomisp_gmin_platform.c index cd0a771454da..2a8ef766b25a 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_gmin_platform.c +++ b/drivers/staging/media/atomisp/pci/atomisp_gmin_platform.c @@ -1198,7 +1198,7 @@ static int gmin_get_config_dsm_var(struct device *dev, dev_info(dev, "found _DSM entry for '%s': %s\n", var, cur->string.pointer); strscpy(out, cur->string.pointer, *out_len); - *out_len = strlen(cur->string.pointer); + *out_len = strlen(out); ACPI_FREE(obj); return 0; diff --git a/drivers/thermal/mtk_thermal.c b/drivers/thermal/mtk_thermal.c index 9c857fb5d968..ede94eadddda 100644 --- a/drivers/thermal/mtk_thermal.c +++ b/drivers/thermal/mtk_thermal.c @@ -1028,12 +1028,7 @@ static int mtk_thermal_probe(struct platform_device *pdev) return -ENODEV; } - auxadc_base = devm_of_iomap(&pdev->dev, auxadc, 0, NULL); - if (IS_ERR(auxadc_base)) { - of_node_put(auxadc); - return PTR_ERR(auxadc_base); - } - + auxadc_base = of_iomap(auxadc, 0); auxadc_phys_base = of_get_phys_base(auxadc); of_node_put(auxadc); @@ -1049,12 +1044,7 @@ static int mtk_thermal_probe(struct platform_device *pdev) return -ENODEV; } - apmixed_base = devm_of_iomap(&pdev->dev, apmixedsys, 0, NULL); - if (IS_ERR(apmixed_base)) { - of_node_put(apmixedsys); - return PTR_ERR(apmixed_base); - } - + apmixed_base = of_iomap(apmixedsys, 0); apmixed_phys_base = of_get_phys_base(apmixedsys); of_node_put(apmixedsys); diff --git a/drivers/thermal/qcom/qmi_sensors.c b/drivers/thermal/qcom/qmi_sensors.c index 93caf312666f..d68ac1970f06 100644 --- a/drivers/thermal/qcom/qmi_sensors.c +++ b/drivers/thermal/qcom/qmi_sensors.c @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-2.0-only /* * Copyright (c) 2018-2021, The Linux Foundation. All rights reserved. - * Copyright (c) 2022, Qualcomm Innovation Center, Inc. All rights reserved. + * Copyright (c) 2022-2023, Qualcomm Innovation Center, Inc. All rights reserved. */ #define pr_fmt(fmt) "%s:%s " fmt, KBUILD_MODNAME, __func__ @@ -80,19 +80,29 @@ static int32_t encode_qmi(int32_t val) return local_val; } -static int32_t decode_qmi(int32_t val) +static int32_t decode_qmi(int32_t float32) { - int32_t sign = 0, shift = 0, local_val; + int fraction, shift, mantissa, sign, exp, zeropre; - sign = (val & QMI_FL_SIGN) ? -1 : 1; - shift = (val & QMI_FL_EXP) >> QMI_MANTISSA_MSB; - shift = QMI_MANTISSA_MSB - (shift - 127); - local_val = (val & QMI_FL_MANTISSA) | QMI_FL_NORM; - pr_debug("val:0x%x sign:%d shift:%d mantissa:%x temp:%d\n", - val, sign, shift, local_val, - sign * (local_val >> shift)); + mantissa = float32 & GENMASK(22, 0); + sign = (float32 & BIT(31)) ? -1 : 1; + exp = (float32 & ~BIT(31)) >> 23; - return sign * (local_val >> shift); + if (!exp && !mantissa) + return 0; + + exp -= 127; + if (exp < 0) { + exp = -exp; + zeropre = (((BIT(23) + mantissa) * 100) >> 23) >> exp; + return zeropre >= 50 ? sign : 0; + } + + shift = 23 - exp; + float32 = BIT(exp) + (mantissa >> shift); + fraction = mantissa & GENMASK(shift - 1, 0); + + return (((fraction * 100) >> shift) >= 50) ? sign * (float32 + 1) : sign * float32; } static int qmi_sensor_pm_notify(struct notifier_block *nb, diff --git a/drivers/thermal/qcom/tsens-v2.c b/drivers/thermal/qcom/tsens-v2.c index 584c01c7c39f..9c219dbc3d03 100644 --- a/drivers/thermal/qcom/tsens-v2.c +++ b/drivers/thermal/qcom/tsens-v2.c @@ -2,7 +2,7 @@ /* * Copyright (c) 2015, The Linux Foundation. All rights reserved. * Copyright (c) 2018, Linaro Limited - * Copyright (c) 2022, Qualcomm Innovation Center, Inc. All rights reserved. + * Copyright (c) 2023, Qualcomm Innovation Center, Inc. All rights reserved. */ #include @@ -97,6 +97,8 @@ static const struct tsens_ops ops_generic_v2 = { .init = init_common, .get_temp = get_temp_tsens_valid, .get_cold_status = get_cold_int_status, + .suspend = tsens_v2_tsens_suspend, + .resume = tsens_v2_tsens_resume, }; struct tsens_plat_data data_tsens_v2 = { diff --git a/drivers/thermal/qcom/tsens.c b/drivers/thermal/qcom/tsens.c index 98d043c2e87c..e53bb5e51095 100644 --- a/drivers/thermal/qcom/tsens.c +++ b/drivers/thermal/qcom/tsens.c @@ -2,7 +2,7 @@ /* * Copyright (c) 2015, The Linux Foundation. All rights reserved. * Copyright (c) 2019, 2020, Linaro Ltd. - * Copyright (c) 2021-2022, Qualcomm Innovation Center, Inc. All rights reserved. + * Copyright (c) 2021-2023, Qualcomm Innovation Center, Inc. All rights reserved. */ #include @@ -19,6 +19,7 @@ #include #include #include +#include #include #include "tsens.h" #include "thermal_zone_internal.h" @@ -1160,7 +1161,7 @@ static const struct thermal_zone_of_device_ops tsens_cold_of_ops = { static int tsens_register_irq(struct tsens_priv *priv, char *irqname, - irq_handler_t thread_fn) + irq_handler_t thread_fn, int *irq_num) { struct platform_device *pdev; int ret, irq; @@ -1170,6 +1171,7 @@ static int tsens_register_irq(struct tsens_priv *priv, char *irqname, return -ENODEV; irq = platform_get_irq_byname(pdev, irqname); + *irq_num = irq; if (irq < 0) { ret = irq; /* For old DTs with no IRQ defined */ @@ -1200,6 +1202,73 @@ static int tsens_register_irq(struct tsens_priv *priv, char *irqname, return ret; } +static int tsens_reinit(struct tsens_priv *priv) +{ + unsigned long flags; + + spin_lock_irqsave(&priv->ul_lock, flags); + + if (priv->feat->has_watchdog) { + regmap_field_write(priv->rf[WDOG_BARK_MASK], 0); + regmap_field_write(priv->rf[CC_MON_MASK], 1); + } + + if (tsens_version(priv) >= VER_0_1) + tsens_enable_irq(priv); + + spin_unlock_irqrestore(&priv->ul_lock, flags); + + return 0; +} + +int tsens_v2_tsens_suspend(struct tsens_priv *priv) +{ + if (!pm_suspend_via_firmware() && !priv->tm_disable_on_suspend) + return 0; + + if (priv->uplow_irq > 0) { + disable_irq_nosync(priv->uplow_irq); + disable_irq_wake(priv->uplow_irq); + } + + if (priv->feat->crit_int && priv->crit_irq > 0) { + disable_irq_nosync(priv->crit_irq); + disable_irq_wake(priv->crit_irq); + } + + if (pm_suspend_via_firmware() && priv->cold_irq > 0) { + disable_irq_nosync(priv->cold_irq); + disable_irq_wake(priv->cold_irq); + } + return 0; +} + +int tsens_v2_tsens_resume(struct tsens_priv *priv) +{ + if (!pm_suspend_via_firmware() && !priv->tm_disable_on_suspend) + return 0; + + if (pm_suspend_via_firmware()) + tsens_reinit(priv); + + if (priv->uplow_irq > 0) { + enable_irq(priv->uplow_irq); + enable_irq_wake(priv->uplow_irq); + } + + if (priv->feat->crit_int && priv->crit_irq > 0) { + enable_irq(priv->crit_irq); + enable_irq_wake(priv->crit_irq); + } + + if (pm_suspend_via_firmware() && priv->cold_irq > 0) { + enable_irq(priv->cold_irq); + enable_irq_wake(priv->cold_irq); + } + + return 0; +} + static int tsens_register(struct tsens_priv *priv) { int i, temp, ret; @@ -1242,14 +1311,15 @@ static int tsens_register(struct tsens_priv *priv) tsens_mC_to_hw(priv->sensor, 0)); } - ret = tsens_register_irq(priv, "uplow", tsens_irq_thread); + ret = tsens_register_irq(priv, "uplow", tsens_irq_thread, + &priv->uplow_irq); if (ret < 0) return ret; if (priv->feat->crit_int) ret = tsens_register_irq(priv, "critical", - tsens_critical_irq_thread); + tsens_critical_irq_thread, &priv->crit_irq); if (priv->feat->cold_int) { priv->cold_sensor = devm_kzalloc(priv->dev, @@ -1264,13 +1334,11 @@ static int tsens_register(struct tsens_priv *priv) priv->cold_sensor->hw_id, priv->cold_sensor, &tsens_cold_of_ops); - if (IS_ERR(tzd)) { - ret = 0; - return ret; + if (!IS_ERR_OR_NULL(tzd)) { + priv->cold_sensor->tzd = tzd; + ret = tsens_register_irq(priv, "cold", + tsens_cold_irq_thread, &priv->cold_irq); } - - priv->cold_sensor->tzd = tzd; - ret = tsens_register_irq(priv, "cold", tsens_cold_irq_thread); } return ret; } @@ -1348,6 +1416,8 @@ static int tsens_probe(struct platform_device *pdev) } priv->tsens_md = thermal_minidump_register(np->name); + priv->tm_disable_on_suspend = + of_property_read_bool(np, "tm-disable-on-suspend"); return tsens_register(priv); } diff --git a/drivers/thermal/qcom/tsens.h b/drivers/thermal/qcom/tsens.h index e144ff61cec5..a6f782aa6277 100644 --- a/drivers/thermal/qcom/tsens.h +++ b/drivers/thermal/qcom/tsens.h @@ -1,7 +1,7 @@ /* SPDX-License-Identifier: GPL-2.0 */ /* * Copyright (c) 2015, The Linux Foundation. All rights reserved. - * Copyright (c) 2021-2022 Qualcomm Innovation Center, Inc. All rights reserved. + * Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved. */ #ifndef __QCOM_TSENS_H__ @@ -612,6 +612,13 @@ struct tsens_priv { const struct reg_field *fields; const struct tsens_ops *ops; + /* add to save irq number to re-use it at runtime */ + int uplow_irq; + int crit_irq; + int cold_irq; + + bool tm_disable_on_suspend; + struct dentry *debug_root; struct dentry *debug; void *ipc_log; @@ -631,6 +638,8 @@ int init_common(struct tsens_priv *priv); int get_temp_tsens_valid(const struct tsens_sensor *s, int *temp); int get_temp_common(const struct tsens_sensor *s, int *temp); int get_cold_int_status(const struct tsens_sensor *s, bool *cold_status); +int tsens_v2_tsens_suspend(struct tsens_priv *priv); +int tsens_v2_tsens_resume(struct tsens_priv *priv); /* TSENS target */ extern struct tsens_plat_data data_8960; diff --git a/drivers/thermal/sun8i_thermal.c b/drivers/thermal/sun8i_thermal.c index d9cd23cbb671..cd464db06414 100644 --- a/drivers/thermal/sun8i_thermal.c +++ b/drivers/thermal/sun8i_thermal.c @@ -319,6 +319,11 @@ out: return ret; } +static void sun8i_ths_reset_control_assert(void *data) +{ + reset_control_assert(data); +} + static int sun8i_ths_resource_init(struct ths_device *tmdev) { struct device *dev = tmdev->dev; @@ -339,47 +344,35 @@ static int sun8i_ths_resource_init(struct ths_device *tmdev) if (IS_ERR(tmdev->reset)) return PTR_ERR(tmdev->reset); - tmdev->bus_clk = devm_clk_get(&pdev->dev, "bus"); + ret = reset_control_deassert(tmdev->reset); + if (ret) + return ret; + + ret = devm_add_action_or_reset(dev, sun8i_ths_reset_control_assert, + tmdev->reset); + if (ret) + return ret; + + tmdev->bus_clk = devm_clk_get_enabled(&pdev->dev, "bus"); if (IS_ERR(tmdev->bus_clk)) return PTR_ERR(tmdev->bus_clk); } if (tmdev->chip->has_mod_clk) { - tmdev->mod_clk = devm_clk_get(&pdev->dev, "mod"); + tmdev->mod_clk = devm_clk_get_enabled(&pdev->dev, "mod"); if (IS_ERR(tmdev->mod_clk)) return PTR_ERR(tmdev->mod_clk); } - ret = reset_control_deassert(tmdev->reset); + ret = clk_set_rate(tmdev->mod_clk, 24000000); if (ret) return ret; - ret = clk_prepare_enable(tmdev->bus_clk); - if (ret) - goto assert_reset; - - ret = clk_set_rate(tmdev->mod_clk, 24000000); - if (ret) - goto bus_disable; - - ret = clk_prepare_enable(tmdev->mod_clk); - if (ret) - goto bus_disable; - ret = sun8i_ths_calibrate(tmdev); if (ret) - goto mod_disable; + return ret; return 0; - -mod_disable: - clk_disable_unprepare(tmdev->mod_clk); -bus_disable: - clk_disable_unprepare(tmdev->bus_clk); -assert_reset: - reset_control_assert(tmdev->reset); - - return ret; } static int sun8i_h3_thermal_init(struct ths_device *tmdev) @@ -530,17 +523,6 @@ static int sun8i_ths_probe(struct platform_device *pdev) return 0; } -static int sun8i_ths_remove(struct platform_device *pdev) -{ - struct ths_device *tmdev = platform_get_drvdata(pdev); - - clk_disable_unprepare(tmdev->mod_clk); - clk_disable_unprepare(tmdev->bus_clk); - reset_control_assert(tmdev->reset); - - return 0; -} - static const struct ths_thermal_chip sun8i_a83t_ths = { .sensor_num = 3, .scale = 705, @@ -642,7 +624,6 @@ MODULE_DEVICE_TABLE(of, of_ths_match); static struct platform_driver ths_driver = { .probe = sun8i_ths_probe, - .remove = sun8i_ths_remove, .driver = { .name = "sun8i-thermal", .of_match_table = of_ths_match, diff --git a/drivers/thermal/thermal_netlink.c b/drivers/thermal/thermal_netlink.c index 41c8d47805c4..ca1054bdba10 100644 --- a/drivers/thermal/thermal_netlink.c +++ b/drivers/thermal/thermal_netlink.c @@ -9,6 +9,7 @@ #include #include #include +#include #include #include "thermal_core.h" @@ -229,6 +230,11 @@ static int thermal_genl_send_event(enum thermal_genl_event event, struct sk_buff *msg; int ret = -EMSGSIZE; void *hdr; + int enable_thermal_genl = 1; + + trace_android_vh_enable_thermal_genl_check(event, p->tz_id, &enable_thermal_genl); + if (!enable_thermal_genl) + return 0; msg = genlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL); if (!msg) diff --git a/drivers/tty/n_gsm.c b/drivers/tty/n_gsm.c index 54173c23263c..67889c014414 100644 --- a/drivers/tty/n_gsm.c +++ b/drivers/tty/n_gsm.c @@ -2387,12 +2387,13 @@ static void gsm_error(struct gsm_mux *gsm, static void gsm_cleanup_mux(struct gsm_mux *gsm, bool disc) { int i; - struct gsm_dlci *dlci = gsm->dlci[0]; + struct gsm_dlci *dlci; struct gsm_msg *txq, *ntxq; gsm->dead = true; mutex_lock(&gsm->mutex); + dlci = gsm->dlci[0]; if (dlci) { if (disc && dlci->state != DLCI_CLOSED) { gsm_dlci_begin_close(dlci); diff --git a/drivers/tty/serial/8250/8250_omap.c b/drivers/tty/serial/8250/8250_omap.c index 078a7028ee5a..a6b374c026a8 100644 --- a/drivers/tty/serial/8250/8250_omap.c +++ b/drivers/tty/serial/8250/8250_omap.c @@ -653,6 +653,8 @@ static irqreturn_t omap8250_irq(int irq, void *dev_id) if ((lsr & UART_LSR_OE) && up->overrun_backoff_time_ms > 0) { unsigned long delay; + /* Synchronize UART_IER access against the console. */ + spin_lock(&port->lock); up->ier = port->serial_in(port, UART_IER); if (up->ier & (UART_IER_RLSI | UART_IER_RDI)) { port->ops->stop_rx(port); @@ -662,6 +664,7 @@ static irqreturn_t omap8250_irq(int irq, void *dev_id) */ cancel_delayed_work(&up->overrun_backoff); } + spin_unlock(&port->lock); delay = msecs_to_jiffies(up->overrun_backoff_time_ms); schedule_delayed_work(&up->overrun_backoff, delay); @@ -1469,7 +1472,9 @@ static int omap8250_probe(struct platform_device *pdev) err: pm_runtime_dont_use_autosuspend(&pdev->dev); pm_runtime_put_sync(&pdev->dev); + flush_work(&priv->qos_work); pm_runtime_disable(&pdev->dev); + cpu_latency_qos_remove_request(&priv->pm_qos_request); return ret; } @@ -1516,25 +1521,35 @@ static int omap8250_suspend(struct device *dev) { struct omap8250_priv *priv = dev_get_drvdata(dev); struct uart_8250_port *up = serial8250_get_port(priv->line); + int err; serial8250_suspend_port(priv->line); - pm_runtime_get_sync(dev); + err = pm_runtime_resume_and_get(dev); + if (err) + return err; if (!device_may_wakeup(dev)) priv->wer = 0; serial_out(up, UART_OMAP_WER, priv->wer); - pm_runtime_mark_last_busy(dev); - pm_runtime_put_autosuspend(dev); - + err = pm_runtime_force_suspend(dev); flush_work(&priv->qos_work); - return 0; + + return err; } static int omap8250_resume(struct device *dev) { struct omap8250_priv *priv = dev_get_drvdata(dev); + int err; + err = pm_runtime_force_resume(dev); + if (err) + return err; serial8250_resume_port(priv->line); + /* Paired with pm_runtime_resume_and_get() in omap8250_suspend() */ + pm_runtime_mark_last_busy(dev); + pm_runtime_put_autosuspend(dev); + return 0; } #else diff --git a/drivers/tty/serial/atmel_serial.c b/drivers/tty/serial/atmel_serial.c index 714e6ff4a8fb..98a3f36b40b9 100644 --- a/drivers/tty/serial/atmel_serial.c +++ b/drivers/tty/serial/atmel_serial.c @@ -873,11 +873,11 @@ static void atmel_complete_tx_dma(void *arg) port->icount.tx += atmel_port->tx_len; - spin_lock_irq(&atmel_port->lock_tx); + spin_lock(&atmel_port->lock_tx); async_tx_ack(atmel_port->desc_tx); atmel_port->cookie_tx = -EINVAL; atmel_port->desc_tx = NULL; - spin_unlock_irq(&atmel_port->lock_tx); + spin_unlock(&atmel_port->lock_tx); if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) uart_write_wakeup(port); diff --git a/drivers/tty/serial/fsl_lpuart.c b/drivers/tty/serial/fsl_lpuart.c index 7f5e9ee50c74..7976bae5cfe7 100644 --- a/drivers/tty/serial/fsl_lpuart.c +++ b/drivers/tty/serial/fsl_lpuart.c @@ -2632,6 +2632,7 @@ OF_EARLYCON_DECLARE(lpuart, "fsl,vf610-lpuart", lpuart_early_console_setup); OF_EARLYCON_DECLARE(lpuart32, "fsl,ls1021a-lpuart", lpuart32_early_console_setup); OF_EARLYCON_DECLARE(lpuart32, "fsl,ls1028a-lpuart", ls1028a_early_console_setup); OF_EARLYCON_DECLARE(lpuart32, "fsl,imx7ulp-lpuart", lpuart32_imx_early_console_setup); +OF_EARLYCON_DECLARE(lpuart32, "fsl,imx8ulp-lpuart", lpuart32_imx_early_console_setup); OF_EARLYCON_DECLARE(lpuart32, "fsl,imx8qxp-lpuart", lpuart32_imx_early_console_setup); EARLYCON_DECLARE(lpuart, lpuart_early_console_setup); EARLYCON_DECLARE(lpuart32, lpuart32_early_console_setup); diff --git a/drivers/tty/serial/imx.c b/drivers/tty/serial/imx.c index 77a4f4af3b8d..3b2beb98eb1e 100644 --- a/drivers/tty/serial/imx.c +++ b/drivers/tty/serial/imx.c @@ -397,6 +397,16 @@ static void start_hrtimer_ms(struct hrtimer *hrt, unsigned long msec) hrtimer_start(hrt, ms_to_ktime(msec), HRTIMER_MODE_REL); } +static void imx_uart_disable_loopback_rs485(struct imx_port *sport) +{ + unsigned int uts; + + /* See SER_RS485_ENABLED/UTS_LOOP comment in imx_uart_probe() */ + uts = imx_uart_readl(sport, imx_uart_uts_reg(sport)); + uts &= ~UTS_LOOP; + imx_uart_writel(sport, uts, imx_uart_uts_reg(sport)); +} + /* called with port.lock taken and irqs off */ static void imx_uart_start_rx(struct uart_port *port) { @@ -418,6 +428,7 @@ static void imx_uart_start_rx(struct uart_port *port) /* Write UCR2 first as it includes RXEN */ imx_uart_writel(sport, ucr2, UCR2); imx_uart_writel(sport, ucr1, UCR1); + imx_uart_disable_loopback_rs485(sport); } /* called with port.lock taken and irqs off */ @@ -1394,7 +1405,7 @@ static int imx_uart_startup(struct uart_port *port) int retval, i; unsigned long flags; int dma_is_inited = 0; - u32 ucr1, ucr2, ucr3, ucr4, uts; + u32 ucr1, ucr2, ucr3, ucr4; retval = clk_prepare_enable(sport->clk_per); if (retval) @@ -1499,10 +1510,7 @@ static int imx_uart_startup(struct uart_port *port) imx_uart_writel(sport, ucr2, UCR2); } - /* See SER_RS485_ENABLED/UTS_LOOP comment in imx_uart_probe() */ - uts = imx_uart_readl(sport, imx_uart_uts_reg(sport)); - uts &= ~UTS_LOOP; - imx_uart_writel(sport, uts, imx_uart_uts_reg(sport)); + imx_uart_disable_loopback_rs485(sport); spin_unlock_irqrestore(&sport->port.lock, flags); diff --git a/drivers/tty/serial/msm_geni_serial.c b/drivers/tty/serial/msm_geni_serial.c index 0bfeb1d38671..6eca49727f57 100644 --- a/drivers/tty/serial/msm_geni_serial.c +++ b/drivers/tty/serial/msm_geni_serial.c @@ -101,9 +101,16 @@ static bool con_enabled = IS_ENABLED(CONFIG_SERIAL_MSM_GENI_CONSOLE_DEFAULT_ENAB #define UART_START_TX (0x1) #define UART_START_BREAK (0x4) #define UART_STOP_BREAK (0x5) + /* UART S_CMD OP codes */ -#define UART_START_READ (0x1) -#define UART_PARAM (0x1) +#define UART_START_READ (0x1) +#define UART_PARAM (0x1) + +/* When set character with framing error is not written in RX fifo */ +#define UART_PARAM_SKIP_FRAME_ERR_CHAR (BIT(5)) + +/* When set break character is not written in RX fifo */ +#define UART_PARAM_SKIP_BREAK_CHAR (BIT(6)) #define UART_PARAM_RFR_OPEN (BIT(7)) /* UART DMA Rx GP_IRQ_BITS */ @@ -2097,7 +2104,10 @@ static void msm_geni_uart_gsi_cancel_tx(struct work_struct *work) struct msm_geni_serial_port, tx_cancel_work); - dmaengine_terminate_all(msm_port->gsi->tx_c); + if (msm_port->gsi->tx_c && dmaengine_terminate_all(msm_port->gsi->tx_c)) + IPC_LOG_MSG(msm_port->ipc_log_misc, + "%s: dmaengine_terminate_all failed for Tx ch\n", + __func__); } static void msm_geni_uart_gsi_cancel_rx(struct work_struct *work) @@ -2114,8 +2124,10 @@ static void msm_geni_uart_gsi_cancel_rx(struct work_struct *work) atomic_set(&msm_port->stop_rx_inprogress, 0); return; } - if (msm_port->gsi->rx_c) - dmaengine_terminate_all(msm_port->gsi->rx_c); + if (msm_port->gsi->rx_c && dmaengine_terminate_all(msm_port->gsi->rx_c)) + IPC_LOG_MSG(msm_port->ipc_log_misc, + "%s: dmaengine_terminate_all failed for Rx ch\n", + __func__); complete(&msm_port->xfer); msm_port->gsi_rx_done = false; atomic_set(&msm_port->stop_rx_inprogress, 0); @@ -2162,6 +2174,7 @@ static int msm_geni_uart_gsi_xfer_rx(struct uart_port *uport) for (k = i; k > 0; k--) { geni_se_common_iommu_free_buf(rx_dev, &msm_port->dma_addr[k - 1], msm_port->rx_gsi_buf[k - 1], DMA_RX_BUF_SIZE); + msm_port->rx_gsi_buf[k - 1] = NULL; } msm_geni_deallocate_chan(uport); return -EIO; @@ -2205,6 +2218,7 @@ exit_gsi_xfer_rx: for (i = 0; i < NUM_RX_BUF; i++) { geni_se_common_iommu_free_buf(rx_dev, &msm_port->dma_addr[i], msm_port->rx_gsi_buf[i], DMA_RX_BUF_SIZE); + msm_port->rx_gsi_buf[i] = NULL; } msm_geni_deallocate_chan(uport); msm_port->gsi_rx_done = false; @@ -2576,7 +2590,8 @@ static void start_rx_sequencer(struct uart_port *uport) { unsigned int geni_status; struct msm_geni_serial_port *port = GET_DEV_PORT(uport); - u32 geni_se_param = UART_PARAM_RFR_OPEN; + u32 geni_se_param = (UART_PARAM_SKIP_FRAME_ERR_CHAR | + UART_PARAM_SKIP_BREAK_CHAR | UART_PARAM_RFR_OPEN); if (port->startup_in_progress) return; @@ -2617,7 +2632,10 @@ static void start_rx_sequencer(struct uart_port *uport) &port->rx_dma); } - /* Start RX with the RFR_OPEN to keep RFR in always ready state */ + /* Start RX with the RFR_OPEN to keep RFR in always ready state. + * Configure for character with Framing error & Break character + * is not written in RX fifo. + */ geni_se_setup_s_cmd(&port->se, UART_START_READ, geni_se_param); msm_geni_serial_enable_interrupts(uport); @@ -3439,7 +3457,6 @@ static bool handle_rx_dma_xfer(u32 s_irq_status, struct uart_port *uport) "%s dma_rx_status:0x%x Rx Framing error:%d\n", __func__, dma_rx_status, uport->icount.frame); - drop_rx = true; } if (dma_rx_status & UART_DMA_RX_BREAK) { @@ -3764,7 +3781,7 @@ static void msm_geni_serial_flush(struct uart_port *uport) struct msm_geni_serial_port *port = GET_DEV_PORT(uport); atomic_set(&port->flush_buffers, 1); - stop_tx_sequencer(uport); + msm_geni_serial_stop_tx(uport); } static void msm_geni_serial_shutdown(struct uart_port *uport) @@ -3813,12 +3830,18 @@ static void msm_geni_serial_shutdown(struct uart_port *uport) UART_LOG_DBG(msm_port->ipc_log_misc, uport->dev, "%s:GSI DMA-Rx ch\n", __func__); + dma_release_channel(msm_port->gsi->rx_c); for (i = 0; i < 4; i++) { - geni_se_common_iommu_free_buf(rx_dev, - &msm_port->dma_addr[i], - msm_port->rx_gsi_buf[i], - DMA_RX_BUF_SIZE); + if (msm_port->dma_addr[i]) { + geni_se_common_iommu_free_buf(rx_dev, + &msm_port->dma_addr[i], + msm_port->rx_gsi_buf[i], + DMA_RX_BUF_SIZE); + msm_port->rx_gsi_buf[i] = NULL; + } + } + msm_port->gsi->rx_c = NULL; UART_LOG_DBG(msm_port->ipc_log_misc, uport->dev, "%s:Unmap buf done\n", __func__); @@ -3827,7 +3850,7 @@ static void msm_geni_serial_shutdown(struct uart_port *uport) UART_LOG_DBG(msm_port->ipc_log_misc, uport->dev, "%s:GSI DMA-Tx ch\n", __func__); - msm_geni_serial_stop_tx(uport); + dma_release_channel(msm_port->gsi->tx_c); if (msm_port->tx_dma) { geni_se_common_iommu_unmap_buf(tx_dev, &msm_port->tx_dma, @@ -3837,6 +3860,7 @@ static void msm_geni_serial_shutdown(struct uart_port *uport) uport->dev, "%s:Unmap buf done\n", __func__); } + msm_port->gsi->tx_c = NULL; } } else { msm_geni_serial_stop_tx(uport); diff --git a/drivers/tty/serial/msm_serial_hs.c b/drivers/tty/serial/msm_serial_hs.c index c19cbe1478c0..bf4a23ab0c90 100644 --- a/drivers/tty/serial/msm_serial_hs.c +++ b/drivers/tty/serial/msm_serial_hs.c @@ -2426,6 +2426,15 @@ static irqreturn_t msm_hs_wakeup_isr(int irq, void *dev) */ if (msm_uport->wakeup.inject_rx) { tty = uport->state->port.tty; + /* uport->state->port.tty pointer initialized as part of + * UART port_open. Adding null check to ensure tty should + * have a valid value before dereference it in wakeup_isr. + */ + if (!tty) { + MSM_HS_ERR("%s: Unexpected wakeup ISR\n", __func__); + spin_unlock_irqrestore(&uport->lock, flags); + return IRQ_HANDLED; + } tty_insert_flip_char(tty->port, msm_uport->wakeup.rx_to_inject, TTY_NORMAL); diff --git a/drivers/tty/serial/samsung_tty.c b/drivers/tty/serial/samsung_tty.c index f460b47ff6f2..09b2b40b63c4 100644 --- a/drivers/tty/serial/samsung_tty.c +++ b/drivers/tty/serial/samsung_tty.c @@ -1478,8 +1478,12 @@ static unsigned int s3c24xx_serial_getclk(struct s3c24xx_uart_port *ourport, continue; rate = clk_get_rate(clk); - if (!rate) + if (!rate) { + dev_err(ourport->port.dev, + "Failed to get clock rate for %s.\n", clkname); + clk_put(clk); continue; + } if (ourport->info->has_divslot) { unsigned long div = rate / req_baud; @@ -1505,10 +1509,18 @@ static unsigned int s3c24xx_serial_getclk(struct s3c24xx_uart_port *ourport, calc_deviation = -calc_deviation; if (calc_deviation < deviation) { + /* + * If we find a better clk, release the previous one, if + * any. + */ + if (!IS_ERR(*best_clk)) + clk_put(*best_clk); *best_clk = clk; best_quot = quot; *clk_num = cnt; deviation = calc_deviation; + } else { + clk_put(clk); } } diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c index 5a08e22a865d..d4876fe227ee 100644 --- a/drivers/usb/core/devio.c +++ b/drivers/usb/core/devio.c @@ -735,6 +735,7 @@ static int driver_resume(struct usb_interface *intf) return 0; } +#ifdef CONFIG_PM /* The following routines apply to the entire device, not interfaces */ void usbfs_notify_suspend(struct usb_device *udev) { @@ -753,6 +754,7 @@ void usbfs_notify_resume(struct usb_device *udev) } mutex_unlock(&usbfs_mutex); } +#endif struct usb_driver usbfs_driver = { .name = "usbfs", diff --git a/drivers/usb/dwc2/platform.c b/drivers/usb/dwc2/platform.c index 7a09476e9f19..6496bfbd34ed 100644 --- a/drivers/usb/dwc2/platform.c +++ b/drivers/usb/dwc2/platform.c @@ -205,6 +205,11 @@ int dwc2_lowlevel_hw_disable(struct dwc2_hsotg *hsotg) return ret; } +static void dwc2_reset_control_assert(void *data) +{ + reset_control_assert(data); +} + static int dwc2_lowlevel_hw_init(struct dwc2_hsotg *hsotg) { int i, ret; @@ -217,6 +222,10 @@ static int dwc2_lowlevel_hw_init(struct dwc2_hsotg *hsotg) } reset_control_deassert(hsotg->reset); + ret = devm_add_action_or_reset(hsotg->dev, dwc2_reset_control_assert, + hsotg->reset); + if (ret) + return ret; hsotg->reset_ecc = devm_reset_control_get_optional(hsotg->dev, "dwc2-ecc"); if (IS_ERR(hsotg->reset_ecc)) { @@ -226,6 +235,10 @@ static int dwc2_lowlevel_hw_init(struct dwc2_hsotg *hsotg) } reset_control_deassert(hsotg->reset_ecc); + ret = devm_add_action_or_reset(hsotg->dev, dwc2_reset_control_assert, + hsotg->reset_ecc); + if (ret) + return ret; /* * Attempt to find a generic PHY, then look for an old style @@ -352,10 +365,7 @@ static int dwc2_driver_remove(struct platform_device *dev) if (hsotg->ll_hw_enabled) dwc2_lowlevel_hw_disable(hsotg); - reset_control_assert(hsotg->reset); - reset_control_assert(hsotg->reset_ecc); - - return ret; + return 0; } /** diff --git a/drivers/usb/dwc3/dwc3-meson-g12a.c b/drivers/usb/dwc3/dwc3-meson-g12a.c index bd814df3bf8b..8f94bc4a82cf 100644 --- a/drivers/usb/dwc3/dwc3-meson-g12a.c +++ b/drivers/usb/dwc3/dwc3-meson-g12a.c @@ -805,7 +805,7 @@ static int dwc3_meson_g12a_probe(struct platform_device *pdev) ret = dwc3_meson_g12a_otg_init(pdev, priv); if (ret) - goto err_phys_power; + goto err_plat_depopulate; pm_runtime_set_active(dev); pm_runtime_enable(dev); @@ -813,6 +813,9 @@ static int dwc3_meson_g12a_probe(struct platform_device *pdev) return 0; +err_plat_depopulate: + of_platform_depopulate(dev); + err_phys_power: for (i = 0 ; i < PHY_COUNT ; ++i) phy_power_off(priv->phys[i]); diff --git a/drivers/usb/dwc3/dwc3-msm-core.c b/drivers/usb/dwc3/dwc3-msm-core.c index 66587d9b803a..6b5ce240b6ed 100644 --- a/drivers/usb/dwc3/dwc3-msm-core.c +++ b/drivers/usb/dwc3/dwc3-msm-core.c @@ -606,6 +606,7 @@ struct dwc3_msm { bool dynamic_disable; bool wcd_usbss; bool force_disconnect; + bool read_u1u2; }; #define USB_HSPHY_3P3_VOL_MIN 3050000 /* uV */ @@ -1196,9 +1197,13 @@ static int dwc3_core_send_gadget_ep_cmd(struct dwc3_ep *dep, unsigned int cmd, } if (DWC3_DEPCMD_CMD(cmd) == DWC3_DEPCMD_STARTTRANSFER) { - if (ret == 0) - mdwc->hw_eps[dep->number].flags |= - DWC3_MSM_HW_EP_TRANSFER_STARTED; + if (ret == 0) { + if (mdwc->hw_eps[dep->number].mode == USB_EP_GSI) + mdwc->hw_eps[dep->number].flags |= + DWC3_MSM_HW_EP_TRANSFER_STARTED; + else + dep->flags |= DWC3_EP_TRANSFER_STARTED; + } if (ret != -ETIMEDOUT) { u32 res_id; @@ -3150,13 +3155,12 @@ static void mdwc3_usb2_phy_soft_reset(struct dwc3_msm *mdwc) static void mdwc3_update_u1u2_value(struct dwc3 *dwc) { struct dwc3_msm *mdwc = dev_get_drvdata(dwc->dev->parent); - static bool read_u1u2; /* cache DT based initial value once */ - if (!read_u1u2) { + if (!mdwc->read_u1u2) { mdwc->cached_dis_u1_entry_quirk = dwc->dis_u1_entry_quirk; mdwc->cached_dis_u2_entry_quirk = dwc->dis_u2_entry_quirk; - read_u1u2 = true; + mdwc->read_u1u2 = true; dbg_log_string("cached_dt_param: u1_disable:%d u2_disable:%d\n", mdwc->cached_dis_u1_entry_quirk, mdwc->cached_dis_u2_entry_quirk); } diff --git a/drivers/usb/dwc3/dwc3-msm-ops.c b/drivers/usb/dwc3/dwc3-msm-ops.c index eb9ca5e85ef7..e7b75f5398c3 100644 --- a/drivers/usb/dwc3/dwc3-msm-ops.c +++ b/drivers/usb/dwc3/dwc3-msm-ops.c @@ -30,6 +30,36 @@ static unsigned long dwc3_pt_reg(struct pt_regs *regs, int reg) #endif } +static int entry_usb_ep_set_maxpacket_limit(struct kretprobe_instance *ri, + struct pt_regs *regs) +{ + struct dwc3_ep *dep = (struct dwc3_ep *)regs->regs[0]; + struct dwc3 *dwc = dep->dwc; + struct kprobe_data *data = (struct kprobe_data *)ri->data; + + data->dwc = dwc; + data->xi0 = dep->number; + + return 0; +} + +static int exit_usb_ep_set_maxpacket_limit(struct kretprobe_instance *ri, + struct pt_regs *regs) +{ + struct kprobe_data *data = (struct kprobe_data *)ri->data; + struct dwc3 *dwc = data->dwc; + u8 epnum = data->xi0; + struct dwc3_ep *dep = dwc->eps[epnum]; + struct usb_ep *ep = &dep->endpoint; + + if (epnum >= 2) { + ep->maxpacket_limit = 1024; + ep->maxpacket = 1024; + } + + return 0; +} + static int entry_dwc3_gadget_run_stop(struct kretprobe_instance *ri, struct pt_regs *regs) { @@ -227,6 +257,7 @@ static struct kretprobe dwc3_msm_probes[] = { ENTRY_EXIT(dwc3_gadget_conndone_interrupt), ENTRY_EXIT(dwc3_gadget_pullup), ENTRY(__dwc3_gadget_start), + ENTRY_EXIT(usb_ep_set_maxpacket_limit), ENTRY(trace_event_raw_event_dwc3_log_request), ENTRY(trace_event_raw_event_dwc3_log_gadget_ep_cmd), ENTRY(trace_event_raw_event_dwc3_log_trb), diff --git a/drivers/usb/dwc3/dwc3-qcom.c b/drivers/usb/dwc3/dwc3-qcom.c index 28bc7480acf3..73c0c381e5d0 100644 --- a/drivers/usb/dwc3/dwc3-qcom.c +++ b/drivers/usb/dwc3/dwc3-qcom.c @@ -727,6 +727,7 @@ static int dwc3_qcom_probe(struct platform_device *pdev) struct device *dev = &pdev->dev; struct dwc3_qcom *qcom; struct resource *res, *parent_res = NULL; + struct resource local_res; int ret, i; bool ignore_pipe_clk; @@ -777,9 +778,8 @@ static int dwc3_qcom_probe(struct platform_device *pdev) if (np) { parent_res = res; } else { - parent_res = kmemdup(res, sizeof(struct resource), GFP_KERNEL); - if (!parent_res) - return -ENOMEM; + memcpy(&local_res, res, sizeof(struct resource)); + parent_res = &local_res; parent_res->start = res->start + qcom->acpi_pdata->qscratch_base_offset; @@ -791,9 +791,10 @@ static int dwc3_qcom_probe(struct platform_device *pdev) if (IS_ERR_OR_NULL(qcom->urs_usb)) { dev_err(dev, "failed to create URS USB platdev\n"); if (!qcom->urs_usb) - return -ENODEV; + ret = -ENODEV; else - return PTR_ERR(qcom->urs_usb); + ret = PTR_ERR(qcom->urs_usb); + goto clk_disable; } } } @@ -873,11 +874,15 @@ reset_assert: static int dwc3_qcom_remove(struct platform_device *pdev) { struct dwc3_qcom *qcom = platform_get_drvdata(pdev); + struct device_node *np = pdev->dev.of_node; struct device *dev = &pdev->dev; int i; device_remove_software_node(&qcom->dwc3->dev); - of_platform_depopulate(dev); + if (np) + of_platform_depopulate(&pdev->dev); + else + platform_device_put(pdev); for (i = qcom->num_clocks - 1; i >= 0; i--) { clk_disable_unprepare(qcom->clks[i]); diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index fdde4262acad..8bd2af65cd6a 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -2620,7 +2620,9 @@ static int dwc3_gadget_pullup(struct usb_gadget *g, int is_on) ret = pm_runtime_get_sync(dwc->dev); if (!ret || ret < 0) { pm_runtime_put(dwc->dev); - return 0; + if (ret < 0) + pm_runtime_set_suspended(dwc->dev); + return ret; } if (dwc->pullups_connected == is_on) { diff --git a/drivers/usb/gadget/function/f_accessory.c b/drivers/usb/gadget/function/f_accessory.c index 84f2bfc6d960..ce7814c22057 100644 --- a/drivers/usb/gadget/function/f_accessory.c +++ b/drivers/usb/gadget/function/f_accessory.c @@ -679,8 +679,11 @@ fail: pr_err("acc_bind() could not allocate requests\n"); while ((req = req_get(dev, &dev->tx_idle))) acc_request_free(req, dev->ep_in); - for (i = 0; i < RX_REQ_MAX; i++) + for (i = 0; i < RX_REQ_MAX; i++) { acc_request_free(dev->rx_req[i], dev->ep_out); + dev->rx_req[i] = NULL; + } + return -1; } @@ -712,6 +715,12 @@ static ssize_t acc_read(struct file *fp, char __user *buf, goto done; } + if (!dev->rx_req[0]) { + pr_warn("acc_read: USB request already handled/freed"); + r = -EINVAL; + goto done; + } + /* * Calculate the data length by considering termination character. * Then compansite the difference of rounding up to @@ -1208,8 +1217,10 @@ acc_function_unbind(struct usb_configuration *c, struct usb_function *f) while ((req = req_get(dev, &dev->tx_idle))) acc_request_free(req, dev->ep_in); - for (i = 0; i < RX_REQ_MAX; i++) + for (i = 0; i < RX_REQ_MAX; i++) { acc_request_free(dev->rx_req[i], dev->ep_out); + dev->rx_req[i] = NULL; + } acc_hid_unbind(dev); } diff --git a/drivers/usb/gadget/function/f_midi.c b/drivers/usb/gadget/function/f_midi.c index 0e78da6fc091..7eddfdad8183 100644 --- a/drivers/usb/gadget/function/f_midi.c +++ b/drivers/usb/gadget/function/f_midi.c @@ -1023,40 +1023,30 @@ static int f_midi_bind(struct usb_configuration *c, struct usb_function *f) if (!f->fs_descriptors) goto fail_f_midi; - if (gadget_is_dualspeed(c->cdev->gadget)) { - bulk_in_desc.wMaxPacketSize = cpu_to_le16(512); - bulk_out_desc.wMaxPacketSize = cpu_to_le16(512); - f->hs_descriptors = usb_copy_descriptors(midi_function); - if (!f->hs_descriptors) - goto fail_f_midi; - } + bulk_in_desc.wMaxPacketSize = cpu_to_le16(512); + bulk_out_desc.wMaxPacketSize = cpu_to_le16(512); + f->hs_descriptors = usb_copy_descriptors(midi_function); + if (!f->hs_descriptors) + goto fail_f_midi; - if (gadget_is_superspeed(c->cdev->gadget)) { - bulk_in_desc.wMaxPacketSize = cpu_to_le16(1024); - bulk_out_desc.wMaxPacketSize = cpu_to_le16(1024); - i = endpoint_descriptor_index; - midi_function[i++] = (struct usb_descriptor_header *) - &bulk_out_desc; - midi_function[i++] = (struct usb_descriptor_header *) - &bulk_out_ss_comp_desc; - midi_function[i++] = (struct usb_descriptor_header *) - &ms_out_desc; - midi_function[i++] = (struct usb_descriptor_header *) - &bulk_in_desc; - midi_function[i++] = (struct usb_descriptor_header *) - &bulk_in_ss_comp_desc; - midi_function[i++] = (struct usb_descriptor_header *) - &ms_in_desc; - f->ss_descriptors = usb_copy_descriptors(midi_function); - if (!f->ss_descriptors) - goto fail_f_midi; - - if (gadget_is_superspeed_plus(c->cdev->gadget)) { - f->ssp_descriptors = usb_copy_descriptors(midi_function); - if (!f->ssp_descriptors) - goto fail_f_midi; - } - } + bulk_in_desc.wMaxPacketSize = cpu_to_le16(1024); + bulk_out_desc.wMaxPacketSize = cpu_to_le16(1024); + i = endpoint_descriptor_index; + midi_function[i++] = (struct usb_descriptor_header *) + &bulk_out_desc; + midi_function[i++] = (struct usb_descriptor_header *) + &bulk_out_ss_comp_desc; + midi_function[i++] = (struct usb_descriptor_header *) + &ms_out_desc; + midi_function[i++] = (struct usb_descriptor_header *) + &bulk_in_desc; + midi_function[i++] = (struct usb_descriptor_header *) + &bulk_in_ss_comp_desc; + midi_function[i++] = (struct usb_descriptor_header *) + &ms_in_desc; + f->ss_descriptors = usb_copy_descriptors(midi_function); + if (!f->ss_descriptors) + goto fail_f_midi; kfree(midi_function); diff --git a/drivers/usb/gadget/function/f_uvc.c b/drivers/usb/gadget/function/f_uvc.c index 32f2c1645467..8eca4aff215c 100644 --- a/drivers/usb/gadget/function/f_uvc.c +++ b/drivers/usb/gadget/function/f_uvc.c @@ -492,6 +492,7 @@ uvc_copy_descriptors(struct uvc_device *uvc, enum usb_device_speed speed) void *mem; switch (speed) { + case USB_SPEED_SUPER_PLUS: case USB_SPEED_SUPER: uvc_control_desc = uvc->desc.ss_control; uvc_streaming_cls = uvc->desc.ss_streaming; @@ -536,7 +537,8 @@ uvc_copy_descriptors(struct uvc_device *uvc, enum usb_device_speed speed) + uvc_control_ep.bLength + uvc_control_cs_ep.bLength + uvc_streaming_intf_alt0.bLength; - if (speed == USB_SPEED_SUPER) { + if (speed == USB_SPEED_SUPER || + speed == USB_SPEED_SUPER_PLUS) { bytes += uvc_ss_control_comp.bLength; n_desc = 6; } else { @@ -580,7 +582,8 @@ uvc_copy_descriptors(struct uvc_device *uvc, enum usb_device_speed speed) uvc_control_header->baInterfaceNr[0] = uvc->streaming_intf; UVC_COPY_DESCRIPTOR(mem, dst, &uvc_control_ep); - if (speed == USB_SPEED_SUPER) + if (speed == USB_SPEED_SUPER + || speed == USB_SPEED_SUPER_PLUS) UVC_COPY_DESCRIPTOR(mem, dst, &uvc_ss_control_comp); UVC_COPY_DESCRIPTOR(mem, dst, &uvc_control_cs_ep); @@ -673,21 +676,13 @@ uvc_function_bind(struct usb_configuration *c, struct usb_function *f) } uvc->control_ep = ep; - if (gadget_is_superspeed(c->cdev->gadget)) - ep = usb_ep_autoconfig_ss(cdev->gadget, &uvc_ss_streaming_ep, - &uvc_ss_streaming_comp); - else if (gadget_is_dualspeed(cdev->gadget)) - ep = usb_ep_autoconfig(cdev->gadget, &uvc_hs_streaming_ep); - else - ep = usb_ep_autoconfig(cdev->gadget, &uvc_fs_streaming_ep); - + ep = usb_ep_autoconfig(cdev->gadget, &uvc_fs_streaming_ep); if (!ep) { uvcg_info(f, "Unable to allocate streaming EP\n"); goto error; } uvc->video.ep = ep; - uvc_fs_streaming_ep.bEndpointAddress = uvc->video.ep->address; uvc_hs_streaming_ep.bEndpointAddress = uvc->video.ep->address; uvc_ss_streaming_ep.bEndpointAddress = uvc->video.ep->address; @@ -726,21 +721,26 @@ uvc_function_bind(struct usb_configuration *c, struct usb_function *f) f->fs_descriptors = NULL; goto error; } - if (gadget_is_dualspeed(cdev->gadget)) { - f->hs_descriptors = uvc_copy_descriptors(uvc, USB_SPEED_HIGH); - if (IS_ERR(f->hs_descriptors)) { - ret = PTR_ERR(f->hs_descriptors); - f->hs_descriptors = NULL; - goto error; - } + + f->hs_descriptors = uvc_copy_descriptors(uvc, USB_SPEED_HIGH); + if (IS_ERR(f->hs_descriptors)) { + ret = PTR_ERR(f->hs_descriptors); + f->hs_descriptors = NULL; + goto error; } - if (gadget_is_superspeed(c->cdev->gadget)) { - f->ss_descriptors = uvc_copy_descriptors(uvc, USB_SPEED_SUPER); - if (IS_ERR(f->ss_descriptors)) { - ret = PTR_ERR(f->ss_descriptors); - f->ss_descriptors = NULL; - goto error; - } + + f->ss_descriptors = uvc_copy_descriptors(uvc, USB_SPEED_SUPER); + if (IS_ERR(f->ss_descriptors)) { + ret = PTR_ERR(f->ss_descriptors); + f->ss_descriptors = NULL; + goto error; + } + + f->ssp_descriptors = uvc_copy_descriptors(uvc, USB_SPEED_SUPER_PLUS); + if (IS_ERR(f->ssp_descriptors)) { + ret = PTR_ERR(f->ssp_descriptors); + f->ssp_descriptors = NULL; + goto error; } /* Preallocate control endpoint request. */ diff --git a/drivers/usb/gadget/function/u_phonet.h b/drivers/usb/gadget/function/u_phonet.h index c53233b37192..ff62ca22c40d 100644 --- a/drivers/usb/gadget/function/u_phonet.h +++ b/drivers/usb/gadget/function/u_phonet.h @@ -20,7 +20,6 @@ struct f_phonet_opts { struct net_device *gphonet_setup_default(void); void gphonet_set_gadget(struct net_device *net, struct usb_gadget *g); int gphonet_register_netdev(struct net_device *net); -int phonet_bind_config(struct usb_configuration *c, struct net_device *dev); void gphonet_cleanup(struct net_device *dev); #endif /* __U_PHONET_H */ diff --git a/drivers/usb/gadget/function/u_serial.h b/drivers/usb/gadget/function/u_serial.h index 102a7323a1fd..901d99310bc4 100644 --- a/drivers/usb/gadget/function/u_serial.h +++ b/drivers/usb/gadget/function/u_serial.h @@ -71,8 +71,4 @@ void gserial_disconnect(struct gserial *); void gserial_suspend(struct gserial *p); void gserial_resume(struct gserial *p); -/* functions are bound to configurations by a config or gadget driver */ -int gser_bind_config(struct usb_configuration *c, u8 port_num); -int obex_bind_config(struct usb_configuration *c, u8 port_num); - #endif /* __U_SERIAL_H */ diff --git a/drivers/usb/gadget/function/uvc.h b/drivers/usb/gadget/function/uvc.h index 40226b1f7e14..289c5611e138 100644 --- a/drivers/usb/gadget/function/uvc.h +++ b/drivers/usb/gadget/function/uvc.h @@ -176,8 +176,6 @@ struct uvc_file_handle { */ extern void uvc_function_setup_continue(struct uvc_device *uvc); -extern void uvc_endpoint_stream(struct uvc_device *dev); - extern void uvc_function_connect(struct uvc_device *uvc); extern void uvc_function_disconnect(struct uvc_device *uvc); diff --git a/drivers/usb/gadget/function/uvc_video.c b/drivers/usb/gadget/function/uvc_video.c index e81865978299..91af3b1ef0d4 100644 --- a/drivers/usb/gadget/function/uvc_video.c +++ b/drivers/usb/gadget/function/uvc_video.c @@ -382,13 +382,13 @@ static void uvcg_video_pump(struct work_struct *work) { struct uvc_video *video = container_of(work, struct uvc_video, pump); struct uvc_video_queue *queue = &video->queue; + /* video->max_payload_size is only set when using bulk transfer */ + bool is_bulk = video->max_payload_size; struct usb_request *req = NULL; struct uvc_buffer *buf; unsigned long flags; + bool buf_done; int ret; - bool buf_int; - /* video->max_payload_size is only set when using bulk transfer */ - bool is_bulk = video->max_payload_size; while (video->ep->enabled) { /* @@ -414,20 +414,19 @@ static void uvcg_video_pump(struct work_struct *work) if (buf != NULL) { video->encode(req, video, buf); - /* Always interrupt for the last request of a video buffer */ - buf_int = buf->state == UVC_BUF_STATE_DONE; + buf_done = buf->state == UVC_BUF_STATE_DONE; } else if (!(queue->flags & UVC_QUEUE_DISCONNECTED) && !is_bulk) { /* * No video buffer available; the queue is still connected and - * we're traferring over ISOC. Queue a 0 length request to + * we're transferring over ISOC. Queue a 0 length request to * prevent missed ISOC transfers. */ req->length = 0; - buf_int = false; + buf_done = false; } else { /* - * Either queue has been disconnected or no video buffer - * available to bulk transfer. Either way, stop processing + * Either the queue has been disconnected or no video buffer + * available for bulk transfer. Either way, stop processing * further. */ spin_unlock_irqrestore(&queue->irqlock, flags); @@ -435,11 +434,24 @@ static void uvcg_video_pump(struct work_struct *work) } /* - * With usb3 we have more requests. This will decrease the - * interrupt load to a quarter but also catches the corner - * cases, which needs to be handled. + * With USB3 handling more requests at a higher speed, we can't + * afford to generate an interrupt for every request. Decide to + * interrupt: + * + * - When no more requests are available in the free queue, as + * this may be our last chance to refill the endpoint's + * request queue. + * + * - When this is request is the last request for the video + * buffer, as we want to start sending the next video buffer + * ASAP in case it doesn't get started already in the next + * iteration of this loop. + * + * - Four times over the length of the requests queue (as + * indicated by video->uvc_num_requests), as a trade-off + * between latency and interrupt load. */ - if (list_empty(&video->req_free) || buf_int || + if (list_empty(&video->req_free) || buf_done || !(video->req_int_count % DIV_ROUND_UP(video->uvc_num_requests, 4))) { video->req_int_count = 0; diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c index 3bc6dcd88b2d..34985e4c31b8 100644 --- a/drivers/usb/host/xhci-mem.c +++ b/drivers/usb/host/xhci-mem.c @@ -2134,7 +2134,7 @@ static void xhci_add_in_port(struct xhci_hcd *xhci, unsigned int num_ports, { u32 temp, port_offset, port_count; int i; - u8 major_revision, minor_revision; + u8 major_revision, minor_revision, tmp_minor_revision; struct xhci_hub *rhub; struct device *dev = xhci_to_hcd(xhci)->self.sysdev; struct xhci_port_cap *port_cap; @@ -2154,6 +2154,15 @@ static void xhci_add_in_port(struct xhci_hcd *xhci, unsigned int num_ports, */ if (minor_revision > 0x00 && minor_revision < 0x10) minor_revision <<= 4; + /* + * Some zhaoxin's xHCI controller that follow usb3.1 spec + * but only support Gen1. + */ + if (xhci->quirks & XHCI_ZHAOXIN_HOST) { + tmp_minor_revision = minor_revision; + minor_revision = 0; + } + } else if (major_revision <= 0x02) { rhub = &xhci->usb2_rhub; } else { @@ -2163,10 +2172,6 @@ static void xhci_add_in_port(struct xhci_hcd *xhci, unsigned int num_ports, /* Ignoring port protocol we can't understand. FIXME */ return; } - rhub->maj_rev = XHCI_EXT_PORT_MAJOR(temp); - - if (rhub->min_rev < minor_revision) - rhub->min_rev = minor_revision; /* Port offset and count in the third dword, see section 7.2 */ temp = readl(addr + 2); @@ -2185,8 +2190,6 @@ static void xhci_add_in_port(struct xhci_hcd *xhci, unsigned int num_ports, if (xhci->num_port_caps > max_caps) return; - port_cap->maj_rev = major_revision; - port_cap->min_rev = minor_revision; port_cap->psi_count = XHCI_EXT_PORT_PSIC(temp); if (port_cap->psi_count) { @@ -2207,6 +2210,11 @@ static void xhci_add_in_port(struct xhci_hcd *xhci, unsigned int num_ports, XHCI_EXT_PORT_PSIV(port_cap->psi[i - 1]))) port_cap->psi_uid_count++; + if (xhci->quirks & XHCI_ZHAOXIN_HOST && + major_revision == 0x03 && + XHCI_EXT_PORT_PSIV(port_cap->psi[i]) >= 5) + minor_revision = tmp_minor_revision; + xhci_dbg(xhci, "PSIV:%d PSIE:%d PLT:%d PFD:%d LP:%d PSIM:%d\n", XHCI_EXT_PORT_PSIV(port_cap->psi[i]), XHCI_EXT_PORT_PSIE(port_cap->psi[i]), @@ -2216,6 +2224,15 @@ static void xhci_add_in_port(struct xhci_hcd *xhci, unsigned int num_ports, XHCI_EXT_PORT_PSIM(port_cap->psi[i])); } } + + rhub->maj_rev = major_revision; + + if (rhub->min_rev < minor_revision) + rhub->min_rev = minor_revision; + + port_cap->maj_rev = major_revision; + port_cap->min_rev = minor_revision; + /* cache usb2 port capabilities */ if (major_revision < 0x03 && xhci->num_ext_caps < max_caps) xhci->ext_caps[xhci->num_ext_caps++] = temp; @@ -2460,8 +2477,12 @@ int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags) * and our use of dma addresses in the trb_address_map radix tree needs * TRB_SEGMENT_SIZE alignment, so we pick the greater alignment need. */ - xhci->segment_pool = dma_pool_create("xHCI ring segments", dev, - TRB_SEGMENT_SIZE, TRB_SEGMENT_SIZE, xhci->page_size); + if (xhci->quirks & XHCI_ZHAOXIN_TRB_FETCH) + xhci->segment_pool = dma_pool_create("xHCI ring segments", dev, + TRB_SEGMENT_SIZE * 2, TRB_SEGMENT_SIZE * 2, xhci->page_size * 2); + else + xhci->segment_pool = dma_pool_create("xHCI ring segments", dev, + TRB_SEGMENT_SIZE, TRB_SEGMENT_SIZE, xhci->page_size); /* See Table 46 and Note on Figure 55 */ xhci->device_pool = dma_pool_create("xHCI input/output contexts", dev, diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c index fea3b92d6a40..ed875d6552c5 100644 --- a/drivers/usb/host/xhci-pci.c +++ b/drivers/usb/host/xhci-pci.c @@ -333,6 +333,18 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci) pdev->device == PCI_DEVICE_ID_AMD_PROMONTORYA_4)) xhci->quirks |= XHCI_NO_SOFT_RETRY; + if (pdev->vendor == PCI_VENDOR_ID_ZHAOXIN) { + xhci->quirks |= XHCI_ZHAOXIN_HOST; + + if (pdev->device == 0x9202) { + xhci->quirks |= XHCI_RESET_ON_RESUME; + xhci->quirks |= XHCI_ZHAOXIN_TRB_FETCH; + } + + if (pdev->device == 0x9203) + xhci->quirks |= XHCI_ZHAOXIN_TRB_FETCH; + } + /* xHC spec requires PCI devices to support D3hot and D3cold */ if (xhci->hci_version >= 0x120) xhci->quirks |= XHCI_DEFAULT_PM_RUNTIME_ALLOW; diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index 4d3adcc18af5..cf26f2237c37 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -20,6 +20,7 @@ #include #include #include +#include #include "xhci.h" #include "xhci-trace.h" @@ -611,8 +612,27 @@ static int xhci_init(struct usb_hcd *hcd) static int xhci_run_finished(struct xhci_hcd *xhci) { + unsigned long flags; + u32 temp; + + /* + * Enable interrupts before starting the host (xhci 4.2 and 5.5.2). + * Protect the short window before host is running with a lock + */ + spin_lock_irqsave(&xhci->lock, flags); + + xhci_dbg_trace(xhci, trace_xhci_dbg_init, "Enable interrupts"); + temp = readl(&xhci->op_regs->command); + temp |= (CMD_EIE); + writel(temp, &xhci->op_regs->command); + + xhci_dbg_trace(xhci, trace_xhci_dbg_init, "Enable primary interrupter"); + temp = readl(&xhci->ir_set->irq_pending); + writel(ER_IRQ_ENABLE(temp), &xhci->ir_set->irq_pending); + if (xhci_start(xhci)) { xhci_halt(xhci); + spin_unlock_irqrestore(&xhci->lock, flags); return -ENODEV; } xhci->shared_hcd->state = HC_STATE_RUNNING; @@ -623,6 +643,9 @@ static int xhci_run_finished(struct xhci_hcd *xhci) xhci_dbg_trace(xhci, trace_xhci_dbg_init, "Finished xhci_run for USB3 roothub"); + + spin_unlock_irqrestore(&xhci->lock, flags); + return 0; } @@ -671,19 +694,6 @@ int xhci_run(struct usb_hcd *hcd) temp |= (xhci->imod_interval / 250) & ER_IRQ_INTERVAL_MASK; writel(temp, &xhci->ir_set->irq_control); - /* Set the HCD state before we enable the irqs */ - temp = readl(&xhci->op_regs->command); - temp |= (CMD_EIE); - xhci_dbg_trace(xhci, trace_xhci_dbg_init, - "// Enable interrupts, cmd = 0x%x.", temp); - writel(temp, &xhci->op_regs->command); - - temp = readl(&xhci->ir_set->irq_pending); - xhci_dbg_trace(xhci, trace_xhci_dbg_init, - "// Enabling event ring interrupter %p by writing 0x%x to irq_pending", - xhci->ir_set, (unsigned int) ER_IRQ_ENABLE(temp)); - writel(ER_IRQ_ENABLE(temp), &xhci->ir_set->irq_pending); - if (xhci->quirks & XHCI_NEC_HOST) { struct xhci_command *command; @@ -1410,6 +1420,11 @@ static void xhci_unmap_temp_buf(struct usb_hcd *hcd, struct urb *urb) urb->transfer_buffer = NULL; } +void _trace_android_vh_xhci_urb_suitable_bypass(struct urb *urb, int *ret) +{ + trace_android_vh_xhci_urb_suitable_bypass(urb, ret); +} + /* * Bypass the DMA mapping if URB is suitable for Immediate Transfer (IDT), * we'll copy the actual data into the TRB address register. This is limited to diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h index d9a2c22146f0..272efa420cd3 100644 --- a/drivers/usb/host/xhci.h +++ b/drivers/usb/host/xhci.h @@ -1916,6 +1916,8 @@ struct xhci_hcd { #define XHCI_EP_CTX_BROKEN_DCS BIT_ULL(42) #define XHCI_SUSPEND_RESUME_CLKS BIT_ULL(43) #define XHCI_RESET_TO_DEFAULT BIT_ULL(44) +#define XHCI_ZHAOXIN_TRB_FETCH BIT_ULL(45) +#define XHCI_ZHAOXIN_HOST BIT_ULL(46) unsigned int num_active_eps; unsigned int limit_active_eps; @@ -2228,6 +2230,8 @@ static inline struct xhci_ring *xhci_urb_to_transfer_ring(struct xhci_hcd *xhci, urb->stream_id); } +void _trace_android_vh_xhci_urb_suitable_bypass(struct urb *urb, int *ret); + /* * TODO: As per spec Isochronous IDT transmissions are supported. We bypass * them anyways as we where unable to find a device that matches the @@ -2235,6 +2239,12 @@ static inline struct xhci_ring *xhci_urb_to_transfer_ring(struct xhci_hcd *xhci, */ static inline bool xhci_urb_suitable_for_idt(struct urb *urb) { + int ret = 1; + + _trace_android_vh_xhci_urb_suitable_bypass(urb, &ret); + if (ret <= 0) + return ret == 0; + if (!usb_endpoint_xfer_isoc(&urb->ep->desc) && usb_urb_dir_out(urb) && usb_endpoint_maxp(&urb->ep->desc) >= TRB_IDT_MAX_SIZE && urb->transfer_buffer_length <= TRB_IDT_MAX_SIZE && diff --git a/drivers/usb/misc/lvstest.c b/drivers/usb/misc/lvstest.c index c51679b818ba..c700ef620c8b 100644 --- a/drivers/usb/misc/lvstest.c +++ b/drivers/usb/misc/lvstest.c @@ -108,7 +108,7 @@ static ssize_t u3_entry_store(struct device *dev, int port; int ret; - if (!kstrtoint(buf, 0, &port) || port >= 1 || port <= 255) { + if (!kstrtoint(buf, 0, &port) && port >= 1 && port <= 255) { lvs->portnum = port; lvs->present = true; } @@ -143,7 +143,7 @@ static ssize_t u3_exit_store(struct device *dev, int port; int ret; - if (!kstrtoint(buf, 0, &port) || port >= 1 || port <= 255) { + if (!kstrtoint(buf, 0, &port) && port >= 1 && port <= 255) { lvs->portnum = port; lvs->present = true; } @@ -280,7 +280,7 @@ static ssize_t get_dev_desc_store(struct device *dev, struct usb_device_descriptor *descriptor; int ret, port; - if (!kstrtoint(buf, 0, &port) || port >= 1 || port <= 255) { + if (!kstrtoint(buf, 0, &port) && port >= 1 && port <= 255) { lvs->portnum = port; lvs->present = true; } diff --git a/drivers/usb/phy/Makefile b/drivers/usb/phy/Makefile index a5707658fbd0..5c3ba26ca017 100644 --- a/drivers/usb/phy/Makefile +++ b/drivers/usb/phy/Makefile @@ -31,5 +31,5 @@ obj-$(CONFIG_USB_MSM_SSPHY_QMP) += phy-msm-ssusb-qmp.o obj-$(CONFIG_MSM_HSUSB_PHY) += phy-msm-snps-hs.o obj-$(CONFIG_USB_MSM_EUSB2_PHY) += phy-msm-snps-eusb2.o obj-$(CONFIG_USB_M31_MSM_EUSB2_PHY) += phy-msm-m31-eusb2.o -obj-$(CONFIG_MSM_QUSB_PHY) += phy-msm-qusb.o +obj-$(CONFIG_MSM_QUSB_PHY) += phy-msm-qusb.o phy-msm-qusb-v2.o obj-$(CONFIG_MSM_SNPS_FEMTO_PHY) += phy-qcom-snps-28nm-hs.o diff --git a/drivers/usb/phy/phy-msm-qusb-v2.c b/drivers/usb/phy/phy-msm-qusb-v2.c new file mode 100644 index 000000000000..00769d2f8cf3 --- /dev/null +++ b/drivers/usb/phy/phy-msm-qusb-v2.c @@ -0,0 +1,1225 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2014-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2023, Qualcomm Innovation Center, Inc. All rights reserved. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* QUSB2PHY_PWR_CTRL1 register related bits */ +#define PWR_CTRL1_POWR_DOWN BIT(0) +#define CLAMP_N_EN BIT(1) + +/* QUSB2PHY_PLL_COMMON_STATUS_ONE register related bits */ +#define CORE_READY_STATUS BIT(0) + +/* Get TUNE value from efuse bit-mask */ +#define TUNE_VAL_MASK(val, pos, mask) ((val >> pos) & mask) + +/* QUSB2PHY_INTR_CTRL register related bits */ +#define DMSE_INTR_HIGH_SEL BIT(4) +#define DPSE_INTR_HIGH_SEL BIT(3) +#define CHG_DET_INTR_EN BIT(2) +#define DMSE_INTR_EN BIT(1) +#define DPSE_INTR_EN BIT(0) + +/* QUSB2PHY_PLL_CORE_INPUT_OVERRIDE register related bits */ +#define CORE_PLL_RATE BIT(0) +#define CORE_PLL_RATE_MUX BIT(1) +#define CORE_PLL_EN BIT(2) +#define CORE_PLL_EN_MUX BIT(3) +#define CORE_PLL_EN_FROM_RESET BIT(4) +#define CORE_RESET BIT(5) +#define CORE_RESET_MUX BIT(6) + +#define QUSB2PHY_1P8_VOL_MIN 1800000 /* uV */ +#define QUSB2PHY_1P8_VOL_MAX 1800000 /* uV */ +#define QUSB2PHY_1P8_HPM_LOAD 30000 /* uA */ + +#define QUSB2PHY_3P3_VOL_MIN 3075000 /* uV */ +#define QUSB2PHY_3P3_VOL_MAX 3200000 /* uV */ +#define QUSB2PHY_3P3_HPM_LOAD 30000 /* uA */ + +#define QUSB2PHY_REFGEN_VOL_MIN 1200000 /* uV */ +#define QUSB2PHY_REFGEN_VOL_MAX 1200000 /* uV */ +#define QUSB2PHY_REFGEN_HPM_LOAD 30000 /* uA */ + +#define LINESTATE_DP BIT(0) +#define LINESTATE_DM BIT(1) + +#define BIAS_CTRL_2_OVERRIDE_VAL 0x28 + +#define DEBUG_CTRL1_OVERRIDE_VAL 0x09 + +/* PERIPH_SS_PHY_REFGEN_NORTH_BG_CTRL register bits */ +#define BANDGAP_BYPASS BIT(0) + +/* DEBUG_CTRL2 register value to program VSTATUS MUX for PHY status */ +#define DEBUG_CTRL2_MUX_PLL_LOCK_STATUS 0x4 + +/* STAT5 register bits */ +#define VSTATUS_PLL_LOCK_STATUS_MASK BIT(0) + +/* DEBUG_CTRL4 register bits */ +#define FORCED_UTMI_DPPULLDOWN BIT(2) +#define FORCED_UTMI_DMPULLDOWN BIT(3) + +enum qusb_phy_reg { + PORT_TUNE1, + PLL_COMMON_STATUS_ONE, + PWR_CTRL1, + INTR_CTRL, + PLL_CORE_INPUT_OVERRIDE, + TEST1, + BIAS_CTRL_2, + DEBUG_CTRL1, + DEBUG_CTRL2, + DEBUG_CTRL3, + DEBUG_CTRL4, + STAT5, + USB2_PHY_REG_MAX, +}; + +struct qusb_phy { + struct usb_phy phy; + struct mutex lock; + void __iomem *base; + void __iomem *efuse_reg; + void __iomem *refgen_north_bg_reg; + void __iomem *eud_enable_reg; + + struct clk *ref_clk_src; + struct clk *ref_clk; + struct clk *cfg_ahb_clk; + struct reset_control *phy_reset; + + struct regulator *vdd; + struct regulator *vdda33; + struct regulator *vdda18; + int vdd_levels[3]; /* none, low, high */ + int init_seq_len; + int *qusb_phy_init_seq; + int host_init_seq_len; + int *qusb_phy_host_init_seq; + + unsigned int *phy_reg; + int qusb_phy_reg_offset_cnt; + + u32 tune_val; + int efuse_bit_pos; + int efuse_num_of_bits; + + bool cable_connected; + bool suspended; + bool dpdm_enable; + + struct regulator_desc dpdm_rdesc; + struct regulator_dev *dpdm_rdev; + + /* emulation targets specific */ + void __iomem *emu_phy_base; + bool emulation; + int *emu_init_seq; + int emu_init_seq_len; + int *phy_pll_reset_seq; + int phy_pll_reset_seq_len; + int *emu_dcm_reset_seq; + int emu_dcm_reset_seq_len; + + /* override TUNEX registers value */ + struct dentry *root; + u8 tune[5]; + u8 bias_ctrl2; + + bool override_bias_ctrl2; +}; + +static void qusb_phy_enable_clocks(struct qusb_phy *qphy, bool on) +{ + dev_dbg(qphy->phy.dev, "%s(): on:%d\n", __func__, on); + + if (on) { + clk_prepare_enable(qphy->ref_clk_src); + if (qphy->ref_clk) + clk_prepare_enable(qphy->ref_clk); + + if (qphy->cfg_ahb_clk) + clk_prepare_enable(qphy->cfg_ahb_clk); + + } else { + if (qphy->cfg_ahb_clk) + clk_disable_unprepare(qphy->cfg_ahb_clk); + + if (qphy->ref_clk) + clk_disable_unprepare(qphy->ref_clk); + + clk_disable_unprepare(qphy->ref_clk_src); + } +} + +static int qusb_phy_config_vdd(struct qusb_phy *qphy, int high) +{ + int min, ret; + + min = high ? 1 : 0; /* low or none? */ + ret = regulator_set_voltage(qphy->vdd, qphy->vdd_levels[min], + qphy->vdd_levels[2]); + if (ret) { + dev_err(qphy->phy.dev, "unable to set voltage for qusb vdd\n"); + return ret; + } + + dev_dbg(qphy->phy.dev, "min_vol:%d max_vol:%d\n", + qphy->vdd_levels[min], qphy->vdd_levels[2]); + return ret; +} + +static int qusb_phy_disable_power(struct qusb_phy *qphy) +{ + int ret = 0; + + mutex_lock(&qphy->lock); + + dev_dbg(qphy->phy.dev, "%s:req to turn off regulators\n", + __func__); + + ret = regulator_disable(qphy->vdda33); + if (ret) + dev_err(qphy->phy.dev, "Unable to disable vdda33:%d\n", ret); + + if (!regulator_is_enabled(qphy->vdda33)) { + ret = regulator_set_voltage(qphy->vdda33, 0, + QUSB2PHY_3P3_VOL_MAX); + if (ret) + dev_err(qphy->phy.dev, + "Unable to set (0) voltage for vdda33:%d\n", + ret); + + ret = regulator_set_load(qphy->vdda33, 0); + if (ret < 0) + dev_err(qphy->phy.dev, + "Unable to set (0) HPM of vdda33\n"); + + } + + ret = regulator_disable(qphy->vdda18); + if (ret) + dev_err(qphy->phy.dev, "Unable to disable vdda18:%d\n", ret); + + if (!regulator_is_enabled(qphy->vdda18)) { + ret = regulator_set_voltage(qphy->vdda18, 0, + QUSB2PHY_1P8_VOL_MAX); + if (ret) + dev_err(qphy->phy.dev, + "Unable to set (0) voltage for vdda18:%d\n", ret); + + ret = regulator_set_load(qphy->vdda18, 0); + if (ret < 0) + dev_err(qphy->phy.dev, + "Unable to set LPM of vdda18\n"); + } + + ret = regulator_disable(qphy->vdd); + if (ret) + dev_err(qphy->phy.dev, "Unable to disable vdd:%d\n", ret); + + if (!regulator_is_enabled(qphy->vdd)) { + ret = qusb_phy_config_vdd(qphy, false); + if (ret) + dev_err(qphy->phy.dev, "Unable unconfig VDD:%d\n", + ret); + } + + pr_debug("%s(): QUSB PHY's regulators are turned OFF.\n", __func__); + + mutex_unlock(&qphy->lock); + + return ret; +} + +static int qusb_phy_enable_power(struct qusb_phy *qphy) +{ + int ret = 0; + + mutex_lock(&qphy->lock); + + dev_dbg(qphy->phy.dev, "%s:req to turn on regulators\n", + __func__); + + ret = qusb_phy_config_vdd(qphy, true); + if (ret) { + dev_err(qphy->phy.dev, "Unable to config VDD:%d\n", + ret); + goto err_vdd; + } + + ret = regulator_enable(qphy->vdd); + if (ret) { + dev_err(qphy->phy.dev, "Unable to enable VDD\n"); + goto unconfig_vdd; + } + + ret = regulator_set_load(qphy->vdda18, QUSB2PHY_1P8_HPM_LOAD); + if (ret < 0) { + dev_err(qphy->phy.dev, "Unable to set HPM of vdda18:%d\n", ret); + goto disable_vdd; + } + + ret = regulator_set_voltage(qphy->vdda18, QUSB2PHY_1P8_VOL_MIN, + QUSB2PHY_1P8_VOL_MAX); + if (ret) { + dev_err(qphy->phy.dev, + "Unable to set voltage for vdda18:%d\n", ret); + goto put_vdda18_lpm; + } + + ret = regulator_enable(qphy->vdda18); + if (ret) { + dev_err(qphy->phy.dev, "Unable to enable vdda18:%d\n", ret); + goto unset_vdda18; + } + + ret = regulator_set_load(qphy->vdda33, QUSB2PHY_3P3_HPM_LOAD); + if (ret < 0) { + dev_err(qphy->phy.dev, "Unable to set HPM of vdda33:%d\n", ret); + goto disable_vdda18; + } + + ret = regulator_set_voltage(qphy->vdda33, QUSB2PHY_3P3_VOL_MIN, + QUSB2PHY_3P3_VOL_MAX); + if (ret) { + dev_err(qphy->phy.dev, + "Unable to set voltage for vdda33:%d\n", ret); + goto put_vdda33_lpm; + } + + ret = regulator_enable(qphy->vdda33); + if (ret) { + dev_err(qphy->phy.dev, "Unable to enable vdda33:%d\n", ret); + goto unset_vdd33; + } + + pr_debug("%s(): QUSB PHY's regulators are turned ON.\n", __func__); + + mutex_unlock(&qphy->lock); + + return ret; + +unset_vdd33: + ret = regulator_set_voltage(qphy->vdda33, 0, QUSB2PHY_3P3_VOL_MAX); + if (ret) + dev_err(qphy->phy.dev, + "Unable to set (0) voltage for vdda33:%d\n", ret); + +put_vdda33_lpm: + ret = regulator_set_load(qphy->vdda33, 0); + if (ret < 0) + dev_err(qphy->phy.dev, "Unable to set (0) HPM of vdda33\n"); + +disable_vdda18: + ret = regulator_disable(qphy->vdda18); + if (ret) + dev_err(qphy->phy.dev, "Unable to disable vdda18:%d\n", ret); + +unset_vdda18: + ret = regulator_set_voltage(qphy->vdda18, 0, QUSB2PHY_1P8_VOL_MAX); + if (ret) + dev_err(qphy->phy.dev, + "Unable to set (0) voltage for vdda18:%d\n", ret); + +put_vdda18_lpm: + ret = regulator_set_load(qphy->vdda18, 0); + if (ret < 0) + dev_err(qphy->phy.dev, "Unable to set LPM of vdda18\n"); + +disable_vdd: + ret = regulator_disable(qphy->vdd); + if (ret) + dev_err(qphy->phy.dev, "Unable to disable vdd:%d\n", + ret); + +unconfig_vdd: + ret = qusb_phy_config_vdd(qphy, false); + if (ret) + dev_err(qphy->phy.dev, "Unable unconfig VDD:%d\n", + ret); +err_vdd: + mutex_unlock(&qphy->lock); + + return ret; +} + +static void qusb_phy_get_tune1_param(struct qusb_phy *qphy) +{ + u8 reg; + u32 bit_mask = 1; + + pr_debug("%s(): num_of_bits:%d bit_pos:%d\n", __func__, + qphy->efuse_num_of_bits, + qphy->efuse_bit_pos); + + /* get bit mask based on number of bits to use with efuse reg */ + bit_mask = (bit_mask << qphy->efuse_num_of_bits) - 1; + + /* + * For 8nm zero is treated as a valid efuse value and driver + * should program the tune1 reg based on efuse value + */ + qphy->tune_val = readl_relaxed(qphy->efuse_reg); + pr_debug("%s(): bit_mask:%d efuse based tune1 value:%d\n", + __func__, bit_mask, qphy->tune_val); + + qphy->tune_val = TUNE_VAL_MASK(qphy->tune_val, + qphy->efuse_bit_pos, bit_mask); + reg = readb_relaxed(qphy->base + qphy->phy_reg[PORT_TUNE1]); + reg = reg & 0x0f; + reg |= (qphy->tune_val << 4); + + qphy->tune_val = reg; +} + +static void qusb_phy_write_seq(void __iomem *base, u32 *seq, int cnt, + unsigned long delay) +{ + int i; + + pr_debug("Seq count:%d\n", cnt); + for (i = 0; i < cnt; i = i+2) { + pr_debug("write 0x%02x to 0x%02x\n", seq[i], seq[i+1]); + writel_relaxed(seq[i], base + seq[i+1]); + if (delay) + usleep_range(delay, (delay + 2000)); + } +} + +static void qusb_phy_reset(struct qusb_phy *qphy) +{ + int ret; + + ret = reset_control_assert(qphy->phy_reset); + if (ret) + dev_err(qphy->phy.dev, "%s: phy_reset assert failed\n", + __func__); + usleep_range(100, 150); + + ret = reset_control_deassert(qphy->phy_reset); + if (ret) + dev_err(qphy->phy.dev, "%s: phy_reset deassert failed\n", + __func__); +} + +static bool qusb_phy_pll_locked(struct qusb_phy *qphy) +{ + u32 val; + + writel_relaxed(DEBUG_CTRL2_MUX_PLL_LOCK_STATUS, + qphy->base + qphy->phy_reg[DEBUG_CTRL2]); + + val = readl_relaxed(qphy->base + qphy->phy_reg[STAT5]); + + return (val & VSTATUS_PLL_LOCK_STATUS_MASK); +} + +static void qusb_phy_host_init(struct usb_phy *phy) +{ + u8 reg; + int p_index; + struct qusb_phy *qphy = container_of(phy, struct qusb_phy, phy); + + dev_dbg(phy->dev, "%s\n", __func__); + + qusb_phy_write_seq(qphy->base, qphy->qusb_phy_host_init_seq, + qphy->host_init_seq_len, 0); + + if (qphy->efuse_reg) { + if (!qphy->tune_val) + qusb_phy_get_tune1_param(qphy); + } else { + /* For non fused chips we need to write the TUNE1 param as + * specified in DT otherwise we will end up writing 0 to + * TUNE1 + */ + qphy->tune_val = readb_relaxed(qphy->base + + qphy->phy_reg[PORT_TUNE1]); + } + + writel_relaxed(qphy->tune_val | BIT(7), + qphy->base + qphy->phy_reg[PORT_TUNE1]); + pr_debug("%s(): Programming TUNE1 parameter as:%x\n", + __func__, readb_relaxed(qphy->base + + qphy->phy_reg[PORT_TUNE1])); + writel_relaxed(DEBUG_CTRL1_OVERRIDE_VAL, + qphy->base + qphy->phy_reg[DEBUG_CTRL1]); + + /* if debugfs based tunex params are set, use that value. */ + for (p_index = 0; p_index < 5; p_index++) { + if (qphy->tune[p_index]) + writel_relaxed(qphy->tune[p_index], + qphy->base + qphy->phy_reg[PORT_TUNE1] + + (4 * p_index)); + } + + if (qphy->refgen_north_bg_reg && qphy->override_bias_ctrl2) + if (readl_relaxed(qphy->refgen_north_bg_reg) & BANDGAP_BYPASS) + writel_relaxed(BIAS_CTRL_2_OVERRIDE_VAL, + qphy->base + qphy->phy_reg[BIAS_CTRL_2]); + + if (qphy->bias_ctrl2) + writel_relaxed(qphy->bias_ctrl2, + qphy->base + qphy->phy_reg[BIAS_CTRL_2]); + + /* Ensure above write is completed before turning ON ref clk */ + wmb(); + + /* Require to get phy pll lock successfully */ + usleep_range(150, 160); + + reg = readb_relaxed(qphy->base + qphy->phy_reg[PLL_COMMON_STATUS_ONE]); + dev_dbg(phy->dev, "QUSB2PHY_PLL_COMMON_STATUS_ONE:%x\n", reg); + if (!(reg & CORE_READY_STATUS)) + dev_err(phy->dev, "QUSB PHY PLL LOCK fails:%x\n", reg); +} + +static int qusb_phy_init(struct usb_phy *phy) +{ + struct qusb_phy *qphy = container_of(phy, struct qusb_phy, phy); + int p_index; + u8 reg; + + dev_dbg(phy->dev, "%s\n", __func__); + + if (qphy->eud_enable_reg && readl_relaxed(qphy->eud_enable_reg)) { + dev_err(qphy->phy.dev, "eud is enabled\n"); + return 0; + } + + qusb_phy_reset(qphy); + + if (qphy->qusb_phy_host_init_seq && qphy->phy.flags & PHY_HOST_MODE) { + qusb_phy_host_init(phy); + return 0; + } + + if (qphy->emulation) { + if (qphy->emu_init_seq) + qusb_phy_write_seq(qphy->emu_phy_base + 0x8000, + qphy->emu_init_seq, + qphy->emu_init_seq_len, 10000); + + if (qphy->qusb_phy_init_seq) + qusb_phy_write_seq(qphy->base, qphy->qusb_phy_init_seq, + qphy->init_seq_len, 0); + + /* Wait for 5ms as per QUSB2 RUMI sequence */ + usleep_range(5000, 7000); + + if (qphy->phy_pll_reset_seq) + qusb_phy_write_seq(qphy->base, qphy->phy_pll_reset_seq, + qphy->phy_pll_reset_seq_len, 10000); + + if (qphy->emu_dcm_reset_seq) + qusb_phy_write_seq(qphy->emu_phy_base, + qphy->emu_dcm_reset_seq, + qphy->emu_dcm_reset_seq_len, 10000); + + return 0; + } + + /* Disable the PHY */ + writel_relaxed(readl_relaxed(qphy->base + qphy->phy_reg[PWR_CTRL1]) | + PWR_CTRL1_POWR_DOWN, + qphy->base + qphy->phy_reg[PWR_CTRL1]); + + if (qphy->qusb_phy_init_seq) + qusb_phy_write_seq(qphy->base, qphy->qusb_phy_init_seq, + qphy->init_seq_len, 0); + if (qphy->efuse_reg) { + if (!qphy->tune_val) + qusb_phy_get_tune1_param(qphy); + + pr_debug("%s(): Programming TUNE1 parameter as:%x\n", __func__, + qphy->tune_val); + writel_relaxed(qphy->tune_val, + qphy->base + qphy->phy_reg[PORT_TUNE1]); + } + + /* if debugfs based tunex params are set, use that value. */ + for (p_index = 0; p_index < 5; p_index++) { + if (qphy->tune[p_index]) + writel_relaxed(qphy->tune[p_index], + qphy->base + qphy->phy_reg[PORT_TUNE1] + + (4 * p_index)); + } + + if (qphy->refgen_north_bg_reg && qphy->override_bias_ctrl2) + if (readl_relaxed(qphy->refgen_north_bg_reg) & BANDGAP_BYPASS) + writel_relaxed(BIAS_CTRL_2_OVERRIDE_VAL, + qphy->base + qphy->phy_reg[BIAS_CTRL_2]); + + if (qphy->bias_ctrl2) + writel_relaxed(qphy->bias_ctrl2, + qphy->base + qphy->phy_reg[BIAS_CTRL_2]); + + /* ensure above writes are completed before re-enabling PHY */ + wmb(); + + /* Enable the PHY */ + writel_relaxed(readl_relaxed(qphy->base + qphy->phy_reg[PWR_CTRL1]) & + ~PWR_CTRL1_POWR_DOWN, + qphy->base + qphy->phy_reg[PWR_CTRL1]); + + /* Ensure above write is completed before turning ON ref clk */ + wmb(); + + /* Require to get phy pll lock successfully */ + usleep_range(150, 160); + + reg = readb_relaxed(qphy->base + qphy->phy_reg[PLL_COMMON_STATUS_ONE]); + dev_dbg(phy->dev, "QUSB2PHY_PLL_COMMON_STATUS_ONE:%x\n", reg); + if (!(reg & CORE_READY_STATUS)) { + dev_err(phy->dev, "QUSB PHY PLL LOCK fails:%x\n", reg); + WARN_ON(1); + } + return 0; +} + +static void qusb_phy_shutdown(struct usb_phy *phy) +{ + struct qusb_phy *qphy = container_of(phy, struct qusb_phy, phy); + + dev_dbg(phy->dev, "%s\n", __func__); + + qusb_phy_disable_power(qphy); + +} + +static u32 qusb_phy_get_linestate(struct qusb_phy *qphy) +{ + u32 linestate = 0; + + if (qphy->cable_connected) { + if (qphy->phy.flags & PHY_HSFS_MODE) + linestate |= LINESTATE_DP; + else if (qphy->phy.flags & PHY_LS_MODE) + linestate |= LINESTATE_DM; + } + return linestate; +} + +/** + * Performs QUSB2 PHY suspend/resume functionality. + * + * @uphy - usb phy pointer. + * @suspend - to enable suspend or not. 1 - suspend, 0 - resume + * + */ +static int qusb_phy_set_suspend(struct usb_phy *phy, int suspend) +{ + struct qusb_phy *qphy = container_of(phy, struct qusb_phy, phy); + u32 linestate = 0, intr_mask = 0; + + if (qphy->suspended == suspend) { + if (qphy->phy.flags & PHY_SUS_OVERRIDE) + goto suspend; + + dev_dbg(phy->dev, "%s: USB PHY is already suspended\n", + __func__); + return 0; + } + +suspend: + if (suspend) { + /* Bus suspend case */ + if (qphy->cable_connected) { + /* Disable all interrupts */ + writel_relaxed(0x00, + qphy->base + qphy->phy_reg[INTR_CTRL]); + + linestate = qusb_phy_get_linestate(qphy); + /* + * D+/D- interrupts are level-triggered, but we are + * only interested if the line state changes, so enable + * the high/low trigger based on current state. In + * other words, enable the triggers _opposite_ of what + * the current D+/D- levels are. + * e.g. if currently D+ high, D- low (HS 'J'/Suspend), + * configure the mask to trigger on D+ low OR D- high + */ + intr_mask = DPSE_INTR_EN | DMSE_INTR_EN; + if (!(linestate & LINESTATE_DP)) /* D+ low */ + intr_mask |= DPSE_INTR_HIGH_SEL; + if (!(linestate & LINESTATE_DM)) /* D- low */ + intr_mask |= DMSE_INTR_HIGH_SEL; + + writel_relaxed(intr_mask, + qphy->base + qphy->phy_reg[INTR_CTRL]); + + if (linestate & (LINESTATE_DP | LINESTATE_DM)) { + /* enable phy auto-resume */ + writel_relaxed(0x91, + qphy->base + qphy->phy_reg[TEST1]); + /* Delay recommended between TEST1 writes */ + usleep_range(10, 20); + writel_relaxed(0x90, + qphy->base + qphy->phy_reg[TEST1]); + } + + dev_dbg(phy->dev, "%s: intr_mask = %x\n", + __func__, intr_mask); + + /* Makes sure that above write goes through */ + wmb(); + qusb_phy_enable_clocks(qphy, false); + } else { /* Cable disconnect case */ + /* Disable all interrupts */ + dev_dbg(phy->dev, "%s: phy->flags:0x%x\n", + __func__, qphy->phy.flags); + if (!(qphy->phy.flags & EUD_SPOOF_DISCONNECT)) { + dev_dbg(phy->dev, "turning off clocks/ldo\n"); + writel_relaxed(0x00, + qphy->base + qphy->phy_reg[INTR_CTRL]); + qusb_phy_reset(qphy); + qusb_phy_enable_clocks(qphy, false); + qusb_phy_disable_power(qphy); + } + } + qphy->suspended = true; + } else { + /* Bus resume case */ + if (qphy->cable_connected) { + qusb_phy_enable_clocks(qphy, true); + /* Clear all interrupts on resume */ + writel_relaxed(0x00, + qphy->base + qphy->phy_reg[INTR_CTRL]); + + /* Reset PLL if needed */ + if (!qusb_phy_pll_locked(qphy)) { + dev_dbg(phy->dev, "%s: reset PLL\n", __func__); + /* hold core PLL into reset */ + writel_relaxed(CORE_PLL_EN_FROM_RESET | + CORE_RESET | CORE_RESET_MUX, + qphy->base + + qphy->phy_reg[PLL_CORE_INPUT_OVERRIDE]); + + /* Wait for PLL to get reset */ + usleep_range(10, 20); + + /* bring core PLL out of reset */ + writel_relaxed(CORE_PLL_EN_FROM_RESET, + qphy->base + + qphy->phy_reg[PLL_CORE_INPUT_OVERRIDE]); + + /* Makes sure that above write goes through */ + wmb(); + } + } else { /* Cable connect case */ + qusb_phy_enable_power(qphy); + qusb_phy_enable_clocks(qphy, true); + } + qphy->suspended = false; + } + + return 0; +} + +static int qusb_phy_notify_connect(struct usb_phy *phy, + enum usb_device_speed speed) +{ + struct qusb_phy *qphy = container_of(phy, struct qusb_phy, phy); + + qphy->cable_connected = true; + + dev_dbg(phy->dev, "QUSB PHY: connect notification cable_connected=%d\n", + qphy->cable_connected); + return 0; +} + +static int qusb_phy_notify_disconnect(struct usb_phy *phy, + enum usb_device_speed speed) +{ + struct qusb_phy *qphy = container_of(phy, struct qusb_phy, phy); + + qphy->cable_connected = false; + + dev_dbg(phy->dev, "QUSB PHY: connect notification cable_connected=%d\n", + qphy->cable_connected); + return 0; +} + +static int qusb_phy_dpdm_regulator_enable(struct regulator_dev *rdev) +{ + int ret = 0; + struct qusb_phy *qphy = rdev_get_drvdata(rdev); + + dev_dbg(qphy->phy.dev, "%s dpdm_enable:%d\n", + __func__, qphy->dpdm_enable); + + if (qphy->eud_enable_reg && readl_relaxed(qphy->eud_enable_reg)) { + dev_err(qphy->phy.dev, "eud is enabled\n"); + return 0; + } + + if (!qphy->dpdm_enable) { + ret = qusb_phy_enable_power(qphy); + if (ret < 0) { + dev_dbg(qphy->phy.dev, + "dpdm regulator enable failed:%d\n", ret); + return ret; + } + qphy->dpdm_enable = true; + qusb_phy_reset(qphy); + } + + return ret; +} + +static int qusb_phy_dpdm_regulator_disable(struct regulator_dev *rdev) +{ + int ret = 0; + struct qusb_phy *qphy = rdev_get_drvdata(rdev); + + dev_dbg(qphy->phy.dev, "%s dpdm_enable:%d\n", + __func__, qphy->dpdm_enable); + + if (qphy->dpdm_enable) { + ret = qusb_phy_disable_power(qphy); + if (ret < 0) { + dev_dbg(qphy->phy.dev, + "dpdm regulator disable failed:%d\n", ret); + return ret; + } + qphy->dpdm_enable = false; + } + + return ret; +} + +static int qusb_phy_dpdm_regulator_is_enabled(struct regulator_dev *rdev) +{ + struct qusb_phy *qphy = rdev_get_drvdata(rdev); + + dev_dbg(qphy->phy.dev, "%s qphy->dpdm_enable = %d\n", __func__, + qphy->dpdm_enable); + return qphy->dpdm_enable; +} + +static const struct regulator_ops qusb_phy_dpdm_regulator_ops = { + .enable = qusb_phy_dpdm_regulator_enable, + .disable = qusb_phy_dpdm_regulator_disable, + .is_enabled = qusb_phy_dpdm_regulator_is_enabled, +}; + +static int qusb_phy_regulator_init(struct qusb_phy *qphy) +{ + struct device *dev = qphy->phy.dev; + struct regulator_config cfg = {}; + struct regulator_init_data *init_data; + + init_data = devm_kzalloc(dev, sizeof(*init_data), GFP_KERNEL); + if (!init_data) + return -ENOMEM; + + init_data->constraints.valid_ops_mask |= REGULATOR_CHANGE_STATUS; + qphy->dpdm_rdesc.owner = THIS_MODULE; + qphy->dpdm_rdesc.type = REGULATOR_VOLTAGE; + qphy->dpdm_rdesc.ops = &qusb_phy_dpdm_regulator_ops; + qphy->dpdm_rdesc.name = kbasename(dev->of_node->full_name); + + cfg.dev = dev; + cfg.init_data = init_data; + cfg.driver_data = qphy; + cfg.of_node = dev->of_node; + + qphy->dpdm_rdev = devm_regulator_register(dev, &qphy->dpdm_rdesc, &cfg); + + return PTR_ERR_OR_ZERO(qphy->dpdm_rdev); +} + +static int qusb_phy_create_debugfs(struct qusb_phy *qphy) +{ + int ret = 0, i; + char name[6]; + + qphy->root = debugfs_create_dir(dev_name(qphy->phy.dev), NULL); + if (IS_ERR_OR_NULL(qphy->root)) { + dev_err(qphy->phy.dev, + "can't create debugfs root for %s\n", + dev_name(qphy->phy.dev)); + ret = -ENOMEM; + goto create_err; + } + + for (i = 0; i < 5; i++) { + snprintf(name, sizeof(name), "tune%d", (i + 1)); + debugfs_create_x8(name, 0644, qphy->root, + &qphy->tune[i]); + } + + debugfs_create_x8("bias_ctrl2", 0644, qphy->root, + &qphy->bias_ctrl2); +create_err: + return ret; +} + +static int qusb2_get_regulators(struct qusb_phy *qphy) +{ + struct device *dev = qphy->phy.dev; + + qphy->vdd = devm_regulator_get(dev, "vdd"); + if (IS_ERR(qphy->vdd)) { + dev_err(dev, "unable to get vdd supply\n"); + return PTR_ERR(qphy->vdd); + } + + qphy->vdda33 = devm_regulator_get(dev, "vdda33"); + if (IS_ERR(qphy->vdda33)) { + dev_err(dev, "unable to get vdda33 supply\n"); + return PTR_ERR(qphy->vdda33); + } + + qphy->vdda18 = devm_regulator_get(dev, "vdda18"); + if (IS_ERR(qphy->vdda18)) { + dev_err(dev, "unable to get vdda18 supply\n"); + return PTR_ERR(qphy->vdda18); + } + + return 0; +} + +static int qusb_phy_probe(struct platform_device *pdev) +{ + struct qusb_phy *qphy; + struct device *dev = &pdev->dev; + struct resource *res; + int ret = 0, size = 0; + + qphy = devm_kzalloc(dev, sizeof(*qphy), GFP_KERNEL); + if (!qphy) + return -ENOMEM; + + qphy->phy.dev = dev; + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, + "qusb_phy_base"); + qphy->base = devm_ioremap_resource(dev, res); + if (IS_ERR(qphy->base)) + return PTR_ERR(qphy->base); + + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, + "emu_phy_base"); + if (res) { + qphy->emu_phy_base = devm_ioremap_resource(dev, res); + if (IS_ERR(qphy->emu_phy_base)) { + dev_dbg(dev, "couldn't ioremap emu_phy_base\n"); + qphy->emu_phy_base = NULL; + } + } + + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, + "efuse_addr"); + if (res) { + qphy->efuse_reg = devm_ioremap(dev, res->start, + resource_size(res)); + if (!IS_ERR_OR_NULL(qphy->efuse_reg)) { + ret = of_property_read_u32(dev->of_node, + "qcom,efuse-bit-pos", + &qphy->efuse_bit_pos); + if (!ret) { + ret = of_property_read_u32(dev->of_node, + "qcom,efuse-num-bits", + &qphy->efuse_num_of_bits); + } + + if (ret) { + dev_err(dev, + "DT Value for efuse is invalid.\n"); + return -EINVAL; + } + } + } + + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, + "refgen_north_bg_reg_addr"); + if (res) + qphy->refgen_north_bg_reg = devm_ioremap(dev, res->start, + resource_size(res)); + + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, + "eud_enable_reg"); + if (res) { + qphy->eud_enable_reg = devm_ioremap_resource(dev, res); + if (IS_ERR(qphy->eud_enable_reg)) { + dev_err(dev, "err getting eud_enable_reg address\n"); + return PTR_ERR(qphy->eud_enable_reg); + } + } + + /* ref_clk_src is needed irrespective of SE_CLK or DIFF_CLK usage */ + qphy->ref_clk_src = devm_clk_get(dev, "ref_clk_src"); + if (IS_ERR(qphy->ref_clk_src)) { + dev_dbg(dev, "clk get failed for ref_clk_src\n"); + ret = PTR_ERR(qphy->ref_clk_src); + return ret; + } + + /* ref_clk is needed only for DIFF_CLK case, hence make it optional. */ + if (of_property_match_string(pdev->dev.of_node, + "clock-names", "ref_clk") >= 0) { + qphy->ref_clk = devm_clk_get(dev, "ref_clk"); + if (IS_ERR(qphy->ref_clk)) { + ret = PTR_ERR(qphy->ref_clk); + if (ret != -EPROBE_DEFER) + dev_dbg(dev, + "clk get failed for ref_clk\n"); + return ret; + } + + clk_set_rate(qphy->ref_clk, 19200000); + } + + if (of_property_match_string(pdev->dev.of_node, + "clock-names", "cfg_ahb_clk") >= 0) { + qphy->cfg_ahb_clk = devm_clk_get(dev, "cfg_ahb_clk"); + if (IS_ERR(qphy->cfg_ahb_clk)) { + ret = PTR_ERR(qphy->cfg_ahb_clk); + if (ret != -EPROBE_DEFER) + dev_err(dev, + "clk get failed for cfg_ahb_clk ret %d\n", ret); + return ret; + } + } + + qphy->phy_reset = devm_reset_control_get(dev, "phy_reset"); + if (IS_ERR(qphy->phy_reset)) + return PTR_ERR(qphy->phy_reset); + + qphy->emulation = of_property_read_bool(dev->of_node, + "qcom,emulation"); + + of_get_property(dev->of_node, "qcom,emu-init-seq", &size); + if (size) { + qphy->emu_init_seq = devm_kzalloc(dev, + size, GFP_KERNEL); + if (qphy->emu_init_seq) { + qphy->emu_init_seq_len = + (size / sizeof(*qphy->emu_init_seq)); + if (qphy->emu_init_seq_len % 2) { + dev_err(dev, "invalid emu_init_seq_len\n"); + return -EINVAL; + } + + of_property_read_u32_array(dev->of_node, + "qcom,emu-init-seq", + qphy->emu_init_seq, + qphy->emu_init_seq_len); + } else { + dev_dbg(dev, + "error allocating memory for emu_init_seq\n"); + } + } + + size = 0; + of_get_property(dev->of_node, "qcom,phy-pll-reset-seq", &size); + if (size) { + qphy->phy_pll_reset_seq = devm_kzalloc(dev, + size, GFP_KERNEL); + if (qphy->phy_pll_reset_seq) { + qphy->phy_pll_reset_seq_len = + (size / sizeof(*qphy->phy_pll_reset_seq)); + if (qphy->phy_pll_reset_seq_len % 2) { + dev_err(dev, "invalid phy_pll_reset_seq_len\n"); + return -EINVAL; + } + + of_property_read_u32_array(dev->of_node, + "qcom,phy-pll-reset-seq", + qphy->phy_pll_reset_seq, + qphy->phy_pll_reset_seq_len); + } else { + dev_dbg(dev, + "error allocating memory for phy_pll_reset_seq\n"); + } + } + + size = 0; + of_get_property(dev->of_node, "qcom,emu-dcm-reset-seq", &size); + if (size) { + qphy->emu_dcm_reset_seq = devm_kzalloc(dev, + size, GFP_KERNEL); + if (qphy->emu_dcm_reset_seq) { + qphy->emu_dcm_reset_seq_len = + (size / sizeof(*qphy->emu_dcm_reset_seq)); + if (qphy->emu_dcm_reset_seq_len % 2) { + dev_err(dev, "invalid emu_dcm_reset_seq_len\n"); + return -EINVAL; + } + + of_property_read_u32_array(dev->of_node, + "qcom,emu-dcm-reset-seq", + qphy->emu_dcm_reset_seq, + qphy->emu_dcm_reset_seq_len); + } else { + dev_dbg(dev, + "error allocating memory for emu_dcm_reset_seq\n"); + } + } + + size = 0; + of_get_property(dev->of_node, "qcom,qusb-phy-reg-offset", &size); + if (size) { + qphy->phy_reg = devm_kzalloc(dev, size, GFP_KERNEL); + if (qphy->phy_reg) { + qphy->qusb_phy_reg_offset_cnt = + size / sizeof(*qphy->phy_reg); + if (qphy->qusb_phy_reg_offset_cnt != USB2_PHY_REG_MAX) { + dev_err(dev, "invalid reg offset count\n"); + return -EINVAL; + } + + of_property_read_u32_array(dev->of_node, + "qcom,qusb-phy-reg-offset", + qphy->phy_reg, + qphy->qusb_phy_reg_offset_cnt); + } else { + dev_err(dev, "err mem alloc for qusb_phy_reg_offset\n"); + return -ENOMEM; + } + } else { + dev_err(dev, "err provide qcom,qmp-phy-reg-offset\n"); + return -EINVAL; + } + + size = 0; + of_get_property(dev->of_node, "qcom,qusb-phy-init-seq", &size); + if (size) { + qphy->qusb_phy_init_seq = devm_kzalloc(dev, + size, GFP_KERNEL); + if (qphy->qusb_phy_init_seq) { + qphy->init_seq_len = + (size / sizeof(*qphy->qusb_phy_init_seq)); + if (qphy->init_seq_len % 2) { + dev_err(dev, "invalid init_seq_len\n"); + return -EINVAL; + } + + of_property_read_u32_array(dev->of_node, + "qcom,qusb-phy-init-seq", + qphy->qusb_phy_init_seq, + qphy->init_seq_len); + } else { + dev_err(dev, + "error allocating memory for phy_init_seq\n"); + } + } + + qphy->host_init_seq_len = of_property_count_elems_of_size(dev->of_node, + "qcom,qusb-phy-host-init-seq", + sizeof(*qphy->qusb_phy_host_init_seq)); + if (qphy->host_init_seq_len > 0) { + qphy->qusb_phy_host_init_seq = devm_kcalloc(dev, + qphy->host_init_seq_len, + sizeof(*qphy->qusb_phy_host_init_seq), + GFP_KERNEL); + if (qphy->qusb_phy_host_init_seq) + of_property_read_u32_array(dev->of_node, + "qcom,qusb-phy-host-init-seq", + qphy->qusb_phy_host_init_seq, + qphy->host_init_seq_len); + else + return -ENOMEM; + } + + qphy->override_bias_ctrl2 = of_property_read_bool(dev->of_node, + "qcom,override-bias-ctrl2"); + + ret = of_property_read_u32_array(dev->of_node, "qcom,vdd-voltage-level", + (u32 *) qphy->vdd_levels, + ARRAY_SIZE(qphy->vdd_levels)); + if (ret) { + dev_err(dev, "error reading qcom,vdd-voltage-level property\n"); + return ret; + } + + ret = qusb2_get_regulators(qphy); + if (ret) + return ret; + + mutex_init(&qphy->lock); + platform_set_drvdata(pdev, qphy); + + qphy->phy.label = "msm-qusb-phy-v2"; + qphy->phy.init = qusb_phy_init; + qphy->phy.set_suspend = qusb_phy_set_suspend; + qphy->phy.shutdown = qusb_phy_shutdown; + qphy->phy.type = USB_PHY_TYPE_USB2; + qphy->phy.notify_connect = qusb_phy_notify_connect; + qphy->phy.notify_disconnect = qusb_phy_notify_disconnect; + + ret = usb_add_phy_dev(&qphy->phy); + if (ret) + return ret; + + ret = qusb_phy_regulator_init(qphy); + if (ret) + usb_remove_phy(&qphy->phy); + + qphy->suspended = true; + qusb_phy_create_debugfs(qphy); + + /* + * EUD may be enable in boot loader and to keep EUD session alive across + * kernel boot till USB phy driver is initialized based on cable status, + * keep LDOs on here. + */ + if (qphy->eud_enable_reg && readl_relaxed(qphy->eud_enable_reg)) + qusb_phy_enable_power(qphy); + + return ret; +} + +static int qusb_phy_remove(struct platform_device *pdev) +{ + struct qusb_phy *qphy = platform_get_drvdata(pdev); + + usb_remove_phy(&qphy->phy); + qphy->cable_connected = false; + qusb_phy_set_suspend(&qphy->phy, true); + debugfs_remove_recursive(qphy->root); + + return 0; +} + +static const struct of_device_id qusb_phy_id_table[] = { + { .compatible = "qcom,qusb2phy-v2", }, + { }, +}; +MODULE_DEVICE_TABLE(of, qusb_phy_id_table); + +static struct platform_driver qusb_phy_driver = { + .probe = qusb_phy_probe, + .remove = qusb_phy_remove, + .driver = { + .name = "msm-qusb-phy-v2", + .of_match_table = of_match_ptr(qusb_phy_id_table), + }, +}; + +module_platform_driver(qusb_phy_driver); + +MODULE_DESCRIPTION("MSM QUSB2 PHY v2 driver"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/usb/phy/phy-msm-snps-eusb2.c b/drivers/usb/phy/phy-msm-snps-eusb2.c index 75f447332b2a..3da0d772dd0d 100644 --- a/drivers/usb/phy/phy-msm-snps-eusb2.c +++ b/drivers/usb/phy/phy-msm-snps-eusb2.c @@ -765,6 +765,10 @@ static int msm_eusb2_phy_init(struct usb_phy *uphy) msm_eusb2_write_readback(phy->base, USB_PHY_HS_PHY_CTRL2, USB2_SUSPEND_N_SEL, 0); + + msm_eusb2_write_readback(phy->base, USB_PHY_CFG0, + CMN_CTRL_OVERRIDE_EN, 0x00); + return 0; } @@ -848,7 +852,7 @@ static int msm_eusb2_phy_notify_disconnect(struct usb_phy *uphy, { struct msm_eusb2_phy *phy = container_of(uphy, struct msm_eusb2_phy, phy); - if (is_eud_debug_mode_active(phy)) { + if (is_eud_debug_mode_active(phy) && !(phy->phy.flags & EUD_SPOOF_DISCONNECT)) { msm_eusb2_phy_update_eud_detect(phy, false); /* Ensure that EUD disable occurs before re-enabling */ mb(); diff --git a/drivers/usb/phy/phy-msm-snps-hs.c b/drivers/usb/phy/phy-msm-snps-hs.c index c590e1fcef53..a9617d8c5fa4 100644 --- a/drivers/usb/phy/phy-msm-snps-hs.c +++ b/drivers/usb/phy/phy-msm-snps-hs.c @@ -598,7 +598,15 @@ static int msm_hsphy_set_suspend(struct usb_phy *uphy, int suspend) suspend: if (suspend) { /* Bus suspend */ - if (phy->cable_connected) { + /* + * The HUB class drivers calls usb_phy_notify_disconnect() upon a device + * disconnect. Consider a scenario where a USB device is disconnected without + * detaching the OTG cable. phy->cable_connected is marked false due to above + * mentioned call path. Now, while entering low power mode (host bus suspend), + * we come here and turn off regulators thinking no cable is connected. Prevent + * this by not turning off regulators while in host mode. + */ + if (phy->cable_connected || (phy->phy.flags & PHY_HOST_MODE)) { /* Enable auto-resume functionality during host mode * bus suspend with some FS/HS peripheral connected. */ diff --git a/drivers/usb/phy/phy-tahvo.c b/drivers/usb/phy/phy-tahvo.c index a3e043e3e4aa..d0672b671298 100644 --- a/drivers/usb/phy/phy-tahvo.c +++ b/drivers/usb/phy/phy-tahvo.c @@ -395,7 +395,7 @@ static int tahvo_usb_probe(struct platform_device *pdev) tu->irq = ret = platform_get_irq(pdev, 0); if (ret < 0) - return ret; + goto err_remove_phy; ret = request_threaded_irq(tu->irq, NULL, tahvo_usb_vbus_interrupt, IRQF_ONESHOT, "tahvo-vbus", tu); diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c index e12fec4c2e2f..6692440c1e0a 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c @@ -1151,6 +1151,10 @@ static const struct usb_device_id option_ids[] = { { USB_DEVICE(QUALCOMM_VENDOR_ID, 0x90fa), .driver_info = RSVD(3) }, /* u-blox products */ + { USB_DEVICE(UBLOX_VENDOR_ID, 0x1311) }, /* u-blox LARA-R6 01B */ + { USB_DEVICE(UBLOX_VENDOR_ID, 0x1312), /* u-blox LARA-R6 01B (RMNET) */ + .driver_info = RSVD(4) }, + { USB_DEVICE_INTERFACE_CLASS(UBLOX_VENDOR_ID, 0x1313, 0xff) }, /* u-blox LARA-R6 01B (ECM) */ { USB_DEVICE(UBLOX_VENDOR_ID, 0x1341) }, /* u-blox LARA-L6 */ { USB_DEVICE(UBLOX_VENDOR_ID, 0x1342), /* u-blox LARA-L6 (RMNET) */ .driver_info = RSVD(4) }, diff --git a/drivers/usb/typec/ucsi/ucsi.c b/drivers/usb/typec/ucsi/ucsi.c index bb55aacd9548..78263a3d9b24 100644 --- a/drivers/usb/typec/ucsi/ucsi.c +++ b/drivers/usb/typec/ucsi/ucsi.c @@ -733,6 +733,7 @@ static void ucsi_handle_connector_change(struct work_struct *work) if (ret < 0) { dev_err(ucsi->dev, "%s: GET_CONNECTOR_STATUS failed (%d)\n", __func__, ret); + clear_bit(EVENT_PENDING, &con->ucsi->flags); goto out_unlock; } diff --git a/drivers/vhost/vringh.c b/drivers/vhost/vringh.c index 786876af0a73..13b75213ebaa 100644 --- a/drivers/vhost/vringh.c +++ b/drivers/vhost/vringh.c @@ -123,8 +123,18 @@ static inline ssize_t vringh_iov_xfer(struct vringh *vrh, done += partlen; len -= partlen; ptr += partlen; + iov->consumed += partlen; + iov->iov[iov->i].iov_len -= partlen; + iov->iov[iov->i].iov_base += partlen; - vringh_kiov_advance(iov, partlen); + if (!iov->iov[iov->i].iov_len) { + /* Fix up old iov element then increment. */ + iov->iov[iov->i].iov_len = iov->consumed; + iov->iov[iov->i].iov_base -= iov->consumed; + + iov->consumed = 0; + iov->i++; + } } return done; } diff --git a/drivers/video/fbdev/au1200fb.c b/drivers/video/fbdev/au1200fb.c index a8a0a448cdb5..80f54111baec 100644 --- a/drivers/video/fbdev/au1200fb.c +++ b/drivers/video/fbdev/au1200fb.c @@ -1732,6 +1732,9 @@ static int au1200fb_drv_probe(struct platform_device *dev) /* Now hook interrupt too */ irq = platform_get_irq(dev, 0); + if (irq < 0) + return irq; + ret = request_irq(irq, au1200fb_handle_irq, IRQF_SHARED, "lcd", (void *)dev); if (ret) { diff --git a/drivers/video/fbdev/imxfb.c b/drivers/video/fbdev/imxfb.c index ad598257ab38..cd376a9bfe1b 100644 --- a/drivers/video/fbdev/imxfb.c +++ b/drivers/video/fbdev/imxfb.c @@ -602,10 +602,10 @@ static int imxfb_activate_var(struct fb_var_screeninfo *var, struct fb_info *inf if (var->hsync_len < 1 || var->hsync_len > 64) printk(KERN_ERR "%s: invalid hsync_len %d\n", info->fix.id, var->hsync_len); - if (var->left_margin > 255) + if (var->left_margin < 3 || var->left_margin > 255) printk(KERN_ERR "%s: invalid left_margin %d\n", info->fix.id, var->left_margin); - if (var->right_margin > 255) + if (var->right_margin < 1 || var->right_margin > 255) printk(KERN_ERR "%s: invalid right_margin %d\n", info->fix.id, var->right_margin); if (var->yres < 1 || var->yres > ymax_mask) diff --git a/drivers/video/fbdev/omap/lcd_mipid.c b/drivers/video/fbdev/omap/lcd_mipid.c index a75ae0c9b14c..d1cd8785d011 100644 --- a/drivers/video/fbdev/omap/lcd_mipid.c +++ b/drivers/video/fbdev/omap/lcd_mipid.c @@ -563,11 +563,15 @@ static int mipid_spi_probe(struct spi_device *spi) r = mipid_detect(md); if (r < 0) - return r; + goto free_md; omapfb_register_panel(&md->panel); return 0; + +free_md: + kfree(md); + return r; } static int mipid_spi_remove(struct spi_device *spi) diff --git a/drivers/virt/gunyah/gh_main.c b/drivers/virt/gunyah/gh_main.c index 37fb1c180355..56819dddaf66 100644 --- a/drivers/virt/gunyah/gh_main.c +++ b/drivers/virt/gunyah/gh_main.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. + * Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved. */ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt @@ -264,7 +264,12 @@ static int gh_vcpu_release(struct inode *inode, struct file *filp) { struct gh_vcpu *vcpu = filp->private_data; - gh_put_vm(vcpu->vm); + /* need to create workqueue if critical vm */ + if (vcpu->vm->keep_running) + gh_vcpu_create_wq(vcpu->vm->vmid, vcpu->vcpu_id); + else + gh_put_vm(vcpu->vm); + return 0; } @@ -452,7 +457,26 @@ int gh_reclaim_mem(struct gh_vm *vm, phys_addr_t phys, } ret = hyp_assign_phys(phys, size, srcVM, 1, destVM, destVMperm, 1); + if (ret) + pr_err("failed hyp_assign for %pa address\t" + " of size %zx - subsys VMid %d rc:%d\n", + &phys, size, vmid, ret); + if (vm->ext_region_supported) { + if (!is_system_vm) { + ret = gh_rm_mem_reclaim(vm->ext_region->ext_mem_handle, 0); + if (ret) + pr_err("Failed to reclaim memory for %d, %d\n", + vm->vmid, ret); + } + ret |= hyp_assign_phys(vm->ext_region->ext_phys, + vm->ext_region->ext_size, srcVM, 1, destVM, destVMperm, 1); + if (ret) + pr_err("failed hyp_assign for %pa address\t" + " of size %zx - subsys VMid %d rc:%d\n", + &vm->ext_region->ext_phys, + vm->ext_region->ext_size, vmid, ret); + } return ret; } @@ -488,6 +512,11 @@ int gh_provide_mem(struct gh_vm *vm, phys_addr_t phys, sgl_desc->sgl_entries[0].ipa_base = phys; sgl_desc->sgl_entries[0].size = size; + if (vm->ext_region_supported) { + destVMperm[0] = PERM_READ; + acl_desc->acl_entries[0].perms = GH_RM_ACL_R; + } + ret = hyp_assign_phys(phys, size, srcVM, 1, destVM, destVMperm, 1); if (ret) { pr_err("failed hyp_assign for %pa address of size %zx - subsys VMid %d rc:%d\n", @@ -502,12 +531,18 @@ int gh_provide_mem(struct gh_vm *vm, phys_addr_t phys, * Whereas any memory lent to a non system VM, can be reclaimed * when VM terminates. */ - if (is_system_vm) + if (is_system_vm) { ret = gh_rm_mem_donate(GH_RM_MEM_TYPE_NORMAL, 0, 0, acl_desc, sgl_desc, NULL, &vm->mem_handle); - else - ret = gh_rm_mem_lend(GH_RM_MEM_TYPE_NORMAL, 0, 0, acl_desc, - sgl_desc, NULL, &vm->mem_handle); + } else { + if (vm->ext_region_supported) + ret = gh_rm_mem_lend(GH_RM_MEM_TYPE_NORMAL, 0, + vm->ext_region->ext_label, acl_desc, + sgl_desc, NULL, &vm->ext_region->ext_mem_handle); + else + ret = gh_rm_mem_lend(GH_RM_MEM_TYPE_NORMAL, 0, 0, acl_desc, + sgl_desc, NULL, &vm->mem_handle); + } if (ret) ret = hyp_assign_phys(phys, size, destVM, 1, @@ -633,7 +668,8 @@ static int gh_vm_release(struct inode *inode, struct file *filp) { struct gh_vm *vm = filp->private_data; - gh_put_vm(vm); + if (!vm->keep_running) + gh_put_vm(vm); return 0; } @@ -647,12 +683,18 @@ static const struct file_operations gh_vm_fops = { static struct gh_vm *gh_create_vm(void) { struct gh_vm *vm; + struct gh_ext_reg *ext_region; int ret; vm = kzalloc(sizeof(*vm), GFP_KERNEL); if (!vm) return ERR_PTR(-ENOMEM); + ext_region = kzalloc(sizeof(*ext_region), GFP_KERNEL); + if (!ext_region) + return ERR_PTR(-ENOMEM); + vm->ext_region = ext_region; + mutex_init(&vm->vm_lock); vm->rm_nb.priority = 1; vm->rm_nb.notifier_call = gh_vm_rm_notifier_fn; diff --git a/drivers/virt/gunyah/gh_private.h b/drivers/virt/gunyah/gh_private.h index 05d8e9f81e65..60cd700b5aa1 100644 --- a/drivers/virt/gunyah/gh_private.h +++ b/drivers/virt/gunyah/gh_private.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. + * Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved. */ #ifndef _GH_PRIVATE_H @@ -21,9 +21,17 @@ struct gh_vcpu { struct gh_vm *vm; }; +struct gh_ext_reg { + u32 ext_label; + phys_addr_t ext_phys; + ssize_t ext_size; + gh_memparcel_handle_t ext_mem_handle; +}; + struct gh_vm { bool is_secure_vm; /* is true for Qcom authenticated secure VMs */ bool vm_run_once; + bool keep_running; u32 created_vcpus; u32 allowed_vcpus; gh_vmid_t vmid; @@ -35,6 +43,8 @@ struct gh_vm { int exit_type; refcount_t users_count; gh_memparcel_handle_t mem_handle; + struct gh_ext_reg *ext_region; + bool ext_region_supported; struct mutex vm_lock; }; diff --git a/drivers/virt/gunyah/gh_proxy_sched.c b/drivers/virt/gunyah/gh_proxy_sched.c index 7c90533dda34..182396eacbe2 100644 --- a/drivers/virt/gunyah/gh_proxy_sched.c +++ b/drivers/virt/gunyah/gh_proxy_sched.c @@ -14,7 +14,7 @@ * This driver is based on idea from Hafnium Hypervisor Linux Driver, * but modified to work with Gunyah Hypervisor as needed. * - * Copyright (c) 2021-2022, Qualcomm Innovation Center, Inc. All rights reserved. + * Copyright (c) 2021-2023, Qualcomm Innovation Center, Inc. All rights reserved. */ #define pr_fmt(fmt) "gh_proxy_sched: " fmt @@ -34,6 +34,8 @@ #include #include #include +#include +#include #include #include @@ -73,6 +75,9 @@ struct gh_proxy_vcpu { char ws_name[32]; wait_queue_head_t wait_queue; struct wakeup_source *ws; + bool workqueue_mode; + struct work_struct work; + struct notifier_block suspend_nb; }; struct gh_proxy_vm { @@ -86,6 +91,7 @@ struct gh_proxy_vm { gh_capid_t vpmg_cap_id; int susp_res_irq; bool is_vpm_group_info_populated; + struct workqueue_struct *vcpu_wq; }; static struct gh_proxy_vm *gh_vms; @@ -211,14 +217,19 @@ static void gh_init_vms(void) static irqreturn_t gh_vcpu_irq_handler(int irq, void *data) { struct gh_proxy_vcpu *vcpu; + struct gh_proxy_vm *vm; spin_lock(&gh_vm_lock); vcpu = data; + vm = vcpu->vm; if (!vcpu || !vcpu->vm || !vcpu->vm->is_vcpu_info_populated) goto unlock; trace_gh_vcpu_irq_handler(vcpu->vm->id, vcpu->idx); - gh_vcpu_wake_up(vcpu); + if (vcpu->workqueue_mode) + queue_work(vm->vcpu_wq, &vcpu->work); + else + gh_vcpu_wake_up(vcpu); unlock: spin_unlock(&gh_vm_lock); @@ -508,6 +519,7 @@ out: static void gh_populate_all_res_info(gh_vmid_t vmid, bool res_populated) { struct gh_proxy_vm *vm; + char workqueue_name[24]; if (!init_done) { pr_err("%s: Driver probe failed\n", __func__); @@ -531,6 +543,9 @@ static void gh_populate_all_res_info(gh_vmid_t vmid, bool res_populated) if (res_populated && !vm->is_vcpu_info_populated) { gh_init_wait_queues(vm); + snprintf(workqueue_name, sizeof(workqueue_name), "vm%d_vcpu_wq", + vm->id); + vm->vcpu_wq = create_freezable_workqueue(workqueue_name); nr_vms++; vm->is_vcpu_info_populated = true; vm->is_active = true; @@ -581,6 +596,107 @@ bool gh_vm_supports_proxy_sched(gh_vmid_t vmid) return false; } +void gh_vcpu_work_function(struct work_struct *work) +{ + struct gh_proxy_vcpu *vcpu = + container_of(work, struct gh_proxy_vcpu, work); + struct gh_proxy_vm *vm = vcpu->vm; + uint64_t resume_data_0 = 0, resume_data_1 = 0, resume_data_2 = 0; + struct gh_hcall_vcpu_run_resp resp; + ktime_t start_ts, yield_ts; + int ret; + + vcpu->abort_sleep = false; + __pm_stay_awake(vcpu->ws); + start_ts = ktime_get(); + preempt_disable(); + if (vcpu->wdog_frozen) { + gh_hcall_wdog_manage(vm->wdog_cap_id, + WATCHDOG_MANAGE_OP_UNFREEZE); + vcpu->wdog_frozen = false; + } + ret = gh_hcall_vcpu_run(vcpu->cap_id, resume_data_0, + resume_data_1, resume_data_2, &resp); + if (ret == GH_ERROR_OK && resp.vcpu_state == GH_VCPU_STATE_READY) { + gh_hcall_wdog_manage(vm->wdog_cap_id, + WATCHDOG_MANAGE_OP_FREEZE); + vcpu->wdog_frozen = true; + } + preempt_enable(); + yield_ts = ktime_get() - start_ts; + trace_gh_hcall_vcpu_run(ret, vcpu->vm->id, vcpu->idx, yield_ts, + resp.vcpu_state, + resp.vcpu_suspend_state); + if (ret == GH_ERROR_OK) { + switch (resp.vcpu_state) { + /* VCPU is preempted by PVM interrupt. */ + case GH_VCPU_STATE_READY: + queue_work(vm->vcpu_wq, &vcpu->work); + break; + + /* VCPU in WFI or suspended/powered down. */ + case GH_VCPU_STATE_EXPECTS_WAKEUP: + case GH_VCPU_STATE_POWERED_OFF: + __pm_relax(vcpu->ws); + /* once cpu is powered off, the work is done */ + if (!vcpu->abort_sleep) + return; + break; + + /* VCPU is blocked in EL2 for an unspecified reason */ + case GH_VCPU_STATE_BLOCKED: + queue_work(vm->vcpu_wq, &vcpu->work); + break; + } + } +} + +int gh_vcpu_pm_notifier_call(struct notifier_block *nb, unsigned long action, + void *data) +{ + struct gh_proxy_vcpu *vcpu = + container_of(nb, struct gh_proxy_vcpu, suspend_nb); + struct gh_proxy_vm *vm = vcpu->vm; + + if (action == PM_SUSPEND_PREPARE) { + if (!vcpu->wdog_frozen) { + gh_hcall_wdog_manage(vm->wdog_cap_id, + WATCHDOG_MANAGE_OP_FREEZE); + vcpu->wdog_frozen = true; + } + } else if (action == PM_POST_SUSPEND) { + queue_work(vm->vcpu_wq, &vcpu->work); + } + + return NOTIFY_OK; +} + +int gh_vcpu_create_wq(gh_vmid_t vmid, unsigned int vcpu_id) +{ + struct gh_proxy_vm *vm; + struct gh_proxy_vcpu *vcpu; + + vm = gh_get_vm(vmid); + if (!vm || !vm->is_active) + return -EINVAL; + if (vm->vcpu[vcpu_id].cap_id == GH_CAPID_INVAL) + return -EINVAL; + + vcpu = &vm->vcpu[vcpu_id]; + + INIT_WORK(&vcpu->work, gh_vcpu_work_function); + vcpu->workqueue_mode = true; + + vcpu->suspend_nb.notifier_call = gh_vcpu_pm_notifier_call; + register_pm_notifier(&vcpu->suspend_nb); + + /* schedule once incase we miss any interrupt */ + schedule_work(&vcpu->work); + queue_work(vm->vcpu_wq, &vcpu->work); + + return 0; +} + int gh_vcpu_run(gh_vmid_t vmid, unsigned int vcpu_id, uint64_t resume_data_0, uint64_t resume_data_1, uint64_t resume_data_2, struct gh_hcall_vcpu_run_resp *resp) { diff --git a/drivers/virt/gunyah/gh_proxy_sched.h b/drivers/virt/gunyah/gh_proxy_sched.h index d7517f1f701a..538645c4ae94 100644 --- a/drivers/virt/gunyah/gh_proxy_sched.h +++ b/drivers/virt/gunyah/gh_proxy_sched.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2021-2022, Qualcomm Innovation Center, Inc. All rights reserved. + * Copyright (c) 2021-2023, Qualcomm Innovation Center, Inc. All rights reserved. */ #ifndef __GH_PROXY_SCHED_H #define __GH_PROXY_SCHED_H @@ -82,6 +82,8 @@ int gh_get_nr_vcpus(gh_vmid_t vmid); bool gh_vm_supports_proxy_sched(gh_vmid_t vmid); +int gh_vcpu_create_wq(gh_vmid_t vmid, unsigned int vcpu_id); + int gh_vcpu_run(gh_vmid_t vmid, unsigned int vcpu_id, uint64_t resume_data_0, uint64_t resume_data_1, uint64_t resume_data_2, struct gh_hcall_vcpu_run_resp *resp); @@ -110,6 +112,11 @@ static inline int gh_vcpu_run(gh_vmid_t vmid, unsigned int vcpu_id, return -EPERM; } +int gh_vcpu_create_wq(gh_vmid_t vmid, unsigned int vcpu_id) +{ + return -EPERM; +} + static inline void gh_wakeup_all_vcpus(gh_vmid_t vmid) { } static inline void gh_proxy_sched_exit(void) { } diff --git a/drivers/virt/gunyah/gh_secure_vm_loader.c b/drivers/virt/gunyah/gh_secure_vm_loader.c index 94fe0575540a..fb3f62da87c3 100644 --- a/drivers/virt/gunyah/gh_secure_vm_loader.c +++ b/drivers/virt/gunyah/gh_secure_vm_loader.c @@ -27,14 +27,23 @@ #define PAGE_ROUND_UP(x) ((((u64)(x) + (PAGE_SIZE - 1)) / PAGE_SIZE) * PAGE_SIZE) +struct gh_sec_ext_region { + phys_addr_t ext_phys; + ssize_t ext_size; + u32 ext_label; +}; + struct gh_sec_vm_dev { struct list_head list; const char *vm_name; struct device *dev; bool system_vm; + bool keep_running; phys_addr_t fw_phys; void *fw_virt; ssize_t fw_size; + struct gh_sec_ext_region *ext_region; + bool ext_region_supported; int pas_id; int vmid; bool is_static; @@ -200,12 +209,30 @@ static int gh_vm_loader_sec_load(struct gh_sec_vm_dev *vm_dev, ret = gh_provide_mem(vm, vm_dev->fw_phys, vm_dev->fw_size, vm_dev->system_vm); + vm->keep_running = vm_dev->keep_running; + if (ret) { dev_err(dev, "Failed to provide memory for %s, %d\n", vm_dev->vm_name, ret); goto release_fw; } + if (vm_dev->ext_region_supported) { + vm->ext_region_supported = vm_dev->ext_region_supported; + vm->ext_region->ext_label = vm_dev->ext_region->ext_label; + vm->ext_region->ext_phys = vm_dev->ext_region->ext_phys; + vm->ext_region->ext_size = vm_dev->ext_region->ext_size; + + ret = gh_provide_mem(vm, vm_dev->ext_region->ext_phys, + vm_dev->ext_region->ext_size, + vm_dev->system_vm); + if (ret) { + dev_err(dev, "Failed to provide memory for ext-region to vm: %s, %d\n", + vm_dev->vm_name, ret); + goto release_fw; + } + } + vm->is_secure_vm = true; ret = gh_vm_configure(GH_VM_AUTH_PIL_ELF, metadata_offset, @@ -280,6 +307,7 @@ long gh_vm_ioctl_set_fw_name(struct gh_vm *vm, unsigned long arg) if (copy_from_user(&vm_fw_name, (void __user *)arg, sizeof(vm_fw_name))) return -EFAULT; + vm_fw_name.name[GH_VM_FW_NAME_MAX - 1] = '\0'; mutex_lock(&vm->vm_lock); if (strlen(vm->fw_name)) { pr_err("Secure VM %s already loaded %ld\n", @@ -421,6 +449,28 @@ static int gh_vm_loader_mem_probe(struct gh_sec_vm_dev *sec_vm_dev) sec_vm_dev->fw_size = size; } + node = of_parse_phandle(dev->of_node, "ext-region", 0); + if (node) { + sec_vm_dev->ext_region_supported = true; + ret = of_address_to_resource(node, 0, &res); + if (ret) { + dev_err(dev, "error %d getting \"ext-region\" resource\n", + ret); + goto err_of_node_put; + } + + + sec_vm_dev->ext_region->ext_phys = res.start; + sec_vm_dev->ext_region->ext_size = (size_t)resource_size(&res); + ret = of_property_read_u32(dev->of_node, "ext-label", + &sec_vm_dev->ext_region->ext_label); + if (ret) { + dev_err(dev, "DT error getting \"ext-label\": %d\n", ret); + goto err_of_node_put; + } + + } + err_of_node_put: of_node_put(node); return ret; @@ -429,6 +479,7 @@ err_of_node_put: static int gh_secure_vm_loader_probe(struct platform_device *pdev) { struct gh_sec_vm_dev *sec_vm_dev; + struct gh_sec_ext_region *ext_region; struct device *dev = &pdev->dev; enum gh_vm_names vm_name; int ret; @@ -437,6 +488,11 @@ static int gh_secure_vm_loader_probe(struct platform_device *pdev) if (!sec_vm_dev) return -ENOMEM; + ext_region = devm_kzalloc(dev, sizeof(*ext_region), GFP_KERNEL); + if (!ext_region) + return -ENOMEM; + sec_vm_dev->ext_region = ext_region; + sec_vm_dev->dev = dev; platform_set_drvdata(pdev, sec_vm_dev); @@ -451,6 +507,10 @@ static int gh_secure_vm_loader_probe(struct platform_device *pdev) if (sec_vm_dev->system_vm) dev_info(dev, "Vm with no shutdown attribute added\n"); + sec_vm_dev->keep_running = + of_property_read_bool(dev->of_node, "qcom,keep-running"); + if (sec_vm_dev->keep_running) + dev_info(dev, "VM with keep running attribute added\n"); ret = of_property_read_u32(dev->of_node, "qcom,vmid", &sec_vm_dev->vmid); diff --git a/drivers/w1/slaves/w1_therm.c b/drivers/w1/slaves/w1_therm.c index 9cbeeb4923ec..67d1cfbbb5f7 100644 --- a/drivers/w1/slaves/w1_therm.c +++ b/drivers/w1/slaves/w1_therm.c @@ -1093,29 +1093,26 @@ static int convert_t(struct w1_slave *sl, struct therm_info *info) w1_write_8(dev_master, W1_CONVERT_TEMP); - if (strong_pullup) { /*some device need pullup */ + if (SLAVE_FEATURES(sl) & W1_THERM_POLL_COMPLETION) { + ret = w1_poll_completion(dev_master, W1_POLL_CONVERT_TEMP); + if (ret) { + dev_dbg(&sl->dev, "%s: Timeout\n", __func__); + goto mt_unlock; + } + mutex_unlock(&dev_master->bus_mutex); + } else if (!strong_pullup) { /*no device need pullup */ sleep_rem = msleep_interruptible(t_conv); if (sleep_rem != 0) { ret = -EINTR; goto mt_unlock; } mutex_unlock(&dev_master->bus_mutex); - } else { /*no device need pullup */ - if (SLAVE_FEATURES(sl) & W1_THERM_POLL_COMPLETION) { - ret = w1_poll_completion(dev_master, W1_POLL_CONVERT_TEMP); - if (ret) { - dev_dbg(&sl->dev, "%s: Timeout\n", __func__); - goto mt_unlock; - } - mutex_unlock(&dev_master->bus_mutex); - } else { - /* Fixed delay */ - mutex_unlock(&dev_master->bus_mutex); - sleep_rem = msleep_interruptible(t_conv); - if (sleep_rem != 0) { - ret = -EINTR; - goto dec_refcnt; - } + } else { /*some device need pullup */ + mutex_unlock(&dev_master->bus_mutex); + sleep_rem = msleep_interruptible(t_conv); + if (sleep_rem != 0) { + ret = -EINTR; + goto dec_refcnt; } } ret = read_scratchpad(sl, info); diff --git a/drivers/w1/w1.c b/drivers/w1/w1.c index 4a2ddf730a3a..2eee26b7fc4a 100644 --- a/drivers/w1/w1.c +++ b/drivers/w1/w1.c @@ -1263,10 +1263,10 @@ err_out_exit_init: static void __exit w1_fini(void) { - struct w1_master *dev; + struct w1_master *dev, *n; /* Set netlink removal messages and some cleanup */ - list_for_each_entry(dev, &w1_masters, w1_master_entry) + list_for_each_entry_safe(dev, n, &w1_masters, w1_master_entry) __w1_remove_master_device(dev); w1_fini_netlink(); diff --git a/files_gki_aarch64.txt b/files_gki_aarch64.txt index e50be9ddc1de..d2b1609e7dec 100644 --- a/files_gki_aarch64.txt +++ b/files_gki_aarch64.txt @@ -1,8 +1,7 @@ -arch/arm/vdso/vdsomunge.c arch/arm64/crypto/aes-ce-core.S arch/arm64/crypto/aes-ce-glue.c -arch/arm64/crypto/aes-ce-setkey.h arch/arm64/crypto/aes-ce.S +arch/arm64/crypto/aes-ce-setkey.h arch/arm64/crypto/aes-glue.c arch/arm64/crypto/aes-modes.S arch/arm64/crypto/chacha-neon-core.S @@ -10,22 +9,22 @@ arch/arm64/crypto/chacha-neon-glue.c arch/arm64/crypto/ghash-ce-core.S arch/arm64/crypto/ghash-ce-glue.c arch/arm64/crypto/poly1305-glue.c +arch/arm64/crypto/sha256-glue.c arch/arm64/crypto/sha2-ce-core.S arch/arm64/crypto/sha2-ce-glue.c -arch/arm64/crypto/sha256-glue.c arch/arm64/crypto/sha512-ce-core.S arch/arm64/crypto/sha512-ce-glue.c arch/arm64/crypto/sha512-glue.c arch/arm64/include/asm/acpi.h -arch/arm64/include/asm/alternative-macros.h arch/arm64/include/asm/alternative.h +arch/arm64/include/asm/alternative-macros.h arch/arm64/include/asm/arch_gicv3.h -arch/arm64/include/asm/arch_timer.h arch/arm64/include/asm/archrandom.h +arch/arm64/include/asm/arch_timer.h arch/arm64/include/asm/asm-bug.h arch/arm64/include/asm/asm-offsets.h -arch/arm64/include/asm/asm-uaccess.h arch/arm64/include/asm/asm_pointer_auth.h +arch/arm64/include/asm/asm-uaccess.h arch/arm64/include/asm/assembler.h arch/arm64/include/asm/atomic.h arch/arm64/include/asm/atomic_ll_sc.h @@ -36,17 +35,17 @@ arch/arm64/include/asm/bitrev.h arch/arm64/include/asm/boot.h arch/arm64/include/asm/brk-imm.h arch/arm64/include/asm/bug.h -arch/arm64/include/asm/cache.h arch/arm64/include/asm/cacheflush.h +arch/arm64/include/asm/cache.h arch/arm64/include/asm/checksum.h arch/arm64/include/asm/clocksource.h arch/arm64/include/asm/cmpxchg.h arch/arm64/include/asm/compat.h arch/arm64/include/asm/compiler.h -arch/arm64/include/asm/cpu.h -arch/arm64/include/asm/cpu_ops.h arch/arm64/include/asm/cpufeature.h +arch/arm64/include/asm/cpu.h arch/arm64/include/asm/cpuidle.h +arch/arm64/include/asm/cpu_ops.h arch/arm64/include/asm/cputype.h arch/arm64/include/asm/current.h arch/arm64/include/asm/daifflags.h @@ -68,15 +67,15 @@ arch/arm64/include/asm/futex.h arch/arm64/include/asm/hardirq.h arch/arm64/include/asm/hw_breakpoint.h arch/arm64/include/asm/hwcap.h -arch/arm64/include/asm/hyp_image.h arch/arm64/include/asm/hypervisor.h +arch/arm64/include/asm/hyp_image.h arch/arm64/include/asm/image.h arch/arm64/include/asm/insn-def.h arch/arm64/include/asm/insn.h arch/arm64/include/asm/io.h +arch/arm64/include/asm/irqflags.h arch/arm64/include/asm/irq.h arch/arm64/include/asm/irq_work.h -arch/arm64/include/asm/irqflags.h arch/arm64/include/asm/jump_label.h arch/arm64/include/asm/kasan.h arch/arm64/include/asm/kernel-pgtable.h @@ -102,13 +101,13 @@ arch/arm64/include/asm/lse.h arch/arm64/include/asm/mem_encrypt.h arch/arm64/include/asm/memory.h arch/arm64/include/asm/mman.h -arch/arm64/include/asm/mmu.h arch/arm64/include/asm/mmu_context.h +arch/arm64/include/asm/mmu.h arch/arm64/include/asm/module.h arch/arm64/include/asm/module.lds.h arch/arm64/include/asm/mte-def.h -arch/arm64/include/asm/mte-kasan.h arch/arm64/include/asm/mte.h +arch/arm64/include/asm/mte-kasan.h arch/arm64/include/asm/neon.h arch/arm64/include/asm/numa.h arch/arm64/include/asm/page-def.h @@ -119,15 +118,15 @@ arch/arm64/include/asm/pci.h arch/arm64/include/asm/percpu.h arch/arm64/include/asm/perf_event.h arch/arm64/include/asm/pgalloc.h +arch/arm64/include/asm/pgtable.h arch/arm64/include/asm/pgtable-hwdef.h arch/arm64/include/asm/pgtable-prot.h arch/arm64/include/asm/pgtable-types.h -arch/arm64/include/asm/pgtable.h arch/arm64/include/asm/pointer_auth.h arch/arm64/include/asm/preempt.h arch/arm64/include/asm/probes.h -arch/arm64/include/asm/proc-fns.h arch/arm64/include/asm/processor.h +arch/arm64/include/asm/proc-fns.h arch/arm64/include/asm/ptdump.h arch/arm64/include/asm/ptrace.h arch/arm64/include/asm/pvclock-abi.h @@ -139,8 +138,8 @@ arch/arm64/include/asm/sections.h arch/arm64/include/asm/set_memory.h arch/arm64/include/asm/setup.h arch/arm64/include/asm/shmparam.h -arch/arm64/include/asm/signal.h arch/arm64/include/asm/signal32.h +arch/arm64/include/asm/signal.h arch/arm64/include/asm/simd.h arch/arm64/include/asm/smp.h arch/arm64/include/asm/smp_plat.h @@ -161,20 +160,20 @@ arch/arm64/include/asm/sysreg.h arch/arm64/include/asm/system_misc.h arch/arm64/include/asm/thread_info.h arch/arm64/include/asm/timex.h -arch/arm64/include/asm/tlb.h arch/arm64/include/asm/tlbflush.h +arch/arm64/include/asm/tlb.h arch/arm64/include/asm/topology.h arch/arm64/include/asm/trans_pgd.h arch/arm64/include/asm/traps.h arch/arm64/include/asm/uaccess.h -arch/arm64/include/asm/unistd.h arch/arm64/include/asm/unistd32.h +arch/arm64/include/asm/unistd.h arch/arm64/include/asm/uprobes.h -arch/arm64/include/asm/vdso.h arch/arm64/include/asm/vdso/clocksource.h arch/arm64/include/asm/vdso/compat_barrier.h arch/arm64/include/asm/vdso/compat_gettimeofday.h arch/arm64/include/asm/vdso/gettimeofday.h +arch/arm64/include/asm/vdso.h arch/arm64/include/asm/vdso/processor.h arch/arm64/include/asm/vdso/vsyscall.h arch/arm64/include/asm/vectors.h @@ -209,15 +208,15 @@ arch/arm64/kernel/armv8_deprecated.c arch/arm64/kernel/asm-offsets.c arch/arm64/kernel/cacheinfo.c arch/arm64/kernel/cpu_errata.c -arch/arm64/kernel/cpu_ops.c arch/arm64/kernel/cpufeature.c arch/arm64/kernel/cpuidle.c arch/arm64/kernel/cpuinfo.c +arch/arm64/kernel/cpu_ops.c arch/arm64/kernel/debug-monitors.c +arch/arm64/kernel/efi.c arch/arm64/kernel/efi-entry.S arch/arm64/kernel/efi-header.S arch/arm64/kernel/efi-rt-wrapper.S -arch/arm64/kernel/efi.c arch/arm64/kernel/elfcore.c arch/arm64/kernel/entry-common.c arch/arm64/kernel/entry-fpsimd.S @@ -230,15 +229,15 @@ arch/arm64/kernel/hw_breakpoint.c arch/arm64/kernel/hyp-stub.S arch/arm64/kernel/idle.c arch/arm64/kernel/idreg-override.c -arch/arm64/kernel/image-vars.h arch/arm64/kernel/image.h +arch/arm64/kernel/image-vars.h arch/arm64/kernel/io.c arch/arm64/kernel/irq.c arch/arm64/kernel/jump_label.c arch/arm64/kernel/kaslr.c arch/arm64/kernel/kuser32.S -arch/arm64/kernel/module-plts.c arch/arm64/kernel/module.c +arch/arm64/kernel/module-plts.c arch/arm64/kernel/mte.c arch/arm64/kernel/paravirt.c arch/arm64/kernel/patching.c @@ -260,8 +259,8 @@ arch/arm64/kernel/psci.c arch/arm64/kernel/ptrace.c arch/arm64/kernel/return_address.c arch/arm64/kernel/setup.c -arch/arm64/kernel/signal.c arch/arm64/kernel/signal32.c +arch/arm64/kernel/signal.c arch/arm64/kernel/sigreturn32.S arch/arm64/kernel/sleep.S arch/arm64/kernel/smccc-call.S @@ -269,24 +268,24 @@ arch/arm64/kernel/smp.c arch/arm64/kernel/smp_spin_table.c arch/arm64/kernel/stacktrace.c arch/arm64/kernel/suspend.c -arch/arm64/kernel/sys.c arch/arm64/kernel/sys32.c -arch/arm64/kernel/sys_compat.c +arch/arm64/kernel/sys.c arch/arm64/kernel/syscall.c +arch/arm64/kernel/sys_compat.c arch/arm64/kernel/time.c arch/arm64/kernel/topology.c arch/arm64/kernel/trace-events-emulation.h arch/arm64/kernel/traps.c -arch/arm64/kernel/vdso-wrap.S +arch/arm64/kernel/vdso32/note.c +arch/arm64/kernel/vdso32/vdso.lds.S +arch/arm64/kernel/vdso32/vgettimeofday.c +arch/arm64/kernel/vdso32-wrap.S arch/arm64/kernel/vdso.c arch/arm64/kernel/vdso/note.S arch/arm64/kernel/vdso/sigreturn.S arch/arm64/kernel/vdso/vdso.lds.S arch/arm64/kernel/vdso/vgettimeofday.c -arch/arm64/kernel/vdso32-wrap.S -arch/arm64/kernel/vdso32/note.c -arch/arm64/kernel/vdso32/vdso.lds.S -arch/arm64/kernel/vdso32/vgettimeofday.c +arch/arm64/kernel/vdso-wrap.S arch/arm64/kernel/vmlinux.lds.S arch/arm64/kvm/arch_timer.c arch/arm64/kvm/arm.c @@ -296,6 +295,7 @@ arch/arm64/kvm/guest.c arch/arm64/kvm/handle_exit.c arch/arm64/kvm/hyp/aarch32.c arch/arm64/kvm/hyp/entry.S +arch/arm64/kvm/hypercalls.c arch/arm64/kvm/hyp/exception.c arch/arm64/kvm/hyp/fpsimd.S arch/arm64/kvm/hyp/hyp-constants.c @@ -309,8 +309,8 @@ arch/arm64/kvm/hyp/include/nvhe/early_alloc.h arch/arm64/kvm/hyp/include/nvhe/ffa.h arch/arm64/kvm/hyp/include/nvhe/gfp.h arch/arm64/kvm/hyp/include/nvhe/iommu.h -arch/arm64/kvm/hyp/include/nvhe/mem_protect.h arch/arm64/kvm/hyp/include/nvhe/memory.h +arch/arm64/kvm/hyp/include/nvhe/mem_protect.h arch/arm64/kvm/hyp/include/nvhe/mm.h arch/arm64/kvm/hyp/include/nvhe/pkvm.h arch/arm64/kvm/hyp/include/nvhe/spinlock.h @@ -322,9 +322,9 @@ arch/arm64/kvm/hyp/nvhe/ffa.c arch/arm64/kvm/hyp/nvhe/gen-hyprel.c arch/arm64/kvm/hyp/nvhe/host.S arch/arm64/kvm/hyp/nvhe/hyp-init.S +arch/arm64/kvm/hyp/nvhe/hyp.lds.S arch/arm64/kvm/hyp/nvhe/hyp-main.c arch/arm64/kvm/hyp/nvhe/hyp-smp.c -arch/arm64/kvm/hyp/nvhe/hyp.lds.S arch/arm64/kvm/hyp/nvhe/iommu.c arch/arm64/kvm/hyp/nvhe/iommu/s2mpu.c arch/arm64/kvm/hyp/nvhe/mem_protect.c @@ -347,7 +347,6 @@ arch/arm64/kvm/hyp/vhe/switch.c arch/arm64/kvm/hyp/vhe/sysreg-sr.c arch/arm64/kvm/hyp/vhe/timer-sr.c arch/arm64/kvm/hyp/vhe/tlb.c -arch/arm64/kvm/hypercalls.c arch/arm64/kvm/inject_fault.c arch/arm64/kvm/iommu.c arch/arm64/kvm/iommu/s2mpu.c @@ -356,34 +355,34 @@ arch/arm64/kvm/mmio.c arch/arm64/kvm/mmu.c arch/arm64/kvm/perf.c arch/arm64/kvm/pkvm.c -arch/arm64/kvm/pmu-emul.c arch/arm64/kvm/pmu.c +arch/arm64/kvm/pmu-emul.c arch/arm64/kvm/psci.c arch/arm64/kvm/pvtime.c arch/arm64/kvm/reset.c arch/arm64/kvm/sys_regs.c arch/arm64/kvm/sys_regs.h -arch/arm64/kvm/trace.h arch/arm64/kvm/trace_arm.h +arch/arm64/kvm/trace.h arch/arm64/kvm/trace_handle_exit.h arch/arm64/kvm/trng.c arch/arm64/kvm/va_layout.c arch/arm64/kvm/vgic-sys-reg-v3.c arch/arm64/kvm/vgic/trace.h +arch/arm64/kvm/vgic/vgic.c arch/arm64/kvm/vgic/vgic-debug.c +arch/arm64/kvm/vgic/vgic.h arch/arm64/kvm/vgic/vgic-init.c arch/arm64/kvm/vgic/vgic-irqfd.c arch/arm64/kvm/vgic/vgic-its.c arch/arm64/kvm/vgic/vgic-kvm-device.c -arch/arm64/kvm/vgic/vgic-mmio-v2.c -arch/arm64/kvm/vgic/vgic-mmio-v3.c arch/arm64/kvm/vgic/vgic-mmio.c arch/arm64/kvm/vgic/vgic-mmio.h +arch/arm64/kvm/vgic/vgic-mmio-v2.c +arch/arm64/kvm/vgic/vgic-mmio-v3.c arch/arm64/kvm/vgic/vgic-v2.c arch/arm64/kvm/vgic/vgic-v3.c arch/arm64/kvm/vgic/vgic-v4.c -arch/arm64/kvm/vgic/vgic.c -arch/arm64/kvm/vgic/vgic.h arch/arm64/lib/clear_page.S arch/arm64/lib/clear_user.S arch/arm64/lib/copy_from_user.S @@ -425,8 +424,9 @@ arch/arm64/mm/pageattr.c arch/arm64/mm/pgd.c arch/arm64/mm/proc.S arch/arm64/mm/trans_pgd.c -arch/arm64/net/bpf_jit.h arch/arm64/net/bpf_jit_comp.c +arch/arm64/net/bpf_jit.h +arch/arm/vdso/vdsomunge.c block/badblocks.c block/bdev.c block/bfq-cgroup.c @@ -434,15 +434,16 @@ block/bfq-iosched.c block/bfq-iosched.h block/bfq-wf2q.c block/bio.c +block/blk-cgroup.c block/blk-cgroup-rwstat.c block/blk-cgroup-rwstat.h -block/blk-cgroup.c block/blk-core.c +block/blk-crypto.c block/blk-crypto-fallback.c block/blk-crypto-internal.h -block/blk-crypto.c block/blk-exec.c block/blk-flush.c +block/blk.h block/blk-ioc.c block/blk-iocost.c block/blk-ioprio.c @@ -450,9 +451,11 @@ block/blk-ioprio.h block/blk-lib.c block/blk-map.c block/blk-merge.c +block/blk-mq.c block/blk-mq-cpumap.c block/blk-mq-debugfs.c block/blk-mq-debugfs.h +block/blk-mq.h block/blk-mq-pci.c block/blk-mq-sched.c block/blk-mq-sched.h @@ -460,8 +463,6 @@ block/blk-mq-sysfs.c block/blk-mq-tag.c block/blk-mq-tag.h block/blk-mq-virtio.c -block/blk-mq.c -block/blk-mq.h block/blk-pm.c block/blk-pm.h block/blk-rq-qos.c @@ -472,9 +473,8 @@ block/blk-stat.h block/blk-sysfs.c block/blk-timeout.c block/blk-wbt.h -block/blk.h -block/bsg-lib.c block/bsg.c +block/bsg-lib.c block/disk-events.c block/elevator.c block/fops.c @@ -527,8 +527,8 @@ crypto/chacha_generic.c crypto/cipher.c crypto/cmac.c crypto/compress.c -crypto/crc32_generic.c crypto/crc32c_generic.c +crypto/crc32_generic.c crypto/crypto_engine.c crypto/crypto_null.c crypto/ctr.c @@ -538,8 +538,8 @@ crypto/des_generic.c crypto/drbg.c crypto/ecb.c crypto/ecc.c -crypto/ecc.h crypto/ecc_curve_defs.h +crypto/ecc.h crypto/ecdh.c crypto/ecdh_helper.c crypto/echainiv.c @@ -551,21 +551,21 @@ crypto/ghash-generic.c crypto/hash_info.c crypto/hmac.c crypto/internal.h -crypto/jitterentropy-kcapi.c crypto/jitterentropy.c crypto/jitterentropy.h +crypto/jitterentropy-kcapi.c crypto/kpp.c crypto/lz4.c -crypto/lzo-rle.c crypto/lzo.c +crypto/lzo-rle.c crypto/md5.c crypto/nhpoly1305.c crypto/poly1305_generic.c crypto/proc.c crypto/rng.c -crypto/rsa-pkcs1pad.c crypto/rsa.c crypto/rsa_helper.c +crypto/rsa-pkcs1pad.c crypto/scatterwalk.c crypto/scompress.c crypto/seqiv.c @@ -580,12 +580,12 @@ crypto/xts.c crypto/zstd.c drivers/amba/bus.c drivers/android/android_debug_symbols.c -drivers/android/binder.c drivers/android/binder_alloc.c drivers/android/binder_alloc.h +drivers/android/binder.c +drivers/android/binderfs.c drivers/android/binder_internal.h drivers/android/binder_trace.h -drivers/android/binderfs.c drivers/android/vendor_hooks.c drivers/base/arch_topology.c drivers/base/attribute_container.c @@ -613,8 +613,8 @@ drivers/base/map.c drivers/base/memory.c drivers/base/module.c drivers/base/pinctrl.c -drivers/base/platform-msi.c drivers/base/platform.c +drivers/base/platform-msi.c drivers/base/power/clock_ops.c drivers/base/power/common.c drivers/base/power/domain.c @@ -630,15 +630,15 @@ drivers/base/power/wakeup.c drivers/base/power/wakeup_stats.c drivers/base/property.c drivers/base/regmap/internal.h +drivers/base/regmap/regcache.c drivers/base/regmap/regcache-flat.c drivers/base/regmap/regcache-rbtree.c -drivers/base/regmap/regcache.c +drivers/base/regmap/regmap.c drivers/base/regmap/regmap-debugfs.c drivers/base/regmap/regmap-i2c.c drivers/base/regmap/regmap-irq.c drivers/base/regmap/regmap-mmio.c drivers/base/regmap/regmap-spi.c -drivers/base/regmap/regmap.c drivers/base/regmap/trace.h drivers/base/soc.c drivers/base/swnode.c @@ -676,8 +676,10 @@ drivers/char/mem.c drivers/char/misc.c drivers/char/random.c drivers/clk/clk-bulk.c +drivers/clk/clk.c drivers/clk/clk-composite.c drivers/clk/clk-conf.c +drivers/clk/clkdev.c drivers/clk/clk-devres.c drivers/clk/clk-divider.c drivers/clk/clk-fixed-factor.c @@ -686,27 +688,25 @@ drivers/clk/clk-fractional-divider.c drivers/clk/clk-fractional-divider.h drivers/clk/clk-gate.c drivers/clk/clk-gpio.c +drivers/clk/clk.h drivers/clk/clk-multiplier.c drivers/clk/clk-mux.c drivers/clk/clk-scpi.c -drivers/clk/clk.c -drivers/clk/clk.h -drivers/clk/clkdev.c -drivers/clk/hisilicon/clk-hi3519.c -drivers/clk/hisilicon/clk-hi3559a.c -drivers/clk/hisilicon/clk-hi3660-stub.c -drivers/clk/hisilicon/clk-hi3660.c -drivers/clk/hisilicon/clk-hi3670.c -drivers/clk/hisilicon/clk-hi6220-stub.c -drivers/clk/hisilicon/clk-hi6220.c -drivers/clk/hisilicon/clk-hisi-phase.c drivers/clk/hisilicon/clk.c -drivers/clk/hisilicon/clk.h drivers/clk/hisilicon/clkdivider-hi6220.c drivers/clk/hisilicon/clkgate-separated.c +drivers/clk/hisilicon/clk.h +drivers/clk/hisilicon/clk-hi3519.c +drivers/clk/hisilicon/clk-hi3559a.c +drivers/clk/hisilicon/clk-hi3660.c +drivers/clk/hisilicon/clk-hi3660-stub.c +drivers/clk/hisilicon/clk-hi3670.c +drivers/clk/hisilicon/clk-hi6220.c +drivers/clk/hisilicon/clk-hi6220-stub.c +drivers/clk/hisilicon/clk-hisi-phase.c +drivers/clk/hisilicon/crg.h drivers/clk/hisilicon/crg-hi3516cv300.c drivers/clk/hisilicon/crg-hi3798cv200.c -drivers/clk/hisilicon/crg.h drivers/clk/hisilicon/reset.c drivers/clk/hisilicon/reset.h drivers/clocksource/arm_arch_timer.c @@ -715,14 +715,14 @@ drivers/clocksource/mmio.c drivers/clocksource/timer-of.c drivers/clocksource/timer-of.h drivers/clocksource/timer-probe.c -drivers/clocksource/timer-sp.h drivers/clocksource/timer-sp804.c +drivers/clocksource/timer-sp.h drivers/clocksource/timer-sun4i.c drivers/cpufreq/cpufreq.c drivers/cpufreq/cpufreq_conservative.c +drivers/cpufreq/cpufreq_governor_attr_set.c drivers/cpufreq/cpufreq_governor.c drivers/cpufreq/cpufreq_governor.h -drivers/cpufreq/cpufreq_governor_attr_set.c drivers/cpufreq/cpufreq_performance.c drivers/cpufreq/cpufreq_powersave.c drivers/cpufreq/cpufreq_stats.c @@ -731,11 +731,11 @@ drivers/cpufreq/freq_table.c drivers/cpufreq/scmi-cpufreq.c drivers/cpufreq/scpi-cpufreq.c drivers/cpuidle/cpuidle-arm.c -drivers/cpuidle/cpuidle-psci-domain.c -drivers/cpuidle/cpuidle-psci.c -drivers/cpuidle/cpuidle-psci.h drivers/cpuidle/cpuidle.c drivers/cpuidle/cpuidle.h +drivers/cpuidle/cpuidle-psci.c +drivers/cpuidle/cpuidle-psci-domain.c +drivers/cpuidle/cpuidle-psci.h drivers/cpuidle/driver.c drivers/cpuidle/dt_idle_states.c drivers/cpuidle/dt_idle_states.h @@ -747,20 +747,20 @@ drivers/dax/bus.c drivers/dax/bus.h drivers/dax/dax-private.h drivers/dax/super.c -drivers/devfreq/devfreq-event.c drivers/devfreq/devfreq.c +drivers/devfreq/devfreq-event.c drivers/devfreq/governor.h drivers/devfreq/governor_passive.c drivers/devfreq/governor_performance.c drivers/devfreq/governor_powersave.c drivers/devfreq/governor_simpleondemand.c drivers/devfreq/governor_userspace.c +drivers/dma-buf/dma-buf.c drivers/dma-buf/dma-buf-sysfs-stats.c drivers/dma-buf/dma-buf-sysfs-stats.h -drivers/dma-buf/dma-buf.c drivers/dma-buf/dma-fence-array.c -drivers/dma-buf/dma-fence-chain.c drivers/dma-buf/dma-fence.c +drivers/dma-buf/dma-fence-chain.c drivers/dma-buf/dma-heap.c drivers/dma-buf/dma-resv.c drivers/dma-buf/heaps/deferred-free-helper.c @@ -808,23 +808,23 @@ drivers/firmware/arm_scmi/voltage.c drivers/firmware/arm_scpi.c drivers/firmware/efi/arm-runtime.c drivers/firmware/efi/earlycon.c +drivers/firmware/efi/efi.c drivers/firmware/efi/efi-init.c drivers/firmware/efi/efi-pstore.c -drivers/firmware/efi/efi.c drivers/firmware/efi/esrt.c drivers/firmware/efi/fdtparams.c drivers/firmware/efi/libstub/alignedmem.c drivers/firmware/efi/libstub/arm64-stub.c -drivers/firmware/efi/libstub/efi-stub-helper.c drivers/firmware/efi/libstub/efi-stub.c drivers/firmware/efi/libstub/efistub.h +drivers/firmware/efi/libstub/efi-stub-helper.c drivers/firmware/efi/libstub/fdt.c drivers/firmware/efi/libstub/file.c drivers/firmware/efi/libstub/gop.c drivers/firmware/efi/libstub/mem.c drivers/firmware/efi/libstub/pci.c -drivers/firmware/efi/libstub/random.c drivers/firmware/efi/libstub/randomalloc.c +drivers/firmware/efi/libstub/random.c drivers/firmware/efi/libstub/relocate.c drivers/firmware/efi/libstub/secureboot.c drivers/firmware/efi/libstub/skip_spaces.c @@ -844,18 +844,18 @@ drivers/firmware/smccc/smccc.c drivers/firmware/smccc/soc_id.c drivers/firmware/sysfb.c drivers/gnss/core.c -drivers/gpio/gpio-mmio.c -drivers/gpio/gpio-pl061.c drivers/gpio/gpiolib-acpi.h +drivers/gpio/gpiolib.c drivers/gpio/gpiolib-cdev.c drivers/gpio/gpiolib-cdev.h drivers/gpio/gpiolib-devres.c +drivers/gpio/gpiolib.h drivers/gpio/gpiolib-legacy.c drivers/gpio/gpiolib-of.c drivers/gpio/gpiolib-of.h drivers/gpio/gpiolib-sysfs.h -drivers/gpio/gpiolib.c -drivers/gpio/gpiolib.h +drivers/gpio/gpio-mmio.c +drivers/gpio/gpio-pl061.c drivers/gpu/drm/bridge/panel.c drivers/gpu/drm/drm_aperture.c drivers/gpu/drm/drm_atomic.c @@ -895,8 +895,8 @@ drivers/gpu/drm/drm_flip_work.c drivers/gpu/drm/drm_format_helper.c drivers/gpu/drm/drm_fourcc.c drivers/gpu/drm/drm_framebuffer.c -drivers/gpu/drm/drm_gem.c drivers/gpu/drm/drm_gem_atomic_helper.c +drivers/gpu/drm/drm_gem.c drivers/gpu/drm/drm_gem_cma_helper.c drivers/gpu/drm/drm_gem_framebuffer_helper.c drivers/gpu/drm/drm_gem_shmem_helper.c @@ -959,25 +959,27 @@ drivers/hid/hid-elecom.c drivers/hid/hid-generic.c drivers/hid/hid-ids.h drivers/hid/hid-input.c -drivers/hid/hid-lg-g15.c -drivers/hid/hid-lg.c -drivers/hid/hid-lg.h drivers/hid/hid-lg4ff.h +drivers/hid/hid-lg.c +drivers/hid/hid-lg-g15.c +drivers/hid/hid-lg.h drivers/hid/hid-logitech-dj.c drivers/hid/hid-logitech-hidpp.c drivers/hid/hid-magicmouse.c drivers/hid/hid-microsoft.c drivers/hid/hid-multitouch.c drivers/hid/hid-nintendo.c -drivers/hid/hid-picolcd.h drivers/hid/hid-picolcd_core.c drivers/hid/hid-picolcd_debugfs.c +drivers/hid/hid-picolcd.h drivers/hid/hid-plantronics.c drivers/hid/hid-playstation.c drivers/hid/hid-prodikeys.c drivers/hid/hid-quirks.c +drivers/hid/hidraw.c drivers/hid/hid-roccat-arvo.c drivers/hid/hid-roccat-arvo.h +drivers/hid/hid-roccat.c drivers/hid/hid-roccat-common.c drivers/hid/hid-roccat-common.h drivers/hid/hid-roccat-isku.c @@ -996,7 +998,6 @@ drivers/hid/hid-roccat-pyra.h drivers/hid/hid-roccat-ryos.c drivers/hid/hid-roccat-savu.c drivers/hid/hid-roccat-savu.h -drivers/hid/hid-roccat.c drivers/hid/hid-sony.c drivers/hid/hid-steam.c drivers/hid/hid-uclogic-core.c @@ -1006,9 +1007,8 @@ drivers/hid/hid-uclogic-rdesc.c drivers/hid/hid-uclogic-rdesc.h drivers/hid/hid-wiimote-core.c drivers/hid/hid-wiimote-debug.c -drivers/hid/hid-wiimote-modules.c drivers/hid/hid-wiimote.h -drivers/hid/hidraw.c +drivers/hid/hid-wiimote-modules.c drivers/hid/uhid.c drivers/hid/usbhid/hid-core.c drivers/hid/usbhid/hiddev.c @@ -1022,9 +1022,9 @@ drivers/hwspinlock/hwspinlock_internal.h drivers/i2c/algos/i2c-algo-bit.c drivers/i2c/i2c-boardinfo.c drivers/i2c/i2c-core-base.c +drivers/i2c/i2c-core.h drivers/i2c/i2c-core-of.c drivers/i2c/i2c-core-smbus.c -drivers/i2c/i2c-core.h drivers/i3c/device.c drivers/i3c/internals.h drivers/i3c/master.c @@ -1040,13 +1040,13 @@ drivers/iio/inkern.c drivers/input/evdev.c drivers/input/ff-core.c drivers/input/ff-memless.c +drivers/input/input.c drivers/input/input-compat.c drivers/input/input-compat.h drivers/input/input-leds.c drivers/input/input-mt.c drivers/input/input-poller.c drivers/input/input-poller.h -drivers/input/input.c drivers/input/joystick/xpad.c drivers/input/keyboard/atkbd.c drivers/input/keyboard/gpio_keys.c @@ -1060,37 +1060,37 @@ drivers/interconnect/core.c drivers/interconnect/internal.h drivers/interconnect/trace.h drivers/iommu/dma-iommu.c -drivers/iommu/io-pgtable-arm-v7s.c -drivers/iommu/io-pgtable-arm.c -drivers/iommu/io-pgtable-arm.h -drivers/iommu/io-pgtable.c +drivers/iommu/iommu.c drivers/iommu/iommu-sysfs.c drivers/iommu/iommu-traces.c -drivers/iommu/iommu.c +drivers/iommu/io-pgtable-arm.c +drivers/iommu/io-pgtable-arm.h +drivers/iommu/io-pgtable-arm-v7s.c +drivers/iommu/io-pgtable.c drivers/iommu/iova.c drivers/iommu/of_iommu.c +drivers/irqchip/irqchip.c +drivers/irqchip/irq-gic.c drivers/irqchip/irq-gic-common.c drivers/irqchip/irq-gic-common.h drivers/irqchip/irq-gic-v2m.c +drivers/irqchip/irq-gic-v3.c +drivers/irqchip/irq-gic-v3-its.c drivers/irqchip/irq-gic-v3-its-pci-msi.c drivers/irqchip/irq-gic-v3-its-platform-msi.c -drivers/irqchip/irq-gic-v3-its.c drivers/irqchip/irq-gic-v3-mbi.c -drivers/irqchip/irq-gic-v3.c drivers/irqchip/irq-gic-v4.c -drivers/irqchip/irq-gic.c drivers/irqchip/irq-mbigen.c drivers/irqchip/irq-partition-percpu.c drivers/irqchip/irq-sun4i.c drivers/irqchip/irq-sun6i-r.c drivers/irqchip/irq-sunxi-nmi.c -drivers/irqchip/irqchip.c +drivers/leds/led-class.c drivers/leds/led-class-flash.c drivers/leds/led-class-multicolor.c -drivers/leds/led-class.c drivers/leds/led-core.c -drivers/leds/led-triggers.c drivers/leds/leds.h +drivers/leds/led-triggers.c drivers/leds/trigger/ledtrig-timer.c drivers/leds/trigger/ledtrig-transient.c drivers/mailbox/hi3660-mailbox.c @@ -1101,11 +1101,13 @@ drivers/mailbox/sun6i-msgbox.c drivers/md/dm-bow.c drivers/md/dm-bufio.c drivers/md/dm-builtin.c +drivers/md/dm.c drivers/md/dm-core.h drivers/md/dm-crypt.c drivers/md/dm-default-key.c drivers/md/dm-exception-store.c drivers/md/dm-exception-store.h +drivers/md/dm.h drivers/md/dm-ima.h drivers/md/dm-init.c drivers/md/dm-io.c @@ -1114,9 +1116,9 @@ drivers/md/dm-kcopyd.c drivers/md/dm-linear.c drivers/md/dm-rq.c drivers/md/dm-rq.h +drivers/md/dm-snap.c drivers/md/dm-snap-persistent.c drivers/md/dm-snap-transient.c -drivers/md/dm-snap.c drivers/md/dm-stats.c drivers/md/dm-stats.h drivers/md/dm-stripe.c @@ -1128,17 +1130,15 @@ drivers/md/dm-uevent.h drivers/md/dm-user.c drivers/md/dm-verity-fec.c drivers/md/dm-verity-fec.h +drivers/md/dm-verity.h drivers/md/dm-verity-target.c drivers/md/dm-verity-verify-sig.h -drivers/md/dm-verity.h -drivers/md/dm.c -drivers/md/dm.h drivers/media/cec/core/cec-adap.c drivers/media/cec/core/cec-api.c drivers/media/cec/core/cec-core.c drivers/media/cec/core/cec-notifier.c -drivers/media/cec/core/cec-pin-priv.h drivers/media/cec/core/cec-pin.c +drivers/media/cec/core/cec-pin-priv.h drivers/media/cec/core/cec-priv.h drivers/media/common/videobuf2/frame_vector.c drivers/media/common/videobuf2/vb2-trace.c @@ -1222,23 +1222,23 @@ drivers/mmc/core/quirks.h drivers/mmc/core/regulator.c drivers/mmc/core/sd.c drivers/mmc/core/sd.h -drivers/mmc/core/sd_ops.c -drivers/mmc/core/sd_ops.h -drivers/mmc/core/sdio.c drivers/mmc/core/sdio_bus.c drivers/mmc/core/sdio_bus.h +drivers/mmc/core/sdio.c drivers/mmc/core/sdio_cis.c drivers/mmc/core/sdio_cis.h drivers/mmc/core/sdio_io.c drivers/mmc/core/sdio_irq.c drivers/mmc/core/sdio_ops.c drivers/mmc/core/sdio_ops.h +drivers/mmc/core/sd_ops.c +drivers/mmc/core/sd_ops.h drivers/mmc/core/slot-gpio.c drivers/mmc/core/slot-gpio.h -drivers/mmc/host/sdhci-pltfm.c -drivers/mmc/host/sdhci-pltfm.h drivers/mmc/host/sdhci.c drivers/mmc/host/sdhci.h +drivers/mmc/host/sdhci-pltfm.c +drivers/mmc/host/sdhci-pltfm.h drivers/net/can/dev/bittiming.c drivers/net/can/dev/dev.c drivers/net/can/dev/length.c @@ -1260,9 +1260,9 @@ drivers/net/phy/mdio-boardinfo.h drivers/net/phy/mdio_bus.c drivers/net/phy/mdio_device.c drivers/net/phy/mdio_devres.c +drivers/net/phy/phy.c drivers/net/phy/phy-c45.c drivers/net/phy/phy-core.c -drivers/net/phy/phy.c drivers/net/phy/phy_device.c drivers/net/phy/phylink.c drivers/net/phy/sfp.h @@ -1279,9 +1279,9 @@ drivers/net/slip/slhc.c drivers/net/tun.c drivers/net/usb/aqc111.c drivers/net/usb/aqc111.h -drivers/net/usb/asix.h drivers/net/usb/asix_common.c drivers/net/usb/asix_devices.c +drivers/net/usb/asix.h drivers/net/usb/ax88172a.c drivers/net/usb/ax88179_178a.c drivers/net/usb/cdc_eem.c @@ -1324,8 +1324,8 @@ drivers/net/wireguard/timers.h drivers/net/wireguard/version.h drivers/nvdimm/badrange.c drivers/nvdimm/btt.c -drivers/nvdimm/btt.h drivers/nvdimm/btt_devs.c +drivers/nvdimm/btt.h drivers/nvdimm/bus.c drivers/nvdimm/claim.c drivers/nvdimm/core.c @@ -1346,8 +1346,8 @@ drivers/nvmem/core.c drivers/of/address.c drivers/of/base.c drivers/of/device.c -drivers/of/fdt.c drivers/of/fdt_address.c +drivers/of/fdt.c drivers/of/irq.c drivers/of/kobj.c drivers/of/of_private.h @@ -1362,11 +1362,11 @@ drivers/opp/opp.h drivers/pci/access.c drivers/pci/ats.c drivers/pci/bus.c +drivers/pci/controller/dwc/pcie-designware.c drivers/pci/controller/dwc/pcie-designware-ep.c +drivers/pci/controller/dwc/pcie-designware.h drivers/pci/controller/dwc/pcie-designware-host.c drivers/pci/controller/dwc/pcie-designware-plat.c -drivers/pci/controller/dwc/pcie-designware.c -drivers/pci/controller/dwc/pcie-designware.h drivers/pci/controller/dwc/pcie-kirin.c drivers/pci/controller/dwc/pcie-qcom.c drivers/pci/controller/pci-host-common.c @@ -1381,18 +1381,18 @@ drivers/pci/irq.c drivers/pci/mmap.c drivers/pci/msi.c drivers/pci/of.c -drivers/pci/pci-driver.c -drivers/pci/pci-sysfs.c drivers/pci/pci.c -drivers/pci/pci.h +drivers/pci/pci-driver.c drivers/pci/pcie/aer.c drivers/pci/pcie/aspm.c drivers/pci/pcie/err.c drivers/pci/pcie/pme.c -drivers/pci/pcie/portdrv.h drivers/pci/pcie/portdrv_core.c +drivers/pci/pcie/portdrv.h drivers/pci/pcie/portdrv_pci.c drivers/pci/pcie/rcec.c +drivers/pci/pci.h +drivers/pci/pci-sysfs.c drivers/pci/probe.c drivers/pci/proc.c drivers/pci/quirks.c @@ -1408,33 +1408,33 @@ drivers/pci/vc.c drivers/pci/vpd.c drivers/perf/arm_pmu.c drivers/perf/arm_pmu_platform.c -drivers/phy/phy-core-mipi-dphy.c drivers/phy/phy-core.c +drivers/phy/phy-core-mipi-dphy.c drivers/pinctrl/core.c drivers/pinctrl/core.h drivers/pinctrl/devicetree.c drivers/pinctrl/devicetree.h -drivers/pinctrl/pinconf-generic.c drivers/pinctrl/pinconf.c +drivers/pinctrl/pinconf-generic.c drivers/pinctrl/pinconf.h drivers/pinctrl/pinctrl-single.c drivers/pinctrl/pinctrl-utils.c drivers/pinctrl/pinctrl-utils.h drivers/pinctrl/pinmux.c drivers/pinctrl/pinmux.h -drivers/pinctrl/sunxi/pinctrl-sun50i-a100-r.c drivers/pinctrl/sunxi/pinctrl-sun50i-a100.c -drivers/pinctrl/sunxi/pinctrl-sun50i-h616-r.c +drivers/pinctrl/sunxi/pinctrl-sun50i-a100-r.c drivers/pinctrl/sunxi/pinctrl-sun50i-h616.c +drivers/pinctrl/sunxi/pinctrl-sun50i-h616-r.c drivers/pinctrl/sunxi/pinctrl-sunxi.c drivers/pinctrl/sunxi/pinctrl-sunxi.h +drivers/powercap/powercap_sys.c drivers/power/reset/hisi-reboot.c drivers/power/reset/syscon-reboot.c -drivers/power/supply/power_supply.h drivers/power/supply/power_supply_core.c +drivers/power/supply/power_supply.h drivers/power/supply/power_supply_leds.c drivers/power/supply/power_supply_sysfs.c -drivers/powercap/powercap_sys.c drivers/pps/kapi.c drivers/pps/kc.h drivers/pps/pps.c @@ -1455,8 +1455,8 @@ drivers/regulator/core.c drivers/regulator/devres.c drivers/regulator/dummy.c drivers/regulator/dummy.h -drivers/regulator/fixed-helper.c drivers/regulator/fixed.c +drivers/regulator/fixed-helper.c drivers/regulator/helpers.c drivers/regulator/internal.h drivers/regulator/irq_helpers.c @@ -1491,8 +1491,9 @@ drivers/rtc/rtc-pl030.c drivers/rtc/rtc-pl031.c drivers/rtc/sysfs.c drivers/scsi/hosts.c -drivers/scsi/scsi.c drivers/scsi/scsi_bsg.c +drivers/scsi/scsi.c +drivers/scsi/scsicam.c drivers/scsi/scsi_common.c drivers/scsi/scsi_debugfs.c drivers/scsi/scsi_debugfs.h @@ -1510,44 +1511,43 @@ drivers/scsi/scsi_sysctl.c drivers/scsi/scsi_sysfs.c drivers/scsi/scsi_trace.c drivers/scsi/scsi_transport_api.h -drivers/scsi/scsicam.c drivers/scsi/sd.c drivers/scsi/sd.h -drivers/scsi/ufs/tc-dwc-g210-pltfrm.c drivers/scsi/ufs/tc-dwc-g210.c drivers/scsi/ufs/tc-dwc-g210.h +drivers/scsi/ufs/tc-dwc-g210-pltfrm.c +drivers/scsi/ufs/ufs_bsg.c +drivers/scsi/ufs/ufs_bsg.h drivers/scsi/ufs/ufs-debugfs.c drivers/scsi/ufs/ufs-debugfs.h drivers/scsi/ufs/ufs-fault-injection.h -drivers/scsi/ufs/ufs-hisi.c -drivers/scsi/ufs/ufs-hisi.h -drivers/scsi/ufs/ufs-sysfs.c -drivers/scsi/ufs/ufs-sysfs.h drivers/scsi/ufs/ufs.h -drivers/scsi/ufs/ufs_bsg.c -drivers/scsi/ufs/ufs_bsg.h -drivers/scsi/ufs/ufs_quirks.h +drivers/scsi/ufs/ufshcd.c drivers/scsi/ufs/ufshcd-crypto.c drivers/scsi/ufs/ufshcd-crypto.h drivers/scsi/ufs/ufshcd-dwc.c drivers/scsi/ufs/ufshcd-dwc.h +drivers/scsi/ufs/ufshcd.h drivers/scsi/ufs/ufshcd-pci.c drivers/scsi/ufs/ufshcd-pltfrm.c drivers/scsi/ufs/ufshcd-pltfrm.h -drivers/scsi/ufs/ufshcd.c -drivers/scsi/ufs/ufshcd.h drivers/scsi/ufs/ufshci-dwc.h drivers/scsi/ufs/ufshci.h +drivers/scsi/ufs/ufs-hisi.c +drivers/scsi/ufs/ufs-hisi.h drivers/scsi/ufs/ufshpb.c drivers/scsi/ufs/ufshpb.h +drivers/scsi/ufs/ufs_quirks.h +drivers/scsi/ufs/ufs-sysfs.c +drivers/scsi/ufs/ufs-sysfs.h drivers/scsi/ufs/unipro.h drivers/soc/qcom/qcom-geni-se.c drivers/soc/qcom/smem_state.c drivers/soc/sunxi/sunxi_mbus.c drivers/soc/sunxi/sunxi_sram.c drivers/spi/internals.h -drivers/spi/spi-mem.c drivers/spi/spi.c +drivers/spi/spi-mem.c drivers/spmi/spmi.c drivers/staging/android/ashmem.c drivers/staging/android/ashmem.h @@ -1576,7 +1576,6 @@ drivers/tty/n_tty.c drivers/tty/pty.c drivers/tty/serdev/core.c drivers/tty/serdev/serdev-ttyport.c -drivers/tty/serial/8250/8250.h drivers/tty/serial/8250/8250_core.c drivers/tty/serial/8250/8250_dma.c drivers/tty/serial/8250/8250_dw.c @@ -1584,6 +1583,7 @@ drivers/tty/serial/8250/8250_dwlib.c drivers/tty/serial/8250/8250_dwlib.h drivers/tty/serial/8250/8250_early.c drivers/tty/serial/8250/8250_fsl.c +drivers/tty/serial/8250/8250.h drivers/tty/serial/8250/8250_of.c drivers/tty/serial/8250/8250_pci.c drivers/tty/serial/8250/8250_port.c @@ -1597,10 +1597,10 @@ drivers/tty/serial/serial_mctrl_gpio.c drivers/tty/serial/serial_mctrl_gpio.h drivers/tty/serial/sprd_serial.c drivers/tty/sysrq.c -drivers/tty/tty.h drivers/tty/tty_audit.c drivers/tty/tty_baudrate.c drivers/tty/tty_buffer.c +drivers/tty/tty.h drivers/tty/tty_io.c drivers/tty/tty_ioctl.c drivers/tty/tty_jobctrl.c @@ -1622,8 +1622,8 @@ drivers/usb/core/driver.c drivers/usb/core/endpoint.c drivers/usb/core/file.c drivers/usb/core/generic.c -drivers/usb/core/hcd-pci.c drivers/usb/core/hcd.c +drivers/usb/core/hcd-pci.c drivers/usb/core/hub.c drivers/usb/core/hub.h drivers/usb/core/message.c @@ -1640,8 +1640,8 @@ drivers/usb/core/usb.c drivers/usb/core/usb.h drivers/usb/dwc3/core.c drivers/usb/dwc3/core.h -drivers/usb/dwc3/debug.h drivers/usb/dwc3/debugfs.c +drivers/usb/dwc3/debug.h drivers/usb/dwc3/drd.c drivers/usb/dwc3/dwc3-haps.c drivers/usb/dwc3/dwc3-of-simple.c @@ -1673,6 +1673,7 @@ drivers/usb/gadget/function/f_serial.c drivers/usb/gadget/function/f_uac2.c drivers/usb/gadget/function/f_uvc.c drivers/usb/gadget/function/f_uvc.h +drivers/usb/gadget/functions.c drivers/usb/gadget/function/storage_common.c drivers/usb/gadget/function/storage_common.h drivers/usb/gadget/function/u_audio.c @@ -1680,8 +1681,8 @@ drivers/usb/gadget/function/u_audio.h drivers/usb/gadget/function/u_ecm.h drivers/usb/gadget/function/u_eem.h drivers/usb/gadget/function/u_ether.c -drivers/usb/gadget/function/u_ether.h drivers/usb/gadget/function/u_ether_configfs.h +drivers/usb/gadget/function/u_ether.h drivers/usb/gadget/function/u_fs.h drivers/usb/gadget/function/u_hid.h drivers/usb/gadget/function/u_midi.h @@ -1690,24 +1691,24 @@ drivers/usb/gadget/function/u_serial.c drivers/usb/gadget/function/u_serial.h drivers/usb/gadget/function/u_uac2.h drivers/usb/gadget/function/u_uvc.h -drivers/usb/gadget/function/uvc.h drivers/usb/gadget/function/uvc_configfs.c drivers/usb/gadget/function/uvc_configfs.h +drivers/usb/gadget/function/uvc.h drivers/usb/gadget/function/uvc_queue.c drivers/usb/gadget/function/uvc_queue.h drivers/usb/gadget/function/uvc_v4l2.c drivers/usb/gadget/function/uvc_v4l2.h drivers/usb/gadget/function/uvc_video.c drivers/usb/gadget/function/uvc_video.h -drivers/usb/gadget/functions.c -drivers/usb/gadget/u_f.c -drivers/usb/gadget/u_f.h -drivers/usb/gadget/u_os_desc.h drivers/usb/gadget/udc/core.c drivers/usb/gadget/udc/trace.c drivers/usb/gadget/udc/trace.h +drivers/usb/gadget/u_f.c +drivers/usb/gadget/u_f.h +drivers/usb/gadget/u_os_desc.h drivers/usb/gadget/usbstring.c drivers/usb/host/ehci-dbg.c +drivers/usb/host/ehci.h drivers/usb/host/ehci-hcd.c drivers/usb/host/ehci-hub.c drivers/usb/host/ehci-mem.c @@ -1717,28 +1718,28 @@ drivers/usb/host/ehci-q.c drivers/usb/host/ehci-sched.c drivers/usb/host/ehci-sysfs.c drivers/usb/host/ehci-timer.c -drivers/usb/host/ehci.h drivers/usb/host/pci-quirks.c drivers/usb/host/pci-quirks.h +drivers/usb/host/xhci.c drivers/usb/host/xhci-dbg.c drivers/usb/host/xhci-dbgcap.h drivers/usb/host/xhci-debugfs.c drivers/usb/host/xhci-debugfs.h drivers/usb/host/xhci-ext-caps.c drivers/usb/host/xhci-ext-caps.h +drivers/usb/host/xhci.h drivers/usb/host/xhci-hub.c drivers/usb/host/xhci-mem.c drivers/usb/host/xhci-mvebu.h drivers/usb/host/xhci-pci.c drivers/usb/host/xhci-pci.h +drivers/usb/host/xhci-pci-renesas.c drivers/usb/host/xhci-plat.c drivers/usb/host/xhci-plat.h drivers/usb/host/xhci-rcar.h drivers/usb/host/xhci-ring.c drivers/usb/host/xhci-trace.c drivers/usb/host/xhci-trace.h -drivers/usb/host/xhci.c -drivers/usb/host/xhci.h drivers/usb/phy/of.c drivers/usb/phy/phy.c drivers/usb/roles/class.c @@ -1755,8 +1756,8 @@ drivers/usb/storage/sierra_ms.c drivers/usb/storage/sierra_ms.h drivers/usb/storage/transport.c drivers/usb/storage/transport.h -drivers/usb/storage/uas-detect.h drivers/usb/storage/uas.c +drivers/usb/storage/uas-detect.h drivers/usb/storage/unusual_alauda.h drivers/usb/storage/unusual_cypress.h drivers/usb/storage/unusual_datafab.h @@ -1836,13 +1837,13 @@ fs/crypto/keyring.c fs/crypto/keysetup.c fs/crypto/keysetup_v1.c fs/crypto/policy.c -fs/d_path.c fs/dcache.c fs/debugfs/file.c fs/debugfs/inode.c fs/debugfs/internal.h fs/devpts/inode.c fs/direct-io.c +fs/d_path.c fs/drop_caches.c fs/erofs/compress.h fs/erofs/data.c @@ -1885,8 +1886,8 @@ fs/ext4/balloc.c fs/ext4/bitmap.c fs/ext4/block_validity.c fs/ext4/dir.c -fs/ext4/ext4.h fs/ext4/ext4_extents.h +fs/ext4/ext4.h fs/ext4/ext4_jbd2.c fs/ext4/ext4_jbd2.h fs/ext4/extents.c @@ -1956,8 +1957,8 @@ fs/f2fs/xattr.c fs/f2fs/xattr.h fs/fat/cache.c fs/fat/dir.c -fs/fat/fat.h fs/fat/fatent.c +fs/fat/fat.h fs/fat/file.c fs/fat/inode.c fs/fat/misc.c @@ -1966,15 +1967,15 @@ fs/fat/namei_vfat.c fs/fat/nfs.c fs/fcntl.c fs/file.c -fs/file_table.c fs/filesystems.c -fs/fs-writeback.c +fs/file_table.c fs/fs_context.c +fs/fsopen.c fs/fs_parser.c fs/fs_pin.c fs/fs_struct.c fs/fs_types.c -fs/fsopen.c +fs/fs-writeback.c fs/fuse/acl.c fs/fuse/backing.c fs/fuse/control.c @@ -2073,10 +2074,10 @@ fs/nls/nls_cp936.c fs/nls/nls_cp949.c fs/nls/nls_cp950.c fs/nls/nls_euc-jp.c -fs/nls/nls_iso8859-1.c fs/nls/nls_iso8859-13.c fs/nls/nls_iso8859-14.c fs/nls/nls_iso8859-15.c +fs/nls/nls_iso8859-1.c fs/nls/nls_iso8859-2.c fs/nls/nls_iso8859-3.c fs/nls/nls_iso8859-4.c @@ -2093,8 +2094,8 @@ fs/notify/fdinfo.h fs/notify/fsnotify.c fs/notify/fsnotify.h fs/notify/group.c -fs/notify/inotify/inotify.h fs/notify/inotify/inotify_fsnotify.c +fs/notify/inotify/inotify.h fs/notify/inotify/inotify_user.c fs/notify/mark.c fs/notify/notification.c @@ -2131,6 +2132,7 @@ fs/proc/interrupts.c fs/proc/kmsg.c fs/proc/loadavg.c fs/proc/meminfo.c +fs/proc_namespace.c fs/proc/namespaces.c fs/proc/page.c fs/proc/proc_net.c @@ -2145,7 +2147,6 @@ fs/proc/thread_self.c fs/proc/uptime.c fs/proc/util.c fs/proc/version.c -fs/proc_namespace.c fs/pstore/inode.c fs/pstore/internal.h fs/pstore/platform.c @@ -2156,15 +2157,15 @@ fs/quota/compat.h fs/quota/dquot.c fs/quota/kqid.c fs/quota/quota.c +fs/quota/quotaio_v2.h fs/quota/quota_tree.c fs/quota/quota_tree.h fs/quota/quota_v2.c -fs/quota/quotaio_v2.h fs/ramfs/file-mmu.c fs/ramfs/inode.c fs/ramfs/internal.h -fs/read_write.c fs/readdir.c +fs/read_write.c fs/remap_range.c fs/select.c fs/seq_file.c @@ -2185,8 +2186,8 @@ fs/sysfs/sysfs.h fs/timerfd.c fs/tracefs/inode.c fs/unicode/utf8-core.c -fs/unicode/utf8-norm.c fs/unicode/utf8n.h +fs/unicode/utf8-norm.c fs/userfaultfd.c fs/utimes.c fs/verity/enable.c @@ -2209,20 +2210,20 @@ include/acpi/acpi_numa.h include/acpi/acpiosxf.h include/acpi/acpixf.h include/acpi/acrestyp.h -include/acpi/actbl.h include/acpi/actbl1.h include/acpi/actbl2.h include/acpi/actbl3.h +include/acpi/actbl.h include/acpi/actypes.h include/acpi/apei.h include/acpi/ghes.h include/acpi/hed.h -include/acpi/platform/acenv.h include/acpi/platform/acenvex.h -include/acpi/platform/acgcc.h +include/acpi/platform/acenv.h include/acpi/platform/acgccex.h -include/acpi/platform/aclinux.h +include/acpi/platform/acgcc.h include/acpi/platform/aclinuxex.h +include/acpi/platform/aclinux.h include/asm-generic/audit_change_attr.h include/asm-generic/audit_dir_write.h include/asm-generic/audit_read.h @@ -2232,8 +2233,8 @@ include/asm-generic/barrier.h include/asm-generic/bitops/arch_hweight.h include/asm-generic/bitops/atomic.h include/asm-generic/bitops/builtin-__ffs.h -include/asm-generic/bitops/builtin-__fls.h include/asm-generic/bitops/builtin-ffs.h +include/asm-generic/bitops/builtin-__fls.h include/asm-generic/bitops/builtin-fls.h include/asm-generic/bitops/const_hweight.h include/asm-generic/bitops/ext2-atomic-setbit.h @@ -2255,8 +2256,8 @@ include/asm-generic/checksum.h include/asm-generic/compat.h include/asm-generic/delay.h include/asm-generic/div64.h -include/asm-generic/dma-mapping.h include/asm-generic/dma.h +include/asm-generic/dma-mapping.h include/asm-generic/early_ioremap.h include/asm-generic/emergency-restart.h include/asm-generic/error-injection.h @@ -2267,16 +2268,16 @@ include/asm-generic/gpio.h include/asm-generic/hardirq.h include/asm-generic/hw_irq.h include/asm-generic/int-ll64.h -include/asm-generic/io.h include/asm-generic/ioctl.h +include/asm-generic/io.h include/asm-generic/irq.h include/asm-generic/irq_regs.h include/asm-generic/kdebug.h include/asm-generic/kmap_size.h include/asm-generic/kprobes.h include/asm-generic/kvm_para.h -include/asm-generic/local.h include/asm-generic/local64.h +include/asm-generic/local.h include/asm-generic/mcs_spinlock.h include/asm-generic/memory_model.h include/asm-generic/mm_hooks.h @@ -2328,8 +2329,8 @@ include/crypto/authenc.h include/crypto/b128ops.h include/crypto/blake2b.h include/crypto/blake2s.h -include/crypto/chacha.h include/crypto/chacha20poly1305.h +include/crypto/chacha.h include/crypto/ctr.h include/crypto/curve25519.h include/crypto/des.h @@ -2369,15 +2370,15 @@ include/crypto/poly1305.h include/crypto/public_key.h include/crypto/rng.h include/crypto/scatterwalk.h -include/crypto/sha1.h include/crypto/sha1_base.h -include/crypto/sha2.h +include/crypto/sha1.h include/crypto/sha256_base.h +include/crypto/sha2.h include/crypto/sha512_base.h include/crypto/skcipher.h include/crypto/sm2.h -include/crypto/sm3.h include/crypto/sm3_base.h +include/crypto/sm3.h include/crypto/streebog.h include/crypto/xts.h include/drm/drm_aperture.h @@ -2387,8 +2388,8 @@ include/drm/drm_atomic_state_helper.h include/drm/drm_atomic_uapi.h include/drm/drm_auth.h include/drm/drm_blend.h -include/drm/drm_bridge.h include/drm/drm_bridge_connector.h +include/drm/drm_bridge.h include/drm/drm_cache.h include/drm/drm_client.h include/drm/drm_color_mgmt.h @@ -2396,8 +2397,8 @@ include/drm/drm_connector.h include/drm/drm_crtc.h include/drm/drm_crtc_helper.h include/drm/drm_damage_helper.h -include/drm/drm_debugfs.h include/drm/drm_debugfs_crc.h +include/drm/drm_debugfs.h include/drm/drm_device.h include/drm/drm_displayid.h include/drm/drm_dp_dual_mode_helper.h @@ -2415,10 +2416,10 @@ include/drm/drm_flip_work.h include/drm/drm_format_helper.h include/drm/drm_fourcc.h include/drm/drm_framebuffer.h -include/drm/drm_gem.h include/drm/drm_gem_atomic_helper.h include/drm/drm_gem_cma_helper.h include/drm/drm_gem_framebuffer_helper.h +include/drm/drm_gem.h include/drm/drm_gem_shmem_helper.h include/drm/drm_hashtab.h include/drm/drm_hdcp.h @@ -2430,10 +2431,10 @@ include/drm/drm_mipi_dsi.h include/drm/drm_mm.h include/drm/drm_mode_config.h include/drm/drm_mode_object.h -include/drm/drm_modes.h include/drm/drm_modeset_helper.h include/drm/drm_modeset_helper_vtables.h include/drm/drm_modeset_lock.h +include/drm/drm_modes.h include/drm/drm_of.h include/drm/drm_panel.h include/drm/drm_plane.h @@ -2500,8 +2501,8 @@ include/kvm/arm_vgic.h include/kvm/iodev.h include/linux/8250_pci.h include/linux/acct.h -include/linux/acpi.h include/linux/acpi_dma.h +include/linux/acpi.h include/linux/acpi_iort.h include/linux/aer.h include/linux/agp_backend.h @@ -2515,19 +2516,19 @@ include/linux/android_kabi.h include/linux/android_vendor.h include/linux/anon_inodes.h include/linux/arch_topology.h -include/linux/arm-smccc.h include/linux/arm_ffa.h include/linux/arm_sdei.h -include/linux/asn1.h +include/linux/arm-smccc.h include/linux/asn1_ber_bytecode.h include/linux/asn1_decoder.h +include/linux/asn1.h include/linux/assoc_array.h include/linux/assoc_array_priv.h include/linux/async.h -include/linux/atomic.h include/linux/atomic/atomic-arch-fallback.h include/linux/atomic/atomic-instrumented.h include/linux/atomic/atomic-long.h +include/linux/atomic.h include/linux/attribute_container.h include/linux/audit.h include/linux/auxvec.h @@ -2540,47 +2541,47 @@ include/linux/balloon_compaction.h include/linux/bcd.h include/linux/binfmts.h include/linux/bio.h -include/linux/bit_spinlock.h include/linux/bitfield.h include/linux/bitmap.h include/linux/bitops.h include/linux/bitrev.h include/linux/bits.h +include/linux/bit_spinlock.h include/linux/blk-cgroup.h include/linux/blk-crypto.h +include/linux/blkdev.h +include/linux/blk-mq.h include/linux/blk-mq-pci.h include/linux/blk-mq-virtio.h -include/linux/blk-mq.h -include/linux/blk-pm.h -include/linux/blk_types.h -include/linux/blkdev.h include/linux/blkpg.h +include/linux/blk-pm.h include/linux/blktrace_api.h +include/linux/blk_types.h include/linux/blockgroup_lock.h include/linux/bootconfig.h include/linux/bootmem_info.h include/linux/bottom_half.h include/linux/bpf-cgroup.h -include/linux/bpf-netns.h include/linux/bpf.h +include/linux/bpfilter.h include/linux/bpf_lirc.h include/linux/bpf_local_storage.h include/linux/bpf_lsm.h +include/linux/bpf-netns.h +include/linux/bpfptr.h include/linux/bpf_trace.h include/linux/bpf_types.h include/linux/bpf_verifier.h -include/linux/bpfilter.h -include/linux/bpfptr.h include/linux/bsearch.h -include/linux/bsg-lib.h include/linux/bsg.h +include/linux/bsg-lib.h include/linux/btf.h include/linux/btf_ids.h include/linux/buffer_head.h include/linux/bug.h -include/linux/build-salt.h include/linux/build_bug.h include/linux/buildid.h +include/linux/build-salt.h include/linux/bvec.h include/linux/byteorder/generic.h include/linux/byteorder/little_endian.h @@ -2604,10 +2605,10 @@ include/linux/cgroup_rdma.h include/linux/cgroup_subsys.h include/linux/circ_buf.h include/linux/cleancache.h -include/linux/clk-provider.h -include/linux/clk.h include/linux/clk/clk-conf.h include/linux/clkdev.h +include/linux/clk.h +include/linux/clk-provider.h include/linux/clockchips.h include/linux/clocksource.h include/linux/clocksource_ids.h @@ -2615,17 +2616,17 @@ include/linux/cma.h include/linux/cn_proc.h include/linux/compaction.h include/linux/compat.h -include/linux/compiler-clang.h -include/linux/compiler-version.h -include/linux/compiler.h include/linux/compiler_attributes.h +include/linux/compiler-clang.h +include/linux/compiler.h include/linux/compiler_types.h +include/linux/compiler-version.h include/linux/completion.h include/linux/component.h include/linux/configfs.h include/linux/console.h -include/linux/console_struct.h include/linux/consolemap.h +include/linux/console_struct.h include/linux/const.h include/linux/container.h include/linux/context_tracking.h @@ -2634,25 +2635,25 @@ include/linux/cookie.h include/linux/coredump.h include/linux/count_zeros.h include/linux/cper.h -include/linux/cpu.h include/linux/cpu_cooling.h -include/linux/cpu_pm.h -include/linux/cpu_rmap.h include/linux/cpufeature.h include/linux/cpufreq.h include/linux/cpufreq_times.h +include/linux/cpu.h include/linux/cpuhotplug.h include/linux/cpuidle.h include/linux/cpumask.h +include/linux/cpu_pm.h +include/linux/cpu_rmap.h include/linux/cpuset.h include/linux/crash_core.h include/linux/crash_dump.h -include/linux/crc-ccitt.h include/linux/crc16.h -include/linux/crc32.h include/linux/crc32c.h +include/linux/crc32.h include/linux/crc32poly.h include/linux/crc8.h +include/linux/crc-ccitt.h include/linux/cred.h include/linux/crypto.h include/linux/ctype.h @@ -2660,8 +2661,8 @@ include/linux/damon.h include/linux/dax.h include/linux/dcache.h include/linux/dccp.h -include/linux/debug_locks.h include/linux/debugfs.h +include/linux/debug_locks.h include/linux/debugobjects.h include/linux/decompress/bunzip2.h include/linux/decompress/generic.h @@ -2672,30 +2673,28 @@ include/linux/decompress/unlzma.h include/linux/decompress/unlzo.h include/linux/decompress/unxz.h include/linux/decompress/unzstd.h -include/linux/delay.h include/linux/delayacct.h include/linux/delayed_call.h -include/linux/dev_printk.h +include/linux/delay.h include/linux/devcoredump.h +include/linux/devfreq_cooling.h include/linux/devfreq-event.h include/linux/devfreq.h -include/linux/devfreq_cooling.h -include/linux/device-mapper.h -include/linux/device.h include/linux/device/bus.h +include/linux/device_cgroup.h include/linux/device/class.h include/linux/device/driver.h -include/linux/device_cgroup.h +include/linux/device.h +include/linux/device-mapper.h +include/linux/dev_printk.h include/linux/devpts_fs.h include/linux/dim.h include/linux/dirent.h -include/linux/dm-bufio.h -include/linux/dm-io.h -include/linux/dm-kcopyd.h -include/linux/dma-buf-map.h include/linux/dma-buf.h +include/linux/dma-buf-map.h include/linux/dma-direct.h include/linux/dma-direction.h +include/linux/dmaengine.h include/linux/dma-fence-array.h include/linux/dma-fence-chain.h include/linux/dma-fence.h @@ -2703,11 +2702,13 @@ include/linux/dma-heap.h include/linux/dma-iommu.h include/linux/dma-map-ops.h include/linux/dma-mapping.h +include/linux/dmapool.h include/linux/dma-resv.h include/linux/dma/sprd-dma.h -include/linux/dmaengine.h -include/linux/dmapool.h +include/linux/dm-bufio.h include/linux/dmi.h +include/linux/dm-io.h +include/linux/dm-kcopyd.h include/linux/dnotify.h include/linux/dqblk_qtree.h include/linux/dqblk_v1.h @@ -2718,12 +2719,12 @@ include/linux/earlycpio.h include/linux/edac.h include/linux/efi.h include/linux/elevator.h -include/linux/elf-randomize.h -include/linux/elf.h include/linux/elfcore-compat.h include/linux/elfcore.h -include/linux/elfnote-lto.h +include/linux/elf.h include/linux/elfnote.h +include/linux/elfnote-lto.h +include/linux/elf-randomize.h include/linux/energy_model.h include/linux/entry-kvm.h include/linux/err.h @@ -2738,46 +2739,46 @@ include/linux/ethtool_netlink.h include/linux/eventfd.h include/linux/eventpoll.h include/linux/evm.h -include/linux/export.h include/linux/exportfs.h +include/linux/export.h include/linux/ext2_fs.h include/linux/extable.h -include/linux/extcon-provider.h include/linux/extcon.h +include/linux/extcon-provider.h include/linux/f2fs_fs.h include/linux/falloc.h include/linux/fanotify.h -include/linux/fault-inject-usercopy.h include/linux/fault-inject.h +include/linux/fault-inject-usercopy.h include/linux/fb.h include/linux/fcntl.h -include/linux/fd.h include/linux/fddidevice.h +include/linux/fd.h include/linux/fdtable.h include/linux/fiemap.h -include/linux/file.h include/linux/fileattr.h +include/linux/file.h include/linux/filter.h include/linux/fips.h -include/linux/firmware-map.h include/linux/firmware.h +include/linux/firmware-map.h include/linux/fixp-arith.h include/linux/flex_proportions.h include/linux/font.h include/linux/freelist.h include/linux/freezer.h include/linux/frontswap.h -include/linux/fs.h include/linux/fs_context.h +include/linux/fscrypt.h +include/linux/fs.h +include/linux/fsl/mc.h +include/linux/fsnotify_backend.h +include/linux/fsnotify.h include/linux/fs_parser.h include/linux/fs_pin.h include/linux/fs_stack.h include/linux/fs_struct.h include/linux/fs_types.h -include/linux/fscrypt.h -include/linux/fsl/mc.h -include/linux/fsnotify.h -include/linux/fsnotify_backend.h include/linux/fsverity.h include/linux/ftrace.h include/linux/ftrace_irq.h @@ -2793,37 +2794,37 @@ include/linux/getcpu.h include/linux/gfp.h include/linux/glob.h include/linux/gnss.h -include/linux/gpio.h include/linux/gpio/consumer.h include/linux/gpio/driver.h -include/linux/gpio/machine.h +include/linux/gpio.h include/linux/gpio_keys.h +include/linux/gpio/machine.h include/linux/hardirq.h include/linux/hash.h include/linux/hashtable.h include/linux/hdmi.h include/linux/hid-debug.h -include/linux/hid-roccat.h -include/linux/hid.h include/linux/hidden.h include/linux/hiddev.h +include/linux/hid.h include/linux/hidraw.h -include/linux/highmem-internal.h +include/linux/hid-roccat.h include/linux/highmem.h +include/linux/highmem-internal.h include/linux/highuid.h -include/linux/hrtimer.h include/linux/hrtimer_defs.h +include/linux/hrtimer.h include/linux/huge_mm.h -include/linux/hugetlb.h include/linux/hugetlb_cgroup.h +include/linux/hugetlb.h include/linux/hugetlb_inline.h include/linux/hw_breakpoint.h include/linux/hw_random.h include/linux/hwspinlock.h include/linux/hypervisor.h include/linux/i2c-algo-bit.h -include/linux/i2c-smbus.h include/linux/i2c.h +include/linux/i2c-smbus.h include/linux/i3c/ccc.h include/linux/i3c/device.h include/linux/i3c/master.h @@ -2851,79 +2852,79 @@ include/linux/iio/buffer_impl.h include/linux/iio/consumer.h include/linux/iio/driver.h include/linux/iio/events.h -include/linux/iio/iio-opaque.h include/linux/iio/iio.h +include/linux/iio/iio-opaque.h include/linux/iio/kfifo_buf.h include/linux/iio/machine.h include/linux/iio/sysfs.h -include/linux/iio/trigger.h include/linux/iio/trigger_consumer.h include/linux/iio/triggered_buffer.h +include/linux/iio/trigger.h include/linux/iio/types.h include/linux/ima.h -include/linux/in.h include/linux/in6.h include/linux/indirect_call_wrapper.h -include/linux/inet.h -include/linux/inet_diag.h include/linux/inetdevice.h +include/linux/inet_diag.h +include/linux/inet.h +include/linux/in.h include/linux/init.h +include/linux/initrd.h include/linux/init_syscalls.h include/linux/init_task.h -include/linux/initrd.h include/linux/inotify.h -include/linux/input.h include/linux/input/elan-i2c-ids.h +include/linux/input.h include/linux/input/mt.h include/linux/input/touchscreen.h include/linux/instrumentation.h include/linux/instrumented.h include/linux/integrity.h -include/linux/interconnect-provider.h include/linux/interconnect.h +include/linux/interconnect-provider.h include/linux/interrupt.h -include/linux/interval_tree.h include/linux/interval_tree_generic.h +include/linux/interval_tree.h include/linux/io-64-nonatomic-hi-lo.h include/linux/io-64-nonatomic-lo-hi.h -include/linux/io-mapping.h -include/linux/io-pgtable.h -include/linux/io.h -include/linux/io_uring.h -include/linux/ioam6.h include/linux/ioam6_genl.h +include/linux/ioam6.h include/linux/ioasid.h include/linux/iocontext.h +include/linux/io.h include/linux/iomap.h -include/linux/iommu-helper.h +include/linux/io-mapping.h include/linux/iommu.h +include/linux/iommu-helper.h +include/linux/io-pgtable.h include/linux/iopoll.h include/linux/ioport.h include/linux/ioprio.h +include/linux/io_uring.h include/linux/iova.h -include/linux/ip.h include/linux/ipc.h include/linux/ipc_namespace.h +include/linux/ip.h include/linux/ipv6.h include/linux/ipv6_route.h -include/linux/irq.h -include/linux/irq_poll.h -include/linux/irq_work.h include/linux/irqbypass.h -include/linux/irqchip.h include/linux/irqchip/arm-gic-common.h +include/linux/irqchip/arm-gic.h include/linux/irqchip/arm-gic-v3.h include/linux/irqchip/arm-gic-v4.h -include/linux/irqchip/arm-gic.h include/linux/irqchip/arm-vgic-info.h include/linux/irqchip/chained_irq.h +include/linux/irqchip.h include/linux/irqchip/irq-partition-percpu.h include/linux/irqdesc.h include/linux/irqdomain.h include/linux/irqflags.h +include/linux/irq.h include/linux/irqhandler.h include/linux/irqnr.h +include/linux/irq_poll.h include/linux/irqreturn.h +include/linux/irq_work.h include/linux/iversion.h include/linux/jbd2.h include/linux/jhash.h @@ -2934,8 +2935,8 @@ include/linux/jump_label_ratelimit.h include/linux/kallsyms.h include/linux/kasan-checks.h include/linux/kasan-enabled.h -include/linux/kasan-tags.h include/linux/kasan.h +include/linux/kasan-tags.h include/linux/kbd_kern.h include/linux/kbuild.h include/linux/kconfig.h @@ -2945,18 +2946,18 @@ include/linux/kcsan.h include/linux/kdb.h include/linux/kdebug.h include/linux/kdev_t.h -include/linux/kern_levels.h -include/linux/kernel-page-flags.h include/linux/kernel.h +include/linux/kernel-page-flags.h include/linux/kernel_read_file.h include/linux/kernel_stat.h include/linux/kernfs.h +include/linux/kern_levels.h include/linux/kexec.h -include/linux/key-type.h -include/linux/key.h include/linux/keyboard.h include/linux/keyctl.h +include/linux/key.h include/linux/keyslot-manager.h +include/linux/key-type.h include/linux/kfence.h include/linux/kfifo.h include/linux/kgdb.h @@ -2965,9 +2966,9 @@ include/linux/klist.h include/linux/kmemleak.h include/linux/kmod.h include/linux/kmsg_dump.h -include/linux/kobj_map.h include/linux/kobject.h include/linux/kobject_ns.h +include/linux/kobj_map.h include/linux/kprobes.h include/linux/kref.h include/linux/ksm.h @@ -2985,8 +2986,8 @@ include/linux/lcm.h include/linux/led-class-flash.h include/linux/led-class-multicolor.h include/linux/leds.h -include/linux/libfdt.h include/linux/libfdt_env.h +include/linux/libfdt.h include/linux/libnvdimm.h include/linux/libps2.h include/linux/license.h @@ -2994,8 +2995,8 @@ include/linux/limits.h include/linux/linear_range.h include/linux/linkage.h include/linux/linkmode.h -include/linux/list.h include/linux/list_bl.h +include/linux/list.h include/linux/list_lru.h include/linux/list_nulls.h include/linux/list_sort.h @@ -3016,13 +3017,13 @@ include/linux/lz4.h include/linux/lzo.h include/linux/mailbox_client.h include/linux/mailbox_controller.h -include/linux/math.h include/linux/math64.h +include/linux/math.h include/linux/mbcache.h include/linux/mdio.h -include/linux/mem_encrypt.h include/linux/memblock.h include/linux/memcontrol.h +include/linux/mem_encrypt.h include/linux/memfd.h include/linux/memory.h include/linux/memory_hotplug.h @@ -3039,10 +3040,6 @@ include/linux/mii_timestamper.h include/linux/min_heap.h include/linux/minmax.h include/linux/miscdevice.h -include/linux/mm.h -include/linux/mm_inline.h -include/linux/mm_types.h -include/linux/mm_types_task.h include/linux/mman.h include/linux/mmap_lock.h include/linux/mmc/card.h @@ -3051,12 +3048,16 @@ include/linux/mmc/host.h include/linux/mmc/mmc.h include/linux/mmc/pm.h include/linux/mmc/sd.h -include/linux/mmc/sdio.h include/linux/mmc/sdio_func.h +include/linux/mmc/sdio.h include/linux/mmc/sdio_ids.h include/linux/mmc/slot-gpio.h include/linux/mmdebug.h +include/linux/mm.h +include/linux/mm_inline.h include/linux/mmiotrace.h +include/linux/mm_types.h +include/linux/mm_types_task.h include/linux/mmu_context.h include/linux/mmu_notifier.h include/linux/mmzone.h @@ -3064,16 +3065,16 @@ include/linux/mnt_idmapping.h include/linux/mnt_namespace.h include/linux/mod_devicetable.h include/linux/module.h -include/linux/module_signature.h include/linux/moduleloader.h include/linux/moduleparam.h +include/linux/module_signature.h include/linux/mount.h include/linux/mpage.h include/linux/mpi.h include/linux/mpls.h -include/linux/mroute.h include/linux/mroute6.h include/linux/mroute_base.h +include/linux/mroute.h include/linux/msdos_fs.h include/linux/msdos_partition.h include/linux/msg.h @@ -3081,18 +3082,25 @@ include/linux/msi.h include/linux/mtd/mtd.h include/linux/mutex.h include/linux/namei.h -include/linux/nd.h include/linux/ndctl.h -include/linux/net.h +include/linux/nd.h include/linux/netdev_features.h include/linux/netdevice.h +include/linux/netfilter_arp/arp_tables.h +include/linux/netfilter_bridge.h +include/linux/netfilter_defs.h include/linux/netfilter.h +include/linux/netfilter_ingress.h +include/linux/netfilter_ipv4.h +include/linux/netfilter_ipv4/ip_tables.h +include/linux/netfilter_ipv6.h +include/linux/netfilter_ipv6/ip6_tables.h include/linux/netfilter/nf_conntrack_amanda.h include/linux/netfilter/nf_conntrack_common.h include/linux/netfilter/nf_conntrack_dccp.h include/linux/netfilter/nf_conntrack_ftp.h -include/linux/netfilter/nf_conntrack_h323.h include/linux/netfilter/nf_conntrack_h323_asn1.h +include/linux/netfilter/nf_conntrack_h323.h include/linux/netfilter/nf_conntrack_h323_types.h include/linux/netfilter/nf_conntrack_irc.h include/linux/netfilter/nf_conntrack_pptp.h @@ -3105,24 +3113,17 @@ include/linux/netfilter/nf_conntrack_zones_common.h include/linux/netfilter/nfnetlink.h include/linux/netfilter/x_tables.h include/linux/netfilter/xt_quota2.h -include/linux/netfilter_arp/arp_tables.h -include/linux/netfilter_bridge.h -include/linux/netfilter_defs.h -include/linux/netfilter_ingress.h -include/linux/netfilter_ipv4.h -include/linux/netfilter_ipv4/ip_tables.h -include/linux/netfilter_ipv6.h -include/linux/netfilter_ipv6/ip6_tables.h +include/linux/net.h include/linux/netlink.h include/linux/netpoll.h -include/linux/nfs.h include/linux/nfs3.h include/linux/nfs4.h +include/linux/nfsacl.h include/linux/nfs_fs.h include/linux/nfs_fs_i.h include/linux/nfs_fs_sb.h +include/linux/nfs.h include/linux/nfs_xdr.h -include/linux/nfsacl.h include/linux/nl802154.h include/linux/nls.h include/linux/nmi.h @@ -3137,7 +3138,6 @@ include/linux/nvme.h include/linux/nvmem-consumer.h include/linux/nvmem-provider.h include/linux/objtool.h -include/linux/of.h include/linux/of_address.h include/linux/of_clk.h include/linux/of_device.h @@ -3145,6 +3145,7 @@ include/linux/of_dma.h include/linux/of_fdt.h include/linux/of_gpio.h include/linux/of_graph.h +include/linux/of.h include/linux/of_iommu.h include/linux/of_irq.h include/linux/of_mdio.h @@ -3159,18 +3160,18 @@ include/linux/oom.h include/linux/osq_lock.h include/linux/overflow.h include/linux/padata.h -include/linux/page-flags-layout.h -include/linux/page-flags.h -include/linux/page-isolation.h +include/linux/pageblock-flags.h include/linux/page_counter.h include/linux/page_ext.h +include/linux/page-flags.h +include/linux/page-flags-layout.h include/linux/page_idle.h +include/linux/page-isolation.h +include/linux/pagemap.h include/linux/page_owner.h include/linux/page_pinner.h include/linux/page_ref.h include/linux/page_reporting.h -include/linux/pageblock-flags.h -include/linux/pagemap.h include/linux/pagevec.h include/linux/pagewalk.h include/linux/panic.h @@ -3189,11 +3190,11 @@ include/linux/pci.h include/linux/pci_hotplug.h include/linux/pci_ids.h include/linux/pe.h +include/linux/percpu_counter.h include/linux/percpu-defs.h +include/linux/percpu.h include/linux/percpu-refcount.h include/linux/percpu-rwsem.h -include/linux/percpu.h -include/linux/percpu_counter.h include/linux/perf/arm_pmu.h include/linux/perf_event.h include/linux/perf_regs.h @@ -3201,13 +3202,13 @@ include/linux/personality.h include/linux/pfn.h include/linux/pfn_t.h include/linux/pgtable.h -include/linux/phy.h -include/linux/phy/phy-dp.h -include/linux/phy/phy-mipi-dphy.h -include/linux/phy/phy.h include/linux/phy_fixed.h +include/linux/phy.h include/linux/phy_led_triggers.h include/linux/phylink.h +include/linux/phy/phy-dp.h +include/linux/phy/phy.h +include/linux/phy/phy-mipi-dphy.h include/linux/pid.h include/linux/pid_namespace.h include/linux/pim.h @@ -3216,8 +3217,8 @@ include/linux/pinctrl/devinfo.h include/linux/pinctrl/machine.h include/linux/pinctrl/pinconf-generic.h include/linux/pinctrl/pinconf.h -include/linux/pinctrl/pinctrl-state.h include/linux/pinctrl/pinctrl.h +include/linux/pinctrl/pinctrl-state.h include/linux/pinctrl/pinmux.h include/linux/pipe_fs_i.h include/linux/pkeys.h @@ -3228,35 +3229,35 @@ include/linux/platform_data/syscon.h include/linux/platform_data/x86/apple.h include/linux/platform_device.h include/linux/plist.h -include/linux/pm-trace.h -include/linux/pm.h include/linux/pm_clock.h include/linux/pm_domain.h +include/linux/pm.h include/linux/pm_opp.h include/linux/pm_qos.h include/linux/pm_runtime.h +include/linux/pm-trace.h include/linux/pm_wakeirq.h include/linux/pm_wakeup.h include/linux/poison.h include/linux/poll.h -include/linux/posix-clock.h -include/linux/posix-timers.h include/linux/posix_acl.h include/linux/posix_acl_xattr.h -include/linux/power_supply.h +include/linux/posix-clock.h +include/linux/posix-timers.h include/linux/powercap.h -include/linux/ppp-comp.h +include/linux/power_supply.h include/linux/ppp_channel.h +include/linux/ppp-comp.h include/linux/ppp_defs.h include/linux/pps_kernel.h -include/linux/pr.h include/linux/prandom.h include/linux/preempt.h include/linux/prefetch.h +include/linux/pr.h include/linux/printk.h +include/linux/processor.h include/linux/proc_fs.h include/linux/proc_ns.h -include/linux/processor.h include/linux/profile.h include/linux/projid.h include/linux/property.h @@ -3270,8 +3271,8 @@ include/linux/pti.h include/linux/ptp_classify.h include/linux/ptp_clock_kernel.h include/linux/ptp_kvm.h -include/linux/ptr_ring.h include/linux/ptrace.h +include/linux/ptr_ring.h include/linux/pvclock_gtod.h include/linux/pwm.h include/linux/qcom-geni-se.h @@ -3287,19 +3288,19 @@ include/linux/ras.h include/linux/ratelimit.h include/linux/ratelimit_types.h include/linux/rational.h -include/linux/rbtree.h include/linux/rbtree_augmented.h +include/linux/rbtree.h include/linux/rbtree_latch.h include/linux/rbtree_types.h -include/linux/rcu_node_tree.h -include/linux/rcu_segcblist.h -include/linux/rcu_sync.h -include/linux/rculist.h include/linux/rculist_bl.h +include/linux/rculist.h include/linux/rculist_nulls.h +include/linux/rcu_node_tree.h include/linux/rcupdate.h include/linux/rcupdate_trace.h include/linux/rcupdate_wait.h +include/linux/rcu_segcblist.h +include/linux/rcu_sync.h include/linux/rcutree.h include/linux/rcuwait.h include/linux/reboot.h @@ -3320,36 +3321,37 @@ include/linux/reset-controller.h include/linux/reset.h include/linux/reset/reset-simple.h include/linux/reset/sunxi.h -include/linux/resource.h include/linux/resource_ext.h +include/linux/resource.h include/linux/restart_block.h include/linux/rfkill.h -include/linux/rhashtable-types.h include/linux/rhashtable.h +include/linux/rhashtable-types.h include/linux/ring_buffer.h include/linux/rmap.h include/linux/rodata_test.h include/linux/root_dev.h -include/linux/rpmsg.h include/linux/rpmsg/byteorder.h +include/linux/rpmsg.h include/linux/rslib.h include/linux/rtc.h include/linux/rtmutex.h include/linux/rtnetlink.h -include/linux/rwlock.h include/linux/rwlock_api_smp.h +include/linux/rwlock.h include/linux/rwlock_types.h include/linux/rwsem.h include/linux/sbitmap.h include/linux/scatterlist.h -include/linux/sched.h include/linux/sched/autogroup.h +include/linux/sched_clock.h include/linux/sched/clock.h include/linux/sched/coredump.h include/linux/sched/cpufreq.h include/linux/sched/cputime.h include/linux/sched/deadline.h include/linux/sched/debug.h +include/linux/sched.h include/linux/sched/hotplug.h include/linux/sched/idle.h include/linux/sched/init.h @@ -3373,7 +3375,6 @@ include/linux/sched/types.h include/linux/sched/user.h include/linux/sched/wake_q.h include/linux/sched/xacct.h -include/linux/sched_clock.h include/linux/scmi_protocol.h include/linux/scpi_protocol.h include/linux/screen_info.h @@ -3384,31 +3385,31 @@ include/linux/secretmem.h include/linux/securebits.h include/linux/security.h include/linux/sed-opal.h -include/linux/seg6.h include/linux/seg6_genl.h +include/linux/seg6.h include/linux/seg6_local.h include/linux/selection.h -include/linux/sem.h include/linux/semaphore.h +include/linux/sem.h include/linux/seq_buf.h include/linux/seq_file.h include/linux/seq_file_net.h include/linux/seqlock.h include/linux/seqno-fence.h include/linux/serdev.h -include/linux/serial.h include/linux/serial_8250.h include/linux/serial_core.h +include/linux/serial.h include/linux/serial_s3c.h include/linux/serio.h include/linux/set_memory.h include/linux/sfp.h -include/linux/shm.h include/linux/shmem_fs.h +include/linux/shm.h include/linux/shrinker.h +include/linux/signalfd.h include/linux/signal.h include/linux/signal_types.h -include/linux/signalfd.h include/linux/siphash.h include/linux/sizes.h include/linux/skb_array.h @@ -3416,21 +3417,21 @@ include/linux/skbuff.h include/linux/skmsg.h include/linux/slab.h include/linux/slub_def.h +include/linux/smpboot.h include/linux/smp.h include/linux/smp_types.h -include/linux/smpboot.h -include/linux/soc/qcom/smem_state.h -include/linux/soc/sunxi/sunxi_sram.h include/linux/sock_diag.h include/linux/socket.h include/linux/sockptr.h +include/linux/soc/qcom/smem_state.h +include/linux/soc/sunxi/sunxi_sram.h include/linux/sort.h -include/linux/spi/spi-mem.h -include/linux/spi/spi.h -include/linux/spinlock.h include/linux/spinlock_api_smp.h +include/linux/spinlock.h include/linux/spinlock_types.h include/linux/spinlock_types_raw.h +include/linux/spi/spi.h +include/linux/spi/spi-mem.h include/linux/splice.h include/linux/spmi.h include/linux/srcu.h @@ -3440,8 +3441,8 @@ include/linux/stackleak.h include/linux/stackprotector.h include/linux/stacktrace.h include/linux/start_kernel.h -include/linux/stat.h include/linux/statfs.h +include/linux/stat.h include/linux/static_call.h include/linux/static_call_types.h include/linux/static_key.h @@ -3449,8 +3450,8 @@ include/linux/stdarg.h include/linux/stddef.h include/linux/stop_machine.h include/linux/string.h -include/linux/string_helpers.h include/linux/stringhash.h +include/linux/string_helpers.h include/linux/stringify.h include/linux/sunrpc/auth.h include/linux/sunrpc/clnt.h @@ -3468,67 +3469,67 @@ include/linux/sunrpc/xprtmultipath.h include/linux/suspend.h include/linux/swab.h include/linux/swait.h -include/linux/swap.h include/linux/swap_cgroup.h -include/linux/swap_slots.h include/linux/swapfile.h +include/linux/swap.h include/linux/swapops.h +include/linux/swap_slots.h include/linux/swiotlb.h include/linux/switchtec.h include/linux/sync_core.h include/linux/sync_file.h -include/linux/sys_soc.h -include/linux/syscall_user_dispatch.h include/linux/syscalls.h +include/linux/syscall_user_dispatch.h include/linux/syscore_ops.h include/linux/sysctl.h include/linux/sysfb.h include/linux/sysfs.h include/linux/syslog.h include/linux/sysrq.h +include/linux/sys_soc.h include/linux/t10-pi.h include/linux/task_io_accounting.h include/linux/task_io_accounting_ops.h -include/linux/task_work.h include/linux/taskstats_kern.h +include/linux/task_work.h include/linux/tcp.h -include/linux/textsearch.h include/linux/textsearch_fsm.h +include/linux/textsearch.h include/linux/thermal.h include/linux/thread_info.h include/linux/threads.h -include/linux/ti_wilink_st.h include/linux/tick.h -include/linux/time.h include/linux/time32.h include/linux/time64.h -include/linux/time_namespace.h include/linux/timecounter.h +include/linux/time.h include/linux/timekeeper_internal.h include/linux/timekeeping.h -include/linux/timer.h +include/linux/time_namespace.h include/linux/timerfd.h +include/linux/timer.h include/linux/timerqueue.h include/linux/timex.h +include/linux/ti_wilink_st.h include/linux/tnum.h include/linux/topology.h -include/linux/tpm.h include/linux/tpm_eventlog.h -include/linux/trace.h +include/linux/tpm.h include/linux/trace_clock.h include/linux/trace_events.h -include/linux/trace_recursion.h -include/linux/trace_seq.h include/linux/tracefs.h +include/linux/trace.h include/linux/tracehook.h include/linux/tracepoint-defs.h include/linux/tracepoint.h +include/linux/trace_recursion.h +include/linux/trace_seq.h include/linux/transport_class.h include/linux/tsacct_kern.h -include/linux/tty.h include/linux/tty_buffer.h include/linux/tty_driver.h include/linux/tty_flip.h +include/linux/tty.h include/linux/tty_ldisc.h include/linux/tty_port.h include/linux/typecheck.h @@ -3538,39 +3539,40 @@ include/linux/uaccess.h include/linux/ucs2_string.h include/linux/udp.h include/linux/uidgid.h -include/linux/uio.h include/linux/uio_driver.h +include/linux/uio.h include/linux/ulpi/interface.h include/linux/umh.h include/linux/unaligned/packed_struct.h include/linux/unicode.h include/linux/units.h include/linux/uprobes.h -include/linux/usb.h +include/linux/usb/audio.h include/linux/usb/audio-v2.h include/linux/usb/audio-v3.h -include/linux/usb/audio.h include/linux/usb/ccid.h include/linux/usb/cdc.h include/linux/usb/cdc_ncm.h include/linux/usb/ch9.h include/linux/usb/composite.h +include/linux/usbdevice_fs.h include/linux/usb/ehci-dbgp.h include/linux/usb/ehci_def.h include/linux/usb/ehci_pdriver.h include/linux/usb/f_accessory.h include/linux/usb/functionfs.h -include/linux/usb/g_hid.h -include/linux/usb/gadget.h include/linux/usb/gadget_configfs.h +include/linux/usb/gadget.h +include/linux/usb/g_hid.h +include/linux/usb.h include/linux/usb/hcd.h include/linux/usb/input.h include/linux/usb/of.h include/linux/usb/otg.h -include/linux/usb/pd.h include/linux/usb/pd_ado.h include/linux/usb/pd_bdo.h include/linux/usb/pd_ext_sdb.h +include/linux/usb/pd.h include/linux/usb/pd_vdo.h include/linux/usb/phy.h include/linux/usb/quirks.h @@ -3578,19 +3580,18 @@ include/linux/usb/r8152.h include/linux/usb/role.h include/linux/usb/storage.h include/linux/usb/tcpm.h -include/linux/usb/typec.h include/linux/usb/typec_altmode.h include/linux/usb/typec_dp.h +include/linux/usb/typec.h include/linux/usb/typec_mux.h include/linux/usb/uas.h include/linux/usb/usbnet.h include/linux/usb_usual.h -include/linux/usbdevice_fs.h -include/linux/user-return-notifier.h -include/linux/user.h -include/linux/user_namespace.h include/linux/userfaultfd_k.h +include/linux/user.h include/linux/usermode_driver.h +include/linux/user_namespace.h +include/linux/user-return-notifier.h include/linux/util_macros.h include/linux/uts.h include/linux/utsname.h @@ -3599,31 +3600,31 @@ include/linux/verification.h include/linux/vermagic.h include/linux/vfio.h include/linux/vfs.h -include/linux/vga_switcheroo.h include/linux/vgaarb.h +include/linux/vga_switcheroo.h include/linux/vhost_iotlb.h include/linux/videodev2.h -include/linux/virtio.h include/linux/virtio_byteorder.h include/linux/virtio_config.h +include/linux/virtio.h include/linux/virtio_net.h include/linux/virtio_ring.h include/linux/virtio_vsock.h -include/linux/vm_event.h -include/linux/vm_event_item.h include/linux/vmacache.h include/linux/vmalloc.h +include/linux/vm_event.h +include/linux/vm_event_item.h include/linux/vmpressure.h include/linux/vmstat.h -include/linux/vt.h include/linux/vt_buffer.h -include/linux/vt_kern.h +include/linux/vt.h include/linux/vtime.h -include/linux/wait.h +include/linux/vt_kern.h include/linux/wait_bit.h +include/linux/wait.h include/linux/wakeup_reason.h -include/linux/watch_queue.h include/linux/watchdog.h +include/linux/watch_queue.h include/linux/win_minmax.h include/linux/wireless.h include/linux/workqueue.h @@ -3639,9 +3640,9 @@ include/linux/zpool.h include/linux/zsmalloc.h include/linux/zstd.h include/linux/zutil.h +include/media/cec.h include/media/cec-notifier.h include/media/cec-pin.h -include/media/cec.h include/media/frame_vector.h include/media/hevc-ctrls.h include/media/i2c/ir-kbd-i2c.h @@ -3683,8 +3684,8 @@ include/net/ah.h include/net/arp.h include/net/ax25.h include/net/bluetooth/bluetooth.h -include/net/bluetooth/hci.h include/net/bluetooth/hci_core.h +include/net/bluetooth/hci.h include/net/bluetooth/hci_mon.h include/net/bluetooth/hci_sock.h include/net/bluetooth/l2cap.h @@ -3707,8 +3708,8 @@ include/net/datalink.h include/net/devlink.h include/net/dsa.h include/net/dsfield.h -include/net/dst.h include/net/dst_cache.h +include/net/dst.h include/net/dst_metadata.h include/net/dst_ops.h include/net/erspan.h @@ -3717,15 +3718,15 @@ include/net/espintcp.h include/net/fib_notifier.h include/net/fib_rules.h include/net/firewire.h -include/net/flow.h include/net/flow_dissector.h +include/net/flow.h include/net/flow_offload.h -include/net/gen_stats.h include/net/genetlink.h include/net/geneve.h +include/net/gen_stats.h include/net/gre.h -include/net/gro.h include/net/gro_cells.h +include/net/gro.h include/net/icmp.h include/net/ieee802154_netdev.h include/net/if_inet6.h @@ -3736,20 +3737,20 @@ include/net/inet_connection_sock.h include/net/inet_ecn.h include/net/inet_frag.h include/net/inet_hashtables.h +include/net/inetpeer.h include/net/inet_sock.h include/net/inet_timewait_sock.h -include/net/inetpeer.h include/net/ioam6.h -include/net/ip.h include/net/ip6_checksum.h include/net/ip6_fib.h include/net/ip6_route.h include/net/ip6_tunnel.h -include/net/ip_fib.h -include/net/ip_tunnels.h include/net/ipcomp.h -include/net/ipv6.h +include/net/ip_fib.h +include/net/ip.h +include/net/ip_tunnels.h include/net/ipv6_frag.h +include/net/ipv6.h include/net/ipv6_stubs.h include/net/iw_handler.h include/net/l3mdev.h @@ -3765,8 +3766,6 @@ include/net/mpls.h include/net/mptcp.h include/net/ndisc.h include/net/neighbour.h -include/net/net_namespace.h -include/net/net_ratelimit.h include/net/netevent.h include/net/netfilter/ipv4/nf_conntrack_ipv4.h include/net/netfilter/ipv4/nf_defrag_ipv4.h @@ -3776,7 +3775,6 @@ include/net/netfilter/ipv6/nf_conntrack_ipv6.h include/net/netfilter/ipv6/nf_defrag_ipv6.h include/net/netfilter/ipv6/nf_dup_ipv6.h include/net/netfilter/ipv6/nf_reject.h -include/net/netfilter/nf_conntrack.h include/net/netfilter/nf_conntrack_acct.h include/net/netfilter/nf_conntrack_bridge.h include/net/netfilter/nf_conntrack_core.h @@ -3784,6 +3782,7 @@ include/net/netfilter/nf_conntrack_count.h include/net/netfilter/nf_conntrack_ecache.h include/net/netfilter/nf_conntrack_expect.h include/net/netfilter/nf_conntrack_extend.h +include/net/netfilter/nf_conntrack.h include/net/netfilter/nf_conntrack_helper.h include/net/netfilter/nf_conntrack_l4proto.h include/net/netfilter/nf_conntrack_labels.h @@ -3805,6 +3804,7 @@ include/net/netfilter/nf_socket.h include/net/netfilter/nf_tproxy.h include/net/netlabel.h include/net/netlink.h +include/net/net_namespace.h include/net/netns/bpf.h include/net/netns/can.h include/net/netns/conntrack.h @@ -3827,6 +3827,7 @@ include/net/netns/unix.h include/net/netns/xdp.h include/net/netns/xfrm.h include/net/netprio_cgroup.h +include/net/net_ratelimit.h include/net/netrom.h include/net/nexthop.h include/net/nfc/nfc.h @@ -3894,15 +3895,15 @@ include/net/tls.h include/net/transp_v6.h include/net/tso.h include/net/udp.h -include/net/udp_tunnel.h include/net/udplite.h +include/net/udp_tunnel.h include/net/vsock_addr.h include/net/vxlan.h include/net/wext.h include/net/xdp.h include/net/xdp_priv.h -include/net/xdp_sock.h include/net/xdp_sock_drv.h +include/net/xdp_sock.h include/net/xfrm.h include/net/xsk_buff_pool.h include/ras/ras_event.h @@ -3912,7 +3913,7 @@ include/rdma/rdma_netlink.h include/rdma/restrack.h include/rdma/signature.h include/scsi/fc/fc_fcoe.h -include/scsi/scsi.h +include/scsi/scsicam.h include/scsi/scsi_cmnd.h include/scsi/scsi_common.h include/scsi/scsi_dbg.h @@ -3921,6 +3922,7 @@ include/scsi/scsi_devinfo.h include/scsi/scsi_dh.h include/scsi/scsi_driver.h include/scsi/scsi_eh.h +include/scsi/scsi.h include/scsi/scsi_host.h include/scsi/scsi_ioctl.h include/scsi/scsi_proto.h @@ -3928,14 +3930,13 @@ include/scsi/scsi_request.h include/scsi/scsi_status.h include/scsi/scsi_tcq.h include/scsi/scsi_transport.h -include/scsi/scsicam.h include/scsi/sg.h include/soc/at91/atmel-secumod.h -include/sound/ac97/regs.h include/sound/ac97_codec.h +include/sound/ac97/regs.h include/sound/asequencer.h -include/sound/asound.h include/sound/asoundef.h +include/sound/asound.h include/sound/compress_driver.h include/sound/control.h include/sound/core.h @@ -3946,8 +3947,8 @@ include/sound/initval.h include/sound/jack.h include/sound/memalloc.h include/sound/minors.h -include/sound/pcm.h include/sound/pcm_drm_eld.h +include/sound/pcm.h include/sound/pcm_iec958.h include/sound/pcm_params.h include/sound/rawmidi.h @@ -3956,10 +3957,10 @@ include/sound/soc-component.h include/sound/soc-dai.h include/sound/soc-dapm.h include/sound/soc-dpcm.h +include/sound/soc.h include/sound/soc-jack.h include/sound/soc-link.h include/sound/soc-topology.h -include/sound/soc.h include/sound/timer.h include/sound/tlv.h include/trace/bpf_probe.h @@ -3985,8 +3986,8 @@ include/trace/events/erofs.h include/trace/events/error_report.h include/trace/events/ext4.h include/trace/events/f2fs.h -include/trace/events/fib.h include/trace/events/fib6.h +include/trace/events/fib.h include/trace/events/filelock.h include/trace/events/filemap.h include/trace/events/gpio.h @@ -3994,9 +3995,9 @@ include/trace/events/gpu_mem.h include/trace/events/huge_memory.h include/trace/events/i2c.h include/trace/events/initcall.h -include/trace/events/io_uring.h include/trace/events/iocost.h include/trace/events/iommu.h +include/trace/events/io_uring.h include/trace/events/ipi.h include/trace/events/irq.h include/trace/events/jbd2.h @@ -4013,12 +4014,12 @@ include/trace/events/module.h include/trace/events/napi.h include/trace/events/neigh.h include/trace/events/net.h -include/trace/events/net_probe_common.h include/trace/events/netlink.h +include/trace/events/net_probe_common.h include/trace/events/oom.h include/trace/events/page_isolation.h -include/trace/events/page_pool.h include/trace/events/pagemap.h +include/trace/events/page_pool.h include/trace/events/percpu.h include/trace/events/power.h include/trace/events/printk.h @@ -4069,8 +4070,8 @@ include/trace/hooks/cpuidle_psci.h include/trace/hooks/creds.h include/trace/hooks/debug.h include/trace/hooks/direct_io.h -include/trace/hooks/dm.h include/trace/hooks/dmabuf.h +include/trace/hooks/dm.h include/trace/hooks/drm_atomic.h include/trace/hooks/drm_framebuffer.h include/trace/hooks/dtask.h @@ -4088,8 +4089,8 @@ include/trace/hooks/iommu.h include/trace/hooks/logbuf.h include/trace/hooks/loop.h include/trace/hooks/memory.h -include/trace/hooks/mm.h include/trace/hooks/mmc.h +include/trace/hooks/mm.h include/trace/hooks/module.h include/trace/hooks/mpam.h include/trace/hooks/net.h @@ -4108,8 +4109,8 @@ include/trace/hooks/sched.h include/trace/hooks/selinux.h include/trace/hooks/signal.h include/trace/hooks/softlockup.h -include/trace/hooks/sys.h include/trace/hooks/syscall_check.h +include/trace/hooks/sys.h include/trace/hooks/sysrqcrash.h include/trace/hooks/thermal.h include/trace/hooks/timekeeping.h @@ -4149,20 +4150,20 @@ include/uapi/asm-generic/signal-defs.h include/uapi/asm-generic/signal.h include/uapi/asm-generic/socket.h include/uapi/asm-generic/sockios.h -include/uapi/asm-generic/stat.h include/uapi/asm-generic/statfs.h +include/uapi/asm-generic/stat.h include/uapi/asm-generic/swab.h include/uapi/asm-generic/termbits.h include/uapi/asm-generic/termios.h include/uapi/asm-generic/types.h include/uapi/asm-generic/unistd.h -include/uapi/drm/drm.h include/uapi/drm/drm_fourcc.h +include/uapi/drm/drm.h include/uapi/drm/drm_mode.h include/uapi/linux/acct.h include/uapi/linux/aio_abi.h -include/uapi/linux/android/binder.h include/uapi/linux/android/binderfs.h +include/uapi/linux/android/binder.h include/uapi/linux/android_fuse.h include/uapi/linux/arm_sdei.h include/uapi/linux/audit.h @@ -4173,17 +4174,17 @@ include/uapi/linux/binfmts.h include/uapi/linux/blkpg.h include/uapi/linux/blktrace_api.h include/uapi/linux/blkzoned.h -include/uapi/linux/bpf.h include/uapi/linux/bpf_common.h -include/uapi/linux/bpf_perf_event.h +include/uapi/linux/bpf.h include/uapi/linux/bpfilter.h +include/uapi/linux/bpf_perf_event.h include/uapi/linux/bsg.h include/uapi/linux/btf.h include/uapi/linux/byteorder/little_endian.h -include/uapi/linux/can.h include/uapi/linux/can/bcm.h include/uapi/linux/can/error.h include/uapi/linux/can/gw.h +include/uapi/linux/can.h include/uapi/linux/can/netlink.h include/uapi/linux/can/raw.h include/uapi/linux/capability.h @@ -4199,10 +4200,10 @@ include/uapi/linux/cramfs_fs.h include/uapi/linux/cryptouser.h include/uapi/linux/dccp.h include/uapi/linux/devlink.h -include/uapi/linux/dm-ioctl.h -include/uapi/linux/dm-user.h include/uapi/linux/dma-buf.h include/uapi/linux/dma-heap.h +include/uapi/linux/dm-ioctl.h +include/uapi/linux/dm-user.h include/uapi/linux/dqblk_xfs.h include/uapi/linux/elf-em.h include/uapi/linux/elf.h @@ -4222,27 +4223,26 @@ include/uapi/linux/fd.h include/uapi/linux/fib_rules.h include/uapi/linux/fiemap.h include/uapi/linux/filter.h -include/uapi/linux/fs.h include/uapi/linux/fscrypt.h +include/uapi/linux/fs.h include/uapi/linux/fsl_mc.h include/uapi/linux/fsmap.h include/uapi/linux/fsverity.h include/uapi/linux/fuse.h include/uapi/linux/futex.h -include/uapi/linux/gen_stats.h include/uapi/linux/genetlink.h +include/uapi/linux/gen_stats.h include/uapi/linux/gpio.h include/uapi/linux/hash_info.h include/uapi/linux/hdlc/ioctl.h include/uapi/linux/hdreg.h -include/uapi/linux/hid.h include/uapi/linux/hiddev.h +include/uapi/linux/hid.h include/uapi/linux/hidraw.h include/uapi/linux/hw_breakpoint.h include/uapi/linux/i2c.h include/uapi/linux/icmp.h include/uapi/linux/icmpv6.h -include/uapi/linux/if.h include/uapi/linux/if_addr.h include/uapi/linux/if_addrlabel.h include/uapi/linux/if_arcnet.h @@ -4252,6 +4252,7 @@ include/uapi/linux/if_bridge.h include/uapi/linux/if_ether.h include/uapi/linux/if_fc.h include/uapi/linux/if_fddi.h +include/uapi/linux/if.h include/uapi/linux/if_hippi.h include/uapi/linux/if_infiniband.h include/uapi/linux/if_link.h @@ -4268,33 +4269,33 @@ include/uapi/linux/igmp.h include/uapi/linux/iio/buffer.h include/uapi/linux/iio/events.h include/uapi/linux/iio/types.h -include/uapi/linux/in.h include/uapi/linux/in6.h -include/uapi/linux/in_route.h include/uapi/linux/incrementalfs.h include/uapi/linux/inet_diag.h +include/uapi/linux/in.h include/uapi/linux/inotify.h include/uapi/linux/input-event-codes.h include/uapi/linux/input.h -include/uapi/linux/io_uring.h -include/uapi/linux/ioam6.h +include/uapi/linux/in_route.h include/uapi/linux/ioam6_genl.h +include/uapi/linux/ioam6.h include/uapi/linux/ioctl.h include/uapi/linux/iommu.h include/uapi/linux/ioprio.h -include/uapi/linux/ip.h +include/uapi/linux/io_uring.h include/uapi/linux/ip6_tunnel.h include/uapi/linux/ipc.h +include/uapi/linux/ip.h include/uapi/linux/ipsec.h include/uapi/linux/ipv6.h include/uapi/linux/ipv6_route.h include/uapi/linux/irqnr.h include/uapi/linux/kcmp.h include/uapi/linux/kcov.h -include/uapi/linux/kd.h include/uapi/linux/kdev_t.h -include/uapi/linux/kernel-page-flags.h +include/uapi/linux/kd.h include/uapi/linux/kernel.h +include/uapi/linux/kernel-page-flags.h include/uapi/linux/kexec.h include/uapi/linux/keyboard.h include/uapi/linux/keyctl.h @@ -4323,19 +4324,28 @@ include/uapi/linux/module.h include/uapi/linux/mount.h include/uapi/linux/mpls.h include/uapi/linux/mqueue.h -include/uapi/linux/mroute.h include/uapi/linux/mroute6.h +include/uapi/linux/mroute.h include/uapi/linux/msdos_fs.h include/uapi/linux/msg.h include/uapi/linux/ndctl.h include/uapi/linux/neighbour.h -include/uapi/linux/net.h -include/uapi/linux/net_dropmon.h -include/uapi/linux/net_namespace.h -include/uapi/linux/net_tstamp.h include/uapi/linux/netconf.h include/uapi/linux/netdevice.h +include/uapi/linux/net_dropmon.h +include/uapi/linux/netfilter_arp/arp_tables.h +include/uapi/linux/netfilter_arp/arpt_mangle.h +include/uapi/linux/netfilter_arp.h +include/uapi/linux/netfilter_bridge.h include/uapi/linux/netfilter.h +include/uapi/linux/netfilter_ipv4.h +include/uapi/linux/netfilter_ipv4/ip_tables.h +include/uapi/linux/netfilter_ipv4/ipt_REJECT.h +include/uapi/linux/netfilter_ipv4/ipt_ttl.h +include/uapi/linux/netfilter_ipv6.h +include/uapi/linux/netfilter_ipv6/ip6_tables.h +include/uapi/linux/netfilter_ipv6/ip6t_hl.h +include/uapi/linux/netfilter_ipv6/ip6t_REJECT.h include/uapi/linux/netfilter/nf_conntrack_common.h include/uapi/linux/netfilter/nf_conntrack_ftp.h include/uapi/linux/netfilter/nf_conntrack_sctp.h @@ -4343,35 +4353,29 @@ include/uapi/linux/netfilter/nf_conntrack_tcp.h include/uapi/linux/netfilter/nf_conntrack_tuple_common.h include/uapi/linux/netfilter/nf_log.h include/uapi/linux/netfilter/nf_nat.h -include/uapi/linux/netfilter/nf_tables.h -include/uapi/linux/netfilter/nfnetlink.h include/uapi/linux/netfilter/nfnetlink_compat.h include/uapi/linux/netfilter/nfnetlink_conntrack.h +include/uapi/linux/netfilter/nfnetlink.h include/uapi/linux/netfilter/nfnetlink_log.h include/uapi/linux/netfilter/nfnetlink_queue.h +include/uapi/linux/netfilter/nf_tables.h include/uapi/linux/netfilter/x_tables.h -include/uapi/linux/netfilter/xt_CLASSIFY.h -include/uapi/linux/netfilter/xt_CONNSECMARK.h -include/uapi/linux/netfilter/xt_CT.h -include/uapi/linux/netfilter/xt_DSCP.h -include/uapi/linux/netfilter/xt_IDLETIMER.h -include/uapi/linux/netfilter/xt_NFLOG.h -include/uapi/linux/netfilter/xt_NFQUEUE.h -include/uapi/linux/netfilter/xt_SECMARK.h -include/uapi/linux/netfilter/xt_TCPMSS.h -include/uapi/linux/netfilter/xt_TEE.h -include/uapi/linux/netfilter/xt_TPROXY.h include/uapi/linux/netfilter/xt_bpf.h +include/uapi/linux/netfilter/xt_CLASSIFY.h include/uapi/linux/netfilter/xt_comment.h include/uapi/linux/netfilter/xt_connlabel.h include/uapi/linux/netfilter/xt_connlimit.h include/uapi/linux/netfilter/xt_connmark.h +include/uapi/linux/netfilter/xt_CONNSECMARK.h include/uapi/linux/netfilter/xt_conntrack.h +include/uapi/linux/netfilter/xt_CT.h include/uapi/linux/netfilter/xt_dscp.h +include/uapi/linux/netfilter/xt_DSCP.h include/uapi/linux/netfilter/xt_ecn.h include/uapi/linux/netfilter/xt_esp.h include/uapi/linux/netfilter/xt_hashlimit.h include/uapi/linux/netfilter/xt_helper.h +include/uapi/linux/netfilter/xt_IDLETIMER.h include/uapi/linux/netfilter/xt_iprange.h include/uapi/linux/netfilter/xt_l2tp.h include/uapi/linux/netfilter/xt_length.h @@ -4379,41 +4383,38 @@ include/uapi/linux/netfilter/xt_limit.h include/uapi/linux/netfilter/xt_mac.h include/uapi/linux/netfilter/xt_mark.h include/uapi/linux/netfilter/xt_multiport.h +include/uapi/linux/netfilter/xt_NFLOG.h +include/uapi/linux/netfilter/xt_NFQUEUE.h include/uapi/linux/netfilter/xt_owner.h include/uapi/linux/netfilter/xt_pkttype.h include/uapi/linux/netfilter/xt_policy.h include/uapi/linux/netfilter/xt_quota.h include/uapi/linux/netfilter/xt_rpfilter.h +include/uapi/linux/netfilter/xt_SECMARK.h include/uapi/linux/netfilter/xt_socket.h include/uapi/linux/netfilter/xt_state.h include/uapi/linux/netfilter/xt_statistic.h include/uapi/linux/netfilter/xt_string.h +include/uapi/linux/netfilter/xt_TCPMSS.h include/uapi/linux/netfilter/xt_tcpudp.h +include/uapi/linux/netfilter/xt_TEE.h include/uapi/linux/netfilter/xt_time.h +include/uapi/linux/netfilter/xt_TPROXY.h include/uapi/linux/netfilter/xt_u32.h -include/uapi/linux/netfilter_arp.h -include/uapi/linux/netfilter_arp/arp_tables.h -include/uapi/linux/netfilter_arp/arpt_mangle.h -include/uapi/linux/netfilter_bridge.h -include/uapi/linux/netfilter_ipv4.h -include/uapi/linux/netfilter_ipv4/ip_tables.h -include/uapi/linux/netfilter_ipv4/ipt_REJECT.h -include/uapi/linux/netfilter_ipv4/ipt_ttl.h -include/uapi/linux/netfilter_ipv6.h -include/uapi/linux/netfilter_ipv6/ip6_tables.h -include/uapi/linux/netfilter_ipv6/ip6t_REJECT.h -include/uapi/linux/netfilter_ipv6/ip6t_hl.h +include/uapi/linux/net.h include/uapi/linux/netlink.h +include/uapi/linux/net_namespace.h include/uapi/linux/netrom.h +include/uapi/linux/net_tstamp.h include/uapi/linux/nexthop.h include/uapi/linux/nfc.h -include/uapi/linux/nfs.h include/uapi/linux/nfs2.h include/uapi/linux/nfs3.h include/uapi/linux/nfs4.h -include/uapi/linux/nfs_fs.h -include/uapi/linux/nfs_mount.h include/uapi/linux/nfsacl.h +include/uapi/linux/nfs_fs.h +include/uapi/linux/nfs.h +include/uapi/linux/nfs_mount.h include/uapi/linux/nl80211.h include/uapi/linux/nsfs.h include/uapi/linux/oom.h @@ -4432,11 +4433,11 @@ include/uapi/linux/posix_acl.h include/uapi/linux/posix_acl_xattr.h include/uapi/linux/posix_types.h include/uapi/linux/ppp-comp.h -include/uapi/linux/ppp-ioctl.h include/uapi/linux/ppp_defs.h +include/uapi/linux/ppp-ioctl.h include/uapi/linux/pps.h -include/uapi/linux/pr.h include/uapi/linux/prctl.h +include/uapi/linux/pr.h include/uapi/linux/psample.h include/uapi/linux/psci.h include/uapi/linux/ptp_clock.h @@ -4463,18 +4464,18 @@ include/uapi/linux/sctp.h include/uapi/linux/seccomp.h include/uapi/linux/securebits.h include/uapi/linux/sed-opal.h -include/uapi/linux/seg6.h include/uapi/linux/seg6_genl.h +include/uapi/linux/seg6.h include/uapi/linux/seg6_local.h include/uapi/linux/selinux_netlink.h include/uapi/linux/sem.h -include/uapi/linux/serial.h include/uapi/linux/serial_core.h +include/uapi/linux/serial.h include/uapi/linux/serial_reg.h include/uapi/linux/serio.h include/uapi/linux/shm.h -include/uapi/linux/signal.h include/uapi/linux/signalfd.h +include/uapi/linux/signal.h include/uapi/linux/snmp.h include/uapi/linux/sock_diag.h include/uapi/linux/socket.h @@ -4511,18 +4512,18 @@ include/uapi/linux/tcp_metrics.h include/uapi/linux/termios.h include/uapi/linux/thermal.h include/uapi/linux/time.h -include/uapi/linux/time_types.h include/uapi/linux/timerfd.h include/uapi/linux/times.h +include/uapi/linux/time_types.h include/uapi/linux/timex.h include/uapi/linux/tiocl.h -include/uapi/linux/tipc.h include/uapi/linux/tipc_config.h +include/uapi/linux/tipc.h include/uapi/linux/tipc_netlink.h include/uapi/linux/tipc_sockets_diag.h include/uapi/linux/tls.h -include/uapi/linux/tty.h include/uapi/linux/tty_flags.h +include/uapi/linux/tty.h include/uapi/linux/types.h include/uapi/linux/udp.h include/uapi/linux/uhid.h @@ -4536,12 +4537,12 @@ include/uapi/linux/usb/cdc.h include/uapi/linux/usb/ch11.h include/uapi/linux/usb/ch9.h include/uapi/linux/usb/charger.h +include/uapi/linux/usbdevice_fs.h include/uapi/linux/usb/f_accessory.h include/uapi/linux/usb/functionfs.h include/uapi/linux/usb/g_uvc.h include/uapi/linux/usb/midi.h include/uapi/linux/usb/video.h -include/uapi/linux/usbdevice_fs.h include/uapi/linux/userfaultfd.h include/uapi/linux/utime.h include/uapi/linux/utsname.h @@ -4564,14 +4565,14 @@ include/uapi/linux/virtio_net.h include/uapi/linux/virtio_ring.h include/uapi/linux/virtio_types.h include/uapi/linux/virtio_vsock.h -include/uapi/linux/vm_sockets.h -include/uapi/linux/vm_sockets_diag.h include/uapi/linux/vmcore.h +include/uapi/linux/vm_sockets_diag.h +include/uapi/linux/vm_sockets.h include/uapi/linux/vsockmon.h include/uapi/linux/vt.h include/uapi/linux/wait.h -include/uapi/linux/watch_queue.h include/uapi/linux/watchdog.h +include/uapi/linux/watch_queue.h include/uapi/linux/wireguard.h include/uapi/linux/wireless.h include/uapi/linux/xattr.h @@ -4582,8 +4583,8 @@ include/uapi/rdma/ib_user_ioctl_verbs.h include/uapi/rdma/ib_user_mad.h include/uapi/rdma/ib_user_verbs.h include/uapi/rdma/rdma_netlink.h -include/uapi/rdma/rdma_user_ioctl.h include/uapi/rdma/rdma_user_ioctl_cmds.h +include/uapi/rdma/rdma_user_ioctl.h include/uapi/scsi/scsi_bsg_ufs.h include/uapi/sound/asequencer.h include/uapi/sound/asoc.h @@ -4601,9 +4602,9 @@ include/vdso/ktime.h include/vdso/limits.h include/vdso/math64.h include/vdso/processor.h -include/vdso/time.h include/vdso/time32.h include/vdso/time64.h +include/vdso/time.h include/vdso/vsyscall.h include/video/display_timing.h include/video/mipi_display.h @@ -4624,21 +4625,21 @@ init/do_mounts.c init/do_mounts.h init/do_mounts_initrd.c init/do_mounts_rd.c -init/init_task.c init/initramfs.c +init/init_task.c init/main.c init/version.c +io_uring/io_uring.c io_uring/io-wq.c io_uring/io-wq.h -io_uring/io_uring.c kernel/async.c kernel/audit.c -kernel/audit.h +kernel/auditfilter.c kernel/audit_fsnotify.c +kernel/audit.h +kernel/auditsc.c kernel/audit_tree.c kernel/audit_watch.c -kernel/auditfilter.c -kernel/auditsc.c kernel/bounds.c kernel/bpf/arraymap.c kernel/bpf/bpf_fuse.c @@ -4684,9 +4685,9 @@ kernel/bpf/trampoline.c kernel/bpf/verifier.c kernel/capability.c kernel/cfi.c +kernel/cgroup/cgroup.c kernel/cgroup/cgroup-internal.h kernel/cgroup/cgroup-v1.c -kernel/cgroup/cgroup.c kernel/cgroup/cpuset.c kernel/cgroup/freezer.c kernel/cgroup/legacy_freezer.c @@ -4764,15 +4765,15 @@ kernel/locking/percpu-rwsem.c kernel/locking/qrwlock.c kernel/locking/qspinlock.c kernel/locking/qspinlock_stat.h -kernel/locking/rtmutex.c kernel/locking/rtmutex_api.c +kernel/locking/rtmutex.c kernel/locking/rtmutex_common.h kernel/locking/rwsem.c kernel/locking/semaphore.c kernel/locking/spinlock.c kernel/locking/ww_mutex.h -kernel/module-internal.h kernel/module.c +kernel/module-internal.h kernel/module_signature.c kernel/module_signing.c kernel/notifier.c @@ -4810,8 +4811,8 @@ kernel/rcu/srcutree.c kernel/rcu/sync.c kernel/rcu/tasks.h kernel/rcu/tree.c -kernel/rcu/tree.h kernel/rcu/tree_exp.h +kernel/rcu/tree.h kernel/rcu/tree_nocb.h kernel/rcu/tree_plugin.h kernel/rcu/tree_stall.h @@ -4844,8 +4845,8 @@ kernel/sched/pelt.c kernel/sched/pelt.h kernel/sched/psi.c kernel/sched/rt.c -kernel/sched/sched-pelt.h kernel/sched/sched.h +kernel/sched/sched-pelt.h kernel/sched/smp.h kernel/sched/stats.c kernel/sched/stats.h @@ -4853,22 +4854,22 @@ kernel/sched/stop_task.c kernel/sched/swait.c kernel/sched/topology.c kernel/sched/vendor_hooks.c -kernel/sched/wait.c kernel/sched/wait_bit.c +kernel/sched/wait.c kernel/scs.c kernel/seccomp.c kernel/signal.c -kernel/smp.c kernel/smpboot.c kernel/smpboot.h +kernel/smp.c kernel/softirq.c kernel/stacktrace.c kernel/stop_machine.c kernel/sys.c -kernel/sys_ni.c kernel/sysctl.c -kernel/task_work.c +kernel/sys_ni.c kernel/taskstats.c +kernel/task_work.c kernel/time/alarmtimer.c kernel/time/clockevents.c kernel/time/clocksource.c @@ -4883,8 +4884,8 @@ kernel/time/posix-cpu-timers.c kernel/time/posix-timers.c kernel/time/posix-timers.h kernel/time/sched_clock.c -kernel/time/tick-broadcast-hrtimer.c kernel/time/tick-broadcast.c +kernel/time/tick-broadcast-hrtimer.c kernel/time/tick-common.c kernel/time/tick-internal.h kernel/time/tick-oneshot.c @@ -4894,8 +4895,8 @@ kernel/time/time.c kernel/time/timeconv.c kernel/time/timecounter.c kernel/time/timekeeping.c -kernel/time/timekeeping.h kernel/time/timekeeping_debug.c +kernel/time/timekeeping.h kernel/time/timekeeping_internal.h kernel/time/timer.c kernel/time/timer_list.c @@ -4906,11 +4907,11 @@ kernel/trace/bpf_trace.h kernel/trace/error_report-traces.c kernel/trace/pid_list.c kernel/trace/pid_list.h +kernel/tracepoint.c kernel/trace/power-traces.c kernel/trace/ring_buffer.c kernel/trace/rpm-traces.c kernel/trace/trace.c -kernel/trace/trace.h kernel/trace/trace_clock.c kernel/trace/trace_dynevent.c kernel/trace/trace_dynevent.h @@ -4923,6 +4924,7 @@ kernel/trace/trace_events_hist.c kernel/trace/trace_events_synth.c kernel/trace/trace_events_trigger.c kernel/trace/trace_export.c +kernel/trace/trace.h kernel/trace/trace_kprobe.c kernel/trace/trace_kprobe_selftest.h kernel/trace/trace_nop.c @@ -4941,7 +4943,6 @@ kernel/trace/trace_synth.h kernel/trace/trace_uprobe.c kernel/trace/tracing_map.c kernel/trace/tracing_map.h -kernel/tracepoint.c kernel/tsacct.c kernel/ucount.c kernel/uid16.c @@ -4971,26 +4972,26 @@ lib/clz_ctz.c lib/clz_tab.c lib/cmdline.c lib/compat_audit.c -lib/cpu_rmap.c lib/cpumask.c -lib/crc-ccitt.c +lib/cpu_rmap.c lib/crc16.c lib/crc32.c lib/crc32defs.h lib/crc8.c +lib/crc-ccitt.c lib/crypto/aes.c lib/crypto/arc4.c -lib/crypto/blake2s-generic.c lib/crypto/blake2s.c -lib/crypto/chacha.c +lib/crypto/blake2s-generic.c lib/crypto/chacha20poly1305.c +lib/crypto/chacha.c +lib/crypto/curve25519.c lib/crypto/curve25519-generic.c lib/crypto/curve25519-hacl64.c -lib/crypto/curve25519.c lib/crypto/des.c lib/crypto/libchacha.c -lib/crypto/poly1305-donna64.c lib/crypto/poly1305.c +lib/crypto/poly1305-donna64.c lib/crypto/sha256.c lib/ctype.c lib/debug_locks.c @@ -5009,8 +5010,8 @@ lib/errname.c lib/error-inject.c lib/errseq.c lib/extable.c -lib/fdt.c lib/fdt_addresses.c +lib/fdt.c lib/fdt_empty_tree.c lib/fdt_ro.c lib/fdt_rw.c @@ -5021,8 +5022,8 @@ lib/find_bit.c lib/flex_proportions.c lib/fonts/font_8x16.c lib/fonts/fonts.c -lib/gen_crc32table.c lib/genalloc.c +lib/gen_crc32table.c lib/generic-radix-tree.c lib/glob.c lib/hexdump.c @@ -5077,7 +5078,11 @@ lib/mpi/longlong.h lib/mpi/mpi-add.c lib/mpi/mpi-bit.c lib/mpi/mpi-cmp.c +lib/mpi/mpicoder.c lib/mpi/mpi-div.c +lib/mpi/mpih-cmp.c +lib/mpi/mpih-div.c +lib/mpi/mpih-mul.c lib/mpi/mpi-inline.h lib/mpi/mpi-internal.h lib/mpi/mpi-inv.c @@ -5085,10 +5090,6 @@ lib/mpi/mpi-mod.c lib/mpi/mpi-mul.c lib/mpi/mpi-pow.c lib/mpi/mpi-sub-ui.c -lib/mpi/mpicoder.c -lib/mpi/mpih-cmp.c -lib/mpi/mpih-div.c -lib/mpi/mpih-mul.c lib/mpi/mpiutil.c lib/net_utils.c lib/nlattr.c @@ -5098,8 +5099,8 @@ lib/oid_registry.c lib/once.c lib/parser.c lib/pci_iomap.c -lib/percpu-refcount.c lib/percpu_counter.c +lib/percpu-refcount.c lib/plist.c lib/radix-tree.c lib/random32.c @@ -5164,12 +5165,12 @@ lib/zstd/compress.c lib/zstd/decompress.c lib/zstd/entropy_common.c lib/zstd/error_private.h -lib/zstd/fse.h lib/zstd/fse_compress.c lib/zstd/fse_decompress.c -lib/zstd/huf.h +lib/zstd/fse.h lib/zstd/huf_compress.c lib/zstd/huf_decompress.c +lib/zstd/huf.h lib/zstd/mem.h lib/zstd/zstd_common.c lib/zstd/zstd_internal.h @@ -5178,11 +5179,11 @@ mm/backing-dev.c mm/balloon_compaction.c mm/cleancache.c mm/cma.c -mm/cma.h mm/cma_debug.c +mm/cma.h mm/compaction.c -mm/damon/core-test.h mm/damon/core.c +mm/damon/core-test.h mm/damon/paddr.c mm/damon/prmtv-common.c mm/damon/prmtv-common.h @@ -5221,9 +5222,9 @@ mm/mempool.c mm/migrate.c mm/mincore.c mm/mlock.c -mm/mm_init.c mm/mmap.c mm/mmap_lock.c +mm/mm_init.c mm/mmu_gather.c mm/mmu_notifier.c mm/mmzone.c @@ -5231,7 +5232,6 @@ mm/mprotect.c mm/mremap.c mm/msync.c mm/oom_kill.c -mm/page-writeback.c mm/page_alloc.c mm/page_counter.c mm/page_ext.c @@ -5243,9 +5243,10 @@ mm/page_reporting.c mm/page_reporting.h mm/page_vma_mapped.c mm/pagewalk.c +mm/page-writeback.c +mm/percpu.c mm/percpu-internal.h mm/percpu-vm.c -mm/percpu.c mm/pgalloc-track.h mm/pgtable-generic.c mm/process_vm_access.c @@ -5254,16 +5255,16 @@ mm/rmap.c mm/shmem.c mm/shuffle.c mm/shuffle.h -mm/slab.h mm/slab_common.c +mm/slab.h mm/slub.c -mm/sparse-vmemmap.c mm/sparse.c +mm/sparse-vmemmap.c mm/swap.c mm/swap_cgroup.c +mm/swapfile.c mm/swap_slots.c mm/swap_state.c -mm/swapfile.c mm/truncate.c mm/usercopy.c mm/userfaultfd.c @@ -5280,24 +5281,24 @@ net/6lowpan/core.c net/6lowpan/iphc.c net/6lowpan/ndisc.c net/6lowpan/nhc.c -net/6lowpan/nhc.h net/6lowpan/nhc_dest.c net/6lowpan/nhc_fragment.c +net/6lowpan/nhc.h net/6lowpan/nhc_hop.c net/6lowpan/nhc_ipv6.c net/6lowpan/nhc_mobility.c net/6lowpan/nhc_routing.c net/6lowpan/nhc_udp.c -net/802/p8022.c -net/802/psnap.c -net/802/stp.c net/8021q/vlan.c -net/8021q/vlan.h net/8021q/vlan_core.c net/8021q/vlan_dev.c +net/8021q/vlan.h net/8021q/vlan_netlink.c net/8021q/vlanproc.c net/8021q/vlanproc.h +net/802/p8022.c +net/802/psnap.c +net/802/stp.c net/bluetooth/a2mp.h net/bluetooth/af_bluetooth.c net/bluetooth/amp.h @@ -5334,8 +5335,8 @@ net/bluetooth/selftest.h net/bluetooth/smp.c net/bluetooth/smp.h net/bpf/test_run.c -net/bridge/br.c net/bridge/br_arp_nd_proxy.c +net/bridge/br.c net/bridge/br_device.c net/bridge/br_fdb.c net/bridge/br_forward.c @@ -5347,13 +5348,13 @@ net/bridge/br_multicast.c net/bridge/br_multicast_eht.c net/bridge/br_netlink.c net/bridge/br_netlink_tunnel.c -net/bridge/br_private.h net/bridge/br_private_cfm.h +net/bridge/br_private.h net/bridge/br_private_mcast_eht.h net/bridge/br_private_stp.h net/bridge/br_private_tunnel.h -net/bridge/br_stp.c net/bridge/br_stp_bpdu.c +net/bridge/br_stp.c net/bridge/br_stp_if.c net/bridge/br_stp_timer.c net/bridge/br_sysfs_br.c @@ -5368,8 +5369,8 @@ net/compat.c net/core/bpf_sk_storage.c net/core/datagram.c net/core/datagram.h -net/core/dev.c net/core/dev_addr_lists.c +net/core/dev.c net/core/dev_ioctl.c net/core/devlink.c net/core/dst.c @@ -5384,13 +5385,13 @@ net/core/gen_stats.c net/core/gro_cells.c net/core/link_watch.c net/core/neighbour.c +net/core/netevent.c +net/core/net_namespace.c +net/core/netprio_cgroup.c net/core/net-procfs.c net/core/net-sysfs.c net/core/net-sysfs.h net/core/net-traces.c -net/core/net_namespace.c -net/core/netevent.c -net/core/netprio_cgroup.c net/core/of_net.c net/core/page_pool.c net/core/ptp_classifier.c @@ -5450,10 +5451,10 @@ net/ieee802154/core.h net/ieee802154/header_ops.c net/ieee802154/ieee802154.h net/ieee802154/netlink.c -net/ieee802154/nl-mac.c -net/ieee802154/nl-phy.c net/ieee802154/nl802154.c net/ieee802154/nl802154.h +net/ieee802154/nl-mac.c +net/ieee802154/nl-phy.c net/ieee802154/nl_policy.c net/ieee802154/rdev-ops.h net/ieee802154/socket.c @@ -5481,31 +5482,31 @@ net/ipv4/inet_connection_sock.c net/ipv4/inet_diag.c net/ipv4/inet_fragment.c net/ipv4/inet_hashtables.c -net/ipv4/inet_timewait_sock.c net/ipv4/inetpeer.c +net/ipv4/inet_timewait_sock.c net/ipv4/ip_forward.c net/ipv4/ip_fragment.c net/ipv4/ip_gre.c net/ipv4/ip_input.c +net/ipv4/ipip.c net/ipv4/ip_options.c net/ipv4/ip_output.c net/ipv4/ip_sockglue.c net/ipv4/ip_tunnel.c net/ipv4/ip_tunnel_core.c net/ipv4/ip_vti.c -net/ipv4/ipip.c net/ipv4/metrics.c -net/ipv4/netfilter.c +net/ipv4/netfilter/arptable_filter.c net/ipv4/netfilter/arp_tables.c net/ipv4/netfilter/arpt_mangle.c -net/ipv4/netfilter/arptable_filter.c -net/ipv4/netfilter/ip_tables.c -net/ipv4/netfilter/ipt_REJECT.c +net/ipv4/netfilter.c net/ipv4/netfilter/iptable_filter.c net/ipv4/netfilter/iptable_mangle.c net/ipv4/netfilter/iptable_nat.c net/ipv4/netfilter/iptable_raw.c +net/ipv4/netfilter/ip_tables.c net/ipv4/netfilter/iptable_security.c +net/ipv4/netfilter/ipt_REJECT.c net/ipv4/netfilter/nf_defrag_ipv4.c net/ipv4/netfilter/nf_dup_ipv4.c net/ipv4/netfilter/nf_nat_h323.c @@ -5522,8 +5523,8 @@ net/ipv4/raw.c net/ipv4/route.c net/ipv4/syncookies.c net/ipv4/sysctl_net_ipv4.c -net/ipv4/tcp.c net/ipv4/tcp_bpf.c +net/ipv4/tcp.c net/ipv4/tcp_cong.c net/ipv4/tcp_cubic.c net/ipv4/tcp_diag.c @@ -5539,15 +5540,15 @@ net/ipv4/tcp_recovery.c net/ipv4/tcp_timer.c net/ipv4/tcp_ulp.c net/ipv4/tunnel4.c -net/ipv4/udp.c net/ipv4/udp_bpf.c +net/ipv4/udp.c net/ipv4/udp_diag.c net/ipv4/udp_impl.h +net/ipv4/udplite.c net/ipv4/udp_offload.c net/ipv4/udp_tunnel_core.c net/ipv4/udp_tunnel_nic.c net/ipv4/udp_tunnel_stub.c -net/ipv4/udplite.c net/ipv4/xfrm4_input.c net/ipv4/xfrm4_output.c net/ipv4/xfrm4_policy.c @@ -5588,12 +5589,12 @@ net/ipv6/mcast_snoop.c net/ipv6/mip6.c net/ipv6/ndisc.c net/ipv6/netfilter.c -net/ipv6/netfilter/ip6_tables.c -net/ipv6/netfilter/ip6t_REJECT.c -net/ipv6/netfilter/ip6t_rpfilter.c net/ipv6/netfilter/ip6table_filter.c net/ipv6/netfilter/ip6table_mangle.c net/ipv6/netfilter/ip6table_raw.c +net/ipv6/netfilter/ip6_tables.c +net/ipv6/netfilter/ip6t_REJECT.c +net/ipv6/netfilter/ip6t_rpfilter.c net/ipv6/netfilter/nf_conntrack_reasm.c net/ipv6/netfilter/nf_defrag_ipv6_hooks.c net/ipv6/netfilter/nf_dup_ipv6.c @@ -5617,8 +5618,8 @@ net/ipv6/tcpv6_offload.c net/ipv6/tunnel6.c net/ipv6/udp.c net/ipv6/udp_impl.h -net/ipv6/udp_offload.c net/ipv6/udplite.c +net/ipv6/udp_offload.c net/ipv6/xfrm6_input.c net/ipv6/xfrm6_output.c net/ipv6/xfrm6_policy.c @@ -5690,59 +5691,59 @@ net/netfilter/nf_nat_masquerade.c net/netfilter/nf_nat_proto.c net/netfilter/nf_nat_redirect.c net/netfilter/nf_nat_tftp.c -net/netfilter/nf_queue.c -net/netfilter/nf_sockopt.c net/netfilter/nfnetlink.c net/netfilter/nfnetlink_log.c net/netfilter/nfnetlink_queue.c +net/netfilter/nf_queue.c +net/netfilter/nf_sockopt.c net/netfilter/utils.c net/netfilter/x_tables.c -net/netfilter/xt_CLASSIFY.c -net/netfilter/xt_CONNSECMARK.c -net/netfilter/xt_CT.c -net/netfilter/xt_DSCP.c -net/netfilter/xt_IDLETIMER.c -net/netfilter/xt_MASQUERADE.c -net/netfilter/xt_NETMAP.c -net/netfilter/xt_NFLOG.c -net/netfilter/xt_NFQUEUE.c -net/netfilter/xt_REDIRECT.c -net/netfilter/xt_SECMARK.c -net/netfilter/xt_TCPMSS.c -net/netfilter/xt_TEE.c -net/netfilter/xt_TPROXY.c -net/netfilter/xt_TRACE.c net/netfilter/xt_bpf.c +net/netfilter/xt_CLASSIFY.c net/netfilter/xt_comment.c net/netfilter/xt_connlimit.c net/netfilter/xt_connmark.c +net/netfilter/xt_CONNSECMARK.c net/netfilter/xt_conntrack.c +net/netfilter/xt_CT.c net/netfilter/xt_dscp.c +net/netfilter/xt_DSCP.c net/netfilter/xt_ecn.c net/netfilter/xt_esp.c net/netfilter/xt_hashlimit.c net/netfilter/xt_helper.c net/netfilter/xt_hl.c +net/netfilter/xt_IDLETIMER.c net/netfilter/xt_iprange.c net/netfilter/xt_l2tp.c net/netfilter/xt_length.c net/netfilter/xt_limit.c net/netfilter/xt_mac.c net/netfilter/xt_mark.c +net/netfilter/xt_MASQUERADE.c net/netfilter/xt_multiport.c net/netfilter/xt_nat.c +net/netfilter/xt_NETMAP.c +net/netfilter/xt_NFLOG.c +net/netfilter/xt_NFQUEUE.c net/netfilter/xt_owner.c net/netfilter/xt_pkttype.c net/netfilter/xt_policy.c -net/netfilter/xt_quota.c net/netfilter/xt_quota2.c +net/netfilter/xt_quota.c +net/netfilter/xt_REDIRECT.c net/netfilter/xt_repldata.h +net/netfilter/xt_SECMARK.c net/netfilter/xt_socket.c net/netfilter/xt_state.c net/netfilter/xt_statistic.c net/netfilter/xt_string.c +net/netfilter/xt_TCPMSS.c net/netfilter/xt_tcpudp.c +net/netfilter/xt_TEE.c net/netfilter/xt_time.c +net/netfilter/xt_TPROXY.c +net/netfilter/xt_TRACE.c net/netfilter/xt_u32.c net/netlink/af_netlink.c net/netlink/af_netlink.h @@ -5750,9 +5751,9 @@ net/netlink/genetlink.c net/netlink/policy.c net/nfc/af_nfc.c net/nfc/core.c -net/nfc/llcp.h net/nfc/llcp_commands.c net/nfc/llcp_core.c +net/nfc/llcp.h net/nfc/llcp_sock.c net/nfc/netlink.c net/nfc/nfc.h @@ -5774,12 +5775,12 @@ net/sched/cls_flow.c net/sched/cls_fw.c net/sched/cls_matchall.c net/sched/cls_u32.c +net/sched/ematch.c net/sched/em_cmp.c net/sched/em_meta.c net/sched/em_nbyte.c net/sched/em_text.c net/sched/em_u32.c -net/sched/ematch.c net/sched/sch_api.c net/sched/sch_blackhole.c net/sched/sch_codel.c @@ -5827,8 +5828,8 @@ net/tipc/name_table.h net/tipc/net.c net/tipc/net.h net/tipc/netlink.c -net/tipc/netlink.h net/tipc/netlink_compat.c +net/tipc/netlink.h net/tipc/node.c net/tipc/node.h net/tipc/socket.c @@ -5860,12 +5861,12 @@ net/wireless/wext-proc.c net/wireless/wext-spy.c net/xdp/xdp_umem.c net/xdp/xdp_umem.h +net/xdp/xsk_buff_pool.c net/xdp/xsk.c net/xdp/xsk.h -net/xdp/xsk_buff_pool.c +net/xdp/xskmap.c net/xdp/xsk_queue.c net/xdp/xsk_queue.h -net/xdp/xskmap.c net/xfrm/xfrm_algo.c net/xfrm/xfrm_device.c net/xfrm/xfrm_hash.c @@ -5890,18 +5891,18 @@ scripts/dtc/dtc.h scripts/dtc/fdtoverlay.c scripts/dtc/flattree.c scripts/dtc/fstree.c -scripts/dtc/libfdt/fdt.c -scripts/dtc/libfdt/fdt.h scripts/dtc/libfdt/fdt_addresses.c +scripts/dtc/libfdt/fdt.c scripts/dtc/libfdt/fdt_empty_tree.c +scripts/dtc/libfdt/fdt.h scripts/dtc/libfdt/fdt_overlay.c scripts/dtc/libfdt/fdt_ro.c scripts/dtc/libfdt/fdt_rw.c scripts/dtc/libfdt/fdt_strerror.c scripts/dtc/libfdt/fdt_sw.c scripts/dtc/libfdt/fdt_wip.c -scripts/dtc/libfdt/libfdt.h scripts/dtc/libfdt/libfdt_env.h +scripts/dtc/libfdt/libfdt.h scripts/dtc/libfdt/libfdt_internal.h scripts/dtc/livetree.c scripts/dtc/srcpos.c @@ -5945,8 +5946,8 @@ security/commoncap.c security/device_cgroup.c security/inode.c security/integrity/iint.c -security/integrity/integrity.h security/integrity/integrity_audit.c +security/integrity/integrity.h security/keys/compat.c security/keys/gc.c security/keys/internal.h @@ -5957,8 +5958,8 @@ security/keys/keyring.c security/keys/permission.c security/keys/proc.c security/keys/process_keys.c -security/keys/request_key.c security/keys/request_key_auth.c +security/keys/request_key.c security/keys/sysctl.c security/keys/user_defined.c security/lsm_audit.c @@ -6085,9 +6086,9 @@ sound/usb/mixer_quirks.h sound/usb/mixer_s1810c.c sound/usb/mixer_s1810c.h sound/usb/mixer_scarlett.c -sound/usb/mixer_scarlett.h sound/usb/mixer_scarlett_gen2.c sound/usb/mixer_scarlett_gen2.h +sound/usb/mixer_scarlett.h sound/usb/mixer_us16x08.c sound/usb/mixer_us16x08.h sound/usb/pcm.c @@ -6096,9 +6097,9 @@ sound/usb/power.c sound/usb/power.h sound/usb/proc.c sound/usb/proc.h -sound/usb/quirks-table.h sound/usb/quirks.c sound/usb/quirks.h +sound/usb/quirks-table.h sound/usb/stream.c sound/usb/stream.h sound/usb/usbaudio.h diff --git a/fs/btrfs/block-group.c b/fs/btrfs/block-group.c index a76796f153d5..d24cef671c1a 100644 --- a/fs/btrfs/block-group.c +++ b/fs/btrfs/block-group.c @@ -78,14 +78,21 @@ static u64 btrfs_reduce_alloc_profile(struct btrfs_fs_info *fs_info, u64 flags) } allowed &= flags; - if (allowed & BTRFS_BLOCK_GROUP_RAID6) + /* Select the highest-redundancy RAID level. */ + if (allowed & BTRFS_BLOCK_GROUP_RAID1C4) + allowed = BTRFS_BLOCK_GROUP_RAID1C4; + else if (allowed & BTRFS_BLOCK_GROUP_RAID6) allowed = BTRFS_BLOCK_GROUP_RAID6; + else if (allowed & BTRFS_BLOCK_GROUP_RAID1C3) + allowed = BTRFS_BLOCK_GROUP_RAID1C3; else if (allowed & BTRFS_BLOCK_GROUP_RAID5) allowed = BTRFS_BLOCK_GROUP_RAID5; else if (allowed & BTRFS_BLOCK_GROUP_RAID10) allowed = BTRFS_BLOCK_GROUP_RAID10; else if (allowed & BTRFS_BLOCK_GROUP_RAID1) allowed = BTRFS_BLOCK_GROUP_RAID1; + else if (allowed & BTRFS_BLOCK_GROUP_DUP) + allowed = BTRFS_BLOCK_GROUP_DUP; else if (allowed & BTRFS_BLOCK_GROUP_RAID0) allowed = BTRFS_BLOCK_GROUP_RAID0; @@ -1534,8 +1541,15 @@ void btrfs_reclaim_bgs_work(struct work_struct *work) } spin_unlock(&bg->lock); - /* Get out fast, in case we're unmounting the filesystem */ - if (btrfs_fs_closing(fs_info)) { + /* + * Get out fast, in case we're read-only or unmounting the + * filesystem. It is OK to drop block groups from the list even + * for the read-only case. As we did sb_start_write(), + * "mount -o remount,ro" won't happen and read-only filesystem + * means it is forced read-only due to a fatal error. So, it + * never gets back to read-write to let us reclaim again. + */ + if (btrfs_need_cleaner_sleep(fs_info)) { up_write(&space_info->groups_sem); goto next; } @@ -1566,11 +1580,27 @@ void btrfs_reclaim_bgs_work(struct work_struct *work) } next: + if (ret) + btrfs_mark_bg_to_reclaim(bg); btrfs_put_block_group(bg); + + mutex_unlock(&fs_info->reclaim_bgs_lock); + /* + * Reclaiming all the block groups in the list can take really + * long. Prioritize cleaning up unused block groups. + */ + btrfs_delete_unused_bgs(fs_info); + /* + * If we are interrupted by a balance, we can just bail out. The + * cleaner thread restart again if necessary. + */ + if (!mutex_trylock(&fs_info->reclaim_bgs_lock)) + goto end; spin_lock(&fs_info->unused_bgs_lock); } spin_unlock(&fs_info->unused_bgs_lock); mutex_unlock(&fs_info->reclaim_bgs_lock); +end: btrfs_exclop_finish(fs_info); sb_end_write(fs_info->sb); } @@ -1825,6 +1855,7 @@ static int exclude_super_stripes(struct btrfs_block_group *cache) /* Shouldn't have super stripes in sequential zones */ if (zoned && nr) { + kfree(logical); btrfs_err(fs_info, "zoned: block group %llu must not contain super block", cache->start); diff --git a/fs/btrfs/ctree.c b/fs/btrfs/ctree.c index 1a19354382b2..a648dff2bece 100644 --- a/fs/btrfs/ctree.c +++ b/fs/btrfs/ctree.c @@ -457,9 +457,14 @@ static noinline int __btrfs_cow_block(struct btrfs_trans_handle *trans, btrfs_header_backref_rev(buf) < BTRFS_MIXED_BACKREF_REV) parent_start = buf->start; - atomic_inc(&cow->refs); ret = btrfs_tree_mod_log_insert_root(root->node, cow, true); - BUG_ON(ret < 0); + if (ret < 0) { + btrfs_tree_unlock(cow); + free_extent_buffer(cow); + btrfs_abort_transaction(trans, ret); + return ret; + } + atomic_inc(&cow->refs); rcu_assign_pointer(root->node, cow); btrfs_free_tree_block(trans, btrfs_root_id(root), buf, @@ -912,7 +917,12 @@ static noinline int balance_level(struct btrfs_trans_handle *trans, } ret = btrfs_tree_mod_log_insert_root(root->node, child, true); - BUG_ON(ret < 0); + if (ret < 0) { + btrfs_tree_unlock(child); + free_extent_buffer(child); + btrfs_abort_transaction(trans, ret); + goto enospc; + } rcu_assign_pointer(root->node, child); add_root_to_dirty_list(root); @@ -994,7 +1004,10 @@ static noinline int balance_level(struct btrfs_trans_handle *trans, btrfs_node_key(right, &right_key, 0); ret = btrfs_tree_mod_log_insert_key(parent, pslot + 1, BTRFS_MOD_LOG_KEY_REPLACE, GFP_NOFS); - BUG_ON(ret < 0); + if (ret < 0) { + btrfs_abort_transaction(trans, ret); + goto enospc; + } btrfs_set_node_key(parent, &right_key, pslot + 1); btrfs_mark_buffer_dirty(parent); } @@ -1040,7 +1053,10 @@ static noinline int balance_level(struct btrfs_trans_handle *trans, btrfs_node_key(mid, &mid_key, 0); ret = btrfs_tree_mod_log_insert_key(parent, pslot, BTRFS_MOD_LOG_KEY_REPLACE, GFP_NOFS); - BUG_ON(ret < 0); + if (ret < 0) { + btrfs_abort_transaction(trans, ret); + goto enospc; + } btrfs_set_node_key(parent, &mid_key, pslot); btrfs_mark_buffer_dirty(parent); } @@ -2626,6 +2642,8 @@ static noinline int split_node(struct btrfs_trans_handle *trans, ret = btrfs_tree_mod_log_eb_copy(split, c, 0, mid, c_nritems - mid); if (ret) { + btrfs_tree_unlock(split); + free_extent_buffer(split); btrfs_abort_transaction(trans, ret); return ret; } diff --git a/fs/btrfs/qgroup.c b/fs/btrfs/qgroup.c index 26110d9587cd..d408d1dfde7c 100644 --- a/fs/btrfs/qgroup.c +++ b/fs/btrfs/qgroup.c @@ -1269,7 +1269,9 @@ int btrfs_quota_disable(struct btrfs_fs_info *fs_info) goto out; } + spin_lock(&fs_info->trans_lock); list_del("a_root->dirty_list); + spin_unlock(&fs_info->trans_lock); btrfs_tree_lock(quota_root->node); btrfs_clean_tree_block(quota_root->node); @@ -4340,4 +4342,5 @@ void btrfs_qgroup_destroy_extent_records(struct btrfs_transaction *trans) ulist_free(entry->old_roots); kfree(entry); } + *root = RB_ROOT; } diff --git a/fs/ceph/caps.c b/fs/ceph/caps.c index 6ff3aaebaf93..ca92f2d2f3c7 100644 --- a/fs/ceph/caps.c +++ b/fs/ceph/caps.c @@ -3517,6 +3517,15 @@ static void handle_cap_grant(struct inode *inode, } BUG_ON(cap->issued & ~cap->implemented); + /* don't let check_caps skip sending a response to MDS for revoke msgs */ + if (le32_to_cpu(grant->op) == CEPH_CAP_OP_REVOKE) { + cap->mds_wanted = 0; + if (cap == ci->i_auth_cap) + check_caps = 1; /* check auth cap only */ + else + check_caps = 2; /* check all caps */ + } + if (extra_info->inline_version > 0 && extra_info->inline_version >= ci->i_inline_version) { ci->i_inline_version = extra_info->inline_version; diff --git a/fs/cifs/file.c b/fs/cifs/file.c index 87324f1c262c..64bd1cc00b97 100644 --- a/fs/cifs/file.c +++ b/fs/cifs/file.c @@ -4924,20 +4924,19 @@ oplock_break_ack: _cifsFileInfo_put(cfile, false /* do not wait for ourself */, false); /* - * releasing stale oplock after recent reconnect of smb session using - * a now incorrect file handle is not a data integrity issue but do - * not bother sending an oplock release if session to server still is - * disconnected since oplock already released by the server + * MS-SMB2 3.2.5.19.1 and 3.2.5.19.2 (and MS-CIFS 3.2.5.42) do not require + * an acknowledgment to be sent when the file has already been closed. + * check for server null, since can race with kill_sb calling tree disconnect. */ - if (!oplock_break_cancelled) { - /* check for server null since can race with kill_sb calling tree disconnect */ - if (tcon->ses && tcon->ses->server) { - rc = tcon->ses->server->ops->oplock_response(tcon, persistent_fid, - volatile_fid, net_fid, cinode); - cifs_dbg(FYI, "Oplock release rc = %d\n", rc); - } else - pr_warn_once("lease break not sent for unmounted share\n"); - } + spin_lock(&cinode->open_file_lock); + if (tcon->ses && tcon->ses->server && !oplock_break_cancelled && + !list_empty(&cinode->openFileList)) { + spin_unlock(&cinode->open_file_lock); + rc = tcon->ses->server->ops->oplock_response(tcon, persistent_fid, + volatile_fid, net_fid, cinode); + cifs_dbg(FYI, "Oplock release rc = %d\n", rc); + } else + spin_unlock(&cinode->open_file_lock); cifs_done_oplock_break(cinode); } diff --git a/fs/dlm/plock.c b/fs/dlm/plock.c index a10d2bcfe75a..edce0b25cd90 100644 --- a/fs/dlm/plock.c +++ b/fs/dlm/plock.c @@ -363,7 +363,9 @@ int dlm_posix_get(dlm_lockspace_t *lockspace, u64 number, struct file *file, locks_init_lock(fl); fl->fl_type = (op->info.ex) ? F_WRLCK : F_RDLCK; fl->fl_flags = FL_POSIX; - fl->fl_pid = -op->info.pid; + fl->fl_pid = op->info.pid; + if (op->info.nodeid != dlm_our_nodeid()) + fl->fl_pid = -fl->fl_pid; fl->fl_start = op->info.start; fl->fl_end = op->info.end; rv = 0; diff --git a/fs/erofs/inode.c b/fs/erofs/inode.c index 3ff36514cff2..638bb70d0d65 100644 --- a/fs/erofs/inode.c +++ b/fs/erofs/inode.c @@ -193,7 +193,8 @@ static struct page *erofs_read_inode(struct inode *inode, inode->i_flags &= ~S_DAX; if (test_opt(&sbi->opt, DAX_ALWAYS) && S_ISREG(inode->i_mode) && - vi->datalayout == EROFS_INODE_FLAT_PLAIN) + (vi->datalayout == EROFS_INODE_FLAT_PLAIN || + vi->datalayout == EROFS_INODE_CHUNK_BASED)) inode->i_flags |= S_DAX; if (!nblks) /* measure inode.i_blocks as generic filesystems */ diff --git a/fs/erofs/zdata.c b/fs/erofs/zdata.c index 6b5bb7ce46ee..17994634c32d 100644 --- a/fs/erofs/zdata.c +++ b/fs/erofs/zdata.c @@ -825,7 +825,7 @@ hitted: tight &= (clt->mode >= COLLECT_PRIMARY_HOOKED && clt->mode != COLLECT_PRIMARY_FOLLOWED_NOINPLACE); - cur = end - min_t(unsigned int, offset + end - map->m_la, end); + cur = end - min_t(erofs_off_t, offset + end - map->m_la, end); if (!(map->m_flags & EROFS_MAP_MAPPED)) { zero_user_segment(page, cur, end); goto next_part; diff --git a/fs/erofs/zmap.c b/fs/erofs/zmap.c index f933f76a01d5..68c76744dc84 100644 --- a/fs/erofs/zmap.c +++ b/fs/erofs/zmap.c @@ -257,7 +257,7 @@ static int unpack_compacted_index(struct z_erofs_maprecorder *m, u8 *in, type; bool big_pcluster; - if (1 << amortizedshift == 4) + if (1 << amortizedshift == 4 && lclusterbits <= 14) vcnt = 2; else if (1 << amortizedshift == 2 && lclusterbits == 12) vcnt = 16; @@ -355,7 +355,6 @@ static int compacted_load_cluster_from_disk(struct z_erofs_maprecorder *m, { struct inode *const inode = m->inode; struct erofs_inode *const vi = EROFS_I(inode); - const unsigned int lclusterbits = vi->z_logical_clusterbits; const erofs_off_t ebase = ALIGN(iloc(EROFS_I_SB(inode), vi->nid) + vi->inode_isize + vi->xattr_isize, 8) + sizeof(struct z_erofs_map_header); @@ -365,9 +364,6 @@ static int compacted_load_cluster_from_disk(struct z_erofs_maprecorder *m, erofs_off_t pos; int err; - if (lclusterbits != 12) - return -EOPNOTSUPP; - if (lcn >= totalidx) return -EINVAL; diff --git a/fs/exec.c b/fs/exec.c index 3ce0c7480335..3463516f7c64 100644 --- a/fs/exec.c +++ b/fs/exec.c @@ -761,6 +761,7 @@ int setup_arg_pages(struct linux_binprm *bprm, unsigned long stack_size; unsigned long stack_expand; unsigned long rlim_stack; + struct mmu_gather tlb; #ifdef CONFIG_STACK_GROWSUP /* Limit stack size */ @@ -815,8 +816,11 @@ int setup_arg_pages(struct linux_binprm *bprm, vm_flags |= mm->def_flags; vm_flags |= VM_STACK_INCOMPLETE_SETUP; - ret = mprotect_fixup(vma, &prev, vma->vm_start, vma->vm_end, + tlb_gather_mmu(&tlb, mm); + ret = mprotect_fixup(&tlb, vma, &prev, vma->vm_start, vma->vm_end, vm_flags); + tlb_finish_mmu(&tlb); + if (ret) goto out_unlock; BUG_ON(prev != vma); diff --git a/fs/exfat/dir.c b/fs/exfat/dir.c index 3940a56902dd..2080eb92f0a9 100644 --- a/fs/exfat/dir.c +++ b/fs/exfat/dir.c @@ -34,6 +34,7 @@ static void exfat_get_uniname_from_ext_entry(struct super_block *sb, { int i; struct exfat_entry_set_cache *es; + unsigned int uni_len = 0, len; es = exfat_get_dentry_set(sb, p_dir, entry, ES_ALL_ENTRIES); if (!es) @@ -52,7 +53,10 @@ static void exfat_get_uniname_from_ext_entry(struct super_block *sb, if (exfat_get_entry_type(ep) != TYPE_EXTEND) break; - exfat_extract_uni_name(ep, uniname); + len = exfat_extract_uni_name(ep, uniname); + uni_len += len; + if (len != EXFAT_FILE_NAME_LEN || uni_len >= MAX_NAME_LENGTH) + break; uniname += EXFAT_FILE_NAME_LEN; } @@ -1035,7 +1039,8 @@ rewind: if (entry_type == TYPE_EXTEND) { unsigned short entry_uniname[16], unichar; - if (step != DIRENT_STEP_NAME) { + if (step != DIRENT_STEP_NAME || + name_len >= MAX_NAME_LENGTH) { step = DIRENT_STEP_FILE; continue; } diff --git a/fs/ext4/indirect.c b/fs/ext4/indirect.c index 9813cc4b7b2a..d795ccef0417 100644 --- a/fs/ext4/indirect.c +++ b/fs/ext4/indirect.c @@ -651,6 +651,14 @@ int ext4_ind_map_blocks(handle_t *handle, struct inode *inode, ext4_update_inode_fsync_trans(handle, inode, 1); count = ar.len; + + /* + * Update reserved blocks/metadata blocks after successful block + * allocation which had been deferred till now. + */ + if (flags & EXT4_GET_BLOCKS_DELALLOC_RESERVE) + ext4_da_update_reserve_space(inode, count, 1); + got_it: map->m_flags |= EXT4_MAP_MAPPED; map->m_pblk = le32_to_cpu(chain[depth-1].key); diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index 004676f8723d..25205610fef9 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c @@ -655,16 +655,6 @@ found: */ ext4_clear_inode_state(inode, EXT4_STATE_EXT_MIGRATE); } - - /* - * Update reserved blocks/metadata blocks after successful - * block allocation which had been deferred till now. We don't - * support fallocate for non extent files. So we can update - * reserve space here. - */ - if ((retval > 0) && - (flags & EXT4_GET_BLOCKS_DELALLOC_RESERVE)) - ext4_da_update_reserve_space(inode, retval, 1); } if (retval > 0) { diff --git a/fs/ext4/ioctl.c b/fs/ext4/ioctl.c index 47ec00cfb445..18002b0a908c 100644 --- a/fs/ext4/ioctl.c +++ b/fs/ext4/ioctl.c @@ -559,6 +559,7 @@ static int ext4_shutdown(struct super_block *sb, unsigned long arg) { struct ext4_sb_info *sbi = EXT4_SB(sb); __u32 flags; + int ret; if (!capable(CAP_SYS_ADMIN)) return -EPERM; @@ -577,7 +578,9 @@ static int ext4_shutdown(struct super_block *sb, unsigned long arg) switch (flags) { case EXT4_GOING_FLAGS_DEFAULT: - freeze_bdev(sb->s_bdev); + ret = freeze_bdev(sb->s_bdev); + if (ret) + return ret; set_bit(EXT4_FLAGS_SHUTDOWN, &sbi->s_ext4_flags); thaw_bdev(sb->s_bdev); break; diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c index e8f5f05bddb3..47c28e3582fd 100644 --- a/fs/ext4/mballoc.c +++ b/fs/ext4/mballoc.c @@ -6086,8 +6086,8 @@ do_more: * them with group lock_held */ if (test_opt(sb, DISCARD)) { - err = ext4_issue_discard(sb, block_group, bit, count, - NULL); + err = ext4_issue_discard(sb, block_group, bit, + count_clusters, NULL); if (err && err != -EOPNOTSUPP) ext4_msg(sb, KERN_WARNING, "discard request in" " group:%u block:%d count:%lu failed" @@ -6171,12 +6171,6 @@ void ext4_free_blocks(handle_t *handle, struct inode *inode, sbi = EXT4_SB(sb); - if (sbi->s_mount_state & EXT4_FC_REPLAY) { - ext4_free_blocks_simple(inode, block, count); - return; - } - - might_sleep(); if (bh) { if (block) BUG_ON(block != bh->b_blocknr); @@ -6184,6 +6178,13 @@ void ext4_free_blocks(handle_t *handle, struct inode *inode, block = bh->b_blocknr; } + if (sbi->s_mount_state & EXT4_FC_REPLAY) { + ext4_free_blocks_simple(inode, block, EXT4_NUM_B2C(sbi, count)); + return; + } + + might_sleep(); + if (!(flags & EXT4_FREE_BLOCKS_VALIDATED) && !ext4_inode_block_valid(inode, block, count)) { ext4_error(sb, "Freeing blocks not in datazone - " diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c index b87269bae4fb..2629e90f8dbb 100644 --- a/fs/ext4/namei.c +++ b/fs/ext4/namei.c @@ -3848,19 +3848,10 @@ static int ext4_rename(struct user_namespace *mnt_userns, struct inode *old_dir, return retval; } - /* - * We need to protect against old.inode directory getting converted - * from inline directory format into a normal one. - */ - if (S_ISDIR(old.inode->i_mode)) - inode_lock_nested(old.inode, I_MUTEX_NONDIR2); - old.bh = ext4_find_entry(old.dir, &old.dentry->d_name, &old.de, &old.inlined); - if (IS_ERR(old.bh)) { - retval = PTR_ERR(old.bh); - goto unlock_moved_dir; - } + if (IS_ERR(old.bh)) + return PTR_ERR(old.bh); /* * Check for inode number is _not_ due to possible IO errors. @@ -4050,10 +4041,6 @@ release_bh: brelse(old.bh); brelse(new.bh); -unlock_moved_dir: - if (S_ISDIR(old.inode->i_mode)) - inode_unlock(old.inode); - return retval; } diff --git a/fs/ext4/super.c b/fs/ext4/super.c index 32c051f00f2f..6ea943422475 100644 --- a/fs/ext4/super.c +++ b/fs/ext4/super.c @@ -1097,6 +1097,12 @@ static void ext4_blkdev_remove(struct ext4_sb_info *sbi) struct block_device *bdev; bdev = sbi->s_journal_bdev; if (bdev) { + /* + * Invalidate the journal device's buffers. We don't want them + * floating about in memory - the physical journal device may + * hotswapped, and it breaks the `ro-after' testing code. + */ + invalidate_bdev(bdev); ext4_blkdev_put(bdev); sbi->s_journal_bdev = NULL; } @@ -1239,13 +1245,7 @@ static void ext4_put_super(struct super_block *sb) sync_blockdev(sb->s_bdev); invalidate_bdev(sb->s_bdev); if (sbi->s_journal_bdev && sbi->s_journal_bdev != sb->s_bdev) { - /* - * Invalidate the journal device's buffers. We don't want them - * floating about in memory - the physical journal device may - * hotswapped, and it breaks the `ro-after' testing code. - */ sync_blockdev(sbi->s_journal_bdev); - invalidate_bdev(sbi->s_journal_bdev); ext4_blkdev_remove(sbi); } @@ -4976,7 +4976,7 @@ no_journal: ext4_msg(sb, KERN_INFO, "recovery complete"); err = ext4_mark_recovery_complete(sb, es); if (err) - goto failed_mount9; + goto failed_mount10; } if (EXT4_SB(sb)->s_journal) { if (test_opt(sb, DATA_FLAGS) == EXT4_MOUNT_JOURNAL_DATA) @@ -5022,7 +5022,9 @@ cantfind_ext4: ext4_msg(sb, KERN_ERR, "VFS: Can't find ext4 filesystem"); goto failed_mount; -failed_mount9: +failed_mount10: + ext4_quota_off_umount(sb); +failed_mount9: __maybe_unused ext4_release_orphan_info(sb); failed_mount8: ext4_unregister_sysfs(sb); @@ -5099,6 +5101,7 @@ failed_mount: brelse(bh); ext4_blkdev_remove(sbi); out_fail: + invalidate_bdev(sb->s_bdev); sb->s_fs_info = NULL; kfree(sbi->s_blockgroup_lock); out_free_base: diff --git a/fs/ext4/xattr.c b/fs/ext4/xattr.c index 6c982869f101..f79705af3aca 100644 --- a/fs/ext4/xattr.c +++ b/fs/ext4/xattr.c @@ -1732,6 +1732,20 @@ static int ext4_xattr_set_entry(struct ext4_xattr_info *i, memmove(here, (void *)here + size, (void *)last - (void *)here + sizeof(__u32)); memset(last, 0, size); + + /* + * Update i_inline_off - moved ibody region might contain + * system.data attribute. Handling a failure here won't + * cause other complications for setting an xattr. + */ + if (!is_block && ext4_has_inline_data(inode)) { + ret = ext4_find_inline_data_nolock(inode); + if (ret) { + ext4_warning_inode(inode, + "unable to update i_inline_off"); + goto out; + } + } } else if (s->not_found) { /* Insert new name. */ size_t size = EXT4_XATTR_LEN(name_len); diff --git a/fs/f2fs/checkpoint.c b/fs/f2fs/checkpoint.c index 71fd73facb6e..22d215d8bac7 100644 --- a/fs/f2fs/checkpoint.c +++ b/fs/f2fs/checkpoint.c @@ -1022,9 +1022,7 @@ static void __add_dirty_inode(struct inode *inode, enum inode_type type) return; set_inode_flag(inode, flag); - if (!f2fs_is_volatile_file(inode)) - list_add_tail(&F2FS_I(inode)->dirty_list, - &sbi->inode_list[type]); + list_add_tail(&F2FS_I(inode)->dirty_list, &sbi->inode_list[type]); stat_inc_dirty_inode(sbi, type); } diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c index 70b8bf024871..0e70d861ea52 100644 --- a/fs/f2fs/data.c +++ b/fs/f2fs/data.c @@ -71,8 +71,7 @@ static bool __is_cp_guaranteed(struct page *page) if (f2fs_is_compressed_page(page)) return false; - if ((S_ISREG(inode->i_mode) && - (f2fs_is_atomic_file(inode) || IS_NOQUOTA(inode))) || + if ((S_ISREG(inode->i_mode) && IS_NOQUOTA(inode)) || page_private_gcing(page)) return true; return false; @@ -2604,7 +2603,12 @@ int f2fs_do_write_data_page(struct f2fs_io_info *fio) bool ipu_force = false; int err = 0; - set_new_dnode(&dn, inode, NULL, NULL, 0); + /* Use COW inode to make dnode_of_data for atomic write */ + if (f2fs_is_atomic_file(inode)) + set_new_dnode(&dn, F2FS_I(inode)->cow_inode, NULL, NULL, 0); + else + set_new_dnode(&dn, inode, NULL, NULL, 0); + if (need_inplace_update(fio) && f2fs_lookup_extent_cache(inode, page->index, &ei)) { fio->old_blkaddr = ei.blk + page->index - ei.fofs; @@ -2641,6 +2645,7 @@ got_it: err = -EFSCORRUPTED; goto out_writepage; } + /* * If current allocation needs SSR, * it had better in-place writes for updated data. @@ -2779,11 +2784,6 @@ int f2fs_write_single_data_page(struct page *page, int *submitted, write: if (f2fs_is_drop_cache(inode)) goto out; - /* we should not write 0'th page having journal header */ - if (f2fs_is_volatile_file(inode) && (!page->index || - (!wbc->for_reclaim && - f2fs_available_free_memory(sbi, BASE_CHECK)))) - goto redirty_out; /* Dentry/quota blocks are controlled by checkpoint */ if (S_ISDIR(inode->i_mode) || IS_NOQUOTA(inode)) { @@ -3357,6 +3357,106 @@ unlock_out: return err; } +static int __find_data_block(struct inode *inode, pgoff_t index, + block_t *blk_addr) +{ + struct dnode_of_data dn; + struct page *ipage; + struct extent_info ei = {0, }; + int err = 0; + + ipage = f2fs_get_node_page(F2FS_I_SB(inode), inode->i_ino); + if (IS_ERR(ipage)) + return PTR_ERR(ipage); + + set_new_dnode(&dn, inode, ipage, ipage, 0); + + if (f2fs_lookup_extent_cache(inode, index, &ei)) { + dn.data_blkaddr = ei.blk + index - ei.fofs; + } else { + /* hole case */ + err = f2fs_get_dnode_of_data(&dn, index, LOOKUP_NODE); + if (err) { + dn.data_blkaddr = NULL_ADDR; + err = 0; + } + } + *blk_addr = dn.data_blkaddr; + f2fs_put_dnode(&dn); + return err; +} + +static int __reserve_data_block(struct inode *inode, pgoff_t index, + block_t *blk_addr, bool *node_changed) +{ + struct f2fs_sb_info *sbi = F2FS_I_SB(inode); + struct dnode_of_data dn; + struct page *ipage; + int err = 0; + + f2fs_do_map_lock(sbi, F2FS_GET_BLOCK_PRE_AIO, true); + + ipage = f2fs_get_node_page(sbi, inode->i_ino); + if (IS_ERR(ipage)) { + err = PTR_ERR(ipage); + goto unlock_out; + } + set_new_dnode(&dn, inode, ipage, ipage, 0); + + err = f2fs_get_block(&dn, index); + + *blk_addr = dn.data_blkaddr; + *node_changed = dn.node_changed; + f2fs_put_dnode(&dn); + +unlock_out: + f2fs_do_map_lock(sbi, F2FS_GET_BLOCK_PRE_AIO, false); + return err; +} + +static int prepare_atomic_write_begin(struct f2fs_sb_info *sbi, + struct page *page, loff_t pos, unsigned int len, + block_t *blk_addr, bool *node_changed, bool *use_cow) +{ + struct inode *inode = page->mapping->host; + struct inode *cow_inode = F2FS_I(inode)->cow_inode; + pgoff_t index = page->index; + int err = 0; + block_t ori_blk_addr = NULL_ADDR; + + /* If pos is beyond the end of file, reserve a new block in COW inode */ + if ((pos & PAGE_MASK) >= i_size_read(inode)) + goto reserve_block; + + /* Look for the block in COW inode first */ + err = __find_data_block(cow_inode, index, blk_addr); + if (err) { + return err; + } else if (*blk_addr != NULL_ADDR) { + *use_cow = true; + return 0; + } + + if (is_inode_flag_set(inode, FI_ATOMIC_REPLACE)) + goto reserve_block; + + /* Look for the block in the original inode */ + err = __find_data_block(inode, index, &ori_blk_addr); + if (err) + return err; + +reserve_block: + /* Finally, we should reserve a new block in COW inode for the update */ + err = __reserve_data_block(cow_inode, index, blk_addr, node_changed); + if (err) + return err; + inc_atomic_write_cnt(inode); + + if (ori_blk_addr != NULL_ADDR) + *blk_addr = ori_blk_addr; + return 0; +} + static int f2fs_write_begin(struct file *file, struct address_space *mapping, loff_t pos, unsigned len, unsigned flags, struct page **pagep, void **fsdata) @@ -3365,7 +3465,8 @@ static int f2fs_write_begin(struct file *file, struct address_space *mapping, struct f2fs_sb_info *sbi = F2FS_I_SB(inode); struct page *page = NULL; pgoff_t index = ((unsigned long long) pos) >> PAGE_SHIFT; - bool need_balance = false, drop_atomic = false; + bool need_balance = false; + bool use_cow = false; block_t blkaddr = NULL_ADDR; int err = 0; @@ -3392,14 +3493,6 @@ static int f2fs_write_begin(struct file *file, struct address_space *mapping, goto fail; } - if ((f2fs_is_atomic_file(inode) && - !f2fs_available_free_memory(sbi, INMEM_PAGES)) || - is_inode_flag_set(inode, FI_ATOMIC_REVOKE_REQUEST)) { - err = -ENOMEM; - drop_atomic = true; - goto fail; - } - /* * We should check this at this moment to avoid deadlock on inode page * and #0 page. The locking rule for inline_data conversion should be: @@ -3447,7 +3540,11 @@ repeat: *pagep = page; - err = prepare_write_begin(sbi, page, pos, len, + if (f2fs_is_atomic_file(inode)) + err = prepare_atomic_write_begin(sbi, page, pos, len, + &blkaddr, &need_balance, &use_cow); + else + err = prepare_write_begin(sbi, page, pos, len, &blkaddr, &need_balance); if (err) goto fail; @@ -3484,7 +3581,9 @@ repeat: err = -EFSCORRUPTED; goto fail; } - err = f2fs_submit_page_read(inode, page, blkaddr, 0, true); + err = f2fs_submit_page_read(use_cow ? + F2FS_I(inode)->cow_inode : inode, page, + blkaddr, 0, true); if (err) goto fail; @@ -3503,8 +3602,6 @@ repeat: fail: f2fs_put_page(page, 1); f2fs_write_failed(inode, pos + len); - if (drop_atomic) - f2fs_drop_inmem_pages_all(sbi, false); return err; } @@ -3549,8 +3646,12 @@ static int f2fs_write_end(struct file *file, set_page_dirty(page); if (pos + copied > i_size_read(inode) && - !f2fs_verity_in_progress(inode)) + !f2fs_verity_in_progress(inode)) { f2fs_i_size_write(inode, pos + copied); + if (f2fs_is_atomic_file(inode)) + f2fs_i_size_write(F2FS_I(inode)->cow_inode, + pos + copied); + } unlock_out: f2fs_put_page(page, 1); f2fs_update_time(F2FS_I_SB(inode), REQ_TIME); @@ -3584,9 +3685,6 @@ void f2fs_invalidate_page(struct page *page, unsigned int offset, inode->i_ino == F2FS_COMPRESS_INO(sbi)) clear_page_private_data(page); - if (page_private_atomic(page)) - return f2fs_drop_inmem_page(inode, page); - detach_page_private(page); set_page_private(page, 0); } @@ -3597,10 +3695,6 @@ int f2fs_release_page(struct page *page, gfp_t wait) if (PageDirty(page)) return 0; - /* This is atomic written page, keep Private */ - if (page_private_atomic(page)) - return 0; - if (test_opt(F2FS_P_SB(page), COMPRESS_CACHE)) { struct inode *inode = page->mapping->host; @@ -3626,18 +3720,6 @@ static int f2fs_set_data_page_dirty(struct page *page) if (PageSwapCache(page)) return __set_page_dirty_nobuffers(page); - if (f2fs_is_atomic_file(inode) && !f2fs_is_commit_atomic_write(inode)) { - if (!page_private_atomic(page)) { - f2fs_register_inmem_page(inode, page); - return 1; - } - /* - * Previously, this page has been registered, we just - * return here. - */ - return 0; - } - if (!PageDirty(page)) { __set_page_dirty_nobuffers(page); f2fs_update_dirty_page(inode, page); @@ -3717,42 +3799,14 @@ out: int f2fs_migrate_page(struct address_space *mapping, struct page *newpage, struct page *page, enum migrate_mode mode) { - int rc, extra_count; - struct f2fs_inode_info *fi = F2FS_I(mapping->host); - bool atomic_written = page_private_atomic(page); + int rc, extra_count = 0; BUG_ON(PageWriteback(page)); - /* migrating an atomic written page is safe with the inmem_lock hold */ - if (atomic_written) { - if (mode != MIGRATE_SYNC) - return -EBUSY; - if (!mutex_trylock(&fi->inmem_lock)) - return -EAGAIN; - } - - /* one extra reference was held for atomic_write page */ - extra_count = atomic_written ? 1 : 0; rc = migrate_page_move_mapping(mapping, newpage, page, extra_count); - if (rc != MIGRATEPAGE_SUCCESS) { - if (atomic_written) - mutex_unlock(&fi->inmem_lock); + if (rc != MIGRATEPAGE_SUCCESS) return rc; - } - - if (atomic_written) { - struct inmem_pages *cur; - - list_for_each_entry(cur, &fi->inmem_pages, list) - if (cur->page == page) { - cur->page = newpage; - break; - } - mutex_unlock(&fi->inmem_lock); - put_page(page); - get_page(newpage); - } /* guarantee to start from no stale private field */ set_page_private(newpage, 0); diff --git a/fs/f2fs/debug.c b/fs/f2fs/debug.c index fcdf253cd211..0060bc7430d9 100644 --- a/fs/f2fs/debug.c +++ b/fs/f2fs/debug.c @@ -91,11 +91,8 @@ static void update_general_status(struct f2fs_sb_info *sbi) si->ndirty_files = sbi->ndirty_inode[FILE_INODE]; si->nquota_files = sbi->nquota_files; si->ndirty_all = sbi->ndirty_inode[DIRTY_META]; - si->inmem_pages = get_pages(sbi, F2FS_INMEM_PAGES); - si->aw_cnt = sbi->atomic_files; - si->vw_cnt = atomic_read(&sbi->vw_cnt); + si->aw_cnt = atomic_read(&sbi->atomic_files); si->max_aw_cnt = atomic_read(&sbi->max_aw_cnt); - si->max_vw_cnt = atomic_read(&sbi->max_vw_cnt); si->nr_dio_read = get_pages(sbi, F2FS_DIO_READ); si->nr_dio_write = get_pages(sbi, F2FS_DIO_WRITE); si->nr_wb_cp_data = get_pages(sbi, F2FS_WB_CP_DATA); @@ -167,8 +164,6 @@ static void update_general_status(struct f2fs_sb_info *sbi) si->alloc_nids = NM_I(sbi)->nid_cnt[PREALLOC_NID]; si->io_skip_bggc = sbi->io_skip_bggc; si->other_skip_bggc = sbi->other_skip_bggc; - si->skipped_atomic_files[BG_GC] = sbi->skipped_atomic_files[BG_GC]; - si->skipped_atomic_files[FG_GC] = sbi->skipped_atomic_files[FG_GC]; si->util_free = (int)(free_user_blocks(sbi) >> sbi->log_blocks_per_seg) * 100 / (int)(sbi->user_block_count >> sbi->log_blocks_per_seg) / 2; @@ -296,7 +291,6 @@ get_cache: sizeof(struct nat_entry); si->cache_mem += NM_I(sbi)->nat_cnt[DIRTY_NAT] * sizeof(struct nat_entry_set); - si->cache_mem += si->inmem_pages * sizeof(struct inmem_pages); for (i = 0; i < MAX_INO_ENTRY; i++) si->cache_mem += sbi->im[i].ino_num * sizeof(struct ino_entry); si->cache_mem += atomic_read(&sbi->total_ext_tree) * @@ -491,10 +485,6 @@ static int stat_show(struct seq_file *s, void *v) si->bg_data_blks); seq_printf(s, " - node blocks : %d (%d)\n", si->node_blks, si->bg_node_blks); - seq_printf(s, "Skipped : atomic write %llu (%llu)\n", - si->skipped_atomic_files[BG_GC] + - si->skipped_atomic_files[FG_GC], - si->skipped_atomic_files[BG_GC]); seq_printf(s, "BG skip : IO: %u, Other: %u\n", si->io_skip_bggc, si->other_skip_bggc); seq_puts(s, "\nExtent Cache:\n"); @@ -519,10 +509,8 @@ static int stat_show(struct seq_file *s, void *v) si->flush_list_empty, si->nr_discarding, si->nr_discarded, si->nr_discard_cmd, si->undiscard_blks); - seq_printf(s, " - inmem: %4d, atomic IO: %4d (Max. %4d), " - "volatile IO: %4d (Max. %4d)\n", - si->inmem_pages, si->aw_cnt, si->max_aw_cnt, - si->vw_cnt, si->max_vw_cnt); + seq_printf(s, " - atomic IO: %4d (Max. %4d)\n", + si->aw_cnt, si->max_aw_cnt); seq_printf(s, " - compress: %4d, hit:%8d\n", si->compress_pages, si->compress_page_hit); seq_printf(s, " - nodes: %4d in %4d\n", si->ndirty_node, si->node_pages); @@ -619,13 +607,12 @@ int f2fs_build_stats(struct f2fs_sb_info *sbi) atomic_set(&sbi->inline_dir, 0); atomic_set(&sbi->compr_inode, 0); atomic64_set(&sbi->compr_blocks, 0); + atomic_set(&sbi->atomic_files, 0); atomic_set(&sbi->inplace_count, 0); for (i = META_CP; i < META_MAX; i++) atomic_set(&sbi->meta_count[i], 0); - atomic_set(&sbi->vw_cnt, 0); atomic_set(&sbi->max_aw_cnt, 0); - atomic_set(&sbi->max_vw_cnt, 0); raw_spin_lock_irqsave(&f2fs_stat_lock, flags); list_add_tail(&si->stat_list, &f2fs_stat_list); diff --git a/fs/f2fs/dir.c b/fs/f2fs/dir.c index 0a3b6303363d..d9269122618d 100644 --- a/fs/f2fs/dir.c +++ b/fs/f2fs/dir.c @@ -806,8 +806,15 @@ int f2fs_add_dentry(struct inode *dir, const struct f2fs_filename *fname, { int err = -EAGAIN; - if (f2fs_has_inline_dentry(dir)) + if (f2fs_has_inline_dentry(dir)) { + /* + * Should get i_xattr_sem to keep the lock order: + * i_xattr_sem -> inode_page lock used by f2fs_setxattr. + */ + f2fs_down_read(&F2FS_I(dir)->i_xattr_sem); err = f2fs_add_inline_entry(dir, fname, inode, ino, mode); + f2fs_up_read(&F2FS_I(dir)->i_xattr_sem); + } if (err == -EAGAIN) err = f2fs_add_regular_entry(dir, fname, inode, ino, mode); diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h index dd621b3c0081..0d90fe71d2dd 100644 --- a/fs/f2fs/f2fs.h +++ b/fs/f2fs/f2fs.h @@ -720,7 +720,6 @@ enum { enum { GC_FAILURE_PIN, - GC_FAILURE_ATOMIC, MAX_GC_FAILURE }; @@ -742,8 +741,6 @@ enum { FI_UPDATE_WRITE, /* inode has in-place-update data */ FI_NEED_IPU, /* used for ipu per file */ FI_ATOMIC_FILE, /* indicate atomic file */ - FI_ATOMIC_COMMIT, /* indicate the state of atomical committing */ - FI_VOLATILE_FILE, /* indicate volatile file */ FI_FIRST_BLOCK_WRITTEN, /* indicate #0 data block was written */ FI_DROP_CACHE, /* drop dirty page cache */ FI_DATA_EXIST, /* indicate data exists */ @@ -756,7 +753,6 @@ enum { FI_EXTRA_ATTR, /* indicate file has extra attribute */ FI_PROJ_INHERIT, /* indicate file inherits projectid */ FI_PIN_FILE, /* indicate file should not be gced */ - FI_ATOMIC_REVOKE_REQUEST, /* request to drop atomic data */ FI_VERITY_IN_PROGRESS, /* building fs-verity Merkle tree */ FI_COMPRESSED_FILE, /* indicate file's data can be compressed */ FI_COMPRESS_CORRUPT, /* indicate compressed cluster is corrupted */ @@ -764,6 +760,9 @@ enum { FI_ENABLE_COMPRESS, /* enable compression in "user" compression mode */ FI_COMPRESS_RELEASED, /* compressed blocks were released */ FI_ALIGNED_WRITE, /* enable aligned write */ + FI_COW_FILE, /* indicate COW file */ + FI_ATOMIC_COMMITTED, /* indicate atomic commit completed except disk sync */ + FI_ATOMIC_REPLACE, /* indicate atomic replace */ FI_MAX, /* max flag, never be used */ }; @@ -799,11 +798,9 @@ struct f2fs_inode_info { #endif struct list_head dirty_list; /* dirty list for dirs and files */ struct list_head gdirty_list; /* linked in global dirty list */ - struct list_head inmem_ilist; /* list for inmem inodes */ - struct list_head inmem_pages; /* inmemory pages managed by f2fs */ - struct task_struct *inmem_task; /* store inmemory task */ - struct mutex inmem_lock; /* lock for inmemory pages */ + struct task_struct *atomic_write_task; /* store atomic write task */ struct extent_tree *extent_tree; /* cached extent_tree entry */ + struct inode *cow_inode; /* copy-on-write inode for atomic write */ /* avoid racing between foreground op and gc */ struct f2fs_rwsem i_gc_rwsem[2]; @@ -822,6 +819,9 @@ struct f2fs_inode_info { unsigned char i_compress_level; /* compress level (lz4hc,zstd) */ unsigned short i_compress_flag; /* compress flag */ unsigned int i_cluster_size; /* cluster size */ + + unsigned int atomic_write_cnt; + loff_t original_i_size; /* original i_size before atomic write */ }; static inline void get_extent_info(struct extent_info *ext, @@ -1097,7 +1097,6 @@ enum count_type { F2FS_DIRTY_QDATA, F2FS_DIRTY_NODES, F2FS_DIRTY_META, - F2FS_INMEM_PAGES, F2FS_DIRTY_IMETA, F2FS_WB_CP_DATA, F2FS_WB_DATA, @@ -1127,11 +1126,7 @@ enum page_type { META, NR_PAGE_TYPE, META_FLUSH, - INMEM, /* the below types are used by tracepoints only. */ - INMEM_DROP, - INMEM_INVALIDATE, - INMEM_REVOKE, - IPU, + IPU, /* the below types are used by tracepoints only. */ OPU, }; @@ -1257,7 +1252,6 @@ enum inode_type { DIR_INODE, /* for dirty dir inode */ FILE_INODE, /* for dirty regular/symlink inode */ DIRTY_META, /* for all dirtied inode metadata */ - ATOMIC_FILE, /* for all atomic files */ NR_INODE_TYPE, }; @@ -1736,8 +1730,6 @@ struct f2fs_sb_info { unsigned int gc_urgent_high_remaining; /* remaining trial count for GC_URGENT_HIGH */ /* for skip statistic */ - unsigned int atomic_files; /* # of opened atomic file */ - unsigned long long skipped_atomic_files[2]; /* FG_GC and BG_GC */ unsigned long long skipped_gc_rwsem; /* FG_GC only */ /* threshold for gc trials on pinned files */ @@ -1768,9 +1760,8 @@ struct f2fs_sb_info { atomic_t inline_dir; /* # of inline_dentry inodes */ atomic_t compr_inode; /* # of compressed inodes */ atomic64_t compr_blocks; /* # of compressed blocks */ - atomic_t vw_cnt; /* # of volatile writes */ + atomic_t atomic_files; /* # of opened atomic file */ atomic_t max_aw_cnt; /* max # of atomic writes */ - atomic_t max_vw_cnt; /* max # of volatile writes */ unsigned int io_skip_bggc; /* skip background gc for in-flight IO */ unsigned int other_skip_bggc; /* skip background gc for other reasons */ unsigned int ndirty_inode[NR_INODE_TYPE]; /* # of dirty inodes */ @@ -1827,6 +1818,12 @@ struct f2fs_sb_info { int max_fragment_chunk; /* max chunk size for block fragmentation mode */ int max_fragment_hole; /* max hole size for block fragmentation mode */ + /* For atomic write statistics */ + atomic64_t current_atomic_write; + s64 peak_atomic_write; + u64 committed_atomic_block; + u64 revoked_atomic_block; + #ifdef CONFIG_F2FS_FS_COMPRESSION struct kmem_cache *page_array_slab; /* page array entry */ unsigned int page_array_slab_size; /* default page array slab size */ @@ -2441,6 +2438,28 @@ static inline void inode_dec_dirty_pages(struct inode *inode) dec_page_count(F2FS_I_SB(inode), F2FS_DIRTY_QDATA); } +static inline void inc_atomic_write_cnt(struct inode *inode) +{ + struct f2fs_sb_info *sbi = F2FS_I_SB(inode); + struct f2fs_inode_info *fi = F2FS_I(inode); + u64 current_write; + + fi->atomic_write_cnt++; + atomic64_inc(&sbi->current_atomic_write); + current_write = atomic64_read(&sbi->current_atomic_write); + if (current_write > sbi->peak_atomic_write) + sbi->peak_atomic_write = current_write; +} + +static inline void release_atomic_write_cnt(struct inode *inode) +{ + struct f2fs_sb_info *sbi = F2FS_I_SB(inode); + struct f2fs_inode_info *fi = F2FS_I(inode); + + atomic64_sub(fi->atomic_write_cnt, &sbi->current_atomic_write); + fi->atomic_write_cnt = 0; +} + static inline s64 get_pages(struct f2fs_sb_info *sbi, int count_type) { return atomic_read(&sbi->nr_pages[count_type]); @@ -3044,6 +3063,8 @@ static inline void f2fs_i_blocks_write(struct inode *inode, set_inode_flag(inode, FI_AUTO_RECOVER); } +static inline bool f2fs_is_atomic_file(struct inode *inode); + static inline void f2fs_i_size_write(struct inode *inode, loff_t i_size) { bool clean = !is_inode_flag_set(inode, FI_DIRTY_INODE); @@ -3053,6 +3074,10 @@ static inline void f2fs_i_size_write(struct inode *inode, loff_t i_size) return; i_size_write(inode, i_size); + + if (f2fs_is_atomic_file(inode)) + return; + f2fs_mark_inode_dirty_sync(inode, true); if (clean || recover) set_inode_flag(inode, FI_AUTO_RECOVER); @@ -3221,14 +3246,9 @@ static inline bool f2fs_is_atomic_file(struct inode *inode) return is_inode_flag_set(inode, FI_ATOMIC_FILE); } -static inline bool f2fs_is_commit_atomic_write(struct inode *inode) +static inline bool f2fs_is_cow_file(struct inode *inode) { - return is_inode_flag_set(inode, FI_ATOMIC_COMMIT); -} - -static inline bool f2fs_is_volatile_file(struct inode *inode) -{ - return is_inode_flag_set(inode, FI_VOLATILE_FILE); + return is_inode_flag_set(inode, FI_COW_FILE); } static inline bool f2fs_is_first_block_written(struct inode *inode) @@ -3463,6 +3483,8 @@ void f2fs_handle_failed_inode(struct inode *inode); int f2fs_update_extension_list(struct f2fs_sb_info *sbi, const char *name, bool hot, bool set); struct dentry *f2fs_get_parent(struct dentry *child); +int f2fs_get_tmpfile(struct user_namespace *mnt_userns, struct inode *dir, + struct inode **new_inode); /* * dir.c @@ -3599,11 +3621,8 @@ void f2fs_destroy_node_manager_caches(void); * segment.c */ bool f2fs_need_SSR(struct f2fs_sb_info *sbi); -void f2fs_register_inmem_page(struct inode *inode, struct page *page); -void f2fs_drop_inmem_pages_all(struct f2fs_sb_info *sbi, bool gc_failure); -void f2fs_drop_inmem_pages(struct inode *inode); -void f2fs_drop_inmem_page(struct inode *inode, struct page *page); -int f2fs_commit_inmem_pages(struct inode *inode); +int f2fs_commit_atomic_write(struct inode *inode); +void f2fs_abort_atomic_write(struct inode *inode, bool clean); void f2fs_balance_fs(struct f2fs_sb_info *sbi, bool need); void f2fs_balance_fs_bg(struct f2fs_sb_info *sbi, bool from_bg); int f2fs_issue_flush(struct f2fs_sb_info *sbi, nid_t ino); @@ -3815,7 +3834,7 @@ block_t f2fs_start_bidx_of_node(unsigned int node_ofs, struct inode *inode); int f2fs_gc(struct f2fs_sb_info *sbi, bool sync, bool background, bool force, unsigned int segno); void f2fs_build_gc_manager(struct f2fs_sb_info *sbi); -int f2fs_resize_fs(struct f2fs_sb_info *sbi, __u64 block_count); +int f2fs_resize_fs(struct file *filp, __u64 block_count); int __init f2fs_create_garbage_collection_cache(void); void f2fs_destroy_garbage_collection_cache(void); @@ -3841,7 +3860,6 @@ struct f2fs_stat_info { int ext_tree, zombie_tree, ext_node; int ndirty_node, ndirty_dent, ndirty_meta, ndirty_imeta; int ndirty_data, ndirty_qdata; - int inmem_pages; unsigned int ndirty_dirs, ndirty_files, nquota_files, ndirty_all; int nats, dirty_nats, sits, dirty_sits; int free_nids, avail_nids, alloc_nids; @@ -3859,7 +3877,7 @@ struct f2fs_stat_info { int inline_xattr, inline_inode, inline_dir, append, update, orphans; int compr_inode; unsigned long long compr_blocks; - int aw_cnt, max_aw_cnt, vw_cnt, max_vw_cnt; + int aw_cnt, max_aw_cnt; unsigned int valid_count, valid_node_count, valid_inode_count, discard_blks; unsigned int bimodal, avg_vblocks; int util_free, util_valid, util_invalid; @@ -3871,7 +3889,6 @@ struct f2fs_stat_info { int bg_node_segs, bg_data_segs; int tot_blks, data_blks, node_blks; int bg_data_blks, bg_node_blks; - unsigned long long skipped_atomic_files[2]; int curseg[NR_CURSEG_TYPE]; int cursec[NR_CURSEG_TYPE]; int curzone[NR_CURSEG_TYPE]; @@ -3947,6 +3964,10 @@ static inline struct f2fs_stat_info *F2FS_STAT(struct f2fs_sb_info *sbi) (atomic64_add(blocks, &F2FS_I_SB(inode)->compr_blocks)) #define stat_sub_compr_blocks(inode, blocks) \ (atomic64_sub(blocks, &F2FS_I_SB(inode)->compr_blocks)) +#define stat_inc_atomic_inode(inode) \ + (atomic_inc(&F2FS_I_SB(inode)->atomic_files)) +#define stat_dec_atomic_inode(inode) \ + (atomic_dec(&F2FS_I_SB(inode)->atomic_files)) #define stat_inc_meta_count(sbi, blkaddr) \ do { \ if (blkaddr < SIT_I(sbi)->sit_base_addr) \ @@ -3966,22 +3987,11 @@ static inline struct f2fs_stat_info *F2FS_STAT(struct f2fs_sb_info *sbi) (atomic_inc(&(sbi)->inplace_count)) #define stat_update_max_atomic_write(inode) \ do { \ - int cur = F2FS_I_SB(inode)->atomic_files; \ + int cur = atomic_read(&F2FS_I_SB(inode)->atomic_files); \ int max = atomic_read(&F2FS_I_SB(inode)->max_aw_cnt); \ if (cur > max) \ atomic_set(&F2FS_I_SB(inode)->max_aw_cnt, cur); \ } while (0) -#define stat_inc_volatile_write(inode) \ - (atomic_inc(&F2FS_I_SB(inode)->vw_cnt)) -#define stat_dec_volatile_write(inode) \ - (atomic_dec(&F2FS_I_SB(inode)->vw_cnt)) -#define stat_update_max_volatile_write(inode) \ - do { \ - int cur = atomic_read(&F2FS_I_SB(inode)->vw_cnt); \ - int max = atomic_read(&F2FS_I_SB(inode)->max_vw_cnt); \ - if (cur > max) \ - atomic_set(&F2FS_I_SB(inode)->max_vw_cnt, cur); \ - } while (0) #define stat_inc_seg_count(sbi, type, gc_type) \ do { \ struct f2fs_stat_info *si = F2FS_STAT(sbi); \ @@ -4042,10 +4052,9 @@ void f2fs_update_sit_info(struct f2fs_sb_info *sbi); #define stat_dec_compr_inode(inode) do { } while (0) #define stat_add_compr_blocks(inode, blocks) do { } while (0) #define stat_sub_compr_blocks(inode, blocks) do { } while (0) +#define stat_inc_atomic_inode(inode) do { } while (0) +#define stat_dec_atomic_inode(inode) do { } while (0) #define stat_update_max_atomic_write(inode) do { } while (0) -#define stat_inc_volatile_write(inode) do { } while (0) -#define stat_dec_volatile_write(inode) do { } while (0) -#define stat_update_max_volatile_write(inode) do { } while (0) #define stat_inc_meta_count(sbi, blkaddr) do { } while (0) #define stat_inc_seg_type(sbi, curseg) do { } while (0) #define stat_inc_block_count(sbi, curseg) do { } while (0) @@ -4466,8 +4475,7 @@ static inline bool f2fs_low_mem_mode(struct f2fs_sb_info *sbi) static inline bool f2fs_may_compress(struct inode *inode) { if (IS_SWAPFILE(inode) || f2fs_is_pinned_file(inode) || - f2fs_is_atomic_file(inode) || - f2fs_is_volatile_file(inode)) + f2fs_is_atomic_file(inode)) return false; return S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode); } @@ -4475,8 +4483,8 @@ static inline bool f2fs_may_compress(struct inode *inode) static inline void f2fs_i_compr_blocks_update(struct inode *inode, u64 blocks, bool add) { - int diff = F2FS_I(inode)->i_cluster_size - blocks; struct f2fs_inode_info *fi = F2FS_I(inode); + int diff = fi->i_cluster_size - blocks; /* don't update i_compr_blocks if saved blocks were released */ if (!add && !atomic_read(&fi->i_compr_blocks)) diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c index ccf3c56d1004..6c08de2ca107 100644 --- a/fs/f2fs/file.c +++ b/fs/f2fs/file.c @@ -1818,16 +1818,10 @@ static int f2fs_release_file(struct inode *inode, struct file *filp) atomic_read(&inode->i_writecount) != 1) return 0; - /* some remained atomic pages should discarded */ - if (f2fs_is_atomic_file(inode)) - f2fs_drop_inmem_pages(inode); - if (f2fs_is_volatile_file(inode)) { - set_inode_flag(inode, FI_DROP_CACHE); - filemap_fdatawrite(inode->i_mapping); - clear_inode_flag(inode, FI_DROP_CACHE); - clear_inode_flag(inode, FI_VOLATILE_FILE); - stat_dec_volatile_write(inode); - } + inode_lock(inode); + f2fs_abort_atomic_write(inode, true); + inode_unlock(inode); + return 0; } @@ -1841,9 +1835,13 @@ static int f2fs_file_flush(struct file *file, fl_owner_t id) * until all the writers close its file. Since this should be done * before dropping file lock, it needs to do in ->flush. */ - if (f2fs_is_atomic_file(inode) && - F2FS_I(inode)->inmem_task == current) - f2fs_drop_inmem_pages(inode); + if (F2FS_I(inode)->atomic_write_task == current && + (current->flags & PF_EXITING)) { + inode_lock(inode); + f2fs_abort_atomic_write(inode, true); + inode_unlock(inode); + } + return 0; } @@ -1993,12 +1991,14 @@ static int f2fs_ioc_getversion(struct file *filp, unsigned long arg) return put_user(inode->i_generation, (int __user *)arg); } -static int f2fs_ioc_start_atomic_write(struct file *filp) +static int f2fs_ioc_start_atomic_write(struct file *filp, bool truncate) { struct inode *inode = file_inode(filp); struct user_namespace *mnt_userns = file_mnt_user_ns(filp); struct f2fs_inode_info *fi = F2FS_I(inode); struct f2fs_sb_info *sbi = F2FS_I_SB(inode); + struct inode *pinode; + loff_t isize; int ret; if (!inode_owner_or_capable(mnt_userns, inode)) @@ -2021,45 +2021,78 @@ static int f2fs_ioc_start_atomic_write(struct file *filp) goto out; } - if (f2fs_is_atomic_file(inode)) { - if (is_inode_flag_set(inode, FI_ATOMIC_REVOKE_REQUEST)) - ret = -EINVAL; + if (f2fs_is_atomic_file(inode)) goto out; - } ret = f2fs_convert_inline_inode(inode); if (ret) goto out; - f2fs_down_write(&F2FS_I(inode)->i_gc_rwsem[WRITE]); + f2fs_down_write(&fi->i_gc_rwsem[WRITE]); /* * Should wait end_io to count F2FS_WB_CP_DATA correctly by * f2fs_is_atomic_file. */ if (get_dirty_pages(inode)) - f2fs_warn(F2FS_I_SB(inode), "Unexpected flush for atomic writes: ino=%lu, npages=%u", + f2fs_warn(sbi, "Unexpected flush for atomic writes: ino=%lu, npages=%u", inode->i_ino, get_dirty_pages(inode)); ret = filemap_write_and_wait_range(inode->i_mapping, 0, LLONG_MAX); if (ret) { - f2fs_up_write(&F2FS_I(inode)->i_gc_rwsem[WRITE]); + f2fs_up_write(&fi->i_gc_rwsem[WRITE]); goto out; } - spin_lock(&sbi->inode_lock[ATOMIC_FILE]); - if (list_empty(&fi->inmem_ilist)) - list_add_tail(&fi->inmem_ilist, &sbi->inode_list[ATOMIC_FILE]); - sbi->atomic_files++; - spin_unlock(&sbi->inode_lock[ATOMIC_FILE]); + /* Check if the inode already has a COW inode */ + if (fi->cow_inode == NULL) { + /* Create a COW inode for atomic write */ + pinode = f2fs_iget(inode->i_sb, fi->i_pino); + if (IS_ERR(pinode)) { + f2fs_up_write(&fi->i_gc_rwsem[WRITE]); + ret = PTR_ERR(pinode); + goto out; + } + + ret = f2fs_get_tmpfile(mnt_userns, pinode, &fi->cow_inode); + iput(pinode); + if (ret) { + f2fs_up_write(&fi->i_gc_rwsem[WRITE]); + goto out; + } + + set_inode_flag(fi->cow_inode, FI_COW_FILE); + clear_inode_flag(fi->cow_inode, FI_INLINE_DATA); + } else { + /* Reuse the already created COW inode */ + ret = f2fs_do_truncate_blocks(fi->cow_inode, 0, true); + if (ret) { + f2fs_up_write(&fi->i_gc_rwsem[WRITE]); + goto out; + } + } + + f2fs_write_inode(inode, NULL); + + stat_inc_atomic_inode(inode); - /* add inode in inmem_list first and set atomic_file */ set_inode_flag(inode, FI_ATOMIC_FILE); - clear_inode_flag(inode, FI_ATOMIC_REVOKE_REQUEST); - f2fs_up_write(&F2FS_I(inode)->i_gc_rwsem[WRITE]); - f2fs_update_time(F2FS_I_SB(inode), REQ_TIME); - F2FS_I(inode)->inmem_task = current; + isize = i_size_read(inode); + fi->original_i_size = isize; + if (truncate) { + set_inode_flag(inode, FI_ATOMIC_REPLACE); + truncate_inode_pages_final(inode->i_mapping); + f2fs_i_size_write(inode, 0); + isize = 0; + } + f2fs_i_size_write(fi->cow_inode, isize); + + f2fs_up_write(&fi->i_gc_rwsem[WRITE]); + + f2fs_update_time(sbi, REQ_TIME); + fi->atomic_write_task = current; stat_update_max_atomic_write(inode); + fi->atomic_write_cnt = 0; out: inode_unlock(inode); mnt_drop_write_file(filp); @@ -2083,69 +2116,22 @@ static int f2fs_ioc_commit_atomic_write(struct file *filp) inode_lock(inode); - if (f2fs_is_volatile_file(inode)) { - ret = -EINVAL; - goto err_out; - } - if (f2fs_is_atomic_file(inode)) { - ret = f2fs_commit_inmem_pages(inode); - if (ret) - goto err_out; - - ret = f2fs_do_sync_file(filp, 0, LLONG_MAX, 0, true); + ret = f2fs_commit_atomic_write(inode); if (!ret) - f2fs_drop_inmem_pages(inode); + ret = f2fs_do_sync_file(filp, 0, LLONG_MAX, 0, true); + + f2fs_abort_atomic_write(inode, ret); } else { ret = f2fs_do_sync_file(filp, 0, LLONG_MAX, 1, false); } -err_out: - if (is_inode_flag_set(inode, FI_ATOMIC_REVOKE_REQUEST)) { - clear_inode_flag(inode, FI_ATOMIC_REVOKE_REQUEST); - ret = -EINVAL; - } + inode_unlock(inode); mnt_drop_write_file(filp); return ret; } -static int f2fs_ioc_start_volatile_write(struct file *filp) -{ - struct inode *inode = file_inode(filp); - struct user_namespace *mnt_userns = file_mnt_user_ns(filp); - int ret; - - if (!inode_owner_or_capable(mnt_userns, inode)) - return -EACCES; - - if (!S_ISREG(inode->i_mode)) - return -EINVAL; - - ret = mnt_want_write_file(filp); - if (ret) - return ret; - - inode_lock(inode); - - if (f2fs_is_volatile_file(inode)) - goto out; - - ret = f2fs_convert_inline_inode(inode); - if (ret) - goto out; - - stat_inc_volatile_write(inode); - stat_update_max_volatile_write(inode); - - set_inode_flag(inode, FI_VOLATILE_FILE); - f2fs_update_time(F2FS_I_SB(inode), REQ_TIME); -out: - inode_unlock(inode); - mnt_drop_write_file(filp); - return ret; -} - -static int f2fs_ioc_release_volatile_write(struct file *filp) +static int f2fs_ioc_abort_atomic_write(struct file *filp) { struct inode *inode = file_inode(filp); struct user_namespace *mnt_userns = file_mnt_user_ns(filp); @@ -2160,45 +2146,7 @@ static int f2fs_ioc_release_volatile_write(struct file *filp) inode_lock(inode); - if (!f2fs_is_volatile_file(inode)) - goto out; - - if (!f2fs_is_first_block_written(inode)) { - ret = truncate_partial_data_page(inode, 0, true); - goto out; - } - - ret = punch_hole(inode, 0, F2FS_BLKSIZE); -out: - inode_unlock(inode); - mnt_drop_write_file(filp); - return ret; -} - -static int f2fs_ioc_abort_volatile_write(struct file *filp) -{ - struct inode *inode = file_inode(filp); - struct user_namespace *mnt_userns = file_mnt_user_ns(filp); - int ret; - - if (!inode_owner_or_capable(mnt_userns, inode)) - return -EACCES; - - ret = mnt_want_write_file(filp); - if (ret) - return ret; - - inode_lock(inode); - - if (f2fs_is_atomic_file(inode)) - f2fs_drop_inmem_pages(inode); - if (f2fs_is_volatile_file(inode)) { - clear_inode_flag(inode, FI_VOLATILE_FILE); - stat_dec_volatile_write(inode); - ret = f2fs_do_sync_file(filp, 0, LLONG_MAX, 0, true); - } - - clear_inode_flag(inode, FI_ATOMIC_REVOKE_REQUEST); + f2fs_abort_atomic_write(inode, true); inode_unlock(inode); @@ -3028,7 +2976,7 @@ static int f2fs_ioc_setproject(struct inode *inode, __u32 projid) kprojid = make_kprojid(&init_user_ns, (projid_t)projid); - if (projid_eq(kprojid, F2FS_I(inode)->i_projid)) + if (projid_eq(kprojid, fi->i_projid)) return 0; err = -EPERM; @@ -3048,7 +2996,7 @@ static int f2fs_ioc_setproject(struct inode *inode, __u32 projid) if (err) goto out_unlock; - F2FS_I(inode)->i_projid = kprojid; + fi->i_projid = kprojid; inode->i_ctime = current_time(inode); f2fs_mark_inode_dirty_sync(inode, true); out_unlock: @@ -3260,7 +3208,7 @@ static int f2fs_ioc_resize_fs(struct file *filp, unsigned long arg) sizeof(block_count))) return -EFAULT; - return f2fs_resize_fs(sbi, block_count); + return f2fs_resize_fs(filp, block_count); } static int f2fs_ioc_enable_verity(struct file *filp, unsigned long arg) @@ -3998,7 +3946,7 @@ static int f2fs_ioc_decompress_file(struct file *filp, unsigned long arg) struct f2fs_inode_info *fi = F2FS_I(inode); pgoff_t page_idx = 0, last_idx; unsigned int blk_per_seg = sbi->blocks_per_seg; - int cluster_size = F2FS_I(inode)->i_cluster_size; + int cluster_size = fi->i_cluster_size; int count, ret; if (!f2fs_sb_has_compression(sbi) || @@ -4143,15 +4091,16 @@ static long __f2fs_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) case FS_IOC_GETVERSION: return f2fs_ioc_getversion(filp, arg); case F2FS_IOC_START_ATOMIC_WRITE: - return f2fs_ioc_start_atomic_write(filp); + return f2fs_ioc_start_atomic_write(filp, false); + case F2FS_IOC_START_ATOMIC_REPLACE: + return f2fs_ioc_start_atomic_write(filp, true); case F2FS_IOC_COMMIT_ATOMIC_WRITE: return f2fs_ioc_commit_atomic_write(filp); + case F2FS_IOC_ABORT_ATOMIC_WRITE: + return f2fs_ioc_abort_atomic_write(filp); case F2FS_IOC_START_VOLATILE_WRITE: - return f2fs_ioc_start_volatile_write(filp); case F2FS_IOC_RELEASE_VOLATILE_WRITE: - return f2fs_ioc_release_volatile_write(filp); - case F2FS_IOC_ABORT_VOLATILE_WRITE: - return f2fs_ioc_abort_volatile_write(filp); + return -EOPNOTSUPP; case F2FS_IOC_SHUTDOWN: return f2fs_ioc_shutdown(filp, arg); case FITRIM: @@ -4846,10 +4795,11 @@ long f2fs_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg) case F2FS_IOC32_MOVE_RANGE: return f2fs_compat_ioc_move_range(file, arg); case F2FS_IOC_START_ATOMIC_WRITE: + case F2FS_IOC_START_ATOMIC_REPLACE: case F2FS_IOC_COMMIT_ATOMIC_WRITE: case F2FS_IOC_START_VOLATILE_WRITE: case F2FS_IOC_RELEASE_VOLATILE_WRITE: - case F2FS_IOC_ABORT_VOLATILE_WRITE: + case F2FS_IOC_ABORT_ATOMIC_WRITE: case F2FS_IOC_SHUTDOWN: case FITRIM: case FS_IOC_SET_ENCRYPTION_POLICY: diff --git a/fs/f2fs/gc.c b/fs/f2fs/gc.c index f1a8e25b60b7..23ed4a4d14c2 100644 --- a/fs/f2fs/gc.c +++ b/fs/f2fs/gc.c @@ -1256,13 +1256,6 @@ static int move_data_block(struct inode *inode, block_t bidx, goto out; } - if (f2fs_is_atomic_file(inode)) { - F2FS_I(inode)->i_gc_failures[GC_FAILURE_ATOMIC]++; - F2FS_I_SB(inode)->skipped_atomic_files[gc_type]++; - err = -EAGAIN; - goto out; - } - err = f2fs_gc_pinned_control(inode, gc_type, segno); if (err) goto out; @@ -1404,12 +1397,6 @@ static int move_data_page(struct inode *inode, block_t bidx, int gc_type, goto out; } - if (f2fs_is_atomic_file(inode)) { - F2FS_I(inode)->i_gc_failures[GC_FAILURE_ATOMIC]++; - F2FS_I_SB(inode)->skipped_atomic_files[gc_type]++; - err = -EAGAIN; - goto out; - } err = f2fs_gc_pinned_control(inode, gc_type, segno); if (err) goto out; @@ -1779,8 +1766,6 @@ int f2fs_gc(struct f2fs_sb_info *sbi, bool sync, .ilist = LIST_HEAD_INIT(gc_list.ilist), .iroot = RADIX_TREE_INIT(gc_list.iroot, GFP_NOFS), }; - unsigned long long last_skipped = sbi->skipped_atomic_files[FG_GC]; - unsigned long long first_skipped; unsigned int skipped_round = 0, round = 0; trace_f2fs_gc_begin(sbi->sb, sync, background, @@ -1794,7 +1779,6 @@ int f2fs_gc(struct f2fs_sb_info *sbi, bool sync, cpc.reason = __get_cp_reason(sbi); sbi->skipped_gc_rwsem = 0; - first_skipped = last_skipped; gc_more: if (unlikely(!(sbi->sb->s_flags & SB_ACTIVE))) { ret = -EINVAL; @@ -1845,10 +1829,8 @@ retry: total_freed += seg_freed; if (gc_type == FG_GC) { - if (sbi->skipped_atomic_files[FG_GC] > last_skipped || - sbi->skipped_gc_rwsem) + if (sbi->skipped_gc_rwsem) skipped_round++; - last_skipped = sbi->skipped_atomic_files[FG_GC]; round++; } @@ -1865,13 +1847,6 @@ retry: goto gc_more; } - if (first_skipped < last_skipped && - (last_skipped - first_skipped) > - sbi->skipped_gc_rwsem) { - f2fs_drop_inmem_pages_all(sbi, true); - segno = NULL_SEGNO; - goto gc_more; - } if (gc_type == FG_GC && !is_sbi_flag_set(sbi, SBI_CP_DISABLED)) ret = f2fs_write_checkpoint(sbi, &cpc); } @@ -2072,8 +2047,9 @@ static void update_fs_metadata(struct f2fs_sb_info *sbi, int secs) } } -int f2fs_resize_fs(struct f2fs_sb_info *sbi, __u64 block_count) +int f2fs_resize_fs(struct file *filp, __u64 block_count) { + struct f2fs_sb_info *sbi = F2FS_I_SB(file_inode(filp)); __u64 old_block_count, shrunk_blocks; struct cp_control cpc = { CP_RESIZE, 0, 0, 0 }; unsigned int secs; @@ -2111,12 +2087,18 @@ int f2fs_resize_fs(struct f2fs_sb_info *sbi, __u64 block_count) return -EINVAL; } + err = mnt_want_write_file(filp); + if (err) + return err; + shrunk_blocks = old_block_count - block_count; secs = div_u64(shrunk_blocks, BLKS_PER_SEC(sbi)); /* stop other GC */ - if (!f2fs_down_write_trylock(&sbi->gc_lock)) - return -EAGAIN; + if (!f2fs_down_write_trylock(&sbi->gc_lock)) { + err = -EAGAIN; + goto out_drop_write; + } /* stop CP to protect MAIN_SEC in free_segment_range */ f2fs_lock_op(sbi); @@ -2136,10 +2118,18 @@ int f2fs_resize_fs(struct f2fs_sb_info *sbi, __u64 block_count) out_unlock: f2fs_unlock_op(sbi); f2fs_up_write(&sbi->gc_lock); +out_drop_write: + mnt_drop_write_file(filp); if (err) return err; freeze_super(sbi->sb); + + if (f2fs_readonly(sbi->sb)) { + thaw_super(sbi->sb); + return -EROFS; + } + f2fs_down_write(&sbi->gc_lock); f2fs_down_write(&sbi->cp_global_sem); diff --git a/fs/f2fs/inode.c b/fs/f2fs/inode.c index 829d767a77bf..29f43176b385 100644 --- a/fs/f2fs/inode.c +++ b/fs/f2fs/inode.c @@ -260,8 +260,8 @@ static bool sanity_check_inode(struct inode *inode, struct page *node_page) return false; } - if (F2FS_I(inode)->extent_tree) { - struct extent_info *ei = &F2FS_I(inode)->extent_tree->largest; + if (fi->extent_tree) { + struct extent_info *ei = &fi->extent_tree->largest; if (ei->len && (!f2fs_is_valid_blkaddr(sbi, ei->blk, @@ -465,10 +465,10 @@ static int do_read_inode(struct inode *inode) } } - F2FS_I(inode)->i_disk_time[0] = inode->i_atime; - F2FS_I(inode)->i_disk_time[1] = inode->i_ctime; - F2FS_I(inode)->i_disk_time[2] = inode->i_mtime; - F2FS_I(inode)->i_disk_time[3] = F2FS_I(inode)->i_crtime; + fi->i_disk_time[0] = inode->i_atime; + fi->i_disk_time[1] = inode->i_ctime; + fi->i_disk_time[2] = inode->i_mtime; + fi->i_disk_time[3] = fi->i_crtime; f2fs_put_page(node_page, 1); stat_inc_inline_xattr(inode); @@ -599,9 +599,12 @@ void f2fs_update_inode(struct inode *inode, struct page *node_page) ri->i_uid = cpu_to_le32(i_uid_read(inode)); ri->i_gid = cpu_to_le32(i_gid_read(inode)); ri->i_links = cpu_to_le32(inode->i_nlink); - ri->i_size = cpu_to_le64(i_size_read(inode)); ri->i_blocks = cpu_to_le64(SECTOR_TO_BLOCK(inode->i_blocks) + 1); + if (!f2fs_is_atomic_file(inode) || + is_inode_flag_set(inode, FI_ATOMIC_COMMITTED)) + ri->i_size = cpu_to_le64(i_size_read(inode)); + if (et) { read_lock(&et->lock); set_raw_extent(&et->largest, &ri->i_ext); @@ -742,12 +745,17 @@ int f2fs_write_inode(struct inode *inode, struct writeback_control *wbc) void f2fs_evict_inode(struct inode *inode) { struct f2fs_sb_info *sbi = F2FS_I_SB(inode); - nid_t xnid = F2FS_I(inode)->i_xattr_nid; + struct f2fs_inode_info *fi = F2FS_I(inode); + nid_t xnid = fi->i_xattr_nid; int err = 0; - /* some remained atomic pages should discarded */ - if (f2fs_is_atomic_file(inode)) - f2fs_drop_inmem_pages(inode); + f2fs_abort_atomic_write(inode, true); + + if (fi->cow_inode) { + clear_inode_flag(fi->cow_inode, FI_COW_FILE); + iput(fi->cow_inode); + fi->cow_inode = NULL; + } trace_f2fs_evict_inode(inode); truncate_inode_pages_final(&inode->i_data); @@ -835,7 +843,7 @@ no_delete: stat_dec_inline_inode(inode); stat_dec_compr_inode(inode); stat_sub_compr_blocks(inode, - atomic_read(&F2FS_I(inode)->i_compr_blocks)); + atomic_read(&fi->i_compr_blocks)); if (likely(!f2fs_cp_error(sbi) && !is_sbi_flag_set(sbi, SBI_CP_DISABLED))) diff --git a/fs/f2fs/namei.c b/fs/f2fs/namei.c index 922a567c3ab9..ed3bdaeed538 100644 --- a/fs/f2fs/namei.c +++ b/fs/f2fs/namei.c @@ -848,8 +848,8 @@ out: } static int __f2fs_tmpfile(struct user_namespace *mnt_userns, struct inode *dir, - struct dentry *dentry, umode_t mode, - struct inode **whiteout) + struct dentry *dentry, umode_t mode, bool is_whiteout, + struct inode **new_inode) { struct f2fs_sb_info *sbi = F2FS_I_SB(dir); struct inode *inode; @@ -863,7 +863,7 @@ static int __f2fs_tmpfile(struct user_namespace *mnt_userns, struct inode *dir, if (IS_ERR(inode)) return PTR_ERR(inode); - if (whiteout) { + if (is_whiteout) { init_special_inode(inode, inode->i_mode, WHITEOUT_DEV); inode->i_op = &f2fs_special_inode_operations; } else { @@ -888,21 +888,25 @@ static int __f2fs_tmpfile(struct user_namespace *mnt_userns, struct inode *dir, f2fs_add_orphan_inode(inode); f2fs_alloc_nid_done(sbi, inode->i_ino); - if (whiteout) { + if (is_whiteout) { f2fs_i_links_write(inode, false); spin_lock(&inode->i_lock); inode->i_state |= I_LINKABLE; spin_unlock(&inode->i_lock); - - *whiteout = inode; } else { - d_tmpfile(dentry, inode); + if (dentry) + d_tmpfile(dentry, inode); + else + f2fs_i_links_write(inode, false); } /* link_count was changed by d_tmpfile as well. */ f2fs_unlock_op(sbi); unlock_new_inode(inode); + if (new_inode) + *new_inode = inode; + f2fs_balance_fs(sbi, true); return 0; @@ -923,7 +927,7 @@ static int f2fs_tmpfile(struct user_namespace *mnt_userns, struct inode *dir, if (!f2fs_is_checkpoint_ready(sbi)) return -ENOSPC; - return __f2fs_tmpfile(mnt_userns, dir, dentry, mode, NULL); + return __f2fs_tmpfile(mnt_userns, dir, dentry, mode, false, NULL); } static int f2fs_create_whiteout(struct user_namespace *mnt_userns, @@ -933,7 +937,13 @@ static int f2fs_create_whiteout(struct user_namespace *mnt_userns, return -EIO; return __f2fs_tmpfile(mnt_userns, dir, NULL, - S_IFCHR | WHITEOUT_MODE, whiteout); + S_IFCHR | WHITEOUT_MODE, true, whiteout); +} + +int f2fs_get_tmpfile(struct user_namespace *mnt_userns, struct inode *dir, + struct inode **new_inode) +{ + return __f2fs_tmpfile(mnt_userns, dir, NULL, S_IFREG, false, new_inode); } static int f2fs_rename(struct user_namespace *mnt_userns, struct inode *old_dir, @@ -995,20 +1005,12 @@ static int f2fs_rename(struct user_namespace *mnt_userns, struct inode *old_dir, goto out; } - /* - * Copied from ext4_rename: we need to protect against old.inode - * directory getting converted from inline directory format into - * a normal one. - */ - if (S_ISDIR(old_inode->i_mode)) - inode_lock_nested(old_inode, I_MUTEX_NONDIR2); - err = -ENOENT; old_entry = f2fs_find_entry(old_dir, &old_dentry->d_name, &old_page); if (!old_entry) { if (IS_ERR(old_page)) err = PTR_ERR(old_page); - goto out_unlock_old; + goto out; } if (S_ISDIR(old_inode->i_mode)) { @@ -1116,9 +1118,6 @@ static int f2fs_rename(struct user_namespace *mnt_userns, struct inode *old_dir, f2fs_unlock_op(sbi); - if (S_ISDIR(old_inode->i_mode)) - inode_unlock(old_inode); - if (IS_DIRSYNC(old_dir) || IS_DIRSYNC(new_dir)) f2fs_sync_fs(sbi->sb, 1); @@ -1133,9 +1132,6 @@ out_dir: f2fs_put_page(old_dir_page, 0); out_old: f2fs_put_page(old_page, 0); -out_unlock_old: - if (S_ISDIR(old_inode->i_mode)) - inode_unlock(old_inode); out: iput(whiteout); return err; diff --git a/fs/f2fs/node.c b/fs/f2fs/node.c index 2b48b7c12beb..54fa770621e5 100644 --- a/fs/f2fs/node.c +++ b/fs/f2fs/node.c @@ -90,10 +90,6 @@ bool f2fs_available_free_memory(struct f2fs_sb_info *sbi, int type) atomic_read(&sbi->total_ext_node) * sizeof(struct extent_node)) >> PAGE_SHIFT; res = mem_size < ((avail_ram * nm_i->ram_thresh / 100) >> 1); - } else if (type == INMEM_PAGES) { - /* it allows 20% / total_ram for inmemory pages */ - mem_size = get_pages(sbi, F2FS_INMEM_PAGES); - res = mem_size < (val.totalram / 5); } else if (type == DISCARD_CACHE) { mem_size = (atomic_read(&dcc->discard_cmd_cnt) * sizeof(struct discard_cmd)) >> PAGE_SHIFT; @@ -942,8 +938,10 @@ static int truncate_dnode(struct dnode_of_data *dn) dn->ofs_in_node = 0; f2fs_truncate_data_blocks(dn); err = truncate_node(dn); - if (err) + if (err) { + f2fs_put_page(page, 1); return err; + } return 1; } diff --git a/fs/f2fs/node.h b/fs/f2fs/node.h index 4c1d34bfea78..3c09cae058b0 100644 --- a/fs/f2fs/node.h +++ b/fs/f2fs/node.h @@ -147,7 +147,6 @@ enum mem_type { DIRTY_DENTS, /* indicates dirty dentry pages */ INO_ENTRIES, /* indicates inode entries */ EXTENT_CACHE, /* indicates extent cache */ - INMEM_PAGES, /* indicates inmemory pages */ DISCARD_CACHE, /* indicates memory of cached discard cmds */ COMPRESS_PAGE, /* indicates memory of cached compressed pages */ BASE_CHECK, /* check kernel status */ diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c index b2c750af24bb..1d109901fa37 100644 --- a/fs/f2fs/segment.c +++ b/fs/f2fs/segment.c @@ -29,7 +29,7 @@ static struct kmem_cache *discard_entry_slab; static struct kmem_cache *discard_cmd_slab; static struct kmem_cache *sit_entry_set_slab; -static struct kmem_cache *inmem_entry_slab; +static struct kmem_cache *revoke_entry_slab; static unsigned long __reverse_ulong(unsigned char *str) { @@ -184,308 +184,204 @@ bool f2fs_need_SSR(struct f2fs_sb_info *sbi) SM_I(sbi)->min_ssr_sections + reserved_sections(sbi)); } -void f2fs_register_inmem_page(struct inode *inode, struct page *page) +void f2fs_abort_atomic_write(struct inode *inode, bool clean) { - struct inmem_pages *new; + struct f2fs_inode_info *fi = F2FS_I(inode); - set_page_private_atomic(page); + if (!f2fs_is_atomic_file(inode)) + return; - new = f2fs_kmem_cache_alloc(inmem_entry_slab, - GFP_NOFS, true, NULL); + release_atomic_write_cnt(inode); + clear_inode_flag(inode, FI_ATOMIC_COMMITTED); + clear_inode_flag(inode, FI_ATOMIC_REPLACE); + clear_inode_flag(inode, FI_ATOMIC_FILE); + stat_dec_atomic_inode(inode); - /* add atomic page indices to the list */ - new->page = page; - INIT_LIST_HEAD(&new->list); + F2FS_I(inode)->atomic_write_task = NULL; - /* increase reference count with clean state */ - get_page(page); - mutex_lock(&F2FS_I(inode)->inmem_lock); - list_add_tail(&new->list, &F2FS_I(inode)->inmem_pages); - inc_page_count(F2FS_I_SB(inode), F2FS_INMEM_PAGES); - mutex_unlock(&F2FS_I(inode)->inmem_lock); - - trace_f2fs_register_inmem_page(page, INMEM); + if (clean) { + truncate_inode_pages_final(inode->i_mapping); + f2fs_i_size_write(inode, fi->original_i_size); + fi->original_i_size = 0; + } } -static int __revoke_inmem_pages(struct inode *inode, - struct list_head *head, bool drop, bool recover, - bool trylock) +static int __replace_atomic_write_block(struct inode *inode, pgoff_t index, + block_t new_addr, block_t *old_addr, bool recover) { struct f2fs_sb_info *sbi = F2FS_I_SB(inode); - struct inmem_pages *cur, *tmp; - int err = 0; + struct dnode_of_data dn; + struct node_info ni; + int err; + +retry: + set_new_dnode(&dn, inode, NULL, NULL, 0); + err = f2fs_get_dnode_of_data(&dn, index, ALLOC_NODE); + if (err) { + if (err == -ENOMEM) { + f2fs_io_schedule_timeout(DEFAULT_IO_TIMEOUT); + goto retry; + } + return err; + } + + err = f2fs_get_node_info(sbi, dn.nid, &ni, false); + if (err) { + f2fs_put_dnode(&dn); + return err; + } + + if (recover) { + /* dn.data_blkaddr is always valid */ + if (!__is_valid_data_blkaddr(new_addr)) { + if (new_addr == NULL_ADDR) + dec_valid_block_count(sbi, inode, 1); + f2fs_invalidate_blocks(sbi, dn.data_blkaddr); + f2fs_update_data_blkaddr(&dn, new_addr); + } else { + f2fs_replace_block(sbi, &dn, dn.data_blkaddr, + new_addr, ni.version, true, true); + } + } else { + blkcnt_t count = 1; + + err = inc_valid_block_count(sbi, inode, &count); + if (err) { + f2fs_put_dnode(&dn); + return err; + } + + *old_addr = dn.data_blkaddr; + f2fs_truncate_data_blocks_range(&dn, 1); + dec_valid_block_count(sbi, F2FS_I(inode)->cow_inode, count); + + f2fs_replace_block(sbi, &dn, dn.data_blkaddr, new_addr, + ni.version, true, false); + } + + f2fs_put_dnode(&dn); + + trace_f2fs_replace_atomic_write_block(inode, F2FS_I(inode)->cow_inode, + index, old_addr ? *old_addr : 0, new_addr, recover); + return 0; +} + +static void __complete_revoke_list(struct inode *inode, struct list_head *head, + bool revoke) +{ + struct revoke_entry *cur, *tmp; + pgoff_t start_index = 0; + bool truncate = is_inode_flag_set(inode, FI_ATOMIC_REPLACE); list_for_each_entry_safe(cur, tmp, head, list) { - struct page *page = cur->page; - - if (drop) - trace_f2fs_commit_inmem_page(page, INMEM_DROP); - - if (trylock) { - /* - * to avoid deadlock in between page lock and - * inmem_lock. - */ - if (!trylock_page(page)) - continue; - } else { - lock_page(page); + if (revoke) { + __replace_atomic_write_block(inode, cur->index, + cur->old_addr, NULL, true); + } else if (truncate) { + f2fs_truncate_hole(inode, start_index, cur->index); + start_index = cur->index + 1; } - f2fs_wait_on_page_writeback(page, DATA, true, true); - - if (recover) { - struct dnode_of_data dn; - struct node_info ni; - - trace_f2fs_commit_inmem_page(page, INMEM_REVOKE); -retry: - set_new_dnode(&dn, inode, NULL, NULL, 0); - err = f2fs_get_dnode_of_data(&dn, page->index, - LOOKUP_NODE); - if (err) { - if (err == -ENOMEM) { - congestion_wait(BLK_RW_ASYNC, - DEFAULT_IO_TIMEOUT); - cond_resched(); - goto retry; - } - err = -EAGAIN; - goto next; - } - - err = f2fs_get_node_info(sbi, dn.nid, &ni, false); - if (err) { - f2fs_put_dnode(&dn); - return err; - } - - if (cur->old_addr == NEW_ADDR) { - f2fs_invalidate_blocks(sbi, dn.data_blkaddr); - f2fs_update_data_blkaddr(&dn, NEW_ADDR); - } else - f2fs_replace_block(sbi, &dn, dn.data_blkaddr, - cur->old_addr, ni.version, true, true); - f2fs_put_dnode(&dn); - } -next: - /* we don't need to invalidate this in the sccessful status */ - if (drop || recover) { - ClearPageUptodate(page); - clear_page_private_gcing(page); - } - detach_page_private(page); - set_page_private(page, 0); - f2fs_put_page(page, 1); - list_del(&cur->list); - kmem_cache_free(inmem_entry_slab, cur); - dec_page_count(F2FS_I_SB(inode), F2FS_INMEM_PAGES); + kmem_cache_free(revoke_entry_slab, cur); } - return err; + + if (!revoke && truncate) + f2fs_do_truncate_blocks(inode, start_index * PAGE_SIZE, false); } -void f2fs_drop_inmem_pages_all(struct f2fs_sb_info *sbi, bool gc_failure) -{ - struct list_head *head = &sbi->inode_list[ATOMIC_FILE]; - struct inode *inode; - struct f2fs_inode_info *fi; - unsigned int count = sbi->atomic_files; - unsigned int looped = 0; -next: - spin_lock(&sbi->inode_lock[ATOMIC_FILE]); - if (list_empty(head)) { - spin_unlock(&sbi->inode_lock[ATOMIC_FILE]); - return; - } - fi = list_first_entry(head, struct f2fs_inode_info, inmem_ilist); - inode = igrab(&fi->vfs_inode); - if (inode) - list_move_tail(&fi->inmem_ilist, head); - spin_unlock(&sbi->inode_lock[ATOMIC_FILE]); - - if (inode) { - if (gc_failure) { - if (!fi->i_gc_failures[GC_FAILURE_ATOMIC]) - goto skip; - } - set_inode_flag(inode, FI_ATOMIC_REVOKE_REQUEST); - f2fs_drop_inmem_pages(inode); -skip: - iput(inode); - } - f2fs_io_schedule_timeout(DEFAULT_IO_TIMEOUT); - if (gc_failure) { - if (++looped >= count) - return; - } - goto next; -} - -void f2fs_drop_inmem_pages(struct inode *inode) +static int __f2fs_commit_atomic_write(struct inode *inode) { struct f2fs_sb_info *sbi = F2FS_I_SB(inode); struct f2fs_inode_info *fi = F2FS_I(inode); - - do { - mutex_lock(&fi->inmem_lock); - if (list_empty(&fi->inmem_pages)) { - fi->i_gc_failures[GC_FAILURE_ATOMIC] = 0; - - spin_lock(&sbi->inode_lock[ATOMIC_FILE]); - if (!list_empty(&fi->inmem_ilist)) - list_del_init(&fi->inmem_ilist); - if (f2fs_is_atomic_file(inode)) { - clear_inode_flag(inode, FI_ATOMIC_FILE); - sbi->atomic_files--; - } - spin_unlock(&sbi->inode_lock[ATOMIC_FILE]); - - mutex_unlock(&fi->inmem_lock); - break; - } - __revoke_inmem_pages(inode, &fi->inmem_pages, - true, false, true); - mutex_unlock(&fi->inmem_lock); - } while (1); -} - -void f2fs_drop_inmem_page(struct inode *inode, struct page *page) -{ - struct f2fs_inode_info *fi = F2FS_I(inode); - struct f2fs_sb_info *sbi = F2FS_I_SB(inode); - struct list_head *head = &fi->inmem_pages; - struct inmem_pages *cur = NULL; - struct inmem_pages *tmp; - - f2fs_bug_on(sbi, !page_private_atomic(page)); - - mutex_lock(&fi->inmem_lock); - list_for_each_entry(tmp, head, list) { - if (tmp->page == page) { - cur = tmp; - break; - } - } - - f2fs_bug_on(sbi, !cur); - list_del(&cur->list); - mutex_unlock(&fi->inmem_lock); - - dec_page_count(sbi, F2FS_INMEM_PAGES); - kmem_cache_free(inmem_entry_slab, cur); - - ClearPageUptodate(page); - clear_page_private_atomic(page); - f2fs_put_page(page, 0); - - detach_page_private(page); - set_page_private(page, 0); - - trace_f2fs_commit_inmem_page(page, INMEM_INVALIDATE); -} - -static int __f2fs_commit_inmem_pages(struct inode *inode) -{ - struct f2fs_sb_info *sbi = F2FS_I_SB(inode); - struct f2fs_inode_info *fi = F2FS_I(inode); - struct inmem_pages *cur, *tmp; - struct f2fs_io_info fio = { - .sbi = sbi, - .ino = inode->i_ino, - .type = DATA, - .op = REQ_OP_WRITE, - .op_flags = REQ_SYNC | REQ_PRIO, - .io_type = FS_DATA_IO, - }; + struct inode *cow_inode = fi->cow_inode; + struct revoke_entry *new; struct list_head revoke_list; - bool submit_bio = false; - int err = 0; + block_t blkaddr; + struct dnode_of_data dn; + pgoff_t len = DIV_ROUND_UP(i_size_read(inode), PAGE_SIZE); + pgoff_t off = 0, blen, index; + int ret = 0, i; INIT_LIST_HEAD(&revoke_list); - list_for_each_entry_safe(cur, tmp, &fi->inmem_pages, list) { - struct page *page = cur->page; + while (len) { + blen = min_t(pgoff_t, ADDRS_PER_BLOCK(cow_inode), len); - lock_page(page); - if (page->mapping == inode->i_mapping) { - trace_f2fs_commit_inmem_page(page, INMEM); - - f2fs_wait_on_page_writeback(page, DATA, true, true); - - set_page_dirty(page); - if (clear_page_dirty_for_io(page)) { - inode_dec_dirty_pages(inode); - f2fs_remove_dirty_inode(inode); - } -retry: - fio.page = page; - fio.old_blkaddr = NULL_ADDR; - fio.encrypted_page = NULL; - fio.need_lock = LOCK_DONE; - err = f2fs_do_write_data_page(&fio); - if (err) { - if (err == -ENOMEM) { - congestion_wait(BLK_RW_ASYNC, - DEFAULT_IO_TIMEOUT); - cond_resched(); - goto retry; - } - unlock_page(page); - break; - } - /* record old blkaddr for revoking */ - cur->old_addr = fio.old_blkaddr; - submit_bio = true; + set_new_dnode(&dn, cow_inode, NULL, NULL, 0); + ret = f2fs_get_dnode_of_data(&dn, off, LOOKUP_NODE_RA); + if (ret && ret != -ENOENT) { + goto out; + } else if (ret == -ENOENT) { + ret = 0; + if (dn.max_level == 0) + goto out; + goto next; } - unlock_page(page); - list_move_tail(&cur->list, &revoke_list); + + blen = min((pgoff_t)ADDRS_PER_PAGE(dn.node_page, cow_inode), + len); + index = off; + for (i = 0; i < blen; i++, dn.ofs_in_node++, index++) { + blkaddr = f2fs_data_blkaddr(&dn); + + if (!__is_valid_data_blkaddr(blkaddr)) { + continue; + } else if (!f2fs_is_valid_blkaddr(sbi, blkaddr, + DATA_GENERIC_ENHANCE)) { + f2fs_put_dnode(&dn); + ret = -EFSCORRUPTED; + goto out; + } + + new = f2fs_kmem_cache_alloc(revoke_entry_slab, GFP_NOFS, + true, NULL); + + ret = __replace_atomic_write_block(inode, index, blkaddr, + &new->old_addr, false); + if (ret) { + f2fs_put_dnode(&dn); + kmem_cache_free(revoke_entry_slab, new); + goto out; + } + + f2fs_update_data_blkaddr(&dn, NULL_ADDR); + new->index = index; + list_add_tail(&new->list, &revoke_list); + } + f2fs_put_dnode(&dn); +next: + off += blen; + len -= blen; } - if (submit_bio) - f2fs_submit_merged_write_cond(sbi, inode, NULL, 0, DATA); - - if (err) { - /* - * try to revoke all committed pages, but still we could fail - * due to no memory or other reason, if that happened, EAGAIN - * will be returned, which means in such case, transaction is - * already not integrity, caller should use journal to do the - * recovery or rewrite & commit last transaction. For other - * error number, revoking was done by filesystem itself. - */ - err = __revoke_inmem_pages(inode, &revoke_list, - false, true, false); - - /* drop all uncommitted pages */ - __revoke_inmem_pages(inode, &fi->inmem_pages, - true, false, false); +out: + if (ret) { + sbi->revoked_atomic_block += fi->atomic_write_cnt; } else { - __revoke_inmem_pages(inode, &revoke_list, - false, false, false); + sbi->committed_atomic_block += fi->atomic_write_cnt; + set_inode_flag(inode, FI_ATOMIC_COMMITTED); } - return err; + __complete_revoke_list(inode, &revoke_list, ret ? true : false); + + return ret; } -int f2fs_commit_inmem_pages(struct inode *inode) +int f2fs_commit_atomic_write(struct inode *inode) { struct f2fs_sb_info *sbi = F2FS_I_SB(inode); struct f2fs_inode_info *fi = F2FS_I(inode); int err; - f2fs_balance_fs(sbi, true); + err = filemap_write_and_wait_range(inode->i_mapping, 0, LLONG_MAX); + if (err) + return err; f2fs_down_write(&fi->i_gc_rwsem[WRITE]); - f2fs_lock_op(sbi); - set_inode_flag(inode, FI_ATOMIC_COMMIT); - mutex_lock(&fi->inmem_lock); - err = __f2fs_commit_inmem_pages(inode); - mutex_unlock(&fi->inmem_lock); - - clear_inode_flag(inode, FI_ATOMIC_COMMIT); + err = __f2fs_commit_atomic_write(inode); f2fs_unlock_op(sbi); f2fs_up_write(&fi->i_gc_rwsem[WRITE]); @@ -3392,8 +3288,7 @@ static int __get_segment_type_6(struct f2fs_io_info *fio) return CURSEG_COLD_DATA; if (file_is_hot(inode) || is_inode_flag_set(inode, FI_HOT_DATA) || - f2fs_is_atomic_file(inode) || - f2fs_is_volatile_file(inode)) + f2fs_is_cow_file(inode)) return CURSEG_HOT_DATA; return f2fs_rw_hint_to_seg_type(inode->i_write_hint); } else { @@ -5416,9 +5311,9 @@ int __init f2fs_create_segment_manager_caches(void) if (!sit_entry_set_slab) goto destroy_discard_cmd; - inmem_entry_slab = f2fs_kmem_cache_create("f2fs_inmem_page_entry", - sizeof(struct inmem_pages)); - if (!inmem_entry_slab) + revoke_entry_slab = f2fs_kmem_cache_create("f2fs_revoke_entry", + sizeof(struct revoke_entry)); + if (!revoke_entry_slab) goto destroy_sit_entry_set; return 0; @@ -5437,5 +5332,5 @@ void f2fs_destroy_segment_manager_caches(void) kmem_cache_destroy(sit_entry_set_slab); kmem_cache_destroy(discard_cmd_slab); kmem_cache_destroy(discard_entry_slab); - kmem_cache_destroy(inmem_entry_slab); + kmem_cache_destroy(revoke_entry_slab); } diff --git a/fs/f2fs/segment.h b/fs/f2fs/segment.h index 9d3400ad5c23..6bf414c013c7 100644 --- a/fs/f2fs/segment.h +++ b/fs/f2fs/segment.h @@ -231,10 +231,10 @@ struct segment_allocation { #define MAX_SKIP_GC_COUNT 16 -struct inmem_pages { +struct revoke_entry { struct list_head list; - struct page *page; block_t old_addr; /* for revoking when fail to commit */ + pgoff_t index; }; struct sit_info { diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c index 51063510c332..30ce903388ed 100644 --- a/fs/f2fs/super.c +++ b/fs/f2fs/super.c @@ -1384,9 +1384,6 @@ static struct inode *f2fs_alloc_inode(struct super_block *sb) spin_lock_init(&fi->i_size_lock); INIT_LIST_HEAD(&fi->dirty_list); INIT_LIST_HEAD(&fi->gdirty_list); - INIT_LIST_HEAD(&fi->inmem_ilist); - INIT_LIST_HEAD(&fi->inmem_pages); - mutex_init(&fi->inmem_lock); init_f2fs_rwsem(&fi->i_gc_rwsem[READ]); init_f2fs_rwsem(&fi->i_gc_rwsem[WRITE]); init_f2fs_rwsem(&fi->i_xattr_sem); @@ -1427,10 +1424,6 @@ static int f2fs_drop_inode(struct inode *inode) atomic_inc(&inode->i_count); spin_unlock(&inode->i_lock); - /* some remained atomic pages should discarded */ - if (f2fs_is_atomic_file(inode)) - f2fs_drop_inmem_pages(inode); - /* should remain fi->extent_tree for writepage */ f2fs_destroy_extent_node(inode); @@ -3627,6 +3620,7 @@ static void init_sb_info(struct f2fs_sb_info *sbi) sbi->max_fragment_chunk = DEF_FRAGMENT_SIZE; sbi->max_fragment_hole = DEF_FRAGMENT_SIZE; spin_lock_init(&sbi->gc_urgent_high_lock); + atomic64_set(&sbi->current_atomic_write, 0); sbi->dir_level = DEF_DIR_LEVEL; sbi->interval_time[CP_TIME] = DEF_CP_INTERVAL; diff --git a/fs/f2fs/sysfs.c b/fs/f2fs/sysfs.c index ca187e4231cb..32c071afdadb 100644 --- a/fs/f2fs/sysfs.c +++ b/fs/f2fs/sysfs.c @@ -340,6 +340,21 @@ static ssize_t f2fs_sbi_show(struct f2fs_attr *a, sbi->gc_reclaimed_segs[sbi->gc_segment_mode]); } + if (!strcmp(a->attr.name, "current_atomic_write")) { + s64 current_write = atomic64_read(&sbi->current_atomic_write); + + return sysfs_emit(buf, "%lld\n", current_write); + } + + if (!strcmp(a->attr.name, "peak_atomic_write")) + return sysfs_emit(buf, "%lld\n", sbi->peak_atomic_write); + + if (!strcmp(a->attr.name, "committed_atomic_block")) + return sysfs_emit(buf, "%llu\n", sbi->committed_atomic_block); + + if (!strcmp(a->attr.name, "revoked_atomic_block")) + return sysfs_emit(buf, "%llu\n", sbi->revoked_atomic_block); + ui = (unsigned int *)(ptr + a->offset); return sprintf(buf, "%u\n", *ui); @@ -608,6 +623,27 @@ out: return count; } + if (!strcmp(a->attr.name, "peak_atomic_write")) { + if (t != 0) + return -EINVAL; + sbi->peak_atomic_write = 0; + return count; + } + + if (!strcmp(a->attr.name, "committed_atomic_block")) { + if (t != 0) + return -EINVAL; + sbi->committed_atomic_block = 0; + return count; + } + + if (!strcmp(a->attr.name, "revoked_atomic_block")) { + if (t != 0) + return -EINVAL; + sbi->revoked_atomic_block = 0; + return count; + } + *ui = (unsigned int)t; return count; @@ -713,6 +749,11 @@ static struct f2fs_attr f2fs_attr_##_name = { \ .offset = _offset \ } +#define F2FS_RO_ATTR(struct_type, struct_name, name, elname) \ + F2FS_ATTR_OFFSET(struct_type, name, 0444, \ + f2fs_sbi_show, NULL, \ + offsetof(struct struct_name, elname)) + #define F2FS_RW_ATTR(struct_type, struct_name, name, elname) \ F2FS_ATTR_OFFSET(struct_type, name, 0644, \ f2fs_sbi_show, f2fs_sbi_store, \ @@ -811,6 +852,8 @@ F2FS_FEATURE_RO_ATTR(encrypted_casefold); #endif /* CONFIG_FS_ENCRYPTION */ #ifdef CONFIG_BLK_DEV_ZONED F2FS_FEATURE_RO_ATTR(block_zoned); +F2FS_RO_ATTR(F2FS_SBI, f2fs_sb_info, unusable_blocks_per_sec, + unusable_blocks_per_sec); #endif F2FS_FEATURE_RO_ATTR(atomic_write); F2FS_FEATURE_RO_ATTR(extra_attr); @@ -848,6 +891,12 @@ F2FS_RW_ATTR(F2FS_SBI, f2fs_sb_info, gc_reclaimed_segments, gc_reclaimed_segs); F2FS_RW_ATTR(F2FS_SBI, f2fs_sb_info, max_fragment_chunk, max_fragment_chunk); F2FS_RW_ATTR(F2FS_SBI, f2fs_sb_info, max_fragment_hole, max_fragment_hole); +/* For atomic write */ +F2FS_RO_ATTR(F2FS_SBI, f2fs_sb_info, current_atomic_write, current_atomic_write); +F2FS_RW_ATTR(F2FS_SBI, f2fs_sb_info, peak_atomic_write, peak_atomic_write); +F2FS_RW_ATTR(F2FS_SBI, f2fs_sb_info, committed_atomic_block, committed_atomic_block); +F2FS_RW_ATTR(F2FS_SBI, f2fs_sb_info, revoked_atomic_block, revoked_atomic_block); + #define ATTR_LIST(name) (&f2fs_attr_##name.attr) static struct attribute *f2fs_attrs[] = { ATTR_LIST(gc_urgent_sleep_time), @@ -919,6 +968,9 @@ static struct attribute *f2fs_attrs[] = { ATTR_LIST(moved_blocks_background), ATTR_LIST(avg_vblocks), #endif +#ifdef CONFIG_BLK_DEV_ZONED + ATTR_LIST(unusable_blocks_per_sec), +#endif #ifdef CONFIG_F2FS_FS_COMPRESSION ATTR_LIST(compr_written_block), ATTR_LIST(compr_saved_block), @@ -934,6 +986,10 @@ static struct attribute *f2fs_attrs[] = { ATTR_LIST(gc_reclaimed_segments), ATTR_LIST(max_fragment_chunk), ATTR_LIST(max_fragment_hole), + ATTR_LIST(current_atomic_write), + ATTR_LIST(peak_atomic_write), + ATTR_LIST(committed_atomic_block), + ATTR_LIST(revoked_atomic_block), NULL, }; ATTRIBUTE_GROUPS(f2fs); diff --git a/fs/f2fs/verity.c b/fs/f2fs/verity.c index 23d23cc5c5b0..652a7a384eaa 100644 --- a/fs/f2fs/verity.c +++ b/fs/f2fs/verity.c @@ -122,7 +122,7 @@ static int f2fs_begin_enable_verity(struct file *filp) if (f2fs_verity_in_progress(inode)) return -EBUSY; - if (f2fs_is_atomic_file(inode) || f2fs_is_volatile_file(inode)) + if (f2fs_is_atomic_file(inode)) return -EOPNOTSUPP; /* diff --git a/fs/f2fs/xattr.c b/fs/f2fs/xattr.c index c76c15086e5f..f7a076d8741d 100644 --- a/fs/f2fs/xattr.c +++ b/fs/f2fs/xattr.c @@ -525,10 +525,12 @@ int f2fs_getxattr(struct inode *inode, int index, const char *name, if (len > F2FS_NAME_LEN) return -ERANGE; - f2fs_down_read(&F2FS_I(inode)->i_xattr_sem); + if (!ipage) + f2fs_down_read(&F2FS_I(inode)->i_xattr_sem); error = lookup_all_xattrs(inode, ipage, index, len, name, &entry, &base_addr, &base_size, &is_inline); - f2fs_up_read(&F2FS_I(inode)->i_xattr_sem); + if (!ipage) + f2fs_up_read(&F2FS_I(inode)->i_xattr_sem); if (error) return error; diff --git a/fs/fs_context.c b/fs/fs_context.c index 24ce12f0db32..851214d1d013 100644 --- a/fs/fs_context.c +++ b/fs/fs_context.c @@ -561,7 +561,8 @@ static int legacy_parse_param(struct fs_context *fc, struct fs_parameter *param) return -ENOMEM; } - ctx->legacy_data[size++] = ','; + if (size) + ctx->legacy_data[size++] = ','; len = strlen(param->key); memcpy(ctx->legacy_data + size, param->key, len); size += len; diff --git a/fs/fuse/backing.c b/fs/fuse/backing.c index aa100e4fd3f9..691d28159c21 100644 --- a/fs/fuse/backing.c +++ b/fs/fuse/backing.c @@ -1446,32 +1446,34 @@ int fuse_mkdir_initialize( int fuse_mkdir_backing( struct fuse_bpf_args *fa, - struct inode *dir, struct dentry *entry, umode_t mode) + struct inode *dir_inode, struct dentry *entry, umode_t mode) { int err = 0; const struct fuse_mkdir_in *fmi = fa->in_args[0].value; - struct fuse_inode *fuse_inode = get_fuse_inode(dir); - struct inode *backing_inode = fuse_inode->backing_inode; + struct fuse_inode *dir_fuse_inode = get_fuse_inode(dir_inode); + struct inode *dir_backing_inode = dir_fuse_inode->backing_inode; struct path backing_path = {}; struct inode *inode = NULL; - struct dentry *d; //TODO Actually deal with changing the backing entry in mkdir get_fuse_backing_path(entry, &backing_path); if (!backing_path.dentry) return -EBADF; - inode_lock_nested(backing_inode, I_MUTEX_PARENT); + inode_lock_nested(dir_backing_inode, I_MUTEX_PARENT); mode = fmi->mode; - if (!IS_POSIXACL(backing_inode)) + if (!IS_POSIXACL(dir_backing_inode)) mode &= ~fmi->umask; - err = vfs_mkdir(&init_user_ns, backing_inode, backing_path.dentry, mode); + err = vfs_mkdir(&init_user_ns, dir_backing_inode, backing_path.dentry, + mode); if (err) goto out; if (d_really_is_negative(backing_path.dentry) || unlikely(d_unhashed(backing_path.dentry))) { - d = lookup_one_len(entry->d_name.name, backing_path.dentry->d_parent, - entry->d_name.len); + struct dentry *d = lookup_one_len(entry->d_name.name, + backing_path.dentry->d_parent, + entry->d_name.len); + if (IS_ERR(d)) { err = PTR_ERR(d); goto out; @@ -1479,14 +1481,19 @@ int fuse_mkdir_backing( dput(backing_path.dentry); backing_path.dentry = d; } - inode = fuse_iget_backing(dir->i_sb, fuse_inode->nodeid, backing_inode); + inode = fuse_iget_backing(dir_inode->i_sb, 0, + backing_path.dentry->d_inode); if (IS_ERR(inode)) { err = PTR_ERR(inode); goto out; } d_instantiate(entry, inode); + if (get_fuse_inode(inode)->bpf) + bpf_prog_put(get_fuse_inode(inode)->bpf); + get_fuse_inode(inode)->bpf = get_fuse_dentry(entry)->bpf; + get_fuse_dentry(entry)->bpf = NULL; out: - inode_unlock(backing_inode); + inode_unlock(dir_backing_inode); path_put(&backing_path); return err; } diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c index b0164fa947f8..f3ed2ff426cd 100644 --- a/fs/fuse/dir.c +++ b/fs/fuse/dir.c @@ -186,7 +186,7 @@ static bool backing_data_changed(struct fuse_inode *fi, struct dentry *entry, int err; bool ret = true; - if (!entry) { + if (!entry || !fi->backing_inode) { ret = false; goto put_backing_file; } diff --git a/fs/fuse/ioctl.c b/fs/fuse/ioctl.c index 7dcadd8dc29a..db5aadc996ad 100644 --- a/fs/fuse/ioctl.c +++ b/fs/fuse/ioctl.c @@ -9,14 +9,23 @@ #include #include -static ssize_t fuse_send_ioctl(struct fuse_mount *fm, struct fuse_args *args) +static ssize_t fuse_send_ioctl(struct fuse_mount *fm, struct fuse_args *args, + struct fuse_ioctl_out *outarg) { - ssize_t ret = fuse_simple_request(fm, args); + ssize_t ret; + + args->out_args[0].size = sizeof(*outarg); + args->out_args[0].value = outarg; + + ret = fuse_simple_request(fm, args); /* Translate ENOSYS, which shouldn't be returned from fs */ if (ret == -ENOSYS) ret = -ENOTTY; + if (ret >= 0 && outarg->result == -ENOSYS) + outarg->result = -ENOTTY; + return ret; } @@ -264,13 +273,11 @@ long fuse_do_ioctl(struct file *file, unsigned int cmd, unsigned long arg, } ap.args.out_numargs = 2; - ap.args.out_args[0].size = sizeof(outarg); - ap.args.out_args[0].value = &outarg; ap.args.out_args[1].size = out_size; ap.args.out_pages = true; ap.args.out_argvar = true; - transferred = fuse_send_ioctl(fm, &ap.args); + transferred = fuse_send_ioctl(fm, &ap.args, &outarg); err = transferred; if (transferred < 0) goto out; @@ -408,12 +415,10 @@ static int fuse_priv_ioctl(struct inode *inode, struct fuse_file *ff, args.in_args[1].size = inarg.in_size; args.in_args[1].value = ptr; args.out_numargs = 2; - args.out_args[0].size = sizeof(outarg); - args.out_args[0].value = &outarg; args.out_args[1].size = inarg.out_size; args.out_args[1].value = ptr; - err = fuse_send_ioctl(fm, &args); + err = fuse_send_ioctl(fm, &args, &outarg); if (!err) { if (outarg.result < 0) err = outarg.result; diff --git a/fs/inode.c b/fs/inode.c index f53c8036f44a..e906ef237e8a 100644 --- a/fs/inode.c +++ b/fs/inode.c @@ -1023,6 +1023,48 @@ void discard_new_inode(struct inode *inode) } EXPORT_SYMBOL(discard_new_inode); +/** + * lock_two_inodes - lock two inodes (may be regular files but also dirs) + * + * Lock any non-NULL argument. The caller must make sure that if he is passing + * in two directories, one is not ancestor of the other. Zero, one or two + * objects may be locked by this function. + * + * @inode1: first inode to lock + * @inode2: second inode to lock + * @subclass1: inode lock subclass for the first lock obtained + * @subclass2: inode lock subclass for the second lock obtained + */ +void lock_two_inodes(struct inode *inode1, struct inode *inode2, + unsigned subclass1, unsigned subclass2) +{ + if (!inode1 || !inode2) { + /* + * Make sure @subclass1 will be used for the acquired lock. + * This is not strictly necessary (no current caller cares) but + * let's keep things consistent. + */ + if (!inode1) + swap(inode1, inode2); + goto lock; + } + + /* + * If one object is directory and the other is not, we must make sure + * to lock directory first as the other object may be its child. + */ + if (S_ISDIR(inode2->i_mode) == S_ISDIR(inode1->i_mode)) { + if (inode1 > inode2) + swap(inode1, inode2); + } else if (!S_ISDIR(inode1->i_mode)) + swap(inode1, inode2); +lock: + if (inode1) + inode_lock_nested(inode1, subclass1); + if (inode2 && inode2 != inode1) + inode_lock_nested(inode2, subclass2); +} + /** * lock_two_nondirectories - take two i_mutexes on non-directory objects * diff --git a/fs/internal.h b/fs/internal.h index 46df4ce58e87..ceb154583a3c 100644 --- a/fs/internal.h +++ b/fs/internal.h @@ -152,6 +152,8 @@ extern void inode_add_lru(struct inode *inode); int dentry_needs_remove_privs(struct user_namespace *, struct dentry *dentry); bool in_group_or_capable(struct user_namespace *mnt_userns, const struct inode *inode, kgid_t gid); +void lock_two_inodes(struct inode *inode1, struct inode *inode2, + unsigned subclass1, unsigned subclass2); /* * fs-writeback.c diff --git a/fs/jbd2/checkpoint.c b/fs/jbd2/checkpoint.c index 746132998c57..fe8bb031b7d7 100644 --- a/fs/jbd2/checkpoint.c +++ b/fs/jbd2/checkpoint.c @@ -57,28 +57,6 @@ static inline void __buffer_unlink(struct journal_head *jh) } } -/* - * Move a buffer from the checkpoint list to the checkpoint io list - * - * Called with j_list_lock held - */ -static inline void __buffer_relink_io(struct journal_head *jh) -{ - transaction_t *transaction = jh->b_cp_transaction; - - __buffer_unlink_first(jh); - - if (!transaction->t_checkpoint_io_list) { - jh->b_cpnext = jh->b_cpprev = jh; - } else { - jh->b_cpnext = transaction->t_checkpoint_io_list; - jh->b_cpprev = transaction->t_checkpoint_io_list->b_cpprev; - jh->b_cpprev->b_cpnext = jh; - jh->b_cpnext->b_cpprev = jh; - } - transaction->t_checkpoint_io_list = jh; -} - /* * Check a checkpoint buffer could be release or not. * @@ -183,6 +161,7 @@ __flush_batch(journal_t *journal, int *batch_count) struct buffer_head *bh = journal->j_chkpt_bhs[i]; BUFFER_TRACE(bh, "brelse"); __brelse(bh); + journal->j_chkpt_bhs[i] = NULL; } *batch_count = 0; } @@ -242,6 +221,11 @@ restart: jh = transaction->t_checkpoint_list; bh = jh2bh(jh); + /* + * The buffer may be writing back, or flushing out in the + * last couple of cycles, or re-adding into a new transaction, + * need to check it again until it's unlocked. + */ if (buffer_locked(bh)) { get_bh(bh); spin_unlock(&journal->j_list_lock); @@ -287,28 +271,32 @@ restart: } if (!buffer_dirty(bh)) { BUFFER_TRACE(bh, "remove from checkpoint"); - if (__jbd2_journal_remove_checkpoint(jh)) - /* The transaction was released; we're done */ + /* + * If the transaction was released or the checkpoint + * list was empty, we're done. + */ + if (__jbd2_journal_remove_checkpoint(jh) || + !transaction->t_checkpoint_list) goto out; - continue; + } else { + /* + * We are about to write the buffer, it could be + * raced by some other transaction shrink or buffer + * re-log logic once we release the j_list_lock, + * leave it on the checkpoint list and check status + * again to make sure it's clean. + */ + BUFFER_TRACE(bh, "queue"); + get_bh(bh); + J_ASSERT_BH(bh, !buffer_jwrite(bh)); + journal->j_chkpt_bhs[batch_count++] = bh; + transaction->t_chp_stats.cs_written++; + transaction->t_checkpoint_list = jh->b_cpnext; } - /* - * Important: we are about to write the buffer, and - * possibly block, while still holding the journal - * lock. We cannot afford to let the transaction - * logic start messing around with this buffer before - * we write it to disk, as that would break - * recoverability. - */ - BUFFER_TRACE(bh, "queue"); - get_bh(bh); - J_ASSERT_BH(bh, !buffer_jwrite(bh)); - journal->j_chkpt_bhs[batch_count++] = bh; - __buffer_relink_io(jh); - transaction->t_chp_stats.cs_written++; + if ((batch_count == JBD2_NR_BATCH) || - need_resched() || - spin_needbreak(&journal->j_list_lock)) + need_resched() || spin_needbreak(&journal->j_list_lock) || + jh2bh(transaction->t_checkpoint_list) == journal->j_chkpt_bhs[0]) goto unlock_and_flush; } @@ -322,38 +310,6 @@ restart: goto restart; } - /* - * Now we issued all of the transaction's buffers, let's deal - * with the buffers that are out for I/O. - */ -restart2: - /* Did somebody clean up the transaction in the meanwhile? */ - if (journal->j_checkpoint_transactions != transaction || - transaction->t_tid != this_tid) - goto out; - - while (transaction->t_checkpoint_io_list) { - jh = transaction->t_checkpoint_io_list; - bh = jh2bh(jh); - if (buffer_locked(bh)) { - get_bh(bh); - spin_unlock(&journal->j_list_lock); - wait_on_buffer(bh); - /* the journal_head may have gone by now */ - BUFFER_TRACE(bh, "brelse"); - __brelse(bh); - spin_lock(&journal->j_list_lock); - goto restart2; - } - - /* - * Now in whatever state the buffer currently is, we - * know that it has been written out and so we can - * drop it from the list - */ - if (__jbd2_journal_remove_checkpoint(jh)) - break; - } out: spin_unlock(&journal->j_list_lock); result = jbd2_cleanup_journal_tail(journal); diff --git a/fs/jffs2/build.c b/fs/jffs2/build.c index 837cd55fd4c5..6ae9d6fefb86 100644 --- a/fs/jffs2/build.c +++ b/fs/jffs2/build.c @@ -211,7 +211,10 @@ static int jffs2_build_filesystem(struct jffs2_sb_info *c) ic->scan_dents = NULL; cond_resched(); } - jffs2_build_xattr_subsystem(c); + ret = jffs2_build_xattr_subsystem(c); + if (ret) + goto exit; + c->flags &= ~JFFS2_SB_FLAG_BUILDING; dbg_fsbuild("FS build complete\n"); diff --git a/fs/jffs2/xattr.c b/fs/jffs2/xattr.c index da3e18503c65..acb4492f5970 100644 --- a/fs/jffs2/xattr.c +++ b/fs/jffs2/xattr.c @@ -772,10 +772,10 @@ void jffs2_clear_xattr_subsystem(struct jffs2_sb_info *c) } #define XREF_TMPHASH_SIZE (128) -void jffs2_build_xattr_subsystem(struct jffs2_sb_info *c) +int jffs2_build_xattr_subsystem(struct jffs2_sb_info *c) { struct jffs2_xattr_ref *ref, *_ref; - struct jffs2_xattr_ref *xref_tmphash[XREF_TMPHASH_SIZE]; + struct jffs2_xattr_ref **xref_tmphash; struct jffs2_xattr_datum *xd, *_xd; struct jffs2_inode_cache *ic; struct jffs2_raw_node_ref *raw; @@ -784,9 +784,12 @@ void jffs2_build_xattr_subsystem(struct jffs2_sb_info *c) BUG_ON(!(c->flags & JFFS2_SB_FLAG_BUILDING)); + xref_tmphash = kcalloc(XREF_TMPHASH_SIZE, + sizeof(struct jffs2_xattr_ref *), GFP_KERNEL); + if (!xref_tmphash) + return -ENOMEM; + /* Phase.1 : Merge same xref */ - for (i=0; i < XREF_TMPHASH_SIZE; i++) - xref_tmphash[i] = NULL; for (ref=c->xref_temp; ref; ref=_ref) { struct jffs2_xattr_ref *tmp; @@ -884,6 +887,8 @@ void jffs2_build_xattr_subsystem(struct jffs2_sb_info *c) "%u of xref (%u dead, %u orphan) found.\n", xdatum_count, xdatum_unchecked_count, xdatum_orphan_count, xref_count, xref_dead_count, xref_orphan_count); + kfree(xref_tmphash); + return 0; } struct jffs2_xattr_datum *jffs2_setup_xattr_datum(struct jffs2_sb_info *c, diff --git a/fs/jffs2/xattr.h b/fs/jffs2/xattr.h index 720007b2fd65..1b5030a3349d 100644 --- a/fs/jffs2/xattr.h +++ b/fs/jffs2/xattr.h @@ -71,7 +71,7 @@ static inline int is_xattr_ref_dead(struct jffs2_xattr_ref *ref) #ifdef CONFIG_JFFS2_FS_XATTR extern void jffs2_init_xattr_subsystem(struct jffs2_sb_info *c); -extern void jffs2_build_xattr_subsystem(struct jffs2_sb_info *c); +extern int jffs2_build_xattr_subsystem(struct jffs2_sb_info *c); extern void jffs2_clear_xattr_subsystem(struct jffs2_sb_info *c); extern struct jffs2_xattr_datum *jffs2_setup_xattr_datum(struct jffs2_sb_info *c, @@ -103,7 +103,7 @@ extern ssize_t jffs2_listxattr(struct dentry *, char *, size_t); #else #define jffs2_init_xattr_subsystem(c) -#define jffs2_build_xattr_subsystem(c) +#define jffs2_build_xattr_subsystem(c) (0) #define jffs2_clear_xattr_subsystem(c) #define jffs2_xattr_do_crccheck_inode(c, ic) diff --git a/fs/jfs/jfs_dmap.c b/fs/jfs/jfs_dmap.c index 0034b0f39715..f235a3d270a0 100644 --- a/fs/jfs/jfs_dmap.c +++ b/fs/jfs/jfs_dmap.c @@ -178,7 +178,13 @@ int dbMount(struct inode *ipbmap) dbmp_le = (struct dbmap_disk *) mp->data; bmp->db_mapsize = le64_to_cpu(dbmp_le->dn_mapsize); bmp->db_nfree = le64_to_cpu(dbmp_le->dn_nfree); + bmp->db_l2nbperpage = le32_to_cpu(dbmp_le->dn_l2nbperpage); + if (bmp->db_l2nbperpage > L2PSIZE - L2MINBLOCKSIZE) { + err = -EINVAL; + goto err_release_metapage; + } + bmp->db_numag = le32_to_cpu(dbmp_le->dn_numag); if (!bmp->db_numag) { err = -EINVAL; @@ -2021,6 +2027,9 @@ dbAllocDmapLev(struct bmap * bmp, if (dbFindLeaf((dmtree_t *) & dp->tree, l2nb, &leafidx)) return -ENOSPC; + if (leafidx < 0) + return -EIO; + /* determine the block number within the file system corresponding * to the leaf at which free space was found. */ diff --git a/fs/jfs/jfs_filsys.h b/fs/jfs/jfs_filsys.h index b5d702df7111..33ef13a0b110 100644 --- a/fs/jfs/jfs_filsys.h +++ b/fs/jfs/jfs_filsys.h @@ -122,7 +122,9 @@ #define NUM_INODE_PER_IAG INOSPERIAG #define MINBLOCKSIZE 512 +#define L2MINBLOCKSIZE 9 #define MAXBLOCKSIZE 4096 +#define L2MAXBLOCKSIZE 12 #define MAXFILESIZE ((s64)1 << 52) #define JFS_LINK_MAX 0xffffffff diff --git a/fs/jfs/jfs_txnmgr.c b/fs/jfs/jfs_txnmgr.c index 042bbe6d8ac2..6c8680d3907a 100644 --- a/fs/jfs/jfs_txnmgr.c +++ b/fs/jfs/jfs_txnmgr.c @@ -354,6 +354,11 @@ tid_t txBegin(struct super_block *sb, int flag) jfs_info("txBegin: flag = 0x%x", flag); log = JFS_SBI(sb)->log; + if (!log) { + jfs_error(sb, "read-only filesystem\n"); + return 0; + } + TXN_LOCK(); INCREMENT(TxStat.txBegin); diff --git a/fs/jfs/namei.c b/fs/jfs/namei.c index 4fbbf88435e6..b3a0fe0649c4 100644 --- a/fs/jfs/namei.c +++ b/fs/jfs/namei.c @@ -799,6 +799,11 @@ static int jfs_link(struct dentry *old_dentry, if (rc) goto out; + if (isReadOnly(ip)) { + jfs_error(ip->i_sb, "read-only filesystem\n"); + return -EROFS; + } + tid = txBegin(ip->i_sb, 0); mutex_lock_nested(&JFS_IP(dir)->commit_mutex, COMMIT_MUTEX_PARENT); diff --git a/fs/kernfs/dir.c b/fs/kernfs/dir.c index 90677cfbcf9c..6a1cb2a182b6 100644 --- a/fs/kernfs/dir.c +++ b/fs/kernfs/dir.c @@ -637,7 +637,9 @@ static struct kernfs_node *__kernfs_new_node(struct kernfs_root *root, return kn; err_out3: + spin_lock(&kernfs_idr_lock); idr_remove(&root->ino_idr, (u32)kernfs_ino(kn)); + spin_unlock(&kernfs_idr_lock); err_out2: kmem_cache_free(kernfs_node_cache, kn); err_out1: diff --git a/fs/ksmbd/server.c b/fs/ksmbd/server.c index c06931bfe230..358f42f488ba 100644 --- a/fs/ksmbd/server.c +++ b/fs/ksmbd/server.c @@ -184,24 +184,31 @@ static void __handle_ksmbd_work(struct ksmbd_work *work, goto send; } - if (conn->ops->check_user_session) { - rc = conn->ops->check_user_session(work); - if (rc < 0) { - command = conn->ops->get_cmd_val(work); - conn->ops->set_rsp_status(work, - STATUS_USER_SESSION_DELETED); - goto send; - } else if (rc > 0) { - rc = conn->ops->get_ksmbd_tcon(work); + do { + if (conn->ops->check_user_session) { + rc = conn->ops->check_user_session(work); if (rc < 0) { - conn->ops->set_rsp_status(work, - STATUS_NETWORK_NAME_DELETED); + if (rc == -EINVAL) + conn->ops->set_rsp_status(work, + STATUS_INVALID_PARAMETER); + else + conn->ops->set_rsp_status(work, + STATUS_USER_SESSION_DELETED); goto send; + } else if (rc > 0) { + rc = conn->ops->get_ksmbd_tcon(work); + if (rc < 0) { + if (rc == -EINVAL) + conn->ops->set_rsp_status(work, + STATUS_INVALID_PARAMETER); + else + conn->ops->set_rsp_status(work, + STATUS_NETWORK_NAME_DELETED); + goto send; + } } } - } - do { rc = __process_request(work, conn, &command); if (rc == SERVER_HANDLER_ABORT) break; diff --git a/fs/ksmbd/smb2misc.c b/fs/ksmbd/smb2misc.c index 33a927df64f1..c24674fc1904 100644 --- a/fs/ksmbd/smb2misc.c +++ b/fs/ksmbd/smb2misc.c @@ -347,19 +347,21 @@ static int smb2_validate_credit_charge(struct ksmbd_conn *conn, int ksmbd_smb2_check_message(struct ksmbd_work *work) { - struct smb2_pdu *pdu = work->request_buf; + struct smb2_pdu *pdu = ksmbd_req_buf_next(work); struct smb2_hdr *hdr = &pdu->hdr; int command; __u32 clc_len; /* calculated length */ - __u32 len = get_rfc1002_len(pdu); + __u32 len = get_rfc1002_len(work->request_buf); + __u32 req_struct_size, next_cmd = le32_to_cpu(hdr->NextCommand); - if (work->next_smb2_rcv_hdr_off) { - pdu = ksmbd_req_buf_next(work); - hdr = &pdu->hdr; + if ((u64)work->next_smb2_rcv_hdr_off + next_cmd > len) { + pr_err("next command(%u) offset exceeds smb msg size\n", + next_cmd); + return 1; } - if (le32_to_cpu(hdr->NextCommand) > 0) - len = le32_to_cpu(hdr->NextCommand); + if (next_cmd > 0) + len = next_cmd; else if (work->next_smb2_rcv_hdr_off) len -= work->next_smb2_rcv_hdr_off; @@ -379,17 +381,9 @@ int ksmbd_smb2_check_message(struct ksmbd_work *work) } if (smb2_req_struct_sizes[command] != pdu->StructureSize2) { - if (command != SMB2_OPLOCK_BREAK_HE && - (hdr->Status == 0 || pdu->StructureSize2 != SMB2_ERROR_STRUCTURE_SIZE2_LE)) { - /* error packets have 9 byte structure size */ - ksmbd_debug(SMB, - "Illegal request size %u for command %d\n", - le16_to_cpu(pdu->StructureSize2), command); - return 1; - } else if (command == SMB2_OPLOCK_BREAK_HE && - hdr->Status == 0 && - le16_to_cpu(pdu->StructureSize2) != OP_BREAK_STRUCT_SIZE_20 && - le16_to_cpu(pdu->StructureSize2) != OP_BREAK_STRUCT_SIZE_21) { + if (command == SMB2_OPLOCK_BREAK_HE && + le16_to_cpu(pdu->StructureSize2) != OP_BREAK_STRUCT_SIZE_20 && + le16_to_cpu(pdu->StructureSize2) != OP_BREAK_STRUCT_SIZE_21) { /* special case for SMB2.1 lease break message */ ksmbd_debug(SMB, "Illegal request size %d for oplock break\n", @@ -398,6 +392,14 @@ int ksmbd_smb2_check_message(struct ksmbd_work *work) } } + req_struct_size = le16_to_cpu(pdu->StructureSize2) + + __SMB2_HEADER_STRUCTURE_SIZE; + if (command == SMB2_LOCK_HE) + req_struct_size -= sizeof(struct smb2_lock_element); + + if (req_struct_size > len + 1) + return 1; + if (smb2_calc_size(hdr, &clc_len)) return 1; diff --git a/fs/ksmbd/smb2pdu.c b/fs/ksmbd/smb2pdu.c index 266430a2a0e0..9f9d07caa57e 100644 --- a/fs/ksmbd/smb2pdu.c +++ b/fs/ksmbd/smb2pdu.c @@ -97,7 +97,6 @@ int smb2_get_ksmbd_tcon(struct ksmbd_work *work) struct smb2_hdr *req_hdr = work->request_buf; int tree_id; - work->tcon = NULL; if (work->conn->ops->get_cmd_val(work) == SMB2_TREE_CONNECT_HE || work->conn->ops->get_cmd_val(work) == SMB2_CANCEL_HE || work->conn->ops->get_cmd_val(work) == SMB2_LOGOFF_HE) { @@ -111,10 +110,28 @@ int smb2_get_ksmbd_tcon(struct ksmbd_work *work) } tree_id = le32_to_cpu(req_hdr->Id.SyncId.TreeId); + + /* + * If request is not the first in Compound request, + * Just validate tree id in header with work->tcon->id. + */ + if (work->next_smb2_rcv_hdr_off) { + if (!work->tcon) { + pr_err("The first operation in the compound does not have tcon\n"); + return -EINVAL; + } + if (work->tcon->id != tree_id) { + pr_err("tree id(%u) is different with id(%u) in first operation\n", + tree_id, work->tcon->id); + return -EINVAL; + } + return 1; + } + work->tcon = ksmbd_tree_conn_lookup(work->sess, tree_id); if (!work->tcon) { pr_err("Invalid tid %d\n", tree_id); - return -EINVAL; + return -ENOENT; } return 1; @@ -569,7 +586,6 @@ int smb2_check_user_session(struct ksmbd_work *work) unsigned int cmd = conn->ops->get_cmd_val(work); unsigned long long sess_id; - work->sess = NULL; /* * SMB2_ECHO, SMB2_NEGOTIATE, SMB2_SESSION_SETUP command do not * require a session id, so no need to validate user session's for @@ -580,15 +596,33 @@ int smb2_check_user_session(struct ksmbd_work *work) return 0; if (!ksmbd_conn_good(work)) - return -EINVAL; + return -EIO; sess_id = le64_to_cpu(req_hdr->SessionId); + + /* + * If request is not the first in Compound request, + * Just validate session id in header with work->sess->id. + */ + if (work->next_smb2_rcv_hdr_off) { + if (!work->sess) { + pr_err("The first operation in the compound does not have sess\n"); + return -EINVAL; + } + if (work->sess->id != sess_id) { + pr_err("session id(%llu) is different with the first operation(%lld)\n", + sess_id, work->sess->id); + return -EINVAL; + } + return 1; + } + /* Check for validity of user session */ work->sess = ksmbd_session_lookup_all(conn, sess_id); if (work->sess) return 1; ksmbd_debug(SMB, "Invalid user session, Uid %llu\n", sess_id); - return -EINVAL; + return -ENOENT; } static void destroy_previous_session(struct ksmbd_conn *conn, diff --git a/fs/ksmbd/smb_common.c b/fs/ksmbd/smb_common.c index f034b75c6d7f..af583e426621 100644 --- a/fs/ksmbd/smb_common.c +++ b/fs/ksmbd/smb_common.c @@ -423,7 +423,7 @@ int ksmbd_extract_shortname(struct ksmbd_conn *conn, const char *longname, out[baselen + 3] = PERIOD; if (dot_present) - memcpy(&out[baselen + 4], extension, 4); + memcpy(out + baselen + 4, extension, 4); else out[baselen + 4] = '\0'; smbConvertToUTF16((__le16 *)shortname, out, PATH_MAX, diff --git a/fs/namei.c b/fs/namei.c index 6e126d5cf625..85cdd24a8bcb 100644 --- a/fs/namei.c +++ b/fs/namei.c @@ -2984,8 +2984,8 @@ struct dentry *lock_rename(struct dentry *p1, struct dentry *p2) return p; } - inode_lock_nested(p1->d_inode, I_MUTEX_PARENT); - inode_lock_nested(p2->d_inode, I_MUTEX_PARENT2); + lock_two_inodes(p1->d_inode, p2->d_inode, + I_MUTEX_PARENT, I_MUTEX_PARENT2); return NULL; } EXPORT_SYMBOL(lock_rename); @@ -4618,7 +4618,7 @@ SYSCALL_DEFINE2(link, const char __user *, oldname, const char __user *, newname * sb->s_vfs_rename_mutex. We might be more accurate, but that's another * story. * c) we have to lock _four_ objects - parents and victim (if it exists), - * and source (if it is not a directory). + * and source. * And that - after we got ->i_mutex on parents (until then we don't know * whether the target exists). Solution: try to be smart with locking * order for inodes. We rely on the fact that tree topology may change @@ -4702,10 +4702,16 @@ int vfs_rename(struct renamedata *rd) take_dentry_name_snapshot(&old_name, old_dentry); dget(new_dentry); - if (!is_dir || (flags & RENAME_EXCHANGE)) - lock_two_nondirectories(source, target); - else if (target) - inode_lock(target); + /* + * Lock all moved children. Moved directories may need to change parent + * pointer so they need the lock to prevent against concurrent + * directory changes moving parent pointer. For regular files we've + * historically always done this. The lockdep locking subclasses are + * somewhat arbitrary but RENAME_EXCHANGE in particular can swap + * regular files and directories so it's difficult to tell which + * subclasses to use. + */ + lock_two_inodes(source, target, I_MUTEX_NORMAL, I_MUTEX_NONDIR2); error = -EPERM; if (IS_SWAPFILE(source) || (target && IS_SWAPFILE(target))) @@ -4753,9 +4759,8 @@ int vfs_rename(struct renamedata *rd) d_exchange(old_dentry, new_dentry); } out: - if (!is_dir || (flags & RENAME_EXCHANGE)) - unlock_two_nondirectories(source, target); - else if (target) + inode_unlock(source); + if (target) inode_unlock(target); dput(new_dentry); if (!error) { diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index 4f39aaf6a8f4..06bc360c241d 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c @@ -924,6 +924,7 @@ out: out_noaction: return ret; session_recover: + set_bit(NFS4_SLOT_TBL_DRAINING, &session->fc_slot_table.slot_tbl_state); nfs4_schedule_session_recovery(session, status); dprintk("%s ERROR: %d Reset session\n", __func__, status); nfs41_sequence_free_slot(res); diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c index 0394dd60a0b4..e8132a17eeb3 100644 --- a/fs/nfsd/nfs4xdr.c +++ b/fs/nfsd/nfs4xdr.c @@ -3816,7 +3816,7 @@ nfsd4_encode_open(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_op p = xdr_reserve_space(xdr, 32); if (!p) return nfserr_resource; - *p++ = cpu_to_be32(0); + *p++ = cpu_to_be32(open->op_recall); /* * TODO: space_limit's in delegations diff --git a/fs/notify/fanotify/fanotify_user.c b/fs/notify/fanotify/fanotify_user.c index 84ec851211d9..0e2a0eb7cb9e 100644 --- a/fs/notify/fanotify/fanotify_user.c +++ b/fs/notify/fanotify/fanotify_user.c @@ -1337,8 +1337,11 @@ static int fanotify_test_fid(struct path *path, __kernel_fsid_t *fsid) return 0; } -static int fanotify_events_supported(struct path *path, __u64 mask) +static int fanotify_events_supported(struct path *path, __u64 mask, + unsigned int flags) { + unsigned int mark_type = flags & FANOTIFY_MARK_TYPE_BITS; + /* * Some filesystems such as 'proc' acquire unusual locks when opening * files. For them fanotify permission events have high chances of @@ -1350,6 +1353,21 @@ static int fanotify_events_supported(struct path *path, __u64 mask) if (mask & FANOTIFY_PERM_EVENTS && path->mnt->mnt_sb->s_type->fs_flags & FS_DISALLOW_NOTIFY_PERM) return -EINVAL; + + /* + * mount and sb marks are not allowed on kernel internal pseudo fs, + * like pipe_mnt, because that would subscribe to events on all the + * anonynous pipes in the system. + * + * SB_NOUSER covers all of the internal pseudo fs whose objects are not + * exposed to user's mount namespace, but there are other SB_KERNMOUNT + * fs, like nsfs, debugfs, for which the value of allowing sb and mount + * mark is questionable. For now we leave them alone. + */ + if (mark_type != FAN_MARK_INODE && + path->mnt->mnt_sb->s_flags & SB_NOUSER) + return -EINVAL; + return 0; } @@ -1476,7 +1494,7 @@ static int do_fanotify_mark(int fanotify_fd, unsigned int flags, __u64 mask, goto fput_and_out; if (flags & FAN_MARK_ADD) { - ret = fanotify_events_supported(&path, mask); + ret = fanotify_events_supported(&path, mask, flags); if (ret) goto path_put_and_out; } diff --git a/fs/ntfs3/xattr.c b/fs/ntfs3/xattr.c index 92b61f22837f..aaf4bafa2c70 100644 --- a/fs/ntfs3/xattr.c +++ b/fs/ntfs3/xattr.c @@ -213,6 +213,9 @@ static ssize_t ntfs_list_ea(struct ntfs_inode *ni, char *buffer, ea = Add2Ptr(ea_all, off); ea_size = unpacked_ea_size(ea); + if (!ea->name_len) + break; + if (buffer) { if (ret + ea->name_len + 1 > bytes_per_buffer) { err = -ERANGE; diff --git a/fs/overlayfs/copy_up.c b/fs/overlayfs/copy_up.c index da7ee5f16794..3f37b96cc394 100644 --- a/fs/overlayfs/copy_up.c +++ b/fs/overlayfs/copy_up.c @@ -542,6 +542,7 @@ static int ovl_link_up(struct ovl_copy_up_ctx *c) /* Restore timestamps on parent (best effort) */ ovl_set_timestamps(upperdir, &c->pstat); ovl_dentry_set_upper_alias(c->dentry); + ovl_dentry_update_reval(c->dentry, upper); } } inode_unlock(udir); @@ -840,6 +841,7 @@ static int ovl_do_copy_up(struct ovl_copy_up_ctx *c) inode_unlock(udir); ovl_dentry_set_upper_alias(c->dentry); + ovl_dentry_update_reval(c->dentry, ovl_dentry_upper(c->dentry)); } out: diff --git a/fs/overlayfs/dir.c b/fs/overlayfs/dir.c index 4bd2aed5fc9e..1dd153fdbcc7 100644 --- a/fs/overlayfs/dir.c +++ b/fs/overlayfs/dir.c @@ -267,8 +267,7 @@ static int ovl_instantiate(struct dentry *dentry, struct inode *inode, ovl_dir_modified(dentry->d_parent, false); ovl_dentry_set_upper_alias(dentry); - ovl_dentry_update_reval(dentry, newdentry, - DCACHE_OP_REVALIDATE | DCACHE_OP_WEAK_REVALIDATE); + ovl_dentry_init_reval(dentry, newdentry); if (!hardlink) { /* diff --git a/fs/overlayfs/export.c b/fs/overlayfs/export.c index 0cc14ce8c7e8..baa50ece0bc5 100644 --- a/fs/overlayfs/export.c +++ b/fs/overlayfs/export.c @@ -326,8 +326,7 @@ static struct dentry *ovl_obtain_alias(struct super_block *sb, if (upper_alias) ovl_dentry_set_upper_alias(dentry); - ovl_dentry_update_reval(dentry, upper, - DCACHE_OP_REVALIDATE | DCACHE_OP_WEAK_REVALIDATE); + ovl_dentry_init_reval(dentry, upper); return d_instantiate_anon(dentry, inode); diff --git a/fs/overlayfs/inode.c b/fs/overlayfs/inode.c index dee23f5f42b7..1ae1199b9fd2 100644 --- a/fs/overlayfs/inode.c +++ b/fs/overlayfs/inode.c @@ -280,10 +280,12 @@ int ovl_permission(struct user_namespace *mnt_userns, { struct inode *upperinode = ovl_inode_upper(inode); struct inode *realinode = upperinode ?: ovl_inode_lower(inode); + struct path realpath; const struct cred *old_cred; int err; /* Careful in RCU walk mode */ + realinode = ovl_i_path_real(inode, &realpath); if (!realinode) { WARN_ON(!(mask & MAY_NOT_BLOCK)); return -ECHILD; @@ -453,7 +455,15 @@ struct posix_acl *ovl_get_acl(struct inode *inode, int type, bool rcu) const struct cred *old_cred; struct posix_acl *acl; - if (!IS_ENABLED(CONFIG_FS_POSIX_ACL) || !IS_POSIXACL(realinode)) + if (!IS_ENABLED(CONFIG_FS_POSIX_ACL)) + return NULL; + + if (!realinode) { + WARN_ON(!rcu); + return ERR_PTR(-ECHILD); + } + + if (!IS_POSIXACL(realinode)) return NULL; if (rcu) diff --git a/fs/overlayfs/namei.c b/fs/overlayfs/namei.c index 0ecb6bab0f2a..233f3cfddaf7 100644 --- a/fs/overlayfs/namei.c +++ b/fs/overlayfs/namei.c @@ -1103,8 +1103,7 @@ struct dentry *ovl_lookup(struct inode *dir, struct dentry *dentry, ovl_set_flag(OVL_UPPERDATA, inode); } - ovl_dentry_update_reval(dentry, upperdentry, - DCACHE_OP_REVALIDATE | DCACHE_OP_WEAK_REVALIDATE); + ovl_dentry_init_reval(dentry, upperdentry); ovl_revert_creds(dentry->d_sb, old_cred); if (origin_path) { diff --git a/fs/overlayfs/overlayfs.h b/fs/overlayfs/overlayfs.h index 07998f3a3ee8..9b35249f2ced 100644 --- a/fs/overlayfs/overlayfs.h +++ b/fs/overlayfs/overlayfs.h @@ -287,14 +287,16 @@ bool ovl_index_all(struct super_block *sb); bool ovl_verify_lower(struct super_block *sb); struct ovl_entry *ovl_alloc_entry(unsigned int numlower); bool ovl_dentry_remote(struct dentry *dentry); -void ovl_dentry_update_reval(struct dentry *dentry, struct dentry *upperdentry, - unsigned int mask); +void ovl_dentry_update_reval(struct dentry *dentry, struct dentry *realdentry); +void ovl_dentry_init_reval(struct dentry *dentry, struct dentry *upperdentry); +void ovl_dentry_init_flags(struct dentry *dentry, struct dentry *upperdentry, + unsigned int mask); bool ovl_dentry_weird(struct dentry *dentry); enum ovl_path_type ovl_path_type(struct dentry *dentry); void ovl_path_upper(struct dentry *dentry, struct path *path); void ovl_path_lower(struct dentry *dentry, struct path *path); void ovl_path_lowerdata(struct dentry *dentry, struct path *path); -void ovl_i_path_real(struct inode *inode, struct path *path); +struct inode *ovl_i_path_real(struct inode *inode, struct path *path); enum ovl_path_type ovl_path_real(struct dentry *dentry, struct path *path); struct dentry *ovl_dentry_upper(struct dentry *dentry); struct dentry *ovl_dentry_lower(struct dentry *dentry); diff --git a/fs/overlayfs/super.c b/fs/overlayfs/super.c index 8231271a1eaf..fb86a93e2571 100644 --- a/fs/overlayfs/super.c +++ b/fs/overlayfs/super.c @@ -1987,7 +1987,7 @@ static struct dentry *ovl_get_root(struct super_block *sb, ovl_dentry_set_flag(OVL_E_CONNECTED, root); ovl_set_upperdata(d_inode(root)); ovl_inode_init(d_inode(root), &oip, ino, fsid); - ovl_dentry_update_reval(root, upperdentry, DCACHE_OP_WEAK_REVALIDATE); + ovl_dentry_init_flags(root, upperdentry, DCACHE_OP_WEAK_REVALIDATE); return root; } diff --git a/fs/overlayfs/util.c b/fs/overlayfs/util.c index 32e4b24bc0e2..4d39d77de403 100644 --- a/fs/overlayfs/util.c +++ b/fs/overlayfs/util.c @@ -103,14 +103,30 @@ struct ovl_entry *ovl_alloc_entry(unsigned int numlower) return oe; } +#define OVL_D_REVALIDATE (DCACHE_OP_REVALIDATE | DCACHE_OP_WEAK_REVALIDATE) + bool ovl_dentry_remote(struct dentry *dentry) { - return dentry->d_flags & - (DCACHE_OP_REVALIDATE | DCACHE_OP_WEAK_REVALIDATE); + return dentry->d_flags & OVL_D_REVALIDATE; } -void ovl_dentry_update_reval(struct dentry *dentry, struct dentry *upperdentry, - unsigned int mask) +void ovl_dentry_update_reval(struct dentry *dentry, struct dentry *realdentry) +{ + if (!ovl_dentry_remote(realdentry)) + return; + + spin_lock(&dentry->d_lock); + dentry->d_flags |= realdentry->d_flags & OVL_D_REVALIDATE; + spin_unlock(&dentry->d_lock); +} + +void ovl_dentry_init_reval(struct dentry *dentry, struct dentry *upperdentry) +{ + return ovl_dentry_init_flags(dentry, upperdentry, OVL_D_REVALIDATE); +} + +void ovl_dentry_init_flags(struct dentry *dentry, struct dentry *upperdentry, + unsigned int mask) { struct ovl_entry *oe = OVL_E(dentry); unsigned int i, flags = 0; @@ -245,7 +261,7 @@ struct dentry *ovl_i_dentry_upper(struct inode *inode) return ovl_upperdentry_dereference(OVL_I(inode)); } -void ovl_i_path_real(struct inode *inode, struct path *path) +struct inode *ovl_i_path_real(struct inode *inode, struct path *path) { path->dentry = ovl_i_dentry_upper(inode); if (!path->dentry) { @@ -254,6 +270,8 @@ void ovl_i_path_real(struct inode *inode, struct path *path) } else { path->mnt = ovl_upper_mnt(OVL_FS(inode->i_sb)); } + + return path->dentry ? d_inode(path->dentry) : NULL; } struct inode *ovl_inode_upper(struct inode *inode) @@ -1100,8 +1118,7 @@ void ovl_copyattr(struct inode *inode) struct inode *realinode; struct user_namespace *real_mnt_userns; - ovl_i_path_real(inode, &realpath); - realinode = d_inode(realpath.dentry); + realinode = ovl_i_path_real(inode, &realpath); real_mnt_userns = mnt_user_ns(realpath.mnt); inode->i_uid = i_uid_into_mnt(real_mnt_userns, realinode); diff --git a/fs/proc/array.c b/fs/proc/array.c index 49be8c8ef555..860e4deafa65 100644 --- a/fs/proc/array.c +++ b/fs/proc/array.c @@ -92,6 +92,7 @@ #include #include #include +#include #include #include "internal.h" @@ -102,6 +103,8 @@ void proc_task_name(struct seq_file *m, struct task_struct *p, bool escape) if (p->flags & PF_WQ_WORKER) wq_worker_comm(tcomm, sizeof(tcomm), p); + else if (p->flags & PF_KTHREAD) + get_kthread_comm(tcomm, sizeof(tcomm), p); else __get_task_comm(tcomm, sizeof(tcomm), p); diff --git a/fs/proc/inode.c b/fs/proc/inode.c index 599eb724ff2d..e5b710674215 100644 --- a/fs/proc/inode.c +++ b/fs/proc/inode.c @@ -489,6 +489,9 @@ static int proc_reg_open(struct inode *inode, struct file *file) typeof_member(struct proc_ops, proc_release) release; struct pde_opener *pdeo; + if (!pde->proc_ops->proc_lseek) + file->f_mode &= ~FMODE_LSEEK; + if (pde_is_permanent(pde)) { open = pde->proc_ops->proc_open; if (open) diff --git a/fs/pstore/ram_core.c b/fs/pstore/ram_core.c index 155c7010b1f8..ccdb71c3dc51 100644 --- a/fs/pstore/ram_core.c +++ b/fs/pstore/ram_core.c @@ -518,7 +518,7 @@ static int persistent_ram_post_init(struct persistent_ram_zone *prz, u32 sig, sig ^= PERSISTENT_RAM_SIG; if (prz->buffer->sig == sig) { - if (buffer_size(prz) == 0) { + if (buffer_size(prz) == 0 && buffer_start(prz) == 0) { pr_debug("found existing empty buffer\n"); return 0; } @@ -591,6 +591,8 @@ struct persistent_ram_zone *persistent_ram_new(phys_addr_t start, size_t size, raw_spin_lock_init(&prz->buffer_lock); prz->flags = flags; prz->label = kstrdup(label, GFP_KERNEL); + if (!prz->label) + goto err; ret = persistent_ram_buffer_map(start, size, prz, memtype); if (ret) diff --git a/fs/quota/dquot.c b/fs/quota/dquot.c index cddd07b7d132..b88f5a2f6032 100644 --- a/fs/quota/dquot.c +++ b/fs/quota/dquot.c @@ -555,7 +555,7 @@ restart: continue; /* Wait for dquot users */ if (atomic_read(&dquot->dq_count)) { - dqgrab(dquot); + atomic_inc(&dquot->dq_count); spin_unlock(&dq_list_lock); /* * Once dqput() wakes us up, we know it's time to free @@ -2413,7 +2413,8 @@ int dquot_load_quota_sb(struct super_block *sb, int type, int format_id, error = add_dquot_ref(sb, type); if (error) - dquot_disable(sb, type, flags); + dquot_disable(sb, type, + DQUOT_USAGE_ENABLED | DQUOT_LIMITS_ENABLED); return error; out_fmt: diff --git a/fs/ramfs/inode.c b/fs/ramfs/inode.c index 65e7e56005b8..dc1f9e6d95a5 100644 --- a/fs/ramfs/inode.c +++ b/fs/ramfs/inode.c @@ -274,7 +274,7 @@ int ramfs_init_fs_context(struct fs_context *fc) return 0; } -static void ramfs_kill_sb(struct super_block *sb) +void ramfs_kill_sb(struct super_block *sb) { kfree(sb->s_fs_info); kill_litter_super(sb); diff --git a/fs/udf/unicode.c b/fs/udf/unicode.c index 622569007b53..2142cbd1dde2 100644 --- a/fs/udf/unicode.c +++ b/fs/udf/unicode.c @@ -247,7 +247,7 @@ static int udf_name_from_CS0(struct super_block *sb, } if (translate) { - if (str_o_len <= 2 && str_o[0] == '.' && + if (str_o_len > 0 && str_o_len <= 2 && str_o[0] == '.' && (str_o_len == 1 || str_o[1] == '.')) needsCRC = 1; if (needsCRC) { diff --git a/include/acpi/acpi_bus.h b/include/acpi/acpi_bus.h index e9c7d7b270e7..7a85ae6b7b00 100644 --- a/include/acpi/acpi_bus.h +++ b/include/acpi/acpi_bus.h @@ -52,7 +52,7 @@ bool acpi_dock_match(acpi_handle handle); bool acpi_check_dsm(acpi_handle handle, const guid_t *guid, u64 rev, u64 funcs); union acpi_object *acpi_evaluate_dsm(acpi_handle handle, const guid_t *guid, u64 rev, u64 func, union acpi_object *argv4); - +#ifdef CONFIG_ACPI static inline union acpi_object * acpi_evaluate_dsm_typed(acpi_handle handle, const guid_t *guid, u64 rev, u64 func, union acpi_object *argv4, @@ -68,6 +68,7 @@ acpi_evaluate_dsm_typed(acpi_handle handle, const guid_t *guid, u64 rev, return obj; } +#endif #define ACPI_INIT_DSM_ARGV4(cnt, eles) \ { \ diff --git a/include/asm-generic/tlb.h b/include/asm-generic/tlb.h index c99710b3027a..7afde1eff239 100644 --- a/include/asm-generic/tlb.h +++ b/include/asm-generic/tlb.h @@ -662,6 +662,20 @@ static inline void tlb_flush_p4d_range(struct mmu_gather *tlb, } while (0) #endif +#ifndef pte_needs_flush +static inline bool pte_needs_flush(pte_t oldpte, pte_t newpte) +{ + return true; +} +#endif + +#ifndef huge_pmd_needs_flush +static inline bool huge_pmd_needs_flush(pmd_t oldpmd, pmd_t newpmd) +{ + return true; +} +#endif + #endif /* CONFIG_MMU */ #endif /* _ASM_GENERIC__TLB_H */ diff --git a/include/crypto/internal/kpp.h b/include/crypto/internal/kpp.h index 659b642efada..05b25a819d0d 100644 --- a/include/crypto/internal/kpp.h +++ b/include/crypto/internal/kpp.h @@ -18,6 +18,12 @@ static inline void *kpp_request_ctx(struct kpp_request *req) return req->__ctx; } +static inline void kpp_set_reqsize(struct crypto_kpp *kpp, + unsigned int reqsize) +{ + crypto_kpp_alg(kpp)->reqsize = reqsize; +} + static inline void *kpp_tfm_ctx(struct crypto_kpp *tfm) { return tfm->base.__crt_ctx; diff --git a/include/dt-bindings/clock/qcom,camcc-sdm845.h b/include/dt-bindings/clock/qcom,camcc-sdm845.h index 4f7a2d2320bf..e1377dedb0fa 100644 --- a/include/dt-bindings/clock/qcom,camcc-sdm845.h +++ b/include/dt-bindings/clock/qcom,camcc-sdm845.h @@ -1,6 +1,7 @@ -// SPDX-License-Identifier: GPL-2.0 +/* SPDX-License-Identifier: GPL-2.0-only */ /* * Copyright (c) 2018, The Linux Foundation. All rights reserved. + * Copyright (c) 2023, Qualcomm Innovation Center, Inc. All rights reserved. */ #ifndef _DT_BINDINGS_CLK_SDM_CAM_CC_SDM845_H @@ -87,11 +88,12 @@ #define CAM_CC_PLL1_OUT_EVEN 77 #define CAM_CC_PLL2 78 #define CAM_CC_PLL2_OUT_EVEN 79 -#define CAM_CC_PLL3 80 -#define CAM_CC_PLL3_OUT_EVEN 81 -#define CAM_CC_SLOW_AHB_CLK_SRC 82 -#define CAM_CC_SOC_AHB_CLK 83 -#define CAM_CC_SYS_TMR_CLK 84 +#define CAM_CC_PLL2_OUT_ODD 80 +#define CAM_CC_PLL3 81 +#define CAM_CC_PLL3_OUT_EVEN 82 +#define CAM_CC_SLOW_AHB_CLK_SRC 83 +#define CAM_CC_SOC_AHB_CLK 84 +#define CAM_CC_SYS_TMR_CLK 85 /* CAM_CC Resets */ #define TITAN_CAM_CC_CCI_BCR 0 @@ -106,11 +108,11 @@ #define TITAN_CAM_CC_TITAN_TOP_BCR 9 /* CAM_CC GDSCRs */ -#define BPS_GDSC 0 -#define IPE_0_GDSC 1 -#define IPE_1_GDSC 2 -#define IFE_0_GDSC 3 -#define IFE_1_GDSC 4 -#define TITAN_TOP_GDSC 5 +#define BPS_GDSC 0 +#define IPE_0_GDSC 1 +#define IPE_1_GDSC 2 +#define IFE_0_GDSC 3 +#define IFE_1_GDSC 4 +#define TITAN_TOP_GDSC 5 #endif diff --git a/include/dt-bindings/clock/qcom,gcc-sdm845.h b/include/dt-bindings/clock/qcom,gcc-sdm845.h index 968fa65b9c42..7e52026bcd3e 100644 --- a/include/dt-bindings/clock/qcom,gcc-sdm845.h +++ b/include/dt-bindings/clock/qcom,gcc-sdm845.h @@ -1,6 +1,7 @@ -/* SPDX-License-Identifier: GPL-2.0 */ +/* SPDX-License-Identifier: GPL-2.0-only */ /* * Copyright (c) 2018, The Linux Foundation. All rights reserved. + * Copyright (c) 2023, Qualcomm Innovation Center, Inc. All rights reserved. */ #ifndef _DT_BINDINGS_CLK_SDM_GCC_SDM845_H @@ -199,6 +200,11 @@ #define GCC_QSPI_CNOC_PERIPH_AHB_CLK 189 #define GCC_LPASS_Q6_AXI_CLK 190 #define GCC_LPASS_SWAY_CLK 191 +#define GCC_UFS_PHY_PHY_AUX_HW_CTL_CLK 192 +#define GCC_UFS_PHY_AXI_HW_CTL_CLK 193 +#define GCC_UFS_PHY_UNIPRO_CORE_HW_CTL_CLK 194 +#define GCC_UFS_PHY_ICE_CORE_HW_CTL_CLK 195 +#define GPLL6 196 /* GCC Resets */ #define GCC_MMSS_BCR 0 @@ -227,6 +233,7 @@ #define GCC_USB_PHY_CFG_AHB2PHY_BCR 23 #define GCC_PCIE_0_PHY_BCR 24 #define GCC_PCIE_1_PHY_BCR 25 +#define GCC_SDCC1_BCR 26 /* GCC GDSCRs */ #define PCIE_0_GDSC 0 diff --git a/include/dt-bindings/clock/qcom,gpucc-crow.h b/include/dt-bindings/clock/qcom,gpucc-crow.h index 786b8a899b80..3c61e52c2792 100644 --- a/include/dt-bindings/clock/qcom,gpucc-crow.h +++ b/include/dt-bindings/clock/qcom,gpucc-crow.h @@ -43,5 +43,5 @@ #define GPUCC_GPU_CC_GX_BCR 7 #define GPUCC_GPU_CC_RBCPR_BCR 8 #define GPUCC_GPU_CC_XO_BCR 9 - +#define GPUCC_GPU_CC_FREQUENCY_LIMITER_IRQ_CLEAR 10 #endif diff --git a/include/dt-bindings/clock/qcom,gpucc-sdm845.h b/include/dt-bindings/clock/qcom,gpucc-sdm845.h index 9690d901b50a..4cab03dce804 100644 --- a/include/dt-bindings/clock/qcom,gpucc-sdm845.h +++ b/include/dt-bindings/clock/qcom,gpucc-sdm845.h @@ -1,24 +1,53 @@ -/* SPDX-License-Identifier: GPL-2.0 */ +/* SPDX-License-Identifier: GPL-2.0-only */ /* * Copyright (c) 2018, The Linux Foundation. All rights reserved. + * Copyright (c) 2023, Qualcomm Innovation Center, Inc. All rights reserved. */ #ifndef _DT_BINDINGS_CLK_SDM_GPU_CC_SDM845_H #define _DT_BINDINGS_CLK_SDM_GPU_CC_SDM845_H -/* GPU_CC clock registers */ -#define GPU_CC_CX_GMU_CLK 0 -#define GPU_CC_CXO_CLK 1 -#define GPU_CC_GMU_CLK_SRC 2 -#define GPU_CC_PLL1 3 - -/* GPU_CC Resets */ -#define GPUCC_GPU_CC_CX_BCR 0 -#define GPUCC_GPU_CC_GMU_BCR 1 -#define GPUCC_GPU_CC_XO_BCR 2 +/* GPUCC clock registers */ +#define GPU_CC_ACD_AHB_CLK 0 +#define GPU_CC_ACD_CXO_CLK 1 +#define GPU_CC_CRC_AHB_CLK 2 +#define GPU_CC_CX_APB_CLK 3 +#define GPU_CC_CX_GMU_CLK 4 +#define GPU_CC_CX_QDSS_AT_CLK 5 +#define GPU_CC_CX_QDSS_TRIG_CLK 6 +#define GPU_CC_CX_QDSS_TSCTR_CLK 7 +#define GPU_CC_CX_SNOC_DVM_CLK 8 +#define GPU_CC_CXO_AON_CLK 9 +#define GPU_CC_CXO_CLK 10 +#define GPU_CC_GX_GMU_CLK 11 +#define GPU_CC_GX_QDSS_TSCTR_CLK 12 +#define GPU_CC_GX_VSENSE_CLK 13 +#define GPU_CC_PLL0 14 +#define GPU_CC_PLL0_OUT_EVEN 15 +#define GPU_CC_PLL0_OUT_MAIN 16 +#define GPU_CC_PLL0_OUT_ODD 17 +#define GPU_CC_PLL1 18 +#define GPU_CC_PLL1_OUT_EVEN 19 +#define GPU_CC_PLL1_OUT_MAIN 20 +#define GPU_CC_PLL1_OUT_ODD 21 +#define GPU_CC_SLEEP_CLK 22 +#define GPU_CC_GMU_CLK_SRC 23 +#define GPU_CC_CX_GFX3D_CLK 24 +#define GPU_CC_CX_GFX3D_SLV_CLK 25 +#define GPU_CC_GX_GFX3D_CLK_SRC 26 +#define GPU_CC_GX_GFX3D_CLK 27 /* GPU_CC GDSCRs */ -#define GPU_CX_GDSC 0 -#define GPU_GX_GDSC 1 +#define GPU_CX_GDSC 0 +#define GPU_GX_GDSC 1 + +/* GPUCC reset clock registers */ +#define GPUCC_GPU_CC_ACD_BCR 0 +#define GPUCC_GPU_CC_CX_BCR 1 +#define GPUCC_GPU_CC_GFX3D_AON_BCR 2 +#define GPUCC_GPU_CC_GMU_BCR 3 +#define GPUCC_GPU_CC_GX_BCR 4 +#define GPUCC_GPU_CC_SPDM_BCR 5 +#define GPUCC_GPU_CC_XO_BCR 6 #endif diff --git a/include/dt-bindings/interconnect/qcom,sdm670.h b/include/dt-bindings/interconnect/qcom,sdm670.h new file mode 100644 index 000000000000..ae8afeb064dd --- /dev/null +++ b/include/dt-bindings/interconnect/qcom,sdm670.h @@ -0,0 +1,138 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2023, Qualcomm Innovation Center, Inc. All rights reserved. + */ + +#ifndef __DT_BINDINGS_INTERCONNECT_QCOM_SDM670_H +#define __DT_BINDINGS_INTERCONNECT_QCOM_SDM670_H + +#define MASTER_APPSS_PROC 0 +#define MASTER_TCU_0 1 +#define MASTER_LLCC 2 +#define MASTER_GNOC_CFG 3 +#define MASTER_A1NOC_CFG 4 +#define MASTER_A2NOC_CFG 5 +#define MASTER_CNOC_DC_NOC 6 +#define MASTER_MEM_NOC_CFG 7 +#define MASTER_CNOC_MNOC_CFG 8 +#define MASTER_QDSS_BAM 9 +#define MASTER_BLSP_1 10 +#define MASTER_BLSP_2 11 +#define MASTER_SNOC_CFG 12 +#define MASTER_SPDM 13 +#define MASTER_TIC 14 +#define MASTER_TSIF 15 +#define MASTER_A1NOC_SNOC 16 +#define MASTER_A2NOC_SNOC 17 +#define MASTER_GNOC_MEM_NOC 18 +#define MASTER_CNOC_A2NOC 19 +#define MASTER_GNOC_SNOC 20 +#define MASTER_MEM_NOC_SNOC 21 +#define MASTER_MNOC_HF_MEM_NOC 22 +#define MASTER_MNOC_SF_MEM_NOC 23 +#define MASTER_SNOC_CNOC 24 +#define MASTER_SNOC_GC_MEM_NOC 25 +#define MASTER_SNOC_SF_MEM_NOC 26 +#define MASTER_CAMNOC_HF0 27 +#define MASTER_CAMNOC_HF0_UNCOMP 28 +#define MASTER_CAMNOC_HF1 29 +#define MASTER_CAMNOC_HF1_UNCOMP 30 +#define MASTER_CAMNOC_SF 31 +#define MASTER_CAMNOC_SF_UNCOMP 32 +#define MASTER_CRYPTO 33 +#define MASTER_GFX3D 34 +#define MASTER_IPA 35 +#define MASTER_MDP0 36 +#define MASTER_MDP1 37 +#define MASTER_PIMEM 38 +#define MASTER_ROTATOR 39 +#define MASTER_VIDEO_P0 40 +#define MASTER_VIDEO_P1 41 +#define MASTER_VIDEO_PROC 42 +#define MASTER_EMMC 43 +#define MASTER_GIC 44 +#define MASTER_QDSS_DAP 45 +#define MASTER_QDSS_ETR 46 +#define MASTER_SDCC_2 47 +#define MASTER_SDCC_4 48 +#define MASTER_UFS_MEM 49 +#define MASTER_USB3_0 50 +#define SLAVE_EBI1 512 +#define SLAVE_A1NOC_CFG 513 +#define SLAVE_A2NOC_CFG 514 +#define SLAVE_AOP 515 +#define SLAVE_AOSS 516 +#define SLAVE_APPSS 517 +#define SLAVE_CAMERA_CFG 518 +#define SLAVE_CLK_CTL 519 +#define SLAVE_CDSP_CFG 520 +#define SLAVE_RBCPR_CX_CFG 521 +#define SLAVE_CRYPTO_0_CFG 522 +#define SLAVE_DCC_CFG 523 +#define SLAVE_CNOC_DDRSS 524 +#define SLAVE_DISPLAY_CFG 525 +#define SLAVE_EMMC_CFG 526 +#define SLAVE_GLM 527 +#define SLAVE_GFX3D_CFG 528 +#define SLAVE_IMEM_CFG 529 +#define SLAVE_IPA_CFG 530 +#define SLAVE_LLCC_CFG 531 +#define SLAVE_MSS_PROC_MS_MPU_CFG 532 +#define SLAVE_MEM_NOC_CFG 533 +#define SLAVE_CNOC_MNOC_CFG 534 +#define SLAVE_PDM 535 +#define SLAVE_SOUTH_PHY_CFG 536 +#define SLAVE_PIMEM_CFG 537 +#define SLAVE_PRNG 538 +#define SLAVE_QDSS_CFG 539 +#define SLAVE_BLSP_2 540 +#define SLAVE_BLSP_1 541 +#define SLAVE_SDCC_2 542 +#define SLAVE_SDCC_4 543 +#define SLAVE_SNOC_CFG 544 +#define SLAVE_SPDM_WRAPPER 545 +#define SLAVE_TCSR 546 +#define SLAVE_TLMM_NORTH 547 +#define SLAVE_TLMM_SOUTH 548 +#define SLAVE_TSIF 549 +#define SLAVE_UFS_MEM_CFG 550 +#define SLAVE_USB3_0 551 +#define SLAVE_VENUS_CFG 552 +#define SLAVE_VSENSE_CTRL_CFG 553 +#define SLAVE_MNOC_SF_MEM_NOC 554 +#define SLAVE_A1NOC_SNOC 555 +#define SLAVE_A2NOC_SNOC 556 +#define SLAVE_MEM_NOC_GNOC 557 +#define SLAVE_CAMNOC_UNCOMP 558 +#define SLAVE_SNOC_CNOC 559 +#define SLAVE_CNOC_A2NOC 560 +#define SLAVE_GNOC_SNOC 561 +#define SLAVE_GNOC_MEM_NOC 562 +#define SLAVE_LLCC 563 +#define SLAVE_MNOC_HF_MEM_NOC 564 +#define SLAVE_SNOC_MEM_NOC_GC 565 +#define SLAVE_SNOC_MEM_NOC_SF 566 +#define SLAVE_MEM_NOC_SNOC 567 +#define SLAVE_IMEM 568 +#define SLAVE_PIMEM 569 +#define SLAVE_SERVICE_A1NOC 570 +#define SLAVE_SERVICE_A2NOC 571 +#define SLAVE_SERVICE_CNOC 572 +#define SLAVE_SERVICE_GNOC 573 +#define SLAVE_SERVICE_MEM_NOC 574 +#define SLAVE_SERVICE_MNOC 575 +#define SLAVE_SERVICE_SNOC 576 +#define SLAVE_QDSS_STM 577 +#define SLAVE_TCU 578 +#define MASTER_LLCC_DISP 1000 +#define MASTER_MNOC_HF_MEM_NOC_DISP 1001 +#define MASTER_MNOC_SF_MEM_NOC_DISP 1002 +#define MASTER_MDP0_DISP 1003 +#define MASTER_MDP1_DISP 1004 +#define MASTER_ROTATOR_DISP 1005 +#define SLAVE_EBI1_DISP 1512 +#define SLAVE_MNOC_SF_MEM_NOC_DISP 1513 +#define SLAVE_LLCC_DISP 1514 +#define SLAVE_MNOC_HF_MEM_NOC_DISP 1515 + +#endif diff --git a/include/dt-bindings/phy/qcom,qcs605-qmp-usb3.h b/include/dt-bindings/phy/qcom,qcs605-qmp-usb3.h new file mode 100644 index 000000000000..d1b3ae868578 --- /dev/null +++ b/include/dt-bindings/phy/qcom,qcs605-qmp-usb3.h @@ -0,0 +1,770 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2023, Qualcomm Innovation Center, Inc. All rights reserved. + */ + +#ifndef _DT_BINDINGS_PHY_QCOM_KHAJE_QMP_USB_H +#define _DT_BINDINGS_PHY_QCOM_KHAJE_QMP_USB_H + +/* USB3-DP Combo PHY register offsets */ +/* Module: USB3_DP_PHY_USB3_DP_COM_USB3_DP_COM_USB3_DP_COM */ +#define USB3_DP_COM_PHY_MODE_CTRL 0x0000 +#define USB3_DP_COM_SW_RESET 0x0004 +#define USB3_DP_COM_POWER_DOWN_CTRL 0x0008 +#define USB3_DP_COM_SWI_CTRL 0x000C +#define USB3_DP_COM_TYPEC_CTRL 0x0010 +#define USB3_DP_COM_TYPEC_PWRDN_CTRL 0x0014 +#define USB3_DP_COM_DP_BIST_CFG_0 0x0018 +#define USB3_DP_COM_RESET_OVRD_CTRL 0x001C +#define USB3_DP_COM_DBG_CLK_MUX_CTRL 0x0020 +#define USB3_DP_COM_TYPEC_STATUS 0x0024 +#define USB3_DP_COM_PLACEHOLDER_STATUS 0x0028 +#define USB3_DP_COM_REVISION_ID0 0x002C +#define USB3_DP_COM_REVISION_ID1 0x0030 +#define USB3_DP_COM_REVISION_ID2 0x0034 +#define USB3_DP_COM_REVISION_ID3 0x0038 + +/* Module: USB3_DP_PHY_USB3_QSERDES_COM_USB3_QSERDES_COM_USB3_DP_QMP_PLL */ +#define USB3_DP_QSERDES_COM_ATB_SEL1 0x1000 +#define USB3_DP_QSERDES_COM_ATB_SEL2 0x1004 +#define USB3_DP_QSERDES_COM_FREQ_UPDATE 0x1008 +#define USB3_DP_QSERDES_COM_BG_TIMER 0x100C +#define USB3_DP_QSERDES_COM_SSC_EN_CENTER 0x1010 +#define USB3_DP_QSERDES_COM_SSC_ADJ_PER1 0x1014 +#define USB3_DP_QSERDES_COM_SSC_ADJ_PER2 0x1018 +#define USB3_DP_QSERDES_COM_SSC_PER1 0x101C +#define USB3_DP_QSERDES_COM_SSC_PER2 0x1020 +#define USB3_DP_QSERDES_COM_SSC_STEP_SIZE1_MODE0 0x1024 +#define USB3_DP_QSERDES_COM_SSC_STEP_SIZE2_MODE0 0x1028 +#define USB3_DP_QSERDES_COM_SSC_STEP_SIZE3_MODE0 0x102C +#define USB3_DP_QSERDES_COM_SSC_STEP_SIZE1_MODE1 0x1030 +#define USB3_DP_QSERDES_COM_SSC_STEP_SIZE2_MODE1 0x1034 +#define USB3_DP_QSERDES_COM_SSC_STEP_SIZE3_MODE1 0x1038 +#define USB3_DP_QSERDES_COM_POST_DIV 0x103C +#define USB3_DP_QSERDES_COM_POST_DIV_MUX 0x1040 +#define USB3_DP_QSERDES_COM_BIAS_EN_CLKBUFLR_EN 0x1044 +#define USB3_DP_QSERDES_COM_CLK_ENABLE1 0x1048 +#define USB3_DP_QSERDES_COM_SYS_CLK_CTRL 0x104C +#define USB3_DP_QSERDES_COM_SYSCLK_BUF_ENABLE 0x1050 +#define USB3_DP_QSERDES_COM_PLL_EN 0x1054 +#define USB3_DP_QSERDES_COM_PLL_IVCO 0x1058 +#define USB3_DP_QSERDES_COM_CMN_IETRIM 0x105C +#define USB3_DP_QSERDES_COM_CMN_IPTRIM 0x1060 +#define USB3_DP_QSERDES_COM_EP_CLOCK_DETECT_CTRL 0x1064 +#define USB3_DP_QSERDES_COM_SYSCLK_DET_COMP_STATUS 0x1068 +#define USB3_DP_QSERDES_COM_CLK_EP_DIV_MODE0 0x106C +#define USB3_DP_QSERDES_COM_CLK_EP_DIV_MODE1 0x1070 +#define USB3_DP_QSERDES_COM_CP_CTRL_MODE0 0x1074 +#define USB3_DP_QSERDES_COM_CP_CTRL_MODE1 0x1078 +#define USB3_DP_QSERDES_COM_PLL_RCTRL_MODE0 0x107C +#define USB3_DP_QSERDES_COM_PLL_RCTRL_MODE1 0x1080 +#define USB3_DP_QSERDES_COM_PLL_CCTRL_MODE0 0x1084 +#define USB3_DP_QSERDES_COM_PLL_CCTRL_MODE1 0x1088 +#define USB3_DP_QSERDES_COM_PLL_CNTRL 0x108C +#define USB3_DP_QSERDES_COM_BIAS_EN_CTRL_BY_PSM 0x1090 +#define USB3_DP_QSERDES_COM_SYSCLK_EN_SEL 0x1094 +#define USB3_DP_QSERDES_COM_CML_SYSCLK_SEL 0x1098 +#define USB3_DP_QSERDES_COM_RESETSM_CNTRL 0x109C +#define USB3_DP_QSERDES_COM_RESETSM_CNTRL2 0x10A0 +#define USB3_DP_QSERDES_COM_LOCK_CMP_EN 0x10A4 +#define USB3_DP_QSERDES_COM_LOCK_CMP_CFG 0x10A8 +#define USB3_DP_QSERDES_COM_LOCK_CMP1_MODE0 0x10AC +#define USB3_DP_QSERDES_COM_LOCK_CMP2_MODE0 0x10B0 +#define USB3_DP_QSERDES_COM_LOCK_CMP1_MODE1 0x10B4 +#define USB3_DP_QSERDES_COM_LOCK_CMP2_MODE1 0x10B8 +#define USB3_DP_QSERDES_COM_DEC_START_MODE0 0x10BC +#define USB3_DP_QSERDES_COM_DEC_START_MSB_MODE0 0x10C0 +#define USB3_DP_QSERDES_COM_DEC_START_MODE1 0x10C4 +#define USB3_DP_QSERDES_COM_DEC_START_MSB_MODE1 0x10C8 +#define USB3_DP_QSERDES_COM_DIV_FRAC_START1_MODE0 0x10CC +#define USB3_DP_QSERDES_COM_DIV_FRAC_START2_MODE0 0x10D0 +#define USB3_DP_QSERDES_COM_DIV_FRAC_START3_MODE0 0x10D4 +#define USB3_DP_QSERDES_COM_DIV_FRAC_START1_MODE1 0x10D8 +#define USB3_DP_QSERDES_COM_DIV_FRAC_START2_MODE1 0x10DC +#define USB3_DP_QSERDES_COM_DIV_FRAC_START3_MODE1 0x10E0 +#define USB3_DP_QSERDES_COM_INTEGLOOP_INITVAL 0x10E4 +#define USB3_DP_QSERDES_COM_INTEGLOOP_EN 0x10E8 +#define USB3_DP_QSERDES_COM_INTEGLOOP_GAIN0_MODE0 0x10EC +#define USB3_DP_QSERDES_COM_INTEGLOOP_GAIN1_MODE0 0x10F0 +#define USB3_DP_QSERDES_COM_INTEGLOOP_GAIN0_MODE1 0x10F4 +#define USB3_DP_QSERDES_COM_INTEGLOOP_GAIN1_MODE1 0x10F8 +#define USB3_DP_QSERDES_COM_INTEGLOOP_P_PATH_GAIN0 0x10FC +#define USB3_DP_QSERDES_COM_INTEGLOOP_P_PATH_GAIN1 0x1100 +#define USB3_DP_QSERDES_COM_VCOCAL_DEADMAN_CTRL 0x1104 +#define USB3_DP_QSERDES_COM_VCO_TUNE_CTRL 0x1108 +#define USB3_DP_QSERDES_COM_VCO_TUNE_MAP 0x110C +#define USB3_DP_QSERDES_COM_VCO_TUNE1_MODE0 0x1110 +#define USB3_DP_QSERDES_COM_VCO_TUNE2_MODE0 0x1114 +#define USB3_DP_QSERDES_COM_VCO_TUNE1_MODE1 0x1118 +#define USB3_DP_QSERDES_COM_VCO_TUNE2_MODE1 0x111C +#define USB3_DP_QSERDES_COM_VCO_TUNE_INITVAL1 0x1120 +#define USB3_DP_QSERDES_COM_VCO_TUNE_INITVAL2 0x1124 +#define USB3_DP_QSERDES_COM_VCO_TUNE_MINVAL1 0x1128 +#define USB3_DP_QSERDES_COM_VCO_TUNE_MINVAL2 0x112C +#define USB3_DP_QSERDES_COM_VCO_TUNE_MAXVAL1 0x1130 +#define USB3_DP_QSERDES_COM_VCO_TUNE_MAXVAL2 0x1134 +#define USB3_DP_QSERDES_COM_VCO_TUNE_TIMER1 0x1138 +#define USB3_DP_QSERDES_COM_VCO_TUNE_TIMER2 0x113C +#define USB3_DP_QSERDES_COM_CMN_STATUS 0x1140 +#define USB3_DP_QSERDES_COM_RESET_SM_STATUS 0x1144 +#define USB3_DP_QSERDES_COM_RESTRIM_CODE_STATUS 0x1148 +#define USB3_DP_QSERDES_COM_PLLCAL_CODE1_STATUS 0x114C +#define USB3_DP_QSERDES_COM_PLLCAL_CODE2_STATUS 0x1150 +#define USB3_DP_QSERDES_COM_CLK_SELECT 0x1154 +#define USB3_DP_QSERDES_COM_HSCLK_SEL 0x1158 +#define USB3_DP_QSERDES_COM_HSCLK_HS_SWITCH_SEL 0x115C +#define USB3_DP_QSERDES_COM_INTEGLOOP_BINCODE_STATUS 0x1160 +#define USB3_DP_QSERDES_COM_PLL_ANALOG 0x1164 +#define USB3_DP_QSERDES_COM_CORECLK_DIV_MODE0 0x1168 +#define USB3_DP_QSERDES_COM_CORECLK_DIV_MODE1 0x116C +#define USB3_DP_QSERDES_COM_SW_RESET 0x1170 +#define USB3_DP_QSERDES_COM_CORE_CLK_EN 0x1174 +#define USB3_DP_QSERDES_COM_C_READY_STATUS 0x1178 +#define USB3_DP_QSERDES_COM_CMN_CONFIG 0x117C +#define USB3_DP_QSERDES_COM_CMN_RATE_OVERRIDE 0x1180 +#define USB3_DP_QSERDES_COM_SVS_MODE_CLK_SEL 0x1184 +#define USB3_DP_QSERDES_COM_DEBUG_BUS0 0x1188 +#define USB3_DP_QSERDES_COM_DEBUG_BUS1 0x118C +#define USB3_DP_QSERDES_COM_DEBUG_BUS2 0x1190 +#define USB3_DP_QSERDES_COM_DEBUG_BUS3 0x1194 +#define USB3_DP_QSERDES_COM_DEBUG_BUS_SEL 0x1198 +#define USB3_DP_QSERDES_COM_CMN_MISC1 0x119C +#define USB3_DP_QSERDES_COM_CMN_MISC2 0x11A0 +#define USB3_DP_QSERDES_COM_CMN_MODE 0x11A4 +#define USB3_DP_QSERDES_COM_VCO_DC_LEVEL_CTRL 0x11A8 +#define USB3_DP_QSERDES_COM_BIN_VCOCAL_CMP_CODE1_MODE0 0x11AC +#define USB3_DP_QSERDES_COM_BIN_VCOCAL_CMP_CODE2_MODE0 0x11B0 +#define USB3_DP_QSERDES_COM_BIN_VCOCAL_CMP_CODE1_MODE1 0x11B4 +#define USB3_DP_QSERDES_COM_BIN_VCOCAL_CMP_CODE2_MODE1 0x11B8 +#define USB3_DP_QSERDES_COM_BIN_VCOCAL_HSCLK_SEL 0x11BC + +/* Module: USB3_DP_PHY_USB3_QSERDES_TXA_USB3_QSERDES_TXA_USB3_DP_QMP_TX */ +#define USB3_DP_QSERDES_TXA_BIST_MODE_LANENO 0x1200 +#define USB3_DP_QSERDES_TXA_BIST_INVERT 0x1204 +#define USB3_DP_QSERDES_TXA_CLKBUF_ENABLE 0x1208 +#define USB3_DP_QSERDES_TXA_TX_EMP_POST1_LVL 0x120C +#define USB3_DP_QSERDES_TXA_TX_IDLE_LVL_LARGE_AMP 0x1210 +#define USB3_DP_QSERDES_TXA_TX_DRV_LVL 0x1214 +#define USB3_DP_QSERDES_TXA_TX_DRV_LVL_OFFSET 0x1218 +#define USB3_DP_QSERDES_TXA_RESET_TSYNC_EN 0x121C +#define USB3_DP_QSERDES_TXA_PRE_STALL_LDO_BOOST_EN 0x1220 +#define USB3_DP_QSERDES_TXA_TX_BAND 0x1224 +#define USB3_DP_QSERDES_TXA_SLEW_CNTL 0x1228 +#define USB3_DP_QSERDES_TXA_INTERFACE_SELECT 0x122C +#define USB3_DP_QSERDES_TXA_LPB_EN 0x1230 +#define USB3_DP_QSERDES_TXA_RES_CODE_LANE_TX 0x1234 +#define USB3_DP_QSERDES_TXA_RES_CODE_LANE_RX 0x1238 +#define USB3_DP_QSERDES_TXA_RES_CODE_LANE_OFFSET_TX 0x123C +#define USB3_DP_QSERDES_TXA_RES_CODE_LANE_OFFSET_RX 0x1240 +#define USB3_DP_QSERDES_TXA_PERL_LENGTH1 0x1244 +#define USB3_DP_QSERDES_TXA_PERL_LENGTH2 0x1248 +#define USB3_DP_QSERDES_TXA_SERDES_BYP_EN_OUT 0x124C +#define USB3_DP_QSERDES_TXA_DEBUG_BUS_SEL 0x1250 +#define USB3_DP_QSERDES_TXA_TRANSCEIVER_BIAS_EN 0x1254 +#define USB3_DP_QSERDES_TXA_HIGHZ_DRVR_EN 0x1258 +#define USB3_DP_QSERDES_TXA_TX_POL_INV 0x125C +#define USB3_DP_QSERDES_TXA_PARRATE_REC_DETECT_IDLE_EN 0x1260 +#define USB3_DP_QSERDES_TXA_BIST_PATTERN1 0x1264 +#define USB3_DP_QSERDES_TXA_BIST_PATTERN2 0x1268 +#define USB3_DP_QSERDES_TXA_BIST_PATTERN3 0x126C +#define USB3_DP_QSERDES_TXA_BIST_PATTERN4 0x1270 +#define USB3_DP_QSERDES_TXA_BIST_PATTERN5 0x1274 +#define USB3_DP_QSERDES_TXA_BIST_PATTERN6 0x1278 +#define USB3_DP_QSERDES_TXA_BIST_PATTERN7 0x127C +#define USB3_DP_QSERDES_TXA_BIST_PATTERN8 0x1280 +#define USB3_DP_QSERDES_TXA_LANE_MODE_1 0x1284 +#define USB3_DP_QSERDES_TXA_LANE_MODE_2 0x1288 +#define USB3_DP_QSERDES_TXA_LANE_MODE_3 0x128C +#define USB3_DP_QSERDES_TXA_ATB_SEL1 0x1290 +#define USB3_DP_QSERDES_TXA_ATB_SEL2 0x1294 +#define USB3_DP_QSERDES_TXA_RCV_DETECT_LVL 0x1298 +#define USB3_DP_QSERDES_TXA_RCV_DETECT_LVL_2 0x129C +#define USB3_DP_QSERDES_TXA_PRBS_SEED1 0x12A0 +#define USB3_DP_QSERDES_TXA_PRBS_SEED2 0x12A4 +#define USB3_DP_QSERDES_TXA_PRBS_SEED3 0x12A8 +#define USB3_DP_QSERDES_TXA_PRBS_SEED4 0x12AC +#define USB3_DP_QSERDES_TXA_RESET_GEN 0x12B0 +#define USB3_DP_QSERDES_TXA_RESET_GEN_MUXES 0x12B4 +#define USB3_DP_QSERDES_TXA_TRAN_DRVR_EMP_EN 0x12B8 +#define USB3_DP_QSERDES_TXA_TX_INTERFACE_MODE 0x12BC +#define USB3_DP_QSERDES_TXA_PWM_CTRL 0x12C0 +#define USB3_DP_QSERDES_TXA_PWM_ENCODED_OR_DATA 0x12C4 +#define USB3_DP_QSERDES_TXA_PWM_GEAR_1_DIVIDER_BAND2 0x12C8 +#define USB3_DP_QSERDES_TXA_PWM_GEAR_2_DIVIDER_BAND2 0x12CC +#define USB3_DP_QSERDES_TXA_PWM_GEAR_3_DIVIDER_BAND2 0x12D0 +#define USB3_DP_QSERDES_TXA_PWM_GEAR_4_DIVIDER_BAND2 0x12D4 +#define USB3_DP_QSERDES_TXA_PWM_GEAR_1_DIVIDER_BAND0_1 0x12D8 +#define USB3_DP_QSERDES_TXA_PWM_GEAR_2_DIVIDER_BAND0_1 0x12DC +#define USB3_DP_QSERDES_TXA_PWM_GEAR_3_DIVIDER_BAND0_1 0x12E0 +#define USB3_DP_QSERDES_TXA_PWM_GEAR_4_DIVIDER_BAND0_1 0x12E4 +#define USB3_DP_QSERDES_TXA_VMODE_CTRL1 0x12E8 +#define USB3_DP_QSERDES_TXA_ALOG_OBSV_BUS_CTRL_1 0x12EC +#define USB3_DP_QSERDES_TXA_BIST_STATUS 0x12F0 +#define USB3_DP_QSERDES_TXA_BIST_ERROR_COUNT1 0x12F4 +#define USB3_DP_QSERDES_TXA_BIST_ERROR_COUNT2 0x12F8 +#define USB3_DP_QSERDES_TXA_ALOG_OBSV_BUS_STATUS_1 0x12FC +#define USB3_DP_QSERDES_TXA_LANE_DIG_CONFIG 0x1300 +#define USB3_DP_QSERDES_TXA_PI_QEC_CTRL 0x1304 +#define USB3_DP_QSERDES_TXA_PRE_EMPH 0x1308 +#define USB3_DP_QSERDES_TXA_SW_RESET 0x130C +#define USB3_DP_QSERDES_TXA_DCC_OFFSET 0x1310 +#define USB3_DP_QSERDES_TXA_DIG_BKUP_CTRL 0x1314 +#define USB3_DP_QSERDES_TXA_DEBUG_BUS0 0x1318 +#define USB3_DP_QSERDES_TXA_DEBUG_BUS1 0x131C +#define USB3_DP_QSERDES_TXA_DEBUG_BUS2 0x1320 +#define USB3_DP_QSERDES_TXA_DEBUG_BUS3 0x1324 +#define USB3_DP_QSERDES_TXA_READ_EQCODE 0x1328 +#define USB3_DP_QSERDES_TXA_READ_OFFSETCODE 0x132C +#define USB3_DP_QSERDES_TXA_IA_ERROR_COUNTER_LOW 0x1330 +#define USB3_DP_QSERDES_TXA_IA_ERROR_COUNTER_HIGH 0x1334 +#define USB3_DP_QSERDES_TXA_VGA_READ_CODE 0x1338 +#define USB3_DP_QSERDES_TXA_VTH_READ_CODE 0x133C +#define USB3_DP_QSERDES_TXA_DFE_TAP1_READ_CODE 0x1340 +#define USB3_DP_QSERDES_TXA_DFE_TAP2_READ_CODE 0x1344 +#define USB3_DP_QSERDES_TXA_IDAC_STATUS_I 0x1348 +#define USB3_DP_QSERDES_TXA_IDAC_STATUS_IBAR 0x134C +#define USB3_DP_QSERDES_TXA_IDAC_STATUS_Q 0x1350 +#define USB3_DP_QSERDES_TXA_IDAC_STATUS_QBAR 0x1354 +#define USB3_DP_QSERDES_TXA_IDAC_STATUS_A 0x1358 +#define USB3_DP_QSERDES_TXA_IDAC_STATUS_ABAR 0x135C +#define USB3_DP_QSERDES_TXA_IDAC_STATUS_SM_ON 0x1360 +#define USB3_DP_QSERDES_TXA_IDAC_STATUS_CAL_DONE 0x1364 +#define USB3_DP_QSERDES_TXA_IDAC_STATUS_SIGNERROR 0x1368 +#define USB3_DP_QSERDES_TXA_DCC_CAL_STATUS 0x136C + +/* Module: USB3_DP_PHY_USB3_QSERDES_RXA_USB3_QSERDES_RXA_USB3_DP_QMP_RX */ +#define USB3_DP_QSERDES_RXA_UCDR_FO_GAIN_HALF 0x1400 +#define USB3_DP_QSERDES_RXA_UCDR_FO_GAIN_QUARTER 0x1404 +#define USB3_DP_QSERDES_RXA_UCDR_FO_GAIN 0x1408 +#define USB3_DP_QSERDES_RXA_UCDR_SO_GAIN_HALF 0x140C +#define USB3_DP_QSERDES_RXA_UCDR_SO_GAIN_QUARTER 0x1410 +#define USB3_DP_QSERDES_RXA_UCDR_SO_GAIN 0x1414 +#define USB3_DP_QSERDES_RXA_UCDR_SVS_FO_GAIN_HALF 0x1418 +#define USB3_DP_QSERDES_RXA_UCDR_SVS_FO_GAIN_QUARTER 0x141C +#define USB3_DP_QSERDES_RXA_UCDR_SVS_FO_GAIN 0x1420 +#define USB3_DP_QSERDES_RXA_UCDR_SVS_SO_GAIN_HALF 0x1424 +#define USB3_DP_QSERDES_RXA_UCDR_SVS_SO_GAIN_QUARTER 0x1428 +#define USB3_DP_QSERDES_RXA_UCDR_SVS_SO_GAIN 0x142C +#define USB3_DP_QSERDES_RXA_UCDR_FASTLOCK_FO_GAIN 0x1430 +#define USB3_DP_QSERDES_RXA_UCDR_SO_SATURATION_AND_ENABLE 0x1434 +#define USB3_DP_QSERDES_RXA_UCDR_FO_TO_SO_DELAY 0x1438 +#define USB3_DP_QSERDES_RXA_UCDR_FASTLOCK_COUNT_LOW 0x143C +#define USB3_DP_QSERDES_RXA_UCDR_FASTLOCK_COUNT_HIGH 0x1440 +#define USB3_DP_QSERDES_RXA_UCDR_PI_CONTROLS 0x1444 +#define USB3_DP_QSERDES_RXA_UCDR_PI_CTRL2 0x1448 +#define USB3_DP_QSERDES_RXA_UCDR_SB2_THRESH1 0x144C +#define USB3_DP_QSERDES_RXA_UCDR_SB2_THRESH2 0x1450 +#define USB3_DP_QSERDES_RXA_UCDR_SB2_GAIN1 0x1454 +#define USB3_DP_QSERDES_RXA_UCDR_SB2_GAIN2 0x1458 +#define USB3_DP_QSERDES_RXA_AUX_CONTROL 0x145C +#define USB3_DP_QSERDES_RXA_AUX_DATA_TCOARSE_TFINE 0x1460 +#define USB3_DP_QSERDES_RXA_RCLK_AUXDATA_SEL 0x1464 +#define USB3_DP_QSERDES_RXA_AC_JTAG_ENABLE 0x1468 +#define USB3_DP_QSERDES_RXA_AC_JTAG_INITP 0x146C +#define USB3_DP_QSERDES_RXA_AC_JTAG_INITN 0x1470 +#define USB3_DP_QSERDES_RXA_AC_JTAG_LVL 0x1474 +#define USB3_DP_QSERDES_RXA_AC_JTAG_MODE 0x1478 +#define USB3_DP_QSERDES_RXA_AC_JTAG_RESET 0x147C +#define USB3_DP_QSERDES_RXA_RX_TERM_BW 0x1480 +#define USB3_DP_QSERDES_RXA_RX_RCVR_IQ_EN 0x1484 +#define USB3_DP_QSERDES_RXA_RX_IDAC_I_DC_OFFSETS 0x1488 +#define USB3_DP_QSERDES_RXA_RX_IDAC_IBAR_DC_OFFSETS 0x148C +#define USB3_DP_QSERDES_RXA_RX_IDAC_Q_DC_OFFSETS 0x1490 +#define USB3_DP_QSERDES_RXA_RX_IDAC_QBAR_DC_OFFSETS 0x1494 +#define USB3_DP_QSERDES_RXA_RX_IDAC_A_DC_OFFSETS 0x1498 +#define USB3_DP_QSERDES_RXA_RX_IDAC_ABAR_DC_OFFSETS 0x149C +#define USB3_DP_QSERDES_RXA_RX_IDAC_EN 0x14A0 +#define USB3_DP_QSERDES_RXA_RX_IDAC_ENABLES 0x14A4 +#define USB3_DP_QSERDES_RXA_RX_IDAC_SIGN 0x14A8 +#define USB3_DP_QSERDES_RXA_RX_HIGHZ_HIGHRATE 0x14AC +#define USB3_DP_QSERDES_RXA_RX_TERM_AC_BYPASS_DC_COUPLE_OFFSET 0x14B0 +#define USB3_DP_QSERDES_RXA_DFE_1 0x14B4 +#define USB3_DP_QSERDES_RXA_DFE_2 0x14B8 +#define USB3_DP_QSERDES_RXA_DFE_3 0x14BC +#define USB3_DP_QSERDES_RXA_DFE_4 0x14C0 +#define USB3_DP_QSERDES_RXA_TX_ADAPT_PRE_THRESH1 0x14C4 +#define USB3_DP_QSERDES_RXA_TX_ADAPT_PRE_THRESH2 0x14C8 +#define USB3_DP_QSERDES_RXA_TX_ADAPT_POST_THRESH 0x14CC +#define USB3_DP_QSERDES_RXA_TX_ADAPT_MAIN_THRESH 0x14D0 +#define USB3_DP_QSERDES_RXA_VGA_CAL_CNTRL1 0x14D4 +#define USB3_DP_QSERDES_RXA_VGA_CAL_CNTRL2 0x14D8 +#define USB3_DP_QSERDES_RXA_GM_CAL 0x14DC +#define USB3_DP_QSERDES_RXA_RX_VGA_GAIN2_LSB 0x14E0 +#define USB3_DP_QSERDES_RXA_RX_VGA_GAIN2_MSB 0x14E4 +#define USB3_DP_QSERDES_RXA_RX_EQU_ADAPTOR_CNTRL1 0x14E8 +#define USB3_DP_QSERDES_RXA_RX_EQU_ADAPTOR_CNTRL2 0x14EC +#define USB3_DP_QSERDES_RXA_RX_EQU_ADAPTOR_CNTRL3 0x14F0 +#define USB3_DP_QSERDES_RXA_RX_EQU_ADAPTOR_CNTRL4 0x14F4 +#define USB3_DP_QSERDES_RXA_RX_IDAC_TSETTLE_LOW 0x14F8 +#define USB3_DP_QSERDES_RXA_RX_IDAC_TSETTLE_HIGH 0x14FC +#define USB3_DP_QSERDES_RXA_RX_IDAC_MEASURE_TIME 0x1500 +#define USB3_DP_QSERDES_RXA_RX_IDAC_ACCUMULATOR 0x1504 +#define USB3_DP_QSERDES_RXA_RX_EQ_OFFSET_LSB 0x1508 +#define USB3_DP_QSERDES_RXA_RX_EQ_OFFSET_MSB 0x150C +#define USB3_DP_QSERDES_RXA_RX_EQ_OFFSET_ADAPTOR_CNTRL1 0x1510 +#define USB3_DP_QSERDES_RXA_RX_OFFSET_ADAPTOR_CNTRL2 0x1514 +#define USB3_DP_QSERDES_RXA_SIGDET_ENABLES 0x1518 +#define USB3_DP_QSERDES_RXA_SIGDET_CNTRL 0x151C +#define USB3_DP_QSERDES_RXA_SIGDET_LVL 0x1520 +#define USB3_DP_QSERDES_RXA_SIGDET_DEGLITCH_CNTRL 0x1524 +#define USB3_DP_QSERDES_RXA_RX_BAND 0x1528 +#define USB3_DP_QSERDES_RXA_CDR_FREEZE_UP_DN 0x152C +#define USB3_DP_QSERDES_RXA_CDR_RESET_OVERRIDE 0x1530 +#define USB3_DP_QSERDES_RXA_RX_INTERFACE_MODE 0x1534 +#define USB3_DP_QSERDES_RXA_JITTER_GEN_MODE 0x1538 +#define USB3_DP_QSERDES_RXA_SJ_AMP1 0x153C +#define USB3_DP_QSERDES_RXA_SJ_AMP2 0x1540 +#define USB3_DP_QSERDES_RXA_SJ_PER1 0x1544 +#define USB3_DP_QSERDES_RXA_SJ_PER2 0x1548 +#define USB3_DP_QSERDES_RXA_PPM_OFFSET1 0x154C +#define USB3_DP_QSERDES_RXA_PPM_OFFSET2 0x1550 +#define USB3_DP_QSERDES_RXA_SIGN_PPM_PERIOD1 0x1554 +#define USB3_DP_QSERDES_RXA_SIGN_PPM_PERIOD2 0x1558 +#define USB3_DP_QSERDES_RXA_RX_PWM_ENABLE_AND_DATA 0x155C +#define USB3_DP_QSERDES_RXA_RX_PWM_GEAR1_TIMEOUT_COUNT 0x1560 +#define USB3_DP_QSERDES_RXA_RX_PWM_GEAR2_TIMEOUT_COUNT 0x1564 +#define USB3_DP_QSERDES_RXA_RX_PWM_GEAR3_TIMEOUT_COUNT 0x1568 +#define USB3_DP_QSERDES_RXA_RX_PWM_GEAR4_TIMEOUT_COUNT 0x156C +#define USB3_DP_QSERDES_RXA_RX_MODE_00_LOW 0x1570 +#define USB3_DP_QSERDES_RXA_RX_MODE_00_HIGH 0x1574 +#define USB3_DP_QSERDES_RXA_RX_MODE_00_HIGH2 0x1578 +#define USB3_DP_QSERDES_RXA_RX_MODE_00_HIGH3 0x157C +#define USB3_DP_QSERDES_RXA_RX_MODE_00_HIGH4 0x1580 +#define USB3_DP_QSERDES_RXA_RX_MODE_01_LOW 0x1584 +#define USB3_DP_QSERDES_RXA_RX_MODE_01_HIGH 0x1588 +#define USB3_DP_QSERDES_RXA_RX_MODE_01_HIGH2 0x158C +#define USB3_DP_QSERDES_RXA_RX_MODE_01_HIGH3 0x1590 +#define USB3_DP_QSERDES_RXA_RX_MODE_01_HIGH4 0x1594 +#define USB3_DP_QSERDES_RXA_RX_MODE_10_LOW 0x1598 +#define USB3_DP_QSERDES_RXA_RX_MODE_10_HIGH 0x159C +#define USB3_DP_QSERDES_RXA_RX_MODE_10_HIGH2 0x15A0 +#define USB3_DP_QSERDES_RXA_RX_MODE_10_HIGH3 0x15A4 +#define USB3_DP_QSERDES_RXA_RX_MODE_10_HIGH4 0x15A8 +#define USB3_DP_QSERDES_RXA_PHPRE_CTRL 0x15AC +#define USB3_DP_QSERDES_RXA_PHPRE_INITVAL 0x15B0 +#define USB3_DP_QSERDES_RXA_DFE_EN_TIMER 0x15B4 +#define USB3_DP_QSERDES_RXA_DFE_CTLE_POST_CAL_OFFSET 0x15B8 +#define USB3_DP_QSERDES_RXA_DCC_CTRL1 0x15BC +#define USB3_DP_QSERDES_RXA_DCC_CTRL2 0x15C0 +#define USB3_DP_QSERDES_RXA_VTH_CODE 0x15C4 +#define USB3_DP_QSERDES_RXA_VTH_MIN_THRESH 0x15C8 +#define USB3_DP_QSERDES_RXA_VTH_MAX_THRESH 0x15CC +#define USB3_DP_QSERDES_RXA_ALOG_OBSV_BUS_CTRL_1 0x15D0 +#define USB3_DP_QSERDES_RXA_PI_CTRL1 0x15D4 +#define USB3_DP_QSERDES_RXA_PI_CTRL2 0x15D8 +#define USB3_DP_QSERDES_RXA_PI_QUAD 0x15DC +#define USB3_DP_QSERDES_RXA_IDATA1 0x15E0 +#define USB3_DP_QSERDES_RXA_IDATA2 0x15E4 +#define USB3_DP_QSERDES_RXA_AUX_DATA1 0x15E8 +#define USB3_DP_QSERDES_RXA_AUX_DATA2 0x15EC +#define USB3_DP_QSERDES_RXA_AC_JTAG_OUTP 0x15F0 +#define USB3_DP_QSERDES_RXA_AC_JTAG_OUTN 0x15F4 +#define USB3_DP_QSERDES_RXA_RX_SIGDET 0x15F8 +#define USB3_DP_QSERDES_RXA_ALOG_OBSV_BUS_STATUS_1 0x15FC + +/* Module: USB3_DP_PHY_USB3_QSERDES_TXB_USB3_QSERDES_TXB_USB3_DP_QMP_TX */ +#define USB3_DP_QSERDES_TXB_BIST_MODE_LANENO 0x1600 +#define USB3_DP_QSERDES_TXB_BIST_INVERT 0x1604 +#define USB3_DP_QSERDES_TXB_CLKBUF_ENABLE 0x1608 +#define USB3_DP_QSERDES_TXB_TX_EMP_POST1_LVL 0x160C +#define USB3_DP_QSERDES_TXB_TX_IDLE_LVL_LARGE_AMP 0x1610 +#define USB3_DP_QSERDES_TXB_TX_DRV_LVL 0x1614 +#define USB3_DP_QSERDES_TXB_TX_DRV_LVL_OFFSET 0x1618 +#define USB3_DP_QSERDES_TXB_RESET_TSYNC_EN 0x161C +#define USB3_DP_QSERDES_TXB_PRE_STALL_LDO_BOOST_EN 0x1620 +#define USB3_DP_QSERDES_TXB_TX_BAND 0x1624 +#define USB3_DP_QSERDES_TXB_SLEW_CNTL 0x1628 +#define USB3_DP_QSERDES_TXB_INTERFACE_SELECT 0x162C +#define USB3_DP_QSERDES_TXB_LPB_EN 0x1630 +#define USB3_DP_QSERDES_TXB_RES_CODE_LANE_TX 0x1634 +#define USB3_DP_QSERDES_TXB_RES_CODE_LANE_RX 0x1638 +#define USB3_DP_QSERDES_TXB_RES_CODE_LANE_OFFSET_TX 0x163C +#define USB3_DP_QSERDES_TXB_RES_CODE_LANE_OFFSET_RX 0x1640 +#define USB3_DP_QSERDES_TXB_PERL_LENGTH1 0x1644 +#define USB3_DP_QSERDES_TXB_PERL_LENGTH2 0x1648 +#define USB3_DP_QSERDES_TXB_SERDES_BYP_EN_OUT 0x164C +#define USB3_DP_QSERDES_TXB_DEBUG_BUS_SEL 0x1650 +#define USB3_DP_QSERDES_TXB_TRANSCEIVER_BIAS_EN 0x1654 +#define USB3_DP_QSERDES_TXB_HIGHZ_DRVR_EN 0x1658 +#define USB3_DP_QSERDES_TXB_TX_POL_INV 0x165C +#define USB3_DP_QSERDES_TXB_PARRATE_REC_DETECT_IDLE_EN 0x1660 +#define USB3_DP_QSERDES_TXB_BIST_PATTERN1 0x1664 +#define USB3_DP_QSERDES_TXB_BIST_PATTERN2 0x1668 +#define USB3_DP_QSERDES_TXB_BIST_PATTERN3 0x166C +#define USB3_DP_QSERDES_TXB_BIST_PATTERN4 0x1670 +#define USB3_DP_QSERDES_TXB_BIST_PATTERN5 0x1674 +#define USB3_DP_QSERDES_TXB_BIST_PATTERN6 0x1678 +#define USB3_DP_QSERDES_TXB_BIST_PATTERN7 0x167C +#define USB3_DP_QSERDES_TXB_BIST_PATTERN8 0x1680 +#define USB3_DP_QSERDES_TXB_LANE_MODE_1 0x1684 +#define USB3_DP_QSERDES_TXB_LANE_MODE_2 0x1688 +#define USB3_DP_QSERDES_TXB_LANE_MODE_3 0x168C +#define USB3_DP_QSERDES_TXB_ATB_SEL1 0x1690 +#define USB3_DP_QSERDES_TXB_ATB_SEL2 0x1694 +#define USB3_DP_QSERDES_TXB_RCV_DETECT_LVL 0x1698 +#define USB3_DP_QSERDES_TXB_RCV_DETECT_LVL_2 0x169C +#define USB3_DP_QSERDES_TXB_PRBS_SEED1 0x16A0 +#define USB3_DP_QSERDES_TXB_PRBS_SEED2 0x16A4 +#define USB3_DP_QSERDES_TXB_PRBS_SEED3 0x16A8 +#define USB3_DP_QSERDES_TXB_PRBS_SEED4 0x16AC +#define USB3_DP_QSERDES_TXB_RESET_GEN 0x16B0 +#define USB3_DP_QSERDES_TXB_RESET_GEN_MUXES 0x16B4 +#define USB3_DP_QSERDES_TXB_TRAN_DRVR_EMP_EN 0x16B8 +#define USB3_DP_QSERDES_TXB_TX_INTERFACE_MODE 0x16BC +#define USB3_DP_QSERDES_TXB_PWM_CTRL 0x16C0 +#define USB3_DP_QSERDES_TXB_PWM_ENCODED_OR_DATA 0x16C4 +#define USB3_DP_QSERDES_TXB_PWM_GEAR_1_DIVIDER_BAND2 0x16C8 +#define USB3_DP_QSERDES_TXB_PWM_GEAR_2_DIVIDER_BAND2 0x16CC +#define USB3_DP_QSERDES_TXB_PWM_GEAR_3_DIVIDER_BAND2 0x16D0 +#define USB3_DP_QSERDES_TXB_PWM_GEAR_4_DIVIDER_BAND2 0x16D4 +#define USB3_DP_QSERDES_TXB_PWM_GEAR_1_DIVIDER_BAND0_1 0x16D8 +#define USB3_DP_QSERDES_TXB_PWM_GEAR_2_DIVIDER_BAND0_1 0x16DC +#define USB3_DP_QSERDES_TXB_PWM_GEAR_3_DIVIDER_BAND0_1 0x16E0 +#define USB3_DP_QSERDES_TXB_PWM_GEAR_4_DIVIDER_BAND0_1 0x16E4 +#define USB3_DP_QSERDES_TXB_VMODE_CTRL1 0x16E8 +#define USB3_DP_QSERDES_TXB_ALOG_OBSV_BUS_CTRL_1 0x16EC +#define USB3_DP_QSERDES_TXB_BIST_STATUS 0x16F0 +#define USB3_DP_QSERDES_TXB_BIST_ERROR_COUNT1 0x16F4 +#define USB3_DP_QSERDES_TXB_BIST_ERROR_COUNT2 0x16F8 +#define USB3_DP_QSERDES_TXB_ALOG_OBSV_BUS_STATUS_1 0x16FC +#define USB3_DP_QSERDES_TXB_LANE_DIG_CONFIG 0x1700 +#define USB3_DP_QSERDES_TXB_PI_QEC_CTRL 0x1704 +#define USB3_DP_QSERDES_TXB_PRE_EMPH 0x1708 +#define USB3_DP_QSERDES_TXB_SW_RESET 0x170C +#define USB3_DP_QSERDES_TXB_DCC_OFFSET 0x1710 +#define USB3_DP_QSERDES_TXB_DIG_BKUP_CTRL 0x1714 +#define USB3_DP_QSERDES_TXB_DEBUG_BUS0 0x1718 +#define USB3_DP_QSERDES_TXB_DEBUG_BUS1 0x171C +#define USB3_DP_QSERDES_TXB_DEBUG_BUS2 0x1720 +#define USB3_DP_QSERDES_TXB_DEBUG_BUS3 0x1724 +#define USB3_DP_QSERDES_TXB_READ_EQCODE 0x1728 +#define USB3_DP_QSERDES_TXB_READ_OFFSETCODE 0x172C +#define USB3_DP_QSERDES_TXB_IA_ERROR_COUNTER_LOW 0x1730 +#define USB3_DP_QSERDES_TXB_IA_ERROR_COUNTER_HIGH 0x1734 +#define USB3_DP_QSERDES_TXB_VGA_READ_CODE 0x1738 +#define USB3_DP_QSERDES_TXB_VTH_READ_CODE 0x173C +#define USB3_DP_QSERDES_TXB_DFE_TAP1_READ_CODE 0x1740 +#define USB3_DP_QSERDES_TXB_DFE_TAP2_READ_CODE 0x1744 +#define USB3_DP_QSERDES_TXB_IDAC_STATUS_I 0x1748 +#define USB3_DP_QSERDES_TXB_IDAC_STATUS_IBAR 0x174C +#define USB3_DP_QSERDES_TXB_IDAC_STATUS_Q 0x1750 +#define USB3_DP_QSERDES_TXB_IDAC_STATUS_QBAR 0x1754 +#define USB3_DP_QSERDES_TXB_IDAC_STATUS_A 0x1758 +#define USB3_DP_QSERDES_TXB_IDAC_STATUS_ABAR 0x175C +#define USB3_DP_QSERDES_TXB_IDAC_STATUS_SM_ON 0x1760 +#define USB3_DP_QSERDES_TXB_IDAC_STATUS_CAL_DONE 0x1764 +#define USB3_DP_QSERDES_TXB_IDAC_STATUS_SIGNERROR 0x1768 +#define USB3_DP_QSERDES_TXB_DCC_CAL_STATUS 0x176C + +/* Module: USB3_DP_PHY_USB3_QSERDES_RXB_USB3_QSERDES_RXB_USB3_DP_QMP_RX */ +#define USB3_DP_QSERDES_RXB_UCDR_FO_GAIN_HALF 0x1800 +#define USB3_DP_QSERDES_RXB_UCDR_FO_GAIN_QUARTER 0x1804 +#define USB3_DP_QSERDES_RXB_UCDR_FO_GAIN 0x1808 +#define USB3_DP_QSERDES_RXB_UCDR_SO_GAIN_HALF 0x180C +#define USB3_DP_QSERDES_RXB_UCDR_SO_GAIN_QUARTER 0x1810 +#define USB3_DP_QSERDES_RXB_UCDR_SO_GAIN 0x1814 +#define USB3_DP_QSERDES_RXB_UCDR_SVS_FO_GAIN_HALF 0x1818 +#define USB3_DP_QSERDES_RXB_UCDR_SVS_FO_GAIN_QUARTER 0x181C +#define USB3_DP_QSERDES_RXB_UCDR_SVS_FO_GAIN 0x1820 +#define USB3_DP_QSERDES_RXB_UCDR_SVS_SO_GAIN_HALF 0x1824 +#define USB3_DP_QSERDES_RXB_UCDR_SVS_SO_GAIN_QUARTER 0x1828 +#define USB3_DP_QSERDES_RXB_UCDR_SVS_SO_GAIN 0x182C +#define USB3_DP_QSERDES_RXB_UCDR_FASTLOCK_FO_GAIN 0x1830 +#define USB3_DP_QSERDES_RXB_UCDR_SO_SATURATION_AND_ENABLE 0x1834 +#define USB3_DP_QSERDES_RXB_UCDR_FO_TO_SO_DELAY 0x1838 +#define USB3_DP_QSERDES_RXB_UCDR_FASTLOCK_COUNT_LOW 0x183C +#define USB3_DP_QSERDES_RXB_UCDR_FASTLOCK_COUNT_HIGH 0x1840 +#define USB3_DP_QSERDES_RXB_UCDR_PI_CONTROLS 0x1844 +#define USB3_DP_QSERDES_RXB_UCDR_PI_CTRL2 0x1848 +#define USB3_DP_QSERDES_RXB_UCDR_SB2_THRESH1 0x184C +#define USB3_DP_QSERDES_RXB_UCDR_SB2_THRESH2 0x1850 +#define USB3_DP_QSERDES_RXB_UCDR_SB2_GAIN1 0x1854 +#define USB3_DP_QSERDES_RXB_UCDR_SB2_GAIN2 0x1858 +#define USB3_DP_QSERDES_RXB_AUX_CONTROL 0x185C +#define USB3_DP_QSERDES_RXB_AUX_DATA_TCOARSE_TFINE 0x1860 +#define USB3_DP_QSERDES_RXB_RCLK_AUXDATA_SEL 0x1864 +#define USB3_DP_QSERDES_RXB_AC_JTAG_ENABLE 0x1868 +#define USB3_DP_QSERDES_RXB_AC_JTAG_INITP 0x186C +#define USB3_DP_QSERDES_RXB_AC_JTAG_INITN 0x1870 +#define USB3_DP_QSERDES_RXB_AC_JTAG_LVL 0x1874 +#define USB3_DP_QSERDES_RXB_AC_JTAG_MODE 0x1878 +#define USB3_DP_QSERDES_RXB_AC_JTAG_RESET 0x187C +#define USB3_DP_QSERDES_RXB_RX_TERM_BW 0x1880 +#define USB3_DP_QSERDES_RXB_RX_RCVR_IQ_EN 0x1884 +#define USB3_DP_QSERDES_RXB_RX_IDAC_I_DC_OFFSETS 0x1888 +#define USB3_DP_QSERDES_RXB_RX_IDAC_IBAR_DC_OFFSETS 0x188C +#define USB3_DP_QSERDES_RXB_RX_IDAC_Q_DC_OFFSETS 0x1890 +#define USB3_DP_QSERDES_RXB_RX_IDAC_QBAR_DC_OFFSETS 0x1894 +#define USB3_DP_QSERDES_RXB_RX_IDAC_A_DC_OFFSETS 0x1898 +#define USB3_DP_QSERDES_RXB_RX_IDAC_ABAR_DC_OFFSETS 0x189C +#define USB3_DP_QSERDES_RXB_RX_IDAC_EN 0x18A0 +#define USB3_DP_QSERDES_RXB_RX_IDAC_ENABLES 0x18A4 +#define USB3_DP_QSERDES_RXB_RX_IDAC_SIGN 0x18A8 +#define USB3_DP_QSERDES_RXB_RX_HIGHZ_HIGHRATE 0x18AC +#define USB3_DP_QSERDES_RXB_RX_TERM_AC_BYPASS_DC_COUPLE_OFFSET 0x18B0 +#define USB3_DP_QSERDES_RXB_DFE_1 0x18B4 +#define USB3_DP_QSERDES_RXB_DFE_2 0x18B8 +#define USB3_DP_QSERDES_RXB_DFE_3 0x18BC +#define USB3_DP_QSERDES_RXB_DFE_4 0x18C0 +#define USB3_DP_QSERDES_RXB_TX_ADAPT_PRE_THRESH1 0x18C4 +#define USB3_DP_QSERDES_RXB_TX_ADAPT_PRE_THRESH2 0x18C8 +#define USB3_DP_QSERDES_RXB_TX_ADAPT_POST_THRESH 0x18CC +#define USB3_DP_QSERDES_RXB_TX_ADAPT_MAIN_THRESH 0x18D0 +#define USB3_DP_QSERDES_RXB_VGA_CAL_CNTRL1 0x18D4 +#define USB3_DP_QSERDES_RXB_VGA_CAL_CNTRL2 0x18D8 +#define USB3_DP_QSERDES_RXB_GM_CAL 0x18DC +#define USB3_DP_QSERDES_RXB_RX_VGA_GAIN2_LSB 0x18E0 +#define USB3_DP_QSERDES_RXB_RX_VGA_GAIN2_MSB 0x18E4 +#define USB3_DP_QSERDES_RXB_RX_EQU_ADAPTOR_CNTRL1 0x18E8 +#define USB3_DP_QSERDES_RXB_RX_EQU_ADAPTOR_CNTRL2 0x18EC +#define USB3_DP_QSERDES_RXB_RX_EQU_ADAPTOR_CNTRL3 0x18F0 +#define USB3_DP_QSERDES_RXB_RX_EQU_ADAPTOR_CNTRL4 0x18F4 +#define USB3_DP_QSERDES_RXB_RX_IDAC_TSETTLE_LOW 0x18F8 +#define USB3_DP_QSERDES_RXB_RX_IDAC_TSETTLE_HIGH 0x18FC +#define USB3_DP_QSERDES_RXB_RX_IDAC_MEASURE_TIME 0x1900 +#define USB3_DP_QSERDES_RXB_RX_IDAC_ACCUMULATOR 0x1904 +#define USB3_DP_QSERDES_RXB_RX_EQ_OFFSET_LSB 0x1908 +#define USB3_DP_QSERDES_RXB_RX_EQ_OFFSET_MSB 0x190C +#define USB3_DP_QSERDES_RXB_RX_EQ_OFFSET_ADAPTOR_CNTRL1 0x1910 +#define USB3_DP_QSERDES_RXB_RX_OFFSET_ADAPTOR_CNTRL2 0x1914 +#define USB3_DP_QSERDES_RXB_SIGDET_ENABLES 0x1918 +#define USB3_DP_QSERDES_RXB_SIGDET_CNTRL 0x191C +#define USB3_DP_QSERDES_RXB_SIGDET_LVL 0x1920 +#define USB3_DP_QSERDES_RXB_SIGDET_DEGLITCH_CNTRL 0x1924 +#define USB3_DP_QSERDES_RXB_RX_BAND 0x1928 +#define USB3_DP_QSERDES_RXB_CDR_FREEZE_UP_DN 0x192C +#define USB3_DP_QSERDES_RXB_CDR_RESET_OVERRIDE 0x1930 +#define USB3_DP_QSERDES_RXB_RX_INTERFACE_MODE 0x1934 +#define USB3_DP_QSERDES_RXB_JITTER_GEN_MODE 0x1938 +#define USB3_DP_QSERDES_RXB_SJ_AMP1 0x193C +#define USB3_DP_QSERDES_RXB_SJ_AMP2 0x1940 +#define USB3_DP_QSERDES_RXB_SJ_PER1 0x1944 +#define USB3_DP_QSERDES_RXB_SJ_PER2 0x1948 +#define USB3_DP_QSERDES_RXB_PPM_OFFSET1 0x194C +#define USB3_DP_QSERDES_RXB_PPM_OFFSET2 0x1950 +#define USB3_DP_QSERDES_RXB_SIGN_PPM_PERIOD1 0x1954 +#define USB3_DP_QSERDES_RXB_SIGN_PPM_PERIOD2 0x1958 +#define USB3_DP_QSERDES_RXB_RX_PWM_ENABLE_AND_DATA 0x195C +#define USB3_DP_QSERDES_RXB_RX_PWM_GEAR1_TIMEOUT_COUNT 0x1960 +#define USB3_DP_QSERDES_RXB_RX_PWM_GEAR2_TIMEOUT_COUNT 0x1964 +#define USB3_DP_QSERDES_RXB_RX_PWM_GEAR3_TIMEOUT_COUNT 0x1968 +#define USB3_DP_QSERDES_RXB_RX_PWM_GEAR4_TIMEOUT_COUNT 0x196C +#define USB3_DP_QSERDES_RXB_RX_MODE_00_LOW 0x1970 +#define USB3_DP_QSERDES_RXB_RX_MODE_00_HIGH 0x1974 +#define USB3_DP_QSERDES_RXB_RX_MODE_00_HIGH2 0x1978 +#define USB3_DP_QSERDES_RXB_RX_MODE_00_HIGH3 0x197C +#define USB3_DP_QSERDES_RXB_RX_MODE_00_HIGH4 0x1980 +#define USB3_DP_QSERDES_RXB_RX_MODE_01_LOW 0x1984 +#define USB3_DP_QSERDES_RXB_RX_MODE_01_HIGH 0x1988 +#define USB3_DP_QSERDES_RXB_RX_MODE_01_HIGH2 0x198C +#define USB3_DP_QSERDES_RXB_RX_MODE_01_HIGH3 0x1990 +#define USB3_DP_QSERDES_RXB_RX_MODE_01_HIGH4 0x1994 +#define USB3_DP_QSERDES_RXB_RX_MODE_10_LOW 0x1998 +#define USB3_DP_QSERDES_RXB_RX_MODE_10_HIGH 0x199C +#define USB3_DP_QSERDES_RXB_RX_MODE_10_HIGH2 0x19A0 +#define USB3_DP_QSERDES_RXB_RX_MODE_10_HIGH3 0x19A4 +#define USB3_DP_QSERDES_RXB_RX_MODE_10_HIGH4 0x19A8 +#define USB3_DP_QSERDES_RXB_PHPRE_CTRL 0x19AC +#define USB3_DP_QSERDES_RXB_PHPRE_INITVAL 0x19B0 +#define USB3_DP_QSERDES_RXB_DFE_EN_TIMER 0x19B4 +#define USB3_DP_QSERDES_RXB_DFE_CTLE_POST_CAL_OFFSET 0x19B8 +#define USB3_DP_QSERDES_RXB_DCC_CTRL1 0x19BC +#define USB3_DP_QSERDES_RXB_DCC_CTRL2 0x19C0 +#define USB3_DP_QSERDES_RXB_VTH_CODE 0x19C4 +#define USB3_DP_QSERDES_RXB_VTH_MIN_THRESH 0x19C8 +#define USB3_DP_QSERDES_RXB_VTH_MAX_THRESH 0x19CC +#define USB3_DP_QSERDES_RXB_ALOG_OBSV_BUS_CTRL_1 0x19D0 +#define USB3_DP_QSERDES_RXB_PI_CTRL1 0x19D4 +#define USB3_DP_QSERDES_RXB_PI_CTRL2 0x19D8 +#define USB3_DP_QSERDES_RXB_PI_QUAD 0x19DC +#define USB3_DP_QSERDES_RXB_IDATA1 0x19E0 +#define USB3_DP_QSERDES_RXB_IDATA2 0x19E4 +#define USB3_DP_QSERDES_RXB_AUX_DATA1 0x19E8 +#define USB3_DP_QSERDES_RXB_AUX_DATA2 0x19EC +#define USB3_DP_QSERDES_RXB_AC_JTAG_OUTP 0x19F0 +#define USB3_DP_QSERDES_RXB_AC_JTAG_OUTN 0x19F4 +#define USB3_DP_QSERDES_RXB_RX_SIGDET 0x19F8 +#define USB3_DP_QSERDES_RXB_ALOG_OBSV_BUS_STATUS_1 0x19FC + +/* Module: USB3_DP_PHY_USB3_PCS_MISC_USB3_PCS_MISC_USB3_PCS_MISC */ +#define USB3_DP_PCS_MISC_TYPEC_CTRL 0x1A00 +#define USB3_DP_PCS_MISC_TYPEC_PWRDN_CTRL 0x1A04 +#define USB3_DP_PCS_MISC_PCS_MISC_CONFIG1 0x1A08 +#define USB3_DP_PCS_MISC_CLAMP_ENABLE 0x1A0C +#define USB3_DP_PCS_MISC_TYPEC_STATUS 0x1A10 +#define USB3_DP_PCS_MISC_PLACEHOLDER_STATUS 0x1A14 + +/* Module: USB3_DP_PHY_USB3_PCS_LN_USB3_PCS_LN_USB3_PCS_LANE */ +#define USB3_DP_PCS_LN_PCS_STATUS1 0x1B00 +#define USB3_DP_PCS_LN_PCS_STATUS2 0x1B04 +#define USB3_DP_PCS_LN_PCS_STATUS2_CLEAR 0x1B08 +#define USB3_DP_PCS_LN_PCS_STATUS3 0x1B0C +#define USB3_DP_PCS_LN_BIST_CHK_ERR_CNT_L_STATUS 0x1B10 +#define USB3_DP_PCS_LN_BIST_CHK_ERR_CNT_H_STATUS 0x1B14 +#define USB3_DP_PCS_LN_BIST_CHK_STATUS 0x1B18 +#define USB3_DP_PCS_LN_INSIG_SW_CTRL1 0x1B1C +#define USB3_DP_PCS_LN_INSIG_MX_CTRL1 0x1B20 +#define USB3_DP_PCS_LN_OUTSIG_SW_CTRL1 0x1B24 +#define USB3_DP_PCS_LN_OUTSIG_MX_CTRL1 0x1B28 +#define USB3_DP_PCS_LN_TEST_CONTROL 0x1B2C +#define USB3_DP_PCS_LN_BIST_CTRL 0x1B30 +#define USB3_DP_PCS_LN_PRBS_SEED0 0x1B34 +#define USB3_DP_PCS_LN_PRBS_SEED1 0x1B38 +#define USB3_DP_PCS_LN_FIXED_PAT_CTRL 0x1B3C +#define USB3_DP_PCS_LN_EQ_CONFIG 0x1B40 + +/* Module: USB3_DP_PHY_USB3_PCS_USB3_PCS_USB3_PCS */ +#define USB3_DP_PCS_SW_RESET 0x1C00 +#define USB3_DP_PCS_REVISION_ID0 0x1C04 +#define USB3_DP_PCS_REVISION_ID1 0x1C08 +#define USB3_DP_PCS_REVISION_ID2 0x1C0C +#define USB3_DP_PCS_REVISION_ID3 0x1C10 +#define USB3_DP_PCS_PCS_STATUS1 0x1C14 +#define USB3_DP_PCS_PCS_STATUS2 0x1C18 +#define USB3_DP_PCS_PCS_STATUS3 0x1C1C +#define USB3_DP_PCS_PCS_STATUS4 0x1C20 +#define USB3_DP_PCS_PCS_STATUS5 0x1C24 +#define USB3_DP_PCS_PCS_STATUS6 0x1C28 +#define USB3_DP_PCS_PCS_STATUS7 0x1C2C +#define USB3_DP_PCS_DEBUG_BUS_0_STATUS 0x1C30 +#define USB3_DP_PCS_DEBUG_BUS_1_STATUS 0x1C34 +#define USB3_DP_PCS_DEBUG_BUS_2_STATUS 0x1C38 +#define USB3_DP_PCS_DEBUG_BUS_3_STATUS 0x1C3C +#define USB3_DP_PCS_POWER_DOWN_CONTROL 0x1C40 +#define USB3_DP_PCS_START_CONTROL 0x1C44 +#define USB3_DP_PCS_INSIG_SW_CTRL1 0x1C48 +#define USB3_DP_PCS_INSIG_SW_CTRL2 0x1C4C +#define USB3_DP_PCS_INSIG_SW_CTRL3 0x1C50 +#define USB3_DP_PCS_INSIG_SW_CTRL4 0x1C54 +#define USB3_DP_PCS_INSIG_SW_CTRL5 0x1C58 +#define USB3_DP_PCS_INSIG_SW_CTRL6 0x1C5C +#define USB3_DP_PCS_INSIG_SW_CTRL7 0x1C60 +#define USB3_DP_PCS_INSIG_SW_CTRL8 0x1C64 +#define USB3_DP_PCS_INSIG_MX_CTRL1 0x1C68 +#define USB3_DP_PCS_INSIG_MX_CTRL2 0x1C6C +#define USB3_DP_PCS_INSIG_MX_CTRL3 0x1C70 +#define USB3_DP_PCS_INSIG_MX_CTRL4 0x1C74 +#define USB3_DP_PCS_INSIG_MX_CTRL5 0x1C78 +#define USB3_DP_PCS_INSIG_MX_CTRL7 0x1C7C +#define USB3_DP_PCS_INSIG_MX_CTRL8 0x1C80 +#define USB3_DP_PCS_OUTSIG_SW_CTRL1 0x1C84 +#define USB3_DP_PCS_OUTSIG_MX_CTRL1 0x1C88 +#define USB3_DP_PCS_CLAMP_ENABLE 0x1C8C +#define USB3_DP_PCS_POWER_STATE_CONFIG1 0x1C90 +#define USB3_DP_PCS_POWER_STATE_CONFIG2 0x1C94 +#define USB3_DP_PCS_FLL_CNTRL1 0x1C98 +#define USB3_DP_PCS_FLL_CNTRL2 0x1C9C +#define USB3_DP_PCS_FLL_CNT_VAL_L 0x1CA0 +#define USB3_DP_PCS_FLL_CNT_VAL_H_TOL 0x1CA4 +#define USB3_DP_PCS_FLL_MAN_CODE 0x1CA8 +#define USB3_DP_PCS_TEST_CONTROL1 0x1CAC +#define USB3_DP_PCS_TEST_CONTROL2 0x1CB0 +#define USB3_DP_PCS_TEST_CONTROL3 0x1CB4 +#define USB3_DP_PCS_TEST_CONTROL4 0x1CB8 +#define USB3_DP_PCS_TEST_CONTROL5 0x1CBC +#define USB3_DP_PCS_TEST_CONTROL6 0x1CC0 +#define USB3_DP_PCS_LOCK_DETECT_CONFIG1 0x1CC4 +#define USB3_DP_PCS_LOCK_DETECT_CONFIG2 0x1CC8 +#define USB3_DP_PCS_LOCK_DETECT_CONFIG3 0x1CCC +#define USB3_DP_PCS_LOCK_DETECT_CONFIG4 0x1CD0 +#define USB3_DP_PCS_LOCK_DETECT_CONFIG5 0x1CD4 +#define USB3_DP_PCS_LOCK_DETECT_CONFIG6 0x1CD8 +#define USB3_DP_PCS_REFGEN_REQ_CONFIG1 0x1CDC +#define USB3_DP_PCS_REFGEN_REQ_CONFIG2 0x1CE0 +#define USB3_DP_PCS_REFGEN_REQ_CONFIG3 0x1CE4 +#define USB3_DP_PCS_BIST_CTRL 0x1CE8 +#define USB3_DP_PCS_PRBS_POLY0 0x1CEC +#define USB3_DP_PCS_PRBS_POLY1 0x1CF0 +#define USB3_DP_PCS_FIXED_PAT0 0x1CF4 +#define USB3_DP_PCS_FIXED_PAT1 0x1CF8 +#define USB3_DP_PCS_FIXED_PAT2 0x1CFC +#define USB3_DP_PCS_FIXED_PAT3 0x1D00 +#define USB3_DP_PCS_FIXED_PAT4 0x1D04 +#define USB3_DP_PCS_FIXED_PAT5 0x1D08 +#define USB3_DP_PCS_FIXED_PAT6 0x1D0C +#define USB3_DP_PCS_FIXED_PAT7 0x1D10 +#define USB3_DP_PCS_FIXED_PAT8 0x1D14 +#define USB3_DP_PCS_FIXED_PAT9 0x1D18 +#define USB3_DP_PCS_FIXED_PAT10 0x1D1C +#define USB3_DP_PCS_FIXED_PAT11 0x1D20 +#define USB3_DP_PCS_FIXED_PAT12 0x1D24 +#define USB3_DP_PCS_FIXED_PAT13 0x1D28 +#define USB3_DP_PCS_FIXED_PAT14 0x1D2C +#define USB3_DP_PCS_FIXED_PAT15 0x1D30 +#define USB3_DP_PCS_TXMGN_CONFIG 0x1D34 +#define USB3_DP_PCS_G12S1_TXMGN_V0 0x1D38 +#define USB3_DP_PCS_G12S1_TXMGN_V1 0x1D3C +#define USB3_DP_PCS_G12S1_TXMGN_V2 0x1D40 +#define USB3_DP_PCS_G12S1_TXMGN_V3 0x1D44 +#define USB3_DP_PCS_G12S1_TXMGN_V4 0x1D48 +#define USB3_DP_PCS_G12S1_TXMGN_V0_RS 0x1D4C +#define USB3_DP_PCS_G12S1_TXMGN_V1_RS 0x1D50 +#define USB3_DP_PCS_G12S1_TXMGN_V2_RS 0x1D54 +#define USB3_DP_PCS_G12S1_TXMGN_V3_RS 0x1D58 +#define USB3_DP_PCS_G12S1_TXMGN_V4_RS 0x1D5C +#define USB3_DP_PCS_G3S2_TXMGN_MAIN 0x1D60 +#define USB3_DP_PCS_G3S2_TXMGN_MAIN_RS 0x1D64 +#define USB3_DP_PCS_G12S1_TXDEEMPH_M6DB 0x1D68 +#define USB3_DP_PCS_G12S1_TXDEEMPH_M3P5DB 0x1D6C +#define USB3_DP_PCS_G3S2_PRE_GAIN 0x1D70 +#define USB3_DP_PCS_G3S2_POST_GAIN 0x1D74 +#define USB3_DP_PCS_G3S2_PRE_POST_OFFSET 0x1D78 +#define USB3_DP_PCS_G3S2_PRE_GAIN_RS 0x1D7C +#define USB3_DP_PCS_G3S2_POST_GAIN_RS 0x1D80 +#define USB3_DP_PCS_G3S2_PRE_POST_OFFSET_RS 0x1D84 +#define USB3_DP_PCS_RX_SIGDET_LVL 0x1D88 +#define USB3_DP_PCS_RX_SIGDET_DTCT_CNTRL 0x1D8C +#define USB3_DP_PCS_RCVR_DTCT_DLY_P1U2_L 0x1D90 +#define USB3_DP_PCS_RCVR_DTCT_DLY_P1U2_H 0x1D94 +#define USB3_DP_PCS_RATE_SLEW_CNTRL1 0x1D98 +#define USB3_DP_PCS_RATE_SLEW_CNTRL2 0x1D9C +#define USB3_DP_PCS_PWRUP_RESET_DLY_TIME_AUXCLK 0x1DA0 +#define USB3_DP_PCS_P2U3_WAKEUP_DLY_TIME_AUXCLK_L 0x1DA4 +#define USB3_DP_PCS_P2U3_WAKEUP_DLY_TIME_AUXCLK_H 0x1DA8 +#define USB3_DP_PCS_TSYNC_RSYNC_TIME 0x1DAC +#define USB3_DP_PCS_CDR_RESET_TIME 0x1DB0 +#define USB3_DP_PCS_TSYNC_DLY_TIME 0x1DB4 +#define USB3_DP_PCS_ELECIDLE_DLY_SEL 0x1DB8 +#define USB3_DP_PCS_CMN_ACK_OUT_SEL 0x1DBC +#define USB3_DP_PCS_ALIGN_DETECT_CONFIG1 0x1DC0 +#define USB3_DP_PCS_ALIGN_DETECT_CONFIG2 0x1DC4 +#define USB3_DP_PCS_ALIGN_DETECT_CONFIG3 0x1DC8 +#define USB3_DP_PCS_ALIGN_DETECT_CONFIG4 0x1DCC +#define USB3_DP_PCS_PCS_TX_RX_CONFIG 0x1DD0 +#define USB3_DP_PCS_RX_IDLE_DTCT_CNTRL 0x1DD4 +#define USB3_DP_PCS_RX_DCC_CAL_CONFIG 0x1DD8 +#define USB3_DP_PCS_EQ_CONFIG1 0x1DDC +#define USB3_DP_PCS_EQ_CONFIG2 0x1DE0 +#define USB3_DP_PCS_EQ_CONFIG3 0x1DE4 +#define USB3_DP_PCS_EQ_CONFIG4 0x1DE8 +#define USB3_DP_PCS_EQ_CONFIG5 0x1DEC +#define USB3PHY_PCS_REFGEN_REQ_CONFIG1 0x1E0C +#define USB3PHY_PCS_REFGEN_REQ_CONFIG2 0x1E10 + +/* Module: USB3_DP_PHY_USB3_PCS_USB3_USB3_PCS_USB3_USB3_PCS_USB3 */ +#define USB3_DP_PCS_USB3_POWER_STATE_CONFIG1 0x1F00 +#define USB3_DP_PCS_USB3_AUTONOMOUS_MODE_STATUS 0x1F04 +#define USB3_DP_PCS_USB3_AUTONOMOUS_MODE_CTRL 0x1F08 +#define USB3_DP_PCS_USB3_AUTONOMOUS_MODE_CTRL2 0x1F0C +#define USB3_DP_PCS_USB3_LFPS_RXTERM_IRQ_SOURCE_STATUS 0x1F10 +#define USB3_DP_PCS_USB3_LFPS_RXTERM_IRQ_CLEAR 0x1F14 +#define USB3_DP_PCS_USB3_LFPS_DET_HIGH_COUNT_VAL 0x1F18 +#define USB3_DP_PCS_USB3_LFPS_TX_ECSTART 0x1F1C +#define USB3_DP_PCS_USB3_LFPS_PER_TIMER_VAL 0x1F20 +#define USB3_DP_PCS_USB3_LFPS_TX_END_CNT_U3_START 0x1F24 +#define USB3_DP_PCS_USB3_RXEQTRAINING_LOCK_TIME 0x1F28 +#define USB3_DP_PCS_USB3_RXEQTRAINING_WAIT_TIME 0x1F2C +#define USB3_DP_PCS_USB3_RXEQTRAINING_CTLE_TIME 0x1F30 +#define USB3_DP_PCS_USB3_RXEQTRAINING_WAIT_TIME_S2 0x1F34 +#define USB3_DP_PCS_USB3_RXEQTRAINING_DFE_TIME_S2 0x1F38 +#define USB3_DP_PCS_USB3_RCVR_DTCT_DLY_U3_L 0x1F3C +#define USB3_DP_PCS_USB3_RCVR_DTCT_DLY_U3_H 0x1F40 +#define USB3_DP_PCS_USB3_ARCVR_DTCT_EN_PERIOD 0x1F44 +#define USB3_DP_PCS_USB3_ARCVR_DTCT_CM_DLY 0x1F48 +#define USB3_DP_PCS_USB3_TXONESZEROS_RUN_LENGTH 0x1F4C +#define USB3_DP_PCS_USB3_ALFPS_DEGLITCH_VAL 0x1F50 +#define USB3_DP_PCS_USB3_SIGDET_STARTUP_TIMER_VAL 0x1F54 +#define USB3_DP_PCS_USB3_TEST_CONTROL 0x1F58 +#define USB3_DP_PCS_RXTERMINATION_DLY_SEL 0x1F5C + +#endif /* _DT_BINDINGS_PHY_QCOM_KHAJE_QMP_USB_H */ diff --git a/include/dt-bindings/regulator/qcom,rpmh-regulator-levels.h b/include/dt-bindings/regulator/qcom,rpmh-regulator-levels.h index 326fbfdad875..73c0340c19d1 100644 --- a/include/dt-bindings/regulator/qcom,rpmh-regulator-levels.h +++ b/include/dt-bindings/regulator/qcom,rpmh-regulator-levels.h @@ -1,13 +1,14 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* * Copyright (c) 2018-2021, The Linux Foundation. All rights reserved. - * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. + * Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved. */ #ifndef __QCOM_RPMH_REGULATOR_LEVELS_H #define __QCOM_RPMH_REGULATOR_LEVELS_H /* These levels may be used for ARC type RPMh regulators. */ +#define RPMH_REGULATOR_LEVEL_OFF 0 #define RPMH_REGULATOR_LEVEL_RETENTION 16 #define RPMH_REGULATOR_LEVEL_MIN_SVS 48 #define RPMH_REGULATOR_LEVEL_LOW_SVS_D2 52 diff --git a/include/linux/bootmem_info.h b/include/linux/bootmem_info.h index 2bc8b1f69c93..888eb660d3f6 100644 --- a/include/linux/bootmem_info.h +++ b/include/linux/bootmem_info.h @@ -3,6 +3,7 @@ #define __LINUX_BOOTMEM_INFO_H #include +#include /* * Types for free bootmem stored in page->lru.next. These have to be in @@ -59,6 +60,7 @@ static inline void get_page_bootmem(unsigned long info, struct page *page, static inline void free_bootmem_page(struct page *page) { + kmemleak_free_part(page_to_virt(page), PAGE_SIZE); free_reserved_page(page); } #endif diff --git a/include/linux/can/length.h b/include/linux/can/length.h index 6995092b774e..ef1fd32cef16 100644 --- a/include/linux/can/length.h +++ b/include/linux/can/length.h @@ -69,17 +69,18 @@ * Error Status Indicator (ESI) 1 * Data length code (DLC) 4 * Data field 0...512 - * Stuff Bit Count (SBC) 0...16: 4 20...64:5 + * Stuff Bit Count (SBC) 4 * CRC 0...16: 17 20...64:21 * CRC delimiter (CD) 1 + * Fixed Stuff bits (FSB) 0...16: 6 20...64:7 * ACK slot (AS) 1 * ACK delimiter (AD) 1 * End-of-frame (EOF) 7 * Inter frame spacing 3 * - * assuming CRC21, rounded up and ignoring bitstuffing + * assuming CRC21, rounded up and ignoring dynamic bitstuffing */ -#define CANFD_FRAME_OVERHEAD_SFF DIV_ROUND_UP(61, 8) +#define CANFD_FRAME_OVERHEAD_SFF DIV_ROUND_UP(67, 8) /* * Size of a CAN-FD Extended Frame @@ -98,17 +99,18 @@ * Error Status Indicator (ESI) 1 * Data length code (DLC) 4 * Data field 0...512 - * Stuff Bit Count (SBC) 0...16: 4 20...64:5 + * Stuff Bit Count (SBC) 4 * CRC 0...16: 17 20...64:21 * CRC delimiter (CD) 1 + * Fixed Stuff bits (FSB) 0...16: 6 20...64:7 * ACK slot (AS) 1 * ACK delimiter (AD) 1 * End-of-frame (EOF) 7 * Inter frame spacing 3 * - * assuming CRC21, rounded up and ignoring bitstuffing + * assuming CRC21, rounded up and ignoring dynamic bitstuffing */ -#define CANFD_FRAME_OVERHEAD_EFF DIV_ROUND_UP(80, 8) +#define CANFD_FRAME_OVERHEAD_EFF DIV_ROUND_UP(86, 8) /* * Maximum size of a Classical CAN frame diff --git a/include/linux/crypto-qti-common.h b/include/linux/crypto-qti-common.h index 1ba9199e5c70..2d9a671a65dc 100644 --- a/include/linux/crypto-qti-common.h +++ b/include/linux/crypto-qti-common.h @@ -53,9 +53,9 @@ int crypto_qti_debug(const struct ice_mmio_data *mmio_data); int crypto_qti_keyslot_program(const struct ice_mmio_data *mmio_data, const struct blk_crypto_key *key, unsigned int slot, u8 data_unit_mask, - int capid); + int capid, int storage_type); int crypto_qti_keyslot_evict(const struct ice_mmio_data *mmio_data, - unsigned int slot); + unsigned int slot, int storage_type); int crypto_qti_derive_raw_secret(const u8 *wrapped_key, unsigned int wrapped_key_size, u8 *secret, unsigned int secret_size); @@ -128,12 +128,12 @@ static inline int crypto_qti_keyslot_program( const struct blk_crypto_key *key, unsigned int slot, u8 data_unit_mask, - int capid) + int capid, int storage_type) { return -EOPNOTSUPP; } static inline int crypto_qti_keyslot_evict(const struct ice_mmio_data *mmio_data, - unsigned int slot) + unsigned int slot, int storage_type) { return -EOPNOTSUPP; } diff --git a/include/linux/etherdevice.h b/include/linux/etherdevice.h index 7f28fa702bb7..ca0e26a858be 100644 --- a/include/linux/etherdevice.h +++ b/include/linux/etherdevice.h @@ -323,7 +323,7 @@ static inline void eth_hw_addr_inherit(struct net_device *dst, struct net_device *src) { dst->addr_assign_type = src->addr_assign_type; - ether_addr_copy(dst->dev_addr, src->dev_addr); + eth_hw_addr_set(dst, src->dev_addr); } /** diff --git a/include/linux/highmem.h b/include/linux/highmem.h index 371946c070dc..400db9b3552a 100644 --- a/include/linux/highmem.h +++ b/include/linux/highmem.h @@ -247,6 +247,30 @@ static inline void copy_user_highpage(struct page *to, struct page *from, #endif +#ifdef copy_mc_to_kernel +static inline int copy_mc_user_highpage(struct page *to, struct page *from, + unsigned long vaddr, struct vm_area_struct *vma) +{ + unsigned long ret; + char *vfrom, *vto; + + vfrom = kmap_local_page(from); + vto = kmap_local_page(to); + ret = copy_mc_to_kernel(vto, vfrom, PAGE_SIZE); + kunmap_local(vto); + kunmap_local(vfrom); + + return ret; +} +#else +static inline int copy_mc_user_highpage(struct page *to, struct page *from, + unsigned long vaddr, struct vm_area_struct *vma) +{ + copy_user_highpage(to, from, vaddr, vma); + return 0; +} +#endif + #ifndef __HAVE_ARCH_COPY_HIGHPAGE static inline void copy_highpage(struct page *to, struct page *from) diff --git a/include/linux/huge_mm.h b/include/linux/huge_mm.h index f123e15d966e..6cb3e6fe11e7 100644 --- a/include/linux/huge_mm.h +++ b/include/linux/huge_mm.h @@ -36,8 +36,9 @@ int zap_huge_pud(struct mmu_gather *tlb, struct vm_area_struct *vma, pud_t *pud, unsigned long addr); bool move_huge_pmd(struct vm_area_struct *vma, unsigned long old_addr, unsigned long new_addr, pmd_t *old_pmd, pmd_t *new_pmd); -int change_huge_pmd(struct vm_area_struct *vma, pmd_t *pmd, unsigned long addr, - pgprot_t newprot, unsigned long cp_flags); +int change_huge_pmd(struct mmu_gather *tlb, struct vm_area_struct *vma, + pmd_t *pmd, unsigned long addr, pgprot_t newprot, + unsigned long cp_flags); vm_fault_t vmf_insert_pfn_pmd_prot(struct vm_fault *vmf, pfn_t pfn, pgprot_t pgprot, bool write); diff --git a/include/linux/ipv6.h b/include/linux/ipv6.h index ab1fff41ed12..a91305f4289a 100644 --- a/include/linux/ipv6.h +++ b/include/linux/ipv6.h @@ -4,6 +4,7 @@ #include #include +#include #define ipv6_optlen(p) (((p)->hdrlen+1) << 3) #define ipv6_authlen(p) (((p)->hdrlen+2) << 2) @@ -81,6 +82,8 @@ struct ipv6_devconf { __u32 ioam6_id; __u32 ioam6_id_wide; __u8 ioam6_enabled; + /* 1 byte padding, unused */ + /* ANDROID HACK: 2 byte padding used for __u16 accept_ra_min_lft */ struct ctl_table_header *sysctl_header; @@ -90,6 +93,17 @@ struct ipv6_devconf { ANDROID_KABI_RESERVE(4); }; +/* Assert that there is actually padding where accept_ra_min_lft is placed */ +static_assert(offsetof(struct ipv6_devconf, sysctl_header) - + offsetof(struct ipv6_devconf, ioam6_enabled) >= + sizeof(((struct ipv6_devconf *)0)->ioam6_enabled) + 1 + sizeof(__u16)); + +/* The ACCEPT_RA_MIN_LFT macro relies on ioam6_enabled being a u8 */ +static_assert(sizeof(((struct ipv6_devconf *)0)->ioam6_enabled) == 1); + +#define ACCEPT_RA_MIN_LFT(cfg) \ + (*((__u16 *)(&(cfg).ioam6_enabled + 2))) + struct ipv6_params { __s32 disable_ipv6; __s32 autoconf; diff --git a/include/linux/kthread.h b/include/linux/kthread.h index db47aae7c481..a1810374eaa9 100644 --- a/include/linux/kthread.h +++ b/include/linux/kthread.h @@ -33,6 +33,7 @@ struct task_struct *kthread_create_on_cpu(int (*threadfn)(void *data), unsigned int cpu, const char *namefmt); +void get_kthread_comm(char *buf, size_t buf_size, struct task_struct *tsk); void set_kthread_struct(struct task_struct *p); void kthread_set_per_cpu(struct task_struct *k, int cpu); diff --git a/include/linux/mm.h b/include/linux/mm.h index 0ad50ffb8317..1b1493f94883 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h @@ -1958,10 +1958,11 @@ extern unsigned long move_page_tables(struct vm_area_struct *vma, #define MM_CP_UFFD_WP_ALL (MM_CP_UFFD_WP | \ MM_CP_UFFD_WP_RESOLVE) -extern unsigned long change_protection(struct vm_area_struct *vma, unsigned long start, +extern unsigned long change_protection(struct mmu_gather *tlb, + struct vm_area_struct *vma, unsigned long start, unsigned long end, pgprot_t newprot, unsigned long cp_flags); -extern int mprotect_fixup(struct vm_area_struct *vma, +extern int mprotect_fixup(struct mmu_gather *tlb, struct vm_area_struct *vma, struct vm_area_struct **pprev, unsigned long start, unsigned long end, unsigned long newflags); @@ -3193,7 +3194,6 @@ enum mf_flags { MF_SOFT_OFFLINE = 1 << 3, }; extern int memory_failure(unsigned long pfn, int flags); -extern void memory_failure_queue(unsigned long pfn, int flags); extern void memory_failure_queue_kick(int cpu); extern int unpoison_memory(unsigned long pfn); extern int sysctl_memory_failure_early_kill; @@ -3202,8 +3202,12 @@ extern void shake_page(struct page *p); extern atomic_long_t num_poisoned_pages __read_mostly; extern int soft_offline_page(unsigned long pfn, int flags); #ifdef CONFIG_MEMORY_FAILURE +extern void memory_failure_queue(unsigned long pfn, int flags); extern int __get_huge_page_for_hwpoison(unsigned long pfn, int flags); #else +static inline void memory_failure_queue(unsigned long pfn, int flags) +{ +} static inline int __get_huge_page_for_hwpoison(unsigned long pfn, int flags) { return 0; diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index f8593215d256..f68ba57131ee 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -5236,6 +5236,15 @@ static inline bool netif_is_l3_slave(const struct net_device *dev) return dev->priv_flags & IFF_L3MDEV_SLAVE; } +static inline int dev_sdif(const struct net_device *dev) +{ +#ifdef CONFIG_NET_L3_MASTER_DEV + if (netif_is_l3_slave(dev)) + return dev->ifindex; +#endif + return 0; +} + static inline bool netif_is_bridge_master(const struct net_device *dev) { return dev->priv_flags & IFF_EBRIDGE; diff --git a/include/linux/nmi.h b/include/linux/nmi.h index f700ff2df074..0db377ff8f60 100644 --- a/include/linux/nmi.h +++ b/include/linux/nmi.h @@ -197,7 +197,7 @@ u64 hw_nmi_get_sample_period(int watchdog_thresh); #endif #if defined(CONFIG_HARDLOCKUP_CHECK_TIMESTAMP) && \ - defined(CONFIG_HARDLOCKUP_DETECTOR) + defined(CONFIG_HARDLOCKUP_DETECTOR_PERF) void watchdog_update_hrtimer_threshold(u64 period); #else static inline void watchdog_update_hrtimer_threshold(u64 period) { } diff --git a/include/linux/of_net.h b/include/linux/of_net.h index 55460ecfa50a..0484b613ca64 100644 --- a/include/linux/of_net.h +++ b/include/linux/of_net.h @@ -14,6 +14,7 @@ struct net_device; extern int of_get_phy_mode(struct device_node *np, phy_interface_t *interface); extern int of_get_mac_address(struct device_node *np, u8 *mac); +int of_get_ethdev_address(struct device_node *np, struct net_device *dev); extern struct net_device *of_find_net_device_by_node(struct device_node *np); #else static inline int of_get_phy_mode(struct device_node *np, @@ -27,6 +28,11 @@ static inline int of_get_mac_address(struct device_node *np, u8 *mac) return -ENODEV; } +static inline int of_get_ethdev_address(struct device_node *np, struct net_device *dev) +{ + return -ENODEV; +} + static inline struct net_device *of_find_net_device_by_node(struct device_node *np) { return NULL; diff --git a/include/linux/pci.h b/include/linux/pci.h index 672ebb099ae7..c6cc7c20ab80 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -1810,6 +1810,7 @@ static inline struct pci_dev *pci_get_class(unsigned int class, #define pci_dev_put(dev) do { } while (0) static inline void pci_set_master(struct pci_dev *dev) { } +static inline void pci_clear_master(struct pci_dev *dev) { } static inline int pci_enable_device(struct pci_dev *dev) { return -EIO; } static inline void pci_disable_device(struct pci_dev *dev) { } static inline int pcim_enable_device(struct pci_dev *pdev) { return -EIO; } diff --git a/include/linux/pgtable.h b/include/linux/pgtable.h index e6889556e0bf..072b80f02c25 100644 --- a/include/linux/pgtable.h +++ b/include/linux/pgtable.h @@ -575,6 +575,26 @@ extern pmd_t pmdp_invalidate(struct vm_area_struct *vma, unsigned long address, pmd_t *pmdp); #endif +#ifndef __HAVE_ARCH_PMDP_INVALIDATE_AD + +/* + * pmdp_invalidate_ad() invalidates the PMD while changing a transparent + * hugepage mapping in the page tables. This function is similar to + * pmdp_invalidate(), but should only be used if the access and dirty bits would + * not be cleared by the software in the new PMD value. The function ensures + * that hardware changes of the access and dirty bits updates would not be lost. + * + * Doing so can allow in certain architectures to avoid a TLB flush in most + * cases. Yet, another TLB flush might be necessary later if the PMD update + * itself requires such flush (e.g., if protection was set to be stricter). Yet, + * even when a TLB flush is needed because of the update, the caller may be able + * to batch these TLB flushing operations, so fewer TLB flush operations are + * needed. + */ +extern pmd_t pmdp_invalidate_ad(struct vm_area_struct *vma, + unsigned long address, pmd_t *pmdp); +#endif + #ifndef __HAVE_ARCH_PTE_SAME static inline int pte_same(pte_t pte_a, pte_t pte_b) { diff --git a/include/linux/pipe_fs_i.h b/include/linux/pipe_fs_i.h index 79d36a6a17e1..9dff70f4255b 100644 --- a/include/linux/pipe_fs_i.h +++ b/include/linux/pipe_fs_i.h @@ -265,18 +265,14 @@ void generic_pipe_buf_release(struct pipe_inode_info *, struct pipe_buffer *); extern const struct pipe_buf_operations nosteal_pipe_buf_ops; -#ifdef CONFIG_WATCH_QUEUE unsigned long account_pipe_buffers(struct user_struct *user, unsigned long old, unsigned long new); bool too_many_pipe_buffers_soft(unsigned long user_bufs); bool too_many_pipe_buffers_hard(unsigned long user_bufs); bool pipe_is_unprivileged_user(void); -#endif /* for F_SETPIPE_SZ and F_GETPIPE_SZ */ -#ifdef CONFIG_WATCH_QUEUE int pipe_resize_ring(struct pipe_inode_info *pipe, unsigned int nr_slots); -#endif long pipe_fcntl(struct file *, unsigned int, unsigned long arg); struct pipe_inode_info *get_pipe_info(struct file *file, bool for_splice); diff --git a/include/linux/qcom_scm.h b/include/linux/qcom_scm.h index 21e030bda8e9..2a4ef3a5acd7 100644 --- a/include/linux/qcom_scm.h +++ b/include/linux/qcom_scm.h @@ -91,6 +91,7 @@ extern enum qcom_scm_custom_reset_type qcom_scm_custom_reset_type; #define QCOM_SCM_VMID_MSS_MSA 0xF #define QCOM_SCM_VMID_WLAN 0x18 #define QCOM_SCM_VMID_WLAN_CE 0x19 +#define QCOM_SCM_VMID_CP_SPSS_SP 0x1A #define QCOM_SCM_PERM_READ 0x4 #define QCOM_SCM_PERM_WRITE 0x2 #define QCOM_SCM_PERM_EXEC 0x1 diff --git a/include/linux/ramfs.h b/include/linux/ramfs.h index 917528d102c4..d506dc63dd47 100644 --- a/include/linux/ramfs.h +++ b/include/linux/ramfs.h @@ -7,6 +7,7 @@ struct inode *ramfs_get_inode(struct super_block *sb, const struct inode *dir, umode_t mode, dev_t dev); extern int ramfs_init_fs_context(struct fs_context *fc); +extern void ramfs_kill_sb(struct super_block *sb); #ifdef CONFIG_MMU static inline int diff --git a/include/linux/tcp.h b/include/linux/tcp.h index 2caa911f4b54..9483af880689 100644 --- a/include/linux/tcp.h +++ b/include/linux/tcp.h @@ -481,7 +481,7 @@ static inline void fastopen_queue_tune(struct sock *sk, int backlog) struct request_sock_queue *queue = &inet_csk(sk)->icsk_accept_queue; int somaxconn = READ_ONCE(sock_net(sk)->core.sysctl_somaxconn); - queue->fastopenq.max_qlen = min_t(unsigned int, backlog, somaxconn); + WRITE_ONCE(queue->fastopenq.max_qlen, min_t(unsigned int, backlog, somaxconn)); } static inline void tcp_move_syn(struct tcp_sock *tp, diff --git a/include/linux/workqueue.h b/include/linux/workqueue.h index e29212ca60be..d42c3a642f1a 100644 --- a/include/linux/workqueue.h +++ b/include/linux/workqueue.h @@ -69,7 +69,6 @@ enum { WORK_OFFQ_FLAG_BASE = WORK_STRUCT_COLOR_SHIFT, __WORK_OFFQ_CANCELING = WORK_OFFQ_FLAG_BASE, - WORK_OFFQ_CANCELING = (1 << __WORK_OFFQ_CANCELING), /* * When a work item is off queue, its high bits point to the last @@ -80,12 +79,6 @@ enum { WORK_OFFQ_POOL_SHIFT = WORK_OFFQ_FLAG_BASE + WORK_OFFQ_FLAG_BITS, WORK_OFFQ_LEFT = BITS_PER_LONG - WORK_OFFQ_POOL_SHIFT, WORK_OFFQ_POOL_BITS = WORK_OFFQ_LEFT <= 31 ? WORK_OFFQ_LEFT : 31, - WORK_OFFQ_POOL_NONE = (1LU << WORK_OFFQ_POOL_BITS) - 1, - - /* convenience constants */ - WORK_STRUCT_FLAG_MASK = (1UL << WORK_STRUCT_FLAG_BITS) - 1, - WORK_STRUCT_WQ_DATA_MASK = ~WORK_STRUCT_FLAG_MASK, - WORK_STRUCT_NO_POOL = (unsigned long)WORK_OFFQ_POOL_NONE << WORK_OFFQ_POOL_SHIFT, /* bit mask for work_busy() return values */ WORK_BUSY_PENDING = 1 << 0, @@ -95,6 +88,14 @@ enum { WORKER_DESC_LEN = 24, }; +/* Convenience constants - of type 'unsigned long', not 'enum'! */ +#define WORK_OFFQ_CANCELING (1ul << __WORK_OFFQ_CANCELING) +#define WORK_OFFQ_POOL_NONE ((1ul << WORK_OFFQ_POOL_BITS) - 1) +#define WORK_STRUCT_NO_POOL (WORK_OFFQ_POOL_NONE << WORK_OFFQ_POOL_SHIFT) + +#define WORK_STRUCT_FLAG_MASK ((1ul << WORK_STRUCT_FLAG_BITS) - 1) +#define WORK_STRUCT_WQ_DATA_MASK (~WORK_STRUCT_FLAG_MASK) + struct work_struct { atomic_long_t data; struct list_head entry; diff --git a/include/net/netfilter/nf_tables.h b/include/net/netfilter/nf_tables.h index 7da74b9428b9..d486bddda15d 100644 --- a/include/net/netfilter/nf_tables.h +++ b/include/net/netfilter/nf_tables.h @@ -437,7 +437,8 @@ struct nft_set_ops { int (*init)(const struct nft_set *set, const struct nft_set_desc *desc, const struct nlattr * const nla[]); - void (*destroy)(const struct nft_set *set); + void (*destroy)(const struct nft_ctx *ctx, + const struct nft_set *set); void (*gc_init)(const struct nft_set *set); unsigned int elemsize; @@ -772,6 +773,8 @@ int nft_set_elem_expr_clone(const struct nft_ctx *ctx, struct nft_set *set, struct nft_expr *expr_array[]); void nft_set_elem_destroy(const struct nft_set *set, void *elem, bool destroy_expr); +void nf_tables_set_elem_destroy(const struct nft_ctx *ctx, + const struct nft_set *set, void *elem); /** * struct nft_set_gc_batch_head - nf_tables set garbage collection batch diff --git a/include/net/pkt_sched.h b/include/net/pkt_sched.h index 9cd2d4e84913..d0d9dd2483dd 100644 --- a/include/net/pkt_sched.h +++ b/include/net/pkt_sched.h @@ -141,7 +141,7 @@ extern const struct nla_policy rtm_tca_policy[TCA_MAX + 1]; */ static inline unsigned int psched_mtu(const struct net_device *dev) { - return dev->mtu + dev->hard_header_len; + return READ_ONCE(dev->mtu) + dev->hard_header_len; } static inline struct net *qdisc_net(struct Qdisc *q) diff --git a/include/net/sock.h b/include/net/sock.h index 01ad2c34c4de..eef2258c70b9 100644 --- a/include/net/sock.h +++ b/include/net/sock.h @@ -2012,6 +2012,7 @@ static inline void sock_graft(struct sock *sk, struct socket *parent) } kuid_t sock_i_uid(struct sock *sk); +unsigned long __sock_i_ino(struct sock *sk); unsigned long sock_i_ino(struct sock *sk); static inline kuid_t sock_net_uid(const struct net *net, const struct sock *sk) diff --git a/include/net/tcp.h b/include/net/tcp.h index 81ef95dc27ba..e1b8ec82feb2 100644 --- a/include/net/tcp.h +++ b/include/net/tcp.h @@ -1473,25 +1473,38 @@ void tcp_leave_memory_pressure(struct sock *sk); static inline int keepalive_intvl_when(const struct tcp_sock *tp) { struct net *net = sock_net((struct sock *)tp); + int val; - return tp->keepalive_intvl ? : - READ_ONCE(net->ipv4.sysctl_tcp_keepalive_intvl); + /* Paired with WRITE_ONCE() in tcp_sock_set_keepintvl() + * and do_tcp_setsockopt(). + */ + val = READ_ONCE(tp->keepalive_intvl); + + return val ? : READ_ONCE(net->ipv4.sysctl_tcp_keepalive_intvl); } static inline int keepalive_time_when(const struct tcp_sock *tp) { struct net *net = sock_net((struct sock *)tp); + int val; - return tp->keepalive_time ? : - READ_ONCE(net->ipv4.sysctl_tcp_keepalive_time); + /* Paired with WRITE_ONCE() in tcp_sock_set_keepidle_locked() */ + val = READ_ONCE(tp->keepalive_time); + + return val ? : READ_ONCE(net->ipv4.sysctl_tcp_keepalive_time); } static inline int keepalive_probes(const struct tcp_sock *tp) { struct net *net = sock_net((struct sock *)tp); + int val; - return tp->keepalive_probes ? : - READ_ONCE(net->ipv4.sysctl_tcp_keepalive_probes); + /* Paired with WRITE_ONCE() in tcp_sock_set_keepcnt() + * and do_tcp_setsockopt(). + */ + val = READ_ONCE(tp->keepalive_probes); + + return val ? : READ_ONCE(net->ipv4.sysctl_tcp_keepalive_probes); } static inline u32 keepalive_time_elapsed(const struct tcp_sock *tp) @@ -1999,7 +2012,11 @@ void __tcp_v4_send_check(struct sk_buff *skb, __be32 saddr, __be32 daddr); static inline u32 tcp_notsent_lowat(const struct tcp_sock *tp) { struct net *net = sock_net((struct sock *)tp); - return tp->notsent_lowat ?: READ_ONCE(net->ipv4.sysctl_tcp_notsent_lowat); + u32 val; + + val = READ_ONCE(tp->notsent_lowat); + + return val ?: READ_ONCE(net->ipv4.sysctl_tcp_notsent_lowat); } bool tcp_stream_memory_free(const struct sock *sk, int wake); diff --git a/include/soc/qcom/dcvs.h b/include/soc/qcom/dcvs.h index 963a1f408af1..158b81fc759a 100644 --- a/include/soc/qcom/dcvs.h +++ b/include/soc/qcom/dcvs.h @@ -17,6 +17,7 @@ enum dcvs_hw_type { DCVS_LLCC, DCVS_L3, DCVS_DDRQOS, + DCVS_L3_1, NUM_DCVS_HW_TYPES }; diff --git a/include/trace/events/f2fs.h b/include/trace/events/f2fs.h index e6ec99ed670b..7fa82286e2c8 100644 --- a/include/trace/events/f2fs.h +++ b/include/trace/events/f2fs.h @@ -15,10 +15,6 @@ TRACE_DEFINE_ENUM(NODE); TRACE_DEFINE_ENUM(DATA); TRACE_DEFINE_ENUM(META); TRACE_DEFINE_ENUM(META_FLUSH); -TRACE_DEFINE_ENUM(INMEM); -TRACE_DEFINE_ENUM(INMEM_DROP); -TRACE_DEFINE_ENUM(INMEM_INVALIDATE); -TRACE_DEFINE_ENUM(INMEM_REVOKE); TRACE_DEFINE_ENUM(IPU); TRACE_DEFINE_ENUM(OPU); TRACE_DEFINE_ENUM(HOT); @@ -59,10 +55,6 @@ TRACE_DEFINE_ENUM(CP_RESIZE); { DATA, "DATA" }, \ { META, "META" }, \ { META_FLUSH, "META_FLUSH" }, \ - { INMEM, "INMEM" }, \ - { INMEM_DROP, "INMEM_DROP" }, \ - { INMEM_INVALIDATE, "INMEM_INVALIDATE" }, \ - { INMEM_REVOKE, "INMEM_REVOKE" }, \ { IPU, "IN-PLACE" }, \ { OPU, "OUT-OF-PLACE" }) @@ -1296,18 +1288,41 @@ DEFINE_EVENT(f2fs__page, f2fs_vm_page_mkwrite, TP_ARGS(page, type) ); -DEFINE_EVENT(f2fs__page, f2fs_register_inmem_page, +TRACE_EVENT(f2fs_replace_atomic_write_block, - TP_PROTO(struct page *page, int type), + TP_PROTO(struct inode *inode, struct inode *cow_inode, pgoff_t index, + block_t old_addr, block_t new_addr, bool recovery), - TP_ARGS(page, type) -); + TP_ARGS(inode, cow_inode, index, old_addr, new_addr, recovery), -DEFINE_EVENT(f2fs__page, f2fs_commit_inmem_page, + TP_STRUCT__entry( + __field(dev_t, dev) + __field(ino_t, ino) + __field(ino_t, cow_ino) + __field(pgoff_t, index) + __field(block_t, old_addr) + __field(block_t, new_addr) + __field(bool, recovery) + ), - TP_PROTO(struct page *page, int type), + TP_fast_assign( + __entry->dev = inode->i_sb->s_dev; + __entry->ino = inode->i_ino; + __entry->cow_ino = cow_inode->i_ino; + __entry->index = index; + __entry->old_addr = old_addr; + __entry->new_addr = new_addr; + __entry->recovery = recovery; + ), - TP_ARGS(page, type) + TP_printk("dev = (%d,%d), ino = %lu, cow_ino = %lu, index = %lu, " + "old_addr = 0x%llx, new_addr = 0x%llx, recovery = %d", + show_dev_ino(__entry), + __entry->cow_ino, + (unsigned long)__entry->index, + (unsigned long long)__entry->old_addr, + (unsigned long long)__entry->new_addr, + __entry->recovery) ); TRACE_EVENT(f2fs_filemap_fault, diff --git a/include/trace/events/timer.h b/include/trace/events/timer.h index 1cf012de6442..d49e44fcc10f 100644 --- a/include/trace/events/timer.h +++ b/include/trace/events/timer.h @@ -156,7 +156,11 @@ DEFINE_EVENT(timer_class, timer_cancel, { HRTIMER_MODE_ABS_SOFT, "ABS|SOFT" }, \ { HRTIMER_MODE_REL_SOFT, "REL|SOFT" }, \ { HRTIMER_MODE_ABS_PINNED_SOFT, "ABS|PINNED|SOFT" }, \ - { HRTIMER_MODE_REL_PINNED_SOFT, "REL|PINNED|SOFT" }) + { HRTIMER_MODE_REL_PINNED_SOFT, "REL|PINNED|SOFT" }, \ + { HRTIMER_MODE_ABS_HARD, "ABS|HARD" }, \ + { HRTIMER_MODE_REL_HARD, "REL|HARD" }, \ + { HRTIMER_MODE_ABS_PINNED_HARD, "ABS|PINNED|HARD" }, \ + { HRTIMER_MODE_REL_PINNED_HARD, "REL|PINNED|HARD" }) /** * hrtimer_init - called when the hrtimer is initialized diff --git a/include/trace/hooks/dtask.h b/include/trace/hooks/dtask.h index 0796ed8c79e4..9b8fbb1a003c 100644 --- a/include/trace/hooks/dtask.h +++ b/include/trace/hooks/dtask.h @@ -98,6 +98,11 @@ DECLARE_HOOK(android_vh_record_pcpu_rwsem_starttime, TP_PROTO(struct task_struct *tsk, unsigned long settime_jiffies), TP_ARGS(tsk, settime_jiffies)); +struct percpu_rw_semaphore; +DECLARE_HOOK(android_vh_percpu_rwsem_wq_add, + TP_PROTO(struct percpu_rw_semaphore *sem, bool reader), + TP_ARGS(sem, reader)); + struct rt_mutex_waiter; struct ww_acquire_ctx; DECLARE_HOOK(android_vh_task_blocks_on_rtmutex, @@ -108,6 +113,19 @@ DECLARE_HOOK(android_vh_task_blocks_on_rtmutex, DECLARE_HOOK(android_vh_rtmutex_waiter_prio, TP_PROTO(struct task_struct *task, int *waiter_prio), TP_ARGS(task, waiter_prio)); + +DECLARE_HOOK(android_vh_exit_signal_whether_wake, + TP_PROTO(struct task_struct *p, bool *wake), + TP_ARGS(p, wake)); + +DECLARE_HOOK(android_vh_exit_check, + TP_PROTO(struct task_struct *p), + TP_ARGS(p)); + +DECLARE_HOOK(android_vh_freeze_whether_wake, + TP_PROTO(struct task_struct *t, bool *wake), + TP_ARGS(t, wake)); + #endif /* _TRACE_HOOK_DTASK_H */ /* This part must be outside protection */ #include diff --git a/include/trace/hooks/iommu.h b/include/trace/hooks/iommu.h index 63f6b9349a72..62cbd072411a 100644 --- a/include/trace/hooks/iommu.h +++ b/include/trace/hooks/iommu.h @@ -29,6 +29,10 @@ DECLARE_HOOK(android_vh_iommu_iovad_free_iova, TP_PROTO(struct iova_domain *iovad, dma_addr_t iova, size_t size), TP_ARGS(iovad, iova, size)); +DECLARE_HOOK(android_vh_adjust_alloc_flags, + TP_PROTO(unsigned int order, gfp_t *alloc_flags), + TP_ARGS(order, alloc_flags)); + #endif /* _TRACE_HOOK_IOMMU_H */ /* This part must be outside protection */ diff --git a/include/trace/hooks/mm.h b/include/trace/hooks/mm.h index 02fb7d694ef2..a83802484fb6 100644 --- a/include/trace/hooks/mm.h +++ b/include/trace/hooks/mm.h @@ -32,6 +32,8 @@ struct slabinfo; struct track; struct address_space; struct page_vma_mapped_walk; +struct cma; +struct compact_control; DECLARE_RESTRICTED_HOOK(android_rvh_set_skip_swapcache_flags, TP_PROTO(gfp_t *flags), @@ -244,6 +246,23 @@ DECLARE_HOOK(android_vh_look_around, DECLARE_HOOK(android_vh_try_cma_fallback, TP_PROTO(struct zone *zone, unsigned int order, bool *try_cma), TP_ARGS(zone, order, try_cma)); +DECLARE_HOOK(android_vh_set_page_migrating, + TP_PROTO(struct page *page), + TP_ARGS(page)); +DECLARE_HOOK(android_vh_clear_page_migrating, + TP_PROTO(struct page *page), + TP_ARGS(page)); +DECLARE_HOOK(android_vh_cma_alloc_bypass, + TP_PROTO(struct cma *cma, unsigned long count, unsigned int align, + bool no_warn, struct page **page, bool *bypass), + TP_ARGS(cma, count, align, no_warn, page, bypass)); +DECLARE_HOOK(android_vh_alloc_pages_entry, + TP_PROTO(gfp_t *gfp, unsigned int order, int preferred_nid, + nodemask_t *nodemask), + TP_ARGS(gfp, order, preferred_nid, nodemask)); +DECLARE_HOOK(android_vh_isolate_freepages, + TP_PROTO(struct compact_control *cc, struct page *page, bool *bypass), + TP_ARGS(cc, page, bypass)); #endif /* _TRACE_HOOK_MM_H */ /* This part must be outside protection */ diff --git a/include/trace/hooks/thermal.h b/include/trace/hooks/thermal.h index 0cfd0e830365..2efcc17519b5 100644 --- a/include/trace/hooks/thermal.h +++ b/include/trace/hooks/thermal.h @@ -58,6 +58,10 @@ DECLARE_HOOK(android_vh_modify_thermal_cpu_get_power, TP_PROTO(struct cpufreq_policy *policy, u32 *power), TP_ARGS(policy, power)); +DECLARE_HOOK(android_vh_enable_thermal_genl_check, + TP_PROTO(int event, int tz_id, int *enable_thermal_genl), + TP_ARGS(event, tz_id, enable_thermal_genl)); + #endif /* _TRACE_HOOK_THERMAL_H */ /* This part must be outside protection */ #include diff --git a/include/trace/hooks/usb.h b/include/trace/hooks/usb.h index 24b815998cda..7e2bf35395f5 100644 --- a/include/trace/hooks/usb.h +++ b/include/trace/hooks/usb.h @@ -16,10 +16,16 @@ #endif struct usb_device; +struct urb; DECLARE_HOOK(android_vh_usb_new_device_added, TP_PROTO(struct usb_device *udev, int *err), TP_ARGS(udev, err)); + +DECLARE_HOOK(android_vh_xhci_urb_suitable_bypass, + TP_PROTO(struct urb *urb, int *ret), + TP_ARGS(urb, ret)); + #endif /* _TRACE_HOOK_USB_H */ /* This part must be outside protection */ #include diff --git a/include/uapi/linux/affs_hardblocks.h b/include/uapi/linux/affs_hardblocks.h index 5e2fb8481252..a5aff2eb5f70 100644 --- a/include/uapi/linux/affs_hardblocks.h +++ b/include/uapi/linux/affs_hardblocks.h @@ -7,42 +7,42 @@ /* Just the needed definitions for the RDB of an Amiga HD. */ struct RigidDiskBlock { - __u32 rdb_ID; + __be32 rdb_ID; __be32 rdb_SummedLongs; - __s32 rdb_ChkSum; - __u32 rdb_HostID; + __be32 rdb_ChkSum; + __be32 rdb_HostID; __be32 rdb_BlockBytes; - __u32 rdb_Flags; - __u32 rdb_BadBlockList; + __be32 rdb_Flags; + __be32 rdb_BadBlockList; __be32 rdb_PartitionList; - __u32 rdb_FileSysHeaderList; - __u32 rdb_DriveInit; - __u32 rdb_Reserved1[6]; - __u32 rdb_Cylinders; - __u32 rdb_Sectors; - __u32 rdb_Heads; - __u32 rdb_Interleave; - __u32 rdb_Park; - __u32 rdb_Reserved2[3]; - __u32 rdb_WritePreComp; - __u32 rdb_ReducedWrite; - __u32 rdb_StepRate; - __u32 rdb_Reserved3[5]; - __u32 rdb_RDBBlocksLo; - __u32 rdb_RDBBlocksHi; - __u32 rdb_LoCylinder; - __u32 rdb_HiCylinder; - __u32 rdb_CylBlocks; - __u32 rdb_AutoParkSeconds; - __u32 rdb_HighRDSKBlock; - __u32 rdb_Reserved4; + __be32 rdb_FileSysHeaderList; + __be32 rdb_DriveInit; + __be32 rdb_Reserved1[6]; + __be32 rdb_Cylinders; + __be32 rdb_Sectors; + __be32 rdb_Heads; + __be32 rdb_Interleave; + __be32 rdb_Park; + __be32 rdb_Reserved2[3]; + __be32 rdb_WritePreComp; + __be32 rdb_ReducedWrite; + __be32 rdb_StepRate; + __be32 rdb_Reserved3[5]; + __be32 rdb_RDBBlocksLo; + __be32 rdb_RDBBlocksHi; + __be32 rdb_LoCylinder; + __be32 rdb_HiCylinder; + __be32 rdb_CylBlocks; + __be32 rdb_AutoParkSeconds; + __be32 rdb_HighRDSKBlock; + __be32 rdb_Reserved4; char rdb_DiskVendor[8]; char rdb_DiskProduct[16]; char rdb_DiskRevision[4]; char rdb_ControllerVendor[8]; char rdb_ControllerProduct[16]; char rdb_ControllerRevision[4]; - __u32 rdb_Reserved5[10]; + __be32 rdb_Reserved5[10]; }; #define IDNAME_RIGIDDISK 0x5244534B /* "RDSK" */ @@ -50,16 +50,16 @@ struct RigidDiskBlock { struct PartitionBlock { __be32 pb_ID; __be32 pb_SummedLongs; - __s32 pb_ChkSum; - __u32 pb_HostID; + __be32 pb_ChkSum; + __be32 pb_HostID; __be32 pb_Next; - __u32 pb_Flags; - __u32 pb_Reserved1[2]; - __u32 pb_DevFlags; + __be32 pb_Flags; + __be32 pb_Reserved1[2]; + __be32 pb_DevFlags; __u8 pb_DriveName[32]; - __u32 pb_Reserved2[15]; + __be32 pb_Reserved2[15]; __be32 pb_Environment[17]; - __u32 pb_EReserved[15]; + __be32 pb_EReserved[15]; }; #define IDNAME_PARTITION 0x50415254 /* "PART" */ diff --git a/include/uapi/linux/android_fuse.h b/include/uapi/linux/android_fuse.h index 221e30ea7f01..58f3d171952d 100644 --- a/include/uapi/linux/android_fuse.h +++ b/include/uapi/linux/android_fuse.h @@ -56,15 +56,29 @@ struct fuse_in_postfilter_header { /** One input argument of a request */ struct fuse_bpf_in_arg { uint32_t size; - const void *value; - const void *end_offset; + uint32_t padding; + union { + const void *value; + uint64_t padding2; + }; + union { + const void *end_offset; + uint64_t padding3; + }; }; /** One output argument of a request */ struct fuse_bpf_arg { uint32_t size; - void *value; - void *end_offset; + uint32_t padding; + union { + void *value; + uint64_t padding2; + }; + union { + void *end_offset; + uint64_t padding3; + }; }; #define FUSE_MAX_IN_ARGS 5 @@ -80,6 +94,7 @@ struct fuse_bpf_args { uint32_t in_numargs; uint32_t out_numargs; uint32_t flags; + uint32_t padding; struct fuse_bpf_in_arg in_args[FUSE_MAX_IN_ARGS]; struct fuse_bpf_arg out_args[FUSE_MAX_OUT_ARGS]; }; diff --git a/include/uapi/linux/auto_dev-ioctl.h b/include/uapi/linux/auto_dev-ioctl.h index 62e625356dc8..08be539605fc 100644 --- a/include/uapi/linux/auto_dev-ioctl.h +++ b/include/uapi/linux/auto_dev-ioctl.h @@ -109,7 +109,7 @@ struct autofs_dev_ioctl { struct args_ismountpoint ismountpoint; }; - char path[0]; + char path[]; }; static inline void init_autofs_dev_ioctl(struct autofs_dev_ioctl *in) diff --git a/include/uapi/linux/f2fs.h b/include/uapi/linux/f2fs.h index 352a822d4370..955d440be104 100644 --- a/include/uapi/linux/f2fs.h +++ b/include/uapi/linux/f2fs.h @@ -13,7 +13,7 @@ #define F2FS_IOC_COMMIT_ATOMIC_WRITE _IO(F2FS_IOCTL_MAGIC, 2) #define F2FS_IOC_START_VOLATILE_WRITE _IO(F2FS_IOCTL_MAGIC, 3) #define F2FS_IOC_RELEASE_VOLATILE_WRITE _IO(F2FS_IOCTL_MAGIC, 4) -#define F2FS_IOC_ABORT_VOLATILE_WRITE _IO(F2FS_IOCTL_MAGIC, 5) +#define F2FS_IOC_ABORT_ATOMIC_WRITE _IO(F2FS_IOCTL_MAGIC, 5) #define F2FS_IOC_GARBAGE_COLLECT _IOW(F2FS_IOCTL_MAGIC, 6, __u32) #define F2FS_IOC_WRITE_CHECKPOINT _IO(F2FS_IOCTL_MAGIC, 7) #define F2FS_IOC_DEFRAGMENT _IOWR(F2FS_IOCTL_MAGIC, 8, \ @@ -42,6 +42,7 @@ struct f2fs_comp_option) #define F2FS_IOC_DECOMPRESS_FILE _IO(F2FS_IOCTL_MAGIC, 23) #define F2FS_IOC_COMPRESS_FILE _IO(F2FS_IOCTL_MAGIC, 24) +#define F2FS_IOC_START_ATOMIC_REPLACE _IO(F2FS_IOCTL_MAGIC, 25) /* * should be same as XFS_IOC_GOINGDOWN. diff --git a/include/uapi/linux/videodev2.h b/include/uapi/linux/videodev2.h index f74b913dca75..4f4b00f552e7 100644 --- a/include/uapi/linux/videodev2.h +++ b/include/uapi/linux/videodev2.h @@ -1652,7 +1652,7 @@ struct v4l2_input { __u8 name[32]; /* Label */ __u32 type; /* Type of input */ __u32 audioset; /* Associated audios (bitfield) */ - __u32 tuner; /* enum v4l2_tuner_type */ + __u32 tuner; /* Tuner index */ v4l2_std_id std; __u32 status; __u32 capabilities; diff --git a/io_uring/io_uring.c b/io_uring/io_uring.c index cbfc9bbe87b0..d7f87157be9a 100644 --- a/io_uring/io_uring.c +++ b/io_uring/io_uring.c @@ -1524,6 +1524,8 @@ static void io_kill_timeout(struct io_kiocb *req, int status) static void io_queue_deferred(struct io_ring_ctx *ctx) { + lockdep_assert_held(&ctx->completion_lock); + while (!list_empty(&ctx->defer_list)) { struct io_defer_entry *de = list_first_entry(&ctx->defer_list, struct io_defer_entry, list); @@ -1575,14 +1577,24 @@ static void __io_commit_cqring_flush(struct io_ring_ctx *ctx) io_queue_deferred(ctx); } -static inline void io_commit_cqring(struct io_ring_ctx *ctx) +static inline bool io_commit_needs_flush(struct io_ring_ctx *ctx) +{ + return ctx->off_timeout_used || ctx->drain_active; +} + +static inline void __io_commit_cqring(struct io_ring_ctx *ctx) { - if (unlikely(ctx->off_timeout_used || ctx->drain_active)) - __io_commit_cqring_flush(ctx); /* order cqe stores with ring update */ smp_store_release(&ctx->rings->cq.tail, ctx->cached_cq_tail); } +static inline void io_commit_cqring(struct io_ring_ctx *ctx) +{ + if (unlikely(io_commit_needs_flush(ctx))) + __io_commit_cqring_flush(ctx); + __io_commit_cqring(ctx); +} + static inline bool io_sqring_full(struct io_ring_ctx *ctx) { struct io_rings *r = ctx->rings; @@ -2205,9 +2217,12 @@ static void tctx_task_work(struct callback_head *cb) } req->io_task_work.func(req, &locked); node = next; + if (unlikely(need_resched())) { + ctx_flush_and_put(ctx, &locked); + ctx = NULL; + cond_resched(); + } } while (node); - - cond_resched(); } ctx_flush_and_put(ctx, &locked); @@ -2521,7 +2536,12 @@ static void io_iopoll_complete(struct io_ring_ctx *ctx, unsigned int *nr_events, io_req_free_batch(&rb, req, &ctx->submit_state); } - io_commit_cqring(ctx); + if (io_commit_needs_flush(ctx)) { + spin_lock(&ctx->completion_lock); + __io_commit_cqring_flush(ctx); + spin_unlock(&ctx->completion_lock); + } + __io_commit_cqring(ctx); io_cqring_ev_posted_iopoll(ctx); io_req_free_batch_finish(ctx, &rb); } @@ -7779,7 +7799,7 @@ static inline int io_cqring_wait_schedule(struct io_ring_ctx *ctx, struct io_wait_queue *iowq, ktime_t *timeout) { - int ret; + int token, ret; /* make sure we run task_work before checking for signals */ ret = io_run_task_work_sig(); @@ -7789,9 +7809,17 @@ static inline int io_cqring_wait_schedule(struct io_ring_ctx *ctx, if (test_bit(0, &ctx->check_cq_overflow)) return 1; + /* + * Use io_schedule_prepare/finish, so cpufreq can take into account + * that the task is waiting for IO - turns out to be important for low + * QD IO. + */ + token = io_schedule_prepare(); + ret = 1; if (!schedule_hrtimeout(timeout, HRTIMER_MODE_ABS)) - return -ETIME; - return 1; + ret = -ETIME; + io_schedule_finish(token); + return ret; } /* @@ -9697,7 +9725,18 @@ static void io_ring_exit_work(struct work_struct *work) /* there is little hope left, don't run it too often */ interval = HZ * 60; } - } while (!wait_for_completion_timeout(&ctx->ref_comp, interval)); + /* + * This is really an uninterruptible wait, as it has to be + * complete. But it's also run from a kworker, which doesn't + * take signals, so it's fine to make it interruptible. This + * avoids scenarios where we knowingly can wait much longer + * on completions, for example if someone does a SIGSTOP on + * a task that needs to finish task_work to make this loop + * complete. That's a synthetic situation that should not + * cause a stuck task backtrace, and hence a potential panic + * on stuck tasks if that is enabled. + */ + } while (!wait_for_completion_interruptible_timeout(&ctx->ref_comp, interval)); init_completion(&exit.completion); init_task_work(&exit.task_work, io_tctx_exit_cb); @@ -9722,7 +9761,12 @@ static void io_ring_exit_work(struct work_struct *work) wake_up_process(node->task); mutex_unlock(&ctx->uring_lock); - wait_for_completion(&exit.completion); + /* + * See comment above for + * wait_for_completion_interruptible_timeout() on why this + * wait is marked as interruptible. + */ + wait_for_completion_interruptible(&exit.completion); mutex_lock(&ctx->uring_lock); } mutex_unlock(&ctx->uring_lock); diff --git a/kernel/bpf/cgroup.c b/kernel/bpf/cgroup.c index 87174832aa86..297569e5c639 100644 --- a/kernel/bpf/cgroup.c +++ b/kernel/bpf/cgroup.c @@ -1481,6 +1481,12 @@ int __cgroup_bpf_run_filter_setsockopt(struct sock *sk, int *level, ret = 1; } else if (ctx.optlen > max_optlen || ctx.optlen < -1) { /* optlen is out of bounds */ + if (*optlen > PAGE_SIZE && ctx.optlen >= 0) { + pr_info_once("bpf setsockopt: ignoring program buffer with optlen=%d (max_optlen=%d)\n", + ctx.optlen, max_optlen); + ret = 0; + goto out; + } ret = -EFAULT; } else { /* optlen within bounds, run kernel handler */ @@ -1536,6 +1542,7 @@ int __cgroup_bpf_run_filter_getsockopt(struct sock *sk, int level, .optname = optname, .retval = retval, }; + int orig_optlen; int ret; /* Opportunistic check to see whether we have any BPF program @@ -1545,6 +1552,7 @@ int __cgroup_bpf_run_filter_getsockopt(struct sock *sk, int level, if (__cgroup_bpf_prog_array_is_empty(cgrp, CGROUP_GETSOCKOPT)) return retval; + orig_optlen = max_optlen; ctx.optlen = max_optlen; max_optlen = sockopt_alloc_buf(&ctx, max_optlen, &buf); @@ -1568,6 +1576,7 @@ int __cgroup_bpf_run_filter_getsockopt(struct sock *sk, int level, ret = -EFAULT; goto out; } + orig_optlen = ctx.optlen; if (copy_from_user(ctx.optval, optval, min(ctx.optlen, max_optlen)) != 0) { @@ -1587,6 +1596,12 @@ int __cgroup_bpf_run_filter_getsockopt(struct sock *sk, int level, } if (optval && (ctx.optlen > max_optlen || ctx.optlen < 0)) { + if (orig_optlen > PAGE_SIZE && ctx.optlen >= 0) { + pr_info_once("bpf getsockopt: ignoring program buffer with optlen=%d (max_optlen=%d)\n", + ctx.optlen, max_optlen); + ret = retval; + goto out; + } ret = -EFAULT; goto out; } diff --git a/kernel/bpf/cpumap.c b/kernel/bpf/cpumap.c index 585b2b77ccc4..db6221773e43 100644 --- a/kernel/bpf/cpumap.c +++ b/kernel/bpf/cpumap.c @@ -126,22 +126,6 @@ static void get_cpu_map_entry(struct bpf_cpu_map_entry *rcpu) atomic_inc(&rcpu->refcnt); } -/* called from workqueue, to workaround syscall using preempt_disable */ -static void cpu_map_kthread_stop(struct work_struct *work) -{ - struct bpf_cpu_map_entry *rcpu; - - rcpu = container_of(work, struct bpf_cpu_map_entry, kthread_stop_wq); - - /* Wait for flush in __cpu_map_entry_free(), via full RCU barrier, - * as it waits until all in-flight call_rcu() callbacks complete. - */ - rcu_barrier(); - - /* kthread_stop will wake_up_process and wait for it to complete */ - kthread_stop(rcpu->kthread); -} - static void __cpu_map_ring_cleanup(struct ptr_ring *ring) { /* The tear-down procedure should have made sure that queue is @@ -169,6 +153,30 @@ static void put_cpu_map_entry(struct bpf_cpu_map_entry *rcpu) } } +/* called from workqueue, to workaround syscall using preempt_disable */ +static void cpu_map_kthread_stop(struct work_struct *work) +{ + struct bpf_cpu_map_entry *rcpu; + int err; + + rcpu = container_of(work, struct bpf_cpu_map_entry, kthread_stop_wq); + + /* Wait for flush in __cpu_map_entry_free(), via full RCU barrier, + * as it waits until all in-flight call_rcu() callbacks complete. + */ + rcu_barrier(); + + /* kthread_stop will wake_up_process and wait for it to complete */ + err = kthread_stop(rcpu->kthread); + if (err) { + /* kthread_stop may be called before cpu_map_kthread_run + * is executed, so we need to release the memory related + * to rcpu. + */ + put_cpu_map_entry(rcpu); + } +} + static void cpu_map_bpf_prog_run_skb(struct bpf_cpu_map_entry *rcpu, struct list_head *listp, struct xdp_cpumap_stats *stats) diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c index 49f0781a7d41..534916990708 100644 --- a/kernel/bpf/verifier.c +++ b/kernel/bpf/verifier.c @@ -3740,7 +3740,7 @@ process_func: continue_func: subprog_end = subprog[idx + 1].start; for (; i < subprog_end; i++) { - int next_insn; + int next_insn, sidx; if (!bpf_pseudo_call(insn + i) && !bpf_pseudo_func(insn + i)) continue; @@ -3750,21 +3750,23 @@ continue_func: /* find the callee */ next_insn = i + insn[i].imm + 1; - idx = find_subprog(env, next_insn); - if (idx < 0) { + sidx = find_subprog(env, next_insn); + if (sidx < 0) { WARN_ONCE(1, "verifier bug. No program starts at insn %d\n", next_insn); return -EFAULT; } - if (subprog[idx].is_async_cb) { - if (subprog[idx].has_tail_call) { + if (subprog[sidx].is_async_cb) { + if (subprog[sidx].has_tail_call) { verbose(env, "verifier bug. subprog has tail_call and async cb\n"); return -EFAULT; } - /* async callbacks don't increase bpf prog stack size */ - continue; + /* async callbacks don't increase bpf prog stack size unless called directly */ + if (!bpf_pseudo_call(insn + i)) + continue; } i = next_insn; + idx = sidx; if (subprog[idx].has_tail_call) tail_call_reachable = true; @@ -12564,9 +12566,10 @@ static int jit_subprogs(struct bpf_verifier_env *env) } /* finally lock prog and jit images for all functions and - * populate kallsysm + * populate kallsysm. Begin at the first subprogram, since + * bpf_prog_load will add the kallsyms for the main program. */ - for (i = 0; i < env->subprog_cnt; i++) { + for (i = 1; i < env->subprog_cnt; i++) { bpf_prog_lock_ro(func[i]); bpf_prog_kallsyms_add(func[i]); } @@ -12591,6 +12594,8 @@ static int jit_subprogs(struct bpf_verifier_env *env) prog->jited = 1; prog->bpf_func = func[0]->bpf_func; + prog->aux->extable = func[0]->aux->extable; + prog->aux->num_exentries = func[0]->aux->num_exentries; prog->aux->func = func; prog->aux->func_cnt = env->subprog_cnt; bpf_prog_jit_attempt_done(prog); diff --git a/kernel/cgroup/freezer.c b/kernel/cgroup/freezer.c index 3984dd6b8ddb..5b9912a026fd 100644 --- a/kernel/cgroup/freezer.c +++ b/kernel/cgroup/freezer.c @@ -7,6 +7,7 @@ #include "cgroup-internal.h" #include +#include /* * Propagate the cgroup frozen state upwards by the cgroup tree. @@ -155,17 +156,21 @@ void cgroup_leave_frozen(bool always_leave) static void cgroup_freeze_task(struct task_struct *task, bool freeze) { unsigned long flags; + bool wake = true; /* If the task is about to die, don't bother with freezing it. */ if (!lock_task_sighand(task, &flags)) return; + trace_android_vh_freeze_whether_wake(task, &wake); if (freeze) { task->jobctl |= JOBCTL_TRAP_FREEZE; - signal_wake_up(task, false); + if (wake) + signal_wake_up(task, false); } else { task->jobctl &= ~JOBCTL_TRAP_FREEZE; - wake_up_process(task); + if (wake) + wake_up_process(task); } unlock_task_sighand(task, &flags); diff --git a/kernel/events/core.c b/kernel/events/core.c index 9f6458cb83bf..d24c8fd95745 100644 --- a/kernel/events/core.c +++ b/kernel/events/core.c @@ -1223,6 +1223,11 @@ static int perf_mux_hrtimer_restart(struct perf_cpu_context *cpuctx) return 0; } +static int perf_mux_hrtimer_restart_ipi(void *arg) +{ + return perf_mux_hrtimer_restart(arg); +} + void perf_pmu_disable(struct pmu *pmu) { int *count = this_cpu_ptr(pmu->pmu_disable_count); @@ -11044,8 +11049,7 @@ perf_event_mux_interval_ms_store(struct device *dev, cpuctx = per_cpu_ptr(pmu->pmu_cpu_context, cpu); cpuctx->hrtimer_interval = ns_to_ktime(NSEC_PER_MSEC * timer); - cpu_function_call(cpu, - (remote_function_f)perf_mux_hrtimer_restart, cpuctx); + cpu_function_call(cpu, perf_mux_hrtimer_restart_ipi, cpuctx); } cpus_read_unlock(); mutex_unlock(&mux_interval_mutex); diff --git a/kernel/exit.c b/kernel/exit.c index e278891e6983..31d8f357f7d6 100644 --- a/kernel/exit.c +++ b/kernel/exit.c @@ -70,6 +70,7 @@ #include #include #include +#include /* * The default value should be high enough to not crash a system that randomly @@ -830,6 +831,8 @@ void __noreturn do_exit(long code) io_uring_files_cancel(); exit_signals(tsk); /* sets PF_EXITING */ + trace_android_vh_exit_check(current); + /* sync mm's RSS info before statistics gathering */ if (tsk->mm) sync_mm_rss(tsk->mm); diff --git a/kernel/kcsan/core.c b/kernel/kcsan/core.c index 526510b3791e..3f3b5e3ca9eb 100644 --- a/kernel/kcsan/core.c +++ b/kernel/kcsan/core.c @@ -1050,7 +1050,9 @@ EXPORT_SYMBOL(__tsan_init); DEFINE_TSAN_ATOMIC_OPS(8); DEFINE_TSAN_ATOMIC_OPS(16); DEFINE_TSAN_ATOMIC_OPS(32); +#ifdef CONFIG_64BIT DEFINE_TSAN_ATOMIC_OPS(64); +#endif void __tsan_atomic_thread_fence(int memorder); void __tsan_atomic_thread_fence(int memorder) diff --git a/kernel/kexec_core.c b/kernel/kexec_core.c index bdc2d952911c..7e735fd33858 100644 --- a/kernel/kexec_core.c +++ b/kernel/kexec_core.c @@ -1029,6 +1029,7 @@ int crash_shrink_memory(unsigned long new_size) start = crashk_res.start; end = crashk_res.end; old_size = (end == 0) ? 0 : end - start + 1; + new_size = roundup(new_size, KEXEC_CRASH_MEM_ALIGN); if (new_size >= old_size) { ret = (new_size == old_size) ? 0 : -EINVAL; goto unlock; @@ -1040,9 +1041,7 @@ int crash_shrink_memory(unsigned long new_size) goto unlock; } - start = roundup(start, KEXEC_CRASH_MEM_ALIGN); - end = roundup(start + new_size, KEXEC_CRASH_MEM_ALIGN); - + end = start + new_size; crash_free_reserved_phys_range(end, crashk_res.end); if ((start == end) && (crashk_res.parent != NULL)) diff --git a/kernel/kthread.c b/kernel/kthread.c index 296b3327768e..f4dfd7d43d44 100644 --- a/kernel/kthread.c +++ b/kernel/kthread.c @@ -60,6 +60,8 @@ struct kthread { #ifdef CONFIG_BLK_CGROUP struct cgroup_subsys_state *blkcg_css; #endif + /* To store the full name if task comm is truncated. */ + char *full_name; }; enum KTHREAD_BITS { @@ -93,6 +95,18 @@ static inline struct kthread *__to_kthread(struct task_struct *p) return kthread; } +void get_kthread_comm(char *buf, size_t buf_size, struct task_struct *tsk) +{ + struct kthread *kthread = to_kthread(tsk); + + if (!kthread || !kthread->full_name) { + __get_task_comm(buf, buf_size, tsk); + return; + } + + strscpy_pad(buf, kthread->full_name, buf_size); +} + void set_kthread_struct(struct task_struct *p) { struct kthread *kthread; @@ -118,9 +132,13 @@ void free_kthread_struct(struct task_struct *k) * or if kmalloc() in kthread() failed. */ kthread = to_kthread(k); + if (!kthread) + return; + #ifdef CONFIG_BLK_CGROUP - WARN_ON_ONCE(kthread && kthread->blkcg_css); + WARN_ON_ONCE(kthread->blkcg_css); #endif + kfree(kthread->full_name); kfree(kthread); } @@ -399,12 +417,22 @@ struct task_struct *__kthread_create_on_node(int (*threadfn)(void *data), if (!IS_ERR(task)) { static const struct sched_param param = { .sched_priority = 0 }; char name[TASK_COMM_LEN]; + va_list aq; + int len; /* * task is already visible to other tasks, so updating * COMM must be protected. */ - vsnprintf(name, sizeof(name), namefmt, args); + va_copy(aq, args); + len = vsnprintf(name, sizeof(name), namefmt, aq); + va_end(aq); + if (len >= TASK_COMM_LEN) { + struct kthread *kthread = to_kthread(task); + + /* leave it truncated when out of memory. */ + kthread->full_name = kvasprintf(GFP_KERNEL, namefmt, args); + } set_task_comm(task, name); /* * root may have changed our (kthreadd's) priority or CPU mask. diff --git a/kernel/locking/percpu-rwsem.c b/kernel/locking/percpu-rwsem.c index be997b3b6db6..cd875ecb299a 100644 --- a/kernel/locking/percpu-rwsem.c +++ b/kernel/locking/percpu-rwsem.c @@ -167,6 +167,7 @@ static void percpu_rwsem_wait(struct percpu_rw_semaphore *sem, bool reader) if (wait) { wq_entry.flags |= WQ_FLAG_EXCLUSIVE | reader * WQ_FLAG_CUSTOM; __add_wait_queue_entry_tail(&sem->waiters, &wq_entry); + trace_android_vh_percpu_rwsem_wq_add(sem, reader); } spin_unlock_irq(&sem->waiters.lock); diff --git a/kernel/printk/printk_ringbuffer.c b/kernel/printk/printk_ringbuffer.c index 2b7b6ddab4f7..0bbcd1344f21 100644 --- a/kernel/printk/printk_ringbuffer.c +++ b/kernel/printk/printk_ringbuffer.c @@ -1735,7 +1735,7 @@ static bool copy_data(struct prb_data_ring *data_ring, if (!buf || !buf_size) return true; - data_size = min_t(u16, buf_size, len); + data_size = min_t(unsigned int, buf_size, len); memcpy(&buf[0], data, data_size); /* LMM(copy_data:A) */ return true; diff --git a/kernel/rcu/rcuscale.c b/kernel/rcu/rcuscale.c index 2cc34a22a506..57ec414710bb 100644 --- a/kernel/rcu/rcuscale.c +++ b/kernel/rcu/rcuscale.c @@ -50,8 +50,8 @@ MODULE_AUTHOR("Paul E. McKenney "); pr_alert("%s" SCALE_FLAG " %s\n", scale_type, s) #define VERBOSE_SCALEOUT_STRING(s) \ do { if (verbose) pr_alert("%s" SCALE_FLAG " %s\n", scale_type, s); } while (0) -#define VERBOSE_SCALEOUT_ERRSTRING(s) \ - do { if (verbose) pr_alert("%s" SCALE_FLAG "!!! %s\n", scale_type, s); } while (0) +#define SCALEOUT_ERRSTRING(s) \ + pr_alert("%s" SCALE_FLAG "!!! %s\n", scale_type, s) /* * The intended use cases for the nreaders and nwriters module parameters @@ -500,89 +500,6 @@ rcu_scale_print_module_parms(struct rcu_scale_ops *cur_ops, const char *tag) scale_type, tag, nrealreaders, nrealwriters, verbose, shutdown); } -static void -rcu_scale_cleanup(void) -{ - int i; - int j; - int ngps = 0; - u64 *wdp; - u64 *wdpp; - - /* - * Would like warning at start, but everything is expedited - * during the mid-boot phase, so have to wait till the end. - */ - if (rcu_gp_is_expedited() && !rcu_gp_is_normal() && !gp_exp) - VERBOSE_SCALEOUT_ERRSTRING("All grace periods expedited, no normal ones to measure!"); - if (rcu_gp_is_normal() && gp_exp) - VERBOSE_SCALEOUT_ERRSTRING("All grace periods normal, no expedited ones to measure!"); - if (gp_exp && gp_async) - VERBOSE_SCALEOUT_ERRSTRING("No expedited async GPs, so went with async!"); - - if (torture_cleanup_begin()) - return; - if (!cur_ops) { - torture_cleanup_end(); - return; - } - - if (reader_tasks) { - for (i = 0; i < nrealreaders; i++) - torture_stop_kthread(rcu_scale_reader, - reader_tasks[i]); - kfree(reader_tasks); - } - - if (writer_tasks) { - for (i = 0; i < nrealwriters; i++) { - torture_stop_kthread(rcu_scale_writer, - writer_tasks[i]); - if (!writer_n_durations) - continue; - j = writer_n_durations[i]; - pr_alert("%s%s writer %d gps: %d\n", - scale_type, SCALE_FLAG, i, j); - ngps += j; - } - pr_alert("%s%s start: %llu end: %llu duration: %llu gps: %d batches: %ld\n", - scale_type, SCALE_FLAG, - t_rcu_scale_writer_started, t_rcu_scale_writer_finished, - t_rcu_scale_writer_finished - - t_rcu_scale_writer_started, - ngps, - rcuscale_seq_diff(b_rcu_gp_test_finished, - b_rcu_gp_test_started)); - for (i = 0; i < nrealwriters; i++) { - if (!writer_durations) - break; - if (!writer_n_durations) - continue; - wdpp = writer_durations[i]; - if (!wdpp) - continue; - for (j = 0; j < writer_n_durations[i]; j++) { - wdp = &wdpp[j]; - pr_alert("%s%s %4d writer-duration: %5d %llu\n", - scale_type, SCALE_FLAG, - i, j, *wdp); - if (j % 100 == 0) - schedule_timeout_uninterruptible(1); - } - kfree(writer_durations[i]); - } - kfree(writer_tasks); - kfree(writer_durations); - kfree(writer_n_durations); - } - - /* Do torture-type-specific cleanup operations. */ - if (cur_ops->cleanup != NULL) - cur_ops->cleanup(); - - torture_cleanup_end(); -} - /* * Return the number if non-negative. If -1, the number of CPUs. * If less than -1, that much less than the number of CPUs, but @@ -602,21 +519,6 @@ static int compute_real(int n) return nr; } -/* - * RCU scalability shutdown kthread. Just waits to be awakened, then shuts - * down system. - */ -static int -rcu_scale_shutdown(void *arg) -{ - wait_event(shutdown_wq, - atomic_read(&n_rcu_scale_writer_finished) >= nrealwriters); - smp_mb(); /* Wake before output. */ - rcu_scale_cleanup(); - kernel_power_off(); - return -EINVAL; -} - /* * kfree_rcu() scalability tests: Start a kfree_rcu() loop on all CPUs for number * of iterations and measure total time and number of GP for all iterations to complete. @@ -736,8 +638,8 @@ kfree_scale_cleanup(void) static int kfree_scale_shutdown(void *arg) { - wait_event(shutdown_wq, - atomic_read(&n_kfree_scale_thread_ended) >= kfree_nrealthreads); + wait_event_idle(shutdown_wq, + atomic_read(&n_kfree_scale_thread_ended) >= kfree_nrealthreads); smp_mb(); /* Wake before output. */ @@ -791,6 +693,108 @@ unwind: return firsterr; } +static void +rcu_scale_cleanup(void) +{ + int i; + int j; + int ngps = 0; + u64 *wdp; + u64 *wdpp; + + /* + * Would like warning at start, but everything is expedited + * during the mid-boot phase, so have to wait till the end. + */ + if (rcu_gp_is_expedited() && !rcu_gp_is_normal() && !gp_exp) + SCALEOUT_ERRSTRING("All grace periods expedited, no normal ones to measure!"); + if (rcu_gp_is_normal() && gp_exp) + SCALEOUT_ERRSTRING("All grace periods normal, no expedited ones to measure!"); + if (gp_exp && gp_async) + SCALEOUT_ERRSTRING("No expedited async GPs, so went with async!"); + + if (kfree_rcu_test) { + kfree_scale_cleanup(); + return; + } + + if (torture_cleanup_begin()) + return; + if (!cur_ops) { + torture_cleanup_end(); + return; + } + + if (reader_tasks) { + for (i = 0; i < nrealreaders; i++) + torture_stop_kthread(rcu_scale_reader, + reader_tasks[i]); + kfree(reader_tasks); + } + + if (writer_tasks) { + for (i = 0; i < nrealwriters; i++) { + torture_stop_kthread(rcu_scale_writer, + writer_tasks[i]); + if (!writer_n_durations) + continue; + j = writer_n_durations[i]; + pr_alert("%s%s writer %d gps: %d\n", + scale_type, SCALE_FLAG, i, j); + ngps += j; + } + pr_alert("%s%s start: %llu end: %llu duration: %llu gps: %d batches: %ld\n", + scale_type, SCALE_FLAG, + t_rcu_scale_writer_started, t_rcu_scale_writer_finished, + t_rcu_scale_writer_finished - + t_rcu_scale_writer_started, + ngps, + rcuscale_seq_diff(b_rcu_gp_test_finished, + b_rcu_gp_test_started)); + for (i = 0; i < nrealwriters; i++) { + if (!writer_durations) + break; + if (!writer_n_durations) + continue; + wdpp = writer_durations[i]; + if (!wdpp) + continue; + for (j = 0; j < writer_n_durations[i]; j++) { + wdp = &wdpp[j]; + pr_alert("%s%s %4d writer-duration: %5d %llu\n", + scale_type, SCALE_FLAG, + i, j, *wdp); + if (j % 100 == 0) + schedule_timeout_uninterruptible(1); + } + kfree(writer_durations[i]); + } + kfree(writer_tasks); + kfree(writer_durations); + kfree(writer_n_durations); + } + + /* Do torture-type-specific cleanup operations. */ + if (cur_ops->cleanup != NULL) + cur_ops->cleanup(); + + torture_cleanup_end(); +} + +/* + * RCU scalability shutdown kthread. Just waits to be awakened, then shuts + * down system. + */ +static int +rcu_scale_shutdown(void *arg) +{ + wait_event_idle(shutdown_wq, atomic_read(&n_rcu_scale_writer_finished) >= nrealwriters); + smp_mb(); /* Wake before output. */ + rcu_scale_cleanup(); + kernel_power_off(); + return -EINVAL; +} + static int __init rcu_scale_init(void) { @@ -845,7 +849,7 @@ rcu_scale_init(void) reader_tasks = kcalloc(nrealreaders, sizeof(reader_tasks[0]), GFP_KERNEL); if (reader_tasks == NULL) { - VERBOSE_SCALEOUT_ERRSTRING("out of memory"); + SCALEOUT_ERRSTRING("out of memory"); firsterr = -ENOMEM; goto unwind; } @@ -865,7 +869,7 @@ rcu_scale_init(void) kcalloc(nrealwriters, sizeof(*writer_n_durations), GFP_KERNEL); if (!writer_tasks || !writer_durations || !writer_n_durations) { - VERBOSE_SCALEOUT_ERRSTRING("out of memory"); + SCALEOUT_ERRSTRING("out of memory"); firsterr = -ENOMEM; goto unwind; } diff --git a/kernel/sched/core.c b/kernel/sched/core.c index a27cd84881f7..4f917662fb6b 100644 --- a/kernel/sched/core.c +++ b/kernel/sched/core.c @@ -4323,6 +4323,7 @@ int wake_up_state(struct task_struct *p, unsigned int state) { return try_to_wake_up(p, state, 0); } +EXPORT_SYMBOL(wake_up_state); /* * Perform scheduler related setup for a newly forked process p. @@ -5165,6 +5166,7 @@ unsigned int nr_running(void) return sum; } +EXPORT_SYMBOL(nr_running); /* * Check if only the current task is running on the CPU. diff --git a/kernel/signal.c b/kernel/signal.c index 6164d658372e..6884863dd751 100644 --- a/kernel/signal.c +++ b/kernel/signal.c @@ -59,6 +59,7 @@ #undef CREATE_TRACE_POINTS #include +#include /* * SLAB caches for signal bits. */ @@ -994,6 +995,7 @@ static void complete_signal(int sig, struct task_struct *p, enum pid_type type) { struct signal_struct *signal = p->signal; struct task_struct *t; + bool wake; /* * Now find a thread we can wake up to take the signal off the queue. @@ -1053,7 +1055,10 @@ static void complete_signal(int sig, struct task_struct *p, enum pid_type type) trace_android_vh_exit_signal(t); task_clear_jobctl_pending(t, JOBCTL_PENDING_MASK); sigaddset(&t->pending.signal, SIGKILL); - signal_wake_up(t, 1); + wake = true; + trace_android_vh_exit_signal_whether_wake(t, &wake); + if (wake) + signal_wake_up(t, 1); } while_each_thread(p, t); return; } diff --git a/kernel/time/posix-timers.c b/kernel/time/posix-timers.c index 808a247205a9..ed3c4a954398 100644 --- a/kernel/time/posix-timers.c +++ b/kernel/time/posix-timers.c @@ -1037,27 +1037,52 @@ retry_delete: } /* - * return timer owned by the process, used by exit_itimers + * Delete a timer if it is armed, remove it from the hash and schedule it + * for RCU freeing. */ static void itimer_delete(struct k_itimer *timer) { -retry_delete: - spin_lock_irq(&timer->it_lock); + unsigned long flags; + /* + * irqsave is required to make timer_wait_running() work. + */ + spin_lock_irqsave(&timer->it_lock, flags); + +retry_delete: + /* + * Even if the timer is not longer accessible from other tasks + * it still might be armed and queued in the underlying timer + * mechanism. Worse, that timer mechanism might run the expiry + * function concurrently. + */ if (timer_delete_hook(timer) == TIMER_RETRY) { - spin_unlock_irq(&timer->it_lock); + /* + * Timer is expired concurrently, prevent livelocks + * and pointless spinning on RT. + * + * timer_wait_running() drops timer::it_lock, which opens + * the possibility for another task to delete the timer. + * + * That's not possible here because this is invoked from + * do_exit() only for the last thread of the thread group. + * So no other task can access and delete that timer. + */ + if (WARN_ON_ONCE(timer_wait_running(timer, &flags) != timer)) + return; + goto retry_delete; } list_del(&timer->list); - spin_unlock_irq(&timer->it_lock); + spin_unlock_irqrestore(&timer->it_lock, flags); release_posix_timer(timer, IT_ID_SET); } /* - * This is called by do_exit or de_thread, only when nobody else can - * modify the signal->posix_timers list. Yet we need sighand->siglock - * to prevent the race with /proc/pid/timers. + * Invoked from do_exit() when the last thread of a thread group exits. + * At that point no other task can access the timers of the dying + * task anymore. */ void exit_itimers(struct task_struct *tsk) { @@ -1067,10 +1092,12 @@ void exit_itimers(struct task_struct *tsk) if (list_empty(&tsk->signal->posix_timers)) return; + /* Protect against concurrent read via /proc/$PID/timers */ spin_lock_irq(&tsk->sighand->siglock); list_replace_init(&tsk->signal->posix_timers, &timers); spin_unlock_irq(&tsk->sighand->siglock); + /* The timers are not longer accessible via tsk::signal */ while (!list_empty(&timers)) { tmr = list_first_entry(&timers, struct k_itimer, list); itimer_delete(tmr); diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c index ca606f878862..0aaff38a2d8e 100644 --- a/kernel/trace/ftrace.c +++ b/kernel/trace/ftrace.c @@ -3191,6 +3191,22 @@ static int ftrace_allocate_records(struct ftrace_page *pg, int count) return cnt; } +static void ftrace_free_pages(struct ftrace_page *pages) +{ + struct ftrace_page *pg = pages; + + while (pg) { + if (pg->records) { + free_pages((unsigned long)pg->records, pg->order); + ftrace_number_of_pages -= 1 << pg->order; + } + pages = pg->next; + kfree(pg); + pg = pages; + ftrace_number_of_groups--; + } +} + static struct ftrace_page * ftrace_allocate_pages(unsigned long num_to_init) { @@ -3229,17 +3245,7 @@ ftrace_allocate_pages(unsigned long num_to_init) return start_pg; free_pages: - pg = start_pg; - while (pg) { - if (pg->records) { - free_pages((unsigned long)pg->records, pg->order); - ftrace_number_of_pages -= 1 << pg->order; - } - start_pg = pg->next; - kfree(pg); - pg = start_pg; - ftrace_number_of_groups--; - } + ftrace_free_pages(start_pg); pr_info("ftrace: FAILED to allocate memory for functions\n"); return NULL; } @@ -6183,9 +6189,11 @@ static int ftrace_process_locs(struct module *mod, unsigned long *start, unsigned long *end) { + struct ftrace_page *pg_unuse = NULL; struct ftrace_page *start_pg; struct ftrace_page *pg; struct dyn_ftrace *rec; + unsigned long skipped = 0; unsigned long count; unsigned long *p; unsigned long addr; @@ -6239,8 +6247,10 @@ static int ftrace_process_locs(struct module *mod, * object files to satisfy alignments. * Skip any NULL pointers. */ - if (!addr) + if (!addr) { + skipped++; continue; + } end_offset = (pg->index+1) * sizeof(pg->records[0]); if (end_offset > PAGE_SIZE << pg->order) { @@ -6254,8 +6264,10 @@ static int ftrace_process_locs(struct module *mod, rec->ip = addr; } - /* We should have used all pages */ - WARN_ON(pg->next); + if (pg->next) { + pg_unuse = pg->next; + pg->next = NULL; + } /* Assign the last page to ftrace_pages */ ftrace_pages = pg; @@ -6277,6 +6289,11 @@ static int ftrace_process_locs(struct module *mod, out: mutex_unlock(&ftrace_lock); + /* We should have used all pages unless we skipped some */ + if (pg_unuse) { + WARN_ON(!skipped); + ftrace_free_pages(pg_unuse); + } return ret; } diff --git a/kernel/trace/ring_buffer.c b/kernel/trace/ring_buffer.c index 83046c6443f1..ceeba8bf1265 100644 --- a/kernel/trace/ring_buffer.c +++ b/kernel/trace/ring_buffer.c @@ -5196,28 +5196,34 @@ unsigned long ring_buffer_size(struct trace_buffer *buffer, int cpu) } EXPORT_SYMBOL_GPL(ring_buffer_size); +static void rb_clear_buffer_page(struct buffer_page *page) +{ + local_set(&page->write, 0); + local_set(&page->entries, 0); + rb_init_page(page->page); + page->read = 0; +} + static void rb_reset_cpu(struct ring_buffer_per_cpu *cpu_buffer) { + struct buffer_page *page; + rb_head_page_deactivate(cpu_buffer); cpu_buffer->head_page = list_entry(cpu_buffer->pages, struct buffer_page, list); - local_set(&cpu_buffer->head_page->write, 0); - local_set(&cpu_buffer->head_page->entries, 0); - local_set(&cpu_buffer->head_page->page->commit, 0); - - cpu_buffer->head_page->read = 0; + rb_clear_buffer_page(cpu_buffer->head_page); + list_for_each_entry(page, cpu_buffer->pages, list) { + rb_clear_buffer_page(page); + } cpu_buffer->tail_page = cpu_buffer->head_page; cpu_buffer->commit_page = cpu_buffer->head_page; INIT_LIST_HEAD(&cpu_buffer->reader_page->list); INIT_LIST_HEAD(&cpu_buffer->new_pages); - local_set(&cpu_buffer->reader_page->write, 0); - local_set(&cpu_buffer->reader_page->entries, 0); - local_set(&cpu_buffer->reader_page->page->commit, 0); - cpu_buffer->reader_page->read = 0; + rb_clear_buffer_page(cpu_buffer->reader_page); local_set(&cpu_buffer->entries_bytes, 0); local_set(&cpu_buffer->overrun, 0); diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c index 8a6bf4b58efb..9ff09852bfa6 100644 --- a/kernel/trace/trace.c +++ b/kernel/trace/trace.c @@ -6661,6 +6661,7 @@ static int tracing_release_pipe(struct inode *inode, struct file *file) free_cpumask_var(iter->started); kfree(iter->fmt); + kfree(iter->temp); mutex_destroy(&iter->mutex); kfree(iter); @@ -8024,7 +8025,7 @@ static const struct file_operations tracing_err_log_fops = { .open = tracing_err_log_open, .write = tracing_err_log_write, .read = seq_read, - .llseek = seq_lseek, + .llseek = tracing_lseek, .release = tracing_err_log_release, }; diff --git a/kernel/trace/trace_eprobe.c b/kernel/trace/trace_eprobe.c index 9806316af127..085f056e66f1 100644 --- a/kernel/trace/trace_eprobe.c +++ b/kernel/trace/trace_eprobe.c @@ -725,6 +725,7 @@ static int enable_trace_eprobe(struct trace_event_call *call, struct trace_eprobe *ep; bool enabled; int ret = 0; + int cnt = 0; tp = trace_probe_primary_from_call(call); if (WARN_ON_ONCE(!tp)) @@ -748,12 +749,25 @@ static int enable_trace_eprobe(struct trace_event_call *call, if (ret) break; enabled = true; + cnt++; } if (ret) { /* Failed to enable one of them. Roll back all */ - if (enabled) - disable_eprobe(ep, file->tr); + if (enabled) { + /* + * It's a bug if one failed for something other than memory + * not being available but another eprobe succeeded. + */ + WARN_ON_ONCE(ret != -ENOMEM); + + list_for_each_entry(pos, trace_probe_probe_list(tp), list) { + ep = container_of(pos, struct trace_eprobe, tp); + disable_eprobe(ep, file->tr); + if (!--cnt) + break; + } + } if (file) trace_probe_remove_file(tp, file); else diff --git a/kernel/trace/trace_events_hist.c b/kernel/trace/trace_events_hist.c index f1c5e8ca9664..bebaa6a66d35 100644 --- a/kernel/trace/trace_events_hist.c +++ b/kernel/trace/trace_events_hist.c @@ -6299,13 +6299,16 @@ static int event_hist_trigger_func(struct event_command *cmd_ops, if (get_named_trigger_data(trigger_data)) goto enable; - if (has_hist_vars(hist_data)) - save_hist_vars(hist_data); - ret = create_actions(hist_data); if (ret) goto out_unreg; + if (has_hist_vars(hist_data) || hist_data->n_var_refs) { + ret = save_hist_vars(hist_data); + if (ret) + goto out_unreg; + } + ret = tracing_map_init(hist_data->map); if (ret) goto out_unreg; diff --git a/kernel/trace/trace_probe_tmpl.h b/kernel/trace/trace_probe_tmpl.h index b3bdb8ddb862..c293a607d536 100644 --- a/kernel/trace/trace_probe_tmpl.h +++ b/kernel/trace/trace_probe_tmpl.h @@ -143,6 +143,8 @@ stage3: array: /* the last stage: Loop on array */ if (code->op == FETCH_OP_LP_ARRAY) { + if (ret < 0) + ret = 0; total += ret; if (++i < code->param) { code = s3; @@ -204,11 +206,13 @@ store_trace_args(void *data, struct trace_probe *tp, void *rec, if (unlikely(arg->dynamic)) *dl = make_data_loc(maxlen, dyndata - base); ret = process_fetch_insn(arg->code, rec, dl, base); - if (unlikely(ret < 0 && arg->dynamic)) { - *dl = make_data_loc(0, dyndata - base); - } else { - dyndata += ret; - maxlen -= ret; + if (arg->dynamic) { + if (unlikely(ret < 0)) { + *dl = make_data_loc(0, dyndata - base); + } else { + dyndata += ret; + maxlen -= ret; + } } } } diff --git a/kernel/watchdog_hld.c b/kernel/watchdog_hld.c index 247bf0b1582c..1e8a49dc956e 100644 --- a/kernel/watchdog_hld.c +++ b/kernel/watchdog_hld.c @@ -114,14 +114,14 @@ static void watchdog_overflow_callback(struct perf_event *event, /* Ensure the watchdog never gets throttled */ event->hw.interrupts = 0; + if (!watchdog_check_timestamp()) + return; + if (__this_cpu_read(watchdog_nmi_touch) == true) { __this_cpu_write(watchdog_nmi_touch, false); return; } - if (!watchdog_check_timestamp()) - return; - /* check for a hardlockup * This is done by making sure our timer interrupt * is incrementing. The timer interrupt should have diff --git a/kernel/workqueue.c b/kernel/workqueue.c index d260a3f22955..06c52b36bcfc 100644 --- a/kernel/workqueue.c +++ b/kernel/workqueue.c @@ -704,12 +704,17 @@ static void clear_work_data(struct work_struct *work) set_work_data(work, WORK_STRUCT_NO_POOL, 0); } +static inline struct pool_workqueue *work_struct_pwq(unsigned long data) +{ + return (struct pool_workqueue *)(data & WORK_STRUCT_WQ_DATA_MASK); +} + static struct pool_workqueue *get_work_pwq(struct work_struct *work) { unsigned long data = atomic_long_read(&work->data); if (data & WORK_STRUCT_PWQ) - return (void *)(data & WORK_STRUCT_WQ_DATA_MASK); + return work_struct_pwq(data); else return NULL; } @@ -737,8 +742,7 @@ static struct worker_pool *get_work_pool(struct work_struct *work) assert_rcu_or_pool_mutex(); if (data & WORK_STRUCT_PWQ) - return ((struct pool_workqueue *) - (data & WORK_STRUCT_WQ_DATA_MASK))->pool; + return work_struct_pwq(data)->pool; pool_id = data >> WORK_OFFQ_POOL_SHIFT; if (pool_id == WORK_OFFQ_POOL_NONE) @@ -759,8 +763,7 @@ static int get_work_pool_id(struct work_struct *work) unsigned long data = atomic_long_read(&work->data); if (data & WORK_STRUCT_PWQ) - return ((struct pool_workqueue *) - (data & WORK_STRUCT_WQ_DATA_MASK))->pool->id; + return work_struct_pwq(data)->pool->id; return data >> WORK_OFFQ_POOL_SHIFT; } diff --git a/lib/test_firmware.c b/lib/test_firmware.c index 2a4078946a3f..b64f87f4f228 100644 --- a/lib/test_firmware.c +++ b/lib/test_firmware.c @@ -183,7 +183,7 @@ static int __kstrncpy(char **dst, const char *name, size_t count, gfp_t gfp) { *dst = kstrndup(name, count, gfp); if (!*dst) - return -ENOSPC; + return -ENOMEM; return count; } @@ -606,7 +606,7 @@ static ssize_t trigger_request_store(struct device *dev, name = kstrndup(buf, count, GFP_KERNEL); if (!name) - return -ENOSPC; + return -ENOMEM; pr_info("loading '%s'\n", name); @@ -654,7 +654,7 @@ static ssize_t trigger_request_platform_store(struct device *dev, name = kstrndup(buf, count, GFP_KERNEL); if (!name) - return -ENOSPC; + return -ENOMEM; pr_info("inserting test platform fw '%s'\n", name); efi_embedded_fw.name = name; @@ -707,7 +707,7 @@ static ssize_t trigger_async_request_store(struct device *dev, name = kstrndup(buf, count, GFP_KERNEL); if (!name) - return -ENOSPC; + return -ENOMEM; pr_info("loading '%s'\n", name); @@ -752,7 +752,7 @@ static ssize_t trigger_custom_fallback_store(struct device *dev, name = kstrndup(buf, count, GFP_KERNEL); if (!name) - return -ENOSPC; + return -ENOMEM; pr_info("loading '%s' using custom fallback mechanism\n", name); @@ -803,7 +803,7 @@ static int test_fw_run_batch_request(void *data) test_buf = kzalloc(TEST_FIRMWARE_BUF_SIZE, GFP_KERNEL); if (!test_buf) - return -ENOSPC; + return -ENOMEM; if (test_fw_config->partial) req->rc = request_partial_firmware_into_buf diff --git a/lib/ts_bm.c b/lib/ts_bm.c index 4cf250031f0f..352ae837e031 100644 --- a/lib/ts_bm.c +++ b/lib/ts_bm.c @@ -60,10 +60,12 @@ static unsigned int bm_find(struct ts_config *conf, struct ts_state *state) struct ts_bm *bm = ts_config_priv(conf); unsigned int i, text_len, consumed = state->offset; const u8 *text; - int shift = bm->patlen - 1, bs; + int bs; const u8 icase = conf->flags & TS_IGNORECASE; for (;;) { + int shift = bm->patlen - 1; + text_len = conf->get_next_block(consumed, &text, conf, state); if (unlikely(text_len == 0)) diff --git a/mm/cma.c b/mm/cma.c index 812c3a936156..9d491328592f 100644 --- a/mm/cma.c +++ b/mm/cma.c @@ -445,6 +445,12 @@ struct page *cma_alloc(struct cma *cma, unsigned long count, int ret = -ENOMEM; int num_attempts = 0; int max_retries = 5; + bool bypass = false; + + trace_android_vh_cma_alloc_bypass(cma, count, align, no_warn, + &page, &bypass); + if (bypass) + return page; if (!cma || !cma->count || !cma->bitmap) goto out; diff --git a/mm/compaction.c b/mm/compaction.c index 2c024dc73c7d..98630c07d591 100644 --- a/mm/compaction.c +++ b/mm/compaction.c @@ -1601,6 +1601,7 @@ static void isolate_freepages(struct compact_control *cc) unsigned long low_pfn; /* lowest pfn scanner is able to scan */ struct list_head *freelist = &cc->freepages; unsigned int stride; + bool bypass = false; /* Try a small search of the free lists for a candidate */ isolate_start_pfn = fast_isolate_freepages(cc); @@ -1656,6 +1657,10 @@ static void isolate_freepages(struct compact_control *cc) if (!isolation_suitable(cc, page)) continue; + trace_android_vh_isolate_freepages(cc, page, &bypass); + if (bypass) + continue; + /* Found a block suitable for isolating free pages from. */ nr_isolated = isolate_freepages_block(cc, &isolate_start_pfn, block_end_pfn, freelist, stride, false); diff --git a/mm/damon/paddr.c b/mm/damon/paddr.c index 5e8244f65a1a..a524b28a6496 100644 --- a/mm/damon/paddr.c +++ b/mm/damon/paddr.c @@ -28,9 +28,9 @@ static bool __damon_pa_mkold(struct page *page, struct vm_area_struct *vma, while (page_vma_mapped_walk(&pvmw)) { addr = pvmw.address; if (pvmw.pte) - damon_ptep_mkold(pvmw.pte, vma->vm_mm, addr); + damon_ptep_mkold(pvmw.pte, vma, addr); else - damon_pmdp_mkold(pvmw.pmd, vma->vm_mm, addr); + damon_pmdp_mkold(pvmw.pmd, vma, addr); } return true; } diff --git a/mm/damon/prmtv-common.c b/mm/damon/prmtv-common.c index 92a04f5831d6..f6c02a4c7852 100644 --- a/mm/damon/prmtv-common.c +++ b/mm/damon/prmtv-common.c @@ -33,7 +33,7 @@ struct page *damon_get_page(unsigned long pfn) return page; } -void damon_ptep_mkold(pte_t *pte, struct mm_struct *mm, unsigned long addr) +void damon_ptep_mkold(pte_t *pte, struct vm_area_struct *vma, unsigned long addr) { bool referenced = false; struct page *page = damon_get_page(pte_pfn(*pte)); @@ -41,13 +41,11 @@ void damon_ptep_mkold(pte_t *pte, struct mm_struct *mm, unsigned long addr) if (!page) return; - if (pte_young(*pte)) { + if (ptep_test_and_clear_young(vma, addr, pte)) referenced = true; - *pte = pte_mkold(*pte); - } #ifdef CONFIG_MMU_NOTIFIER - if (mmu_notifier_clear_young(mm, addr, addr + PAGE_SIZE)) + if (mmu_notifier_clear_young(vma->vm_mm, addr, addr + PAGE_SIZE)) referenced = true; #endif /* CONFIG_MMU_NOTIFIER */ @@ -58,7 +56,7 @@ void damon_ptep_mkold(pte_t *pte, struct mm_struct *mm, unsigned long addr) put_page(page); } -void damon_pmdp_mkold(pmd_t *pmd, struct mm_struct *mm, unsigned long addr) +void damon_pmdp_mkold(pmd_t *pmd, struct vm_area_struct *vma, unsigned long addr) { #ifdef CONFIG_TRANSPARENT_HUGEPAGE bool referenced = false; @@ -67,13 +65,11 @@ void damon_pmdp_mkold(pmd_t *pmd, struct mm_struct *mm, unsigned long addr) if (!page) return; - if (pmd_young(*pmd)) { + if (pmdp_test_and_clear_young(vma, addr, pmd)) referenced = true; - *pmd = pmd_mkold(*pmd); - } #ifdef CONFIG_MMU_NOTIFIER - if (mmu_notifier_clear_young(mm, addr, + if (mmu_notifier_clear_young(vma->vm_mm, addr, addr + ((1UL) << HPAGE_PMD_SHIFT))) referenced = true; #endif /* CONFIG_MMU_NOTIFIER */ diff --git a/mm/damon/prmtv-common.h b/mm/damon/prmtv-common.h index e790cb5f8fe0..0697e1e21e1c 100644 --- a/mm/damon/prmtv-common.h +++ b/mm/damon/prmtv-common.h @@ -9,8 +9,8 @@ struct page *damon_get_page(unsigned long pfn); -void damon_ptep_mkold(pte_t *pte, struct mm_struct *mm, unsigned long addr); -void damon_pmdp_mkold(pmd_t *pmd, struct mm_struct *mm, unsigned long addr); +void damon_ptep_mkold(pte_t *pte, struct vm_area_struct *vma, unsigned long addr); +void damon_pmdp_mkold(pmd_t *pmd, struct vm_area_struct *vma, unsigned long addr); int damon_pageout_score(struct damon_ctx *c, struct damon_region *r, struct damos *s); diff --git a/mm/damon/vaddr.c b/mm/damon/vaddr.c index c0dec53b2330..6e8ffc0b52b1 100644 --- a/mm/damon/vaddr.c +++ b/mm/damon/vaddr.c @@ -381,7 +381,7 @@ static int damon_mkold_pmd_entry(pmd_t *pmd, unsigned long addr, } if (pmd_huge(*pmd)) { - damon_pmdp_mkold(pmd, walk->mm, addr); + damon_pmdp_mkold(pmd, walk->vma, addr); spin_unlock(ptl); return 0; } @@ -393,7 +393,7 @@ static int damon_mkold_pmd_entry(pmd_t *pmd, unsigned long addr, pte = pte_offset_map_lock(walk->mm, pmd, addr, &ptl); if (!pte_present(*pte)) goto out; - damon_ptep_mkold(pte, walk->mm, addr); + damon_ptep_mkold(pte, walk->vma, addr); out: pte_unmap_unlock(pte, ptl); return 0; diff --git a/mm/filemap.c b/mm/filemap.c index c6613f4453d6..279380cf6280 100644 --- a/mm/filemap.c +++ b/mm/filemap.c @@ -2611,6 +2611,7 @@ ssize_t filemap_read(struct kiocb *iocb, struct iov_iter *iter, int i, error = 0; bool writably_mapped; loff_t isize, end_offset; + loff_t last_pos = ra->prev_pos; if (unlikely(iocb->ki_pos >= inode->i_sb->s_maxbytes)) return 0; @@ -2659,7 +2660,7 @@ ssize_t filemap_read(struct kiocb *iocb, struct iov_iter *iter, * mark it as accessed the first time. */ if (iocb->ki_pos >> PAGE_SHIFT != - ra->prev_pos >> PAGE_SHIFT) + last_pos >> PAGE_SHIFT) mark_page_accessed(pvec.pages[0]); for (i = 0; i < pagevec_count(&pvec); i++) { @@ -2690,7 +2691,7 @@ ssize_t filemap_read(struct kiocb *iocb, struct iov_iter *iter, already_read += copied; iocb->ki_pos += copied; - ra->prev_pos = iocb->ki_pos; + last_pos = iocb->ki_pos; if (copied < bytes) { error = -EFAULT; @@ -2704,7 +2705,7 @@ put_pages: } while (iov_iter_count(iter) && iocb->ki_pos < isize && !error); file_accessed(filp); - + ra->prev_pos = last_pos; return already_read ? already_read : error; } EXPORT_SYMBOL_GPL(filemap_read); diff --git a/mm/huge_memory.c b/mm/huge_memory.c index cf93829f4d8c..884e1327187b 100644 --- a/mm/huge_memory.c +++ b/mm/huge_memory.c @@ -1720,18 +1720,21 @@ bool move_huge_pmd(struct vm_area_struct *vma, unsigned long old_addr, * or if prot_numa but THP migration is not supported * - HPAGE_PMD_NR if protections changed and TLB flush necessary */ -int change_huge_pmd(struct vm_area_struct *vma, pmd_t *pmd, - unsigned long addr, pgprot_t newprot, unsigned long cp_flags) +int change_huge_pmd(struct mmu_gather *tlb, struct vm_area_struct *vma, + pmd_t *pmd, unsigned long addr, pgprot_t newprot, + unsigned long cp_flags) { struct mm_struct *mm = vma->vm_mm; spinlock_t *ptl; - pmd_t entry; + pmd_t oldpmd, entry; bool preserve_write; int ret; bool prot_numa = cp_flags & MM_CP_PROT_NUMA; bool uffd_wp = cp_flags & MM_CP_UFFD_WP; bool uffd_wp_resolve = cp_flags & MM_CP_UFFD_WP_RESOLVE; + tlb_change_page_size(tlb, HPAGE_PMD_SIZE); + if (prot_numa && !thp_migration_supported()) return 1; @@ -1795,12 +1798,12 @@ int change_huge_pmd(struct vm_area_struct *vma, pmd_t *pmd, * The race makes MADV_DONTNEED miss the huge pmd and don't clear it * which may break userspace. * - * pmdp_invalidate() is required to make sure we don't miss + * pmdp_invalidate_ad() is required to make sure we don't miss * dirty/young flags set by hardware. */ - entry = pmdp_invalidate(vma, addr, pmd); + oldpmd = pmdp_invalidate_ad(vma, addr, pmd); - entry = pmd_modify(entry, newprot); + entry = pmd_modify(oldpmd, newprot); if (preserve_write) entry = pmd_mk_savedwrite(entry); if (uffd_wp) { @@ -1816,6 +1819,10 @@ int change_huge_pmd(struct vm_area_struct *vma, pmd_t *pmd, } ret = HPAGE_PMD_NR; set_pmd_at(mm, addr, pmd, entry); + + if (huge_pmd_needs_flush(oldpmd, entry)) + tlb_flush_pmd_range(tlb, addr, HPAGE_PMD_SIZE); + BUG_ON(vma_is_anonymous(vma) && !preserve_write && pmd_write(entry)); unlock: spin_unlock(ptl); diff --git a/mm/memcontrol.c b/mm/memcontrol.c index 45a44b6f6dc4..c78b505aaa38 100644 --- a/mm/memcontrol.c +++ b/mm/memcontrol.c @@ -78,6 +78,7 @@ struct cgroup_subsys memory_cgrp_subsys __read_mostly; EXPORT_SYMBOL(memory_cgrp_subsys); struct mem_cgroup *root_mem_cgroup __read_mostly; +EXPORT_SYMBOL_GPL(root_mem_cgroup); /* Active memory cgroup to use from an interrupt context */ DEFINE_PER_CPU(struct mem_cgroup *, int_active_memcg); diff --git a/mm/memory.c b/mm/memory.c index 9f1cbcaebb8f..1558f4db7711 100644 --- a/mm/memory.c +++ b/mm/memory.c @@ -2905,10 +2905,16 @@ static inline int pte_unmap_same(struct mm_struct *mm, pmd_t *pmd, return same; } -static inline bool cow_user_page(struct page *dst, struct page *src, - struct vm_fault *vmf) +/* + * Return: + * 0: copied succeeded + * -EHWPOISON: copy failed due to hwpoison in source page + * -EAGAIN: copied failed (some other reason) + */ +static inline int cow_user_page(struct page *dst, struct page *src, + struct vm_fault *vmf) { - bool ret; + int ret; void *kaddr; void __user *uaddr; bool locked = false; @@ -2917,8 +2923,11 @@ static inline bool cow_user_page(struct page *dst, struct page *src, unsigned long addr = vmf->address; if (likely(src)) { - copy_user_highpage(dst, src, addr, vma); - return true; + if (copy_mc_user_highpage(dst, src, addr, vma)) { + memory_failure_queue(page_to_pfn(src), 0); + return -EHWPOISON; + } + return 0; } /* @@ -2945,7 +2954,7 @@ static inline bool cow_user_page(struct page *dst, struct page *src, * and update local tlb only */ update_mmu_tlb(vma, addr, vmf->pte); - ret = false; + ret = -EAGAIN; goto pte_unlock; } @@ -2970,7 +2979,7 @@ static inline bool cow_user_page(struct page *dst, struct page *src, if (!likely(pte_same(*vmf->pte, vmf->orig_pte))) { /* The PTE changed under us, update local tlb */ update_mmu_tlb(vma, addr, vmf->pte); - ret = false; + ret = -EAGAIN; goto pte_unlock; } @@ -2989,7 +2998,7 @@ warn: } } - ret = true; + ret = 0; pte_unlock: if (locked) @@ -3178,17 +3187,20 @@ static vm_fault_t wp_page_copy(struct vm_fault *vmf) if (!new_page) goto out; - if (!cow_user_page(new_page, old_page, vmf)) { + ret = cow_user_page(new_page, old_page, vmf); + if (ret) { /* * COW failed, if the fault was solved by other, * it's fine. If not, userspace would re-fault on * the same address and we will handle the fault * from the second attempt. + * The -EHWPOISON case will not be retried. */ put_page(new_page); if (old_page) put_page(old_page); - return 0; + + return ret == -EHWPOISON ? VM_FAULT_HWPOISON : 0; } } diff --git a/mm/mempolicy.c b/mm/mempolicy.c index 83f6c5737841..d290b840cbbb 100644 --- a/mm/mempolicy.c +++ b/mm/mempolicy.c @@ -104,6 +104,7 @@ #include #include +#include #include #include "internal.h" @@ -634,12 +635,18 @@ unlock: unsigned long change_prot_numa(struct vm_area_struct *vma, unsigned long addr, unsigned long end) { + struct mmu_gather tlb; int nr_updated; - nr_updated = change_protection(vma, addr, end, PAGE_NONE, MM_CP_PROT_NUMA); + tlb_gather_mmu(&tlb, vma->vm_mm); + + nr_updated = change_protection(&tlb, vma, addr, end, PAGE_NONE, + MM_CP_PROT_NUMA); if (nr_updated) count_vm_numa_events(NUMA_PTE_UPDATES, nr_updated); + tlb_finish_mmu(&tlb); + return nr_updated; } #else diff --git a/mm/migrate.c b/mm/migrate.c index 704e82ae98ae..33ad211f1c90 100644 --- a/mm/migrate.c +++ b/mm/migrate.c @@ -281,10 +281,14 @@ void remove_migration_ptes(struct page *old, struct page *new, bool locked) .arg = old, }; + trace_android_vh_set_page_migrating(new); + if (locked) rmap_walk_locked(new, &rwc); else rmap_walk(new, &rwc); + + trace_android_vh_clear_page_migrating(new); } /* diff --git a/mm/mprotect.c b/mm/mprotect.c index ba53529cdd5e..e7f055349581 100644 --- a/mm/mprotect.c +++ b/mm/mprotect.c @@ -32,12 +32,13 @@ #include #include #include +#include #include "internal.h" -static unsigned long change_pte_range(struct vm_area_struct *vma, pmd_t *pmd, - unsigned long addr, unsigned long end, pgprot_t newprot, - unsigned long cp_flags) +static unsigned long change_pte_range(struct mmu_gather *tlb, + struct vm_area_struct *vma, pmd_t *pmd, unsigned long addr, + unsigned long end, pgprot_t newprot, unsigned long cp_flags) { pte_t *pte, oldpte; spinlock_t *ptl; @@ -48,6 +49,8 @@ static unsigned long change_pte_range(struct vm_area_struct *vma, pmd_t *pmd, bool uffd_wp = cp_flags & MM_CP_UFFD_WP; bool uffd_wp_resolve = cp_flags & MM_CP_UFFD_WP_RESOLVE; + tlb_change_page_size(tlb, PAGE_SIZE); + /* * Can be called with only the mmap_lock for reading by * prot_numa so we must check the pmd isn't constantly @@ -138,6 +141,8 @@ static unsigned long change_pte_range(struct vm_area_struct *vma, pmd_t *pmd, ptent = pte_mkwrite(ptent); } ptep_modify_prot_commit(vma, addr, pte, oldpte, ptent); + if (pte_needs_flush(oldpte, ptent)) + tlb_flush_pte_range(tlb, addr, PAGE_SIZE); pages++; } else if (is_swap_pte(oldpte)) { swp_entry_t entry = pte_to_swp_entry(oldpte); @@ -219,9 +224,9 @@ static inline int pmd_none_or_clear_bad_unless_trans_huge(pmd_t *pmd) return 0; } -static inline unsigned long change_pmd_range(struct vm_area_struct *vma, - pud_t *pud, unsigned long addr, unsigned long end, - pgprot_t newprot, unsigned long cp_flags) +static inline unsigned long change_pmd_range(struct mmu_gather *tlb, + struct vm_area_struct *vma, pud_t *pud, unsigned long addr, + unsigned long end, pgprot_t newprot, unsigned long cp_flags) { pmd_t *pmd; unsigned long next; @@ -261,8 +266,12 @@ static inline unsigned long change_pmd_range(struct vm_area_struct *vma, if (next - addr != HPAGE_PMD_SIZE) { __split_huge_pmd(vma, pmd, addr, false, NULL); } else { - int nr_ptes = change_huge_pmd(vma, pmd, addr, - newprot, cp_flags); + /* + * change_huge_pmd() does not defer TLB flushes, + * so no need to propagate the tlb argument. + */ + int nr_ptes = change_huge_pmd(tlb, vma, pmd, + addr, newprot, cp_flags); if (nr_ptes) { if (nr_ptes == HPAGE_PMD_NR) { @@ -276,8 +285,8 @@ static inline unsigned long change_pmd_range(struct vm_area_struct *vma, } /* fall through, the trans huge pmd just split */ } - this_pages = change_pte_range(vma, pmd, addr, next, newprot, - cp_flags); + this_pages = change_pte_range(tlb, vma, pmd, addr, next, + newprot, cp_flags); pages += this_pages; next: cond_resched(); @@ -291,9 +300,9 @@ next: return pages; } -static inline unsigned long change_pud_range(struct vm_area_struct *vma, - p4d_t *p4d, unsigned long addr, unsigned long end, - pgprot_t newprot, unsigned long cp_flags) +static inline unsigned long change_pud_range(struct mmu_gather *tlb, + struct vm_area_struct *vma, p4d_t *p4d, unsigned long addr, + unsigned long end, pgprot_t newprot, unsigned long cp_flags) { pud_t *pud; unsigned long next; @@ -304,16 +313,16 @@ static inline unsigned long change_pud_range(struct vm_area_struct *vma, next = pud_addr_end(addr, end); if (pud_none_or_clear_bad(pud)) continue; - pages += change_pmd_range(vma, pud, addr, next, newprot, + pages += change_pmd_range(tlb, vma, pud, addr, next, newprot, cp_flags); } while (pud++, addr = next, addr != end); return pages; } -static inline unsigned long change_p4d_range(struct vm_area_struct *vma, - pgd_t *pgd, unsigned long addr, unsigned long end, - pgprot_t newprot, unsigned long cp_flags) +static inline unsigned long change_p4d_range(struct mmu_gather *tlb, + struct vm_area_struct *vma, pgd_t *pgd, unsigned long addr, + unsigned long end, pgprot_t newprot, unsigned long cp_flags) { p4d_t *p4d; unsigned long next; @@ -324,44 +333,40 @@ static inline unsigned long change_p4d_range(struct vm_area_struct *vma, next = p4d_addr_end(addr, end); if (p4d_none_or_clear_bad(p4d)) continue; - pages += change_pud_range(vma, p4d, addr, next, newprot, + pages += change_pud_range(tlb, vma, p4d, addr, next, newprot, cp_flags); } while (p4d++, addr = next, addr != end); return pages; } -static unsigned long change_protection_range(struct vm_area_struct *vma, - unsigned long addr, unsigned long end, pgprot_t newprot, - unsigned long cp_flags) +static unsigned long change_protection_range(struct mmu_gather *tlb, + struct vm_area_struct *vma, unsigned long addr, + unsigned long end, pgprot_t newprot, unsigned long cp_flags) { struct mm_struct *mm = vma->vm_mm; pgd_t *pgd; unsigned long next; - unsigned long start = addr; unsigned long pages = 0; BUG_ON(addr >= end); pgd = pgd_offset(mm, addr); - flush_cache_range(vma, addr, end); - inc_tlb_flush_pending(mm); + tlb_start_vma(tlb, vma); do { next = pgd_addr_end(addr, end); if (pgd_none_or_clear_bad(pgd)) continue; - pages += change_p4d_range(vma, pgd, addr, next, newprot, + pages += change_p4d_range(tlb, vma, pgd, addr, next, newprot, cp_flags); } while (pgd++, addr = next, addr != end); - /* Only flush the TLB if we actually modified any entries: */ - if (pages) - flush_tlb_range(vma, start, end); - dec_tlb_flush_pending(mm); + tlb_end_vma(tlb, vma); return pages; } -unsigned long change_protection(struct vm_area_struct *vma, unsigned long start, +unsigned long change_protection(struct mmu_gather *tlb, + struct vm_area_struct *vma, unsigned long start, unsigned long end, pgprot_t newprot, unsigned long cp_flags) { @@ -372,7 +377,7 @@ unsigned long change_protection(struct vm_area_struct *vma, unsigned long start, if (is_vm_hugetlb_page(vma)) pages = hugetlb_change_protection(vma, start, end, newprot); else - pages = change_protection_range(vma, start, end, newprot, + pages = change_protection_range(tlb, vma, start, end, newprot, cp_flags); return pages; @@ -406,8 +411,9 @@ static const struct mm_walk_ops prot_none_walk_ops = { }; int -mprotect_fixup(struct vm_area_struct *vma, struct vm_area_struct **pprev, - unsigned long start, unsigned long end, unsigned long newflags) +mprotect_fixup(struct mmu_gather *tlb, struct vm_area_struct *vma, + struct vm_area_struct **pprev, unsigned long start, + unsigned long end, unsigned long newflags) { struct mm_struct *mm = vma->vm_mm; unsigned long oldflags = vma->vm_flags; @@ -494,7 +500,7 @@ success: dirty_accountable = vma_wants_writenotify(vma, vma->vm_page_prot); vma_set_page_prot(vma); - change_protection(vma, start, end, vma->vm_page_prot, + change_protection(tlb, vma, start, end, vma->vm_page_prot, dirty_accountable ? MM_CP_DIRTY_ACCT : 0); /* @@ -528,6 +534,7 @@ static int do_mprotect_pkey(unsigned long start, size_t len, const int grows = prot & (PROT_GROWSDOWN|PROT_GROWSUP); const bool rier = (current->personality & READ_IMPLIES_EXEC) && (prot & PROT_READ); + struct mmu_gather tlb; start = untagged_addr(start); @@ -584,6 +591,7 @@ static int do_mprotect_pkey(unsigned long start, size_t len, if (start > vma->vm_start) prev = vma; + tlb_gather_mmu(&tlb, current->mm); for (nstart = start ; ; ) { unsigned long mask_off_old_flags; unsigned long newflags; @@ -610,18 +618,18 @@ static int do_mprotect_pkey(unsigned long start, size_t len, /* newflags >> 4 shift VM_MAY% in place of VM_% */ if ((newflags & ~(newflags >> 4)) & VM_ACCESS_FLAGS) { error = -EACCES; - goto out; + break; } /* Allow architectures to sanity-check the new flags */ if (!arch_validate_flags(newflags)) { error = -EINVAL; - goto out; + break; } error = security_file_mprotect(vma, reqprot, prot); if (error) - goto out; + break; tmp = vma->vm_end; if (tmp > end) @@ -630,27 +638,28 @@ static int do_mprotect_pkey(unsigned long start, size_t len, if (vma->vm_ops && vma->vm_ops->mprotect) { error = vma->vm_ops->mprotect(vma, nstart, tmp, newflags); if (error) - goto out; + break; } - error = mprotect_fixup(vma, &prev, nstart, tmp, newflags); + error = mprotect_fixup(&tlb, vma, &prev, nstart, tmp, newflags); if (error) - goto out; + break; nstart = tmp; if (nstart < prev->vm_end) nstart = prev->vm_end; if (nstart >= end) - goto out; + break; vma = prev->vm_next; if (!vma || vma->vm_start != nstart) { error = -ENOMEM; - goto out; + break; } prot = reqprot; } + tlb_finish_mmu(&tlb); out: mmap_write_unlock(current->mm); return error; diff --git a/mm/page_alloc.c b/mm/page_alloc.c index 7418769f3d59..c94aa620ff27 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c @@ -83,6 +83,8 @@ #include "shuffle.h" #include "page_reporting.h" +EXPORT_TRACEPOINT_SYMBOL_GPL(mm_page_alloc); + /* Free Page Internal flags: for internal, non-pcp variants of free_pages(). */ typedef int __bitwise fpi_t; @@ -3606,7 +3608,7 @@ void free_unref_page(struct page *page, unsigned int order) struct per_cpu_pages *pcp; struct zone *zone; unsigned long pfn = page_to_pfn(page); - int migratetype; + int migratetype, pcpmigratetype; bool pcp_skip_cma_pages = false; bool skip_free_unref_page = false; @@ -3621,11 +3623,11 @@ void free_unref_page(struct page *page, unsigned int order) /* * We only track unmovable, reclaimable movable, and CMA on pcp lists. * Place ISOLATE pages on the isolated list because they are being - * offlined but treat HIGHATOMIC as movable pages so we can get those - * areas back if necessary. Otherwise, we may have to free + * offlined but treat HIGHATOMIC and CMA as movable pages so we can + * get those areas back if necessary. Otherwise, we may have to free * excessively into the page allocator */ - migratetype = get_pcppage_migratetype(page); + migratetype = pcpmigratetype = get_pcppage_migratetype(page); if (unlikely(migratetype >= MIGRATE_PCPTYPES)) { trace_android_vh_pcplist_add_cma_pages_bypass(migratetype, &pcp_skip_cma_pages); @@ -3634,14 +3636,14 @@ void free_unref_page(struct page *page, unsigned int order) free_one_page(page_zone(page), page, pfn, order, migratetype, FPI_NONE); return; } - migratetype = MIGRATE_MOVABLE; + pcpmigratetype = MIGRATE_MOVABLE; } zone = page_zone(page); pcp_trylock_prepare(UP_flags); pcp = pcp_spin_trylock_irqsave(zone_per_cpu_pageset(zone), flags); if (pcp) { - free_unref_page_commit(zone, pcp, page, pfn, migratetype, order); + free_unref_page_commit(zone, pcp, page, pfn, pcpmigratetype, order); pcp_spin_unlock_irqrestore(pcp, flags); } else { free_one_page(zone, page, pfn, order, migratetype, FPI_NONE); @@ -5740,6 +5742,7 @@ struct page *__alloc_pages(gfp_t gfp, unsigned int order, int preferred_nid, gfp_t alloc_gfp; /* The gfp_t that was actually used for allocation */ struct alloc_context ac = { }; + trace_android_vh_alloc_pages_entry(&gfp, order, preferred_nid, nodemask); /* * There are several places where we assume that the order value is sane * so bail out early if the request is out of bound. diff --git a/mm/page_owner.c b/mm/page_owner.c index a77f82a873a1..25d2405407b9 100644 --- a/mm/page_owner.c +++ b/mm/page_owner.c @@ -33,6 +33,7 @@ struct page_owner { static bool page_owner_enabled = false; DEFINE_STATIC_KEY_FALSE(page_owner_inited); +EXPORT_SYMBOL_GPL(page_owner_inited); static depot_stack_handle_t dummy_handle; static depot_stack_handle_t failure_handle; @@ -205,6 +206,7 @@ noinline void __set_page_owner(struct page *page, unsigned int order, __set_page_owner_handle(page_ext, handle, order, gfp_mask); page_ext_put(page_ext); } +EXPORT_SYMBOL_GPL(__set_page_owner); void __set_page_owner_migrate_reason(struct page *page, int reason) { diff --git a/mm/pgtable-generic.c b/mm/pgtable-generic.c index 4e640baf9794..b0ce6c7391bf 100644 --- a/mm/pgtable-generic.c +++ b/mm/pgtable-generic.c @@ -200,6 +200,14 @@ pmd_t pmdp_invalidate(struct vm_area_struct *vma, unsigned long address, } #endif +#ifndef __HAVE_ARCH_PMDP_INVALIDATE_AD +pmd_t pmdp_invalidate_ad(struct vm_area_struct *vma, unsigned long address, + pmd_t *pmdp) +{ + return pmdp_invalidate(vma, address, pmdp); +} +#endif + #ifndef pmdp_collapse_flush pmd_t pmdp_collapse_flush(struct vm_area_struct *vma, unsigned long address, pmd_t *pmdp) diff --git a/mm/rmap.c b/mm/rmap.c index 1e08813fada3..469f45027f7b 100644 --- a/mm/rmap.c +++ b/mm/rmap.c @@ -930,6 +930,7 @@ int page_referenced(struct page *page, return rwc.contended ? -1 : pra.referenced; } +EXPORT_SYMBOL_GPL(page_referenced); static bool page_mkclean_one(struct page *page, struct vm_area_struct *vma, unsigned long address, void *arg) @@ -2066,10 +2067,14 @@ void try_to_migrate(struct page *page, enum ttu_flags flags) if (!PageKsm(page) && PageAnon(page)) rwc.invalid_vma = invalid_migration_vma; + trace_android_vh_set_page_migrating(page); + if (flags & TTU_RMAP_LOCKED) rmap_walk_locked(page, &rwc); else rmap_walk(page, &rwc); + + trace_android_vh_clear_page_migrating(page); } /* diff --git a/mm/shmem.c b/mm/shmem.c index 55c837973f90..3e7e0b7a23b3 100644 --- a/mm/shmem.c +++ b/mm/shmem.c @@ -4044,7 +4044,7 @@ static struct file_system_type shmem_fs_type = { .name = "tmpfs", .init_fs_context = ramfs_init_fs_context, .parameters = ramfs_fs_parameters, - .kill_sb = kill_litter_super, + .kill_sb = ramfs_kill_sb, .fs_flags = FS_USERNS_MOUNT, }; diff --git a/mm/userfaultfd.c b/mm/userfaultfd.c index caa13abe0c56..cb146100c5e4 100644 --- a/mm/userfaultfd.c +++ b/mm/userfaultfd.c @@ -16,6 +16,7 @@ #include #include #include +#include #include "internal.h" static __always_inline @@ -686,6 +687,7 @@ int mwriteprotect_range(struct mm_struct *dst_mm, unsigned long start, atomic_t *mmap_changing) { struct vm_area_struct *dst_vma; + struct mmu_gather tlb; pgprot_t newprot; int err; @@ -727,8 +729,10 @@ int mwriteprotect_range(struct mm_struct *dst_mm, unsigned long start, else newprot = vm_get_page_prot(dst_vma->vm_flags); - change_protection(dst_vma, start, start + len, newprot, + tlb_gather_mmu(&tlb, dst_mm); + change_protection(&tlb, dst_vma, start, start + len, newprot, enable_wp ? MM_CP_UFFD_WP : MM_CP_UFFD_WP_RESOLVE); + tlb_finish_mmu(&tlb); err = 0; out_unlock: diff --git a/modules.list.msm.kalama.lu b/modules.list.msm.kalama.lu new file mode 100644 index 000000000000..2f51ba8ae486 --- /dev/null +++ b/modules.list.msm.kalama.lu @@ -0,0 +1,100 @@ +qcom_wdt_core.ko +gh_virt_wdt.ko +qcom_cpu_vendor_hooks.ko +clk-rpmh.ko +gcc-kalama.ko +icc-rpmh.ko +camcc-kalama.ko +qcom_ipcc.ko +qcom_ipc_logging.ko +qcom-pdc.ko +thermal_minidump.ko +qcom_tsens.ko +rpmh-regulator.ko +bwmon.ko +qcom-cpufreq-hw.ko +sched-walt.ko +sched-walt-debug.ko +thermal_pause.ko +cpu_hotplug.ko +clk-dummy.ko +clk-qcom.ko +cmd-db.ko +cqhci.ko +crypto-qti-common.ko +crypto-qti-hwkm.ko +dcc_v2.ko +dcvs_fp.ko +debug-regulator.ko +dispcc-kalama.ko +tcsrcc-kalama.ko +videocc-kalama.ko +gdsc-regulator.ko +gh_arm_drv.ko +gh_ctrl.ko +gh_dbl.ko +gh_msgq.ko +gh_rm_drv.ko +gunyah.ko +mdt_loader.ko +hwkm.ko +icc-bcm-voter.ko +icc-debug.ko +iommu-logger.ko +llcc-qcom.ko +mem-hooks.ko +mem_buf_dev.ko +mem_buf_msgq.ko +mem_buf.ko +memory_dump_v2.ko +minidump.ko +msm_dma_iommu_mapping.ko +pinctrl-kalama.ko +qnoc-kalama.ko +msm_rtb.ko +ns.ko +nvmem_qcom-spmi-sdam.ko +phy-qcom-ufs.ko +phy-qcom-ufs-qmp-v4-kalama.ko +phy-qcom-ufs-qrbtc-sdm845.ko +pinctrl-msm.ko +proxy-consumer.ko +qcom-dcvs.ko +qcom-dload-mode.ko +qcom_dma_heaps.ko +gic_intr_routing.ko +qcom_hwspinlock.ko +qcom_logbuf_vh.ko +qcom_iommu_util.ko +qcom_llcc_pmu.ko +qcom-pmu-lib.ko +pmu_vendor.ko +pmu_scmi.ko +qcom-spmi-pmic.ko +spmi-pmic-arb.ko +qcom-reboot-reason.ko +qcom_rpmh.ko +qcom-scm.ko +qnoc-qos.ko +qrtr.ko +qti-regmap-debugfs.ko +regmap-spmi.ko +rtc-pm8xxx.ko +secure_buffer.ko +smem.ko +socinfo.ko +stub-regulator.ko +qcom_aoss.ko +msm_qmp.ko +tmecom-intf.ko +ufs_qcom.ko +ufshcd-crypto-qti.ko +arm_smmu.ko +mem-offline.ko +sdhci-msm.ko +qcom_rimps.ko +c1dcvs_vendor.ko +c1dcvs_scmi.ko +bcl_pmic5.ko +nvme-core.ko +nvme.ko diff --git a/modules.list.msm.qcs605 b/modules.list.msm.qcs605 new file mode 100644 index 000000000000..df9dece68d90 --- /dev/null +++ b/modules.list.msm.qcs605 @@ -0,0 +1,79 @@ +qcom_wdt_core.ko +qcom_cpu_vendor_hooks.ko +clk-rpmh.ko +gcc-sdm845.ko +icc-rpmh.ko +qcom_ipcc.ko +qcom_ipc_logging.ko +qcom-pdc.ko +rpmh-regulator.ko +bwmon.ko +qcom-cpufreq-hw.ko +sched-walt.ko +clk-dummy.ko +clk-qcom.ko +cmd-db.ko +cqhci.ko +crypto-qti-common.ko +crypto-qti-hwkm.ko +dcc_v2.ko +dcvs_fp.ko +debug-regulator.ko +gdsc-regulator.ko +smp2p.ko +rproc_qcom_common.ko +qcom_pil_info.ko +qcom_ramdump.ko +qcom_glink_smem.ko +qcom_glink.ko +qmi_helpers.ko +qcom_smd.ko +mdt_loader.ko +hwkm.ko +icc-bcm-voter.ko +icc-debug.ko +iommu-logger.ko +llcc-qcom.ko +mem-hooks.ko +mem_buf_dev.ko +mem_buf.ko +memory_dump_v2.ko +minidump.ko +msm_dma_iommu_mapping.ko +pinctrl-sdm670.ko +msm_rtb.ko +nvmem_qcom-spmi-sdam.ko +pinctrl-msm.ko +proxy-consumer.ko +qcom-dcvs.ko +qcom_dma_heaps.ko +qcom_hwspinlock.ko +qcom_logbuf_vh.ko +qcom_iommu_util.ko +qcom_llcc_pmu.ko +qcom-pmu-lib.ko +qcom-spmi-pmic.ko +spmi-pmic-arb.ko +qcom_rpmh.ko +qcom-scm.ko +qnoc-qos.ko +qrtr.ko +qti-regmap-debugfs.ko +regmap-spmi.ko +rtc-pm8xxx.ko +secure_buffer.ko +smem.ko +socinfo.ko +stub-regulator.ko +qcom_aoss.ko +msm_qmp.ko +tmecom-intf.ko +arm_smmu.ko +mem-offline.ko +sdhci-msm.ko +nvme-core.ko +nvme.ko +qcom-apcs-ipc-mailbox.ko +msm-poweroff.ko +qpnp-power-on.ko +nvmem_qfprom.ko diff --git a/modules.list.msm.trinket b/modules.list.msm.trinket index 5e0b47fa4519..78c573e98142 100644 --- a/modules.list.msm.trinket +++ b/modules.list.msm.trinket @@ -66,3 +66,11 @@ sdhci-msm.ko qpnp-power-on.ko msm-poweroff.ko mem-hooks.ko +ufs_qcom.ko +phy-qcom-ufs.ko +phy-qcom-ufs-qmp-v3-660.ko +ufshcd-crypto-qti.ko +cqhci-crypto-qti.ko +crypto-qti-common.ko +crypto-qti-tz.ko +nvmem_qfprom.ko diff --git a/modules.systemdlkm_blocklist.msm.kalama.lu b/modules.systemdlkm_blocklist.msm.kalama.lu new file mode 100644 index 000000000000..85698d918b21 --- /dev/null +++ b/modules.systemdlkm_blocklist.msm.kalama.lu @@ -0,0 +1,3 @@ +# SPDX-License-Identifier: GPL-2.0-only +# Copyright (c) 2022, Qualcomm Innovation Center, Inc. All rights reserved. + diff --git a/modules.vendor_blocklist.msm.autogvm b/modules.vendor_blocklist.msm.autogvm index da1235ad472f..efd5f493bea8 100644 --- a/modules.vendor_blocklist.msm.autogvm +++ b/modules.vendor_blocklist.msm.autogvm @@ -61,3 +61,14 @@ blocklist vsock_diag blocklist xc4000 blocklist xc5000 blocklist limits_stat +blocklist cnss2 +blocklist cnss_plat_ipc_qmi_svc +blocklist wlan_firmware_service +blocklist cnss_nl +blocklist cnss_utils +blocklist qca_cld3_qca6174 +blocklist qca_cld3_qcn7605 +blocklist qca_cld3_qca6390 +blocklist qca_cld3_qca6490 +blocklist qca_cld3_qca6390_cnss2 +blocklist qca_cld3_qca6490_cnss2 diff --git a/modules.vendor_blocklist.msm.gen3auto b/modules.vendor_blocklist.msm.gen3auto index a5d502acb18e..389fba43c576 100644 --- a/modules.vendor_blocklist.msm.gen3auto +++ b/modules.vendor_blocklist.msm.gen3auto @@ -63,3 +63,12 @@ blocklist vsock_diag blocklist xc4000 blocklist xc5000 blocklist limits_stat +blocklist cnss2 +blocklist cnss_plat_ipc_qmi_svc +blocklist wlan_firmware_service +blocklist cnss_nl +blocklist cnss_utils +blocklist qca_cld3_qca6174 +blocklist qca_cld3_qcn7605 +blocklist qca_cld3_qca6390 +blocklist qca_cld3_qca6490 diff --git a/modules.vendor_blocklist.msm.gen4auto b/modules.vendor_blocklist.msm.gen4auto index a5d502acb18e..61c2f46ea38f 100644 --- a/modules.vendor_blocklist.msm.gen4auto +++ b/modules.vendor_blocklist.msm.gen4auto @@ -4,6 +4,7 @@ blocklist 8250_of blocklist adc-tm blocklist atomic64_test +blocklist aurix-can blocklist can-bcm blocklist can-gw blocklist can-raw @@ -63,3 +64,12 @@ blocklist vsock_diag blocklist xc4000 blocklist xc5000 blocklist limits_stat +blocklist cnss2 +blocklist cnss_plat_ipc_qmi_svc +blocklist wlan_firmware_service +blocklist cnss_nl +blocklist cnss_utils +blocklist qca_cld3_qca6174 +blocklist qca_cld3_qcn7605 +blocklist qca_cld3_qca6390 +blocklist qca_cld3_qca6490 diff --git a/modules.vendor_blocklist.msm.kalama.lu b/modules.vendor_blocklist.msm.kalama.lu new file mode 100644 index 000000000000..e251a4331653 --- /dev/null +++ b/modules.vendor_blocklist.msm.kalama.lu @@ -0,0 +1,65 @@ +# SPDX-License-Identifier: GPL-2.0-only +# Copyright (c) 2020, The Linux Foundation. All rights reserved. + +blocklist 8250_of +blocklist adc-tm +blocklist atomic64_test +blocklist can-bcm +blocklist can-gw +blocklist can-raw +blocklist dummy-cpufreq +blocklist dummy_hcd +blocklist dummy_hcd +blocklist e4000 +blocklist failover +blocklist fc0011 +blocklist fc0012 +blocklist fc0013 +blocklist fc2580 +blocklist it913x +blocklist kheaders +blocklist lkdtm +blocklist llcc_perfmon +blocklist locktorture +blocklist m88rs6000t +blocklist max2165 +blocklist mc44s803 +blocklist mmrm_test_module +blocklist msi001 +blocklist mt2060 +blocklist mt2063 +blocklist mt20xx +blocklist mt2131 +blocklist mt2266 +blocklist mxl301rf +blocklist net_failover +blocklist qm1d1b0004 +blocklist qm1d1c0042 +blocklist qt1010 +blocklist r820t +blocklist rcutorture +blocklist rtc-test +blocklist si2157 +blocklist tda18212 +blocklist tda18218 +blocklist tda18250 +blocklist tda18271 +blocklist tda827x +blocklist tda8290 +blocklist tda9887 +blocklist tea5761 +blocklist tea5767 +blocklist test_user_copy +blocklist torture +blocklist tua9001 +blocklist tuner-simple +blocklist tuner-types +blocklist tuner-xc2028 +blocklist vmw_vsock_virtio_transport +blocklist vmw_vsock_virtio_transport_common +blocklist vsock +blocklist vsock_diag +blocklist xc4000 +blocklist xc5000 +blocklist limits_stat +blocklist kunit diff --git a/modules.vendor_blocklist.msm.qcs605 b/modules.vendor_blocklist.msm.qcs605 new file mode 100644 index 000000000000..cd9f1ba6c113 --- /dev/null +++ b/modules.vendor_blocklist.msm.qcs605 @@ -0,0 +1,63 @@ +# SPDX-License-Identifier: GPL-2.0-only +# Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved. + +blocklist 8250_of +blocklist adc-tm +blocklist atomic64_test +blocklist can-bcm +blocklist can-gw +blocklist can-raw +blocklist dummy-cpufreq +blocklist dummy_hcd +blocklist dummy_hcd +blocklist e4000 +blocklist failover +blocklist fc0011 +blocklist fc0012 +blocklist fc0013 +blocklist fc2580 +blocklist it913x +blocklist kheaders +blocklist lkdtm +blocklist llcc_perfmon +blocklist locktorture +blocklist m88rs6000t +blocklist max2165 +blocklist mc44s803 +blocklist mmrm_test_module +blocklist msi001 +blocklist mt2060 +blocklist mt2063 +blocklist mt20xx +blocklist mt2131 +blocklist mt2266 +blocklist mxl301rf +blocklist net_failover +blocklist qm1d1b0004 +blocklist qm1d1c0042 +blocklist qt1010 +blocklist r820t +blocklist rcutorture +blocklist rtc-test +blocklist si2157 +blocklist tda18212 +blocklist tda18218 +blocklist tda18250 +blocklist tda18271 +blocklist tda827x +blocklist tda8290 +blocklist tda9887 +blocklist tea5761 +blocklist tea5767 +blocklist test_user_copy +blocklist torture +blocklist tua9001 +blocklist tuner-simple +blocklist tuner-types +blocklist tuner-xc2028 +blocklist vmw_vsock_virtio_transport +blocklist vmw_vsock_virtio_transport_common +blocklist vsock +blocklist vsock_diag +blocklist xc4000 +blocklist xc5000 diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c index a267c9b6bcef..756523e5402a 100644 --- a/net/bluetooth/l2cap_sock.c +++ b/net/bluetooth/l2cap_sock.c @@ -45,6 +45,7 @@ static const struct proto_ops l2cap_sock_ops; static void l2cap_sock_init(struct sock *sk, struct sock *parent); static struct sock *l2cap_sock_alloc(struct net *net, struct socket *sock, int proto, gfp_t prio, int kern); +static void l2cap_sock_cleanup_listen(struct sock *parent); bool l2cap_is_socket(struct socket *sock) { @@ -1414,6 +1415,7 @@ static int l2cap_sock_release(struct socket *sock) if (!sk) return 0; + l2cap_sock_cleanup_listen(sk); bt_sock_unlink(&l2cap_sk_list, sk); err = l2cap_sock_shutdown(sock, SHUT_RDWR); diff --git a/net/bridge/br_if.c b/net/bridge/br_if.c index 4a02f8bb278a..1f70441cbada 100644 --- a/net/bridge/br_if.c +++ b/net/bridge/br_if.c @@ -157,8 +157,9 @@ void br_manage_promisc(struct net_bridge *br) * This lets us disable promiscuous mode and write * this config to hw. */ - if (br->auto_cnt == 0 || - (br->auto_cnt == 1 && br_auto_port(p))) + if ((p->dev->priv_flags & IFF_UNICAST_FLT) && + (br->auto_cnt == 0 || + (br->auto_cnt == 1 && br_auto_port(p)))) br_port_clear_promisc(p); else br_port_set_promisc(p); diff --git a/net/bridge/br_stp_if.c b/net/bridge/br_stp_if.c index ba55851fe132..3326dfced68a 100644 --- a/net/bridge/br_stp_if.c +++ b/net/bridge/br_stp_if.c @@ -201,6 +201,9 @@ int br_stp_set_enabled(struct net_bridge *br, unsigned long val, { ASSERT_RTNL(); + if (!net_eq(dev_net(br->dev), &init_net)) + NL_SET_ERR_MSG_MOD(extack, "STP does not work in non-root netns"); + if (br_mrp_enabled(br)) { NL_SET_ERR_MSG_MOD(extack, "STP can't be enabled if MRP is already enabled"); diff --git a/net/can/bcm.c b/net/can/bcm.c index 5727a073189b..a2fd68d1149b 100644 --- a/net/can/bcm.c +++ b/net/can/bcm.c @@ -1521,6 +1521,12 @@ static int bcm_release(struct socket *sock) lock_sock(sk); +#if IS_ENABLED(CONFIG_PROC_FS) + /* remove procfs entry */ + if (net->can.bcmproc_dir && bo->bcm_proc_read) + remove_proc_entry(bo->procname, net->can.bcmproc_dir); +#endif /* CONFIG_PROC_FS */ + list_for_each_entry_safe(op, next, &bo->tx_ops, list) bcm_remove_op(op); @@ -1556,12 +1562,6 @@ static int bcm_release(struct socket *sock) list_for_each_entry_safe(op, next, &bo->rx_ops, list) bcm_remove_op(op); -#if IS_ENABLED(CONFIG_PROC_FS) - /* remove procfs entry */ - if (net->can.bcmproc_dir && bo->bcm_proc_read) - remove_proc_entry(bo->procname, net->can.bcmproc_dir); -#endif /* CONFIG_PROC_FS */ - /* remove device reference */ if (bo->bound) { bo->bound = 0; diff --git a/net/can/isotp.c b/net/can/isotp.c index ca69ca39c8fd..4dccf7b4b88d 100644 --- a/net/can/isotp.c +++ b/net/can/isotp.c @@ -992,8 +992,9 @@ static int isotp_sendmsg(struct socket *sock, struct msghdr *msg, size_t size) /* wait for complete transmission of current pdu */ wait_event_interruptible(so->wait, so->tx.state == ISOTP_IDLE); - if (sk->sk_err) - return -sk->sk_err; + err = sock_error(sk); + if (err) + return err; } return size; diff --git a/net/ceph/messenger_v2.c b/net/ceph/messenger_v2.c index cc40ce4e02fb..c3d105e59d25 100644 --- a/net/ceph/messenger_v2.c +++ b/net/ceph/messenger_v2.c @@ -391,6 +391,8 @@ static int head_onwire_len(int ctrl_len, bool secure) int head_len; int rem_len; + BUG_ON(ctrl_len < 0 || ctrl_len > CEPH_MSG_MAX_CONTROL_LEN); + if (secure) { head_len = CEPH_PREAMBLE_SECURE_LEN; if (ctrl_len > CEPH_PREAMBLE_INLINE_LEN) { @@ -409,6 +411,10 @@ static int head_onwire_len(int ctrl_len, bool secure) static int __tail_onwire_len(int front_len, int middle_len, int data_len, bool secure) { + BUG_ON(front_len < 0 || front_len > CEPH_MSG_MAX_FRONT_LEN || + middle_len < 0 || middle_len > CEPH_MSG_MAX_MIDDLE_LEN || + data_len < 0 || data_len > CEPH_MSG_MAX_DATA_LEN); + if (!front_len && !middle_len && !data_len) return 0; @@ -521,29 +527,34 @@ static int decode_preamble(void *p, struct ceph_frame_desc *desc) desc->fd_aligns[i] = ceph_decode_16(&p); } + if (desc->fd_lens[0] < 0 || + desc->fd_lens[0] > CEPH_MSG_MAX_CONTROL_LEN) { + pr_err("bad control segment length %d\n", desc->fd_lens[0]); + return -EINVAL; + } + if (desc->fd_lens[1] < 0 || + desc->fd_lens[1] > CEPH_MSG_MAX_FRONT_LEN) { + pr_err("bad front segment length %d\n", desc->fd_lens[1]); + return -EINVAL; + } + if (desc->fd_lens[2] < 0 || + desc->fd_lens[2] > CEPH_MSG_MAX_MIDDLE_LEN) { + pr_err("bad middle segment length %d\n", desc->fd_lens[2]); + return -EINVAL; + } + if (desc->fd_lens[3] < 0 || + desc->fd_lens[3] > CEPH_MSG_MAX_DATA_LEN) { + pr_err("bad data segment length %d\n", desc->fd_lens[3]); + return -EINVAL; + } + /* * This would fire for FRAME_TAG_WAIT (it has one empty * segment), but we should never get it as client. */ if (!desc->fd_lens[desc->fd_seg_cnt - 1]) { - pr_err("last segment empty\n"); - return -EINVAL; - } - - if (desc->fd_lens[0] > CEPH_MSG_MAX_CONTROL_LEN) { - pr_err("control segment too big %d\n", desc->fd_lens[0]); - return -EINVAL; - } - if (desc->fd_lens[1] > CEPH_MSG_MAX_FRONT_LEN) { - pr_err("front segment too big %d\n", desc->fd_lens[1]); - return -EINVAL; - } - if (desc->fd_lens[2] > CEPH_MSG_MAX_MIDDLE_LEN) { - pr_err("middle segment too big %d\n", desc->fd_lens[2]); - return -EINVAL; - } - if (desc->fd_lens[3] > CEPH_MSG_MAX_DATA_LEN) { - pr_err("data segment too big %d\n", desc->fd_lens[3]); + pr_err("last segment empty, segment count %d\n", + desc->fd_seg_cnt); return -EINVAL; } diff --git a/net/core/filter.c b/net/core/filter.c index 519315a1acf3..18eb8049c795 100644 --- a/net/core/filter.c +++ b/net/core/filter.c @@ -6174,12 +6174,11 @@ static struct sock *sk_lookup(struct net *net, struct bpf_sock_tuple *tuple, static struct sock * __bpf_skc_lookup(struct sk_buff *skb, struct bpf_sock_tuple *tuple, u32 len, struct net *caller_net, u32 ifindex, u8 proto, u64 netns_id, - u64 flags) + u64 flags, int sdif) { struct sock *sk = NULL; - u8 family = AF_UNSPEC; struct net *net; - int sdif; + u8 family; if (len == sizeof(tuple->ipv4)) family = AF_INET; @@ -6188,14 +6187,15 @@ __bpf_skc_lookup(struct sk_buff *skb, struct bpf_sock_tuple *tuple, u32 len, else return NULL; - if (unlikely(family == AF_UNSPEC || flags || - !((s32)netns_id < 0 || netns_id <= S32_MAX))) + if (unlikely(flags || !((s32)netns_id < 0 || netns_id <= S32_MAX))) goto out; - if (family == AF_INET) - sdif = inet_sdif(skb); - else - sdif = inet6_sdif(skb); + if (sdif < 0) { + if (family == AF_INET) + sdif = inet_sdif(skb); + else + sdif = inet6_sdif(skb); + } if ((s32)netns_id < 0) { net = caller_net; @@ -6215,10 +6215,11 @@ out: static struct sock * __bpf_sk_lookup(struct sk_buff *skb, struct bpf_sock_tuple *tuple, u32 len, struct net *caller_net, u32 ifindex, u8 proto, u64 netns_id, - u64 flags) + u64 flags, int sdif) { struct sock *sk = __bpf_skc_lookup(skb, tuple, len, caller_net, - ifindex, proto, netns_id, flags); + ifindex, proto, netns_id, flags, + sdif); if (sk) { struct sock *sk2 = sk_to_full_sk(sk); @@ -6258,7 +6259,7 @@ bpf_skc_lookup(struct sk_buff *skb, struct bpf_sock_tuple *tuple, u32 len, } return __bpf_skc_lookup(skb, tuple, len, caller_net, ifindex, proto, - netns_id, flags); + netns_id, flags, -1); } static struct sock * @@ -6347,6 +6348,78 @@ static const struct bpf_func_proto bpf_sk_lookup_udp_proto = { .arg5_type = ARG_ANYTHING, }; +BPF_CALL_5(bpf_tc_skc_lookup_tcp, struct sk_buff *, skb, + struct bpf_sock_tuple *, tuple, u32, len, u64, netns_id, u64, flags) +{ + struct net_device *dev = skb->dev; + int ifindex = dev->ifindex, sdif = dev_sdif(dev); + struct net *caller_net = dev_net(dev); + + return (unsigned long)__bpf_skc_lookup(skb, tuple, len, caller_net, + ifindex, IPPROTO_TCP, netns_id, + flags, sdif); +} + +static const struct bpf_func_proto bpf_tc_skc_lookup_tcp_proto = { + .func = bpf_tc_skc_lookup_tcp, + .gpl_only = false, + .pkt_access = true, + .ret_type = RET_PTR_TO_SOCK_COMMON_OR_NULL, + .arg1_type = ARG_PTR_TO_CTX, + .arg2_type = ARG_PTR_TO_MEM | MEM_RDONLY, + .arg3_type = ARG_CONST_SIZE, + .arg4_type = ARG_ANYTHING, + .arg5_type = ARG_ANYTHING, +}; + +BPF_CALL_5(bpf_tc_sk_lookup_tcp, struct sk_buff *, skb, + struct bpf_sock_tuple *, tuple, u32, len, u64, netns_id, u64, flags) +{ + struct net_device *dev = skb->dev; + int ifindex = dev->ifindex, sdif = dev_sdif(dev); + struct net *caller_net = dev_net(dev); + + return (unsigned long)__bpf_sk_lookup(skb, tuple, len, caller_net, + ifindex, IPPROTO_TCP, netns_id, + flags, sdif); +} + +static const struct bpf_func_proto bpf_tc_sk_lookup_tcp_proto = { + .func = bpf_tc_sk_lookup_tcp, + .gpl_only = false, + .pkt_access = true, + .ret_type = RET_PTR_TO_SOCKET_OR_NULL, + .arg1_type = ARG_PTR_TO_CTX, + .arg2_type = ARG_PTR_TO_MEM | MEM_RDONLY, + .arg3_type = ARG_CONST_SIZE, + .arg4_type = ARG_ANYTHING, + .arg5_type = ARG_ANYTHING, +}; + +BPF_CALL_5(bpf_tc_sk_lookup_udp, struct sk_buff *, skb, + struct bpf_sock_tuple *, tuple, u32, len, u64, netns_id, u64, flags) +{ + struct net_device *dev = skb->dev; + int ifindex = dev->ifindex, sdif = dev_sdif(dev); + struct net *caller_net = dev_net(dev); + + return (unsigned long)__bpf_sk_lookup(skb, tuple, len, caller_net, + ifindex, IPPROTO_UDP, netns_id, + flags, sdif); +} + +static const struct bpf_func_proto bpf_tc_sk_lookup_udp_proto = { + .func = bpf_tc_sk_lookup_udp, + .gpl_only = false, + .pkt_access = true, + .ret_type = RET_PTR_TO_SOCKET_OR_NULL, + .arg1_type = ARG_PTR_TO_CTX, + .arg2_type = ARG_PTR_TO_MEM | MEM_RDONLY, + .arg3_type = ARG_CONST_SIZE, + .arg4_type = ARG_ANYTHING, + .arg5_type = ARG_ANYTHING, +}; + BPF_CALL_1(bpf_sk_release, struct sock *, sk) { if (sk && sk_is_refcounted(sk)) @@ -6364,12 +6437,13 @@ static const struct bpf_func_proto bpf_sk_release_proto = { BPF_CALL_5(bpf_xdp_sk_lookup_udp, struct xdp_buff *, ctx, struct bpf_sock_tuple *, tuple, u32, len, u32, netns_id, u64, flags) { - struct net *caller_net = dev_net(ctx->rxq->dev); - int ifindex = ctx->rxq->dev->ifindex; + struct net_device *dev = ctx->rxq->dev; + int ifindex = dev->ifindex, sdif = dev_sdif(dev); + struct net *caller_net = dev_net(dev); return (unsigned long)__bpf_sk_lookup(NULL, tuple, len, caller_net, ifindex, IPPROTO_UDP, netns_id, - flags); + flags, sdif); } static const struct bpf_func_proto bpf_xdp_sk_lookup_udp_proto = { @@ -6387,12 +6461,13 @@ static const struct bpf_func_proto bpf_xdp_sk_lookup_udp_proto = { BPF_CALL_5(bpf_xdp_skc_lookup_tcp, struct xdp_buff *, ctx, struct bpf_sock_tuple *, tuple, u32, len, u32, netns_id, u64, flags) { - struct net *caller_net = dev_net(ctx->rxq->dev); - int ifindex = ctx->rxq->dev->ifindex; + struct net_device *dev = ctx->rxq->dev; + int ifindex = dev->ifindex, sdif = dev_sdif(dev); + struct net *caller_net = dev_net(dev); return (unsigned long)__bpf_skc_lookup(NULL, tuple, len, caller_net, ifindex, IPPROTO_TCP, netns_id, - flags); + flags, sdif); } static const struct bpf_func_proto bpf_xdp_skc_lookup_tcp_proto = { @@ -6410,12 +6485,13 @@ static const struct bpf_func_proto bpf_xdp_skc_lookup_tcp_proto = { BPF_CALL_5(bpf_xdp_sk_lookup_tcp, struct xdp_buff *, ctx, struct bpf_sock_tuple *, tuple, u32, len, u32, netns_id, u64, flags) { - struct net *caller_net = dev_net(ctx->rxq->dev); - int ifindex = ctx->rxq->dev->ifindex; + struct net_device *dev = ctx->rxq->dev; + int ifindex = dev->ifindex, sdif = dev_sdif(dev); + struct net *caller_net = dev_net(dev); return (unsigned long)__bpf_sk_lookup(NULL, tuple, len, caller_net, ifindex, IPPROTO_TCP, netns_id, - flags); + flags, sdif); } static const struct bpf_func_proto bpf_xdp_sk_lookup_tcp_proto = { @@ -6435,7 +6511,8 @@ BPF_CALL_5(bpf_sock_addr_skc_lookup_tcp, struct bpf_sock_addr_kern *, ctx, { return (unsigned long)__bpf_skc_lookup(NULL, tuple, len, sock_net(ctx->sk), 0, - IPPROTO_TCP, netns_id, flags); + IPPROTO_TCP, netns_id, flags, + -1); } static const struct bpf_func_proto bpf_sock_addr_skc_lookup_tcp_proto = { @@ -6454,7 +6531,7 @@ BPF_CALL_5(bpf_sock_addr_sk_lookup_tcp, struct bpf_sock_addr_kern *, ctx, { return (unsigned long)__bpf_sk_lookup(NULL, tuple, len, sock_net(ctx->sk), 0, IPPROTO_TCP, - netns_id, flags); + netns_id, flags, -1); } static const struct bpf_func_proto bpf_sock_addr_sk_lookup_tcp_proto = { @@ -6473,7 +6550,7 @@ BPF_CALL_5(bpf_sock_addr_sk_lookup_udp, struct bpf_sock_addr_kern *, ctx, { return (unsigned long)__bpf_sk_lookup(NULL, tuple, len, sock_net(ctx->sk), 0, IPPROTO_UDP, - netns_id, flags); + netns_id, flags, -1); } static const struct bpf_func_proto bpf_sock_addr_sk_lookup_udp_proto = { @@ -7476,9 +7553,9 @@ tc_cls_act_func_proto(enum bpf_func_id func_id, const struct bpf_prog *prog) #endif #ifdef CONFIG_INET case BPF_FUNC_sk_lookup_tcp: - return &bpf_sk_lookup_tcp_proto; + return &bpf_tc_sk_lookup_tcp_proto; case BPF_FUNC_sk_lookup_udp: - return &bpf_sk_lookup_udp_proto; + return &bpf_tc_sk_lookup_udp_proto; case BPF_FUNC_sk_release: return &bpf_sk_release_proto; case BPF_FUNC_tcp_sock: @@ -7486,7 +7563,7 @@ tc_cls_act_func_proto(enum bpf_func_id func_id, const struct bpf_prog *prog) case BPF_FUNC_get_listener_sock: return &bpf_get_listener_sock_proto; case BPF_FUNC_skc_lookup_tcp: - return &bpf_skc_lookup_tcp_proto; + return &bpf_tc_skc_lookup_tcp_proto; case BPF_FUNC_tcp_check_syncookie: return &bpf_tcp_check_syncookie_proto; case BPF_FUNC_skb_ecn_set_ce: diff --git a/net/core/of_net.c b/net/core/of_net.c index dbac3a172a11..f1a9bf7578e7 100644 --- a/net/core/of_net.c +++ b/net/core/of_net.c @@ -143,3 +143,28 @@ int of_get_mac_address(struct device_node *np, u8 *addr) return of_get_mac_addr_nvmem(np, addr); } EXPORT_SYMBOL(of_get_mac_address); + +/** + * of_get_ethdev_address() + * @np: Caller's Device Node + * @dev: Pointer to netdevice which address will be updated + * + * Search the device tree for the best MAC address to use. + * If found set @dev->dev_addr to that address. + * + * See documentation of of_get_mac_address() for more information on how + * the best address is determined. + * + * Return: 0 on success and errno in case of error. + */ +int of_get_ethdev_address(struct device_node *np, struct net_device *dev) +{ + u8 addr[ETH_ALEN]; + int ret; + + ret = of_get_mac_address(np, addr); + if (!ret) + eth_hw_addr_set(dev, addr); + return ret; +} +EXPORT_SYMBOL(of_get_ethdev_address); diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c index bc187289bf64..49766446797c 100644 --- a/net/core/rtnetlink.c +++ b/net/core/rtnetlink.c @@ -922,24 +922,27 @@ static inline int rtnl_vfinfo_size(const struct net_device *dev, nla_total_size(sizeof(struct ifla_vf_rate)) + nla_total_size(sizeof(struct ifla_vf_link_state)) + nla_total_size(sizeof(struct ifla_vf_rss_query_en)) + - nla_total_size(0) + /* nest IFLA_VF_STATS */ - /* IFLA_VF_STATS_RX_PACKETS */ - nla_total_size_64bit(sizeof(__u64)) + - /* IFLA_VF_STATS_TX_PACKETS */ - nla_total_size_64bit(sizeof(__u64)) + - /* IFLA_VF_STATS_RX_BYTES */ - nla_total_size_64bit(sizeof(__u64)) + - /* IFLA_VF_STATS_TX_BYTES */ - nla_total_size_64bit(sizeof(__u64)) + - /* IFLA_VF_STATS_BROADCAST */ - nla_total_size_64bit(sizeof(__u64)) + - /* IFLA_VF_STATS_MULTICAST */ - nla_total_size_64bit(sizeof(__u64)) + - /* IFLA_VF_STATS_RX_DROPPED */ - nla_total_size_64bit(sizeof(__u64)) + - /* IFLA_VF_STATS_TX_DROPPED */ - nla_total_size_64bit(sizeof(__u64)) + nla_total_size(sizeof(struct ifla_vf_trust))); + if (~ext_filter_mask & RTEXT_FILTER_SKIP_STATS) { + size += num_vfs * + (nla_total_size(0) + /* nest IFLA_VF_STATS */ + /* IFLA_VF_STATS_RX_PACKETS */ + nla_total_size_64bit(sizeof(__u64)) + + /* IFLA_VF_STATS_TX_PACKETS */ + nla_total_size_64bit(sizeof(__u64)) + + /* IFLA_VF_STATS_RX_BYTES */ + nla_total_size_64bit(sizeof(__u64)) + + /* IFLA_VF_STATS_TX_BYTES */ + nla_total_size_64bit(sizeof(__u64)) + + /* IFLA_VF_STATS_BROADCAST */ + nla_total_size_64bit(sizeof(__u64)) + + /* IFLA_VF_STATS_MULTICAST */ + nla_total_size_64bit(sizeof(__u64)) + + /* IFLA_VF_STATS_RX_DROPPED */ + nla_total_size_64bit(sizeof(__u64)) + + /* IFLA_VF_STATS_TX_DROPPED */ + nla_total_size_64bit(sizeof(__u64))); + } return size; } else return 0; @@ -1214,7 +1217,8 @@ static noinline_for_stack int rtnl_fill_stats(struct sk_buff *skb, static noinline_for_stack int rtnl_fill_vfinfo(struct sk_buff *skb, struct net_device *dev, int vfs_num, - struct nlattr *vfinfo) + struct nlattr *vfinfo, + u32 ext_filter_mask) { struct ifla_vf_rss_query_en vf_rss_query_en; struct nlattr *vf, *vfstats, *vfvlanlist; @@ -1320,33 +1324,35 @@ static noinline_for_stack int rtnl_fill_vfinfo(struct sk_buff *skb, goto nla_put_vf_failure; } nla_nest_end(skb, vfvlanlist); - memset(&vf_stats, 0, sizeof(vf_stats)); - if (dev->netdev_ops->ndo_get_vf_stats) - dev->netdev_ops->ndo_get_vf_stats(dev, vfs_num, - &vf_stats); - vfstats = nla_nest_start_noflag(skb, IFLA_VF_STATS); - if (!vfstats) - goto nla_put_vf_failure; - if (nla_put_u64_64bit(skb, IFLA_VF_STATS_RX_PACKETS, - vf_stats.rx_packets, IFLA_VF_STATS_PAD) || - nla_put_u64_64bit(skb, IFLA_VF_STATS_TX_PACKETS, - vf_stats.tx_packets, IFLA_VF_STATS_PAD) || - nla_put_u64_64bit(skb, IFLA_VF_STATS_RX_BYTES, - vf_stats.rx_bytes, IFLA_VF_STATS_PAD) || - nla_put_u64_64bit(skb, IFLA_VF_STATS_TX_BYTES, - vf_stats.tx_bytes, IFLA_VF_STATS_PAD) || - nla_put_u64_64bit(skb, IFLA_VF_STATS_BROADCAST, - vf_stats.broadcast, IFLA_VF_STATS_PAD) || - nla_put_u64_64bit(skb, IFLA_VF_STATS_MULTICAST, - vf_stats.multicast, IFLA_VF_STATS_PAD) || - nla_put_u64_64bit(skb, IFLA_VF_STATS_RX_DROPPED, - vf_stats.rx_dropped, IFLA_VF_STATS_PAD) || - nla_put_u64_64bit(skb, IFLA_VF_STATS_TX_DROPPED, - vf_stats.tx_dropped, IFLA_VF_STATS_PAD)) { - nla_nest_cancel(skb, vfstats); - goto nla_put_vf_failure; + if (~ext_filter_mask & RTEXT_FILTER_SKIP_STATS) { + memset(&vf_stats, 0, sizeof(vf_stats)); + if (dev->netdev_ops->ndo_get_vf_stats) + dev->netdev_ops->ndo_get_vf_stats(dev, vfs_num, + &vf_stats); + vfstats = nla_nest_start_noflag(skb, IFLA_VF_STATS); + if (!vfstats) + goto nla_put_vf_failure; + if (nla_put_u64_64bit(skb, IFLA_VF_STATS_RX_PACKETS, + vf_stats.rx_packets, IFLA_VF_STATS_PAD) || + nla_put_u64_64bit(skb, IFLA_VF_STATS_TX_PACKETS, + vf_stats.tx_packets, IFLA_VF_STATS_PAD) || + nla_put_u64_64bit(skb, IFLA_VF_STATS_RX_BYTES, + vf_stats.rx_bytes, IFLA_VF_STATS_PAD) || + nla_put_u64_64bit(skb, IFLA_VF_STATS_TX_BYTES, + vf_stats.tx_bytes, IFLA_VF_STATS_PAD) || + nla_put_u64_64bit(skb, IFLA_VF_STATS_BROADCAST, + vf_stats.broadcast, IFLA_VF_STATS_PAD) || + nla_put_u64_64bit(skb, IFLA_VF_STATS_MULTICAST, + vf_stats.multicast, IFLA_VF_STATS_PAD) || + nla_put_u64_64bit(skb, IFLA_VF_STATS_RX_DROPPED, + vf_stats.rx_dropped, IFLA_VF_STATS_PAD) || + nla_put_u64_64bit(skb, IFLA_VF_STATS_TX_DROPPED, + vf_stats.tx_dropped, IFLA_VF_STATS_PAD)) { + nla_nest_cancel(skb, vfstats); + goto nla_put_vf_failure; + } + nla_nest_end(skb, vfstats); } - nla_nest_end(skb, vfstats); nla_nest_end(skb, vf); return 0; @@ -1379,7 +1385,7 @@ static noinline_for_stack int rtnl_fill_vf(struct sk_buff *skb, return -EMSGSIZE; for (i = 0; i < num_vfs; i++) { - if (rtnl_fill_vfinfo(skb, dev, i, vfinfo)) + if (rtnl_fill_vfinfo(skb, dev, i, vfinfo, ext_filter_mask)) return -EMSGSIZE; } @@ -3905,7 +3911,7 @@ static int nlmsg_populate_fdb_fill(struct sk_buff *skb, ndm->ndm_ifindex = dev->ifindex; ndm->ndm_state = ndm_state; - if (nla_put(skb, NDA_LLADDR, ETH_ALEN, addr)) + if (nla_put(skb, NDA_LLADDR, dev->addr_len, addr)) goto nla_put_failure; if (vid) if (nla_put(skb, NDA_VLAN, sizeof(u16), &vid)) @@ -3919,10 +3925,10 @@ nla_put_failure: return -EMSGSIZE; } -static inline size_t rtnl_fdb_nlmsg_size(void) +static inline size_t rtnl_fdb_nlmsg_size(const struct net_device *dev) { return NLMSG_ALIGN(sizeof(struct ndmsg)) + - nla_total_size(ETH_ALEN) + /* NDA_LLADDR */ + nla_total_size(dev->addr_len) + /* NDA_LLADDR */ nla_total_size(sizeof(u16)) + /* NDA_VLAN */ 0; } @@ -3934,7 +3940,7 @@ static void rtnl_fdb_notify(struct net_device *dev, u8 *addr, u16 vid, int type, struct sk_buff *skb; int err = -ENOBUFS; - skb = nlmsg_new(rtnl_fdb_nlmsg_size(), GFP_ATOMIC); + skb = nlmsg_new(rtnl_fdb_nlmsg_size(dev), GFP_ATOMIC); if (!skb) goto errout; diff --git a/net/core/skbuff.c b/net/core/skbuff.c index d062311a37bf..d0e77c4f8d32 100644 --- a/net/core/skbuff.c +++ b/net/core/skbuff.c @@ -3906,6 +3906,11 @@ struct sk_buff *skb_segment_list(struct sk_buff *skb, skb_push(skb, -skb_network_offset(skb) + offset); + /* Ensure the head is writeable before touching the shared info */ + err = skb_unclone(skb, GFP_ATOMIC); + if (err) + goto err_linearize; + skb_shinfo(skb)->frag_list = NULL; while (list_skb) { diff --git a/net/core/sock.c b/net/core/sock.c index 5917f32743e9..8d8fc642c188 100644 --- a/net/core/sock.c +++ b/net/core/sock.c @@ -2330,13 +2330,24 @@ kuid_t sock_i_uid(struct sock *sk) } EXPORT_SYMBOL(sock_i_uid); +unsigned long __sock_i_ino(struct sock *sk) +{ + unsigned long ino; + + read_lock(&sk->sk_callback_lock); + ino = sk->sk_socket ? SOCK_INODE(sk->sk_socket)->i_ino : 0; + read_unlock(&sk->sk_callback_lock); + return ino; +} +EXPORT_SYMBOL(__sock_i_ino); + unsigned long sock_i_ino(struct sock *sk) { unsigned long ino; - read_lock_bh(&sk->sk_callback_lock); - ino = sk->sk_socket ? SOCK_INODE(sk->sk_socket)->i_ino : 0; - read_unlock_bh(&sk->sk_callback_lock); + local_bh_disable(); + ino = __sock_i_ino(sk); + local_bh_enable(); return ino; } EXPORT_SYMBOL(sock_i_ino); diff --git a/net/dsa/tag_sja1105.c b/net/dsa/tag_sja1105.c index d43feadd5fa6..a163f535697e 100644 --- a/net/dsa/tag_sja1105.c +++ b/net/dsa/tag_sja1105.c @@ -100,8 +100,8 @@ static void sja1105_meta_unpack(const struct sk_buff *skb, * a unified unpacking command for both device series. */ packing(buf, &meta->tstamp, 31, 0, 4, UNPACK, 0); - packing(buf + 4, &meta->dmac_byte_4, 7, 0, 1, UNPACK, 0); - packing(buf + 5, &meta->dmac_byte_3, 7, 0, 1, UNPACK, 0); + packing(buf + 4, &meta->dmac_byte_3, 7, 0, 1, UNPACK, 0); + packing(buf + 5, &meta->dmac_byte_4, 7, 0, 1, UNPACK, 0); packing(buf + 6, &meta->source_port, 7, 0, 1, UNPACK, 0); packing(buf + 7, &meta->switch_id, 7, 0, 1, UNPACK, 0); } diff --git a/net/ipv4/esp4.c b/net/ipv4/esp4.c index f04935ce298b..5ae36f6c0d2f 100644 --- a/net/ipv4/esp4.c +++ b/net/ipv4/esp4.c @@ -1133,7 +1133,7 @@ static int esp_init_authenc(struct xfrm_state *x) err = crypto_aead_setkey(aead, key, keylen); free_key: - kfree(key); + kfree_sensitive(key); error: return err; diff --git a/net/ipv4/inet_connection_sock.c b/net/ipv4/inet_connection_sock.c index 29ec42c1f5d0..21a955a9b69d 100644 --- a/net/ipv4/inet_connection_sock.c +++ b/net/ipv4/inet_connection_sock.c @@ -833,7 +833,7 @@ static void reqsk_timer_handler(struct timer_list *t) icsk = inet_csk(sk_listener); net = sock_net(sk_listener); - max_syn_ack_retries = icsk->icsk_syn_retries ? : + max_syn_ack_retries = READ_ONCE(icsk->icsk_syn_retries) ? : READ_ONCE(net->ipv4.sysctl_tcp_synack_retries); /* Normally all the openreqs are young and become mature * (i.e. converted to established socket) for first timeout. diff --git a/net/ipv4/inet_hashtables.c b/net/ipv4/inet_hashtables.c index 39b3db5b6119..2936676f86eb 100644 --- a/net/ipv4/inet_hashtables.c +++ b/net/ipv4/inet_hashtables.c @@ -571,20 +571,8 @@ bool inet_ehash_insert(struct sock *sk, struct sock *osk, bool *found_dup_sk) spin_lock(lock); if (osk) { WARN_ON_ONCE(sk->sk_hash != osk->sk_hash); - ret = sk_hashed(osk); - if (ret) { - /* Before deleting the node, we insert a new one to make - * sure that the look-up-sk process would not miss either - * of them and that at least one node would exist in ehash - * table all the time. Otherwise there's a tiny chance - * that lookup process could find nothing in ehash table. - */ - __sk_nulls_add_node_tail_rcu(sk, list); - sk_nulls_del_node_init_rcu(osk); - } - goto unlock; - } - if (found_dup_sk) { + ret = sk_nulls_del_node_init_rcu(osk); + } else if (found_dup_sk) { *found_dup_sk = inet_ehash_lookup_by_sk(sk, list); if (*found_dup_sk) ret = false; @@ -593,7 +581,6 @@ bool inet_ehash_insert(struct sock *sk, struct sock *osk, bool *found_dup_sk) if (ret) __sk_nulls_add_node_rcu(sk, list); -unlock: spin_unlock(lock); return ret; diff --git a/net/ipv4/inet_timewait_sock.c b/net/ipv4/inet_timewait_sock.c index fe6340c363b4..437afe392e66 100644 --- a/net/ipv4/inet_timewait_sock.c +++ b/net/ipv4/inet_timewait_sock.c @@ -81,10 +81,10 @@ void inet_twsk_put(struct inet_timewait_sock *tw) } EXPORT_SYMBOL_GPL(inet_twsk_put); -static void inet_twsk_add_node_tail_rcu(struct inet_timewait_sock *tw, - struct hlist_nulls_head *list) +static void inet_twsk_add_node_rcu(struct inet_timewait_sock *tw, + struct hlist_nulls_head *list) { - hlist_nulls_add_tail_rcu(&tw->tw_node, list); + hlist_nulls_add_head_rcu(&tw->tw_node, list); } static void inet_twsk_add_bind_node(struct inet_timewait_sock *tw, @@ -120,7 +120,7 @@ void inet_twsk_hashdance(struct inet_timewait_sock *tw, struct sock *sk, spin_lock(lock); - inet_twsk_add_node_tail_rcu(tw, &ehead->chain); + inet_twsk_add_node_rcu(tw, &ehead->chain); /* Step 3: Remove SK from hash chain */ if (__sk_nulls_del_node_init_rcu(sk)) diff --git a/net/ipv4/route.c b/net/ipv4/route.c index ca59b61fd3a3..f4f6dc356f67 100644 --- a/net/ipv4/route.c +++ b/net/ipv4/route.c @@ -1220,6 +1220,7 @@ EXPORT_INDIRECT_CALLABLE(ipv4_dst_check); static void ipv4_send_dest_unreach(struct sk_buff *skb) { + struct net_device *dev; struct ip_options opt; int res; @@ -1237,7 +1238,8 @@ static void ipv4_send_dest_unreach(struct sk_buff *skb) opt.optlen = ip_hdr(skb)->ihl * 4 - sizeof(struct iphdr); rcu_read_lock(); - res = __ip_options_compile(dev_net(skb->dev), &opt, skb, NULL); + dev = skb->dev ? skb->dev : skb_rtable(skb)->dst.dev; + res = __ip_options_compile(dev_net(dev), &opt, skb, NULL); rcu_read_unlock(); if (res) diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c index 3f4a1ff31c9a..ba6f47b1d1a2 100644 --- a/net/ipv4/tcp.c +++ b/net/ipv4/tcp.c @@ -3290,7 +3290,7 @@ int tcp_sock_set_syncnt(struct sock *sk, int val) return -EINVAL; lock_sock(sk); - inet_csk(sk)->icsk_syn_retries = val; + WRITE_ONCE(inet_csk(sk)->icsk_syn_retries, val); release_sock(sk); return 0; } @@ -3299,7 +3299,7 @@ EXPORT_SYMBOL(tcp_sock_set_syncnt); void tcp_sock_set_user_timeout(struct sock *sk, u32 val) { lock_sock(sk); - inet_csk(sk)->icsk_user_timeout = val; + WRITE_ONCE(inet_csk(sk)->icsk_user_timeout, val); release_sock(sk); } EXPORT_SYMBOL(tcp_sock_set_user_timeout); @@ -3311,7 +3311,8 @@ int tcp_sock_set_keepidle_locked(struct sock *sk, int val) if (val < 1 || val > MAX_TCP_KEEPIDLE) return -EINVAL; - tp->keepalive_time = val * HZ; + /* Paired with WRITE_ONCE() in keepalive_time_when() */ + WRITE_ONCE(tp->keepalive_time, val * HZ); if (sock_flag(sk, SOCK_KEEPOPEN) && !((1 << sk->sk_state) & (TCPF_CLOSE | TCPF_LISTEN))) { u32 elapsed = keepalive_time_elapsed(tp); @@ -3343,7 +3344,7 @@ int tcp_sock_set_keepintvl(struct sock *sk, int val) return -EINVAL; lock_sock(sk); - tcp_sk(sk)->keepalive_intvl = val * HZ; + WRITE_ONCE(tcp_sk(sk)->keepalive_intvl, val * HZ); release_sock(sk); return 0; } @@ -3355,7 +3356,8 @@ int tcp_sock_set_keepcnt(struct sock *sk, int val) return -EINVAL; lock_sock(sk); - tcp_sk(sk)->keepalive_probes = val; + /* Paired with READ_ONCE() in keepalive_probes() */ + WRITE_ONCE(tcp_sk(sk)->keepalive_probes, val); release_sock(sk); return 0; } @@ -3557,19 +3559,19 @@ static int do_tcp_setsockopt(struct sock *sk, int level, int optname, if (val < 1 || val > MAX_TCP_KEEPINTVL) err = -EINVAL; else - tp->keepalive_intvl = val * HZ; + WRITE_ONCE(tp->keepalive_intvl, val * HZ); break; case TCP_KEEPCNT: if (val < 1 || val > MAX_TCP_KEEPCNT) err = -EINVAL; else - tp->keepalive_probes = val; + WRITE_ONCE(tp->keepalive_probes, val); break; case TCP_SYNCNT: if (val < 1 || val > MAX_TCP_SYNCNT) err = -EINVAL; else - icsk->icsk_syn_retries = val; + WRITE_ONCE(icsk->icsk_syn_retries, val); break; case TCP_SAVE_SYN: @@ -3582,18 +3584,18 @@ static int do_tcp_setsockopt(struct sock *sk, int level, int optname, case TCP_LINGER2: if (val < 0) - tp->linger2 = -1; + WRITE_ONCE(tp->linger2, -1); else if (val > TCP_FIN_TIMEOUT_MAX / HZ) - tp->linger2 = TCP_FIN_TIMEOUT_MAX; + WRITE_ONCE(tp->linger2, TCP_FIN_TIMEOUT_MAX); else - tp->linger2 = val * HZ; + WRITE_ONCE(tp->linger2, val * HZ); break; case TCP_DEFER_ACCEPT: /* Translate value in seconds to number of retransmits */ - icsk->icsk_accept_queue.rskq_defer_accept = - secs_to_retrans(val, TCP_TIMEOUT_INIT / HZ, - TCP_RTO_MAX / HZ); + WRITE_ONCE(icsk->icsk_accept_queue.rskq_defer_accept, + secs_to_retrans(val, TCP_TIMEOUT_INIT / HZ, + TCP_RTO_MAX / HZ)); break; case TCP_WINDOW_CLAMP: @@ -3617,7 +3619,7 @@ static int do_tcp_setsockopt(struct sock *sk, int level, int optname, if (val < 0) err = -EINVAL; else - icsk->icsk_user_timeout = val; + WRITE_ONCE(icsk->icsk_user_timeout, val); break; case TCP_FASTOPEN: @@ -3661,7 +3663,7 @@ static int do_tcp_setsockopt(struct sock *sk, int level, int optname, err = tcp_repair_set_window(tp, optval, optlen); break; case TCP_NOTSENT_LOWAT: - tp->notsent_lowat = val; + WRITE_ONCE(tp->notsent_lowat, val); sk->sk_write_space(sk); break; case TCP_INQ: @@ -3673,7 +3675,7 @@ static int do_tcp_setsockopt(struct sock *sk, int level, int optname, case TCP_TX_DELAY: if (val) tcp_enable_tx_delay(); - tp->tcp_tx_delay = val; + WRITE_ONCE(tp->tcp_tx_delay, val); break; default: err = -ENOPROTOOPT; @@ -3983,17 +3985,18 @@ static int do_tcp_getsockopt(struct sock *sk, int level, val = keepalive_probes(tp); break; case TCP_SYNCNT: - val = icsk->icsk_syn_retries ? : + val = READ_ONCE(icsk->icsk_syn_retries) ? : READ_ONCE(net->ipv4.sysctl_tcp_syn_retries); break; case TCP_LINGER2: - val = tp->linger2; + val = READ_ONCE(tp->linger2); if (val >= 0) val = (val ? : READ_ONCE(net->ipv4.sysctl_tcp_fin_timeout)) / HZ; break; case TCP_DEFER_ACCEPT: - val = retrans_to_secs(icsk->icsk_accept_queue.rskq_defer_accept, - TCP_TIMEOUT_INIT / HZ, TCP_RTO_MAX / HZ); + val = READ_ONCE(icsk->icsk_accept_queue.rskq_defer_accept); + val = retrans_to_secs(val, TCP_TIMEOUT_INIT / HZ, + TCP_RTO_MAX / HZ); break; case TCP_WINDOW_CLAMP: val = tp->window_clamp; @@ -4129,11 +4132,11 @@ static int do_tcp_getsockopt(struct sock *sk, int level, break; case TCP_USER_TIMEOUT: - val = icsk->icsk_user_timeout; + val = READ_ONCE(icsk->icsk_user_timeout); break; case TCP_FASTOPEN: - val = icsk->icsk_accept_queue.fastopenq.max_qlen; + val = READ_ONCE(icsk->icsk_accept_queue.fastopenq.max_qlen); break; case TCP_FASTOPEN_CONNECT: @@ -4145,14 +4148,14 @@ static int do_tcp_getsockopt(struct sock *sk, int level, break; case TCP_TX_DELAY: - val = tp->tcp_tx_delay; + val = READ_ONCE(tp->tcp_tx_delay); break; case TCP_TIMESTAMP: val = tcp_time_stamp_raw() + tp->tsoffset; break; case TCP_NOTSENT_LOWAT: - val = tp->notsent_lowat; + val = READ_ONCE(tp->notsent_lowat); break; case TCP_INQ: val = tp->recvmsg_inq; diff --git a/net/ipv4/tcp_fastopen.c b/net/ipv4/tcp_fastopen.c index 6e0a8ef5e816..e9b5d6f10c56 100644 --- a/net/ipv4/tcp_fastopen.c +++ b/net/ipv4/tcp_fastopen.c @@ -301,6 +301,7 @@ static struct sock *tcp_fastopen_create_child(struct sock *sk, static bool tcp_fastopen_queue_check(struct sock *sk) { struct fastopen_queue *fastopenq; + int max_qlen; /* Make sure the listener has enabled fastopen, and we don't * exceed the max # of pending TFO requests allowed before trying @@ -313,10 +314,11 @@ static bool tcp_fastopen_queue_check(struct sock *sk) * temporarily vs a server not supporting Fast Open at all. */ fastopenq = &inet_csk(sk)->icsk_accept_queue.fastopenq; - if (fastopenq->max_qlen == 0) + max_qlen = READ_ONCE(fastopenq->max_qlen); + if (max_qlen == 0) return false; - if (fastopenq->qlen >= fastopenq->max_qlen) { + if (fastopenq->qlen >= max_qlen) { struct request_sock *req1; spin_lock(&fastopenq->lock); req1 = fastopenq->rskq_rst_head; diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index 5b8ab3bdd053..1aa6ab387764 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c @@ -3585,8 +3585,11 @@ static int tcp_ack_update_window(struct sock *sk, const struct sk_buff *skb, u32 static bool __tcp_oow_rate_limited(struct net *net, int mib_idx, u32 *last_oow_ack_time) { - if (*last_oow_ack_time) { - s32 elapsed = (s32)(tcp_jiffies32 - *last_oow_ack_time); + /* Paired with the WRITE_ONCE() in this function. */ + u32 val = READ_ONCE(*last_oow_ack_time); + + if (val) { + s32 elapsed = (s32)(tcp_jiffies32 - val); if (0 <= elapsed && elapsed < READ_ONCE(net->ipv4.sysctl_tcp_invalid_ratelimit)) { @@ -3595,7 +3598,10 @@ static bool __tcp_oow_rate_limited(struct net *net, int mib_idx, } } - *last_oow_ack_time = tcp_jiffies32; + /* Paired with the prior READ_ONCE() and with itself, + * as we might be lockless. + */ + WRITE_ONCE(*last_oow_ack_time, tcp_jiffies32); return false; /* not rate-limited: go ahead, send dupack now! */ } diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index 86e6aaa148ae..b3c8f869c892 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c @@ -970,7 +970,7 @@ static void tcp_v4_reqsk_send_ack(const struct sock *sk, struct sk_buff *skb, tcp_rsk(req)->rcv_nxt, req->rsk_rcv_wnd >> inet_rsk(req)->rcv_wscale, tcp_time_stamp_raw() + tcp_rsk(req)->ts_off, - req->ts_recent, + READ_ONCE(req->ts_recent), 0, tcp_md5_do_lookup(sk, l3index, addr, AF_INET), inet_rsk(req)->no_srccheck ? IP_REPLY_ARG_NOSRCCHECK : 0, diff --git a/net/ipv4/tcp_minisocks.c b/net/ipv4/tcp_minisocks.c index aa67d5adcbca..2606a5571116 100644 --- a/net/ipv4/tcp_minisocks.c +++ b/net/ipv4/tcp_minisocks.c @@ -523,7 +523,7 @@ struct sock *tcp_create_openreq_child(const struct sock *sk, newtp->max_window = newtp->snd_wnd; if (newtp->rx_opt.tstamp_ok) { - newtp->rx_opt.ts_recent = req->ts_recent; + newtp->rx_opt.ts_recent = READ_ONCE(req->ts_recent); newtp->rx_opt.ts_recent_stamp = ktime_get_seconds(); newtp->tcp_header_len = sizeof(struct tcphdr) + TCPOLEN_TSTAMP_ALIGNED; } else { @@ -586,7 +586,7 @@ struct sock *tcp_check_req(struct sock *sk, struct sk_buff *skb, tcp_parse_options(sock_net(sk), skb, &tmp_opt, 0, NULL); if (tmp_opt.saw_tstamp) { - tmp_opt.ts_recent = req->ts_recent; + tmp_opt.ts_recent = READ_ONCE(req->ts_recent); if (tmp_opt.rcv_tsecr) tmp_opt.rcv_tsecr -= tcp_rsk(req)->ts_off; /* We do not store true stamp, but it is not required, @@ -726,8 +726,11 @@ struct sock *tcp_check_req(struct sock *sk, struct sk_buff *skb, /* In sequence, PAWS is OK. */ + /* TODO: We probably should defer ts_recent change once + * we take ownership of @req. + */ if (tmp_opt.saw_tstamp && !after(TCP_SKB_CB(skb)->seq, tcp_rsk(req)->rcv_nxt)) - req->ts_recent = tmp_opt.rcv_tsval; + WRITE_ONCE(req->ts_recent, tmp_opt.rcv_tsval); if (TCP_SKB_CB(skb)->seq == tcp_rsk(req)->rcv_isn) { /* Truncate SYN, it is out of window starting diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c index 6cada32c2705..17bc0a1bb249 100644 --- a/net/ipv4/tcp_output.c +++ b/net/ipv4/tcp_output.c @@ -875,7 +875,7 @@ static unsigned int tcp_synack_options(const struct sock *sk, if (likely(ireq->tstamp_ok)) { opts->options |= OPTION_TS; opts->tsval = tcp_skb_timestamp(skb) + tcp_rsk(req)->ts_off; - opts->tsecr = req->ts_recent; + opts->tsecr = READ_ONCE(req->ts_recent); remaining -= TCPOLEN_TSTAMP_ALIGNED; } if (likely(ireq->sack_ok)) { diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index ee5261af3c94..ff304c048b4c 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c @@ -325,9 +325,8 @@ static void addrconf_del_dad_work(struct inet6_ifaddr *ifp) static void addrconf_mod_rs_timer(struct inet6_dev *idev, unsigned long when) { - if (!timer_pending(&idev->rs_timer)) + if (!mod_timer(&idev->rs_timer, jiffies + when)) in6_dev_hold(idev); - mod_timer(&idev->rs_timer, jiffies + when); } static void addrconf_mod_dad_work(struct inet6_ifaddr *ifp, @@ -2751,6 +2750,9 @@ void addrconf_prefix_rcv(struct net_device *dev, u8 *opt, int len, bool sllao) return; } + if (valid_lft != 0 && valid_lft < ACCEPT_RA_MIN_LFT(in6_dev->cnf)) + goto put; + /* * Two things going on here: * 1) Add routes for on-link prefixes @@ -6252,6 +6254,28 @@ static int addrconf_sysctl_mtu(struct ctl_table *ctl, int write, return proc_dointvec_minmax(&lctl, write, buffer, lenp, ppos); } +static int addrconf_sysctl_accept_ra_min_lft(struct ctl_table *ctl, int write, + void *buffer, size_t *lenp, loff_t *ppos) +{ + struct ctl_table tmp = *ctl; + unsigned int min = 0, max = 65535U, val; + u16 *data = ctl->data; + int res; + + tmp.maxlen = sizeof(val); + tmp.data = &val; + tmp.extra1 = &min; + tmp.extra2 = &max; + val = READ_ONCE(*data); + + res = proc_douintvec_minmax(&tmp, write, buffer, lenp, ppos); + if (res) + return res; + if (write) + WRITE_ONCE(*data, val); + return 0; +} + static void dev_disable_change(struct inet6_dev *idev) { struct netdev_notifier_info info; @@ -6799,6 +6823,13 @@ static const struct ctl_table addrconf_sysctl[] = { .mode = 0644, .proc_handler = proc_dointvec, }, + { + .procname = "accept_ra_min_lft", + .data = &ACCEPT_RA_MIN_LFT(ipv6_devconf), + .maxlen = sizeof(u16), + .mode = 0644, + .proc_handler = addrconf_sysctl_accept_ra_min_lft, + }, { .procname = "accept_ra_pinfo", .data = &ipv6_devconf.accept_ra_pinfo, @@ -7251,6 +7282,10 @@ int __init addrconf_init(void) struct inet6_dev *idev; int i, err; + /* 0 initialize slot for accept_ra_min_lft */ + ACCEPT_RA_MIN_LFT(ipv6_devconf) = 0; + ACCEPT_RA_MIN_LFT(ipv6_devconf_dflt) = 0; + err = ipv6_addr_label_init(); if (err < 0) { pr_crit("%s: cannot initialize default policy table: %d\n", diff --git a/net/ipv6/icmp.c b/net/ipv6/icmp.c index 716e7717fe8f..71a69166a6bd 100644 --- a/net/ipv6/icmp.c +++ b/net/ipv6/icmp.c @@ -430,7 +430,10 @@ static struct net_device *icmp6_dev(const struct sk_buff *skb) if (unlikely(dev->ifindex == LOOPBACK_IFINDEX || netif_is_l3_master(skb->dev))) { const struct rt6_info *rt6 = skb_rt6_info(skb); - if (rt6) + /* The destination could be an external IP in Ext Hdr (SRv6, RPL, etc.), + * and ip6_null_entry could be set to skb if no route is found. + */ + if (rt6 && rt6->rt6i_idev) dev = rt6->rt6i_idev->dev; } diff --git a/net/ipv6/ip6_gre.c b/net/ipv6/ip6_gre.c index 0b041ab79ad9..0efd5b4346b0 100644 --- a/net/ipv6/ip6_gre.c +++ b/net/ipv6/ip6_gre.c @@ -955,7 +955,8 @@ static netdev_tx_t ip6erspan_tunnel_xmit(struct sk_buff *skb, goto tx_err; if (skb->len > dev->mtu + dev->hard_header_len) { - pskb_trim(skb, dev->mtu + dev->hard_header_len); + if (pskb_trim(skb, dev->mtu + dev->hard_header_len)) + goto tx_err; truncate = true; } diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c index 8108e9a941d0..fbfcd8c997d6 100644 --- a/net/ipv6/ndisc.c +++ b/net/ipv6/ndisc.c @@ -1269,6 +1269,14 @@ static void ndisc_router_discovery(struct sk_buff *skb) goto skip_defrtr; } + lifetime = ntohs(ra_msg->icmph.icmp6_rt_lifetime); + if (lifetime != 0 && lifetime < ACCEPT_RA_MIN_LFT(in6_dev->cnf)) { + ND_PRINTK(2, info, + "RA: router lifetime (%ds) is too short: %s\n", + lifetime, skb->dev->name); + goto skip_defrtr; + } + /* Do not accept RA with source-addr found on local machine unless * accept_ra_from_local is set to true. */ @@ -1281,8 +1289,6 @@ static void ndisc_router_discovery(struct sk_buff *skb) goto skip_defrtr; } - lifetime = ntohs(ra_msg->icmph.icmp6_rt_lifetime); - #ifdef CONFIG_IPV6_ROUTER_PREF pref = ra_msg->icmph.icmp6_router_pref; /* 10b is handled as if it were 00b (medium) */ @@ -1453,6 +1459,9 @@ skip_linkparms: if (ri->prefix_len == 0 && !in6_dev->cnf.accept_ra_defrtr) continue; + if (ri->lifetime != 0 && + ntohl(ri->lifetime) < ACCEPT_RA_MIN_LFT(in6_dev->cnf)) + continue; if (ri->prefix_len < in6_dev->cnf.accept_ra_rt_info_min_plen) continue; if (ri->prefix_len > in6_dev->cnf.accept_ra_rt_info_max_plen) diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index b6f5a4474d8b..c18fdddbfa09 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c @@ -1171,7 +1171,7 @@ static void tcp_v6_reqsk_send_ack(const struct sock *sk, struct sk_buff *skb, tcp_rsk(req)->rcv_nxt, req->rsk_rcv_wnd >> inet_rsk(req)->rcv_wscale, tcp_time_stamp_raw() + tcp_rsk(req)->ts_off, - req->ts_recent, sk->sk_bound_dev_if, + READ_ONCE(req->ts_recent), sk->sk_bound_dev_if, tcp_v6_md5_do_lookup(sk, &ipv6_hdr(skb)->saddr, l3index), ipv6_get_dsfield(ipv6_hdr(skb)), 0, sk->sk_priority); } diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c index 5161e98f6fcf..a746abbe81b5 100644 --- a/net/ipv6/udp.c +++ b/net/ipv6/udp.c @@ -88,7 +88,7 @@ static u32 udp6_ehashfn(const struct net *net, fhash = __ipv6_addr_jhash(faddr, udp_ipv6_hash_secret); return __inet6_ehashfn(lhash, lport, fhash, fport, - udp_ipv6_hash_secret + net_hash_mix(net)); + udp6_ehash_secret + net_hash_mix(net)); } int udp_v6_get_port(struct sock *sk, unsigned short snum) diff --git a/net/llc/llc_input.c b/net/llc/llc_input.c index c309b72a5877..7cac441862e2 100644 --- a/net/llc/llc_input.c +++ b/net/llc/llc_input.c @@ -163,9 +163,6 @@ int llc_rcv(struct sk_buff *skb, struct net_device *dev, void (*sta_handler)(struct sk_buff *skb); void (*sap_handler)(struct llc_sap *sap, struct sk_buff *skb); - if (!net_eq(dev_net(dev), &init_net)) - goto drop; - /* * When the interface is in promisc. mode, drop all the crap that it * receives, do not try to analyse it. diff --git a/net/mptcp/protocol.c b/net/mptcp/protocol.c index b6a38af72e1b..6941f5d68fa0 100644 --- a/net/mptcp/protocol.c +++ b/net/mptcp/protocol.c @@ -51,7 +51,7 @@ enum { static struct percpu_counter mptcp_sockets_allocated; static void __mptcp_destroy_sock(struct sock *sk); -static void __mptcp_check_send_data_fin(struct sock *sk); +static void mptcp_check_send_data_fin(struct sock *sk); DEFINE_PER_CPU(struct mptcp_delegated_action, mptcp_delegated_actions); static struct net_device mptcp_napi_dev; @@ -355,8 +355,7 @@ static bool mptcp_pending_data_fin_ack(struct sock *sk) { struct mptcp_sock *msk = mptcp_sk(sk); - return !__mptcp_check_fallback(msk) && - ((1 << sk->sk_state) & + return ((1 << sk->sk_state) & (TCPF_FIN_WAIT1 | TCPF_CLOSING | TCPF_LAST_ACK)) && msk->write_seq == READ_ONCE(msk->snd_una); } @@ -509,9 +508,6 @@ static bool mptcp_check_data_fin(struct sock *sk) u64 rcv_data_fin_seq; bool ret = false; - if (__mptcp_check_fallback(msk)) - return ret; - /* Need to ack a DATA_FIN received from a peer while this side * of the connection is in ESTABLISHED, FIN_WAIT1, or FIN_WAIT2. * msk->rcv_data_fin was set when parsing the incoming options @@ -549,7 +545,8 @@ static bool mptcp_check_data_fin(struct sock *sk) } ret = true; - mptcp_send_ack(msk); + if (!__mptcp_check_fallback(msk)) + mptcp_send_ack(msk); mptcp_close_wake_up(sk); } return ret; @@ -1612,7 +1609,7 @@ out: if (!mptcp_timer_pending(sk)) mptcp_reset_timer(sk); if (copied) - __mptcp_check_send_data_fin(sk); + mptcp_check_send_data_fin(sk); } static void __mptcp_subflow_push_pending(struct sock *sk, struct sock *ssk) @@ -2451,7 +2448,6 @@ static void mptcp_worker(struct work_struct *work) if (unlikely((1 << state) & (TCPF_CLOSE | TCPF_LISTEN))) goto unlock; - mptcp_check_data_fin_ack(sk); mptcp_flush_join_list(msk); mptcp_check_fastclose(msk); @@ -2462,7 +2458,8 @@ static void mptcp_worker(struct work_struct *work) if (test_and_clear_bit(MPTCP_WORK_EOF, &msk->flags)) mptcp_check_for_eof(msk); - __mptcp_check_send_data_fin(sk); + mptcp_check_send_data_fin(sk); + mptcp_check_data_fin_ack(sk); mptcp_check_data_fin(sk); /* There is no point in keeping around an orphaned sk timedout or @@ -2591,6 +2588,12 @@ void mptcp_subflow_shutdown(struct sock *sk, struct sock *ssk, int how) pr_debug("Fallback"); ssk->sk_shutdown |= how; tcp_shutdown(ssk, how); + + /* simulate the data_fin ack reception to let the state + * machine move forward + */ + WRITE_ONCE(mptcp_sk(sk)->snd_una, mptcp_sk(sk)->snd_nxt); + mptcp_schedule_work(sk); } else { pr_debug("Sending DATA_FIN on subflow %p", ssk); tcp_send_ack(ssk); @@ -2630,7 +2633,7 @@ static int mptcp_close_state(struct sock *sk) return next & TCP_ACTION_FIN; } -static void __mptcp_check_send_data_fin(struct sock *sk) +static void mptcp_check_send_data_fin(struct sock *sk) { struct mptcp_subflow_context *subflow; struct mptcp_sock *msk = mptcp_sk(sk); @@ -2648,18 +2651,6 @@ static void __mptcp_check_send_data_fin(struct sock *sk) WRITE_ONCE(msk->snd_nxt, msk->write_seq); - /* fallback socket will not get data_fin/ack, can move to the next - * state now - */ - if (__mptcp_check_fallback(msk)) { - if ((1 << sk->sk_state) & (TCPF_CLOSING | TCPF_LAST_ACK)) { - inet_sk_state_store(sk, TCP_CLOSE); - mptcp_close_wake_up(sk); - } else if (sk->sk_state == TCP_FIN_WAIT1) { - inet_sk_state_store(sk, TCP_FIN_WAIT2); - } - } - mptcp_flush_join_list(msk); mptcp_for_each_subflow(msk, subflow) { struct sock *tcp_sk = mptcp_subflow_tcp_sock(subflow); @@ -2680,7 +2671,7 @@ static void __mptcp_wr_shutdown(struct sock *sk) WRITE_ONCE(msk->write_seq, msk->write_seq + 1); WRITE_ONCE(msk->snd_data_fin_enable, 1); - __mptcp_check_send_data_fin(sk); + mptcp_check_send_data_fin(sk); } static void __mptcp_destroy_sock(struct sock *sk) diff --git a/net/mptcp/subflow.c b/net/mptcp/subflow.c index 9b89999062c9..666f6720db76 100644 --- a/net/mptcp/subflow.c +++ b/net/mptcp/subflow.c @@ -1653,14 +1653,16 @@ static void subflow_state_change(struct sock *sk) { struct mptcp_subflow_context *subflow = mptcp_subflow_ctx(sk); struct sock *parent = subflow->conn; + struct mptcp_sock *msk; __subflow_state_change(sk); + msk = mptcp_sk(parent); if (subflow_simultaneous_connect(sk)) { mptcp_propagate_sndbuf(parent, sk); mptcp_do_fallback(sk); - mptcp_rcv_space_init(mptcp_sk(parent), sk); - pr_fallback(mptcp_sk(parent)); + mptcp_rcv_space_init(msk, sk); + pr_fallback(msk); subflow->conn_finished = 1; mptcp_set_connected(parent); } @@ -1676,11 +1678,12 @@ static void subflow_state_change(struct sock *sk) subflow_sched_work_if_closed(mptcp_sk(parent), sk); - if (__mptcp_check_fallback(mptcp_sk(parent)) && - !subflow->rx_eof && subflow_is_done(sk)) { - subflow->rx_eof = 1; - mptcp_subflow_eof(parent); - } + /* when the fallback subflow closes the rx side, trigger a 'dummy' + * ingress data fin, so that the msk state will follow along + */ + if (__mptcp_check_fallback(msk) && subflow_is_done(sk) && msk->first == sk && + mptcp_update_rcv_data_fin(msk, READ_ONCE(msk->ack_seq), true)) + mptcp_schedule_work(parent); } static int subflow_ulp_init(struct sock *sk) diff --git a/net/netfilter/ipset/ip_set_core.c b/net/netfilter/ipset/ip_set_core.c index c911fc09f363..33869db42bb6 100644 --- a/net/netfilter/ipset/ip_set_core.c +++ b/net/netfilter/ipset/ip_set_core.c @@ -682,6 +682,14 @@ __ip_set_put(struct ip_set *set) /* set->ref can be swapped out by ip_set_swap, netlink events (like dump) need * a separate reference counter */ +static void +__ip_set_get_netlink(struct ip_set *set) +{ + write_lock_bh(&ip_set_ref_lock); + set->ref_netlink++; + write_unlock_bh(&ip_set_ref_lock); +} + static void __ip_set_put_netlink(struct ip_set *set) { @@ -1695,11 +1703,11 @@ call_ad(struct net *net, struct sock *ctnl, struct sk_buff *skb, do { if (retried) { - __ip_set_get(set); + __ip_set_get_netlink(set); nfnl_unlock(NFNL_SUBSYS_IPSET); cond_resched(); nfnl_lock(NFNL_SUBSYS_IPSET); - __ip_set_put(set); + __ip_set_put_netlink(set); } ip_set_lock(set); diff --git a/net/netfilter/ipset/ip_set_hash_netportnet.c b/net/netfilter/ipset/ip_set_hash_netportnet.c index 005a7ce87217..bf4f91b78e1d 100644 --- a/net/netfilter/ipset/ip_set_hash_netportnet.c +++ b/net/netfilter/ipset/ip_set_hash_netportnet.c @@ -36,6 +36,7 @@ MODULE_ALIAS("ip_set_hash:net,port,net"); #define IP_SET_HASH_WITH_PROTO #define IP_SET_HASH_WITH_NETS #define IPSET_NET_COUNT 2 +#define IP_SET_HASH_WITH_NET0 /* IPv4 variant */ diff --git a/net/netfilter/ipvs/Kconfig b/net/netfilter/ipvs/Kconfig index 271da8447b29..2a3017b9c001 100644 --- a/net/netfilter/ipvs/Kconfig +++ b/net/netfilter/ipvs/Kconfig @@ -44,7 +44,8 @@ config IP_VS_DEBUG config IP_VS_TAB_BITS int "IPVS connection table size (the Nth power of 2)" - range 8 20 + range 8 20 if !64BIT + range 8 27 if 64BIT default 12 help The IPVS connection hash table uses the chaining scheme to handle @@ -54,24 +55,24 @@ config IP_VS_TAB_BITS Note the table size must be power of 2. The table size will be the value of 2 to the your input number power. The number to choose is - from 8 to 20, the default number is 12, which means the table size - is 4096. Don't input the number too small, otherwise you will lose - performance on it. You can adapt the table size yourself, according - to your virtual server application. It is good to set the table size - not far less than the number of connections per second multiplying - average lasting time of connection in the table. For example, your - virtual server gets 200 connections per second, the connection lasts - for 200 seconds in average in the connection table, the table size - should be not far less than 200x200, it is good to set the table - size 32768 (2**15). + from 8 to 27 for 64BIT(20 otherwise), the default number is 12, + which means the table size is 4096. Don't input the number too + small, otherwise you will lose performance on it. You can adapt the + table size yourself, according to your virtual server application. + It is good to set the table size not far less than the number of + connections per second multiplying average lasting time of + connection in the table. For example, your virtual server gets 200 + connections per second, the connection lasts for 200 seconds in + average in the connection table, the table size should be not far + less than 200x200, it is good to set the table size 32768 (2**15). Another note that each connection occupies 128 bytes effectively and each hash entry uses 8 bytes, so you can estimate how much memory is needed for your box. You can overwrite this number setting conn_tab_bits module parameter - or by appending ip_vs.conn_tab_bits=? to the kernel command line - if IP VS was compiled built-in. + or by appending ip_vs.conn_tab_bits=? to the kernel command line if + IP VS was compiled built-in. comment "IPVS transport protocol load balancing support" diff --git a/net/netfilter/ipvs/ip_vs_conn.c b/net/netfilter/ipvs/ip_vs_conn.c index cb6d68220c26..3252d67b6df0 100644 --- a/net/netfilter/ipvs/ip_vs_conn.c +++ b/net/netfilter/ipvs/ip_vs_conn.c @@ -1484,8 +1484,8 @@ int __init ip_vs_conn_init(void) int idx; /* Compute size and mask */ - if (ip_vs_conn_tab_bits < 8 || ip_vs_conn_tab_bits > 20) { - pr_info("conn_tab_bits not in [8, 20]. Using default value\n"); + if (ip_vs_conn_tab_bits < 8 || ip_vs_conn_tab_bits > 27) { + pr_info("conn_tab_bits not in [8, 27]. Using default value\n"); ip_vs_conn_tab_bits = CONFIG_IP_VS_TAB_BITS; } ip_vs_conn_tab_size = 1 << ip_vs_conn_tab_bits; diff --git a/net/netfilter/nf_conntrack_helper.c b/net/netfilter/nf_conntrack_helper.c index ceb38a7b37cb..41c9708b5057 100644 --- a/net/netfilter/nf_conntrack_helper.c +++ b/net/netfilter/nf_conntrack_helper.c @@ -405,6 +405,9 @@ int nf_conntrack_helper_register(struct nf_conntrack_helper *me) BUG_ON(me->expect_class_max >= NF_CT_MAX_EXPECT_CLASSES); BUG_ON(strlen(me->name) > NF_CT_HELPER_NAME_LEN - 1); + if (!nf_ct_helper_hash) + return -ENOENT; + if (me->expect_policy->max_expected > NF_CT_EXPECT_MAX_CNT) return -EINVAL; @@ -595,4 +598,5 @@ void nf_conntrack_helper_fini(void) { nf_ct_extend_unregister(&helper_extend); kvfree(nf_ct_helper_hash); + nf_ct_helper_hash = NULL; } diff --git a/net/netfilter/nf_conntrack_proto_dccp.c b/net/netfilter/nf_conntrack_proto_dccp.c index c1557d47ccd1..d4fd626d2b8c 100644 --- a/net/netfilter/nf_conntrack_proto_dccp.c +++ b/net/netfilter/nf_conntrack_proto_dccp.c @@ -432,9 +432,19 @@ static bool dccp_error(const struct dccp_hdr *dh, struct sk_buff *skb, unsigned int dataoff, const struct nf_hook_state *state) { + static const unsigned long require_seq48 = 1 << DCCP_PKT_REQUEST | + 1 << DCCP_PKT_RESPONSE | + 1 << DCCP_PKT_CLOSEREQ | + 1 << DCCP_PKT_CLOSE | + 1 << DCCP_PKT_RESET | + 1 << DCCP_PKT_SYNC | + 1 << DCCP_PKT_SYNCACK; unsigned int dccp_len = skb->len - dataoff; unsigned int cscov; const char *msg; + u8 type; + + BUILD_BUG_ON(DCCP_PKT_INVALID >= BITS_PER_LONG); if (dh->dccph_doff * 4 < sizeof(struct dccp_hdr) || dh->dccph_doff * 4 > dccp_len) { @@ -459,34 +469,70 @@ static bool dccp_error(const struct dccp_hdr *dh, goto out_invalid; } - if (dh->dccph_type >= DCCP_PKT_INVALID) { + type = dh->dccph_type; + if (type >= DCCP_PKT_INVALID) { msg = "nf_ct_dccp: reserved packet type "; goto out_invalid; } + + if (test_bit(type, &require_seq48) && !dh->dccph_x) { + msg = "nf_ct_dccp: type lacks 48bit sequence numbers"; + goto out_invalid; + } + return false; out_invalid: nf_l4proto_log_invalid(skb, state, IPPROTO_DCCP, "%s", msg); return true; } +struct nf_conntrack_dccp_buf { + struct dccp_hdr dh; /* generic header part */ + struct dccp_hdr_ext ext; /* optional depending dh->dccph_x */ + union { /* depends on header type */ + struct dccp_hdr_ack_bits ack; + struct dccp_hdr_request req; + struct dccp_hdr_response response; + struct dccp_hdr_reset rst; + } u; +}; + +static struct dccp_hdr * +dccp_header_pointer(const struct sk_buff *skb, int offset, const struct dccp_hdr *dh, + struct nf_conntrack_dccp_buf *buf) +{ + unsigned int hdrlen = __dccp_hdr_len(dh); + + if (hdrlen > sizeof(*buf)) + return NULL; + + return skb_header_pointer(skb, offset, hdrlen, buf); +} + int nf_conntrack_dccp_packet(struct nf_conn *ct, struct sk_buff *skb, unsigned int dataoff, enum ip_conntrack_info ctinfo, const struct nf_hook_state *state) { enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo); - struct dccp_hdr _dh, *dh; + struct nf_conntrack_dccp_buf _dh; u_int8_t type, old_state, new_state; enum ct_dccp_roles role; unsigned int *timeouts; + struct dccp_hdr *dh; - dh = skb_header_pointer(skb, dataoff, sizeof(_dh), &_dh); + dh = skb_header_pointer(skb, dataoff, sizeof(*dh), &_dh.dh); if (!dh) return NF_DROP; if (dccp_error(dh, skb, dataoff, state)) return -NF_ACCEPT; + /* pull again, including possible 48 bit sequences and subtype header */ + dh = dccp_header_pointer(skb, dataoff, dh, &_dh); + if (!dh) + return NF_DROP; + type = dh->dccph_type; if (!nf_ct_is_confirmed(ct) && !dccp_new(ct, skb, dh, state)) return -NF_ACCEPT; diff --git a/net/netfilter/nf_conntrack_sip.c b/net/netfilter/nf_conntrack_sip.c index 78fd9122b70c..751df19fe0f8 100644 --- a/net/netfilter/nf_conntrack_sip.c +++ b/net/netfilter/nf_conntrack_sip.c @@ -611,7 +611,7 @@ int ct_sip_parse_numerical_param(const struct nf_conn *ct, const char *dptr, start += strlen(name); *val = simple_strtoul(start, &end, 0); if (start == end) - return 0; + return -1; if (matchoff && matchlen) { *matchoff = start - dptr; *matchlen = end - start; diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c index 37f42526a598..c7f95402ec7e 100644 --- a/net/netfilter/nf_tables_api.c +++ b/net/netfilter/nf_tables_api.c @@ -581,6 +581,58 @@ static int nft_trans_set_add(const struct nft_ctx *ctx, int msg_type, return __nft_trans_set_add(ctx, msg_type, set, NULL); } +static void nft_setelem_data_deactivate(const struct net *net, + const struct nft_set *set, + struct nft_set_elem *elem); + +static int nft_mapelem_deactivate(const struct nft_ctx *ctx, + struct nft_set *set, + const struct nft_set_iter *iter, + struct nft_set_elem *elem) +{ + nft_setelem_data_deactivate(ctx->net, set, elem); + + return 0; +} + +struct nft_set_elem_catchall { + struct list_head list; + struct rcu_head rcu; + void *elem; +}; + +static void nft_map_catchall_deactivate(const struct nft_ctx *ctx, + struct nft_set *set) +{ + u8 genmask = nft_genmask_next(ctx->net); + struct nft_set_elem_catchall *catchall; + struct nft_set_elem elem; + struct nft_set_ext *ext; + + list_for_each_entry(catchall, &set->catchall_list, list) { + ext = nft_set_elem_ext(set, catchall->elem); + if (!nft_set_elem_active(ext, genmask)) + continue; + + elem.priv = catchall->elem; + nft_setelem_data_deactivate(ctx->net, set, &elem); + break; + } +} + +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), + .fn = nft_mapelem_deactivate, + }; + + set->ops->walk(ctx, set, &iter); + WARN_ON_ONCE(iter.err); + + nft_map_catchall_deactivate(ctx, set); +} + static int nft_delset(const struct nft_ctx *ctx, struct nft_set *set) { int err; @@ -589,6 +641,9 @@ static int nft_delset(const struct nft_ctx *ctx, struct nft_set *set) if (err < 0) return err; + if (set->flags & (NFT_SET_MAP | NFT_SET_OBJECT)) + nft_map_deactivate(ctx, set); + nft_deactivate_next(ctx->net, set); ctx->table->use--; @@ -1286,7 +1341,7 @@ static int nft_flush_table(struct nft_ctx *ctx) if (!nft_is_active_next(ctx->net, chain)) continue; - if (nft_chain_is_bound(chain)) + if (nft_chain_binding(chain)) continue; ctx->chain = chain; @@ -1331,7 +1386,7 @@ static int nft_flush_table(struct nft_ctx *ctx) if (!nft_is_active_next(ctx->net, chain)) continue; - if (nft_chain_is_bound(chain)) + if (nft_chain_binding(chain)) continue; ctx->chain = chain; @@ -2478,7 +2533,7 @@ err: static struct nft_chain *nft_chain_lookup_byid(const struct net *net, const struct nft_table *table, - const struct nlattr *nla) + const struct nlattr *nla, u8 genmask) { struct nftables_pernet *nft_net = nft_pernet(net); u32 id = ntohl(nla_get_be32(nla)); @@ -2489,7 +2544,8 @@ static struct nft_chain *nft_chain_lookup_byid(const struct net *net, if (trans->msg_type == NFT_MSG_NEWCHAIN && chain->table == table && - id == nft_trans_chain_id(trans)) + id == nft_trans_chain_id(trans) && + nft_active_genmask(chain, genmask)) return chain; } return ERR_PTR(-ENOENT); @@ -2632,6 +2688,9 @@ static int nf_tables_delchain(struct sk_buff *skb, const struct nfnl_info *info, return PTR_ERR(chain); } + if (nft_chain_binding(chain)) + return -EOPNOTSUPP; + if (info->nlh->nlmsg_flags & NLM_F_NONREC && chain->use > 0) return -EBUSY; @@ -3407,12 +3466,6 @@ int nft_setelem_validate(const struct nft_ctx *ctx, struct nft_set *set, return 0; } -struct nft_set_elem_catchall { - struct list_head list; - struct rcu_head rcu; - void *elem; -}; - int nft_set_catchall_validate(const struct nft_ctx *ctx, struct nft_set *set) { u8 genmask = nft_genmask_next(ctx->net); @@ -3479,11 +3532,10 @@ static int nf_tables_newrule(struct sk_buff *skb, const struct nfnl_info *info, NL_SET_BAD_ATTR(extack, nla[NFTA_RULE_CHAIN]); return PTR_ERR(chain); } - if (nft_chain_is_bound(chain)) - return -EOPNOTSUPP; } else if (nla[NFTA_RULE_CHAIN_ID]) { - chain = nft_chain_lookup_byid(net, table, nla[NFTA_RULE_CHAIN_ID]); + chain = nft_chain_lookup_byid(net, table, nla[NFTA_RULE_CHAIN_ID], + genmask); if (IS_ERR(chain)) { NL_SET_BAD_ATTR(extack, nla[NFTA_RULE_CHAIN_ID]); return PTR_ERR(chain); @@ -3492,6 +3544,9 @@ static int nf_tables_newrule(struct sk_buff *skb, const struct nfnl_info *info, return -EINVAL; } + if (nft_chain_is_bound(chain)) + return -EOPNOTSUPP; + if (nla[NFTA_RULE_HANDLE]) { handle = be64_to_cpu(nla_get_be64(nla[NFTA_RULE_HANDLE])); rule = __nft_rule_lookup(chain, handle); @@ -3611,6 +3666,11 @@ static int nf_tables_newrule(struct sk_buff *skb, const struct nfnl_info *info, } if (info->nlh->nlmsg_flags & NLM_F_REPLACE) { + if (nft_chain_binding(chain)) { + err = -EOPNOTSUPP; + goto err_destroy_flow_rule; + } + err = nft_delrule(&ctx, old_rule); if (err < 0) goto err_destroy_flow_rule; @@ -3714,7 +3774,7 @@ static int nf_tables_delrule(struct sk_buff *skb, const struct nfnl_info *info, NL_SET_BAD_ATTR(extack, nla[NFTA_RULE_CHAIN]); return PTR_ERR(chain); } - if (nft_chain_is_bound(chain)) + if (nft_chain_binding(chain)) return -EOPNOTSUPP; } @@ -3744,7 +3804,7 @@ static int nf_tables_delrule(struct sk_buff *skb, const struct nfnl_info *info, list_for_each_entry(chain, &table->chains, list) { if (!nft_is_active_next(net, chain)) continue; - if (nft_chain_is_bound(chain)) + if (nft_chain_binding(chain)) continue; ctx.chain = chain; @@ -4736,7 +4796,7 @@ err_set_expr_alloc: for (i = 0; i < set->num_exprs; i++) nft_expr_destroy(&ctx, set->exprs[i]); err_set_destroy: - ops->destroy(set); + ops->destroy(&ctx, set); err_set_init: kfree(set->name); err_set_name: @@ -4751,7 +4811,7 @@ static void nft_set_catchall_destroy(const struct nft_ctx *ctx, list_for_each_entry_safe(catchall, next, &set->catchall_list, list) { list_del_rcu(&catchall->list); - nft_set_elem_destroy(set, catchall->elem, true); + nf_tables_set_elem_destroy(ctx, set, catchall->elem); kfree_rcu(catchall, rcu); } } @@ -4766,7 +4826,7 @@ static void nft_set_destroy(const struct nft_ctx *ctx, struct nft_set *set) for (i = 0; i < set->num_exprs; i++) nft_expr_destroy(ctx, set->exprs[i]); - set->ops->destroy(set); + set->ops->destroy(ctx, set); nft_set_catchall_destroy(ctx, set); kfree(set->name); kvfree(set); @@ -4927,10 +4987,60 @@ static void nf_tables_unbind_set(const struct nft_ctx *ctx, struct nft_set *set, } } +static void nft_setelem_data_activate(const struct net *net, + const struct nft_set *set, + struct nft_set_elem *elem); + +static int nft_mapelem_activate(const struct nft_ctx *ctx, + struct nft_set *set, + const struct nft_set_iter *iter, + struct nft_set_elem *elem) +{ + nft_setelem_data_activate(ctx->net, set, elem); + + return 0; +} + +static void nft_map_catchall_activate(const struct nft_ctx *ctx, + struct nft_set *set) +{ + u8 genmask = nft_genmask_next(ctx->net); + struct nft_set_elem_catchall *catchall; + struct nft_set_elem elem; + struct nft_set_ext *ext; + + list_for_each_entry(catchall, &set->catchall_list, list) { + ext = nft_set_elem_ext(set, catchall->elem); + if (!nft_set_elem_active(ext, genmask)) + continue; + + elem.priv = catchall->elem; + nft_setelem_data_activate(ctx->net, set, &elem); + break; + } +} + +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), + .fn = nft_mapelem_activate, + }; + + set->ops->walk(ctx, set, &iter); + WARN_ON_ONCE(iter.err); + + nft_map_catchall_activate(ctx, set); +} + void nf_tables_activate_set(const struct nft_ctx *ctx, struct nft_set *set) { - if (nft_set_is_anonymous(set)) + if (nft_set_is_anonymous(set)) { + if (set->flags & (NFT_SET_MAP | NFT_SET_OBJECT)) + nft_map_activate(ctx, set); + nft_clear(ctx->net, set); + } set->use++; } @@ -4945,17 +5055,26 @@ void nf_tables_deactivate_set(const struct nft_ctx *ctx, struct nft_set *set, nft_set_trans_unbind(ctx, set); if (nft_set_is_anonymous(set)) nft_deactivate_next(ctx->net, set); + else + list_del_rcu(&binding->list); set->use--; break; case NFT_TRANS_PREPARE: - if (nft_set_is_anonymous(set)) - nft_deactivate_next(ctx->net, set); + if (nft_set_is_anonymous(set)) { + if (set->flags & (NFT_SET_MAP | NFT_SET_OBJECT)) + nft_map_deactivate(ctx, set); + nft_deactivate_next(ctx->net, set); + } set->use--; return; case NFT_TRANS_ABORT: case NFT_TRANS_RELEASE: + if (nft_set_is_anonymous(set) && + set->flags & (NFT_SET_MAP | NFT_SET_OBJECT)) + nft_map_deactivate(ctx, set); + set->use--; fallthrough; default: @@ -5671,6 +5790,7 @@ static void nft_set_elem_expr_destroy(const struct nft_ctx *ctx, __nft_set_elem_expr_destroy(ctx, expr); } +/* Drop references and destroy. Called from gc, dynset and abort path. */ void nft_set_elem_destroy(const struct nft_set *set, void *elem, bool destroy_expr) { @@ -5692,11 +5812,11 @@ void nft_set_elem_destroy(const struct nft_set *set, void *elem, } EXPORT_SYMBOL_GPL(nft_set_elem_destroy); -/* Only called from commit path, nft_setelem_data_deactivate() already deals - * with the refcounting from the preparation phase. +/* Destroy element. References have been already dropped in the preparation + * path via nft_setelem_data_deactivate(). */ -static void nf_tables_set_elem_destroy(const struct nft_ctx *ctx, - const struct nft_set *set, void *elem) +void nf_tables_set_elem_destroy(const struct nft_ctx *ctx, + const struct nft_set *set, void *elem) { struct nft_set_ext *ext = nft_set_elem_ext(set, elem); @@ -6585,6 +6705,7 @@ static int nft_set_catchall_flush(const struct nft_ctx *ctx, ret = __nft_set_catchall_flush(ctx, set, &elem); if (ret < 0) break; + nft_set_elem_change_active(ctx->net, set, ext); } return ret; @@ -9325,6 +9446,9 @@ static int __nf_tables_abort(struct net *net, enum nfnl_abort_action action) case NFT_MSG_DELSET: trans->ctx.table->use++; nft_clear(trans->ctx.net, nft_trans_set(trans)); + if (nft_trans_set(trans)->flags & (NFT_SET_MAP | NFT_SET_OBJECT)) + nft_map_activate(&trans->ctx, nft_trans_set(trans)); + nft_trans_destroy(trans); break; case NFT_MSG_NEWSETELEM: @@ -9796,6 +9920,9 @@ static int nft_verdict_init(const struct nft_ctx *ctx, struct nft_data *data, if (!tb[NFTA_VERDICT_CODE]) return -EINVAL; + + /* zero padding hole for memcmp */ + memset(data, 0, sizeof(*data)); data->verdict.code = ntohl(nla_get_be32(tb[NFTA_VERDICT_CODE])); switch (data->verdict.code) { @@ -9821,7 +9948,8 @@ static int nft_verdict_init(const struct nft_ctx *ctx, struct nft_data *data, genmask); } else if (tb[NFTA_VERDICT_CHAIN_ID]) { chain = nft_chain_lookup_byid(ctx->net, ctx->table, - tb[NFTA_VERDICT_CHAIN_ID]); + tb[NFTA_VERDICT_CHAIN_ID], + genmask); if (IS_ERR(chain)) return PTR_ERR(chain); } else { @@ -10076,6 +10204,9 @@ static void __nft_release_table(struct net *net, struct nft_table *table) ctx.family = table->family; ctx.table = table; list_for_each_entry(chain, &table->chains, list) { + if (nft_chain_is_bound(chain)) + continue; + ctx.chain = chain; list_for_each_entry_safe(rule, nr, &chain->rules, list) { list_del(&rule->list); @@ -10091,6 +10222,9 @@ static void __nft_release_table(struct net *net, struct nft_table *table) list_for_each_entry_safe(set, ns, &table->sets, list) { list_del(&set->list); table->use--; + if (set->flags & (NFT_SET_MAP | NFT_SET_OBJECT)) + nft_map_deactivate(&ctx, set); + nft_set_destroy(&ctx, set); } list_for_each_entry_safe(obj, ne, &table->objects, list) { diff --git a/net/netfilter/nfnetlink_log.c b/net/netfilter/nfnetlink_log.c index 7f83f9697fc1..bf6d7f96dd5b 100644 --- a/net/netfilter/nfnetlink_log.c +++ b/net/netfilter/nfnetlink_log.c @@ -587,9 +587,9 @@ __build_packet_message(struct nfnl_log_net *log, goto nla_put_failure; } - if (hooknum <= NF_INET_FORWARD && skb->tstamp) { + if (hooknum <= NF_INET_FORWARD) { struct nfulnl_msg_packet_timestamp ts; - struct timespec64 kts = ktime_to_timespec64(skb->tstamp); + struct timespec64 kts = ktime_to_timespec64(skb->tstamp ?: ktime_get_real()); ts.sec = cpu_to_be64(kts.tv_sec); ts.usec = cpu_to_be64(kts.tv_nsec / NSEC_PER_USEC); diff --git a/net/netfilter/nfnetlink_osf.c b/net/netfilter/nfnetlink_osf.c index 8f1bfa6ccc2d..50723ba08289 100644 --- a/net/netfilter/nfnetlink_osf.c +++ b/net/netfilter/nfnetlink_osf.c @@ -315,6 +315,14 @@ static int nfnl_osf_add_callback(struct sk_buff *skb, f = nla_data(osf_attrs[OSF_ATTR_FINGER]); + if (f->opt_num > ARRAY_SIZE(f->opt)) + return -EINVAL; + + if (!memchr(f->genre, 0, MAXGENRELEN) || + !memchr(f->subtype, 0, MAXGENRELEN) || + !memchr(f->version, 0, MAXGENRELEN)) + return -EINVAL; + kf = kmalloc(sizeof(struct nf_osf_finger), GFP_KERNEL); if (!kf) return -ENOMEM; diff --git a/net/netfilter/nft_byteorder.c b/net/netfilter/nft_byteorder.c index 9d5947ab8d4e..7b0b8fecb220 100644 --- a/net/netfilter/nft_byteorder.c +++ b/net/netfilter/nft_byteorder.c @@ -30,11 +30,11 @@ void nft_byteorder_eval(const struct nft_expr *expr, const struct nft_byteorder *priv = nft_expr_priv(expr); u32 *src = ®s->data[priv->sreg]; u32 *dst = ®s->data[priv->dreg]; - union { u32 u32; u16 u16; } *s, *d; + u16 *s16, *d16; unsigned int i; - s = (void *)src; - d = (void *)dst; + s16 = (void *)src; + d16 = (void *)dst; switch (priv->size) { case 8: { @@ -61,11 +61,11 @@ void nft_byteorder_eval(const struct nft_expr *expr, switch (priv->op) { case NFT_BYTEORDER_NTOH: for (i = 0; i < priv->len / 4; i++) - d[i].u32 = ntohl((__force __be32)s[i].u32); + dst[i] = ntohl((__force __be32)src[i]); break; case NFT_BYTEORDER_HTON: for (i = 0; i < priv->len / 4; i++) - d[i].u32 = (__force __u32)htonl(s[i].u32); + dst[i] = (__force __u32)htonl(src[i]); break; } break; @@ -73,11 +73,11 @@ void nft_byteorder_eval(const struct nft_expr *expr, switch (priv->op) { case NFT_BYTEORDER_NTOH: for (i = 0; i < priv->len / 2; i++) - d[i].u16 = ntohs((__force __be16)s[i].u16); + d16[i] = ntohs((__force __be16)s16[i]); break; case NFT_BYTEORDER_HTON: for (i = 0; i < priv->len / 2; i++) - d[i].u16 = (__force __u16)htons(s[i].u16); + d16[i] = (__force __u16)htons(s16[i]); break; } break; diff --git a/net/netfilter/nft_set_bitmap.c b/net/netfilter/nft_set_bitmap.c index e7ae5914971e..60122539fee6 100644 --- a/net/netfilter/nft_set_bitmap.c +++ b/net/netfilter/nft_set_bitmap.c @@ -271,13 +271,14 @@ static int nft_bitmap_init(const struct nft_set *set, return 0; } -static void nft_bitmap_destroy(const struct nft_set *set) +static void nft_bitmap_destroy(const struct nft_ctx *ctx, + const struct nft_set *set) { struct nft_bitmap *priv = nft_set_priv(set); struct nft_bitmap_elem *be, *n; list_for_each_entry_safe(be, n, &priv->list, head) - nft_set_elem_destroy(set, be, true); + nf_tables_set_elem_destroy(ctx, set, be); } static bool nft_bitmap_estimate(const struct nft_set_desc *desc, u32 features, diff --git a/net/netfilter/nft_set_hash.c b/net/netfilter/nft_set_hash.c index 76de6c8d9865..0b73cb0e752f 100644 --- a/net/netfilter/nft_set_hash.c +++ b/net/netfilter/nft_set_hash.c @@ -400,19 +400,31 @@ static int nft_rhash_init(const struct nft_set *set, return 0; } +struct nft_rhash_ctx { + const struct nft_ctx ctx; + const struct nft_set *set; +}; + static void nft_rhash_elem_destroy(void *ptr, void *arg) { - nft_set_elem_destroy(arg, ptr, true); + struct nft_rhash_ctx *rhash_ctx = arg; + + nf_tables_set_elem_destroy(&rhash_ctx->ctx, rhash_ctx->set, ptr); } -static void nft_rhash_destroy(const struct nft_set *set) +static void nft_rhash_destroy(const struct nft_ctx *ctx, + const struct nft_set *set) { struct nft_rhash *priv = nft_set_priv(set); + struct nft_rhash_ctx rhash_ctx = { + .ctx = *ctx, + .set = set, + }; cancel_delayed_work_sync(&priv->gc_work); rcu_barrier(); rhashtable_free_and_destroy(&priv->ht, nft_rhash_elem_destroy, - (void *)set); + (void *)&rhash_ctx); } /* Number of buckets is stored in u32, so cap our result to 1U<<31 */ @@ -643,7 +655,8 @@ static int nft_hash_init(const struct nft_set *set, return 0; } -static void nft_hash_destroy(const struct nft_set *set) +static void nft_hash_destroy(const struct nft_ctx *ctx, + const struct nft_set *set) { struct nft_hash *priv = nft_set_priv(set); struct nft_hash_elem *he; @@ -653,7 +666,7 @@ static void nft_hash_destroy(const struct nft_set *set) for (i = 0; i < priv->buckets; i++) { hlist_for_each_entry_safe(he, next, &priv->table[i], node) { hlist_del_rcu(&he->node); - nft_set_elem_destroy(set, he, true); + nf_tables_set_elem_destroy(ctx, set, he); } } } diff --git a/net/netfilter/nft_set_pipapo.c b/net/netfilter/nft_set_pipapo.c index 9da4b4e24c34..a81829c10fea 100644 --- a/net/netfilter/nft_set_pipapo.c +++ b/net/netfilter/nft_set_pipapo.c @@ -2156,10 +2156,12 @@ out_scratch: /** * nft_set_pipapo_match_destroy() - Destroy elements from key mapping array + * @ctx: context * @set: nftables API set representation * @m: matching data pointing to key mapping array */ -static void nft_set_pipapo_match_destroy(const struct nft_set *set, +static void nft_set_pipapo_match_destroy(const struct nft_ctx *ctx, + const struct nft_set *set, struct nft_pipapo_match *m) { struct nft_pipapo_field *f; @@ -2176,15 +2178,17 @@ static void nft_set_pipapo_match_destroy(const struct nft_set *set, e = f->mt[r].e; - nft_set_elem_destroy(set, e, true); + nf_tables_set_elem_destroy(ctx, set, e); } } /** * nft_pipapo_destroy() - Free private data for set and all committed elements + * @ctx: context * @set: nftables API set representation */ -static void nft_pipapo_destroy(const struct nft_set *set) +static void nft_pipapo_destroy(const struct nft_ctx *ctx, + const struct nft_set *set) { struct nft_pipapo *priv = nft_set_priv(set); struct nft_pipapo_match *m; @@ -2194,7 +2198,7 @@ static void nft_pipapo_destroy(const struct nft_set *set) if (m) { rcu_barrier(); - nft_set_pipapo_match_destroy(set, m); + nft_set_pipapo_match_destroy(ctx, set, m); #ifdef NFT_PIPAPO_ALIGN free_percpu(m->scratch_aligned); @@ -2211,7 +2215,7 @@ static void nft_pipapo_destroy(const struct nft_set *set) m = priv->clone; if (priv->dirty) - nft_set_pipapo_match_destroy(set, m); + nft_set_pipapo_match_destroy(ctx, set, m); #ifdef NFT_PIPAPO_ALIGN free_percpu(priv->clone->scratch_aligned); diff --git a/net/netfilter/nft_set_rbtree.c b/net/netfilter/nft_set_rbtree.c index 2f114aa10f1a..5c05c9b990fb 100644 --- a/net/netfilter/nft_set_rbtree.c +++ b/net/netfilter/nft_set_rbtree.c @@ -664,7 +664,8 @@ static int nft_rbtree_init(const struct nft_set *set, return 0; } -static void nft_rbtree_destroy(const struct nft_set *set) +static void nft_rbtree_destroy(const struct nft_ctx *ctx, + const struct nft_set *set) { struct nft_rbtree *priv = nft_set_priv(set); struct nft_rbtree_elem *rbe; @@ -675,7 +676,7 @@ static void nft_rbtree_destroy(const struct nft_set *set) while ((node = priv->root.rb_node) != NULL) { rb_erase(node, &priv->root); rbe = rb_entry(node, struct nft_rbtree_elem, node); - nft_set_elem_destroy(set, rbe, true); + nf_tables_set_elem_destroy(ctx, set, rbe); } } diff --git a/net/netfilter/xt_sctp.c b/net/netfilter/xt_sctp.c index 680015ba7cb6..d4bf089c9e3f 100644 --- a/net/netfilter/xt_sctp.c +++ b/net/netfilter/xt_sctp.c @@ -150,6 +150,8 @@ static int sctp_mt_check(const struct xt_mtchk_param *par) { const struct xt_sctp_info *info = par->matchinfo; + if (info->flag_count > ARRAY_SIZE(info->flag_info)) + return -EINVAL; if (info->flags & ~XT_SCTP_VALID_FLAGS) return -EINVAL; if (info->invflags & ~XT_SCTP_VALID_FLAGS) diff --git a/net/netfilter/xt_u32.c b/net/netfilter/xt_u32.c index 177b40d08098..117d4615d668 100644 --- a/net/netfilter/xt_u32.c +++ b/net/netfilter/xt_u32.c @@ -96,11 +96,32 @@ static bool u32_mt(const struct sk_buff *skb, struct xt_action_param *par) return ret ^ data->invert; } +static int u32_mt_checkentry(const struct xt_mtchk_param *par) +{ + const struct xt_u32 *data = par->matchinfo; + const struct xt_u32_test *ct; + unsigned int i; + + if (data->ntests > ARRAY_SIZE(data->tests)) + return -EINVAL; + + for (i = 0; i < data->ntests; ++i) { + ct = &data->tests[i]; + + if (ct->nnums > ARRAY_SIZE(ct->location) || + ct->nvalues > ARRAY_SIZE(ct->value)) + return -EINVAL; + } + + return 0; +} + static struct xt_match xt_u32_mt_reg __read_mostly = { .name = "u32", .revision = 0, .family = NFPROTO_UNSPEC, .match = u32_mt, + .checkentry = u32_mt_checkentry, .matchsize = sizeof(struct xt_u32), .me = THIS_MODULE, }; diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c index 46c4306ddee7..f41e130a812f 100644 --- a/net/netlink/af_netlink.c +++ b/net/netlink/af_netlink.c @@ -1610,6 +1610,7 @@ out: int netlink_set_err(struct sock *ssk, u32 portid, u32 group, int code) { struct netlink_set_err_data info; + unsigned long flags; struct sock *sk; int ret = 0; @@ -1619,12 +1620,12 @@ int netlink_set_err(struct sock *ssk, u32 portid, u32 group, int code) /* sk->sk_err wants a positive error value */ info.code = -code; - read_lock(&nl_table_lock); + read_lock_irqsave(&nl_table_lock, flags); sk_for_each_bound(sk, &nl_table[ssk->sk_protocol].mc_list) ret += do_one_set_err(sk, &info); - read_unlock(&nl_table_lock); + read_unlock_irqrestore(&nl_table_lock, flags); return ret; } EXPORT_SYMBOL(netlink_set_err); diff --git a/net/netlink/diag.c b/net/netlink/diag.c index c6255eac305c..e4f21b1067bc 100644 --- a/net/netlink/diag.c +++ b/net/netlink/diag.c @@ -94,6 +94,7 @@ static int __netlink_diag_dump(struct sk_buff *skb, struct netlink_callback *cb, struct net *net = sock_net(skb->sk); struct netlink_diag_req *req; struct netlink_sock *nlsk; + unsigned long flags; struct sock *sk; int num = 2; int ret = 0; @@ -152,7 +153,7 @@ static int __netlink_diag_dump(struct sk_buff *skb, struct netlink_callback *cb, num++; mc_list: - read_lock(&nl_table_lock); + read_lock_irqsave(&nl_table_lock, flags); sk_for_each_bound(sk, &tbl->mc_list) { if (sk_hashed(sk)) continue; @@ -167,13 +168,13 @@ mc_list: NETLINK_CB(cb->skb).portid, cb->nlh->nlmsg_seq, NLM_F_MULTI, - sock_i_ino(sk)) < 0) { + __sock_i_ino(sk)) < 0) { ret = 1; break; } num++; } - read_unlock(&nl_table_lock); + read_unlock_irqrestore(&nl_table_lock, flags); done: cb->args[0] = num; diff --git a/net/nfc/llcp.h b/net/nfc/llcp.h index d49d4bf2e37c..a81893bc06ce 100644 --- a/net/nfc/llcp.h +++ b/net/nfc/llcp.h @@ -202,7 +202,6 @@ void nfc_llcp_sock_link(struct llcp_sock_list *l, struct sock *s); void nfc_llcp_sock_unlink(struct llcp_sock_list *l, struct sock *s); void nfc_llcp_socket_remote_param_init(struct nfc_llcp_sock *sock); struct nfc_llcp_local *nfc_llcp_find_local(struct nfc_dev *dev); -struct nfc_llcp_local *nfc_llcp_local_get(struct nfc_llcp_local *local); int nfc_llcp_local_put(struct nfc_llcp_local *local); u8 nfc_llcp_get_sdp_ssap(struct nfc_llcp_local *local, struct nfc_llcp_sock *sock); diff --git a/net/nfc/llcp_commands.c b/net/nfc/llcp_commands.c index 3c4172a5aeb5..5b8754ae7d3a 100644 --- a/net/nfc/llcp_commands.c +++ b/net/nfc/llcp_commands.c @@ -361,6 +361,7 @@ int nfc_llcp_send_symm(struct nfc_dev *dev) struct sk_buff *skb; struct nfc_llcp_local *local; u16 size = 0; + int err; pr_debug("Sending SYMM\n"); @@ -372,8 +373,10 @@ int nfc_llcp_send_symm(struct nfc_dev *dev) size += dev->tx_headroom + dev->tx_tailroom + NFC_HEADER_SIZE; skb = alloc_skb(size, GFP_KERNEL); - if (skb == NULL) - return -ENOMEM; + if (skb == NULL) { + err = -ENOMEM; + goto out; + } skb_reserve(skb, dev->tx_headroom + NFC_HEADER_SIZE); @@ -383,8 +386,11 @@ int nfc_llcp_send_symm(struct nfc_dev *dev) nfc_llcp_send_to_raw_sock(local, skb, NFC_DIRECTION_TX); - return nfc_data_exchange(dev, local->target_idx, skb, + err = nfc_data_exchange(dev, local->target_idx, skb, nfc_llcp_recv, local); +out: + nfc_llcp_local_put(local); + return err; } int nfc_llcp_send_connect(struct nfc_llcp_sock *sock) @@ -394,7 +400,8 @@ int nfc_llcp_send_connect(struct nfc_llcp_sock *sock) const u8 *service_name_tlv = NULL; const u8 *miux_tlv = NULL; const u8 *rw_tlv = NULL; - u8 service_name_tlv_length, miux_tlv_length, rw_tlv_length, rw; + u8 service_name_tlv_length = 0; + u8 miux_tlv_length, rw_tlv_length, rw; int err; u16 size = 0; __be16 miux; diff --git a/net/nfc/llcp_core.c b/net/nfc/llcp_core.c index fd43e75abd94..ddfd159f64e1 100644 --- a/net/nfc/llcp_core.c +++ b/net/nfc/llcp_core.c @@ -17,6 +17,8 @@ static u8 llcp_magic[3] = {0x46, 0x66, 0x6d}; static LIST_HEAD(llcp_devices); +/* Protects llcp_devices list */ +static DEFINE_SPINLOCK(llcp_devices_lock); static void nfc_llcp_rx_skb(struct nfc_llcp_local *local, struct sk_buff *skb); @@ -143,7 +145,7 @@ static void nfc_llcp_socket_release(struct nfc_llcp_local *local, bool device, write_unlock(&local->raw_sockets.lock); } -struct nfc_llcp_local *nfc_llcp_local_get(struct nfc_llcp_local *local) +static struct nfc_llcp_local *nfc_llcp_local_get(struct nfc_llcp_local *local) { kref_get(&local->ref); @@ -171,7 +173,6 @@ static void local_release(struct kref *ref) local = container_of(ref, struct nfc_llcp_local, ref); - list_del(&local->list); local_cleanup(local); kfree(local); } @@ -284,12 +285,33 @@ static void nfc_llcp_sdreq_timer(struct timer_list *t) struct nfc_llcp_local *nfc_llcp_find_local(struct nfc_dev *dev) { struct nfc_llcp_local *local; + struct nfc_llcp_local *res = NULL; + spin_lock(&llcp_devices_lock); list_for_each_entry(local, &llcp_devices, list) - if (local->dev == dev) - return local; + if (local->dev == dev) { + res = nfc_llcp_local_get(local); + break; + } + spin_unlock(&llcp_devices_lock); - pr_debug("No device found\n"); + return res; +} + +static struct nfc_llcp_local *nfc_llcp_remove_local(struct nfc_dev *dev) +{ + struct nfc_llcp_local *local, *tmp; + + spin_lock(&llcp_devices_lock); + list_for_each_entry_safe(local, tmp, &llcp_devices, list) + if (local->dev == dev) { + list_del(&local->list); + spin_unlock(&llcp_devices_lock); + return local; + } + spin_unlock(&llcp_devices_lock); + + pr_warn("Shutting down device not found\n"); return NULL; } @@ -610,12 +632,15 @@ u8 *nfc_llcp_general_bytes(struct nfc_dev *dev, size_t *general_bytes_len) *general_bytes_len = local->gb_len; + nfc_llcp_local_put(local); + return local->gb; } int nfc_llcp_set_remote_gb(struct nfc_dev *dev, const u8 *gb, u8 gb_len) { struct nfc_llcp_local *local; + int err; if (gb_len < 3 || gb_len > NFC_MAX_GT_LEN) return -EINVAL; @@ -632,12 +657,16 @@ int nfc_llcp_set_remote_gb(struct nfc_dev *dev, const u8 *gb, u8 gb_len) if (memcmp(local->remote_gb, llcp_magic, 3)) { pr_err("MAC does not support LLCP\n"); - return -EINVAL; + err = -EINVAL; + goto out; } - return nfc_llcp_parse_gb_tlv(local, + err = nfc_llcp_parse_gb_tlv(local, &local->remote_gb[3], local->remote_gb_len - 3); +out: + nfc_llcp_local_put(local); + return err; } static u8 nfc_llcp_dsap(const struct sk_buff *pdu) @@ -1527,6 +1556,8 @@ int nfc_llcp_data_received(struct nfc_dev *dev, struct sk_buff *skb) __nfc_llcp_recv(local, skb); + nfc_llcp_local_put(local); + return 0; } @@ -1543,6 +1574,8 @@ void nfc_llcp_mac_is_down(struct nfc_dev *dev) /* Close and purge all existing sockets */ nfc_llcp_socket_release(local, true, 0); + + nfc_llcp_local_put(local); } void nfc_llcp_mac_is_up(struct nfc_dev *dev, u32 target_idx, @@ -1568,6 +1601,8 @@ void nfc_llcp_mac_is_up(struct nfc_dev *dev, u32 target_idx, mod_timer(&local->link_timer, jiffies + msecs_to_jiffies(local->remote_lto)); } + + nfc_llcp_local_put(local); } int nfc_llcp_register_device(struct nfc_dev *ndev) @@ -1618,7 +1653,7 @@ int nfc_llcp_register_device(struct nfc_dev *ndev) void nfc_llcp_unregister_device(struct nfc_dev *dev) { - struct nfc_llcp_local *local = nfc_llcp_find_local(dev); + struct nfc_llcp_local *local = nfc_llcp_remove_local(dev); if (local == NULL) { pr_debug("No such device\n"); diff --git a/net/nfc/llcp_sock.c b/net/nfc/llcp_sock.c index 0b93a17b9f11..6e1fba208493 100644 --- a/net/nfc/llcp_sock.c +++ b/net/nfc/llcp_sock.c @@ -99,7 +99,7 @@ static int llcp_sock_bind(struct socket *sock, struct sockaddr *addr, int alen) } llcp_sock->dev = dev; - llcp_sock->local = nfc_llcp_local_get(local); + llcp_sock->local = local; llcp_sock->nfc_protocol = llcp_addr.nfc_protocol; llcp_sock->service_name_len = min_t(unsigned int, llcp_addr.service_name_len, @@ -181,7 +181,7 @@ static int llcp_raw_sock_bind(struct socket *sock, struct sockaddr *addr, } llcp_sock->dev = dev; - llcp_sock->local = nfc_llcp_local_get(local); + llcp_sock->local = local; llcp_sock->nfc_protocol = llcp_addr.nfc_protocol; nfc_llcp_sock_link(&local->raw_sockets, sk); @@ -698,24 +698,22 @@ static int llcp_sock_connect(struct socket *sock, struct sockaddr *_addr, if (dev->dep_link_up == false) { ret = -ENOLINK; device_unlock(&dev->dev); - goto put_dev; + goto sock_llcp_put_local; } device_unlock(&dev->dev); if (local->rf_mode == NFC_RF_INITIATOR && addr->target_idx != local->target_idx) { ret = -ENOLINK; - goto put_dev; + goto sock_llcp_put_local; } llcp_sock->dev = dev; - llcp_sock->local = nfc_llcp_local_get(local); + llcp_sock->local = local; llcp_sock->ssap = nfc_llcp_get_local_ssap(local); if (llcp_sock->ssap == LLCP_SAP_MAX) { - nfc_llcp_local_put(llcp_sock->local); - llcp_sock->local = NULL; ret = -ENOMEM; - goto put_dev; + goto sock_llcp_nullify; } llcp_sock->reserved_ssap = llcp_sock->ssap; @@ -760,8 +758,13 @@ sock_unlink: sock_llcp_release: nfc_llcp_put_ssap(local, llcp_sock->ssap); - nfc_llcp_local_put(llcp_sock->local); + +sock_llcp_nullify: llcp_sock->local = NULL; + llcp_sock->dev = NULL; + +sock_llcp_put_local: + nfc_llcp_local_put(local); put_dev: nfc_put_device(dev); diff --git a/net/nfc/netlink.c b/net/nfc/netlink.c index 9bc0ab759ea4..eb4f70a827e4 100644 --- a/net/nfc/netlink.c +++ b/net/nfc/netlink.c @@ -1039,11 +1039,14 @@ static int nfc_genl_llc_get_params(struct sk_buff *skb, struct genl_info *info) msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); if (!msg) { rc = -ENOMEM; - goto exit; + goto put_local; } rc = nfc_genl_send_params(msg, local, info->snd_portid, info->snd_seq); +put_local: + nfc_llcp_local_put(local); + exit: device_unlock(&dev->dev); @@ -1105,7 +1108,7 @@ static int nfc_genl_llc_set_params(struct sk_buff *skb, struct genl_info *info) if (info->attrs[NFC_ATTR_LLC_PARAM_LTO]) { if (dev->dep_link_up) { rc = -EINPROGRESS; - goto exit; + goto put_local; } local->lto = nla_get_u8(info->attrs[NFC_ATTR_LLC_PARAM_LTO]); @@ -1117,6 +1120,9 @@ static int nfc_genl_llc_set_params(struct sk_buff *skb, struct genl_info *info) if (info->attrs[NFC_ATTR_LLC_PARAM_MIUX]) local->miux = cpu_to_be16(miux); +put_local: + nfc_llcp_local_put(local); + exit: device_unlock(&dev->dev); @@ -1172,7 +1178,7 @@ static int nfc_genl_llc_sdreq(struct sk_buff *skb, struct genl_info *info) if (rc != 0) { rc = -EINVAL; - goto exit; + goto put_local; } if (!sdp_attrs[NFC_SDP_ATTR_URI]) @@ -1191,7 +1197,7 @@ static int nfc_genl_llc_sdreq(struct sk_buff *skb, struct genl_info *info) sdreq = nfc_llcp_build_sdreq_tlv(tid, uri, uri_len); if (sdreq == NULL) { rc = -ENOMEM; - goto exit; + goto put_local; } tlvs_len += sdreq->tlv_len; @@ -1201,10 +1207,14 @@ static int nfc_genl_llc_sdreq(struct sk_buff *skb, struct genl_info *info) if (hlist_empty(&sdreq_list)) { rc = -EINVAL; - goto exit; + goto put_local; } rc = nfc_llcp_send_snl_sdreq(local, &sdreq_list, tlvs_len); + +put_local: + nfc_llcp_local_put(local); + exit: device_unlock(&dev->dev); diff --git a/net/nfc/nfc.h b/net/nfc/nfc.h index de2ec66d7e83..0b1e6466f4fb 100644 --- a/net/nfc/nfc.h +++ b/net/nfc/nfc.h @@ -52,6 +52,7 @@ int nfc_llcp_set_remote_gb(struct nfc_dev *dev, const u8 *gb, u8 gb_len); u8 *nfc_llcp_general_bytes(struct nfc_dev *dev, size_t *general_bytes_len); int nfc_llcp_data_received(struct nfc_dev *dev, struct sk_buff *skb); struct nfc_llcp_local *nfc_llcp_find_local(struct nfc_dev *dev); +int nfc_llcp_local_put(struct nfc_llcp_local *local); int __init nfc_llcp_init(void); void nfc_llcp_exit(void); void nfc_llcp_free_sdp_tlv(struct nfc_llcp_sdp_tlv *sdp); diff --git a/net/qrtr/af_qrtr.c b/net/qrtr/af_qrtr.c index 7788366c2ff1..420fd5102502 100644 --- a/net/qrtr/af_qrtr.c +++ b/net/qrtr/af_qrtr.c @@ -1504,13 +1504,13 @@ void qrtr_endpoint_unregister(struct qrtr_endpoint *ep) if (*slot != node) continue; src.sq_node = iter.index; - skb = qrtr_alloc_ctrl_packet(&pkt, GFP_ATOMIC); + spin_unlock_irqrestore(&qrtr_nodes_lock, flags); + skb = qrtr_alloc_ctrl_packet(&pkt, GFP_KERNEL); if (skb) { pkt->cmd = cpu_to_le32(QRTR_TYPE_BYE); qrtr_local_enqueue(NULL, skb, QRTR_TYPE_BYE, &src, &dst, 0); } - spin_unlock_irqrestore(&qrtr_nodes_lock, flags); qrtr_fwd_del_proc(node, iter.index); spin_lock_irqsave(&qrtr_nodes_lock, flags); } diff --git a/net/qrtr/mhi.c b/net/qrtr/mhi.c index bec0a48ebda0..b53501575694 100644 --- a/net/qrtr/mhi.c +++ b/net/qrtr/mhi.c @@ -19,6 +19,7 @@ struct qrtr_mhi_dev { struct mhi_device *mhi_dev; struct device *dev; struct completion prepared; + struct completion ringfull; }; /* From MHI to QRTR */ @@ -42,10 +43,13 @@ static void qcom_mhi_qrtr_ul_callback(struct mhi_device *mhi_dev, struct mhi_result *mhi_res) { struct sk_buff *skb = mhi_res->buf_addr; + struct qrtr_mhi_dev *qdev = dev_get_drvdata(&mhi_dev->dev); if (skb->sk) sock_put(skb->sk); consume_skb(skb); + + complete_all(&qdev->ringfull); } /* Send data over MHI */ @@ -82,14 +86,15 @@ free_skb: static int qcom_mhi_qrtr_send(struct qrtr_endpoint *ep, struct sk_buff *skb) { + struct qrtr_mhi_dev *qdev = container_of(ep, struct qrtr_mhi_dev, ep); int rc; - int retry = 5; do { + reinit_completion(&qdev->ringfull); rc = __qcom_mhi_qrtr_send(ep, skb); if (rc == -EAGAIN) - usleep_range(1000, 2000); - } while (rc == -EAGAIN && --retry); + wait_for_completion(&qdev->ringfull); + } while (rc == -EAGAIN); return rc; } @@ -138,6 +143,7 @@ static int qcom_mhi_qrtr_probe(struct mhi_device *mhi_dev, qdev->dev = &mhi_dev->dev; qdev->ep.xmit = qcom_mhi_qrtr_send; init_completion(&qdev->prepared); + init_completion(&qdev->ringfull); dev_set_drvdata(&mhi_dev->dev, qdev); diff --git a/net/sched/Kconfig b/net/sched/Kconfig index bcdd6e925343..24cf0bf7c80e 100644 --- a/net/sched/Kconfig +++ b/net/sched/Kconfig @@ -548,34 +548,6 @@ config CLS_U32_MARK help Say Y here to be able to use netfilter marks as u32 key. -config NET_CLS_RSVP - tristate "IPv4 Resource Reservation Protocol (RSVP)" - select NET_CLS - help - The Resource Reservation Protocol (RSVP) permits end systems to - request a minimum and maximum data flow rate for a connection; this - is important for real time data such as streaming sound or video. - - Say Y here if you want to be able to classify outgoing packets based - on their RSVP requests. - - To compile this code as a module, choose M here: the - module will be called cls_rsvp. - -config NET_CLS_RSVP6 - tristate "IPv6 Resource Reservation Protocol (RSVP6)" - select NET_CLS - help - The Resource Reservation Protocol (RSVP) permits end systems to - request a minimum and maximum data flow rate for a connection; this - is important for real time data such as streaming sound or video. - - Say Y here if you want to be able to classify outgoing packets based - on their RSVP requests and you are using the IPv6 protocol. - - To compile this code as a module, choose M here: the - module will be called cls_rsvp6. - config NET_CLS_FLOW tristate "Flow classifier" select NET_CLS diff --git a/net/sched/Makefile b/net/sched/Makefile index b7dbac5c519f..8a33a35fc50d 100644 --- a/net/sched/Makefile +++ b/net/sched/Makefile @@ -69,8 +69,6 @@ obj-$(CONFIG_NET_SCH_TAPRIO) += sch_taprio.o obj-$(CONFIG_NET_CLS_U32) += cls_u32.o obj-$(CONFIG_NET_CLS_ROUTE4) += cls_route.o obj-$(CONFIG_NET_CLS_FW) += cls_fw.o -obj-$(CONFIG_NET_CLS_RSVP) += cls_rsvp.o -obj-$(CONFIG_NET_CLS_RSVP6) += cls_rsvp6.o obj-$(CONFIG_NET_CLS_BASIC) += cls_basic.o obj-$(CONFIG_NET_CLS_FLOW) += cls_flow.o obj-$(CONFIG_NET_CLS_CGROUP) += cls_cgroup.o diff --git a/net/sched/act_ipt.c b/net/sched/act_ipt.c index 2f3d507c24a1..ebd403f571ea 100644 --- a/net/sched/act_ipt.c +++ b/net/sched/act_ipt.c @@ -50,7 +50,7 @@ static int ipt_init_target(struct net *net, struct xt_entry_target *t, par.entryinfo = &e; par.target = target; par.targinfo = t->data; - par.hook_mask = hook; + par.hook_mask = 1 << hook; par.family = NFPROTO_IPV4; ret = xt_check_target(&par, t->u.target_size - sizeof(*t), 0, false); @@ -87,7 +87,8 @@ static void tcf_ipt_release(struct tc_action *a) static const struct nla_policy ipt_policy[TCA_IPT_MAX + 1] = { [TCA_IPT_TABLE] = { .type = NLA_STRING, .len = IFNAMSIZ }, - [TCA_IPT_HOOK] = { .type = NLA_U32 }, + [TCA_IPT_HOOK] = NLA_POLICY_RANGE(NLA_U32, NF_INET_PRE_ROUTING, + NF_INET_NUMHOOKS), [TCA_IPT_INDEX] = { .type = NLA_U32 }, [TCA_IPT_TARG] = { .len = sizeof(struct xt_entry_target) }, }; @@ -160,15 +161,27 @@ static int __tcf_ipt_init(struct net *net, unsigned int id, struct nlattr *nla, return -EEXIST; } } - hook = nla_get_u32(tb[TCA_IPT_HOOK]); - err = -ENOMEM; - tname = kmalloc(IFNAMSIZ, GFP_KERNEL); + err = -EINVAL; + hook = nla_get_u32(tb[TCA_IPT_HOOK]); + switch (hook) { + case NF_INET_PRE_ROUTING: + break; + case NF_INET_POST_ROUTING: + break; + default: + goto err1; + } + + if (tb[TCA_IPT_TABLE]) { + /* mangle only for now */ + if (nla_strcmp(tb[TCA_IPT_TABLE], "mangle")) + goto err1; + } + + tname = kstrdup("mangle", GFP_KERNEL); if (unlikely(!tname)) goto err1; - if (tb[TCA_IPT_TABLE] == NULL || - nla_strscpy(tname, tb[TCA_IPT_TABLE], IFNAMSIZ) >= IFNAMSIZ) - strcpy(tname, "mangle"); t = kmemdup(td, td->u.target_size, GFP_KERNEL); if (unlikely(!t)) diff --git a/net/sched/act_pedit.c b/net/sched/act_pedit.c index e77da0545b55..df9ff123a7ee 100644 --- a/net/sched/act_pedit.c +++ b/net/sched/act_pedit.c @@ -29,6 +29,7 @@ static struct tc_action_ops act_pedit_ops; static const struct nla_policy pedit_policy[TCA_PEDIT_MAX + 1] = { [TCA_PEDIT_PARMS] = { .len = sizeof(struct tc_pedit) }, + [TCA_PEDIT_PARMS_EX] = { .len = sizeof(struct tc_pedit) }, [TCA_PEDIT_KEYS_EX] = { .type = NLA_NESTED }, }; diff --git a/net/sched/cls_bpf.c b/net/sched/cls_bpf.c index df19a847829e..b7c46a93a412 100644 --- a/net/sched/cls_bpf.c +++ b/net/sched/cls_bpf.c @@ -402,56 +402,6 @@ static int cls_bpf_prog_from_efd(struct nlattr **tb, struct cls_bpf_prog *prog, return 0; } -static int cls_bpf_set_parms(struct net *net, struct tcf_proto *tp, - struct cls_bpf_prog *prog, unsigned long base, - struct nlattr **tb, struct nlattr *est, u32 flags, - struct netlink_ext_ack *extack) -{ - bool is_bpf, is_ebpf, have_exts = false; - u32 gen_flags = 0; - int ret; - - is_bpf = tb[TCA_BPF_OPS_LEN] && tb[TCA_BPF_OPS]; - is_ebpf = tb[TCA_BPF_FD]; - if ((!is_bpf && !is_ebpf) || (is_bpf && is_ebpf)) - return -EINVAL; - - ret = tcf_exts_validate(net, tp, tb, est, &prog->exts, flags, - extack); - if (ret < 0) - return ret; - - if (tb[TCA_BPF_FLAGS]) { - u32 bpf_flags = nla_get_u32(tb[TCA_BPF_FLAGS]); - - if (bpf_flags & ~TCA_BPF_FLAG_ACT_DIRECT) - return -EINVAL; - - have_exts = bpf_flags & TCA_BPF_FLAG_ACT_DIRECT; - } - if (tb[TCA_BPF_FLAGS_GEN]) { - gen_flags = nla_get_u32(tb[TCA_BPF_FLAGS_GEN]); - if (gen_flags & ~CLS_BPF_SUPPORTED_GEN_FLAGS || - !tc_flags_valid(gen_flags)) - return -EINVAL; - } - - prog->exts_integrated = have_exts; - prog->gen_flags = gen_flags; - - ret = is_bpf ? cls_bpf_prog_from_ops(tb, prog) : - cls_bpf_prog_from_efd(tb, prog, gen_flags, tp); - if (ret < 0) - return ret; - - if (tb[TCA_BPF_CLASSID]) { - prog->res.classid = nla_get_u32(tb[TCA_BPF_CLASSID]); - tcf_bind_filter(tp, &prog->res, base); - } - - return 0; -} - static int cls_bpf_change(struct net *net, struct sk_buff *in_skb, struct tcf_proto *tp, unsigned long base, u32 handle, struct nlattr **tca, @@ -459,9 +409,12 @@ static int cls_bpf_change(struct net *net, struct sk_buff *in_skb, struct netlink_ext_ack *extack) { struct cls_bpf_head *head = rtnl_dereference(tp->root); + bool is_bpf, is_ebpf, have_exts = false; struct cls_bpf_prog *oldprog = *arg; struct nlattr *tb[TCA_BPF_MAX + 1]; + bool bound_to_filter = false; struct cls_bpf_prog *prog; + u32 gen_flags = 0; int ret; if (tca[TCA_OPTIONS] == NULL) @@ -500,11 +453,51 @@ static int cls_bpf_change(struct net *net, struct sk_buff *in_skb, goto errout; prog->handle = handle; - ret = cls_bpf_set_parms(net, tp, prog, base, tb, tca[TCA_RATE], flags, - extack); + is_bpf = tb[TCA_BPF_OPS_LEN] && tb[TCA_BPF_OPS]; + is_ebpf = tb[TCA_BPF_FD]; + if ((!is_bpf && !is_ebpf) || (is_bpf && is_ebpf)) { + ret = -EINVAL; + goto errout_idr; + } + + ret = tcf_exts_validate(net, tp, tb, tca[TCA_RATE], &prog->exts, + flags, extack); if (ret < 0) goto errout_idr; + if (tb[TCA_BPF_FLAGS]) { + u32 bpf_flags = nla_get_u32(tb[TCA_BPF_FLAGS]); + + if (bpf_flags & ~TCA_BPF_FLAG_ACT_DIRECT) { + ret = -EINVAL; + goto errout_idr; + } + + have_exts = bpf_flags & TCA_BPF_FLAG_ACT_DIRECT; + } + if (tb[TCA_BPF_FLAGS_GEN]) { + gen_flags = nla_get_u32(tb[TCA_BPF_FLAGS_GEN]); + if (gen_flags & ~CLS_BPF_SUPPORTED_GEN_FLAGS || + !tc_flags_valid(gen_flags)) { + ret = -EINVAL; + goto errout_idr; + } + } + + prog->exts_integrated = have_exts; + prog->gen_flags = gen_flags; + + ret = is_bpf ? cls_bpf_prog_from_ops(tb, prog) : + cls_bpf_prog_from_efd(tb, prog, gen_flags, tp); + if (ret < 0) + goto errout_idr; + + if (tb[TCA_BPF_CLASSID]) { + prog->res.classid = nla_get_u32(tb[TCA_BPF_CLASSID]); + tcf_bind_filter(tp, &prog->res, base); + bound_to_filter = true; + } + ret = cls_bpf_offload(tp, prog, oldprog, extack); if (ret) goto errout_parms; @@ -526,6 +519,8 @@ static int cls_bpf_change(struct net *net, struct sk_buff *in_skb, return 0; errout_parms: + if (bound_to_filter) + tcf_unbind_filter(tp, &prog->res); cls_bpf_free_parms(prog); errout_idr: if (!oldprog) diff --git a/net/sched/cls_flower.c b/net/sched/cls_flower.c index ee137d5c20a4..bff0a5f24aca 100644 --- a/net/sched/cls_flower.c +++ b/net/sched/cls_flower.c @@ -784,6 +784,16 @@ static int fl_set_key_port_range(struct nlattr **tb, struct fl_flow_key *key, TCA_FLOWER_KEY_PORT_SRC_MAX, &mask->tp_range.tp_max.src, TCA_FLOWER_UNSPEC, sizeof(key->tp_range.tp_max.src)); + if (mask->tp_range.tp_min.dst != mask->tp_range.tp_max.dst) { + NL_SET_ERR_MSG(extack, + "Both min and max destination ports must be specified"); + return -EINVAL; + } + if (mask->tp_range.tp_min.src != mask->tp_range.tp_max.src) { + NL_SET_ERR_MSG(extack, + "Both min and max source ports must be specified"); + return -EINVAL; + } if (mask->tp_range.tp_min.dst && mask->tp_range.tp_max.dst && ntohs(key->tp_range.tp_max.dst) <= ntohs(key->tp_range.tp_min.dst)) { diff --git a/net/sched/cls_fw.c b/net/sched/cls_fw.c index ea52c320f67c..a2f53aee3909 100644 --- a/net/sched/cls_fw.c +++ b/net/sched/cls_fw.c @@ -265,7 +265,6 @@ static int fw_change(struct net *net, struct sk_buff *in_skb, return -ENOBUFS; fnew->id = f->id; - fnew->res = f->res; fnew->ifindex = f->ifindex; fnew->tp = f->tp; diff --git a/net/sched/cls_route.c b/net/sched/cls_route.c index 48712bc51bda..194468d0355a 100644 --- a/net/sched/cls_route.c +++ b/net/sched/cls_route.c @@ -511,7 +511,6 @@ static int route4_change(struct net *net, struct sk_buff *in_skb, if (fold) { f->id = fold->id; f->iif = fold->iif; - f->res = fold->res; f->handle = fold->handle; f->tp = fold->tp; diff --git a/net/sched/cls_rsvp.c b/net/sched/cls_rsvp.c deleted file mode 100644 index de1c1d4da597..000000000000 --- a/net/sched/cls_rsvp.c +++ /dev/null @@ -1,24 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later -/* - * net/sched/cls_rsvp.c Special RSVP packet classifier for IPv4. - * - * Authors: Alexey Kuznetsov, - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define RSVP_DST_LEN 1 -#define RSVP_ID "rsvp" -#define RSVP_OPS cls_rsvp_ops - -#include "cls_rsvp.h" -MODULE_LICENSE("GPL"); diff --git a/net/sched/cls_rsvp.h b/net/sched/cls_rsvp.h deleted file mode 100644 index 5cd9d6b143c4..000000000000 --- a/net/sched/cls_rsvp.h +++ /dev/null @@ -1,776 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ -/* - * net/sched/cls_rsvp.h Template file for RSVPv[46] classifiers. - * - * Authors: Alexey Kuznetsov, - */ - -/* - Comparing to general packet classification problem, - RSVP needs only several relatively simple rules: - - * (dst, protocol) are always specified, - so that we are able to hash them. - * src may be exact, or may be wildcard, so that - we can keep a hash table plus one wildcard entry. - * source port (or flow label) is important only if src is given. - - IMPLEMENTATION. - - We use a two level hash table: The top level is keyed by - destination address and protocol ID, every bucket contains a list - of "rsvp sessions", identified by destination address, protocol and - DPI(="Destination Port ID"): triple (key, mask, offset). - - Every bucket has a smaller hash table keyed by source address - (cf. RSVP flowspec) and one wildcard entry for wildcard reservations. - Every bucket is again a list of "RSVP flows", selected by - source address and SPI(="Source Port ID" here rather than - "security parameter index"): triple (key, mask, offset). - - - NOTE 1. All the packets with IPv6 extension headers (but AH and ESP) - and all fragmented packets go to the best-effort traffic class. - - - NOTE 2. Two "port id"'s seems to be redundant, rfc2207 requires - only one "Generalized Port Identifier". So that for classic - ah, esp (and udp,tcp) both *pi should coincide or one of them - should be wildcard. - - At first sight, this redundancy is just a waste of CPU - resources. But DPI and SPI add the possibility to assign different - priorities to GPIs. Look also at note 4 about tunnels below. - - - NOTE 3. One complication is the case of tunneled packets. - We implement it as following: if the first lookup - matches a special session with "tunnelhdr" value not zero, - flowid doesn't contain the true flow ID, but the tunnel ID (1...255). - In this case, we pull tunnelhdr bytes and restart lookup - with tunnel ID added to the list of keys. Simple and stupid 8)8) - It's enough for PIMREG and IPIP. - - - NOTE 4. Two GPIs make it possible to parse even GRE packets. - F.e. DPI can select ETH_P_IP (and necessary flags to make - tunnelhdr correct) in GRE protocol field and SPI matches - GRE key. Is it not nice? 8)8) - - - Well, as result, despite its simplicity, we get a pretty - powerful classification engine. */ - - -struct rsvp_head { - u32 tmap[256/32]; - u32 hgenerator; - u8 tgenerator; - struct rsvp_session __rcu *ht[256]; - struct rcu_head rcu; -}; - -struct rsvp_session { - struct rsvp_session __rcu *next; - __be32 dst[RSVP_DST_LEN]; - struct tc_rsvp_gpi dpi; - u8 protocol; - u8 tunnelid; - /* 16 (src,sport) hash slots, and one wildcard source slot */ - struct rsvp_filter __rcu *ht[16 + 1]; - struct rcu_head rcu; -}; - - -struct rsvp_filter { - struct rsvp_filter __rcu *next; - __be32 src[RSVP_DST_LEN]; - struct tc_rsvp_gpi spi; - u8 tunnelhdr; - - struct tcf_result res; - struct tcf_exts exts; - - u32 handle; - struct rsvp_session *sess; - struct rcu_work rwork; -}; - -static inline unsigned int hash_dst(__be32 *dst, u8 protocol, u8 tunnelid) -{ - unsigned int h = (__force __u32)dst[RSVP_DST_LEN - 1]; - - h ^= h>>16; - h ^= h>>8; - return (h ^ protocol ^ tunnelid) & 0xFF; -} - -static inline unsigned int hash_src(__be32 *src) -{ - unsigned int h = (__force __u32)src[RSVP_DST_LEN-1]; - - h ^= h>>16; - h ^= h>>8; - h ^= h>>4; - return h & 0xF; -} - -#define RSVP_APPLY_RESULT() \ -{ \ - int r = tcf_exts_exec(skb, &f->exts, res); \ - if (r < 0) \ - continue; \ - else if (r > 0) \ - return r; \ -} - -static int rsvp_classify(struct sk_buff *skb, const struct tcf_proto *tp, - struct tcf_result *res) -{ - struct rsvp_head *head = rcu_dereference_bh(tp->root); - struct rsvp_session *s; - struct rsvp_filter *f; - unsigned int h1, h2; - __be32 *dst, *src; - u8 protocol; - u8 tunnelid = 0; - u8 *xprt; -#if RSVP_DST_LEN == 4 - struct ipv6hdr *nhptr; - - if (!pskb_network_may_pull(skb, sizeof(*nhptr))) - return -1; - nhptr = ipv6_hdr(skb); -#else - struct iphdr *nhptr; - - if (!pskb_network_may_pull(skb, sizeof(*nhptr))) - return -1; - nhptr = ip_hdr(skb); -#endif -restart: - -#if RSVP_DST_LEN == 4 - src = &nhptr->saddr.s6_addr32[0]; - dst = &nhptr->daddr.s6_addr32[0]; - protocol = nhptr->nexthdr; - xprt = ((u8 *)nhptr) + sizeof(struct ipv6hdr); -#else - src = &nhptr->saddr; - dst = &nhptr->daddr; - protocol = nhptr->protocol; - xprt = ((u8 *)nhptr) + (nhptr->ihl<<2); - if (ip_is_fragment(nhptr)) - return -1; -#endif - - h1 = hash_dst(dst, protocol, tunnelid); - h2 = hash_src(src); - - for (s = rcu_dereference_bh(head->ht[h1]); s; - s = rcu_dereference_bh(s->next)) { - if (dst[RSVP_DST_LEN-1] == s->dst[RSVP_DST_LEN - 1] && - protocol == s->protocol && - !(s->dpi.mask & - (*(u32 *)(xprt + s->dpi.offset) ^ s->dpi.key)) && -#if RSVP_DST_LEN == 4 - dst[0] == s->dst[0] && - dst[1] == s->dst[1] && - dst[2] == s->dst[2] && -#endif - tunnelid == s->tunnelid) { - - for (f = rcu_dereference_bh(s->ht[h2]); f; - f = rcu_dereference_bh(f->next)) { - if (src[RSVP_DST_LEN-1] == f->src[RSVP_DST_LEN - 1] && - !(f->spi.mask & (*(u32 *)(xprt + f->spi.offset) ^ f->spi.key)) -#if RSVP_DST_LEN == 4 - && - src[0] == f->src[0] && - src[1] == f->src[1] && - src[2] == f->src[2] -#endif - ) { - *res = f->res; - RSVP_APPLY_RESULT(); - -matched: - if (f->tunnelhdr == 0) - return 0; - - tunnelid = f->res.classid; - nhptr = (void *)(xprt + f->tunnelhdr - sizeof(*nhptr)); - goto restart; - } - } - - /* And wildcard bucket... */ - for (f = rcu_dereference_bh(s->ht[16]); f; - f = rcu_dereference_bh(f->next)) { - *res = f->res; - RSVP_APPLY_RESULT(); - goto matched; - } - return -1; - } - } - return -1; -} - -static void rsvp_replace(struct tcf_proto *tp, struct rsvp_filter *n, u32 h) -{ - struct rsvp_head *head = rtnl_dereference(tp->root); - struct rsvp_session *s; - struct rsvp_filter __rcu **ins; - struct rsvp_filter *pins; - unsigned int h1 = h & 0xFF; - unsigned int h2 = (h >> 8) & 0xFF; - - for (s = rtnl_dereference(head->ht[h1]); s; - s = rtnl_dereference(s->next)) { - for (ins = &s->ht[h2], pins = rtnl_dereference(*ins); ; - ins = &pins->next, pins = rtnl_dereference(*ins)) { - if (pins->handle == h) { - RCU_INIT_POINTER(n->next, pins->next); - rcu_assign_pointer(*ins, n); - return; - } - } - } - - /* Something went wrong if we are trying to replace a non-existent - * node. Mind as well halt instead of silently failing. - */ - BUG_ON(1); -} - -static void *rsvp_get(struct tcf_proto *tp, u32 handle) -{ - struct rsvp_head *head = rtnl_dereference(tp->root); - struct rsvp_session *s; - struct rsvp_filter *f; - unsigned int h1 = handle & 0xFF; - unsigned int h2 = (handle >> 8) & 0xFF; - - if (h2 > 16) - return NULL; - - for (s = rtnl_dereference(head->ht[h1]); s; - s = rtnl_dereference(s->next)) { - for (f = rtnl_dereference(s->ht[h2]); f; - f = rtnl_dereference(f->next)) { - if (f->handle == handle) - return f; - } - } - return NULL; -} - -static int rsvp_init(struct tcf_proto *tp) -{ - struct rsvp_head *data; - - data = kzalloc(sizeof(struct rsvp_head), GFP_KERNEL); - if (data) { - rcu_assign_pointer(tp->root, data); - return 0; - } - return -ENOBUFS; -} - -static void __rsvp_delete_filter(struct rsvp_filter *f) -{ - tcf_exts_destroy(&f->exts); - tcf_exts_put_net(&f->exts); - kfree(f); -} - -static void rsvp_delete_filter_work(struct work_struct *work) -{ - struct rsvp_filter *f = container_of(to_rcu_work(work), - struct rsvp_filter, - rwork); - rtnl_lock(); - __rsvp_delete_filter(f); - rtnl_unlock(); -} - -static void rsvp_delete_filter(struct tcf_proto *tp, struct rsvp_filter *f) -{ - tcf_unbind_filter(tp, &f->res); - /* all classifiers are required to call tcf_exts_destroy() after rcu - * grace period, since converted-to-rcu actions are relying on that - * in cleanup() callback - */ - if (tcf_exts_get_net(&f->exts)) - tcf_queue_work(&f->rwork, rsvp_delete_filter_work); - else - __rsvp_delete_filter(f); -} - -static void rsvp_destroy(struct tcf_proto *tp, bool rtnl_held, - struct netlink_ext_ack *extack) -{ - struct rsvp_head *data = rtnl_dereference(tp->root); - int h1, h2; - - if (data == NULL) - return; - - for (h1 = 0; h1 < 256; h1++) { - struct rsvp_session *s; - - while ((s = rtnl_dereference(data->ht[h1])) != NULL) { - RCU_INIT_POINTER(data->ht[h1], s->next); - - for (h2 = 0; h2 <= 16; h2++) { - struct rsvp_filter *f; - - while ((f = rtnl_dereference(s->ht[h2])) != NULL) { - rcu_assign_pointer(s->ht[h2], f->next); - rsvp_delete_filter(tp, f); - } - } - kfree_rcu(s, rcu); - } - } - kfree_rcu(data, rcu); -} - -static int rsvp_delete(struct tcf_proto *tp, void *arg, bool *last, - bool rtnl_held, struct netlink_ext_ack *extack) -{ - struct rsvp_head *head = rtnl_dereference(tp->root); - struct rsvp_filter *nfp, *f = arg; - struct rsvp_filter __rcu **fp; - unsigned int h = f->handle; - struct rsvp_session __rcu **sp; - struct rsvp_session *nsp, *s = f->sess; - int i, h1; - - fp = &s->ht[(h >> 8) & 0xFF]; - for (nfp = rtnl_dereference(*fp); nfp; - fp = &nfp->next, nfp = rtnl_dereference(*fp)) { - if (nfp == f) { - RCU_INIT_POINTER(*fp, f->next); - rsvp_delete_filter(tp, f); - - /* Strip tree */ - - for (i = 0; i <= 16; i++) - if (s->ht[i]) - goto out; - - /* OK, session has no flows */ - sp = &head->ht[h & 0xFF]; - for (nsp = rtnl_dereference(*sp); nsp; - sp = &nsp->next, nsp = rtnl_dereference(*sp)) { - if (nsp == s) { - RCU_INIT_POINTER(*sp, s->next); - kfree_rcu(s, rcu); - goto out; - } - } - - break; - } - } - -out: - *last = true; - for (h1 = 0; h1 < 256; h1++) { - if (rcu_access_pointer(head->ht[h1])) { - *last = false; - break; - } - } - - return 0; -} - -static unsigned int gen_handle(struct tcf_proto *tp, unsigned salt) -{ - struct rsvp_head *data = rtnl_dereference(tp->root); - int i = 0xFFFF; - - while (i-- > 0) { - u32 h; - - if ((data->hgenerator += 0x10000) == 0) - data->hgenerator = 0x10000; - h = data->hgenerator|salt; - if (!rsvp_get(tp, h)) - return h; - } - return 0; -} - -static int tunnel_bts(struct rsvp_head *data) -{ - int n = data->tgenerator >> 5; - u32 b = 1 << (data->tgenerator & 0x1F); - - if (data->tmap[n] & b) - return 0; - data->tmap[n] |= b; - return 1; -} - -static void tunnel_recycle(struct rsvp_head *data) -{ - struct rsvp_session __rcu **sht = data->ht; - u32 tmap[256/32]; - int h1, h2; - - memset(tmap, 0, sizeof(tmap)); - - for (h1 = 0; h1 < 256; h1++) { - struct rsvp_session *s; - for (s = rtnl_dereference(sht[h1]); s; - s = rtnl_dereference(s->next)) { - for (h2 = 0; h2 <= 16; h2++) { - struct rsvp_filter *f; - - for (f = rtnl_dereference(s->ht[h2]); f; - f = rtnl_dereference(f->next)) { - if (f->tunnelhdr == 0) - continue; - data->tgenerator = f->res.classid; - tunnel_bts(data); - } - } - } - } - - memcpy(data->tmap, tmap, sizeof(tmap)); -} - -static u32 gen_tunnel(struct rsvp_head *data) -{ - int i, k; - - for (k = 0; k < 2; k++) { - for (i = 255; i > 0; i--) { - if (++data->tgenerator == 0) - data->tgenerator = 1; - if (tunnel_bts(data)) - return data->tgenerator; - } - tunnel_recycle(data); - } - return 0; -} - -static const struct nla_policy rsvp_policy[TCA_RSVP_MAX + 1] = { - [TCA_RSVP_CLASSID] = { .type = NLA_U32 }, - [TCA_RSVP_DST] = { .len = RSVP_DST_LEN * sizeof(u32) }, - [TCA_RSVP_SRC] = { .len = RSVP_DST_LEN * sizeof(u32) }, - [TCA_RSVP_PINFO] = { .len = sizeof(struct tc_rsvp_pinfo) }, -}; - -static int rsvp_change(struct net *net, struct sk_buff *in_skb, - struct tcf_proto *tp, unsigned long base, - u32 handle, struct nlattr **tca, - void **arg, u32 flags, - struct netlink_ext_ack *extack) -{ - struct rsvp_head *data = rtnl_dereference(tp->root); - struct rsvp_filter *f, *nfp; - struct rsvp_filter __rcu **fp; - struct rsvp_session *nsp, *s; - struct rsvp_session __rcu **sp; - struct tc_rsvp_pinfo *pinfo = NULL; - struct nlattr *opt = tca[TCA_OPTIONS]; - struct nlattr *tb[TCA_RSVP_MAX + 1]; - struct tcf_exts e; - unsigned int h1, h2; - __be32 *dst; - int err; - - if (opt == NULL) - return handle ? -EINVAL : 0; - - err = nla_parse_nested_deprecated(tb, TCA_RSVP_MAX, opt, rsvp_policy, - NULL); - if (err < 0) - return err; - - err = tcf_exts_init(&e, net, TCA_RSVP_ACT, TCA_RSVP_POLICE); - if (err < 0) - return err; - err = tcf_exts_validate(net, tp, tb, tca[TCA_RATE], &e, flags, - extack); - if (err < 0) - goto errout2; - - f = *arg; - if (f) { - /* Node exists: adjust only classid */ - struct rsvp_filter *n; - - if (f->handle != handle && handle) - goto errout2; - - n = kmemdup(f, sizeof(*f), GFP_KERNEL); - if (!n) { - err = -ENOMEM; - goto errout2; - } - - err = tcf_exts_init(&n->exts, net, TCA_RSVP_ACT, - TCA_RSVP_POLICE); - if (err < 0) { - kfree(n); - goto errout2; - } - - if (tb[TCA_RSVP_CLASSID]) { - n->res.classid = nla_get_u32(tb[TCA_RSVP_CLASSID]); - tcf_bind_filter(tp, &n->res, base); - } - - tcf_exts_change(&n->exts, &e); - rsvp_replace(tp, n, handle); - return 0; - } - - /* Now more serious part... */ - err = -EINVAL; - if (handle) - goto errout2; - if (tb[TCA_RSVP_DST] == NULL) - goto errout2; - - err = -ENOBUFS; - f = kzalloc(sizeof(struct rsvp_filter), GFP_KERNEL); - if (f == NULL) - goto errout2; - - err = tcf_exts_init(&f->exts, net, TCA_RSVP_ACT, TCA_RSVP_POLICE); - if (err < 0) - goto errout; - h2 = 16; - if (tb[TCA_RSVP_SRC]) { - memcpy(f->src, nla_data(tb[TCA_RSVP_SRC]), sizeof(f->src)); - h2 = hash_src(f->src); - } - if (tb[TCA_RSVP_PINFO]) { - pinfo = nla_data(tb[TCA_RSVP_PINFO]); - f->spi = pinfo->spi; - f->tunnelhdr = pinfo->tunnelhdr; - } - if (tb[TCA_RSVP_CLASSID]) - f->res.classid = nla_get_u32(tb[TCA_RSVP_CLASSID]); - - dst = nla_data(tb[TCA_RSVP_DST]); - h1 = hash_dst(dst, pinfo ? pinfo->protocol : 0, pinfo ? pinfo->tunnelid : 0); - - err = -ENOMEM; - if ((f->handle = gen_handle(tp, h1 | (h2<<8))) == 0) - goto errout; - - if (f->tunnelhdr) { - err = -EINVAL; - if (f->res.classid > 255) - goto errout; - - err = -ENOMEM; - if (f->res.classid == 0 && - (f->res.classid = gen_tunnel(data)) == 0) - goto errout; - } - - for (sp = &data->ht[h1]; - (s = rtnl_dereference(*sp)) != NULL; - sp = &s->next) { - if (dst[RSVP_DST_LEN-1] == s->dst[RSVP_DST_LEN-1] && - pinfo && pinfo->protocol == s->protocol && - memcmp(&pinfo->dpi, &s->dpi, sizeof(s->dpi)) == 0 && -#if RSVP_DST_LEN == 4 - dst[0] == s->dst[0] && - dst[1] == s->dst[1] && - dst[2] == s->dst[2] && -#endif - pinfo->tunnelid == s->tunnelid) { - -insert: - /* OK, we found appropriate session */ - - fp = &s->ht[h2]; - - f->sess = s; - if (f->tunnelhdr == 0) - tcf_bind_filter(tp, &f->res, base); - - tcf_exts_change(&f->exts, &e); - - fp = &s->ht[h2]; - for (nfp = rtnl_dereference(*fp); nfp; - fp = &nfp->next, nfp = rtnl_dereference(*fp)) { - __u32 mask = nfp->spi.mask & f->spi.mask; - - if (mask != f->spi.mask) - break; - } - RCU_INIT_POINTER(f->next, nfp); - rcu_assign_pointer(*fp, f); - - *arg = f; - return 0; - } - } - - /* No session found. Create new one. */ - - err = -ENOBUFS; - s = kzalloc(sizeof(struct rsvp_session), GFP_KERNEL); - if (s == NULL) - goto errout; - memcpy(s->dst, dst, sizeof(s->dst)); - - if (pinfo) { - s->dpi = pinfo->dpi; - s->protocol = pinfo->protocol; - s->tunnelid = pinfo->tunnelid; - } - sp = &data->ht[h1]; - for (nsp = rtnl_dereference(*sp); nsp; - sp = &nsp->next, nsp = rtnl_dereference(*sp)) { - if ((nsp->dpi.mask & s->dpi.mask) != s->dpi.mask) - break; - } - RCU_INIT_POINTER(s->next, nsp); - rcu_assign_pointer(*sp, s); - - goto insert; - -errout: - tcf_exts_destroy(&f->exts); - kfree(f); -errout2: - tcf_exts_destroy(&e); - return err; -} - -static void rsvp_walk(struct tcf_proto *tp, struct tcf_walker *arg, - bool rtnl_held) -{ - struct rsvp_head *head = rtnl_dereference(tp->root); - unsigned int h, h1; - - if (arg->stop) - return; - - for (h = 0; h < 256; h++) { - struct rsvp_session *s; - - for (s = rtnl_dereference(head->ht[h]); s; - s = rtnl_dereference(s->next)) { - for (h1 = 0; h1 <= 16; h1++) { - struct rsvp_filter *f; - - for (f = rtnl_dereference(s->ht[h1]); f; - f = rtnl_dereference(f->next)) { - if (arg->count < arg->skip) { - arg->count++; - continue; - } - if (arg->fn(tp, f, arg) < 0) { - arg->stop = 1; - return; - } - arg->count++; - } - } - } - } -} - -static int rsvp_dump(struct net *net, struct tcf_proto *tp, void *fh, - struct sk_buff *skb, struct tcmsg *t, bool rtnl_held) -{ - struct rsvp_filter *f = fh; - struct rsvp_session *s; - struct nlattr *nest; - struct tc_rsvp_pinfo pinfo; - - if (f == NULL) - return skb->len; - s = f->sess; - - t->tcm_handle = f->handle; - - nest = nla_nest_start_noflag(skb, TCA_OPTIONS); - if (nest == NULL) - goto nla_put_failure; - - if (nla_put(skb, TCA_RSVP_DST, sizeof(s->dst), &s->dst)) - goto nla_put_failure; - pinfo.dpi = s->dpi; - pinfo.spi = f->spi; - pinfo.protocol = s->protocol; - pinfo.tunnelid = s->tunnelid; - pinfo.tunnelhdr = f->tunnelhdr; - pinfo.pad = 0; - if (nla_put(skb, TCA_RSVP_PINFO, sizeof(pinfo), &pinfo)) - goto nla_put_failure; - if (f->res.classid && - nla_put_u32(skb, TCA_RSVP_CLASSID, f->res.classid)) - goto nla_put_failure; - if (((f->handle >> 8) & 0xFF) != 16 && - nla_put(skb, TCA_RSVP_SRC, sizeof(f->src), f->src)) - goto nla_put_failure; - - if (tcf_exts_dump(skb, &f->exts) < 0) - goto nla_put_failure; - - nla_nest_end(skb, nest); - - if (tcf_exts_dump_stats(skb, &f->exts) < 0) - goto nla_put_failure; - return skb->len; - -nla_put_failure: - nla_nest_cancel(skb, nest); - return -1; -} - -static void rsvp_bind_class(void *fh, u32 classid, unsigned long cl, void *q, - unsigned long base) -{ - struct rsvp_filter *f = fh; - - if (f && f->res.classid == classid) { - if (cl) - __tcf_bind_filter(q, &f->res, base); - else - __tcf_unbind_filter(q, &f->res); - } -} - -static struct tcf_proto_ops RSVP_OPS __read_mostly = { - .kind = RSVP_ID, - .classify = rsvp_classify, - .init = rsvp_init, - .destroy = rsvp_destroy, - .get = rsvp_get, - .change = rsvp_change, - .delete = rsvp_delete, - .walk = rsvp_walk, - .dump = rsvp_dump, - .bind_class = rsvp_bind_class, - .owner = THIS_MODULE, -}; - -static int __init init_rsvp(void) -{ - return register_tcf_proto_ops(&RSVP_OPS); -} - -static void __exit exit_rsvp(void) -{ - unregister_tcf_proto_ops(&RSVP_OPS); -} - -module_init(init_rsvp) -module_exit(exit_rsvp) diff --git a/net/sched/cls_rsvp6.c b/net/sched/cls_rsvp6.c deleted file mode 100644 index 64078846000e..000000000000 --- a/net/sched/cls_rsvp6.c +++ /dev/null @@ -1,24 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later -/* - * net/sched/cls_rsvp6.c Special RSVP packet classifier for IPv6. - * - * Authors: Alexey Kuznetsov, - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define RSVP_DST_LEN 4 -#define RSVP_ID "rsvp6" -#define RSVP_OPS cls_rsvp6_ops - -#include "cls_rsvp.h" -MODULE_LICENSE("GPL"); diff --git a/net/sched/cls_u32.c b/net/sched/cls_u32.c index 0025fa837e85..25430c163282 100644 --- a/net/sched/cls_u32.c +++ b/net/sched/cls_u32.c @@ -812,7 +812,6 @@ static struct tc_u_knode *u32_init_knode(struct net *net, struct tcf_proto *tp, new->ifindex = n->ifindex; new->fshift = n->fshift; - new->res = n->res; new->flags = n->flags; RCU_INIT_POINTER(new->ht_down, ht); diff --git a/net/sched/sch_hfsc.c b/net/sched/sch_hfsc.c index c802a027b4f3..01126e285f94 100644 --- a/net/sched/sch_hfsc.c +++ b/net/sched/sch_hfsc.c @@ -1012,6 +1012,10 @@ hfsc_change_class(struct Qdisc *sch, u32 classid, u32 parentid, if (parent == NULL) return -ENOENT; } + if (!(parent->cl_flags & HFSC_FSC) && parent != &q->root) { + NL_SET_ERR_MSG(extack, "Invalid parent - parent class must have FSC"); + return -EINVAL; + } if (classid == 0 || TC_H_MAJ(classid ^ sch->handle) != 0) return -EINVAL; diff --git a/net/sched/sch_plug.c b/net/sched/sch_plug.c index cbc2ebca4548..339990bb5981 100644 --- a/net/sched/sch_plug.c +++ b/net/sched/sch_plug.c @@ -210,7 +210,7 @@ static struct Qdisc_ops plug_qdisc_ops __read_mostly = { .priv_size = sizeof(struct plug_sched_data), .enqueue = plug_enqueue, .dequeue = plug_dequeue, - .peek = qdisc_peek_head, + .peek = qdisc_peek_dequeued, .init = plug_init, .change = plug_change, .reset = qdisc_reset_queue, diff --git a/net/sched/sch_qfq.c b/net/sched/sch_qfq.c index 3ba6a766601c..b1dbe03dde1b 100644 --- a/net/sched/sch_qfq.c +++ b/net/sched/sch_qfq.c @@ -428,10 +428,17 @@ static int qfq_change_class(struct Qdisc *sch, u32 classid, u32 parentid, else weight = 1; - if (tb[TCA_QFQ_LMAX]) + if (tb[TCA_QFQ_LMAX]) { lmax = nla_get_u32(tb[TCA_QFQ_LMAX]); - else + } else { + /* MTU size is user controlled */ lmax = psched_mtu(qdisc_dev(sch)); + if (lmax < QFQ_MIN_LMAX || lmax > QFQ_MAX_LMAX) { + NL_SET_ERR_MSG_MOD(extack, + "MTU size out of bounds for qfq"); + return -EINVAL; + } + } inv_w = ONE_FP / weight; weight = ONE_FP / inv_w; @@ -973,10 +980,13 @@ static void qfq_update_eligible(struct qfq_sched *q) } /* Dequeue head packet of the head class in the DRR queue of the aggregate. */ -static void agg_dequeue(struct qfq_aggregate *agg, - struct qfq_class *cl, unsigned int len) +static struct sk_buff *agg_dequeue(struct qfq_aggregate *agg, + struct qfq_class *cl, unsigned int len) { - qdisc_dequeue_peeked(cl->qdisc); + struct sk_buff *skb = qdisc_dequeue_peeked(cl->qdisc); + + if (!skb) + return NULL; cl->deficit -= (int) len; @@ -986,6 +996,8 @@ static void agg_dequeue(struct qfq_aggregate *agg, cl->deficit += agg->lmax; list_move_tail(&cl->alist, &agg->active); } + + return skb; } static inline struct sk_buff *qfq_peek_skb(struct qfq_aggregate *agg, @@ -1131,11 +1143,18 @@ static struct sk_buff *qfq_dequeue(struct Qdisc *sch) if (!skb) return NULL; - qdisc_qstats_backlog_dec(sch, skb); sch->q.qlen--; + + skb = agg_dequeue(in_serv_agg, cl, len); + + if (!skb) { + sch->q.qlen++; + return NULL; + } + + qdisc_qstats_backlog_dec(sch, skb); qdisc_bstats_update(sch, skb); - agg_dequeue(in_serv_agg, cl, len); /* If lmax is lowered, through qfq_change_class, for a class * owning pending packets with larger size than the new value * of lmax, then the following condition may hold. diff --git a/net/sctp/socket.c b/net/sctp/socket.c index 23fe303cf682..34bdaef89290 100644 --- a/net/sctp/socket.c +++ b/net/sctp/socket.c @@ -362,9 +362,9 @@ static void sctp_auto_asconf_init(struct sctp_sock *sp) struct net *net = sock_net(&sp->inet.sk); if (net->sctp.default_auto_asconf) { - spin_lock(&net->sctp.addr_wq_lock); + spin_lock_bh(&net->sctp.addr_wq_lock); list_add_tail(&sp->auto_asconf_list, &net->sctp.auto_asconf_splist); - spin_unlock(&net->sctp.addr_wq_lock); + spin_unlock_bh(&net->sctp.addr_wq_lock); sp->do_auto_asconf = 1; } } @@ -8292,6 +8292,22 @@ static int sctp_getsockopt(struct sock *sk, int level, int optname, return retval; } +static bool sctp_bpf_bypass_getsockopt(int level, int optname) +{ + if (level == SOL_SCTP) { + switch (optname) { + case SCTP_SOCKOPT_PEELOFF: + case SCTP_SOCKOPT_PEELOFF_FLAGS: + case SCTP_SOCKOPT_CONNECTX3: + return true; + default: + return false; + } + } + + return false; +} + static int sctp_hash(struct sock *sk) { /* STUB */ @@ -9660,6 +9676,7 @@ struct proto sctp_prot = { .shutdown = sctp_shutdown, .setsockopt = sctp_setsockopt, .getsockopt = sctp_getsockopt, + .bpf_bypass_getsockopt = sctp_bpf_bypass_getsockopt, .sendmsg = sctp_sendmsg, .recvmsg = sctp_recvmsg, .bind = sctp_bind, @@ -9712,6 +9729,7 @@ struct proto sctpv6_prot = { .shutdown = sctp_shutdown, .setsockopt = sctp_setsockopt, .getsockopt = sctp_getsockopt, + .bpf_bypass_getsockopt = sctp_bpf_bypass_getsockopt, .sendmsg = sctp_sendmsg, .recvmsg = sctp_recvmsg, .bind = sctp_bind, diff --git a/net/sunrpc/svcsock.c b/net/sunrpc/svcsock.c index 6fc7a8c52369..be7081284a09 100644 --- a/net/sunrpc/svcsock.c +++ b/net/sunrpc/svcsock.c @@ -685,12 +685,6 @@ static void svc_tcp_listen_data_ready(struct sock *sk) { struct svc_sock *svsk = (struct svc_sock *)sk->sk_user_data; - if (svsk) { - /* Refer to svc_setup_socket() for details. */ - rmb(); - svsk->sk_odata(sk); - } - /* * This callback may called twice when a new connection * is established as a child socket inherits everything @@ -699,13 +693,18 @@ static void svc_tcp_listen_data_ready(struct sock *sk) * when one of child sockets become ESTABLISHED. * 2) data_ready method of the child socket may be called * when it receives data before the socket is accepted. - * In case of 2, we should ignore it silently. + * In case of 2, we should ignore it silently and DO NOT + * dereference svsk. */ - if (sk->sk_state == TCP_LISTEN) { - if (svsk) { - set_bit(XPT_CONN, &svsk->sk_xprt.xpt_flags); - svc_xprt_enqueue(&svsk->sk_xprt); - } + if (sk->sk_state != TCP_LISTEN) + return; + + if (svsk) { + /* Refer to svc_setup_socket() for details. */ + rmb(); + svsk->sk_odata(sk); + set_bit(XPT_CONN, &svsk->sk_xprt.xpt_flags); + svc_xprt_enqueue(&svsk->sk_xprt); } } diff --git a/net/sunrpc/xprtrdma/svc_rdma_recvfrom.c b/net/sunrpc/xprtrdma/svc_rdma_recvfrom.c index 3ad4291148a6..0377679678f9 100644 --- a/net/sunrpc/xprtrdma/svc_rdma_recvfrom.c +++ b/net/sunrpc/xprtrdma/svc_rdma_recvfrom.c @@ -791,6 +791,12 @@ int svc_rdma_recvfrom(struct svc_rqst *rqstp) struct svc_rdma_recv_ctxt *ctxt; int ret; + /* Prevent svc_xprt_release() from releasing pages in rq_pages + * when returning 0 or an error. + */ + rqstp->rq_respages = rqstp->rq_pages; + rqstp->rq_next_page = rqstp->rq_respages; + rqstp->rq_xprt_ctxt = NULL; ctxt = NULL; @@ -814,12 +820,6 @@ int svc_rdma_recvfrom(struct svc_rqst *rqstp) DMA_FROM_DEVICE); svc_rdma_build_arg_xdr(rqstp, ctxt); - /* Prevent svc_xprt_release from releasing pages in rq_pages - * if we return 0 or an error. - */ - rqstp->rq_respages = rqstp->rq_pages; - rqstp->rq_next_page = rqstp->rq_respages; - ret = svc_rdma_xdr_decode_req(&rqstp->rq_arg, ctxt); if (ret < 0) goto out_err; diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c index fa18a7125042..1abf1ab0059e 100644 --- a/net/unix/af_unix.c +++ b/net/unix/af_unix.c @@ -2156,6 +2156,7 @@ static ssize_t unix_stream_sendpage(struct socket *socket, struct page *page, if (false) { alloc_skb: + spin_unlock(&other->sk_receive_queue.lock); unix_state_unlock(other); mutex_unlock(&unix_sk(other)->iolock); newskb = sock_alloc_send_pskb(sk, 0, 0, flags & MSG_DONTWAIT, @@ -2195,6 +2196,7 @@ alloc_skb: init_scm = false; } + spin_lock(&other->sk_receive_queue.lock); skb = skb_peek_tail(&other->sk_receive_queue); if (tail && tail == skb) { skb = newskb; @@ -2225,14 +2227,11 @@ alloc_skb: refcount_add(size, &sk->sk_wmem_alloc); if (newskb) { - err = unix_scm_to_skb(&scm, skb, false); - if (err) - goto err_state_unlock; - spin_lock(&other->sk_receive_queue.lock); + unix_scm_to_skb(&scm, skb, false); __skb_queue_tail(&other->sk_receive_queue, newskb); - spin_unlock(&other->sk_receive_queue.lock); } + spin_unlock(&other->sk_receive_queue.lock); unix_state_unlock(other); mutex_unlock(&unix_sk(other)->iolock); diff --git a/net/wireless/util.c b/net/wireless/util.c index bac788fb80e9..41763e4f7d31 100644 --- a/net/wireless/util.c +++ b/net/wireless/util.c @@ -85,6 +85,10 @@ u32 ieee80211_channel_to_freq_khz(int chan, enum nl80211_band band) return MHZ_TO_KHZ(2484); else if (chan < 14) return MHZ_TO_KHZ(2407 + chan * 5); + else if (chan == 221 || chan == 222) + return MHZ_TO_KHZ(2477 + (chan - 221) * 5); + else if (chan >= 203 && chan <= 216) + return MHZ_TO_KHZ(2399 + (chan - 200) * 5); break; case NL80211_BAND_5GHZ: if (chan >= 182 && chan <= 196) diff --git a/net/xdp/xsk.c b/net/xdp/xsk.c index 1381a4b2f192..d76871dc7137 100644 --- a/net/xdp/xsk.c +++ b/net/xdp/xsk.c @@ -893,6 +893,7 @@ static int xsk_bind(struct socket *sock, struct sockaddr *addr, int addr_len) struct sock *sk = sock->sk; struct xdp_sock *xs = xdp_sk(sk); struct net_device *dev; + int bound_dev_if; u32 flags, qid; int err = 0; @@ -906,6 +907,10 @@ static int xsk_bind(struct socket *sock, struct sockaddr *addr, int addr_len) XDP_USE_NEED_WAKEUP)) return -EINVAL; + bound_dev_if = READ_ONCE(sk->sk_bound_dev_if); + if (bound_dev_if && bound_dev_if != sxdp->sxdp_ifindex) + return -EINVAL; + rtnl_lock(); mutex_lock(&xs->mutex); if (xs->state != XSK_READY) { diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c index 951ca8e4ee08..65ee282cb551 100644 --- a/net/xfrm/xfrm_user.c +++ b/net/xfrm/xfrm_user.c @@ -1159,6 +1159,15 @@ static int xfrm_dump_sa(struct sk_buff *skb, struct netlink_callback *cb) sizeof(*filter), GFP_KERNEL); if (filter == NULL) return -ENOMEM; + + /* see addr_match(), (prefix length >> 5) << 2 + * will be used to compare xfrm_address_t + */ + if (filter->splen > (sizeof(xfrm_address_t) << 3) || + filter->dplen > (sizeof(xfrm_address_t) << 3)) { + kfree(filter); + return -EINVAL; + } } if (attrs[XFRMA_PROTO]) diff --git a/samples/bpf/tcp_basertt_kern.c b/samples/bpf/tcp_basertt_kern.c index 8dfe09a92fec..822b0742b815 100644 --- a/samples/bpf/tcp_basertt_kern.c +++ b/samples/bpf/tcp_basertt_kern.c @@ -47,7 +47,7 @@ int bpf_basertt(struct bpf_sock_ops *skops) case BPF_SOCK_OPS_BASE_RTT: n = bpf_getsockopt(skops, SOL_TCP, TCP_CONGESTION, cong, sizeof(cong)); - if (!n && !__builtin_memcmp(cong, nv, sizeof(nv)+1)) { + if (!n && !__builtin_memcmp(cong, nv, sizeof(nv))) { /* Set base_rtt to 80us */ rv = 80; } else if (n) { diff --git a/samples/ftrace/ftrace-direct-too.c b/samples/ftrace/ftrace-direct-too.c index 3927cb880d1a..4bdd67916ce4 100644 --- a/samples/ftrace/ftrace-direct-too.c +++ b/samples/ftrace/ftrace-direct-too.c @@ -4,14 +4,14 @@ #include /* for handle_mm_fault() */ #include -extern void my_direct_func(struct vm_area_struct *vma, - unsigned long address, unsigned int flags); +extern void my_direct_func(struct vm_area_struct *vma, unsigned long address, + unsigned int flags, struct pt_regs *regs); -void my_direct_func(struct vm_area_struct *vma, - unsigned long address, unsigned int flags) +void my_direct_func(struct vm_area_struct *vma, unsigned long address, + unsigned int flags, struct pt_regs *regs) { - trace_printk("handle mm fault vma=%p address=%lx flags=%x\n", - vma, address, flags); + trace_printk("handle mm fault vma=%p address=%lx flags=%x regs=%p\n", + vma, address, flags, regs); } extern void my_tramp(void *); @@ -26,7 +26,9 @@ asm ( " pushq %rdi\n" " pushq %rsi\n" " pushq %rdx\n" +" pushq %rcx\n" " call my_direct_func\n" +" popq %rcx\n" " popq %rdx\n" " popq %rsi\n" " popq %rdi\n" diff --git a/scripts/Makefile.modfinal b/scripts/Makefile.modfinal index 10d9a902f851..0e3f22f7cd47 100644 --- a/scripts/Makefile.modfinal +++ b/scripts/Makefile.modfinal @@ -25,7 +25,7 @@ modname = $(notdir $(@:.mod.o=)) part-of-module = y quiet_cmd_cc_o_c = CC [M] $@ - cmd_cc_o_c = $(CC) $(filter-out $(CC_FLAGS_CFI), $(c_flags)) -c -o $@ $< + cmd_cc_o_c = $(CC) $(filter-out $(CC_FLAGS_CFI) $(CFLAGS_GCOV), $(c_flags)) -c -o $@ $< %.mod.o: %.mod.c FORCE $(call if_changed_dep,cc_o_c) diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c index 44a55aeb35e2..d6339783c5ec 100644 --- a/scripts/mod/modpost.c +++ b/scripts/mod/modpost.c @@ -1303,6 +1303,10 @@ static Elf_Sym *find_elf_symbol(struct elf_info *elf, Elf64_Sword addr, if (relsym->st_name != 0) return relsym; + /* + * Strive to find a better symbol name, but the resulting name may not + * match the symbol referenced in the original code. + */ relsym_secindex = get_secindex(elf, relsym); for (sym = elf->symtab_start; sym < elf->symtab_stop; sym++) { if (get_secindex(elf, sym) != relsym_secindex) @@ -1607,49 +1611,12 @@ static void default_mismatch_handler(const char *modname, struct elf_info *elf, static int is_executable_section(struct elf_info* elf, unsigned int section_index) { - if (section_index > elf->num_sections) + if (section_index >= elf->num_sections) fatal("section_index is outside elf->num_sections!\n"); return ((elf->sechdrs[section_index].sh_flags & SHF_EXECINSTR) == SHF_EXECINSTR); } -/* - * We rely on a gross hack in section_rel[a]() calling find_extable_entry_size() - * to know the sizeof(struct exception_table_entry) for the target architecture. - */ -static unsigned int extable_entry_size = 0; -static void find_extable_entry_size(const char* const sec, const Elf_Rela* r) -{ - /* - * If we're currently checking the second relocation within __ex_table, - * that relocation offset tells us the offsetof(struct - * exception_table_entry, fixup) which is equal to sizeof(struct - * exception_table_entry) divided by two. We use that to our advantage - * since there's no portable way to get that size as every architecture - * seems to go with different sized types. Not pretty but better than - * hard-coding the size for every architecture.. - */ - if (!extable_entry_size) - extable_entry_size = r->r_offset * 2; -} - -static inline bool is_extable_fault_address(Elf_Rela *r) -{ - /* - * extable_entry_size is only discovered after we've handled the - * _second_ relocation in __ex_table, so only abort when we're not - * handling the first reloc and extable_entry_size is zero. - */ - if (r->r_offset && extable_entry_size == 0) - fatal("extable_entry size hasn't been discovered!\n"); - - return ((r->r_offset == 0) || - (r->r_offset % extable_entry_size == 0)); -} - -#define is_second_extable_reloc(Start, Cur, Sec) \ - (((Cur) == (Start) + 1) && (strcmp("__ex_table", (Sec)) == 0)) - static void report_extable_warnings(const char* modname, struct elf_info* elf, const struct sectioncheck* const mismatch, Elf_Rela* r, Elf_Sym* sym, @@ -1706,22 +1673,9 @@ static void extable_mismatch_handler(const char* modname, struct elf_info *elf, "You might get more information about where this is\n" "coming from by using scripts/check_extable.sh %s\n", fromsec, (long)r->r_offset, tosec, modname); - else if (!is_executable_section(elf, get_secindex(elf, sym))) { - if (is_extable_fault_address(r)) - fatal("The relocation at %s+0x%lx references\n" - "section \"%s\" which is not executable, IOW\n" - "it is not possible for the kernel to fault\n" - "at that address. Something is seriously wrong\n" - "and should be fixed.\n", - fromsec, (long)r->r_offset, tosec); - else - fatal("The relocation at %s+0x%lx references\n" - "section \"%s\" which is not executable, IOW\n" - "the kernel will fault if it ever tries to\n" - "jump to it. Something is seriously wrong\n" - "and should be fixed.\n", - fromsec, (long)r->r_offset, tosec); - } + else if (!is_executable_section(elf, get_secindex(elf, sym))) + error("%s+0x%lx references non-executable section '%s'\n", + fromsec, (long)r->r_offset, tosec); } static void check_section_mismatch(const char *modname, struct elf_info *elf, @@ -1782,19 +1736,33 @@ static int addend_386_rel(struct elf_info *elf, Elf_Shdr *sechdr, Elf_Rela *r) #define R_ARM_THM_JUMP19 51 #endif +static int32_t sign_extend32(int32_t value, int index) +{ + uint8_t shift = 31 - index; + + return (int32_t)(value << shift) >> shift; +} + static int addend_arm_rel(struct elf_info *elf, Elf_Shdr *sechdr, Elf_Rela *r) { unsigned int r_typ = ELF_R_TYPE(r->r_info); + Elf_Sym *sym = elf->symtab_start + ELF_R_SYM(r->r_info); + void *loc = reloc_location(elf, sechdr, r); + uint32_t inst; + int32_t offset; switch (r_typ) { case R_ARM_ABS32: - /* From ARM ABI: (S + A) | T */ - r->r_addend = (int)(long) - (elf->symtab_start + ELF_R_SYM(r->r_info)); + inst = TO_NATIVE(*(uint32_t *)loc); + r->r_addend = inst + sym->st_value; break; case R_ARM_PC24: case R_ARM_CALL: case R_ARM_JUMP24: + inst = TO_NATIVE(*(uint32_t *)loc); + offset = sign_extend32((inst & 0x00ffffff) << 2, 25); + r->r_addend = offset + sym->st_value + 8; + break; case R_ARM_THM_CALL: case R_ARM_THM_JUMP24: case R_ARM_THM_JUMP19: @@ -1872,8 +1840,6 @@ static void section_rela(const char *modname, struct elf_info *elf, /* Skip special sections */ if (is_shndx_special(sym->st_shndx)) continue; - if (is_second_extable_reloc(start, rela, fromsec)) - find_extable_entry_size(fromsec, &r); check_section_mismatch(modname, elf, &r, sym, fromsec); } } @@ -1932,8 +1898,6 @@ static void section_rel(const char *modname, struct elf_info *elf, /* Skip special sections */ if (is_shndx_special(sym->st_shndx)) continue; - if (is_second_extable_reloc(start, rel, fromsec)) - find_extable_entry_size(fromsec, &r); check_section_mismatch(modname, elf, &r, sym, fromsec); } } diff --git a/scripts/tags.sh b/scripts/tags.sh index 91413d45f0fa..d40cae4e7ea2 100755 --- a/scripts/tags.sh +++ b/scripts/tags.sh @@ -32,6 +32,13 @@ else ignore="$ignore ( -path ${tree}tools ) -prune -o" fi +# gtags(1) refuses to index any file outside of its current working dir. +# If gtags indexing is requested and the build output directory is not +# the kernel source tree, index all files in absolute-path form. +if [[ "$1" == "gtags" && -n "${tree}" ]]; then + tree=$(realpath "$tree")/ +fi + # Detect if ALLSOURCE_ARCHS is set. If not, we assume SRCARCH if [ "${ALLSOURCE_ARCHS}" = "" ]; then ALLSOURCE_ARCHS=${SRCARCH} @@ -131,7 +138,7 @@ docscope() dogtags() { - all_target_sources | gtags -i -f - + all_target_sources | gtags -i -C "${tree:-.}" -f - "$PWD" } # Basic regular expressions with an optional /kind-spec/ for ctags and diff --git a/security/apparmor/policy_unpack.c b/security/apparmor/policy_unpack.c index d5b3a062d1d1..5f758b289ace 100644 --- a/security/apparmor/policy_unpack.c +++ b/security/apparmor/policy_unpack.c @@ -909,8 +909,13 @@ static struct aa_profile *unpack_profile(struct aa_ext *e, char **ns_name) goto fail; } - rhashtable_insert_fast(profile->data, &data->head, - profile->data->p); + if (rhashtable_insert_fast(profile->data, &data->head, + profile->data->p)) { + kfree_sensitive(data->key); + kfree_sensitive(data); + info = "failed to insert data to table"; + goto fail; + } } if (!unpack_nameX(e, AA_STRUCTEND, NULL)) { diff --git a/security/integrity/evm/evm_crypto.c b/security/integrity/evm/evm_crypto.c index b862f0f919bf..99c7452555c3 100644 --- a/security/integrity/evm/evm_crypto.c +++ b/security/integrity/evm/evm_crypto.c @@ -40,7 +40,7 @@ static const char evm_hmac[] = "hmac(sha1)"; /** * evm_set_key() - set EVM HMAC key from the kernel * @key: pointer to a buffer with the key data - * @size: length of the key data + * @keylen: length of the key data * * This function allows setting the EVM HMAC key from the kernel * without using the "encrypted" key subsystem keys. It can be used diff --git a/security/integrity/evm/evm_main.c b/security/integrity/evm/evm_main.c index 7d87772f0ce6..b0e791e18432 100644 --- a/security/integrity/evm/evm_main.c +++ b/security/integrity/evm/evm_main.c @@ -324,7 +324,6 @@ int evm_protected_xattr_if_enabled(const char *req_xattr_name) /** * evm_read_protected_xattrs - read EVM protected xattr names, lengths, values * @dentry: dentry of the read xattrs - * @inode: inode of the read xattrs * @buffer: buffer xattr names, lengths or values are copied to * @buffer_size: size of buffer * @type: n: names, l: lengths, v: values @@ -396,6 +395,7 @@ int evm_read_protected_xattrs(struct dentry *dentry, u8 *buffer, * @xattr_name: requested xattr * @xattr_value: requested xattr value * @xattr_value_len: requested xattr value length + * @iint: inode integrity metadata * * Calculate the HMAC for the given dentry and verify it against the stored * security.evm xattr. For performance, use the xattr value and length @@ -770,7 +770,9 @@ static int evm_attr_change(struct dentry *dentry, struct iattr *attr) /** * evm_inode_setattr - prevent updating an invalid EVM extended attribute + * @idmap: idmap of the mount * @dentry: pointer to the affected dentry + * @attr: iattr structure containing the new file attributes * * Permit update of file attributes when files have a valid EVM signature, * except in the case of them having an immutable portable signature. diff --git a/security/integrity/iint.c b/security/integrity/iint.c index 8638976f7990..65418e0906c1 100644 --- a/security/integrity/iint.c +++ b/security/integrity/iint.c @@ -43,12 +43,10 @@ static struct integrity_iint_cache *__integrity_iint_find(struct inode *inode) else if (inode > iint->inode) n = n->rb_right; else - break; + return iint; } - if (!n) - return NULL; - return iint; + return NULL; } /* @@ -121,10 +119,15 @@ struct integrity_iint_cache *integrity_inode_get(struct inode *inode) parent = *p; test_iint = rb_entry(parent, struct integrity_iint_cache, rb_node); - if (inode < test_iint->inode) + if (inode < test_iint->inode) { p = &(*p)->rb_left; - else + } else if (inode > test_iint->inode) { p = &(*p)->rb_right; + } else { + write_unlock(&integrity_iint_lock); + kmem_cache_free(iint_cache, iint); + return test_iint; + } } iint->inode = inode; diff --git a/security/integrity/ima/ima_modsig.c b/security/integrity/ima/ima_modsig.c index fb25723c65bc..3e7bee30080f 100644 --- a/security/integrity/ima/ima_modsig.c +++ b/security/integrity/ima/ima_modsig.c @@ -89,6 +89,9 @@ int ima_read_modsig(enum ima_hooks func, const void *buf, loff_t buf_len, /** * ima_collect_modsig - Calculate the file hash without the appended signature. + * @modsig: parsed module signature + * @buf: data to verify the signature on + * @size: data size * * Since the modsig is part of the file contents, the hash used in its signature * isn't the same one ordinarily calculated by IMA. Therefore PKCS7 code diff --git a/security/integrity/ima/ima_policy.c b/security/integrity/ima/ima_policy.c index ed43d30682ff..7e41917e1f76 100644 --- a/security/integrity/ima/ima_policy.c +++ b/security/integrity/ima/ima_policy.c @@ -674,6 +674,7 @@ static int get_subaction(struct ima_rule_entry *rule, enum ima_hooks func) * @secid: LSM secid of the task to be validated * @func: IMA hook identifier * @mask: requested action (MAY_READ | MAY_WRITE | MAY_APPEND | MAY_EXEC) + * @flags: IMA actions to consider (e.g. IMA_MEASURE | IMA_APPRAISE) * @pcr: set the pcr to extend * @template_desc: the template that should be used for this rule * @func_data: func specific data, may be NULL @@ -1709,7 +1710,7 @@ static int ima_parse_rule(char *rule, struct ima_rule_entry *entry) /** * ima_parse_add_rule - add a rule to ima_policy_rules - * @rule - ima measurement policy rule + * @rule: ima measurement policy rule * * Avoid locking by allowing just one writer at a time in ima_write_policy() * Returns the length of the rule parsed, an error code on failure diff --git a/security/keys/request_key.c b/security/keys/request_key.c index 07a0ef2baacd..a7673ad86d18 100644 --- a/security/keys/request_key.c +++ b/security/keys/request_key.c @@ -401,17 +401,21 @@ static int construct_alloc_key(struct keyring_search_context *ctx, set_bit(KEY_FLAG_USER_CONSTRUCT, &key->flags); if (dest_keyring) { - ret = __key_link_lock(dest_keyring, &ctx->index_key); + ret = __key_link_lock(dest_keyring, &key->index_key); if (ret < 0) goto link_lock_failed; - ret = __key_link_begin(dest_keyring, &ctx->index_key, &edit); - if (ret < 0) - goto link_prealloc_failed; } - /* attach the key to the destination keyring under lock, but we do need + /* + * Attach the key to the destination keyring under lock, but we do need * to do another check just in case someone beat us to it whilst we - * waited for locks */ + * waited for locks. + * + * The caller might specify a comparison function which looks for keys + * that do not exactly match but are still equivalent from the caller's + * perspective. The __key_link_begin() operation must be done only after + * an actual key is determined. + */ mutex_lock(&key_construction_mutex); rcu_read_lock(); @@ -420,12 +424,16 @@ static int construct_alloc_key(struct keyring_search_context *ctx, if (!IS_ERR(key_ref)) goto key_already_present; - if (dest_keyring) + if (dest_keyring) { + ret = __key_link_begin(dest_keyring, &key->index_key, &edit); + if (ret < 0) + goto link_alloc_failed; __key_link(dest_keyring, key, &edit); + } mutex_unlock(&key_construction_mutex); if (dest_keyring) - __key_link_end(dest_keyring, &ctx->index_key, edit); + __key_link_end(dest_keyring, &key->index_key, edit); mutex_unlock(&user->cons_lock); *_key = key; kleave(" = 0 [%d]", key_serial(key)); @@ -438,10 +446,13 @@ key_already_present: mutex_unlock(&key_construction_mutex); key = key_ref_to_ptr(key_ref); if (dest_keyring) { + ret = __key_link_begin(dest_keyring, &key->index_key, &edit); + if (ret < 0) + goto link_alloc_failed_unlocked; ret = __key_link_check_live_key(dest_keyring, key); if (ret == 0) __key_link(dest_keyring, key, &edit); - __key_link_end(dest_keyring, &ctx->index_key, edit); + __key_link_end(dest_keyring, &key->index_key, edit); if (ret < 0) goto link_check_failed; } @@ -456,8 +467,10 @@ link_check_failed: kleave(" = %d [linkcheck]", ret); return ret; -link_prealloc_failed: - __key_link_end(dest_keyring, &ctx->index_key, edit); +link_alloc_failed: + mutex_unlock(&key_construction_mutex); +link_alloc_failed_unlocked: + __key_link_end(dest_keyring, &key->index_key, edit); link_lock_failed: mutex_unlock(&user->cons_lock); key_put(key); diff --git a/security/keys/trusted-keys/trusted_tpm2.c b/security/keys/trusted-keys/trusted_tpm2.c index 2b2c8eb258d5..bc700f85f80b 100644 --- a/security/keys/trusted-keys/trusted_tpm2.c +++ b/security/keys/trusted-keys/trusted_tpm2.c @@ -186,7 +186,7 @@ int tpm2_key_priv(void *context, size_t hdrlen, } /** - * tpm_buf_append_auth() - append TPMS_AUTH_COMMAND to the buffer. + * tpm2_buf_append_auth() - append TPMS_AUTH_COMMAND to the buffer. * * @buf: an allocated tpm_buf instance * @session_handle: session handle diff --git a/sound/core/jack.c b/sound/core/jack.c index d1e3055f2b6a..813726c60094 100644 --- a/sound/core/jack.c +++ b/sound/core/jack.c @@ -638,6 +638,7 @@ void snd_jack_report(struct snd_jack *jack, int status) struct snd_jack_kctl *jack_kctl; unsigned int mask_bits = 0; #ifdef CONFIG_SND_JACK_INPUT_DEV + struct input_dev *idev; int i; #endif @@ -654,14 +655,15 @@ void snd_jack_report(struct snd_jack *jack, int status) status & jack_kctl->mask_bits); #ifdef CONFIG_SND_JACK_INPUT_DEV - if (!jack->input_dev) + idev = input_get_device(jack->input_dev); + if (!idev) return; for (i = 0; i < ARRAY_SIZE(jack->key); i++) { int testbit = ((SND_JACK_BTN_0 >> i) & ~mask_bits); if (jack->type & testbit) - input_report_key(jack->input_dev, jack->key[i], + input_report_key(idev, jack->key[i], status & testbit); } @@ -669,12 +671,13 @@ void snd_jack_report(struct snd_jack *jack, int status) int testbit = ((1 << i) & ~mask_bits); if (jack->type & testbit) - input_report_switch(jack->input_dev, + input_report_switch(idev, jack_switch_types[i], status & testbit); } - input_sync(jack->input_dev); + input_sync(idev); + input_put_device(idev); #endif /* CONFIG_SND_JACK_INPUT_DEV */ } EXPORT_SYMBOL(snd_jack_report); diff --git a/sound/pci/ac97/ac97_codec.c b/sound/pci/ac97/ac97_codec.c index ceead55f13ab..58ae0c3ce1e4 100644 --- a/sound/pci/ac97/ac97_codec.c +++ b/sound/pci/ac97/ac97_codec.c @@ -2070,8 +2070,8 @@ int snd_ac97_mixer(struct snd_ac97_bus *bus, struct snd_ac97_template *template, .dev_disconnect = snd_ac97_dev_disconnect, }; - if (rac97) - *rac97 = NULL; + if (!rac97) + return -EINVAL; if (snd_BUG_ON(!bus || !template)) return -EINVAL; if (snd_BUG_ON(template->num >= 4)) diff --git a/sound/pci/emu10k1/emufx.c b/sound/pci/emu10k1/emufx.c index 6cf7c8b1de47..4ca65f425f39 100644 --- a/sound/pci/emu10k1/emufx.c +++ b/sound/pci/emu10k1/emufx.c @@ -1563,14 +1563,8 @@ A_OP(icode, &ptr, iMAC0, A_GPR(var), A_GPR(var), A_GPR(vol), A_EXTIN(input)) gpr += 2; /* Master volume (will be renamed later) */ - A_OP(icode, &ptr, iMAC0, A_GPR(playback+0+SND_EMU10K1_PLAYBACK_CHANNELS), A_C_00000000, A_GPR(gpr), A_GPR(playback+0+SND_EMU10K1_PLAYBACK_CHANNELS)); - A_OP(icode, &ptr, iMAC0, A_GPR(playback+1+SND_EMU10K1_PLAYBACK_CHANNELS), A_C_00000000, A_GPR(gpr), A_GPR(playback+1+SND_EMU10K1_PLAYBACK_CHANNELS)); - A_OP(icode, &ptr, iMAC0, A_GPR(playback+2+SND_EMU10K1_PLAYBACK_CHANNELS), A_C_00000000, A_GPR(gpr), A_GPR(playback+2+SND_EMU10K1_PLAYBACK_CHANNELS)); - A_OP(icode, &ptr, iMAC0, A_GPR(playback+3+SND_EMU10K1_PLAYBACK_CHANNELS), A_C_00000000, A_GPR(gpr), A_GPR(playback+3+SND_EMU10K1_PLAYBACK_CHANNELS)); - A_OP(icode, &ptr, iMAC0, A_GPR(playback+4+SND_EMU10K1_PLAYBACK_CHANNELS), A_C_00000000, A_GPR(gpr), A_GPR(playback+4+SND_EMU10K1_PLAYBACK_CHANNELS)); - A_OP(icode, &ptr, iMAC0, A_GPR(playback+5+SND_EMU10K1_PLAYBACK_CHANNELS), A_C_00000000, A_GPR(gpr), A_GPR(playback+5+SND_EMU10K1_PLAYBACK_CHANNELS)); - A_OP(icode, &ptr, iMAC0, A_GPR(playback+6+SND_EMU10K1_PLAYBACK_CHANNELS), A_C_00000000, A_GPR(gpr), A_GPR(playback+6+SND_EMU10K1_PLAYBACK_CHANNELS)); - A_OP(icode, &ptr, iMAC0, A_GPR(playback+7+SND_EMU10K1_PLAYBACK_CHANNELS), A_C_00000000, A_GPR(gpr), A_GPR(playback+7+SND_EMU10K1_PLAYBACK_CHANNELS)); + for (z = 0; z < 8; z++) + A_OP(icode, &ptr, iMAC0, A_GPR(playback+z+SND_EMU10K1_PLAYBACK_CHANNELS), A_C_00000000, A_GPR(gpr), A_GPR(playback+z+SND_EMU10K1_PLAYBACK_CHANNELS)); snd_emu10k1_init_mono_control(&controls[nctl++], "Wave Master Playback Volume", gpr, 0); gpr += 2; @@ -1654,102 +1648,14 @@ A_OP(icode, &ptr, iMAC0, A_GPR(var), A_GPR(var), A_GPR(vol), A_EXTIN(input)) dev_dbg(emu->card->dev, "emufx.c: gpr=0x%x, tmp=0x%x\n", gpr, tmp); */ - /* For the EMU1010: How to get 32bit values from the DSP. High 16bits into L, low 16bits into R. */ - /* A_P16VIN(0) is delayed by one sample, - * so all other A_P16VIN channels will need to also be delayed - */ - /* Left ADC in. 1 of 2 */ snd_emu10k1_audigy_dsp_convert_32_to_2x16( icode, &ptr, tmp, bit_shifter16, A_P16VIN(0x0), A_FXBUS2(0) ); - /* Right ADC in 1 of 2 */ - gpr_map[gpr++] = 0x00000000; - /* Delaying by one sample: instead of copying the input - * value A_P16VIN to output A_FXBUS2 as in the first channel, - * we use an auxiliary register, delaying the value by one - * sample - */ - snd_emu10k1_audigy_dsp_convert_32_to_2x16( icode, &ptr, tmp, bit_shifter16, A_GPR(gpr - 1), A_FXBUS2(2) ); - A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0x1), A_C_00000000, A_C_00000000); - gpr_map[gpr++] = 0x00000000; - snd_emu10k1_audigy_dsp_convert_32_to_2x16( icode, &ptr, tmp, bit_shifter16, A_GPR(gpr - 1), A_FXBUS2(4) ); - A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0x2), A_C_00000000, A_C_00000000); - gpr_map[gpr++] = 0x00000000; - snd_emu10k1_audigy_dsp_convert_32_to_2x16( icode, &ptr, tmp, bit_shifter16, A_GPR(gpr - 1), A_FXBUS2(6) ); - A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0x3), A_C_00000000, A_C_00000000); - /* For 96kHz mode */ - /* Left ADC in. 2 of 2 */ - gpr_map[gpr++] = 0x00000000; - snd_emu10k1_audigy_dsp_convert_32_to_2x16( icode, &ptr, tmp, bit_shifter16, A_GPR(gpr - 1), A_FXBUS2(0x8) ); - A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0x4), A_C_00000000, A_C_00000000); - /* Right ADC in 2 of 2 */ - gpr_map[gpr++] = 0x00000000; - snd_emu10k1_audigy_dsp_convert_32_to_2x16( icode, &ptr, tmp, bit_shifter16, A_GPR(gpr - 1), A_FXBUS2(0xa) ); - A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0x5), A_C_00000000, A_C_00000000); - gpr_map[gpr++] = 0x00000000; - snd_emu10k1_audigy_dsp_convert_32_to_2x16( icode, &ptr, tmp, bit_shifter16, A_GPR(gpr - 1), A_FXBUS2(0xc) ); - A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0x6), A_C_00000000, A_C_00000000); - gpr_map[gpr++] = 0x00000000; - snd_emu10k1_audigy_dsp_convert_32_to_2x16( icode, &ptr, tmp, bit_shifter16, A_GPR(gpr - 1), A_FXBUS2(0xe) ); - A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0x7), A_C_00000000, A_C_00000000); - /* Pavel Hofman - we still have voices, A_FXBUS2s, and - * A_P16VINs available - - * let's add 8 more capture channels - total of 16 - */ - gpr_map[gpr++] = 0x00000000; - snd_emu10k1_audigy_dsp_convert_32_to_2x16(icode, &ptr, tmp, - bit_shifter16, - A_GPR(gpr - 1), - A_FXBUS2(0x10)); - A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0x8), - A_C_00000000, A_C_00000000); - gpr_map[gpr++] = 0x00000000; - snd_emu10k1_audigy_dsp_convert_32_to_2x16(icode, &ptr, tmp, - bit_shifter16, - A_GPR(gpr - 1), - A_FXBUS2(0x12)); - A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0x9), - A_C_00000000, A_C_00000000); - gpr_map[gpr++] = 0x00000000; - snd_emu10k1_audigy_dsp_convert_32_to_2x16(icode, &ptr, tmp, - bit_shifter16, - A_GPR(gpr - 1), - A_FXBUS2(0x14)); - A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0xa), - A_C_00000000, A_C_00000000); - gpr_map[gpr++] = 0x00000000; - snd_emu10k1_audigy_dsp_convert_32_to_2x16(icode, &ptr, tmp, - bit_shifter16, - A_GPR(gpr - 1), - A_FXBUS2(0x16)); - A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0xb), - A_C_00000000, A_C_00000000); - gpr_map[gpr++] = 0x00000000; - snd_emu10k1_audigy_dsp_convert_32_to_2x16(icode, &ptr, tmp, - bit_shifter16, - A_GPR(gpr - 1), - A_FXBUS2(0x18)); - A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0xc), - A_C_00000000, A_C_00000000); - gpr_map[gpr++] = 0x00000000; - snd_emu10k1_audigy_dsp_convert_32_to_2x16(icode, &ptr, tmp, - bit_shifter16, - A_GPR(gpr - 1), - A_FXBUS2(0x1a)); - A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0xd), - A_C_00000000, A_C_00000000); - gpr_map[gpr++] = 0x00000000; - snd_emu10k1_audigy_dsp_convert_32_to_2x16(icode, &ptr, tmp, - bit_shifter16, - A_GPR(gpr - 1), - A_FXBUS2(0x1c)); - A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0xe), - A_C_00000000, A_C_00000000); - gpr_map[gpr++] = 0x00000000; - snd_emu10k1_audigy_dsp_convert_32_to_2x16(icode, &ptr, tmp, - bit_shifter16, - A_GPR(gpr - 1), - A_FXBUS2(0x1e)); - A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0xf), - A_C_00000000, A_C_00000000); + /* A_P16VIN(0) is delayed by one sample, so all other A_P16VIN channels + * will need to also be delayed; we use an auxiliary register for that. */ + for (z = 1; z < 0x10; z++) { + snd_emu10k1_audigy_dsp_convert_32_to_2x16( icode, &ptr, tmp, bit_shifter16, A_GPR(gpr), A_FXBUS2(z * 2) ); + A_OP(icode, &ptr, iACC3, A_GPR(gpr), A_P16VIN(z), A_C_00000000, A_C_00000000); + gpr_map[gpr++] = 0x00000000; + } } #if 0 diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 22f0d1b359f0..0bc3f3f1b8a7 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -120,6 +120,7 @@ struct alc_spec { unsigned int ultra_low_power:1; unsigned int has_hs_key:1; unsigned int no_internal_mic_pin:1; + unsigned int en_3kpull_low:1; /* for PLL fix */ hda_nid_t pll_nid; @@ -3616,6 +3617,7 @@ static void alc256_shutup(struct hda_codec *codec) if (!hp_pin) hp_pin = 0x21; + alc_update_coefex_idx(codec, 0x57, 0x04, 0x0007, 0x1); /* Low power */ hp_pin_sense = snd_hda_jack_detect(codec, hp_pin); if (hp_pin_sense) @@ -3632,8 +3634,7 @@ static void alc256_shutup(struct hda_codec *codec) /* If disable 3k pulldown control for alc257, the Mic detection will not work correctly * when booting with headset plugged. So skip setting it for the codec alc257 */ - if (codec->core.vendor_id != 0x10ec0236 && - codec->core.vendor_id != 0x10ec0257) + if (spec->en_3kpull_low) alc_update_coef_idx(codec, 0x46, 0, 3 << 12); if (!spec->no_shutup_pins) @@ -4616,6 +4617,21 @@ static void alc236_fixup_hp_mute_led_coefbit(struct hda_codec *codec, } } +static void alc236_fixup_hp_mute_led_coefbit2(struct hda_codec *codec, + const struct hda_fixup *fix, int action) +{ + struct alc_spec *spec = codec->spec; + + if (action == HDA_FIXUP_ACT_PRE_PROBE) { + spec->mute_led_polarity = 0; + spec->mute_led_coef.idx = 0x07; + spec->mute_led_coef.mask = 1; + spec->mute_led_coef.on = 1; + spec->mute_led_coef.off = 0; + snd_hda_gen_add_mute_led_cdev(codec, coef_mute_led_set); + } +} + /* turn on/off mic-mute LED per capture hook by coef bit */ static int coef_micmute_led_set(struct led_classdev *led_cdev, enum led_brightness brightness) @@ -6934,6 +6950,7 @@ enum { ALC285_FIXUP_HP_GPIO_LED, ALC285_FIXUP_HP_MUTE_LED, ALC285_FIXUP_HP_SPECTRE_X360_MUTE_LED, + ALC236_FIXUP_HP_MUTE_LED_COEFBIT2, ALC236_FIXUP_HP_GPIO_LED, ALC236_FIXUP_HP_MUTE_LED, ALC236_FIXUP_HP_MUTE_LED_MICMUTE_VREF, @@ -8307,6 +8324,10 @@ static const struct hda_fixup alc269_fixups[] = { .type = HDA_FIXUP_FUNC, .v.func = alc285_fixup_hp_spectre_x360_mute_led, }, + [ALC236_FIXUP_HP_MUTE_LED_COEFBIT2] = { + .type = HDA_FIXUP_FUNC, + .v.func = alc236_fixup_hp_mute_led_coefbit2, + }, [ALC236_FIXUP_HP_GPIO_LED] = { .type = HDA_FIXUP_FUNC, .v.func = alc236_fixup_hp_gpio_led, @@ -9067,6 +9088,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { SND_PCI_QUIRK(0x103c, 0x886d, "HP ZBook Fury 17.3 Inch G8 Mobile Workstation PC", ALC285_FIXUP_HP_GPIO_AMP_INIT), SND_PCI_QUIRK(0x103c, 0x8870, "HP ZBook Fury 15.6 Inch G8 Mobile Workstation PC", ALC285_FIXUP_HP_GPIO_AMP_INIT), SND_PCI_QUIRK(0x103c, 0x8873, "HP ZBook Studio 15.6 Inch G8 Mobile Workstation PC", ALC285_FIXUP_HP_GPIO_AMP_INIT), + SND_PCI_QUIRK(0x103c, 0x887a, "HP Laptop 15s-eq2xxx", ALC236_FIXUP_HP_MUTE_LED_COEFBIT2), SND_PCI_QUIRK(0x103c, 0x888d, "HP ZBook Power 15.6 inch G8 Mobile Workstation PC", ALC236_FIXUP_HP_GPIO_LED), SND_PCI_QUIRK(0x103c, 0x8895, "HP EliteBook 855 G8 Notebook PC", ALC285_FIXUP_HP_SPEAKERS_MICMUTE_LED), SND_PCI_QUIRK(0x103c, 0x8896, "HP EliteBook 855 G8 Notebook PC", ALC285_FIXUP_HP_MUTE_LED), @@ -9206,6 +9228,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { SND_PCI_QUIRK(0x1558, 0x5157, "Clevo W517GU1", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE), SND_PCI_QUIRK(0x1558, 0x51a1, "Clevo NS50MU", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE), SND_PCI_QUIRK(0x1558, 0x51b1, "Clevo NS50AU", ALC256_FIXUP_SYSTEM76_MIC_NO_PRESENCE), + SND_PCI_QUIRK(0x1558, 0x51b3, "Clevo NS70AU", ALC256_FIXUP_SYSTEM76_MIC_NO_PRESENCE), SND_PCI_QUIRK(0x1558, 0x5630, "Clevo NP50RNJS", ALC256_FIXUP_SYSTEM76_MIC_NO_PRESENCE), SND_PCI_QUIRK(0x1558, 0x70a1, "Clevo NB70T[HJK]", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE), SND_PCI_QUIRK(0x1558, 0x70b3, "Clevo NK70SB", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE), @@ -9242,6 +9265,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { SND_PCI_QUIRK(0x1558, 0x971d, "Clevo N970T[CDF]", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE), SND_PCI_QUIRK(0x1558, 0xa500, "Clevo NL5[03]RU", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE), SND_PCI_QUIRK(0x1558, 0xa600, "Clevo NL50NU", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE), + SND_PCI_QUIRK(0x1558, 0xa650, "Clevo NP[567]0SN[CD]", ALC256_FIXUP_SYSTEM76_MIC_NO_PRESENCE), SND_PCI_QUIRK(0x1558, 0xa671, "Clevo NP70SN[CDE]", ALC256_FIXUP_SYSTEM76_MIC_NO_PRESENCE), SND_PCI_QUIRK(0x1558, 0xb018, "Clevo NP50D[BE]", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE), SND_PCI_QUIRK(0x1558, 0xb019, "Clevo NH77D[BE]Q", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE), @@ -10145,6 +10169,8 @@ static int patch_alc269(struct hda_codec *codec) spec->shutup = alc256_shutup; spec->init_hook = alc256_init; spec->gen.mixer_nid = 0; /* ALC256 does not have any loopback mixer path */ + if (codec->bus->pci->vendor == PCI_VENDOR_ID_AMD) + spec->en_3kpull_low = true; break; case 0x10ec0257: spec->codec_variant = ALC269_TYPE_ALC257; diff --git a/sound/soc/codecs/es8316.c b/sound/soc/codecs/es8316.c index afd6d401e3d0..b36ccfc54cd6 100644 --- a/sound/soc/codecs/es8316.c +++ b/sound/soc/codecs/es8316.c @@ -52,7 +52,12 @@ static const SNDRV_CTL_TLVD_DECLARE_DB_SCALE(dac_vol_tlv, -9600, 50, 1); static const SNDRV_CTL_TLVD_DECLARE_DB_SCALE(adc_vol_tlv, -9600, 50, 1); static const SNDRV_CTL_TLVD_DECLARE_DB_SCALE(alc_max_gain_tlv, -650, 150, 0); static const SNDRV_CTL_TLVD_DECLARE_DB_SCALE(alc_min_gain_tlv, -1200, 150, 0); -static const SNDRV_CTL_TLVD_DECLARE_DB_SCALE(alc_target_tlv, -1650, 150, 0); + +static const SNDRV_CTL_TLVD_DECLARE_DB_RANGE(alc_target_tlv, + 0, 10, TLV_DB_SCALE_ITEM(-1650, 150, 0), + 11, 11, TLV_DB_SCALE_ITEM(-150, 0, 0), +); + static const SNDRV_CTL_TLVD_DECLARE_DB_RANGE(hpmixer_gain_tlv, 0, 4, TLV_DB_SCALE_ITEM(-1200, 150, 0), 8, 11, TLV_DB_SCALE_ITEM(-450, 150, 0), @@ -115,7 +120,7 @@ static const struct snd_kcontrol_new es8316_snd_controls[] = { alc_max_gain_tlv), SOC_SINGLE_TLV("ALC Capture Min Volume", ES8316_ADC_ALC2, 0, 28, 0, alc_min_gain_tlv), - SOC_SINGLE_TLV("ALC Capture Target Volume", ES8316_ADC_ALC3, 4, 10, 0, + SOC_SINGLE_TLV("ALC Capture Target Volume", ES8316_ADC_ALC3, 4, 11, 0, alc_target_tlv), SOC_SINGLE("ALC Capture Hold Time", ES8316_ADC_ALC3, 0, 10, 0), SOC_SINGLE("ALC Capture Decay Time", ES8316_ADC_ALC4, 4, 10, 0), @@ -364,13 +369,11 @@ static int es8316_set_dai_sysclk(struct snd_soc_dai *codec_dai, int count = 0; es8316->sysclk = freq; + es8316->sysclk_constraints.list = NULL; + es8316->sysclk_constraints.count = 0; - if (freq == 0) { - es8316->sysclk_constraints.list = NULL; - es8316->sysclk_constraints.count = 0; - + if (freq == 0) return 0; - } ret = clk_set_rate(es8316->mclk, freq); if (ret) @@ -386,8 +389,10 @@ static int es8316_set_dai_sysclk(struct snd_soc_dai *codec_dai, es8316->allowed_rates[count++] = freq / ratio; } - es8316->sysclk_constraints.list = es8316->allowed_rates; - es8316->sysclk_constraints.count = count; + if (count) { + es8316->sysclk_constraints.list = es8316->allowed_rates; + es8316->sysclk_constraints.count = count; + } return 0; } diff --git a/sound/soc/codecs/wcd-mbhc-v2.c b/sound/soc/codecs/wcd-mbhc-v2.c index 405128ccb4b0..26f26f442d7c 100644 --- a/sound/soc/codecs/wcd-mbhc-v2.c +++ b/sound/soc/codecs/wcd-mbhc-v2.c @@ -1370,7 +1370,7 @@ struct wcd_mbhc *wcd_mbhc_init(struct snd_soc_component *component, return ERR_PTR(-EINVAL); } - mbhc = devm_kzalloc(dev, sizeof(*mbhc), GFP_KERNEL); + mbhc = kzalloc(sizeof(*mbhc), GFP_KERNEL); if (!mbhc) return ERR_PTR(-ENOMEM); @@ -1390,61 +1390,76 @@ struct wcd_mbhc *wcd_mbhc_init(struct snd_soc_component *component, INIT_WORK(&mbhc->correct_plug_swch, wcd_correct_swch_plug); - ret = devm_request_threaded_irq(dev, mbhc->intr_ids->mbhc_sw_intr, NULL, + ret = request_threaded_irq(mbhc->intr_ids->mbhc_sw_intr, NULL, wcd_mbhc_mech_plug_detect_irq, IRQF_ONESHOT | IRQF_TRIGGER_RISING, "mbhc sw intr", mbhc); if (ret) - goto err; + goto err_free_mbhc; - ret = devm_request_threaded_irq(dev, mbhc->intr_ids->mbhc_btn_press_intr, NULL, + ret = request_threaded_irq(mbhc->intr_ids->mbhc_btn_press_intr, NULL, wcd_mbhc_btn_press_handler, IRQF_ONESHOT | IRQF_TRIGGER_RISING, "Button Press detect", mbhc); if (ret) - goto err; + goto err_free_sw_intr; - ret = devm_request_threaded_irq(dev, mbhc->intr_ids->mbhc_btn_release_intr, NULL, + ret = request_threaded_irq(mbhc->intr_ids->mbhc_btn_release_intr, NULL, wcd_mbhc_btn_release_handler, IRQF_ONESHOT | IRQF_TRIGGER_RISING, "Button Release detect", mbhc); if (ret) - goto err; + goto err_free_btn_press_intr; - ret = devm_request_threaded_irq(dev, mbhc->intr_ids->mbhc_hs_ins_intr, NULL, + ret = request_threaded_irq(mbhc->intr_ids->mbhc_hs_ins_intr, NULL, wcd_mbhc_adc_hs_ins_irq, IRQF_ONESHOT | IRQF_TRIGGER_RISING, "Elect Insert", mbhc); if (ret) - goto err; + goto err_free_btn_release_intr; disable_irq_nosync(mbhc->intr_ids->mbhc_hs_ins_intr); - ret = devm_request_threaded_irq(dev, mbhc->intr_ids->mbhc_hs_rem_intr, NULL, + ret = request_threaded_irq(mbhc->intr_ids->mbhc_hs_rem_intr, NULL, wcd_mbhc_adc_hs_rem_irq, IRQF_ONESHOT | IRQF_TRIGGER_RISING, "Elect Remove", mbhc); if (ret) - goto err; + goto err_free_hs_ins_intr; disable_irq_nosync(mbhc->intr_ids->mbhc_hs_rem_intr); - ret = devm_request_threaded_irq(dev, mbhc->intr_ids->hph_left_ocp, NULL, + ret = request_threaded_irq(mbhc->intr_ids->hph_left_ocp, NULL, wcd_mbhc_hphl_ocp_irq, IRQF_ONESHOT | IRQF_TRIGGER_RISING, "HPH_L OCP detect", mbhc); if (ret) - goto err; + goto err_free_hs_rem_intr; - ret = devm_request_threaded_irq(dev, mbhc->intr_ids->hph_right_ocp, NULL, + ret = request_threaded_irq(mbhc->intr_ids->hph_right_ocp, NULL, wcd_mbhc_hphr_ocp_irq, IRQF_ONESHOT | IRQF_TRIGGER_RISING, "HPH_R OCP detect", mbhc); if (ret) - goto err; + goto err_free_hph_left_ocp; return mbhc; -err: + +err_free_hph_left_ocp: + free_irq(mbhc->intr_ids->hph_left_ocp, mbhc); +err_free_hs_rem_intr: + free_irq(mbhc->intr_ids->mbhc_hs_rem_intr, mbhc); +err_free_hs_ins_intr: + free_irq(mbhc->intr_ids->mbhc_hs_ins_intr, mbhc); +err_free_btn_release_intr: + free_irq(mbhc->intr_ids->mbhc_btn_release_intr, mbhc); +err_free_btn_press_intr: + free_irq(mbhc->intr_ids->mbhc_btn_press_intr, mbhc); +err_free_sw_intr: + free_irq(mbhc->intr_ids->mbhc_sw_intr, mbhc); +err_free_mbhc: + kfree(mbhc); + dev_err(dev, "Failed to request mbhc interrupts %d\n", ret); return ERR_PTR(ret); @@ -1453,9 +1468,19 @@ EXPORT_SYMBOL(wcd_mbhc_init); void wcd_mbhc_deinit(struct wcd_mbhc *mbhc) { + free_irq(mbhc->intr_ids->hph_right_ocp, mbhc); + free_irq(mbhc->intr_ids->hph_left_ocp, mbhc); + free_irq(mbhc->intr_ids->mbhc_hs_rem_intr, mbhc); + free_irq(mbhc->intr_ids->mbhc_hs_ins_intr, mbhc); + free_irq(mbhc->intr_ids->mbhc_btn_release_intr, mbhc); + free_irq(mbhc->intr_ids->mbhc_btn_press_intr, mbhc); + free_irq(mbhc->intr_ids->mbhc_sw_intr, mbhc); + mutex_lock(&mbhc->lock); wcd_cancel_hs_detect_plug(mbhc, &mbhc->correct_plug_swch); mutex_unlock(&mbhc->lock); + + kfree(mbhc); } EXPORT_SYMBOL(wcd_mbhc_deinit); diff --git a/sound/soc/codecs/wcd934x.c b/sound/soc/codecs/wcd934x.c index 4ca52d9db23a..94ffd2ba29ae 100644 --- a/sound/soc/codecs/wcd934x.c +++ b/sound/soc/codecs/wcd934x.c @@ -3044,6 +3044,17 @@ static int wcd934x_mbhc_init(struct snd_soc_component *component) return 0; } + +static void wcd934x_mbhc_deinit(struct snd_soc_component *component) +{ + struct wcd934x_codec *wcd = snd_soc_component_get_drvdata(component); + + if (!wcd->mbhc) + return; + + wcd_mbhc_deinit(wcd->mbhc); +} + static int wcd934x_comp_probe(struct snd_soc_component *component) { struct wcd934x_codec *wcd = dev_get_drvdata(component->dev); @@ -3077,6 +3088,7 @@ static void wcd934x_comp_remove(struct snd_soc_component *comp) { struct wcd934x_codec *wcd = dev_get_drvdata(comp->dev); + wcd934x_mbhc_deinit(comp); wcd_clsh_ctrl_free(wcd->clsh_ctrl); } diff --git a/sound/soc/codecs/wcd938x.c b/sound/soc/codecs/wcd938x.c index 8cdc45e669f2..99b4c804fd50 100644 --- a/sound/soc/codecs/wcd938x.c +++ b/sound/soc/codecs/wcd938x.c @@ -3621,6 +3621,8 @@ static int wcd938x_mbhc_init(struct snd_soc_component *component) WCD938X_IRQ_HPHR_OCP_INT); wcd938x->wcd_mbhc = wcd_mbhc_init(component, &mbhc_cb, intr_ids, wcd_mbhc_fields, true); + if (IS_ERR(wcd938x->wcd_mbhc)) + return PTR_ERR(wcd938x->wcd_mbhc); snd_soc_add_component_controls(component, impedance_detect_controls, ARRAY_SIZE(impedance_detect_controls)); @@ -3629,6 +3631,14 @@ static int wcd938x_mbhc_init(struct snd_soc_component *component) return 0; } + +static void wcd938x_mbhc_deinit(struct snd_soc_component *component) +{ + struct wcd938x_priv *wcd938x = snd_soc_component_get_drvdata(component); + + wcd_mbhc_deinit(wcd938x->wcd_mbhc); +} + /* END MBHC */ static const struct snd_kcontrol_new wcd938x_snd_controls[] = { @@ -4076,16 +4086,33 @@ static int wcd938x_irq_init(struct wcd938x_priv *wcd, struct device *dev) static int wcd938x_soc_codec_probe(struct snd_soc_component *component) { struct wcd938x_priv *wcd938x = snd_soc_component_get_drvdata(component); + struct sdw_slave *tx_sdw_dev = wcd938x->tx_sdw_dev; struct device *dev = component->dev; + unsigned long time_left; int ret, i; + time_left = wait_for_completion_timeout(&tx_sdw_dev->initialization_complete, + msecs_to_jiffies(2000)); + if (!time_left) { + dev_err(dev, "soundwire device init timeout\n"); + return -ETIMEDOUT; + } + snd_soc_component_init_regmap(component, wcd938x->regmap); + ret = pm_runtime_resume_and_get(dev); + if (ret < 0) + return ret; + wcd938x->variant = snd_soc_component_read_field(component, WCD938X_DIGITAL_EFUSE_REG_0, WCD938X_ID_MASK); wcd938x->clsh_info = wcd_clsh_ctrl_alloc(component, WCD938X); + if (IS_ERR(wcd938x->clsh_info)) { + pm_runtime_put(dev); + return PTR_ERR(wcd938x->clsh_info); + } wcd938x_io_init(wcd938x); /* Set all interrupts as edge triggered */ @@ -4094,6 +4121,8 @@ static int wcd938x_soc_codec_probe(struct snd_soc_component *component) (WCD938X_DIGITAL_INTR_LEVEL_0 + i), 0); } + pm_runtime_put(dev); + wcd938x->hphr_pdm_wd_int = regmap_irq_get_virq(wcd938x->irq_chip, WCD938X_IRQ_HPHR_PDM_WD_INT); wcd938x->hphl_pdm_wd_int = regmap_irq_get_virq(wcd938x->irq_chip, @@ -4105,20 +4134,26 @@ static int wcd938x_soc_codec_probe(struct snd_soc_component *component) ret = request_threaded_irq(wcd938x->hphr_pdm_wd_int, NULL, wcd938x_wd_handle_irq, IRQF_ONESHOT | IRQF_TRIGGER_RISING, "HPHR PDM WD INT", wcd938x); - if (ret) + if (ret) { dev_err(dev, "Failed to request HPHR WD interrupt (%d)\n", ret); + goto err_free_clsh_ctrl; + } ret = request_threaded_irq(wcd938x->hphl_pdm_wd_int, NULL, wcd938x_wd_handle_irq, IRQF_ONESHOT | IRQF_TRIGGER_RISING, "HPHL PDM WD INT", wcd938x); - if (ret) + if (ret) { dev_err(dev, "Failed to request HPHL WD interrupt (%d)\n", ret); + goto err_free_hphr_pdm_wd_int; + } ret = request_threaded_irq(wcd938x->aux_pdm_wd_int, NULL, wcd938x_wd_handle_irq, IRQF_ONESHOT | IRQF_TRIGGER_RISING, "AUX PDM WD INT", wcd938x); - if (ret) + if (ret) { dev_err(dev, "Failed to request Aux WD interrupt (%d)\n", ret); + goto err_free_hphl_pdm_wd_int; + } /* Disable watchdog interrupt for HPH and AUX */ disable_irq_nosync(wcd938x->hphr_pdm_wd_int); @@ -4133,7 +4168,7 @@ static int wcd938x_soc_codec_probe(struct snd_soc_component *component) dev_err(component->dev, "%s: Failed to add snd ctrls for variant: %d\n", __func__, wcd938x->variant); - goto err; + goto err_free_aux_pdm_wd_int; } break; case WCD9385: @@ -4143,7 +4178,7 @@ static int wcd938x_soc_codec_probe(struct snd_soc_component *component) dev_err(component->dev, "%s: Failed to add snd ctrls for variant: %d\n", __func__, wcd938x->variant); - goto err; + goto err_free_aux_pdm_wd_int; } break; default: @@ -4151,12 +4186,38 @@ static int wcd938x_soc_codec_probe(struct snd_soc_component *component) } ret = wcd938x_mbhc_init(component); - if (ret) + if (ret) { dev_err(component->dev, "mbhc initialization failed\n"); -err: + goto err_free_aux_pdm_wd_int; + } + + return 0; + +err_free_aux_pdm_wd_int: + free_irq(wcd938x->aux_pdm_wd_int, wcd938x); +err_free_hphl_pdm_wd_int: + free_irq(wcd938x->hphl_pdm_wd_int, wcd938x); +err_free_hphr_pdm_wd_int: + free_irq(wcd938x->hphr_pdm_wd_int, wcd938x); +err_free_clsh_ctrl: + wcd_clsh_ctrl_free(wcd938x->clsh_info); + return ret; } +static void wcd938x_soc_codec_remove(struct snd_soc_component *component) +{ + struct wcd938x_priv *wcd938x = snd_soc_component_get_drvdata(component); + + wcd938x_mbhc_deinit(component); + + free_irq(wcd938x->aux_pdm_wd_int, wcd938x); + free_irq(wcd938x->hphl_pdm_wd_int, wcd938x); + free_irq(wcd938x->hphr_pdm_wd_int, wcd938x); + + wcd_clsh_ctrl_free(wcd938x->clsh_info); +} + static int wcd938x_codec_set_jack(struct snd_soc_component *comp, struct snd_soc_jack *jack, void *data) { @@ -4173,6 +4234,7 @@ static int wcd938x_codec_set_jack(struct snd_soc_component *comp, static const struct snd_soc_component_driver soc_codec_dev_wcd938x = { .name = "wcd938x_codec", .probe = wcd938x_soc_codec_probe, + .remove = wcd938x_soc_codec_remove, .controls = wcd938x_snd_controls, .num_controls = ARRAY_SIZE(wcd938x_snd_controls), .dapm_widgets = wcd938x_dapm_widgets, diff --git a/sound/soc/fsl/fsl_sai.c b/sound/soc/fsl/fsl_sai.c index 6a12cbd43084..59dffa5ff34f 100644 --- a/sound/soc/fsl/fsl_sai.c +++ b/sound/soc/fsl/fsl_sai.c @@ -560,7 +560,7 @@ static void fsl_sai_config_disable(struct fsl_sai *sai, int dir) u32 xcsr, count = 100; regmap_update_bits(sai->regmap, FSL_SAI_xCSR(tx, ofs), - FSL_SAI_CSR_TERE, 0); + FSL_SAI_CSR_TERE | FSL_SAI_CSR_BCE, 0); /* TERE will remain set till the end of current frame */ do { diff --git a/sound/soc/fsl/fsl_sai.h b/sound/soc/fsl/fsl_sai.h index 93da86009c75..f8c9a8fb7898 100644 --- a/sound/soc/fsl/fsl_sai.h +++ b/sound/soc/fsl/fsl_sai.h @@ -87,6 +87,7 @@ /* SAI Transmit/Receive Control Register */ #define FSL_SAI_CSR_TERE BIT(31) #define FSL_SAI_CSR_SE BIT(30) +#define FSL_SAI_CSR_BCE BIT(28) #define FSL_SAI_CSR_FR BIT(25) #define FSL_SAI_CSR_SR BIT(24) #define FSL_SAI_CSR_xF_SHIFT 16 diff --git a/sound/soc/fsl/imx-audmix.c b/sound/soc/fsl/imx-audmix.c index a364e2415de0..d991e457060c 100644 --- a/sound/soc/fsl/imx-audmix.c +++ b/sound/soc/fsl/imx-audmix.c @@ -228,6 +228,8 @@ static int imx_audmix_probe(struct platform_device *pdev) dai_name = devm_kasprintf(&pdev->dev, GFP_KERNEL, "%s%s", fe_name_pref, args.np->full_name + 1); + if (!dai_name) + return -ENOMEM; dev_info(pdev->dev.parent, "DAI FE name:%s\n", dai_name); @@ -236,6 +238,8 @@ static int imx_audmix_probe(struct platform_device *pdev) capture_dai_name = devm_kasprintf(&pdev->dev, GFP_KERNEL, "%s %s", dai_name, "CPU-Capture"); + if (!capture_dai_name) + return -ENOMEM; } priv->dai[i].cpus = &dlc[0]; @@ -266,6 +270,8 @@ static int imx_audmix_probe(struct platform_device *pdev) "AUDMIX-Playback-%d", i); be_cp = devm_kasprintf(&pdev->dev, GFP_KERNEL, "AUDMIX-Capture-%d", i); + if (!be_name || !be_pb || !be_cp) + return -ENOMEM; priv->dai[num_dai + i].cpus = &dlc[3]; priv->dai[num_dai + i].codecs = &dlc[4]; @@ -293,6 +299,9 @@ static int imx_audmix_probe(struct platform_device *pdev) priv->dapm_routes[i].source = devm_kasprintf(&pdev->dev, GFP_KERNEL, "%s %s", dai_name, "CPU-Playback"); + if (!priv->dapm_routes[i].source) + return -ENOMEM; + priv->dapm_routes[i].sink = be_pb; priv->dapm_routes[num_dai + i].source = be_pb; priv->dapm_routes[num_dai + i].sink = be_cp; diff --git a/sound/soc/mediatek/mt8173/mt8173-afe-pcm.c b/sound/soc/mediatek/mt8173/mt8173-afe-pcm.c index 8092506facbd..b8b5038d1be1 100644 --- a/sound/soc/mediatek/mt8173/mt8173-afe-pcm.c +++ b/sound/soc/mediatek/mt8173/mt8173-afe-pcm.c @@ -1072,6 +1072,10 @@ static int mt8173_afe_pcm_dev_probe(struct platform_device *pdev) afe->dev = &pdev->dev; + irq_id = platform_get_irq(pdev, 0); + if (irq_id <= 0) + return irq_id < 0 ? irq_id : -ENXIO; + afe->base_addr = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(afe->base_addr)) return PTR_ERR(afe->base_addr); @@ -1158,14 +1162,14 @@ static int mt8173_afe_pcm_dev_probe(struct platform_device *pdev) comp_hdmi = devm_kzalloc(&pdev->dev, sizeof(*comp_hdmi), GFP_KERNEL); if (!comp_hdmi) { ret = -ENOMEM; - goto err_pm_disable; + goto err_cleanup_components; } ret = snd_soc_component_initialize(comp_hdmi, &mt8173_afe_hdmi_dai_component, &pdev->dev); if (ret) - goto err_pm_disable; + goto err_cleanup_components; #ifdef CONFIG_DEBUG_FS comp_hdmi->debugfs_prefix = "hdmi"; @@ -1177,14 +1181,11 @@ static int mt8173_afe_pcm_dev_probe(struct platform_device *pdev) if (ret) goto err_cleanup_components; - irq_id = platform_get_irq(pdev, 0); - if (irq_id <= 0) - return irq_id < 0 ? irq_id : -ENXIO; ret = devm_request_irq(afe->dev, irq_id, mt8173_afe_irq_handler, 0, "Afe_ISR_Handle", (void *)afe); if (ret) { dev_err(afe->dev, "could not request_irq\n"); - goto err_pm_disable; + goto err_cleanup_components; } dev_info(&pdev->dev, "MT8173 AFE driver initialized.\n"); diff --git a/sound/usb/usb_audio_qmi_svc.c b/sound/usb/usb_audio_qmi_svc.c index 7185fee986e9..67cadca67e7b 100644 --- a/sound/usb/usb_audio_qmi_svc.c +++ b/sound/usb/usb_audio_qmi_svc.c @@ -1542,6 +1542,65 @@ static int enable_audio_stream(struct snd_usb_substream *subs, return ret; } +static int __handle_uaudio_stream_req(struct qmi_uaudio_stream_req_msg_v01 *req_msg, + int *info_idx) +{ + struct snd_usb_substream *subs; + struct snd_usb_audio *chip; + int ifnum; + u8 pcm_card_num, pcm_dev_num, direction; + + direction = req_msg->usb_token & SND_PCM_STREAM_DIRECTION; + pcm_dev_num = (req_msg->usb_token & SND_PCM_DEV_NUM_MASK) >> 8; + pcm_card_num = (req_msg->usb_token & SND_PCM_CARD_NUM_MASK) >> 16; + + uaudio_info("card#:%d dev#:%d dir:%d en:%d fmt:%d rate:%d #ch:%d\n", + pcm_card_num, pcm_dev_num, direction, req_msg->enable, + req_msg->audio_format, req_msg->bit_rate, + req_msg->number_of_ch); + + if (pcm_card_num >= SNDRV_CARDS) { + uaudio_err("invalid card # %u", pcm_card_num); + return -EINVAL; + } + + if (req_msg->audio_format > USB_QMI_PCM_FORMAT_U32_BE) { + uaudio_err("unsupported pcm format received %d\n", + req_msg->audio_format); + return -EINVAL; + } + + subs = find_substream(pcm_card_num, pcm_dev_num, direction); + chip = uadev[pcm_card_num].chip; + if (!subs || !chip || atomic_read(&chip->shutdown)) { + uaudio_err("can't find substream for card# %u, dev# %u dir%u\n", + pcm_card_num, pcm_dev_num, direction); + return -ENODEV; + } + + ifnum = subs->cur_audiofmt ? subs->cur_audiofmt->iface : -1; + *info_idx = info_idx_from_ifnum(pcm_card_num, ifnum, req_msg->enable); + + if (atomic_read(&chip->shutdown) || !subs->stream || !subs->stream->pcm + || !subs->stream->chip) { + uaudio_err("chip or sub not available: shutdown:%d stream:%p\n", + atomic_read(&chip->shutdown), subs->stream); + + if (subs->stream) + uaudio_err("pcm:%p chip:%p\n", subs->stream->pcm, subs->stream->chip); + + return -ENODEV; + } + + if (req_msg->enable && (*info_idx < 0)) { + uaudio_err("interface# %d already in use card# %d\n", + ifnum, pcm_card_num); + return -EBUSY; + } + + return 0; +} + static void handle_uaudio_stream_req(struct qmi_handle *handle, struct sockaddr_qrtr *sq, struct qmi_txn *txn, @@ -1549,12 +1608,12 @@ static void handle_uaudio_stream_req(struct qmi_handle *handle, { struct qmi_uaudio_stream_req_msg_v01 *req_msg; struct qmi_uaudio_stream_resp_msg_v01 resp = {{0}, 0}; - struct snd_usb_substream *subs; + struct snd_usb_substream *subs = NULL; struct uaudio_qmi_svc *svc = uaudio_svc; struct intf_info *info; struct usb_host_endpoint *ep; ktime_t t_request_recvd = ktime_get(); - struct snd_usb_audio *chip; + struct snd_usb_audio *chip = NULL; u8 pcm_card_num, pcm_dev_num, direction; int info_idx = -EINVAL, datainterval = -EINVAL, ret = 0; @@ -1578,54 +1637,12 @@ static void handle_uaudio_stream_req(struct qmi_handle *handle, pcm_dev_num = (req_msg->usb_token & SND_PCM_DEV_NUM_MASK) >> 8; pcm_card_num = (req_msg->usb_token & SND_PCM_CARD_NUM_MASK) >> 16; - uaudio_info("card#:%d dev#:%d dir:%d en:%d fmt:%d rate:%d #ch:%d\n", - pcm_card_num, pcm_dev_num, direction, req_msg->enable, - req_msg->audio_format, req_msg->bit_rate, - req_msg->number_of_ch); - - if (pcm_card_num >= SNDRV_CARDS) { - uaudio_err("invalid card # %u", pcm_card_num); - ret = -EINVAL; - goto response; - } - - if (req_msg->audio_format > USB_QMI_PCM_FORMAT_U32_BE) { - uaudio_err("unsupported pcm format received %d\n", - req_msg->audio_format); - ret = -EINVAL; - goto response; - } - subs = find_substream(pcm_card_num, pcm_dev_num, direction); chip = uadev[pcm_card_num].chip; - if (!subs || !chip || atomic_read(&chip->shutdown)) { - uaudio_err("can't find substream for card# %u, dev# %u dir%u\n", - pcm_card_num, pcm_dev_num, direction); - ret = -ENODEV; + + ret = __handle_uaudio_stream_req(req_msg, &info_idx); + if (ret) goto response; - } - - info_idx = info_idx_from_ifnum(pcm_card_num, subs->cur_audiofmt ? - subs->cur_audiofmt->iface : -1, req_msg->enable); - if (atomic_read(&chip->shutdown) || !subs->stream || !subs->stream->pcm - || !subs->stream->chip) { - uaudio_err("chip or sub not available: shutdown:%d stream:%p\n", - atomic_read(&chip->shutdown), subs->stream); - - if (subs->stream) - uaudio_err("pcm:%p chip:%p\n", subs->stream->pcm, subs->stream->chip); - - ret = -ENODEV; - goto response; - } - - if ((req_msg->enable) && (info_idx < 0)) { - uaudio_err("interface# %d already in use card# %d\n", - subs->cur_audiofmt ? subs->cur_audiofmt->iface : -1, - pcm_card_num); - ret = -EBUSY; - goto response; - } if (req_msg->service_interval_valid) { ret = get_data_interval_from_si(subs, @@ -1677,7 +1694,8 @@ static void handle_uaudio_stream_req(struct qmi_handle *handle, disable_audio_stream(subs); } - atomic_dec(&chip->usage_count); + if (atomic_dec_and_test(&chip->usage_count) && atomic_read(&chip->shutdown)) + wake_up(&chip->shutdown_wait); response: if (!req_msg->enable && ret != -EINVAL && ret != -ENODEV) { diff --git a/tools/bpf/bpftool/feature.c b/tools/bpf/bpftool/feature.c index 7f36385aa9e2..0c9544c6d302 100644 --- a/tools/bpf/bpftool/feature.c +++ b/tools/bpf/bpftool/feature.c @@ -135,12 +135,12 @@ static void print_end_section(void) /* Probing functions */ -static int read_procfs(const char *path) +static long read_procfs(const char *path) { char *endptr, *line = NULL; size_t len = 0; FILE *fd; - int res; + long res; fd = fopen(path, "r"); if (!fd) @@ -162,7 +162,7 @@ static int read_procfs(const char *path) static void probe_unprivileged_disabled(void) { - int res; + long res; /* No support for C-style ouptut */ @@ -181,14 +181,14 @@ static void probe_unprivileged_disabled(void) printf("Unable to retrieve required privileges for bpf() syscall\n"); break; default: - printf("bpf() syscall restriction has unknown value %d\n", res); + printf("bpf() syscall restriction has unknown value %ld\n", res); } } } static void probe_jit_enable(void) { - int res; + long res; /* No support for C-style ouptut */ @@ -210,7 +210,7 @@ static void probe_jit_enable(void) printf("Unable to retrieve JIT-compiler status\n"); break; default: - printf("JIT-compiler status has unknown value %d\n", + printf("JIT-compiler status has unknown value %ld\n", res); } } @@ -218,7 +218,7 @@ static void probe_jit_enable(void) static void probe_jit_harden(void) { - int res; + long res; /* No support for C-style ouptut */ @@ -240,7 +240,7 @@ static void probe_jit_harden(void) printf("Unable to retrieve JIT hardening status\n"); break; default: - printf("JIT hardening status has unknown value %d\n", + printf("JIT hardening status has unknown value %ld\n", res); } } @@ -248,7 +248,7 @@ static void probe_jit_harden(void) static void probe_jit_kallsyms(void) { - int res; + long res; /* No support for C-style ouptut */ @@ -267,14 +267,14 @@ static void probe_jit_kallsyms(void) printf("Unable to retrieve JIT kallsyms export status\n"); break; default: - printf("JIT kallsyms exports status has unknown value %d\n", res); + printf("JIT kallsyms exports status has unknown value %ld\n", res); } } } static void probe_jit_limit(void) { - int res; + long res; /* No support for C-style ouptut */ @@ -287,7 +287,7 @@ static void probe_jit_limit(void) printf("Unable to retrieve global memory limit for JIT compiler for unprivileged users\n"); break; default: - printf("Global memory limit for JIT compiler for unprivileged users is %d bytes\n", res); + printf("Global memory limit for JIT compiler for unprivileged users is %ld bytes\n", res); } } } diff --git a/tools/bpf/resolve_btfids/Makefile b/tools/bpf/resolve_btfids/Makefile index 35f092065c4f..21a17ad1e10d 100644 --- a/tools/bpf/resolve_btfids/Makefile +++ b/tools/bpf/resolve_btfids/Makefile @@ -44,7 +44,7 @@ $(OUTPUT) $(OUTPUT)/libbpf $(OUTPUT)/libsubcmd: $(Q)mkdir -p $(@) $(SUBCMDOBJ): fixdep FORCE | $(OUTPUT)/libsubcmd - $(Q)$(MAKE) -C $(SUBCMD_SRC) OUTPUT=$(abspath $(dir $@))/ $(abspath $@) + $(Q)$(MAKE) -C $(SUBCMD_SRC) EXTRA_CFLAGS="$(CFLAGS)" OUTPUT=$(abspath $(dir $@))/ $(abspath $@) $(BPFOBJ): $(wildcard $(LIBBPF_SRC)/*.[ch] $(LIBBPF_SRC)/Makefile) | $(OUTPUT)/libbpf $(Q)$(MAKE) $(submake_extras) -C $(LIBBPF_SRC) OUTPUT=$(abspath $(dir $@))/ \ diff --git a/tools/lib/bpf/bpf_helpers.h b/tools/lib/bpf/bpf_helpers.h index b9987c3efa3c..956b57d02eb9 100644 --- a/tools/lib/bpf/bpf_helpers.h +++ b/tools/lib/bpf/bpf_helpers.h @@ -72,16 +72,21 @@ /* * Helper macros to manipulate data structures */ -#ifndef offsetof -#define offsetof(TYPE, MEMBER) ((unsigned long)&((TYPE *)0)->MEMBER) -#endif -#ifndef container_of + +/* offsetof() definition that uses __builtin_offset() might not preserve field + * offset CO-RE relocation properly, so force-redefine offsetof() using + * old-school approach which works with CO-RE correctly + */ +#undef offsetof +#define offsetof(type, member) ((unsigned long)&((type *)0)->member) + +/* redefined container_of() to ensure we use the above offsetof() macro */ +#undef container_of #define container_of(ptr, type, member) \ ({ \ void *__mptr = (void *)(ptr); \ ((type *)(__mptr - offsetof(type, member))); \ }) -#endif /* * Helper macro to throw a compilation error if __bpf_unreachable() gets diff --git a/tools/lib/bpf/btf_dump.c b/tools/lib/bpf/btf_dump.c index 98cb3831aa18..b91dd7cd4ffb 100644 --- a/tools/lib/bpf/btf_dump.c +++ b/tools/lib/bpf/btf_dump.c @@ -2126,9 +2126,25 @@ static int btf_dump_type_data_check_overflow(struct btf_dump *d, const struct btf_type *t, __u32 id, const void *data, - __u8 bits_offset) + __u8 bits_offset, + __u8 bit_sz) { - __s64 size = btf__resolve_size(d->btf, id); + __s64 size; + + if (bit_sz) { + /* bits_offset is at most 7. bit_sz is at most 128. */ + __u8 nr_bytes = (bits_offset + bit_sz + 7) / 8; + + /* When bit_sz is non zero, it is called from + * btf_dump_struct_data() where it only cares about + * negative error value. + * Return nr_bytes in success case to make it + * consistent as the regular integer case below. + */ + return data + nr_bytes > d->typed_dump->data_end ? -E2BIG : nr_bytes; + } + + size = btf__resolve_size(d->btf, id); if (size < 0 || size >= INT_MAX) { pr_warn("unexpected size [%zu] for id [%u]\n", @@ -2281,7 +2297,7 @@ static int btf_dump_dump_type_data(struct btf_dump *d, { int size, err = 0; - size = btf_dump_type_data_check_overflow(d, t, id, data, bits_offset); + size = btf_dump_type_data_check_overflow(d, t, id, data, bits_offset, bit_sz); if (size < 0) return size; err = btf_dump_type_data_check_zero(d, t, id, data, bits_offset, bit_sz); diff --git a/tools/lib/subcmd/parse-options.c b/tools/lib/subcmd/parse-options.c index 39ebf6192016..5c96dfdeb840 100644 --- a/tools/lib/subcmd/parse-options.c +++ b/tools/lib/subcmd/parse-options.c @@ -637,10 +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]) { char *buf = NULL; + 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]); @@ -666,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/perf/Makefile.config b/tools/perf/Makefile.config index 2c30a2b577d3..973c0d5ed8d8 100644 --- a/tools/perf/Makefile.config +++ b/tools/perf/Makefile.config @@ -143,9 +143,9 @@ FEATURE_CHECK_LDFLAGS-libcrypto = -lcrypto ifdef CSINCLUDES LIBOPENCSD_CFLAGS := -I$(CSINCLUDES) endif -OPENCSDLIBS := -lopencsd_c_api +OPENCSDLIBS := -lopencsd_c_api -lopencsd ifeq ($(findstring -static,${LDFLAGS}),-static) - OPENCSDLIBS += -lopencsd -lstdc++ + OPENCSDLIBS += -lstdc++ endif ifdef CSLIBS LIBOPENCSD_LDFLAGS := -L$(CSLIBS) diff --git a/tools/perf/builtin-bench.c b/tools/perf/builtin-bench.c index d0895162c2ba..ac72bcccc353 100644 --- a/tools/perf/builtin-bench.c +++ b/tools/perf/builtin-bench.c @@ -21,6 +21,7 @@ #include "builtin.h" #include "bench/bench.h" +#include #include #include #include @@ -226,7 +227,6 @@ static void run_collection(struct collection *coll) if (!bench->fn) break; printf("# Running %s/%s benchmark...\n", coll->name, bench->name); - fflush(stdout); argv[1] = bench->name; run_bench(coll->name, bench->name, bench->fn, 1, argv); @@ -247,6 +247,10 @@ int cmd_bench(int argc, const char **argv) struct collection *coll; int ret = 0; + /* Unbuffered output */ + setvbuf(stdout, NULL, _IONBF, 0); + setlocale(LC_ALL, ""); + if (argc < 2) { /* No collection specified. */ print_usage(); @@ -300,7 +304,6 @@ int cmd_bench(int argc, const char **argv) if (bench_format == BENCH_FORMAT_DEFAULT) printf("# Running '%s/%s' benchmark:\n", coll->name, bench->name); - fflush(stdout); ret = run_bench(coll->name, bench->name, bench->fn, argc-1, argv+1); goto end; } diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c index c6c40191933d..34e809c934d7 100644 --- a/tools/perf/builtin-script.c +++ b/tools/perf/builtin-script.c @@ -2260,6 +2260,9 @@ out_put: return ret; } +// Used when scr->per_event_dump is not set +static struct evsel_script es_stdout; + static int process_attr(struct perf_tool *tool, union perf_event *event, struct evlist **pevlist) { @@ -2268,7 +2271,6 @@ static int process_attr(struct perf_tool *tool, union perf_event *event, struct evsel *evsel, *pos; u64 sample_type; int err; - static struct evsel_script *es; err = perf_event__process_attr(tool, event, pevlist); if (err) @@ -2278,14 +2280,13 @@ static int process_attr(struct perf_tool *tool, union perf_event *event, evsel = evlist__last(*pevlist); if (!evsel->priv) { - if (scr->per_event_dump) { + if (scr->per_event_dump) { evsel->priv = evsel_script__new(evsel, scr->session->data); - } else { - es = zalloc(sizeof(*es)); - if (!es) + if (!evsel->priv) return -ENOMEM; - es->fp = stdout; - evsel->priv = es; + } else { // Replicate what is done in perf_script__setup_per_event_dump() + es_stdout.fp = stdout; + evsel->priv = &es_stdout; } } @@ -2591,7 +2592,6 @@ out_err_fclose: static int perf_script__setup_per_event_dump(struct perf_script *script) { struct evsel *evsel; - static struct evsel_script es_stdout; if (script->per_event_dump) return perf_script__fopen_per_event_dump(script); diff --git a/tools/perf/tests/builtin-test.c b/tools/perf/tests/builtin-test.c index da7dc5e45d0c..4d6d3e314200 100644 --- a/tools/perf/tests/builtin-test.c +++ b/tools/perf/tests/builtin-test.c @@ -828,6 +828,9 @@ int cmd_test(int argc, const char **argv) if (ret < 0) return ret; + /* Unbuffered output */ + setvbuf(stdout, NULL, _IONBF, 0); + argc = parse_options_subcommand(argc, argv, test_options, test_subcommands, test_usage, 0); if (argc >= 1 && !strcmp(argv[0], "list")) return perf_test__list(argc - 1, argv + 1); diff --git a/tools/perf/tests/shell/test_uprobe_from_different_cu.sh b/tools/perf/tests/shell/test_uprobe_from_different_cu.sh new file mode 100644 index 000000000000..00d2e0e2e0c2 --- /dev/null +++ b/tools/perf/tests/shell/test_uprobe_from_different_cu.sh @@ -0,0 +1,77 @@ +#!/bin/bash +# test perf probe of function from different CU +# SPDX-License-Identifier: GPL-2.0 + +set -e + +temp_dir=$(mktemp -d /tmp/perf-uprobe-different-cu-sh.XXXXXXXXXX) + +cleanup() +{ + trap - EXIT TERM INT + if [[ "${temp_dir}" =~ ^/tmp/perf-uprobe-different-cu-sh.*$ ]]; then + echo "--- Cleaning up ---" + perf probe -x ${temp_dir}/testfile -d foo + rm -f "${temp_dir}/"* + rmdir "${temp_dir}" + fi +} + +trap_cleanup() +{ + cleanup + exit 1 +} + +trap trap_cleanup EXIT TERM INT + +cat > ${temp_dir}/testfile-foo.h << EOF +struct t +{ + int *p; + int c; +}; + +extern int foo (int i, struct t *t); +EOF + +cat > ${temp_dir}/testfile-foo.c << EOF +#include "testfile-foo.h" + +int +foo (int i, struct t *t) +{ + int j, res = 0; + for (j = 0; j < i && j < t->c; j++) + res += t->p[j]; + + return res; +} +EOF + +cat > ${temp_dir}/testfile-main.c << EOF +#include "testfile-foo.h" + +static struct t g; + +int +main (int argc, char **argv) +{ + int i; + int j[argc]; + g.c = argc; + g.p = j; + for (i = 0; i < argc; i++) + j[i] = (int) argv[i][0]; + return foo (3, &g); +} +EOF + +gcc -g -Og -flto -c ${temp_dir}/testfile-foo.c -o ${temp_dir}/testfile-foo.o +gcc -g -Og -c ${temp_dir}/testfile-main.c -o ${temp_dir}/testfile-main.o +gcc -g -Og -o ${temp_dir}/testfile ${temp_dir}/testfile-foo.o ${temp_dir}/testfile-main.o + +perf probe -x ${temp_dir}/testfile --funcs foo +perf probe -x ${temp_dir}/testfile foo + +cleanup diff --git a/tools/perf/util/dwarf-aux.c b/tools/perf/util/dwarf-aux.c index 623527edeac1..b125eaadcec4 100644 --- a/tools/perf/util/dwarf-aux.c +++ b/tools/perf/util/dwarf-aux.c @@ -1081,7 +1081,7 @@ int die_get_varname(Dwarf_Die *vr_die, struct strbuf *buf) ret = die_get_typename(vr_die, buf); if (ret < 0) { pr_debug("Failed to get type, make it unknown.\n"); - ret = strbuf_add(buf, " (unknown_type)", 14); + ret = strbuf_add(buf, "(unknown_type)", 14); } return ret < 0 ? ret : strbuf_addf(buf, "\t%s", dwarf_diename(vr_die)); diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c index b1e5fd99e38a..80c54196e0e4 100644 --- a/tools/perf/util/symbol.c +++ b/tools/perf/util/symbol.c @@ -1357,10 +1357,23 @@ static int dso__load_kcore(struct dso *dso, struct map *map, /* Find the kernel map using the '_stext' symbol */ if (!kallsyms__get_function_start(kallsyms_filename, "_stext", &stext)) { + u64 replacement_size = 0; + list_for_each_entry(new_map, &md.maps, node) { - if (stext >= new_map->start && stext < new_map->end) { + u64 new_size = new_map->end - new_map->start; + + if (!(stext >= new_map->start && stext < new_map->end)) + continue; + + /* + * On some architectures, ARM64 for example, the kernel + * text can get allocated inside of the vmalloc segment. + * Select the smallest matching segment, in case stext + * falls within more than one in the list. + */ + if (!replacement_map || new_size < replacement_size) { replacement_map = new_map; - break; + replacement_size = new_size; } } } diff --git a/tools/testing/selftests/bpf/prog_tests/check_mtu.c b/tools/testing/selftests/bpf/prog_tests/check_mtu.c index 012068f33a0a..871971cdd7b7 100644 --- a/tools/testing/selftests/bpf/prog_tests/check_mtu.c +++ b/tools/testing/selftests/bpf/prog_tests/check_mtu.c @@ -197,7 +197,7 @@ cleanup: void test_check_mtu(void) { - __u32 mtu_lo; + int mtu_lo; if (test__start_subtest("bpf_check_mtu XDP-attach")) test_check_mtu_xdp_attach(); diff --git a/tools/testing/selftests/filesystems/fuse/fuse_test.c b/tools/testing/selftests/filesystems/fuse/fuse_test.c index 79158d1f186f..01730e57dc51 100644 --- a/tools/testing/selftests/filesystems/fuse/fuse_test.c +++ b/tools/testing/selftests/filesystems/fuse/fuse_test.c @@ -2047,6 +2047,38 @@ out: return result; } +static int bpf_test_mkdir_and_remove_bpf(const char *mount_dir) +{ + const char *dir = "dir"; + + int result = TEST_FAILURE; + int src_fd = -1; + int bpf_fd = -1; + int fuse_dev = -1; + int fd = -1; + int fd2 = -1; + + TEST(src_fd = open(ft_src, O_DIRECTORY | O_RDONLY | O_CLOEXEC), + src_fd != -1); + TESTEQUAL(install_elf_bpf("test_bpf.bpf", "test_mkdir_remove", &bpf_fd, + NULL, NULL), 0); + TESTEQUAL(mount_fuse_no_init(mount_dir, bpf_fd, src_fd, &fuse_dev), 0); + TEST(fd = s_mkdir(s_path(s(mount_dir), s(dir)), 0777), + fd != -1); + TEST(fd2 = s_open(s_path(s(mount_dir), s(dir)), O_RDONLY), + fd2 != -1); + + result = TEST_SUCCESS; +out: + close(fd2); + close(fd); + close(fuse_dev); + close(bpf_fd); + close(src_fd); + umount(mount_dir); + return result; +} + static void parse_range(const char *ranges, bool *run_test, size_t tests) { size_t i; @@ -2175,7 +2207,7 @@ int main(int argc, char *argv[]) MAKE_TEST(bpf_test_lookup_postfilter), MAKE_TEST(flock_test), MAKE_TEST(bpf_test_create_and_remove_bpf), - + MAKE_TEST(bpf_test_mkdir_and_remove_bpf), }; #undef MAKE_TEST diff --git a/tools/testing/selftests/filesystems/fuse/test_bpf.c b/tools/testing/selftests/filesystems/fuse/test_bpf.c index e02bdb4a9380..a014b915c059 100644 --- a/tools/testing/selftests/filesystems/fuse/test_bpf.c +++ b/tools/testing/selftests/filesystems/fuse/test_bpf.c @@ -530,4 +530,26 @@ int createremovebpf_test(struct fuse_bpf_args *fa) } } +SEC("test_mkdir_remove") +int mkdirremovebpf_test(struct fuse_bpf_args *fa) +{ + switch (fa->opcode) { + case FUSE_LOOKUP | FUSE_PREFILTER: { + return FUSE_BPF_BACKING | FUSE_BPF_POST_FILTER; + } + case FUSE_LOOKUP | FUSE_POSTFILTER: { + struct fuse_entry_bpf_out *febo = fa->out_args[1].value; + + febo->bpf_action = FUSE_ACTION_REMOVE; + return 0; + } + + case FUSE_OPENDIR | FUSE_PREFILTER: { + return -EIO; + } + + default: + return FUSE_BPF_BACKING; + } +} diff --git a/tools/testing/selftests/net/mptcp/config b/tools/testing/selftests/net/mptcp/config index f7d33a16051c..3f9e540fee57 100644 --- a/tools/testing/selftests/net/mptcp/config +++ b/tools/testing/selftests/net/mptcp/config @@ -6,6 +6,7 @@ CONFIG_INET_DIAG=m CONFIG_INET_MPTCP_DIAG=m CONFIG_VETH=y CONFIG_NET_SCH_NETEM=m +CONFIG_SYN_COOKIES=y CONFIG_NETFILTER=y CONFIG_NETFILTER_ADVANCED=y CONFIG_NETFILTER_NETLINK=m diff --git a/tools/testing/selftests/net/mptcp/mptcp_sockopt.sh b/tools/testing/selftests/net/mptcp/mptcp_sockopt.sh index 89a53aa0ab9d..d5c79e4a8f1e 100755 --- a/tools/testing/selftests/net/mptcp/mptcp_sockopt.sh +++ b/tools/testing/selftests/net/mptcp/mptcp_sockopt.sh @@ -119,6 +119,7 @@ check_mark() for v in $values; do if [ $v -ne 0 ]; then echo "FAIL: got $tables $values in ns $ns , not 0 - not all expected packets marked" 1>&2 + ret=1 return 1 fi done @@ -213,11 +214,11 @@ do_transfer() fi if [ $local_addr = "::" ];then - check_mark $listener_ns 6 - check_mark $connector_ns 6 + check_mark $listener_ns 6 || retc=1 + check_mark $connector_ns 6 || retc=1 else - check_mark $listener_ns 4 - check_mark $connector_ns 4 + check_mark $listener_ns 4 || retc=1 + check_mark $connector_ns 4 || retc=1 fi check_transfer $cin $sout "file received by server" diff --git a/tools/testing/selftests/net/rtnetlink.sh b/tools/testing/selftests/net/rtnetlink.sh index c3a905923ef2..cbf166df57da 100755 --- a/tools/testing/selftests/net/rtnetlink.sh +++ b/tools/testing/selftests/net/rtnetlink.sh @@ -835,6 +835,7 @@ EOF fi # clean up any leftovers + echo 0 > /sys/bus/netdevsim/del_device $probed && rmmod netdevsim if [ $ret -ne 0 ]; then diff --git a/tools/testing/selftests/rcutorture/configs/rcu/BUSTED-BOOST.boot b/tools/testing/selftests/rcutorture/configs/rcu/BUSTED-BOOST.boot index f57720c52c0f..84f6bb98ce99 100644 --- a/tools/testing/selftests/rcutorture/configs/rcu/BUSTED-BOOST.boot +++ b/tools/testing/selftests/rcutorture/configs/rcu/BUSTED-BOOST.boot @@ -5,4 +5,4 @@ rcutree.gp_init_delay=3 rcutree.gp_cleanup_delay=3 rcutree.kthread_prio=2 threadirqs -tree.use_softirq=0 +rcutree.use_softirq=0 diff --git a/tools/testing/selftests/rcutorture/configs/rcu/TREE03.boot b/tools/testing/selftests/rcutorture/configs/rcu/TREE03.boot index 64f864f1f361..8e50bfd4b710 100644 --- a/tools/testing/selftests/rcutorture/configs/rcu/TREE03.boot +++ b/tools/testing/selftests/rcutorture/configs/rcu/TREE03.boot @@ -4,4 +4,4 @@ rcutree.gp_init_delay=3 rcutree.gp_cleanup_delay=3 rcutree.kthread_prio=2 threadirqs -tree.use_softirq=0 +rcutree.use_softirq=0 diff --git a/tools/testing/selftests/tc-testing/config b/tools/testing/selftests/tc-testing/config index b71828df5a6d..db1dcc139d34 100644 --- a/tools/testing/selftests/tc-testing/config +++ b/tools/testing/selftests/tc-testing/config @@ -5,6 +5,8 @@ CONFIG_NF_CONNTRACK=m CONFIG_NF_CONNTRACK_MARK=y CONFIG_NF_CONNTRACK_ZONES=y CONFIG_NF_CONNTRACK_LABELS=y +CONFIG_NF_CONNTRACK_PROCFS=y +CONFIG_NF_FLOW_TABLE=m CONFIG_NF_NAT=m CONFIG_NET_SCHED=y diff --git a/tools/testing/selftests/tc-testing/settings b/tools/testing/selftests/tc-testing/settings new file mode 100644 index 000000000000..e2206265f67c --- /dev/null +++ b/tools/testing/selftests/tc-testing/settings @@ -0,0 +1 @@ +timeout=900 diff --git a/tools/testing/selftests/vDSO/vdso_test_clock_getres.c b/tools/testing/selftests/vDSO/vdso_test_clock_getres.c index 15dcee16ff72..38d46a8bf7cb 100644 --- a/tools/testing/selftests/vDSO/vdso_test_clock_getres.c +++ b/tools/testing/selftests/vDSO/vdso_test_clock_getres.c @@ -84,12 +84,12 @@ static inline int vdso_test_clock(unsigned int clock_id) int main(int argc, char **argv) { - int ret; + int ret = 0; #if _POSIX_TIMERS > 0 #ifdef CLOCK_REALTIME - ret = vdso_test_clock(CLOCK_REALTIME); + ret += vdso_test_clock(CLOCK_REALTIME); #endif #ifdef CLOCK_BOOTTIME diff --git a/tools/testing/selftests/wireguard/netns.sh b/tools/testing/selftests/wireguard/netns.sh index 8a9461aa0878..93e44410f170 100755 --- a/tools/testing/selftests/wireguard/netns.sh +++ b/tools/testing/selftests/wireguard/netns.sh @@ -502,10 +502,32 @@ n2 bash -c 'printf 0 > /proc/sys/net/ipv4/conf/all/rp_filter' n1 ping -W 1 -c 1 192.168.241.2 [[ $(n2 wg show wg0 endpoints) == "$pub1 10.0.0.3:1" ]] -ip1 link del veth1 -ip1 link del veth3 -ip1 link del wg0 -ip2 link del wg0 +ip1 link del dev veth3 +ip1 link del dev wg0 +ip2 link del dev wg0 + +# Make sure persistent keep alives are sent when an adapter comes up +ip1 link add dev wg0 type wireguard +n1 wg set wg0 private-key <(echo "$key1") peer "$pub2" endpoint 10.0.0.1:1 persistent-keepalive 1 +read _ _ tx_bytes < <(n1 wg show wg0 transfer) +[[ $tx_bytes -eq 0 ]] +ip1 link set dev wg0 up +read _ _ tx_bytes < <(n1 wg show wg0 transfer) +[[ $tx_bytes -gt 0 ]] +ip1 link del dev wg0 +# This should also happen even if the private key is set later +ip1 link add dev wg0 type wireguard +n1 wg set wg0 peer "$pub2" endpoint 10.0.0.1:1 persistent-keepalive 1 +read _ _ tx_bytes < <(n1 wg show wg0 transfer) +[[ $tx_bytes -eq 0 ]] +ip1 link set dev wg0 up +read _ _ tx_bytes < <(n1 wg show wg0 transfer) +[[ $tx_bytes -eq 0 ]] +n1 wg set wg0 private-key <(echo "$key1") +read _ _ tx_bytes < <(n1 wg show wg0 transfer) +[[ $tx_bytes -gt 0 ]] +ip1 link del dev veth1 +ip1 link del dev wg0 # We test that Netlink/IPC is working properly by doing things that usually cause split responses ip0 link add dev wg0 type wireguard